20260921-audit-r3-bugs.md 7.8 KB

第三轮审计整改 · B 批 bug 组(R3-8 / R3-9)

① 头部

对照网址 http://39.97.59.228:8013/hrx/mky-vent-base/compare/master...fix/audit-r3-bugs-20260921
依据文档 tools/verify/代码审核-第三轮-mky-vent-base-20260921.md(R3-8、R3-9)
分支 fix/audit-r3-bugs-20260921
基线 upstream/master = 4e311cb6(behind=0)
日期 2026-09-21(Asia/Shanghai)
状态 仅本地提交、未推送,待人工审核

② 提交清单

  • ce74a288 [Fix R3-8] 恢复 resetMicroContentWH 的 onTimeout 形参(修 4 调用方失配致遮罩永久卡死)
  • c046275a [Fix R3-9] 缩小重新生成去重删除范围(服务端时间戳基线,防误删历史同文案提问)
  • a54f990e [Docs] 第三轮审计 R3-B 批改动说明(docs/ai-changes)

③ 改动面

git diff --stat(基线 4e311cb6 → 本分支):

 src/utils/domUtils.ts                            | 12 +++++++++-
 .../components/AiAssistantModal.vue               | 26 +++++++++++++++++-----
 2 files changed, 32 insertions(+), 6 deletions(-)

另新增本说明目录:docs/ai-changes/README.md(本分支基线无该目录;规范要求仓库内补建)+ 本文件。

④ 逐项说明

R3-8【🟠 已采纳功能失效】resetMicroContentWH 形参被删但 4 个调用方未同步

  • 原来的行为:团队提交 7e9858ec 把签名从 (domId, callBack?, onTimeout?, maxWaitMs = 60000) 改为 (domId, callBack?, maxWaitMs = 60000) 并删掉了超时分支里的 onTimeout() 调用,但 4 个调用方(needAir.vueventDoc.vueventModal.vueventModal2D.vue)仍按旧签名传 3 个参数(第 3 个是错误态回调)→ 回调落进 maxWaitMsDate.now() - start >= maxWaitMs(number 与 function 比较)恒 false → 60s 超时兜底永不触发:子应用加载失败时遮罩永久转圈、loadFailed 永不置位(MicroLoadError 错误态与重试入口成死代码)、每秒一次 setTimeout 轮询永不停止。
  • 现在的行为src/utils/domUtils.ts:174 签名恢复为 (domId, callBack?: Function, onTimeout?: Function, maxWaitMs = 60000)(照我方原始实现 2eb75d33 [Fix SEC-20260913],顺序一致:超时分支先 onTimeout()callBack()),并新增加固:函数开头 if (typeof maxWaitMs !== 'number') maxWaitMs = 60000;
  • 为什么这么改:这是恢复 09-14 人工审核已采纳的"子应用加载超时错误态与重试"功能,不是新功能开发。调用方本来就是对的,本次只改被回滚的函数本体。
  • 与原来的差别:相对 4e311cb6(master 现状)是"恢复 + 加固"——多了一条类型防御,防止将来再出现"回调被塞进数值参数"这类失配导致兜底静默失效。
  • 4 个调用方未改(它们按旧签名传参本来就是对的)。

R3-9【🟠 数据丢失】"重新生成"的去重会删掉历史上所有同文案用户消息

  • 原来的行为removeDuplicateRegenerateUserMessage 只豁免"第一条"user 消息,凡内容同文案的历史提问("继续"、"总结一下"这类极常见)都会被 deleteMessage 静默删除。
  • 现在的行为:采用服务端时间戳基线方案(同一时钟域内比较)。handleRegenerate 在发起重发之前取一次 getDetail 服务端快照,取其中 created_at 的最大值 baselineMs 作为基线(快照无可解析时间戳则 NaN);去重过滤条件为"内容一致 + idx > 0 + id != null + created_at 可解析 + 严格大于 baselineMs"——只删本次重发产生的那一条重复用户消息,历史同文案消息全部保留。baselineMsNaN 时退化为"只删匹配项中最后一条"(本次重发产生的即最新一条),仍不删全部;created_at 缺失/不可解析的消息一律不删。
  • 为什么这么改:先查了 src/views/ventAI/manageAssistent/api.tsgetDetail'/ventAI/api/chat/history/' + session_id),消息对象含 created_at 字符串字段(本组件 958 行已用 dayjs(item.created_at) 解析展示时间,格式可靠)。基线取自服务端快照而非浏览器 Date.now():前后端时钟偏差(矿内网常见分钟级)下,若用浏览器时钟比较,服务器时钟超前时历史消息会被误判为"晚于重发"而真丢数据(第一次实现有此缺陷,本次收口修正)。基线与候选消息同属服务端 created_at 时钟域,偏差被消除。用严格大于(不用 >=)是因为基线那条本身可能就是上一次的同文案提问,且 created_at 若为秒级精度,同秒的新消息宁可漏删也不能误删。
  • 与原来的差别:删除范围从"所有同文案匹配项(除第一条)"收窄为"仅本次重发新产生的那条(或退化方案的仅最后一条)";created_at 缺失或无法解析的消息不删(宁留重复、不误删历史)。
  • 关键业务取舍:只动"重新生成"这一条去重逻辑,不改 handleEditResend、不改后端、不改其它重发路径。
  • 调用点同步:handleRegenerateremoveDuplicateRegenerateUserMessage(userInput)removeDuplicateRegenerateUserMessage(userInput, baselineMs)(全仓仅这一个调用点,已 grep 确认)。

⑤ 验收证据

  • 逻辑走查(R3-8):grep 确认 4 个调用点均传 3 个参数(domId、成功回调、错误态回调),与新签名 (domId, callBack?, onTimeout?, maxWaitMs?) 逐位对齐;超时分支执行顺序与原始实现 2eb75d33 一致(onTimeout() 在前、callBack() 在后)。
  • 逻辑走查(R3-9):模拟"历史上存在 2 条同文案提问 + 本次重发新增 1 条"场景,基线为重发前快照最大 created_at,过滤条件只放行严格大于基线的那条(同秒同值不会被误删);快照无时间戳时走退化分支只删最后一条匹配;created_at 缺失/非法(dayjs 解析出 Invalid Date → NaN)时拦截,不删除。
  • 未验证项:浏览器实测(子应用加载失败时遮罩转错误态、重试入口可点;"重新生成"后历史消息不丢)待父方在 192.168.1.88 上部署后验收;本机未跑构建(按任务要求)。

⑥ 静态检查

软链依赖 node_modules -> /root/VentAnaly60/mky-vent-base/node_modules(只读使用)。

  1. src/utils/domUtils.ts —— @babel/parser@7.29.7(.pnpm 嵌套路径,@babel/parser 未提升,任务书给的一行命令在本环境报 MODULE_NOT_FOUND,故用嵌套真实路径,解析器版本一致):

    OK src/utils/domUtils.ts
    
  2. AiAssistantModal.vue —— @vue/compiler-sfcparse + compileScript(script 块语法+类型检查通过):

    OK src/views/ventAI/manageAssistent/components/AiAssistantModal.vue
    
  3. 未跑 vite build / pnpm install(任务书明令禁止);无既有 lint 报错基线对比,本次两个文件解析均通过。

关键 hunk 见 git diff(③中 stat,④中说明)。

⑦ 已知取舍

  • R3-9 方案局限:① created_at 若为秒级精度,重发新消息与基线同秒时 > 不成立会漏删一条重复(宁留重复、不误删历史,属有意取舍);② 退化分支(服务端时间戳不可得时"只删最后一条匹配")依赖消息顺序,后端若提供可靠时间戳建议切回主方案。
  • R3-8 的浏览器实测、遮罩/错误态/重试验收:待父方部署到 88 后验证。
  • 本轮只做 R3-8、R3-9,未做顺手重构;第三轮审计的其余条目不在本分支。

⑧ 交付状态

  • 仅本地提交,未推送、未部署;推送与合并由父方/用户决定。
  • 基线:upstream/master = 4e311cb6(behind=0,开工时已确认)。