fix: prevent duplicate history animation
This commit is contained in:
parent
4262922694
commit
8de3b5d24a
@ -130,6 +130,8 @@ const appOptions = {
|
||||
toolStacks: new Map(),
|
||||
// 当前任务是否仍在进行中(用于保持输入区的“停止”状态)
|
||||
taskInProgress: false,
|
||||
// 记录上一次成功加载历史的对话ID,防止初始化阶段重复加载导致动画播放两次
|
||||
lastHistoryLoadedConversationId: null,
|
||||
|
||||
// ==========================================
|
||||
// 对话管理相关状态
|
||||
@ -1132,6 +1134,9 @@ const appOptions = {
|
||||
this.ensureScrollListener();
|
||||
});
|
||||
|
||||
// 重置已加载对话标记,便于后续重新加载新对话历史
|
||||
this.lastHistoryLoadedConversationId = null;
|
||||
|
||||
this.logMessageState('resetAllStates:after-cleanup', { reason });
|
||||
},
|
||||
|
||||
@ -1182,6 +1187,8 @@ const appOptions = {
|
||||
if (statusConversationId) {
|
||||
if (!this.currentConversationId) {
|
||||
this.skipConversationHistoryReload = true;
|
||||
// 首次从状态恢复对话时,避免 socket 的 conversation_loaded 再次触发历史加载
|
||||
this.skipConversationLoadedEvent = true;
|
||||
this.currentConversationId = statusConversationId;
|
||||
|
||||
// 如果有当前对话,尝试获取标题和历史
|
||||
@ -1192,7 +1199,13 @@ const appOptions = {
|
||||
this.currentConversationTitle = convData.data.title;
|
||||
}
|
||||
// 初始化时调用一次,因为 skipConversationHistoryReload 会阻止 watch 触发
|
||||
await this.fetchAndDisplayHistory();
|
||||
if (
|
||||
this.lastHistoryLoadedConversationId !== this.currentConversationId ||
|
||||
!Array.isArray(this.messages) ||
|
||||
this.messages.length === 0
|
||||
) {
|
||||
await this.fetchAndDisplayHistory();
|
||||
}
|
||||
// 获取当前对话的Token统计
|
||||
this.fetchConversationTokenStatistics();
|
||||
this.updateCurrentContextTokens();
|
||||
@ -1417,7 +1430,8 @@ const appOptions = {
|
||||
// ==========================================
|
||||
// 关键功能:获取并显示历史对话内容
|
||||
// ==========================================
|
||||
async fetchAndDisplayHistory() {
|
||||
async fetchAndDisplayHistory(options = {}) {
|
||||
const { force = false } = options as { force?: boolean };
|
||||
const targetConversationId = this.currentConversationId;
|
||||
if (!targetConversationId || targetConversationId.startsWith('temp_')) {
|
||||
debugLog('没有当前对话ID,跳过历史加载');
|
||||
@ -1431,6 +1445,20 @@ const appOptions = {
|
||||
return;
|
||||
}
|
||||
|
||||
// 已经有完整历史且非强制刷新时,避免重复加载导致动画播放两次
|
||||
const alreadyHydrated =
|
||||
!force &&
|
||||
this.lastHistoryLoadedConversationId === targetConversationId &&
|
||||
Array.isArray(this.messages) &&
|
||||
this.messages.length > 0;
|
||||
if (alreadyHydrated) {
|
||||
debugLog('历史已加载,跳过重复请求');
|
||||
this.logMessageState('fetchAndDisplayHistory:skip-duplicate', {
|
||||
conversationId: targetConversationId
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const loadSeq = ++this.historyLoadSeq;
|
||||
this.historyLoading = true;
|
||||
this.historyLoadingFor = targetConversationId;
|
||||
@ -1743,6 +1771,7 @@ const appOptions = {
|
||||
|
||||
debugLog(`历史消息渲染完成,共 ${this.messages.length} 条消息`);
|
||||
this.logMessageState('renderHistoryMessages:after-render');
|
||||
this.lastHistoryLoadedConversationId = this.currentConversationId || null;
|
||||
|
||||
// 强制更新视图
|
||||
this.$forceUpdate();
|
||||
|
||||
@ -522,16 +522,30 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
};
|
||||
|
||||
|
||||
const scheduleHistoryReload = (delay = 0) => {
|
||||
const scheduleHistoryReload = (delay = 0, options: { force?: boolean } = {}) => {
|
||||
const { force = false } = options;
|
||||
if (!ctx || typeof ctx.fetchAndDisplayHistory !== 'function') {
|
||||
return;
|
||||
}
|
||||
if (!ctx.currentConversationId || ctx.currentConversationId.startsWith('temp_')) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
const targetConversationId = ctx.currentConversationId;
|
||||
if (!targetConversationId || targetConversationId.startsWith('temp_')) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ctx.fetchAndDisplayHistory();
|
||||
if (!force) {
|
||||
const loadingSame =
|
||||
!!ctx.historyLoading && ctx.historyLoadingFor === targetConversationId;
|
||||
const historyReady =
|
||||
ctx.lastHistoryLoadedConversationId === targetConversationId &&
|
||||
Array.isArray(ctx.messages) &&
|
||||
ctx.messages.length > 0;
|
||||
if (loadingSame || historyReady) {
|
||||
socketLog('跳过重复历史加载(scheduleHistoryReload)');
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.fetchAndDisplayHistory({ force });
|
||||
if (typeof ctx.fetchConversationTokenStatistics === 'function') {
|
||||
ctx.fetchConversationTokenStatistics();
|
||||
}
|
||||
@ -565,13 +579,31 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
});
|
||||
}
|
||||
|
||||
let hasConnectedOnce = false;
|
||||
|
||||
// 连接事件
|
||||
ctx.socket.on('connect', () => {
|
||||
const isReconnect = hasConnectedOnce;
|
||||
const historyLoadingSame =
|
||||
!!ctx.historyLoading && ctx.historyLoadingFor === ctx.currentConversationId;
|
||||
const historyReady =
|
||||
ctx.lastHistoryLoadedConversationId === ctx.currentConversationId &&
|
||||
Array.isArray(ctx.messages) &&
|
||||
ctx.messages.length > 0;
|
||||
|
||||
ctx.isConnected = true;
|
||||
socketLog('WebSocket已连接');
|
||||
// 连接时重置所有状态并刷新当前对话
|
||||
ctx.resetAllStates('socket:connect');
|
||||
scheduleHistoryReload(200);
|
||||
|
||||
// 首次连接且历史已在加载/已就绪时,避免重复清空与重复动画
|
||||
if (!isReconnect && (historyLoadingSame || historyReady)) {
|
||||
socketLog('初次连接已存在历史,跳过重复重置与加载');
|
||||
hasConnectedOnce = true;
|
||||
return;
|
||||
}
|
||||
|
||||
hasConnectedOnce = true;
|
||||
ctx.resetAllStates(isReconnect ? 'socket:reconnect' : 'socket:connect');
|
||||
scheduleHistoryReload(200, { force: isReconnect });
|
||||
});
|
||||
|
||||
ctx.socket.on('disconnect', () => {
|
||||
@ -731,15 +763,30 @@ export async function initializeLegacySocket(ctx: any) {
|
||||
socketLog('跳过重复的 conversation_loaded 处理');
|
||||
return;
|
||||
}
|
||||
if (data.clear_ui) {
|
||||
// 清理当前UI状态,准备显示历史内容
|
||||
ctx.resetAllStates('socket:conversation_loaded');
|
||||
}
|
||||
const targetConversationId = (data && data.conversation_id) || ctx.currentConversationId;
|
||||
const historyLoadingSame =
|
||||
!!targetConversationId &&
|
||||
!!ctx.historyLoading &&
|
||||
ctx.historyLoadingFor === targetConversationId;
|
||||
const historyReady =
|
||||
!!targetConversationId &&
|
||||
ctx.lastHistoryLoadedConversationId === targetConversationId &&
|
||||
Array.isArray(ctx.messages) &&
|
||||
ctx.messages.length > 0;
|
||||
const forceReload = !!(data && data.force_reload);
|
||||
|
||||
// 延迟获取并显示历史对话内容
|
||||
setTimeout(() => {
|
||||
ctx.fetchAndDisplayHistory();
|
||||
}, 300);
|
||||
if (!forceReload && (historyLoadingSame || historyReady)) {
|
||||
socketLog('conversation_loaded: 历史已加载/加载中,跳过重复刷新');
|
||||
} else {
|
||||
if (data.clear_ui) {
|
||||
// 清理当前UI状态,准备显示历史内容
|
||||
ctx.resetAllStates('socket:conversation_loaded');
|
||||
}
|
||||
// 延迟获取并显示历史对话内容
|
||||
setTimeout(() => {
|
||||
ctx.fetchAndDisplayHistory({ force: forceReload });
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// 延迟获取Token统计(累计+当前上下文)
|
||||
setTimeout(() => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user