diff --git a/src/components/ToolCardList.vue b/src/components/ToolCardList.vue index b4d0786..eff3710 100644 --- a/src/components/ToolCardList.vue +++ b/src/components/ToolCardList.vue @@ -313,9 +313,11 @@ let _unlistenPending: UnlistenFn | null = null let _disposed = false onMounted(async () => { const fn = await listen('ai-pending-arrived', () => { - // nextTick 等 pending_approval 类挂到 DOM 后再查(scrollToFirstPending 查 .ai-tool-card--pending_approval)。 - // 多个 ToolCardList 实例(每条 AI 消息一个)各自 listen,querySelector 只命中自身 root 内的 - // pending 卡,非含 pending 卡的实例查 null no-op,天然过滤不串扰。 + // BUG-260624-01 残留优化:本实例无 pending 卡时短路返回,避免大列表 N 个 ToolCardList 实例 + // 每次广播都跑 querySelector(N 实例 × M 次 emit = N×M 次 DOM 查询)。原靠 scrollToFirstPending + // 内 querySelector 返 null no-op 天然过滤(功能正确),此处显式 props 过滤把无 pending 实例挡在 + // 进入函数前。含 pending 的实例再走 nextTick + scrollToFirstPending(展开折叠组 + scroll)。 + if (!props.toolCalls.some(tc => tc.status === 'pending_approval')) return nextTick(() => scrollToFirstPending()) }) // 解析时若已卸载(HMR/极速 mount/unmount),立即 unlisten 刚拿到的句柄,防孤儿监听器。 diff --git a/src/components/ai/MessageList.vue b/src/components/ai/MessageList.vue index 21fa13f..de2dfb5 100644 --- a/src/components/ai/MessageList.vue +++ b/src/components/ai/MessageList.vue @@ -503,10 +503,12 @@ function collapseAllToolLists(active: Set): void { function scrollToFirstPending(): void { const tcl = toolCardListRef.value as unknown const refs = Array.isArray(tcl) ? tcl : (tcl ? [tcl] : []) + // BUG-260624-01 残留修复:遍历所有实例调 scrollToFirstPending,各实例内部 querySelector 无 + // pending 卡则 no-op,含 pending 的实例滚到其首张待审批卡。原 `return` 首个有方法的实例即停, + // pending 若落在后续实例(头部徽标点击场景)滚不到。移除 return 让所有实例尝试,no-op 实例零成本。 for (const r of refs) { if (typeof (r as any)?.scrollToFirstPending === 'function') { ;(r as any).scrollToFirstPending() - return } } }