// pages/chat/chat.js const chatApi = require('../../api/chat'); const userUtil = require('../../utils/user'); Page({ data: { userId: null, sessionId: null, messages: [], inputMessage: '', loading: false, sending: false, scrollIntoView: '' // 用于scroll-view滚动到底部 }, onLoad(options) { console.log('聊天页面加载, options:', options); const userInfo = userUtil.getUserInfo(); console.log('用户信息:', userInfo); if (!userInfo || !userInfo.userId) { console.error('用户未登录或userId为空'); wx.showToast({ title: '请先登录', icon: 'none' }); setTimeout(() => { wx.navigateBack(); }, 1500); return; } console.log('设置userId:', userInfo.userId); this.setData({ userId: userInfo.userId }); // 优先使用传入的sessionId(如果有) if (options.sessionId) { console.log('使用传入的sessionId:', options.sessionId); this.setData({ sessionId: options.sessionId }); // 保存sessionId到本地存储 this.saveSessionId(options.sessionId); this.loadMessageHistory(); } else { // 尝试从本地存储加载sessionId const savedSessionId = this.getSavedSessionId(userInfo.userId); if (savedSessionId) { console.log('从本地存储加载sessionId:', savedSessionId); this.setData({ sessionId: savedSessionId }); this.loadMessageHistory(); } else { // 创建新会话 console.log('创建新会话'); this.createSession(); } } }, onShow() { // 检查用户是否仍然登录 const userInfo = userUtil.getUserInfo(); if (!userInfo || !userInfo.userId) { // 用户已退出登录,清除会话数据 if (this.data.sessionId) { this.clearSavedSessionId(this.data.userId); } return; } // 如果userId发生变化(可能是切换了账号),重新加载 if (this.data.userId && userInfo.userId !== this.data.userId) { console.log('检测到用户切换,重新加载会话'); this.setData({ userId: userInfo.userId, sessionId: null, messages: [] }); const savedSessionId = this.getSavedSessionId(userInfo.userId); if (savedSessionId) { this.setData({ sessionId: savedSessionId }); this.loadMessageHistory(); } else { this.createSession(); } } }, // 创建新会话 async createSession() { try { console.log('开始创建会话, userId:', this.data.userId); if (!this.data.userId) { throw new Error('userId为空,请先登录'); } this.setData({ loading: true }); const session = await chatApi.createSession(this.data.userId); console.log('创建会话成功:', session); if (!session || !session.sessionId) { throw new Error('创建会话失败,未返回sessionId'); } // 保存sessionId到本地存储 this.saveSessionId(session.sessionId); this.setData({ sessionId: session.sessionId, messages: [], loading: false }); console.log('会话创建完成, sessionId:', session.sessionId); } catch (error) { console.error('创建会话失败:', error); wx.showToast({ title: '创建会话失败: ' + (error.message || error), icon: 'none', duration: 2000 }); this.setData({ loading: false }); throw error; // 重新抛出错误,让调用方知道失败 } }, // 保存sessionId到本地存储 saveSessionId(sessionId) { if (!this.data.userId || !sessionId) { return; } const key = `chat_sessionId_${this.data.userId}`; wx.setStorageSync(key, sessionId); console.log('保存sessionId到本地存储:', key, sessionId); }, // 从本地存储获取sessionId getSavedSessionId(userId) { if (!userId) { return null; } const key = `chat_sessionId_${userId}`; const sessionId = wx.getStorageSync(key); console.log('从本地存储获取sessionId:', key, sessionId); return sessionId || null; }, // 清除本地存储的sessionId clearSavedSessionId(userId) { if (!userId) { return; } const key = `chat_sessionId_${userId}`; wx.removeStorageSync(key); console.log('清除本地存储的sessionId:', key); }, // 加载消息历史 async loadMessageHistory() { if (!this.data.sessionId || !this.data.userId) { console.warn('无法加载消息历史:sessionId或userId为空'); return; } try { this.setData({ loading: true }); console.log('加载消息历史:', this.data.sessionId, this.data.userId); const messages = await chatApi.getMessageHistory(this.data.sessionId, this.data.userId); console.log('收到消息历史:', messages); // 确保消息格式正确(处理时间戳) const formattedMessages = (messages || []).map(msg => { return { role: msg.role || 'user', content: msg.content || '', timestamp: msg.timestamp || new Date().toISOString() }; }); this.setData({ messages: formattedMessages, loading: false }); // 延迟滚动到底部,确保DOM已更新 setTimeout(() => { this.scrollToBottom(); }, 200); } catch (error) { console.error('加载消息历史失败:', error); // 如果是会话不存在或无权访问,清除本地保存的sessionId if (error.message && (error.message.includes('不存在') || error.message.includes('无权访问'))) { console.log('会话无效,清除本地保存的sessionId'); this.clearSavedSessionId(this.data.userId); this.setData({ sessionId: null, messages: [] }); // 创建新会话 this.createSession(); } else { wx.showToast({ title: '加载消息失败', icon: 'none' }); this.setData({ loading: false }); } } }, // 输入消息 onInput(e) { this.setData({ inputMessage: e.detail.value }); }, // 发送消息 async sendMessage() { const message = this.data.inputMessage.trim(); if (!message) { wx.showToast({ title: '请输入消息', icon: 'none' }); return; } // 检查userId if (!this.data.userId) { console.error('userId为空,请先登录'); wx.showToast({ title: '请先登录', icon: 'none' }); return; } // 如果没有sessionId,先创建会话 if (!this.data.sessionId) { console.log('没有sessionId,创建新会话'); try { await this.createSession(); if (!this.data.sessionId) { wx.showToast({ title: '创建会话失败', icon: 'none' }); return; } } catch (error) { console.error('创建会话失败:', error); wx.showToast({ title: '创建会话失败: ' + error, icon: 'none', duration: 2000 }); return; } } try { this.setData({ sending: true, inputMessage: '' }); console.log('开始发送消息:', { sessionId: this.data.sessionId, userId: this.data.userId, message: message }); // 添加用户消息到列表 const userMessage = { role: 'user', content: message, timestamp: new Date().toISOString() }; const currentMessages = [...this.data.messages, userMessage]; this.setData({ messages: currentMessages }); this.scrollToBottom(); // 发送消息到服务器 console.log('调用API发送消息...'); const response = await chatApi.sendMessage(this.data.sessionId, message, this.data.userId); console.log('收到API响应:', response); // 更新会话ID(如果是新创建的) if (response.session && response.session.sessionId) { const newSessionId = response.session.sessionId; console.log('更新sessionId:', newSessionId); this.setData({ sessionId: newSessionId }); // 保存新的sessionId到本地存储 this.saveSessionId(newSessionId); } // 添加AI回复到列表 if (response.assistantMessage) { console.log('收到AI回复:', response.assistantMessage.content); this.setData({ messages: [...currentMessages, response.assistantMessage] }); this.scrollToBottom(); } else { console.warn('未收到AI回复'); wx.showToast({ title: '未收到AI回复', icon: 'none' }); } this.setData({ sending: false }); } catch (error) { console.error('发送消息失败:', error); console.error('错误详情:', JSON.stringify(error)); wx.showToast({ title: '发送失败: ' + (error.message || error || '未知错误'), icon: 'none', duration: 3000 }); // 移除用户消息(发送失败) const messages = this.data.messages.filter(m => m.content !== message || m.role !== 'user'); this.setData({ messages: messages, sending: false, inputMessage: message }); } }, // 滚动到底部 scrollToBottom() { // 使用scroll-view的scroll-into-view属性滚动到底部 if (this.data.messages && this.data.messages.length > 0) { const lastIndex = this.data.messages.length - 1; const scrollIntoView = `msg-${lastIndex}`; this.setData({ scrollIntoView: scrollIntoView }); // 清除scrollIntoView,以便下次可以再次触发 setTimeout(() => { this.setData({ scrollIntoView: '' }); }, 300); } }, // 格式化时间 formatTime(date) { if (!date) return ''; try { const d = typeof date === 'string' ? new Date(date) : date; if (isNaN(d.getTime())) return ''; const hours = d.getHours().toString().padStart(2, '0'); const minutes = d.getMinutes().toString().padStart(2, '0'); return `${hours}:${minutes}`; } catch (e) { return ''; } } });