From 2d411de7d8d0b668129e08043efa95cd3648643d Mon Sep 17 00:00:00 2001 From: ingkele <598792849@qq.com> Date: Mon, 19 Oct 2026 19:31:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=A7=AF=E5=88=86?= =?UTF-8?q?=E4=B8=8D=E8=B6=B3=E6=97=B6=E5=8E=BB=E5=85=85=E5=80=BC=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=B7=B3=E8=BD=AC=EF=BC=8C=E4=BF=AE=E6=AD=A3=20AI=20?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E5=9B=9E=E5=A4=8D=E9=87=8D=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/contract/index.vue | 13 ++++++- .../router/service/client/ai/pub/chat.js | 36 +++++++++++++++++-- .../service/client/ai/pub/jjxDoReview.js | 7 +++- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/pages/contract/index.vue b/pages/contract/index.vue index 138f6f8..f913c79 100644 --- a/pages/contract/index.vue +++ b/pages/contract/index.vue @@ -560,7 +560,7 @@
⚠️ 积分不足,当前余额 {{ pointsBalance }},需要 {{ reviewPoints }} 积分且审查后余额需保留至少 200 积分。 - 去充值 + 去充值
@@ -1712,6 +1712,17 @@ return html; }, // ===== 积分相关 ===== + // 积分不足时跳转到「积分管理」并刷新余额与明细 + goRecharge() { + this.menuIndex = '6'; + this.isSign = false; + this.isSignIntro = false; + this.isSignLog = false; + this.isSignFlow = false; + this.isSignTips = false; + this.getPointsBalance(); + this.getPointsLog(); + }, async getPointsBalance() { try { const res = await vk.callFunction({ diff --git a/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/chat.js b/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/chat.js index c43baba..23c0e5e 100644 --- a/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/chat.js +++ b/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/chat.js @@ -25,22 +25,52 @@ module.exports = { } }); - let answer = ''; + // 扣子 v3 流式事件说明: + // conversation.message.delta —— 增量片段(应当拼接) + // conversation.message.completed —— 该条消息的「完整内容」(不能再次拼接,否则重复) + // 因此必须按事件类型区分,只累加 delta;completed 仅用于兜底。 let conversationId = ''; + const msgMap = new Map(); // messageId -> { text } + let curEvent = ''; const text = res.data || ''; const lines = text.split('\n'); for (const line of lines) { + if (line.startsWith('event:')) { + curEvent = line.slice(6).trim(); + continue; + } if (!line.startsWith('data:')) continue; const d = line.slice(5).trim(); if (d === '[DONE]' || d === '"[DONE]"') continue; try { const p = JSON.parse(d); if (p.conversation_id) conversationId = p.conversation_id; - if (p.type === 'answer' && p.content) { - answer += p.content; // 拼接,不是覆盖 + // 只取正文,忽略 verbose(工具调用日志)等其他类型 + if (p.type !== 'answer' || typeof p.content !== 'string') continue; + const key = p.id || '__default__'; + const rec = msgMap.get(key) || { text: '' }; + + if (curEvent === 'conversation.message.delta') { + // 防御:万一上游发的是累计内容而非增量,用长度+前缀判断避免重复 + if (p.content.length > rec.text.length && p.content.indexOf(rec.text) === 0) { + rec.text = p.content; + } else { + rec.text += p.content; + } + msgMap.set(key, rec); + } else if (curEvent === 'conversation.message.completed') { + // 已有 delta 拼出的内容就丢掉 completed,避免重复;没有则用它兜底 + if (!rec.text && p.content) { + rec.text = p.content; + msgMap.set(key, rec); + } } } catch (e) { /* 跳过 */ } } + + // 按消息首次出现顺序拼接(多段消息之间自带换行,直接相连) + let answer = ''; + for (const rec of msgMap.values()) answer += rec.text; if (!answer) answer = '暂时无法回复,请拨打 400-686-5559 咨询'; return { diff --git a/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/jjxDoReview.js b/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/jjxDoReview.js index 86b3b98..c1c27f7 100644 --- a/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/jjxDoReview.js +++ b/uniCloud-tcb/cloudfunctions/router/service/client/ai/pub/jjxDoReview.js @@ -73,8 +73,13 @@ module.exports = { if (p.conversation_id) conversationId = p.conversation_id; // 处理回答内容 + // 注意:conversation.message.completed 携带的是该条消息的完整内容, + // 若前面已经通过 delta 拼过,再拼一次就会重复,这里做去重 if (p.type === 'answer' && p.content) { - answer += p.content; + const isDup = eventName === 'conversation.message.completed' && answer.indexOf(p.content) >= 0; + if (!isDup) { + answer += p.content; + } // 每积累 200 字更新一次数据库(前端轮询能看到进度) if (answer.length - lastUpdateLen >= 200) {