fix: 修复页面刷新时思考块自动展开的问题

- 在历史加载时给思考块设置 collapsed: true 默认折叠
- 在任务恢复时跳过思考块的展开/折叠动画
- 延迟清除 _rebuildingFromScratch 标记,确保所有历史事件处理完毕
- 删除过早清除重建标记的逻辑,避免后续思考块被展开

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
JOJO 2026-03-09 16:31:00 +08:00
parent d71525a3c6
commit cd68812743
2 changed files with 114 additions and 107 deletions

View File

@ -194,6 +194,7 @@ export const historyMethods = {
type: 'thinking',
content: reasoningText,
streaming: false,
collapsed: true,
timestamp: Date.now(),
blockId
});

View File

@ -104,12 +104,8 @@ export const taskPollingMethods = {
debugLog(`[TaskPolling] 未知事件类型: ${eventType}`);
}
// 如果正在从头重建,检查是否已经处理到当前事件
// 当处理到工具相关事件时,说明思考已经结束,可以清除重建标记
if (this._rebuildingFromScratch && (eventType === 'tool_preparing' || eventType === 'tool_start')) {
debugLog('[TaskPolling] 检测到工具事件,清除重建标记');
this._rebuildingFromScratch = false;
}
// 注意:不要在这里清除 _rebuildingFromScratch 标记
// 该标记应该在恢复完所有历史事件后才清除
},
handleAiMessageStart(data: any, eventIdx: number) {
@ -160,42 +156,48 @@ export const taskPollingMethods = {
this.monitorShowThinking();
// 获取当前 actions 数量,用于调试
const lastMessage = this.messages[this.messages.length - 1];
const beforeCount = lastMessage?.actions?.length || 0;
console.log('[TaskPolling] 添加思考块前actions 数量:', beforeCount);
console.log('[TaskPolling] 当前 currentMessageIndex:', this.currentMessageIndex);
console.log('[TaskPolling] messages 总数:', this.messages.length);
console.log('[TaskPolling] 最后一条消息 role:', lastMessage?.role);
// 获取当前 actions 数量,用于调试(已禁用)
// const lastMessage = this.messages[this.messages.length - 1];
// const beforeCount = lastMessage?.actions?.length || 0;
// console.log('[TaskPolling] 添加思考块前actions 数量:', beforeCount);
// console.log('[TaskPolling] 当前 currentMessageIndex:', this.currentMessageIndex);
// console.log('[TaskPolling] messages 总数:', this.messages.length);
// console.log('[TaskPolling] 最后一条消息 role:', lastMessage?.role);
const result = this.chatStartThinkingAction();
console.log('[TaskPolling] chatStartThinkingAction 返回:', result);
// console.log('[TaskPolling] chatStartThinkingAction 返回:', result);
if (result && result.blockId) {
const blockId = result.blockId;
// 检查新添加的 action
const afterCount = lastMessage?.actions?.length || 0;
console.log('[TaskPolling] 添加思考块后actions 数量:', afterCount);
// 检查新添加的 action(已禁用)
// const afterCount = lastMessage?.actions?.length || 0;
// console.log('[TaskPolling] 添加思考块后actions 数量:', afterCount);
// 检查 currentMessageIndex 指向的消息
const currentMsg = this.messages[this.currentMessageIndex];
if (currentMsg) {
console.log('[TaskPolling] currentMessageIndex 指向的消息 actions 数量:', currentMsg.actions?.length || 0);
}
// 检查 currentMessageIndex 指向的消息(已禁用)
// const currentMsg = this.messages[this.currentMessageIndex];
// if (currentMsg) {
// console.log('[TaskPolling] currentMessageIndex 指向的消息 actions 数量:', currentMsg.actions?.length || 0);
// }
if (afterCount > beforeCount) {
const newAction = lastMessage.actions[afterCount - 1];
console.log('[TaskPolling] 新添加的思考块:', {
type: newAction.type,
blockId: newAction.blockId,
hasId: !!newAction.id,
timestamp: newAction.timestamp
});
}
// if (afterCount > beforeCount) {
// const newAction = lastMessage.actions[afterCount - 1];
// console.log('[TaskPolling] 新添加的思考块:', {
// type: newAction.type,
// blockId: newAction.blockId,
// hasId: !!newAction.id,
// timestamp: newAction.timestamp
// });
// }
const lastMessage = this.messages[this.messages.length - 1];
// 只在非历史恢复时展开思考块
if (!this._rebuildingFromScratch) {
this.chatExpandBlock(blockId);
}
this.scrollToBottom();
this.chatSetThinkingLock(blockId, true);
@ -235,11 +237,17 @@ export const taskPollingMethods = {
// 解锁思考块
this.chatSetThinkingLock(blockId, false);
// 只在非历史恢复时延迟折叠思考块
if (!this._rebuildingFromScratch) {
// 延迟折叠思考块(给用户一点时间看到思考完成)
setTimeout(() => {
this.chatCollapseBlock(blockId);
this.$forceUpdate();
}, 1000);
} else {
// 历史恢复时立即折叠,不需要动画
this.chatCollapseBlock(blockId);
}
this.$nextTick(() => this.scrollThinkingToBottom(blockId));
}
@ -641,12 +649,12 @@ export const taskPollingMethods = {
const lastMessage = this.messages[this.messages.length - 1];
const isAssistantMessage = lastMessage && lastMessage.role === 'assistant';
console.log('[TaskPolling] 最后一条消息:', {
exists: !!lastMessage,
role: lastMessage?.role,
actionsCount: lastMessage?.actions?.length || 0,
isAssistant: isAssistantMessage
});
// console.log('[TaskPolling] 最后一条消息:', {
// exists: !!lastMessage,
// role: lastMessage?.role,
// actionsCount: lastMessage?.actions?.length || 0,
// isAssistant: isAssistantMessage
// });
// 检查是否需要从头重建
// 1. 最后一条不是 assistant 消息
@ -661,13 +669,13 @@ export const taskPollingMethods = {
historyIncomplete;
if (needsRebuild) {
if (historyIncomplete) {
console.log('[TaskPolling] 历史不完整,从头重建:', {
historyActionsCount,
eventCount,
diff: eventCount - historyActionsCount
});
}
// if (historyIncomplete) {
// console.log('[TaskPolling] 历史不完整,从头重建:', {
// historyActionsCount,
// eventCount,
// diff: eventCount - historyActionsCount
// });
// }
debugLog('[TaskPolling] 需要从头重建 assistant 响应');
// 清空所有消息,准备从头重建
@ -687,6 +695,7 @@ export const taskPollingMethods = {
// 标记正在从头重建,用于后续处理
this._rebuildingFromScratch = true;
this._rebuildingEventCount = allEvents.length; // 记录当前事件总数
(window as any).__taskEventHandler = (event: any) => {
this.handleTaskEvent(event);
@ -695,6 +704,14 @@ export const taskPollingMethods = {
taskStore.startPolling((event: any) => {
this.handleTaskEvent(event);
});
// 延迟清除重建标记,确保所有历史事件都处理完毕
setTimeout(() => {
debugLog('[TaskPolling] 历史事件处理完毕,清除重建标记');
this._rebuildingFromScratch = false;
this._rebuildingEventCount = 0;
}, 2000);
return;
}
@ -718,95 +735,84 @@ export const taskPollingMethods = {
}
}
console.log('[TaskPolling] 分析结果:', {
inThinking,
inText,
totalEvents: allEvents.length,
lastEventType: allEvents[allEvents.length - 1]?.type,
lastEventIdx: allEvents[allEvents.length - 1]?.idx
});
// console.log('[TaskPolling] 分析结果:', {
// inThinking,
// inText,
// totalEvents: allEvents.length,
// lastEventType: allEvents[allEvents.length - 1]?.type,
// lastEventIdx: allEvents[allEvents.length - 1]?.idx
// });
// 恢复思考块状态
if (lastMessage.actions) {
console.log('[TaskPolling] 历史中的 actions 详情:', lastMessage.actions.map((a, idx) => ({
index: idx,
type: a.type,
id: a.id,
hasContent: !!a.content,
contentLength: a.content?.length || 0,
toolName: a.tool?.name,
hasBlockId: !!a.blockId,
blockId: a.blockId,
collapsed: a.collapsed,
streaming: a.streaming
})));
// console.log('[TaskPolling] 历史中的 actions 详情:', lastMessage.actions.map((a, idx) => ({
// index: idx,
// type: a.type,
// id: a.id,
// hasContent: !!a.content,
// contentLength: a.content?.length || 0,
// toolName: a.tool?.name,
// hasBlockId: !!a.blockId,
// blockId: a.blockId,
// collapsed: a.collapsed,
// streaming: a.streaming
// })));
const thinkingActions = lastMessage.actions.filter(a => a.type === 'thinking');
console.log('[TaskPolling] 思考块数量:', thinkingActions.length);
// console.log('[TaskPolling] 思考块数量:', thinkingActions.length);
if (inThinking && thinkingActions.length > 0) {
// 正在思考中,检查最后一个思考块是否正在流式输出
const lastThinking = thinkingActions[thinkingActions.length - 1];
// 只有当思考块正在流式输出时才展开
// 只有当思考块正在流式输出时才设置锁定状态(但不展开
if (lastThinking.streaming && lastThinking.blockId) {
console.log('[TaskPolling] 找到正在流式输出的思考块,展开:', lastThinking.blockId);
lastThinking.collapsed = false;
// console.log('[TaskPolling] 找到正在流式输出的思考块,设置锁定状态:', lastThinking.blockId);
this.$nextTick(() => {
this.chatExpandBlock(lastThinking.blockId);
this.chatSetThinkingLock(lastThinking.blockId, true);
});
} else {
console.log('[TaskPolling] 没有找到正在流式输出的思考块,不展开');
// 折叠所有思考块
for (const thinking of thinkingActions) {
if (thinking.blockId) {
thinking.collapsed = true;
}
}
}
} else {
// 不在思考中,折叠所有思考块
console.log('[TaskPolling] 不在思考中,折叠所有思考块');
for (const thinking of thinkingActions) {
if (thinking.blockId) {
thinking.collapsed = true;
}
}
}
// 检查思考块状态(在设置之后)
thinkingActions.forEach((thinking, idx) => {
console.log(`[TaskPolling] 思考块 ${idx} (设置后):`, {
hasBlockId: !!thinking.blockId,
blockId: thinking.blockId,
collapsed: thinking.collapsed,
contentLength: thinking.content?.length || 0
});
});
// 确保所有思考块都是折叠状态
for (const thinking of thinkingActions) {
if (thinking.blockId) {
thinking.collapsed = true;
}
}
// 检查思考块状态(在设置之后)(已禁用)
// thinkingActions.forEach((thinking, idx) => {
// console.log(`[TaskPolling] 思考块 ${idx} (设置后):`, {
// hasBlockId: !!thinking.blockId,
// blockId: thinking.blockId,
// collapsed: thinking.collapsed,
// contentLength: thinking.content?.length || 0
// });
// });
// 恢复文本块状态
const textActions = lastMessage.actions.filter(a => a.type === 'text');
console.log('[TaskPolling] 文本块数量:', textActions.length);
// console.log('[TaskPolling] 文本块数量:', textActions.length);
if (inText && textActions.length > 0) {
const lastText = textActions[textActions.length - 1];
console.log('[TaskPolling] 标记文本块为流式状态');
// console.log('[TaskPolling] 标记文本块为流式状态');
lastText.streaming = true;
}
// 注册历史中的工具块到 toolActionIndex
// 这样后续的 update_action 事件可以找到对应的块进行状态更新
const toolActions = lastMessage.actions.filter(a => a.type === 'tool');
console.log('[TaskPolling] 工具块数量:', toolActions.length);
// console.log('[TaskPolling] 工具块数量:', toolActions.length);
for (const toolAction of toolActions) {
if (toolAction.tool && toolAction.tool.id) {
console.log('[TaskPolling] 注册工具块:', {
id: toolAction.tool.id,
name: toolAction.tool.name,
status: toolAction.tool.status
});
// console.log('[TaskPolling] 注册工具块:', {
// id: toolAction.tool.id,
// name: toolAction.tool.name,
// status: toolAction.tool.status
// });
// 注册到 toolActionIndex
this.toolRegisterAction(toolAction, toolAction.tool.id);
// 如果有 executionId也注册
@ -830,7 +836,7 @@ export const taskPollingMethods = {
const lastMessageIndex = this.messages.length - 1;
if (lastMessage && lastMessage.role === 'assistant') {
this.currentMessageIndex = lastMessageIndex;
console.log('[TaskPolling] 设置 currentMessageIndex 为:', lastMessageIndex);
// console.log('[TaskPolling] 设置 currentMessageIndex 为:', lastMessageIndex);
}
// 强制更新界面