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