feat: 重构聊天时间线与附件上传交互

- 管理端和用户中心统一切换到 chatTime 时间线模型,按真实 assistant/tool 时序渲染

- 收紧工具气泡与 JSON 展示样式,保留同气泡内的工具状态更新

- 回形针直接触发文件选择,附件列表上移到输入框上方并补充共享 helper 测试
This commit is contained in:
2026-05-11 21:25:21 +08:00
parent e27834ee0c
commit 4a15124183
27 changed files with 2527 additions and 751 deletions

View File

@@ -1,7 +1,10 @@
<script setup lang="ts">
import type { ChatTimeTimelineItem } from '@easyflow/types';
import { computed, onMounted, ref } from 'vue';
import { useEasyFlowDrawer } from '@easyflow/common-ui';
import { ChatTimeHistoryMapper } from '@easyflow/utils';
import { Search } from '@element-plus/icons-vue';
import {
@@ -43,7 +46,8 @@ const quickRangeOptions = [
const drawerLoading = ref(false);
const currentSession = ref<any>();
const messageList = ref<any[]>([]);
const messageList = ref<ChatTimeTimelineItem[]>([]);
const loadedMessageRecordCount = ref(0);
const messagePage = ref({
total: 0,
pageNumber: 1,
@@ -63,7 +67,7 @@ const [Drawer, drawerApi] = useEasyFlowDrawer({
});
const hasMoreMessages = computed(
() => messageList.value.length < messagePage.value.total,
() => loadedMessageRecordCount.value < messagePage.value.total,
);
const selectedSessionId = computed(() =>
@@ -111,6 +115,7 @@ async function openSession(sessionId: number | string) {
sessions.value.find((item: any) => String(item.id) === String(sessionId)) ||
undefined;
messageList.value = [];
loadedMessageRecordCount.value = 0;
messagePage.value = {
total: 0,
pageNumber: 1,
@@ -154,31 +159,15 @@ async function loadMessages(reset = false) {
messageList.value = reset
? normalized
: [...normalized, ...messageList.value];
loadedMessageRecordCount.value = reset
? (res.data?.records || []).length
: loadedMessageRecordCount.value + (res.data?.records || []).length;
messagePage.value.total = res.data?.total || 0;
messagePage.value.pageNumber = nextPageNumber;
}
function normalizeMessages(records: any[]) {
return [...records].reverse().map((item: any) => ({
key: String(item.id),
role: item.senderRole === 'assistant' ? 'assistant' : 'user',
content:
item.senderRole === 'assistant'
? String(item.contentText || '').replace(/^Final Answer:\s*/i, '')
: item.contentText,
created: item.created,
senderName: item.senderName,
chains: Array.isArray(item.contentPayload?.chains)
? item.contentPayload.chains.map((chain: any) =>
chain?.id
? chain
: {
...chain,
thinkingExpanded: false,
},
)
: [],
}));
return ChatTimeHistoryMapper.fromHistoryRecords([...records].reverse());
}
function changePage(pageNumber: number) {