diff --git a/dashboard/src/components/chat/Chat.vue b/dashboard/src/components/chat/Chat.vue new file mode 100644 index 000000000..651cf83ee --- /dev/null +++ b/dashboard/src/components/chat/Chat.vue @@ -0,0 +1,1347 @@ + + + + + \ No newline at end of file diff --git a/dashboard/src/components/chat/MessageList.vue b/dashboard/src/components/chat/MessageList.vue new file mode 100644 index 000000000..8d244d44f --- /dev/null +++ b/dashboard/src/components/chat/MessageList.vue @@ -0,0 +1,775 @@ + + + + + + + diff --git a/dashboard/src/components/shared/UiParentCard.vue b/dashboard/src/components/shared/UiParentCard.vue deleted file mode 100644 index 5eda86a4c..000000000 --- a/dashboard/src/components/shared/UiParentCard.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/dashboard/src/views/ChatBoxPage.vue b/dashboard/src/views/ChatBoxPage.vue index 123b7b4a2..940b52dce 100644 --- a/dashboard/src/views/ChatBoxPage.vue +++ b/dashboard/src/views/ChatBoxPage.vue @@ -1,5 +1,5 @@ @@ -9,7 +9,7 @@ const customizer = useCustomizerStore();
- +
@@ -18,24 +18,6 @@ const customizer = useCustomizerStore(); \ No newline at end of file diff --git a/dashboard/src/views/ChatPage.vue b/dashboard/src/views/ChatPage.vue index eb0bdf231..93dfdad84 100644 --- a/dashboard/src/views/ChatPage.vue +++ b/dashboard/src/views/ChatPage.vue @@ -1,2048 +1,15 @@ - - - - \ No newline at end of file diff --git a/dashboard/src/views/ConversationPage.vue b/dashboard/src/views/ConversationPage.vue index 9d93bb279..d632afd4a 100644 --- a/dashboard/src/views/ConversationPage.vue +++ b/dashboard/src/views/ConversationPage.vue @@ -167,46 +167,12 @@

{{ tm('status.emptyContent') }}

- -
-
- -
-
- - - -
-
- -
-
- - -
- -
-
- - - -
- - -
- - - -
-
-
-
-
-
+ + @@ -291,6 +257,7 @@ import { VueMonacoEditor } from '@guolao/vue-monaco-editor'; import MarkdownIt from 'markdown-it'; import { useCommonStore } from '@/stores/common'; import { useI18n, useModuleI18n } from '@/i18n/composables'; +import MessageList from '@/components/chat/MessageList.vue'; // 配置markdown-it,默认安全设置 const md = new MarkdownIt({ @@ -303,7 +270,8 @@ const md = new MarkdownIt({ export default { name: 'ConversationPage', components: { - VueMonacoEditor + VueMonacoEditor, + MessageList }, setup() { @@ -484,6 +452,30 @@ export default { messageTypes: this.messageTypeFilter, search: this.search }; + }, + + // 将对话历史转换为 MessageList 组件期望的格式 + formattedMessages() { + return this.conversationHistory.map(msg => { + console.log('处理消息:', msg.role, msg.image_url, msg.audio_url); + if (msg.role === 'user') { + return { + content: { + type: 'user', + message: this.extractTextFromContent(msg.content), + image_url: this.extractImagesFromContent(msg.content), + } + }; + } else { + return { + content: { + type: 'bot', + message: this.extractTextFromContent(msg.content), + embedded_images: this.extractImagesFromContent(msg.content), + } + }; + } + }); } }, @@ -861,6 +853,30 @@ export default { this.message = message; this.messageType = 'error'; this.showMessage = true; + }, + + // 从内容中提取文本 + extractTextFromContent(content) { + if (typeof content === 'string') { + return content; + } else if (Array.isArray(content)) { + return content.filter(item => item.type === 'text') + .map(item => item.text) + .join('\n'); + } else if (typeof content === 'object') { + return Object.values(content).filter(val => typeof val === 'string').join(''); + } + return ''; + }, + + // 从内容中提取图片URL + extractImagesFromContent(content) { + if (Array.isArray(content)) { + return content.filter(item => item.type === 'image_url') + .map(item => item.image_url?.url) + .filter(url => url); + } + return []; } } } @@ -885,7 +901,7 @@ export default { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } -/* 聊天消息样式 */ +/* 聊天消息容器样式 */ .conversation-messages-container { max-height: 500px; overflow-y: auto; @@ -894,87 +910,6 @@ export default { background-color: #f9f9f9; } -.message-list { - display: flex; - flex-direction: column; - gap: 16px; -} - -.message-item { - margin-bottom: 8px; - animation: fadeIn 0.3s ease-out; -} - -.user-message { - display: flex; - justify-content: flex-end; - align-items: flex-start; - gap: 12px; -} - -.bot-message { - display: flex; - justify-content: flex-start; - align-items: flex-start; - gap: 12px; -} - -.message-bubble { - padding: 12px 16px; - border-radius: 18px; - max-width: 80%; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.user-bubble { - background-color: #f0f4ff; - color: #333; - border-top-right-radius: 4px; -} - -.bot-bubble { - background-color: #fff; - border: 1px solid #eaeaea; - color: #333; - border-top-left-radius: 4px; -} - -.user-avatar, -.bot-avatar { - margin-top: 2px; -} - -/* 附件样式 */ -.image-attachments { - display: flex; - gap: 8px; - margin-top: 8px; - flex-wrap: wrap; -} - -.attached-image { - width: 120px; - height: 120px; - object-fit: cover; - border-radius: 8px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - transition: transform 0.2s ease; -} - -.attached-image:hover { - transform: scale(1.05); -} - -.audio-attachment { - margin-top: 8px; -} - -.audio-player { - width: 100%; - height: 36px; - border-radius: 18px; -} - /* 对话详情卡片 */ .conversation-detail-card { max-height: 90vh; @@ -982,95 +917,6 @@ export default { flex-direction: column; } -/* Markdown内容样式 */ -.markdown-content { - font-family: inherit; - line-height: 1.6; -} - -.markdown-content h1, -.markdown-content h2, -.markdown-content h3, -.markdown-content h4, -.markdown-content h5, -.markdown-content h6 { - margin-top: 16px; - margin-bottom: 10px; - font-weight: 600; - color: #333; -} - -.markdown-content h1 { - font-size: 1.8em; - border-bottom: 1px solid #eee; - padding-bottom: 6px; -} - -.markdown-content h2 { - font-size: 1.5em; -} - -.markdown-content h3 { - font-size: 1.3em; -} - -.markdown-content li { - margin-left: 16px; - margin-bottom: 4px; -} - -.markdown-content p { - margin-top: 10px; - margin-bottom: 10px; -} - -.markdown-content pre { - background-color: #f8f8f8; - padding: 12px; - border-radius: 6px; - overflow-x: auto; - margin: 12px 0; -} - -.markdown-content code { - background-color: #f5f0ff; - padding: 2px 4px; - border-radius: 4px; - font-family: 'Fira Code', monospace; - font-size: 0.9em; - color: #673ab7; -} - -.markdown-content img { - max-width: 100%; - border-radius: 8px; - margin: 10px 0; -} - -.markdown-content blockquote { - border-left: 4px solid #673ab7; - padding-left: 16px; - color: #666; - margin: 16px 0; -} - -.markdown-content table { - border-collapse: collapse; - width: 100%; - margin: 16px 0; -} - -.markdown-content th, -.markdown-content td { - border: 1px solid #eee; - padding: 8px 12px; - text-align: left; -} - -.markdown-content th { - background-color: #f5f0ff; -} - /* 动画 */ @keyframes fadeIn { from { diff --git a/dashboard/src/views/PersonaPage.vue b/dashboard/src/views/PersonaPage.vue index 18cc54452..1da6a7dec 100644 --- a/dashboard/src/views/PersonaPage.vue +++ b/dashboard/src/views/PersonaPage.vue @@ -23,7 +23,7 @@ - +
{{ persona.persona_id }} @@ -296,9 +296,9 @@

{{ tm('form.systemPrompt') }}

-
+
                             {{ viewingPersona.system_prompt }}
-                        
+
@@ -759,10 +759,6 @@ export default { cursor: pointer; } -.persona-card:hover { - box-shadow: 0 8px 25px 0 rgba(0, 0, 0, 0.15); -} - .system-prompt-preview { font-size: 14px; line-height: 1.4; @@ -775,10 +771,10 @@ export default { } .system-prompt-content { - background-color: rgba(var(--v-theme-surface-variant), 0.3); + max-height: 400px; + overflow: auto; padding: 12px; border-radius: 8px; - font-family: 'Roboto Mono', monospace; font-size: 14px; line-height: 1.5; white-space: pre-wrap; diff --git a/dashboard/src/views/dashboards/default/DefaultDashboard.vue b/dashboard/src/views/dashboards/default/DefaultDashboard.vue index 3b66f83de..4037a0045 100644 --- a/dashboard/src/views/dashboards/default/DefaultDashboard.vue +++ b/dashboard/src/views/dashboards/default/DefaultDashboard.vue @@ -1,10 +1,5 @@