From 8137a38060a8bc2fc06a198e9add959dcb150ef5 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 00:58:02 +0800 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20websocket=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- src/common/WebSocketManager.ts | 52 ++++++++++++++++------ src/renderer/views/home/ChatBox.vue | 7 +-- src/renderer/views/home/index.vue | 4 +- src/renderer/views/home/model/ChatModel.ts | 6 ++- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/index.html b/index.html index f141c3e..8576aba 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ diff --git a/src/common/WebSocketManager.ts b/src/common/WebSocketManager.ts index 95c8259..b082232 100644 --- a/src/common/WebSocketManager.ts +++ b/src/common/WebSocketManager.ts @@ -113,22 +113,46 @@ export class WebSocketManager { await this.connect() } + // 改进方案:让connect()真正等待连接 async connect(): Promise { - if (this.isConnecting || this.connectionState) return - this.isConnecting = true - - try { - this.ws = new WebSocket(this.wsUrl, this.protocols) - console.log('WebSocket connecting to:', this.wsUrl) - this.ws.onopen = this.handleOpen - this.ws.onmessage = this.handleMessage - this.ws.onclose = this.handleClose - this.ws.onerror = this.handleError - } catch (error) { - this.isConnecting = false - this.safeCall('onError', error) - this.scheduleReconnect() + console.log('[WebSocket] connect() called, isConnecting:', this.isConnecting, 'connectionState:', this.connectionState) + if (this.isConnecting || this.connectionState) { + console.log('[WebSocket] Already connecting or connected, returning early') + return } + this.isConnecting = true + console.log('[WebSocket] Starting connection...') + + return new Promise((resolve, reject) => { + try { + console.log('[WebSocket] About to create new WebSocket with URL:', this.wsUrl) + this.ws = new WebSocket(this.wsUrl, this.protocols) + console.log('[WebSocket] WebSocket object created, readyState:', this.ws?.readyState) + + // 包装handleOpen以resolve Promise + this.ws.onopen = (event: Event) => { + console.log('[WebSocket] onopen event fired') + this.handleOpen(event) + resolve() // ← 真正的连接成功 + } + + this.ws.onmessage = this.handleMessage + this.ws.onclose = (event: CloseEvent) => { + console.log('[WebSocket] onclose event fired, code:', event.code, 'reason:', event.reason) + this.handleClose(event) + } + this.ws.onerror = (error: Event) => { + console.log('[WebSocket] onerror event fired', error) + this.handleError(error) + reject(error) // ← Promise拒绝 + } + } catch (error) { + this.isConnecting = false + this.safeCall('onError', error) + this.scheduleReconnect() + reject(error) + } + }) } private handleOpen = (event: Event): void => { diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index 514c792..d1b3a04 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -24,12 +24,12 @@ -
+
本回答由 AI 生成
-
@@ -38,7 +38,6 @@
-
@@ -318,6 +317,7 @@ const initWebSocket = async () => { // 处理WebSocket消息 const handleWebSocketMessage = (data: any) => { + console.log("收到WebSocket消息:", data); // 验证关键字段(若服务端传回 conversationId/agentId,则校验是否属于当前会话) if (data.conversationId && data.conversationId !== conversationId.value) { console.warn("收到不属于当前会话的消息,忽略", data.conversationId); @@ -374,6 +374,7 @@ const handleWebSocketMessage = (data: any) => { // 处理完成状态 if (data.finish) { + chatMsgList.value[aiMsgIndex].finished = data.finish; const msg = chatMsgList.value[aiMsgIndex].messageContent; if (!msg || chatMsgList.value[aiMsgIndex].isLoading) { chatMsgList.value[aiMsgIndex].messageContent = "未获取到内容,请重试"; diff --git a/src/renderer/views/home/index.vue b/src/renderer/views/home/index.vue index 75111b1..15de520 100644 --- a/src/renderer/views/home/index.vue +++ b/src/renderer/views/home/index.vue @@ -3,8 +3,8 @@
- - + +
diff --git a/src/renderer/views/home/model/ChatModel.ts b/src/renderer/views/home/model/ChatModel.ts index a123c05..107e976 100644 --- a/src/renderer/views/home/model/ChatModel.ts +++ b/src/renderer/views/home/model/ChatModel.ts @@ -18,6 +18,8 @@ export class ChatMessage { messageContent: string; // 是否加载中 isLoading?: boolean; + // 是否完成 + finished?: boolean; // 工具调用信息 toolCall?: any; // 问题信息 @@ -28,13 +30,15 @@ export class ChatMessage { messageRole: MessageRole, messageContent: string, isLoading: boolean = false, + finished: boolean = false, toolCall?: any, question?: any ) { + this.messageId = messageId; this.messageRole = messageRole; this.messageContent = messageContent; + this.finished = finished; this.isLoading = isLoading; - this.messageId = messageId; this.toolCall = toolCall; this.question = question; } -- 2.43.7 From 9c5afcaa04bccd676575905e92447a9959fd2187 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 01:46:30 +0800 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=E8=81=8A=E5=A4=A9=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- global.d.ts | 6 +++ src/renderer/views/home/ChatBox.vue | 41 ++++-------------- .../views/home/components/ChatAvatar.vue | 13 ++++++ .../views/home/components/ChatOperation.vue | 43 +++++++++++++++++++ src/renderer/views/home/model/ChatModel.ts | 4 +- 5 files changed, 73 insertions(+), 34 deletions(-) create mode 100644 src/renderer/views/home/components/ChatAvatar.vue create mode 100644 src/renderer/views/home/components/ChatOperation.vue diff --git a/global.d.ts b/global.d.ts index b396180..ff00914 100644 --- a/global.d.ts +++ b/global.d.ts @@ -134,6 +134,12 @@ declare global { } } +declare module "*.vue" { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} + declare module "@store/*"; declare module "@service/*"; declare module "@utils/*"; diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index d1b3a04..892c985 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -8,8 +8,7 @@ :class="msg.messageRole === MessageRole.ME ? 'justify-end' : 'justify-start'"> - +
@@ -18,6 +17,7 @@ ZHINIAN 20:30
+
{{ msg.messageContent }} @@ -29,21 +29,11 @@
-
- -
- - - - -
-
+ - + @@ -84,9 +74,14 @@ import { onMounted, nextTick, onUnmounted } from "vue"; import { WebSocketManager } from "@common/WebSocketManager"; import { MessageRole, ChatMessage } from "./model/ChatModel"; import { IdUtils } from "@common/index"; +import ChatAvatar from './components/ChatAvatar.vue'; +import ChatOperation from './components/ChatOperation.vue'; import { Session } from '../../utils/storage'; +import userAvatar from '@assets/images/login/user_icon.png'; +import aiAvatar from '@assets/images/login/blue_logo.png'; + ///(控制滚动位置) const scrollTop = ref(99999); @@ -161,24 +156,6 @@ const handleReplyInstruct = async (message: string, type: string) => { setTimeoutScrollToBottom(); }; - -/// actions 实现复制、分享、下载、点赞等功能 -const copyFileClick = (msg: ChatMessage) => { - console.log('copy file', msg) -} -const shareForwardClick = (msg: ChatMessage) => { - console.log('share forward', msg) -} -const downloadClick = (msg: ChatMessage) => { - console.log('download', msg) -} -const thumbUpClick = (msg: ChatMessage) => { - console.log('thumb up', msg) -} -const thumbDownClick = (msg: ChatMessage) => { - console.log('thumb down', msg) -} - /// 添加附件按钮事件 const addAttachmentAction = () => { console.log("添加附件"); diff --git a/src/renderer/views/home/components/ChatAvatar.vue b/src/renderer/views/home/components/ChatAvatar.vue new file mode 100644 index 0000000..99bbe3e --- /dev/null +++ b/src/renderer/views/home/components/ChatAvatar.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/src/renderer/views/home/components/ChatOperation.vue b/src/renderer/views/home/components/ChatOperation.vue new file mode 100644 index 0000000..36265a6 --- /dev/null +++ b/src/renderer/views/home/components/ChatOperation.vue @@ -0,0 +1,43 @@ + + \ No newline at end of file diff --git a/src/renderer/views/home/model/ChatModel.ts b/src/renderer/views/home/model/ChatModel.ts index 107e976..60bd013 100644 --- a/src/renderer/views/home/model/ChatModel.ts +++ b/src/renderer/views/home/model/ChatModel.ts @@ -34,11 +34,11 @@ export class ChatMessage { toolCall?: any, question?: any ) { - this.messageId = messageId; + this.messageId = messageId; this.messageRole = messageRole; this.messageContent = messageContent; - this.finished = finished; this.isLoading = isLoading; + this.finished = finished; this.toolCall = toolCall; this.question = question; } -- 2.43.7 From acc3d24f78662df8a06e8a9f02ecc7f5e6b8a451 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 15:39:59 +0800 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=E5=B0=86=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E4=BD=BF=E7=94=A8markdown=20=E6=B8=B2?= =?UTF-8?q?=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 607 +++++++++++++++++- package.json | 4 +- src/renderer/views/home/ChatBox.vue | 16 +- .../views/home/components/ChatRoleAI.vue | 31 + .../views/home/components/ChatRoleMe.vue | 17 + 5 files changed, 665 insertions(+), 10 deletions(-) create mode 100644 src/renderer/views/home/components/ChatRoleAI.vue create mode 100644 src/renderer/views/home/components/ChatRoleMe.vue diff --git a/package-lock.json b/package-lock.json index 92f8598..79e8bc8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,10 +26,12 @@ "electron-log": "^5.4.3", "electron-squirrel-startup": "^1.0.1", "element-plus": "^2.12.0", + "highlight.js": "^11.11.1", "js-base64": "^3.7.8", "js-cookie": "^3.0.5", "lodash-es": "^4.17.21", "log4js": "^6.9.1", + "markdown-it": "^14.1.0", "openai": "^6.14.0", "pinia": "^2.3.1", "vue": "^3.5.22", @@ -1501,6 +1503,99 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@exodus/schemasafe": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", @@ -1540,6 +1635,47 @@ "dev": true, "license": "MIT" }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/@iconify-json/material-symbols": { "version": "1.2.50", "resolved": "https://registry.npmmirror.com/@iconify-json/material-symbols/-/material-symbols-1.2.50.tgz", @@ -3136,6 +3272,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", @@ -3541,6 +3685,17 @@ "acorn": "^8.14.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -4585,6 +4740,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -4703,6 +4866,20 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "17.2.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", @@ -5726,7 +5903,6 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=10" }, @@ -5734,6 +5910,64 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -5761,6 +5995,75 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/esniff": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/esniff/-/esniff-2.0.1.tgz", @@ -5777,6 +6080,50 @@ "node": ">=0.10" } }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -5820,6 +6167,17 @@ "@types/estree": "^1.0.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz", @@ -6050,6 +6408,14 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -6112,6 +6478,20 @@ } } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -6170,6 +6550,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -6514,6 +6910,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -6597,6 +7024,14 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6660,6 +7095,15 @@ "node": ">= 0.4" } }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -6957,6 +7401,17 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-2.2.2.tgz", @@ -7139,6 +7594,14 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -7180,6 +7643,21 @@ "json-buffer": "3.0.1" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lightningcss": { "version": "1.30.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", @@ -7630,6 +8108,14 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -8244,6 +8730,14 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -8759,6 +9253,25 @@ "dev": true, "license": "0BSD" }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -9233,6 +9746,17 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.7.4", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", @@ -9307,6 +9831,17 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/punycode.js": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", @@ -9377,6 +9912,16 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-binary-file-arch": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", @@ -10351,6 +10896,20 @@ "node": ">=0.10.0" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", @@ -10618,6 +11177,14 @@ "dev": true, "license": "MIT" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/timers-ext": { "version": "0.1.8", "resolved": "https://registry.npmmirror.com/timers-ext/-/timers-ext-0.1.8.tgz", @@ -10783,6 +11350,20 @@ "dev": true, "license": "ISC" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -10800,7 +11381,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11002,6 +11583,17 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/username": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz", @@ -11332,7 +11924,6 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } @@ -11566,6 +12157,16 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index cdd2fbb..336b86e 100644 --- a/package.json +++ b/package.json @@ -63,10 +63,12 @@ "electron-log": "^5.4.3", "electron-squirrel-startup": "^1.0.1", "element-plus": "^2.12.0", + "highlight.js": "^11.11.1", "js-base64": "^3.7.8", "js-cookie": "^3.0.5", "lodash-es": "^4.17.21", "log4js": "^6.9.1", + "markdown-it": "^14.1.0", "openai": "^6.14.0", "pinia": "^2.3.1", "vue": "^3.5.22", @@ -74,4 +76,4 @@ "vue-markdown-render": "^2.3.0", "vue-router": "^4.5.1" } -} \ No newline at end of file +} diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index 892c985..1841805 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -18,10 +18,11 @@ 20:30 -
- {{ msg.messageContent }} -
+ + + + +
@@ -29,7 +30,7 @@
- + @@ -69,19 +70,22 @@ \ No newline at end of file diff --git a/src/renderer/views/home/components/ChatRoleMe.vue b/src/renderer/views/home/components/ChatRoleMe.vue new file mode 100644 index 0000000..1dccffd --- /dev/null +++ b/src/renderer/views/home/components/ChatRoleMe.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file -- 2.43.7 From b8cdf530fcc0173d775caec9e69ab6bb11184e3b Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 16:08:36 +0800 Subject: [PATCH 04/15] =?UTF-8?q?feat=EF=BC=9A=E8=B0=83=E6=95=B4=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/views/home/ChatBox.vue | 13 ++--- .../views/home/components/ChatAIMark.vue | 5 ++ .../views/home/components/ChatLoading.vue | 50 +++++++++++++++++++ .../views/home/components/ChatNameTime.vue | 17 +++++++ .../views/home/components/ChatRoleAI.vue | 5 +- 5 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/renderer/views/home/components/ChatAIMark.vue create mode 100644 src/renderer/views/home/components/ChatLoading.vue create mode 100644 src/renderer/views/home/components/ChatNameTime.vue diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index 1841805..b61278e 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -12,11 +12,8 @@
-
- ZHINIAN - 20:30 -
+ + @@ -25,9 +22,7 @@ -
- 本回答由 AI 生成 -
+ @@ -79,6 +74,8 @@ import ChatAvatar from './components/ChatAvatar.vue'; import ChatOperation from './components/ChatOperation.vue'; import ChatRoleAI from './components/ChatRoleAI.vue'; import ChatRoleMe from './components/ChatRoleMe.vue'; +import ChatAIMark from './components/ChatAIMark.vue'; +import ChatNameTime from './components/ChatNameTime.vue'; import { Session } from '../../utils/storage'; diff --git a/src/renderer/views/home/components/ChatAIMark.vue b/src/renderer/views/home/components/ChatAIMark.vue new file mode 100644 index 0000000..59f7945 --- /dev/null +++ b/src/renderer/views/home/components/ChatAIMark.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/src/renderer/views/home/components/ChatLoading.vue b/src/renderer/views/home/components/ChatLoading.vue new file mode 100644 index 0000000..8739f80 --- /dev/null +++ b/src/renderer/views/home/components/ChatLoading.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/renderer/views/home/components/ChatNameTime.vue b/src/renderer/views/home/components/ChatNameTime.vue new file mode 100644 index 0000000..3b28e25 --- /dev/null +++ b/src/renderer/views/home/components/ChatNameTime.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/src/renderer/views/home/components/ChatRoleAI.vue b/src/renderer/views/home/components/ChatRoleAI.vue index 71f538f..94b1960 100644 --- a/src/renderer/views/home/components/ChatRoleAI.vue +++ b/src/renderer/views/home/components/ChatRoleAI.vue @@ -1,5 +1,7 @@ @@ -9,6 +11,7 @@ import { computed } from 'vue' import MarkdownIt from 'markdown-it' import hljs from 'highlight.js' import 'highlight.js/styles/github.css' +import ChatLoading from './ChatLoading.vue'; interface Props { msg: ChatMessage -- 2.43.7 From bdb685b4ec06957070d891c0941f1f12ebcf2b99 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 17:07:48 +0800 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20=E6=9B=B4=E6=8D=A2=E4=BC=9A?= =?UTF-8?q?=E8=AF=9Did?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/views/home/ChatBox.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index b61278e..9c9a3b3 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -94,7 +94,7 @@ const inputMessage = ref(""); const isSendingMessage = ref(false); /// agentId 首页接口中获取 -const agentId = ref("1"); +const agentId = ref("1953462165250859010"); /// 会话ID 历史数据接口中获取 const conversationId = ref(""); // 会话进行中标志 @@ -605,6 +605,7 @@ const sendChat = async (message: string, isInstruct = false) => { pendingMap.delete(currentSessionMessageId); pendingTimeouts.delete(currentSessionMessageId); isSessionActive.value = false; + isSendingMessage.value = false; setTimeoutScrollToBottom(); } }, MESSAGE_TIMEOUT); -- 2.43.7 From aa8c1737ad0aece9700205116ebecfe6c91bc567 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 21:21:30 +0800 Subject: [PATCH 06/15] =?UTF-8?q?feat:=20=E5=A4=84=E7=90=86=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=8F=91=E9=80=81=E4=B9=8B=E5=90=8E=E7=9A=84=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=BB=9A=E5=8A=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/views/home/ChatBox.vue | 49 ++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index 9c9a3b3..1338c7e 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -83,8 +83,8 @@ import userAvatar from '@assets/images/login/user_icon.png'; import aiAvatar from '@assets/images/login/blue_logo.png'; -///(控制滚动位置) -const scrollTop = ref(99999); +// 列表滚动容器引用 +const listRef = ref(null); /// 会话列表 const chatMsgList = ref([]); @@ -93,8 +93,8 @@ const inputMessage = ref(""); /// 发送消息中标志 const isSendingMessage = ref(false); -/// agentId 首页接口中获取 -const agentId = ref("1953462165250859010"); +/// agentId 首页接口中获取 1953462165250859010 +const agentId = ref("1"); /// 会话ID 历史数据接口中获取 const conversationId = ref(""); // 会话进行中标志 @@ -123,15 +123,39 @@ const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); // 当前会话的消息ID,用于保持发送和终止的messageId一致 let currentSessionMessageId: string | null = null; -// 滚动到底部 - 优化版本,确保打字机效果始终可见 -const scrollToBottom = () => { +// 滚动到底部 - 精确计算 last 元素位置并使用双 rAF 保证布局稳定 +const scrollToBottom = (smooth = false) => { nextTick(() => { - // 使用更大的值确保滚动到真正的底部 - scrollTop.value = 99999; - // 强制触发滚动更新,增加延迟确保DOM更新完成 - setTimeout(() => { - scrollTop.value = scrollTop.value + Math.random(); - }, 10); + const el = listRef.value; + if (!el) return; + + const doScroll = () => { + const last = el.lastElementChild as HTMLElement | null; + // 计算容器 style padding-bottom,保证滚动到真正可视底部 + const style = window.getComputedStyle(el); + const paddingBottom = parseFloat(style.paddingBottom || '0') || 0; + + if (last) { + const lastOffset = last.offsetTop + last.offsetHeight; + const target = lastOffset + paddingBottom - el.clientHeight; + const top = Math.max(0, Math.ceil(target)); + if (smooth && typeof el.scrollTo === 'function') { + el.scrollTo({ top, behavior: 'smooth' }); + } else { + el.scrollTop = top; + } + return; + } + + // 兜底:滚到底 + if (smooth && typeof el.scrollTo === 'function') { + el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' }); + } else { + el.scrollTop = el.scrollHeight; + } + }; + // 使用两次 requestAnimationFrame 增强在复杂渲染/打字机更新场景的可靠性 + requestAnimationFrame(() => requestAnimationFrame(doScroll)); }); }; @@ -388,6 +412,7 @@ const handleWebSocketMessage = (data: any) => { isSessionActive.value = false; // 清理当前会话的 messageId,避免保留陈旧 id resetMessageState(); + setTimeoutScrollToBottom(); } }; -- 2.43.7 From 34ad0ed8e36fa9a3bae749a8f7d87ce90cada686 Mon Sep 17 00:00:00 2001 From: zoujing Date: Wed, 21 Jan 2026 21:37:31 +0800 Subject: [PATCH 07/15] =?UTF-8?q?feat:=20=E5=8F=91=E9=80=81=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/views/home/ChatBox.vue | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/renderer/views/home/ChatBox.vue b/src/renderer/views/home/ChatBox.vue index 1338c7e..5d40f29 100644 --- a/src/renderer/views/home/ChatBox.vue +++ b/src/renderer/views/home/ChatBox.vue @@ -45,7 +45,7 @@ shadow-[0_1px_0_rgba(0,0,0,0.03)] p-[18px] mt-[8px] flex flex-col justify-between">