fix(frontend): 修复对话压缩后页面抽搐、重复显示与滚动重置
三管齐下,消除 in-place 压缩触发的多余重载: 1. handleTaskEvent: _rebuildingFromScratch 重放时跳过 compression_finished/compression_state/shallow_compression, 打破 restoreTaskState 重放 → 再次触发压缩完成的无限循环。 2. handleCompressionFinished + compressConversation: in-place 压缩(对话 id 不变)跳过 loadConversation + restoreTaskState + loadConversationsList, 避免 resetAllStates 重置滚动状态和清空消息列表。 3. useLegacySocket conversation_loaded: 同对话 clear_ui 跳过 resetAllStates + fetchAndDisplayHistory, 避免后端 Socket.IO 推送触发二次重置。
This commit is contained in:
parent
66261e91c6
commit
0d4f6c9e56
@ -1073,9 +1073,11 @@ export const messageMethods = {
|
||||
|
||||
if (response.ok && result.success) {
|
||||
this.compressionStage = 'switching';
|
||||
// in-place 压缩:对话 id 不变,重新加载以刷新“已压缩历史”展示。
|
||||
const newId = result.compressed_conversation_id;
|
||||
if (newId) {
|
||||
const isInPlace = newId && newId === this.currentConversationId;
|
||||
// in-place 压缩:对话 id 不变,不重新加载(避免 resetAllStates
|
||||
// 重置滚动状态 + fetchAndDisplayHistory 清空重渲染导致闪烁和锁死)。
|
||||
if (newId && !isInPlace) {
|
||||
await this.loadConversation(newId, { force: true });
|
||||
}
|
||||
const guideMessage = (result.guide_message || '').trim();
|
||||
@ -1099,15 +1101,16 @@ export const messageMethods = {
|
||||
}
|
||||
} else if (compressBehavior === 'wait') {
|
||||
// 等待用户:后端已把引导语作为 user 消息追加进历史,这里仅刷新展示,不触发请求。
|
||||
if (newId) {
|
||||
if (newId && !isInPlace) {
|
||||
await this.loadConversation(newId, { force: true });
|
||||
}
|
||||
} else if (guideMessage) {
|
||||
await this.sendAutoUserMessage(guideMessage);
|
||||
}
|
||||
|
||||
this.conversationsOffset = 0;
|
||||
await this.loadConversationsList();
|
||||
if (!isInPlace) {
|
||||
await this.loadConversationsList();
|
||||
}
|
||||
|
||||
debugLog('对话压缩完成:', result);
|
||||
this.uiPushToast({
|
||||
|
||||
@ -756,12 +756,18 @@ export const taskPollingMethods = {
|
||||
this.handleConversationResolved(eventData, eventIdx);
|
||||
break;
|
||||
case 'compression_state':
|
||||
// 重放历史事件时不处理管理类事件,避免触发副作用(如 toast 闪烁 / 状态回退)。
|
||||
if (this._rebuildingFromScratch) break;
|
||||
this.handleCompressionState(eventData, eventIdx);
|
||||
break;
|
||||
case 'compression_finished':
|
||||
// 重放历史事件时不处理管理类事件,避免 restoreTaskState → 重放 → 再次触发 compression_finished 的无限循环。
|
||||
if (this._rebuildingFromScratch) break;
|
||||
this.handleCompressionFinished(eventData, eventIdx);
|
||||
break;
|
||||
case 'shallow_compression':
|
||||
// 同上。
|
||||
if (this._rebuildingFromScratch) break;
|
||||
this.handleShallowCompression(eventData, eventIdx);
|
||||
break;
|
||||
|
||||
@ -2431,19 +2437,21 @@ export const taskPollingMethods = {
|
||||
this.compressionMode = '';
|
||||
this.compressionStage = '';
|
||||
this.compressionError = '';
|
||||
// in-place 压缩:对话 id 不变。重新加载该对话以刷新“已压缩历史”的展示;
|
||||
// 若返回的 id 与当前不一致(兼容旧行为)也按其加载。
|
||||
const newId = data?.conversation_id;
|
||||
if (newId) {
|
||||
const isInPlace = newId && newId === this.currentConversationId;
|
||||
if (newId && !isInPlace) {
|
||||
// 旧行为兼容:压缩产生了新对话 id(非 in-place),需要切换并重新加载。
|
||||
await this.loadConversation(newId, { force: true });
|
||||
this.conversationsOffset = 0;
|
||||
if (typeof this.loadConversationsList === 'function') {
|
||||
await this.loadConversationsList();
|
||||
}
|
||||
await this.refreshRunningWorkspaceTasks?.();
|
||||
await this.restoreTaskState?.();
|
||||
}
|
||||
this.conversationsOffset = 0;
|
||||
if (typeof this.loadConversationsList === 'function') {
|
||||
await this.loadConversationsList();
|
||||
}
|
||||
await this.refreshRunningWorkspaceTasks?.();
|
||||
// 续接任务仍在同一对话内运行,恢复轮询以持续显示进度。
|
||||
await this.restoreTaskState?.();
|
||||
// in-place 压缩:对话 id 不变,不重新加载对话,也不触发 restoreTaskState。
|
||||
// loadConversation 会 clearTask 停止轮询才需要 restore;in-place 跳过了
|
||||
// loadConversation,轮询仍在运行,restoreTaskState 的 rebuild 反而会
|
||||
this.uiPushToast({
|
||||
title: '压缩完成',
|
||||
message: '已压缩较早的对话内容',
|
||||
|
||||
@ -841,6 +841,10 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
|
||||
if (!forceReload && (historyLoadingSame || historyReady)) {
|
||||
socketLog('conversation_loaded: 历史已加载/加载中,跳过重复刷新');
|
||||
} else if (data.clear_ui && targetConversationId === ctx.currentConversationId) {
|
||||
// in-place 压缩等同一对话内的刷新:不 resetAllStates(避免重置滚动状态
|
||||
// 导致锁死),不重新 fetchAndDisplayHistory(避免消息闪烁)。
|
||||
socketLog('conversation_loaded: 同对话 clear_ui,跳过重置以保持滚动状态');
|
||||
} else {
|
||||
if (data.clear_ui) {
|
||||
// 清理当前UI状态,准备显示历史内容
|
||||
|
||||
Loading…
Reference in New Issue
Block a user