diff --git a/README.md b/README.md index 4e786f6..b9f19bb 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,5 @@ npm install router 路由 npm install axios 网络请求 npm install element-plus --save element-plus组件库 npm install @element-plus/icons-vue 组件库图标 -npm install marked markdown解析 \ No newline at end of file +npm install marked 解析markdown 解析文本样式 +npm install katex 数学公式 解析数学公式样式 diff --git a/package-lock.json b/package-lock.json index c130012..8d8b556 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@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", @@ -1102,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", @@ -1431,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", @@ -1467,7 +1491,6 @@ "version": "15.0.7", "resolved": "https://registry.npmmirror.com/marked/-/marked-15.0.7.tgz", "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", - "license": "MIT", "bin": { "marked": "bin/marked.js" }, diff --git a/package.json b/package.json index c147b34..bd9f75b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@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", 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 944943a..26c6b79 100644 --- a/src/views/chat.vue +++ b/src/views/chat.vue @@ -4,6 +4,9 @@ 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库 +import katex from 'katex'; // 引入 KaTeX 库 +import 'katex/dist/katex.min.css'; // 引入 KaTeX 样式 const { getQueryVariable } = useUserInfo() // 假设 getSessionId 已经正确定义 @@ -17,7 +20,7 @@ const fnGetToken = () => { setTimeout(() => { fnGetToken() }, 800) -const token = localStorage.getItem('localToken') + // 验证 token const validateToken = async () => { const token = localStorage.getItem('localToken') @@ -34,7 +37,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://wnxvxx.natappfree.cc/api/v1/chats/8b37cd9cf0c811efa4210242ac120003/completions", {}, { headers: { @@ -132,7 +135,7 @@ const sendMessage = async () => { try { // 调用API获取回复 - const response = await fetch("http://2zhyw2.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 }) @@ -142,44 +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}`; - - // 添加初始空消息 - const botMessageIndex = messages.value.length; - messages.value.push({ - content: '', - sender: 'bot', - timestamp: new Date() - }); - // 使用定时器逐个字符更新消息内容 - let currentIndex = 0; - const intervalId = setInterval(() => { - if (currentIndex < combinedContent.length) { - messages.value[botMessageIndex].content += combinedContent[currentIndex]; - scrollToBottom(); - currentIndex++; - } else { - clearInterval(intervalId); + // 检查 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(); } - }, 100); // 每100毫秒添加一个字符,可以根据需要调整 + // 组合推理思考内容和结果内容,并添加 HTML 标签 + let combinedContent = ''; + // if (thinking) { + // combinedContent += `推理思考:${thinking}
`; + // } + combinedContent += `${result}`; + + // 使用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毫秒添加一个字符,可以根据需要调整 + } else { + console.error('API 返回的数据格式不正确:', data); + messages.value.push({ + content: '服务返回数据格式错误,请稍后再试', + sender: 'bot', + timestamp: new Date() + }); + scrollToBottom(); + } } catch (error) { console.error('API请求失败:', error); // 移除加载消息 @@ -280,14 +308,34 @@ onMounted(async () => { \ No newline at end of file