From d6ab956951e7da903d3cb40808fff11ee0f12a81 Mon Sep 17 00:00:00 2001 From: donghaolin <17667510818@163.com> Date: Tue, 25 Feb 2025 11:44:46 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=BF=99=E6=98=AF=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/chat.vue | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/views/chat.vue b/src/views/chat.vue index 944943a..ca68658 100644 --- a/src/views/chat.vue +++ b/src/views/chat.vue @@ -4,6 +4,7 @@ import { useUserInfo } from '../store/userPermissionCode' import axios from 'axios' import { ElMessage } from 'element-plus'; import { Loading, Position } from '@element-plus/icons-vue'; // 引入图标组件 +import { marked } from 'marked'; // 引入marked库 const { getQueryVariable } = useUserInfo() // 假设 getSessionId 已经正确定义 @@ -17,7 +18,7 @@ const fnGetToken = () => { setTimeout(() => { fnGetToken() }, 800) -const token = localStorage.getItem('localToken') + // 验证 token const validateToken = async () => { const token = localStorage.getItem('localToken') @@ -34,7 +35,7 @@ const sessionId = ref(localStorage.getItem('sessionId') || {}); const add = async () => { try { const result = await axios.post( - "http://2zhyw2.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", + "http://td7idg.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", {}, { headers: { @@ -132,7 +133,7 @@ const sendMessage = async () => { try { // 调用API获取回复 - const response = await fetch("http://2zhyw2.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { + const response = await fetch("http://td7idg.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, body: JSON.stringify({ question: content, stream: false, session_id: sessionId.value }) @@ -160,6 +161,9 @@ const sendMessage = async () => { // } combinedContent += `${result}`; + // 使用marked库将Markdown转换为HTML + const markdownContent = marked(combinedContent); + // 添加初始空消息 const botMessageIndex = messages.value.length; messages.value.push({ @@ -171,8 +175,8 @@ const sendMessage = async () => { // 使用定时器逐个字符更新消息内容 let currentIndex = 0; const intervalId = setInterval(() => { - if (currentIndex < combinedContent.length) { - messages.value[botMessageIndex].content += combinedContent[currentIndex]; + if (currentIndex < markdownContent.length) { + messages.value[botMessageIndex].content += markdownContent[currentIndex]; scrollToBottom(); currentIndex++; } else { @@ -288,6 +292,7 @@ onMounted(async () => { /* 其他样式保持不变 */ .message-item.bot { justify-content: flex-start; /* 让机器人消息靠左对齐 */ + text-align: left; /* 新增:设置文本左对齐 */ } .chat-container { display: flex; From 13bf134089907026cebdb5f0e443479cbd388454 Mon Sep 17 00:00:00 2001 From: donghaolin <17667510818@163.com> Date: Tue, 25 Feb 2025 11:45:14 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- package-lock.json | 36 ++++++++++++++++++++++++++++++++++++ package.json | 2 ++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f0ae81..8309258 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,6 @@ npm run build 打包 npm install router 路由 npm install axios 网络请求 npm install element-plus --save element-plus组件库 -npm install @element-plus/icons-vue 组件库图标 \ No newline at end of file +npm install @element-plus/icons-vue 组件库图标 +npm install marked 解析markdown 解析文本样式 +npm install katex 数学公式 解析数学公式样式 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7aface2..8d8b556 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "@element-plus/icons-vue": "^2.3.1", "axios": "^1.7.9", "element-plus": "^2.9.4", + "katex": "^0.16.21", + "marked": "^15.0.7", "stream": "^0.0.3", "vue": "^3.5.13", "vue-router": "^4.5.0" @@ -1101,6 +1103,14 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, "node_modules/component-emitter": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/component-emitter/-/component-emitter-2.0.0.tgz", @@ -1430,6 +1440,21 @@ "node": ">= 0.4" } }, + "node_modules/katex": { + "version": "0.16.21", + "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.21.tgz", + "integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", @@ -1462,6 +1487,17 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/marked": { + "version": "15.0.7", + "resolved": "https://registry.npmmirror.com/marked/-/marked-15.0.7.tgz", + "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/package.json b/package.json index 62a6fef..bd9f75b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "@element-plus/icons-vue": "^2.3.1", "axios": "^1.7.9", "element-plus": "^2.9.4", + "katex": "^0.16.21", + "marked": "^15.0.7", "stream": "^0.0.3", "vue": "^3.5.13", "vue-router": "^4.5.0" From 560989512ec8125fde69844b58e9e7edcaf69a02 Mon Sep 17 00:00:00 2001 From: donghaolin <17667510818@163.com> Date: Tue, 25 Feb 2025 13:55:37 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=8A=A0=E4=BA=86=E6=95=B0=E5=AD=A6?= =?UTF-8?q?=E5=85=AC=E5=BC=8F=E7=9A=84=E6=A0=B7=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/chat.vue | 100 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/src/views/chat.vue b/src/views/chat.vue index ca68658..34d5460 100644 --- a/src/views/chat.vue +++ b/src/views/chat.vue @@ -5,6 +5,8 @@ import axios from 'axios' import { ElMessage } from 'element-plus'; import { Loading, Position } from '@element-plus/icons-vue'; // 引入图标组件 import { marked } from 'marked'; // 引入marked库 +import katex from 'katex'; // 引入 KaTeX 库 +import 'katex/dist/katex.min.css'; // 引入 KaTeX 样式 const { getQueryVariable } = useUserInfo() // 假设 getSessionId 已经正确定义 @@ -35,7 +37,7 @@ const sessionId = ref(localStorage.getItem('sessionId') || {}); const add = async () => { try { const result = await axios.post( - "http://td7idg.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", + "http://asp69f.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", {}, { headers: { @@ -133,7 +135,7 @@ const sendMessage = async () => { try { // 调用API获取回复 - const response = await fetch("http://td7idg.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { + const response = await fetch("http://asp69f.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, body: JSON.stringify({ question: content, stream: false, session_id: sessionId.value }) @@ -143,47 +145,69 @@ const sendMessage = async () => { // 移除加载消息 messages.value = messages.value.filter(msg => !msg.isLoading); - // 提取推理思考部分和结果部分 - const regex = /(.*?)<\/think>(.*)/s; - const match = data.data.answer.match(regex); - let thinking = ''; - let result = data.data.answer; - - if (match) { - thinking = match[1].trim(); - result = match[2].trim(); - } - - // 组合推理思考内容和结果内容,并添加 HTML 标签 - let combinedContent = ''; - // if (thinking) { - // combinedContent += `推理思考:${thinking}
`; - // } - combinedContent += `${result}`; - // 使用marked库将Markdown转换为HTML - const markdownContent = marked(combinedContent); + // 检查 data 对象的结构,确保正确提取所需属性 + if (data && data.data && typeof data.data.answer === 'string') { + // 提取推理思考部分和结果部分 + const regex = /(.*?)<\/think>(.*)/s; + const match = data.data.answer.match(regex); + let thinking = ''; + let result = data.data.answer; + + if (match) { + thinking = match[1].trim(); + result = match[2].trim(); + } - // 添加初始空消息 - const botMessageIndex = messages.value.length; - messages.value.push({ - content: '', - sender: 'bot', - timestamp: new Date() - }); + // 组合推理思考内容和结果内容,并添加 HTML 标签 + let combinedContent = ''; + // if (thinking) { + // combinedContent += `推理思考:${thinking}
`; + // } + combinedContent += `${result}`; - // 使用定时器逐个字符更新消息内容 - let currentIndex = 0; - const intervalId = setInterval(() => { + // 使用marked库将Markdown转换为HTML + let markdownContent = marked(combinedContent); + + // 使用 KaTeX 渲染数学公式 + const katexRegex = /\$\$(.*?)\$\$/g; + markdownContent = markdownContent.replace(katexRegex, (match, formula) => { + try { + return katex.renderToString(formula, { throwOnError: false }); + } catch (error) { + console.error('KaTeX 渲染错误:', error); + return match; + } + }); + + // 添加初始空消息 + const botMessageIndex = messages.value.length; + messages.value.push({ + content: '', + sender: 'bot', + timestamp: new Date() + }); + + // 使用定时器逐个字符更新消息内容 + let currentIndex = 0; + const intervalId = setInterval(() => { if (currentIndex < markdownContent.length) { messages.value[botMessageIndex].content += markdownContent[currentIndex]; - scrollToBottom(); - currentIndex++; - } else { - clearInterval(intervalId); - } - }, 100); // 每100毫秒添加一个字符,可以根据需要调整 - + scrollToBottom(); + currentIndex++; + } else { + clearInterval(intervalId); + } + }, 100); // 每100毫秒添加一个字符,可以根据需要调整 + } else { + console.error('API 返回的数据格式不正确:', data); + messages.value.push({ + content: '服务返回数据格式错误,请稍后再试', + sender: 'bot', + timestamp: new Date() + }); + scrollToBottom(); + } } catch (error) { console.error('API请求失败:', error); // 移除加载消息 From 504c53e88947da294e0004ea144469c68b600edf Mon Sep 17 00:00:00 2001 From: donghaolin <17667510818@163.com> Date: Tue, 25 Feb 2025 15:02:32 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=A1=A8=E6=A0=BC=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/style.css | 29 +++++++++++++++++++++++++++++ src/views/chat.vue | 26 ++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/style.css b/src/style.css index 7820c46..a339ef5 100644 --- a/src/style.css +++ b/src/style.css @@ -77,3 +77,32 @@ button:focus-visible { background-color: #f9f9f9; } } + +/* 表格整体样式 */ +table { + border-collapse: collapse; /* 合并相邻单元格的边框 */ + width: 100%; /* 表格宽度为父容器的 100% */ + margin-bottom: 1rem; /* 表格底部外边距 */ + color: #212529; /* 表格文字颜色 */ +} + +/* 表头单元格样式 */ +table th { + padding: 0.75rem; /* 内边距 */ + border: 2px solid #dee2e6; /* 边框宽度、样式和颜色 */ + background-color: #f8f9fa; /* 表头背景颜色 */ + text-align: left; /* 文字左对齐 */ + font-weight: bold; /* 文字加粗 */ +} + +/* 表格数据单元格样式 */ +table td { + padding: 0.75rem; /* 内边距 */ + border: 1px solid #dee2e6; /* 边框宽度、样式和颜色 */ + text-align: left; /* 文字左对齐 */ +} + +/* 鼠标悬停时表格行的样式 */ +table tr:hover { + background-color: #f2f2f2; /* 鼠标悬停时的背景颜色 */ +} diff --git a/src/views/chat.vue b/src/views/chat.vue index 34d5460..26c6b79 100644 --- a/src/views/chat.vue +++ b/src/views/chat.vue @@ -37,7 +37,7 @@ const sessionId = ref(localStorage.getItem('sessionId') || {}); const add = async () => { try { const result = await axios.post( - "http://asp69f.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", + "http://wnxvxx.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", {}, { headers: { @@ -135,7 +135,7 @@ const sendMessage = async () => { try { // 调用API获取回复 - const response = await fetch("http://asp69f.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { + const response = await fetch("http://wnxvxx.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ragflow-hkNjEwYjcwZjBlMDExZWZiYjYzMDI0Mm' }, body: JSON.stringify({ question: content, stream: false, session_id: sessionId.value }) @@ -308,11 +308,30 @@ onMounted(async () => { \ No newline at end of file