Pārlūkot izejas kodu

[Fix R4-R4-8] 合并冲突取值更正:useChatScroll 卸载取消 rAF 取审计分支版本

按「AI 助手相关代码冲突以审计分支为主」的原则,R4-8 处由上游的
`if (scrollRafId)`(destroyOnClose 语义)改回审计分支的
`if (scrollRafId !== null)` + R4-8 注释(两者行为等价,rAF id 非 0)。
交付说明 §⑨ 同步补记取值原则与冲突表。

核对:10 个审计改动文件的 `审计-第四轮` 标记计数与审计分支一致(无审计逻辑被上游覆盖)。
wangkeyi 2 nedēļas atpakaļ
vecāks
revīzija
50f1b66141

+ 5 - 1
docs/ai-changes/20260929-audit-r4.md

@@ -160,13 +160,17 @@ less.render(index.less, modifyVars 打桩)  # 输出无 modal-close-x、保留 f
 `6de78411` API 按域拆分重构、`5f41a3be` dxf 支持、`64cfbb1a` 文件预览修复)。本次将 `origin/master` 合入分支,
 逐项核对「审计修改在新结构上是否仍然成立」。
 
+**取值原则**:AI 助手相关代码冲突时**以审计分支为主**(M1/M2/M3/R4-* 的审计语义一律保留);
+上游若已删除/重构掉载体文件,则把审计逻辑**平移**到新结构(见下表 `api/client.ts` 一行),不改审计行为。
+核对方式:对每个审计改动文件比对 `git grep -c "审计-第四轮"` 在审计分支与合并结果上的计数,10 个文件全部一致。
+
 ### 冲突解决(3 处)
 
 | 文件 | 冲突 | 解决 |
 |---|---|---|
 | `api/client.ts` | 上游删除(拆分成 `api/*.ts`)vs 本分支修改(M2 加 export + M3 `getMe`) | 接受删除。M2 的「加 export」在新结构中**天然满足**(`throwStreamHttpError`/`StreamError` 已是 `api/errors.ts` 的导出);M3 的 `MeInfo`/`getMe()` 迁到新建 `api/user.ts`(按 barrel 约定 `export * from './user'`) |
 | `components/AiAssistantModal.vue` | 双方改同一 import 行 | 取上游的 barrel 路径并补 `getMe`:`import { …, StreamError, getMe } from '.../api'` |
-| `hooks/useChatScroll.ts` | 双方各加了 `onBeforeUnmount` 取消 rAF(R4-8 与上游重构撞车) | R4-8 上游已有等价实现,**取上游版本**(`if (scrollRafId)` 与 `!== null` 等价,rAF id 非 0) |
+| `hooks/useChatScroll.ts` | 双方各加了 `onBeforeUnmount` 取消 rAF(R4-8 与上游重构撞车) | 两边等价(上游为 destroyOnClose 语义,本分支为 R4-8),按**冲突以审计分支为主**取审计版本(`if (scrollRafId !== null)` + R4-8 注释) |
 
 ### 其他适配(非冲突但必须改)
 

+ 8 - 3
src/views/ventAI/manageAssistent/hooks/useChatScroll.ts

@@ -30,10 +30,15 @@ export const useChatScroll = (getChatMessages: () => InstanceType<typeof ChatMes
     }
   };
 
-  // 弹框是 destroyOnClose,卸载时可能正压着一帧待执行的滚动:显式取消,避免在已销毁的组件上跑 nextTick
-  // [审计-第四轮 R4-8] 与审计分支同源修复:卸载时取消挂起 rAF(上游重构已自带,取上游实现)
+  // [审计-第四轮 R4-8] 卸载时取消挂起的 rAF。
+  // 原行为:scrollRafId 仅在重入时 cancel 自身,组件卸载后不 cancel,残留回调会在卸载后
+  //         再执行一次(内部全 optional chaining,无崩溃、无累积,但无意义)。
+  // 现行为:onBeforeUnmount 里若有挂起 rAF 则 cancel 并复位。
+  // 为什么:定时器/动画帧挂摘对称,消除卸载后的空转回调。
+  // 注:本 composable 仅在组件 setup 内调用(AiAssistantModal),onBeforeUnmount 注册到该组件上。
+  //     上游重构(master)在同一位置也加了等价实现(destroyOnClose 语义),此处按「冲突以审计分支为主」取审计版本。
   onBeforeUnmount(() => {
-    if (scrollRafId) {
+    if (scrollRafId !== null) {
       cancelAnimationFrame(scrollRafId);
       scrollRafId = null;
     }