From ac240892dde468ea556786d0ad9ca082ffb72bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=98=B1=E8=BE=BE?= Date: Wed, 18 Jun 2025 17:48:52 +0800 Subject: [PATCH] =?UTF-8?q?refactor(AI):=20=E4=BC=98=E5=8C=96=E6=89=93?= =?UTF-8?q?=E5=AD=97=E6=9C=BA=E6=95=88=E6=9E=9C=E5=92=8C=E6=B5=81=E5=BC=8F?= =?UTF-8?q?=E5=9B=9E=E7=AD=94=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整打字速度为 30 毫秒/字 - 修复流式回答中思考状态的判断逻辑 - 优化打字机效果,支持整块文本的逐字输出 - 调整代码结构,提高可读性和可维护性 --- src/views/AI/components/chat.vue | 52 +++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/views/AI/components/chat.vue b/src/views/AI/components/chat.vue index fed0555..2eb54e6 100644 --- a/src/views/AI/components/chat.vue +++ b/src/views/AI/components/chat.vue @@ -106,8 +106,9 @@ export default { // 打字机相关 typingText: '', typingQueue: [], + typingQueueText: [], isTyping: false, - typingSpeed: 50, + typingSpeed: 30, typingTimeout: null, } }, @@ -269,8 +270,8 @@ export default { if (data.answer) { this.answerMap += data.answer } - this.updateConversationState(data) - return data + + return this.updateConversationState(data) } catch (error) { console.error('流数据解析失败:', error) return null @@ -279,27 +280,42 @@ export default { updateConversationState(data) { this.$emit('update:conversationId', data.conversation_id || '') if (data.answer && data.answer.indexOf('') !== -1) { + data.isThink = true this.isThink = true this.$emit('getIsThink', true) } if (data.answer && data.answer.indexOf('') !== -1) { + data.isThink = true this.isThink = false this.$emit('getIsThink', false) } + if (data.answer && this.isThink) { + data.isThink = true + } + if (data.answer && !this.isThink) { + data.isThink = false + } + + return data }, - updateMessageContent({ answer, event }) { + updateMessageContent(parse) { + let { event, answer, isThink } = parse if (event === 'message_end') { this.$emit('update:messageStatus', 'stop') } if (!this.currentMessage || !answer) return - const mode = this.isThink ? 'think' : 'text' - const chars = answer.split('') - this.typingQueue.push(...chars) + const mode = isThink ? 'think' : 'text' + const chars = { + answer: answer, + isThink: isThink, + } + + this.typingQueue.push(chars) if (!this.isTyping) { this.startTypingAnimation(mode) } }, - startTypingAnimation(mode) { + startTypingAnimation() { this.isTyping = true const typeNextChar = () => { @@ -308,10 +324,24 @@ export default { return } - const char = this.typingQueue.shift() - this.currentMessage[mode] += char + // 取出一个完整文本块 + const chunk = this.typingQueue.shift() + const chars = chunk.answer.split('') + const isThink = chunk.isThink + // 内部递归函数,用于逐字输出当前块 + const outputChar = () => { + if (chars.length === 0) { + // 当前块输出完毕,继续处理下一个 + setTimeout(typeNextChar, 10) + return + } + const char = chars.shift() + this.currentMessage[isThink ? 'think' : 'text'] += char + const delay = this.getTypingDelay(char) + setTimeout(outputChar, delay) + } - this.typingTimeout = setTimeout(typeNextChar, this.getTypingDelay(char)) + outputChar() } typeNextChar()