From b2688dc8a1fc4c8d714a275278179994ddeb047f Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Wed, 13 May 2026 09:00:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai-chat):=20=E4=BF=AE=E5=A4=8D=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=B6=88=E6=81=AF=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=8F=8A=E8=B6=85=E6=97=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/js/ai-service.js | 8 - pages_tool/ai-chat/ai-chat-message.vue | 197 +++++++++++++------------ 2 files changed, 99 insertions(+), 106 deletions(-) diff --git a/common/js/ai-service.js b/common/js/ai-service.js index 1b3a278..c99000c 100644 --- a/common/js/ai-service.js +++ b/common/js/ai-service.js @@ -210,14 +210,6 @@ export default { } }); - const timeout = setTimeout(() => { - if (!isAuthenticated || content === '') { - console.warn('WebSocket 超时,强制关闭'); - socketTask.close(); - safeComplete({ error: 'AI服务响应超时' }); - safeReject(new Error('AI服务响应超时')); - } - }, 20000); }); // #endif }, diff --git a/pages_tool/ai-chat/ai-chat-message.vue b/pages_tool/ai-chat/ai-chat-message.vue index babb4a2..fa9d3c6 100644 --- a/pages_tool/ai-chat/ai-chat-message.vue +++ b/pages_tool/ai-chat/ai-chat-message.vue @@ -534,28 +534,30 @@ export default { } }, onShow() { - // 如果不是 AI 客服,立即退出并跳转 - if (customerServiceType !== 'ai') { - uni.showToast({ title: '当前客服类型不支持此页面', icon: 'none' }); - setTimeout(() => { - uni.navigateBack({ delta: 1 }); // 或 redirectTo 首页 - }, 1000); - return; // 关键:阻止后续初始化 - } - // 优先读取本地缓存的会话 ID - const localConvId = this.getConversationIdFromLocal(); - if (localConvId) { - this.currentConversationId = localConvId; - aiService.setConversationId(localConvId); - } else { - this.currentConversationId = aiService.getConversationId(); - } - // 加载初始历史后,同步historyOffset - this.loadChatHistoryIfExist().then(() => { - // 初始历史条数作为偏移量 - this.historyOffset = this.messages.length; - }); - }, + // 如果不是 AI 客服,立即退出并跳转 + if (customerServiceType !== 'ai') { + uni.showToast({ title: '当前客服类型不支持此页面', icon: 'none' }); + setTimeout(() => { + uni.navigateBack({ delta: 1 }); + }, 1000); + return; + } + // 只在初次渲染或会话ID发生变化时才加载历史 + const localConvId = this.getConversationIdFromLocal(); + const shouldReload = this.currentConversationId !== localConvId; + + if (localConvId && shouldReload) { + // 切换到已有的历史会话 → 重新加载历史 + this.currentConversationId = localConvId; + aiService.setConversationId(localConvId); + this.loadChatHistoryIfExist(); + // 注意: historyOffset 和 hasMoreHistory 在 loadChatHistoryIfExist() 内部设置 + } else if (!localConvId && !this.currentConversationId) { + // 全新会话,初始化偏移量 + this.historyOffset = this.messages.length; + } + // 会话未变化且已有消息 → 跳过加载,保留当前消息 + }, // 新增:组件销毁时清除防抖定时器 beforeDestroy() { if (this.scrollTimer) clearTimeout(this.scrollTimer); @@ -631,8 +633,8 @@ export default { // 防抖处理:50ms内只执行一次,避免频繁触发 if (this.scrollTimer) clearTimeout(this.scrollTimer); this.scrollTimer = setTimeout(() => { - // 滚动到顶部附近(<20px)、不在加载中、显示加载更多时,触发加载 - if (currentScrollTop < 20 && !this.isLoadingHistory && this.showLoadMore) { + // 滚动到顶部附近(<20px)、不在加载中、还有更多历史时,触发加载 + if (currentScrollTop < 20 && !this.isLoadingHistory && this.hasMoreHistory) { this.loadMoreHistory(); } }, 50); @@ -682,7 +684,7 @@ async loadChatHistoryIfExist() { const realTimestamp = msg.created_at || msg.create_time || msg.time; return { id: msg.message_id || (Date.now() + Math.random() * 10000), - role: msg.role === 'user' ? 'user' : 'assistant', + role: msg.role === 'user' ? 'user' : 'ai', content: content, timestamp: realTimestamp, actions: msg.role !== 'user' ? [ @@ -691,6 +693,10 @@ async loadChatHistoryIfExist() { ] : [] }; }).filter(msg => msg.content.trim() !== ''); // 过滤掉内容为空的消息 + // 根据服务端 total 判断是否还有更多历史可加载 + const msgCount = this.messages.length; + this.hasMoreHistory = response.total > msgCount; + this.historyOffset = msgCount; } catch (error) { console.error('加载历史记录失败:', error); // 只需调用服务层的清除方法,它会处理本地存储 @@ -1393,80 +1399,74 @@ async loadChatHistoryIfExist() { }, // 加载更多历史消息 - async loadMoreHistory() { - if (!this.currentConversationId) { - this.currentConversationId = this.getConversationIdFromLocal(); - aiService.setConversationId(this.currentConversationId); - } - // 防止重复加载 - if (!this.showLoadMore || !this.currentConversationId || this.isLoadingHistory) { - return; - } - this.isFetchingHistory = true; - this.isLoadingHistory = true; - this.loadingText = '加载历史消息中...'; - this.hasMoreHistory = true; - - try { - // 关键修改:用独立的historyOffset作为偏移量,不再依赖messages.length - const response = await aiService.getConversationHistory({ - conversation_id: this.currentConversationId, - limit: 20, - offset: this.historyOffset // 改用独立偏移量 - }); - + async loadMoreHistory() { + if (!this.currentConversationId) { + this.currentConversationId = this.getConversationIdFromLocal(); + aiService.setConversationId(this.currentConversationId); + } + // 防止重复加载 + if (!this.hasMoreHistory || !this.currentConversationId || this.isLoadingHistory) { + return; + } + this.isFetchingHistory = true; + this.isLoadingHistory = true; + this.loadingText = '加载历史消息中...'; + + try { + const response = await aiService.getConversationHistory({ + conversation_id: this.currentConversationId, + limit: 20, + offset: this.historyOffset + }); + if (response.success && Array.isArray(response.messages) && response.messages.length > 0) { const historyMessages = response.messages.map(msg => { - // 只使用后端返回的真实时间,不使用假时间 - const realTimestamp = msg.create_time || msg.created_at || msg.time; - return { - id: msg.id || `history-${Date.now()}-${Math.random().toString(36).slice(2)}`, - role: msg.role === 'user' ? 'user' : 'ai', - type: 'text', - content: msg.content, - timestamp: realTimestamp - }; - }); - - // 1. 记录新增消息数量 - const newMsgCount = historyMessages.length; - // 2. 添加到消息列表开头 - this.messages = [...historyMessages, ...this.messages]; - // 3. 更新历史偏移量(累加,不是覆盖) - this.historyOffset += newMsgCount; - - // 4. 等待DOM渲染后,精准计算滚动位置 - await this.$nextTick(); - // 获取新增消息的实际DOM高度 - const query = uni.createSelectorQuery().in(this); - const heightPromises = []; - for (let i = 0; i < newMsgCount; i++) { - heightPromises.push(new Promise(resolve => { - query.select(`.message-item:nth-child(${i + 1})`).boundingClientRect(rect => { - resolve(rect ? rect.height + 32 : 0); // 加上消息间距(32rpx) - }).exec(); - })); - } - // 计算总高度 - const heights = await Promise.all(heightPromises); - const totalNewHeight = heights.reduce((sum, h) => sum + h, 0); - // 5. 设置scrollTop,保持滚动条在顶部附近 - this.scrollTop = totalNewHeight; - } else { - // 无更多历史 - this.showLoadMore = false; - } - } catch (error) { - console.error('加载历史失败:', error); - uni.showToast({ title: '加载历史失败', icon: 'none' }); - this.showLoadMore = false; - } finally { - this.isLoadingHistory = false; - this.isFetchingHistory = false; - this.hasMoreHistory = false; - this.loadingText = '加载更多历史消息'; - } - }, + const realTimestamp = msg.create_time || msg.created_at || msg.time; + return { + id: msg.id || `history-${Date.now()}-${Math.random().toString(36).slice(2)}`, + role: msg.role === 'user' ? 'user' : 'ai', + type: 'text', + content: msg.content, + timestamp: realTimestamp + }; + }); + + const newMsgCount = historyMessages.length; + this.messages = [...historyMessages, ...this.messages]; + this.historyOffset += newMsgCount; + + // 根据服务端 total 判断是否还有更多 + if (response.total !== undefined) { + this.hasMoreHistory = this.historyOffset < response.total; + } + + await this.$nextTick(); + const query = uni.createSelectorQuery().in(this); + const heightPromises = []; + for (let i = 0; i < newMsgCount; i++) { + heightPromises.push(new Promise(resolve => { + query.select(`.message-item:nth-child(${i + 1})`).boundingClientRect(rect => { + resolve(rect ? rect.height + 32 : 0); + }).exec(); + })); + } + const heights = await Promise.all(heightPromises); + const totalNewHeight = heights.reduce((sum, h) => sum + h, 0); + this.scrollTop = totalNewHeight; + } else { + // 无更多历史 + this.hasMoreHistory = false; + } + } catch (error) { + console.error('加载历史失败:', error); + uni.showToast({ title: '加载历史失败', icon: 'none' }); + this.hasMoreHistory = false; + } finally { + this.isLoadingHistory = false; + this.isFetchingHistory = false; + this.loadingText = '加载更多历史消息'; + } + }, // 显示更多工具 showMoreTools() { this.showToolsPanel = true @@ -1908,8 +1908,9 @@ async loadChatHistoryIfExist() { this.currentConversationId = null aiService.clearConversationId() this.clearConversationIdFromLocal() - // 重置历史偏移量 + // 重置历史偏移量和加载状态 this.historyOffset = 0 + this.hasMoreHistory = false // 触发清空事件 this.$emit('messages-cleared') },