From e00442647be30788518afc9a3017bb29b09d3965 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Wed, 16 Sep 2026 15:40:49 +0800 Subject: [PATCH] feat: improve conversation data previews (#10108) --- .../ConversationHistoryPreview.vue | 588 ++++++++++++++++++ .../locales/en-US/features/conversation.json | 19 +- .../locales/ja-JP/features/conversation.json | 19 +- .../locales/ru-RU/features/conversation.json | 19 +- .../locales/zh-CN/features/conversation.json | 19 +- .../ConversationWorkspacePage.vue | 110 +--- 6 files changed, 678 insertions(+), 96 deletions(-) create mode 100644 dashboard/src/components/conversation/ConversationHistoryPreview.vue diff --git a/dashboard/src/components/conversation/ConversationHistoryPreview.vue b/dashboard/src/components/conversation/ConversationHistoryPreview.vue new file mode 100644 index 000000000..11f660291 --- /dev/null +++ b/dashboard/src/components/conversation/ConversationHistoryPreview.vue @@ -0,0 +1,588 @@ + + + + + diff --git a/dashboard/src/i18n/locales/en-US/features/conversation.json b/dashboard/src/i18n/locales/en-US/features/conversation.json index ac6179bd0..49ec8547d 100644 --- a/dashboard/src/i18n/locales/en-US/features/conversation.json +++ b/dashboard/src/i18n/locales/en-US/features/conversation.json @@ -147,7 +147,24 @@ "empty": "This conversation has no messages", "copyUmo": "Copy UMO", "rawData": "Raw data", - "copyRawData": "Copy raw data" + "copyRawData": "Copy raw data", + "messageCount": "{count} messages", + "markdown": "Render Markdown", + "fontSize": "Text size", + "smallerText": "Decrease text size", + "largerText": "Increase text size", + "structuredData": "Structured content", + "toolCall": "Tool call", + "reasoning": "Reasoning", + "image": "Message image", + "roles": { + "user": "User", + "assistant": "Assistant", + "system": "System", + "developer": "Developer", + "tool": "Tool result", + "function": "Function result" + } }, "actions": { "editTitle": "Edit title", diff --git a/dashboard/src/i18n/locales/ja-JP/features/conversation.json b/dashboard/src/i18n/locales/ja-JP/features/conversation.json index b696e143f..9d4c88301 100644 --- a/dashboard/src/i18n/locales/ja-JP/features/conversation.json +++ b/dashboard/src/i18n/locales/ja-JP/features/conversation.json @@ -147,7 +147,24 @@ "empty": "この会話にはまだメッセージがありません", "copyUmo": "UMO をコピー", "rawData": "生データ", - "copyRawData": "生データをコピー" + "copyRawData": "生データをコピー", + "messageCount": "{count} 件のメッセージ", + "markdown": "Markdown を表示", + "fontSize": "文字サイズ", + "smallerText": "文字を小さくする", + "largerText": "文字を大きくする", + "structuredData": "構造化コンテンツ", + "toolCall": "ツール呼び出し", + "reasoning": "思考過程", + "image": "メッセージ画像", + "roles": { + "user": "ユーザー", + "assistant": "アシスタント", + "system": "システム", + "developer": "開発者", + "tool": "ツール結果", + "function": "関数結果" + } }, "actions": { "editTitle": "タイトルを編集", diff --git a/dashboard/src/i18n/locales/ru-RU/features/conversation.json b/dashboard/src/i18n/locales/ru-RU/features/conversation.json index 8afda742b..fcb47ae8f 100644 --- a/dashboard/src/i18n/locales/ru-RU/features/conversation.json +++ b/dashboard/src/i18n/locales/ru-RU/features/conversation.json @@ -147,7 +147,24 @@ "empty": "В этом диалоге нет сообщений", "copyUmo": "Копировать UMO", "rawData": "Исходные данные", - "copyRawData": "Копировать исходные данные" + "copyRawData": "Копировать исходные данные", + "messageCount": "Сообщений: {count}", + "markdown": "Отображать Markdown", + "fontSize": "Размер текста", + "smallerText": "Уменьшить текст", + "largerText": "Увеличить текст", + "structuredData": "Структурированные данные", + "toolCall": "Вызов инструмента", + "reasoning": "Рассуждения", + "image": "Изображение в сообщении", + "roles": { + "user": "Пользователь", + "assistant": "Ассистент", + "system": "Система", + "developer": "Разработчик", + "tool": "Результат инструмента", + "function": "Результат функции" + } }, "actions": { "editTitle": "Изменить заголовок", diff --git a/dashboard/src/i18n/locales/zh-CN/features/conversation.json b/dashboard/src/i18n/locales/zh-CN/features/conversation.json index ef7ae0d7b..404a16050 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/conversation.json +++ b/dashboard/src/i18n/locales/zh-CN/features/conversation.json @@ -147,7 +147,24 @@ "empty": "这个对话还没有消息", "copyUmo": "复制 UMO", "rawData": "原始数据", - "copyRawData": "复制原始数据" + "copyRawData": "复制原始数据", + "messageCount": "{count} 条消息", + "markdown": "渲染 Markdown", + "fontSize": "正文字号", + "smallerText": "缩小字号", + "largerText": "放大字号", + "structuredData": "结构化内容", + "toolCall": "工具调用", + "reasoning": "思考过程", + "image": "消息图片", + "roles": { + "user": "用户", + "assistant": "助手", + "system": "系统", + "developer": "开发者", + "tool": "工具结果", + "function": "函数结果" + } }, "actions": { "editTitle": "编辑标题", diff --git a/dashboard/src/views/conversation/ConversationWorkspacePage.vue b/dashboard/src/views/conversation/ConversationWorkspacePage.vue index b8cc90d9c..130cd792b 100644 --- a/dashboard/src/views/conversation/ConversationWorkspacePage.vue +++ b/dashboard/src/views/conversation/ConversationWorkspacePage.vue @@ -27,7 +27,7 @@ import { X, } from "@lucide/vue"; import { conversationApi } from "@/api/v1"; -import MessageList from "@/components/chat/MessageList.vue"; +import ConversationHistoryPreview from "@/components/conversation/ConversationHistoryPreview.vue"; import { useI18n, useModuleI18n } from "@/i18n/composables"; import { useCustomizerStore } from "@/stores/customizer"; import { copyToClipboard } from "@/utils/clipboard"; @@ -113,11 +113,10 @@ const listRequestId = ref(0); const selectedByKey = ref>({}); const activeConversation = ref(null); -const conversationHistory = ref([]); +const conversationHistory = ref([]); const previewLoading = ref(false); const previewRequestId = ref(0); const previewPageScroll = ref(0); -const previewMessagesRef = ref(null); const rawDataDialog = ref(false); const rawHistoryText = ref(""); @@ -220,65 +219,6 @@ const messageTypes = computed(() => [ { label: tm("messageTypes.group"), value: "GroupMessage" }, ]); -const formattedMessages = computed(() => { - const toolResultsById: Record = {}; - for (const message of conversationHistory.value) { - if (message?.role === "tool" && message.tool_call_id) { - toolResultsById[message.tool_call_id] = message.content; - } - } - - return conversationHistory.value - .filter( - (message) => message?.role === "user" || message?.role === "assistant", - ) - .map((message) => { - const parts: any[] = []; - const content = message.content; - if (typeof content === "string" && content.trim()) { - parts.push({ type: "plain", text: content }); - } else if (Array.isArray(content)) { - for (const item of content) { - if (item?.type === "text" && item.text) { - parts.push({ type: "plain", text: item.text }); - } else if (item?.type === "image_url" && item.image_url?.url) { - parts.push({ type: "image", embedded_url: item.image_url.url }); - } - } - } else if (content && typeof content === "object") { - const text = Object.values(content) - .filter((value) => typeof value === "string" && value.trim()) - .join("\n"); - if (text) parts.push({ type: "plain", text }); - } - - if ( - message.role === "assistant" && - Array.isArray(message.tool_calls) && - message.tool_calls.length - ) { - parts.push({ - type: "tool_call", - tool_calls: message.tool_calls.map((toolCall: any) => ({ - id: toolCall.id, - name: toolCall.function?.name || toolCall.name, - args: toolCall.function?.arguments ?? toolCall.arguments, - result: toolResultsById[toolCall.id], - ts: 0, - finished_ts: 1, - })), - }); - } - - return { - content: { - type: message.role === "user" ? "user" : "bot", - message: parts.length ? parts : [{ type: "plain", text: "" }], - }, - }; - }); -}); - watch([keyword, umoQuery], () => { listAbortController.value?.abort(); scheduleFetch(); @@ -543,9 +483,12 @@ async function openConversation(item: Conversation) { const detail = response.data.data || {}; activeConversation.value = { ...item, ...detail }; const history = detail.history || []; - conversationHistory.value = Array.isArray(history) - ? history - : JSON.parse(history || "[]"); + const parsedHistory = + typeof history === "string" ? JSON.parse(history) : history; + if (!Array.isArray(parsedHistory)) { + throw new Error(tm("messages.historyError")); + } + conversationHistory.value = parsedHistory; } catch (error: any) { if (requestId !== previewRequestId.value) return; conversationHistory.value = []; @@ -558,11 +501,6 @@ async function openConversation(item: Conversation) { } finally { if (requestId === previewRequestId.value) { previewLoading.value = false; - await nextTick(); - if (requestId === previewRequestId.value && previewMessagesRef.value) { - previewMessagesRef.value.scrollTop = - previewMessagesRef.value.scrollHeight; - } } } } @@ -1332,19 +1270,17 @@ function changePage(nextPage: number) { -
-
+
+
{{ tm("workspace.preview.loading") }}
-
- {{ tm("workspace.preview.empty") }} -
-
+ @@ -1581,7 +1517,9 @@ function changePage(nextPage: number) { height: 28px; justify-content: center; padding: 0; - transition: background-color 0.16s ease, color 0.16s ease; + transition: + background-color 0.16s ease, + color 0.16s ease; width: 28px; } @@ -2042,18 +1980,6 @@ function changePage(nextPage: number) { padding: 2px 6px 10px; } -.preview-messages :deep(.messages-list) { - padding: 12px 8px 20px; -} - -.preview-messages :deep(.message-row) { - margin-bottom: 14px; -} - -.preview-messages :deep(.bot-avatar) { - display: none; -} - .raw-data-card { max-height: min(82dvh, 760px); }