fix: 工具页签滚动彻底重写

- 统一 scrollToolsToBottom:scrollTop=scrollHeight + 双重rAF
- appendToolCardDOM/updateToolCardDOM/renderToolCalls 全部调用
- 废弃 scrollIntoView(overflow-y:auto 容器中不稳定)
- 卡片更新后也跟随滚动(结果内容可能导致高度变化)
This commit is contained in:
thzxx
2026-06-13 09:24:21 +08:00
parent 41ee21ccb3
commit ad5b67ea3e
+14 -10
View File
@@ -836,11 +836,9 @@ function appendToolCardDOM(tc: ToolCallRecord): void {
if (card) {
card.dataset.toolName = tc.name;
container.appendChild(card);
// 等浏览器完成布局后再滚到底部
requestAnimationFrame(() => {
container.lastElementChild?.scrollIntoView({ block: 'end' });
});
}
// 始终滚到底部
scrollToolsToBottom(container);
}
/** 增量更新工具卡片 DOM 节点(找到 pending/running 状态的卡片并替换) */
@@ -861,6 +859,8 @@ function updateToolCardDOM(tc: ToolCallRecord): void {
if (newCard) {
newCard.dataset.toolName = tc.name;
runningCard.replaceWith(newCard);
// 卡片内容变化后可能变高(如出现执行结果),跟随滚动
scrollToolsToBottom(container);
}
} else {
// running 卡片不在 DOM 中(可能是 tab 切换后再切回或其他边缘情况)
@@ -869,6 +869,15 @@ function updateToolCardDOM(tc: ToolCallRecord): void {
}
}
/** 工具页签滚动到底部(双重 rAF 保证布局完成) */
function scrollToolsToBottom(container: HTMLElement): void {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
container.scrollTop = container.scrollHeight;
});
});
}
/** CSS.escape 回退(兼容旧 Electron */
function escapeAttr(value: string): string {
try { return CSS.escape(value); } catch { return value.replace(/["\\]/g, '\\$&'); }
@@ -943,12 +952,7 @@ function renderToolCalls(): void {
html += renderToolCard(tc);
}
container.innerHTML = html;
// 全量重建后等两帧让布局稳定,再滚到底部
requestAnimationFrame(() => {
requestAnimationFrame(() => {
container.lastElementChild?.scrollIntoView({ block: 'end' });
});
});
scrollToolsToBottom(container);
}
function getToolDisplayName(name: string): string {