/** * 对话管理器 - 负责管理聊天会话的保存、加载和持久化 */ class ChatManager { constructor() { this.currentChatId = null; this.chats = new Map(); // 存储所有聊天会话 this.storageKey = 'yundage_chat_history'; this.currentUserKey = 'yundage_current_user'; this.initialized = false; // 监听认证状态变化事件 window.addEventListener('authStatusChecked', () => { if (!this.initialized) { console.log('ChatManager 收到认证状态检查完成事件,开始初始化'); this.init(); this.initialized = true; } }); // 备用方案:如果3秒内没有收到认证事件,强制初始化 setTimeout(() => { if (!this.initialized) { console.log('ChatManager 超时初始化'); this.init(); this.initialized = true; } }, 3000); } /** * 初始化 */ init() { this.loadFromStorage(); this.setupAutoSave(); } /** * 从本地存储加载聊天记录 */ loadFromStorage() { try { // 清空当前聊天记录 this.chats.clear(); this.currentChatId = null; const currentUser = this.getCurrentUser(); if (!currentUser) { console.log('没有登录用户,跳过加载'); return; } const storageKey = `${this.storageKey}_${currentUser.id}`; const currentChatKey = `${this.storageKey}_current_${currentUser.id}`; console.log(`[ChatManager] 开始加载聊天记录...`); console.log(`[ChatManager] 存储键: ${storageKey}`); console.log(`[ChatManager] 当前聊天键: ${currentChatKey}`); const savedChats = localStorage.getItem(storageKey); const savedCurrentChatId = localStorage.getItem(currentChatKey); console.log(`[ChatManager] localStorage中保存的当前聊天ID: ${savedCurrentChatId}`); if (savedChats) { const chatsData = JSON.parse(savedChats); this.chats = new Map(chatsData.map(chat => [chat.id, chat])); console.log(`[ChatManager] 成功加载了 ${this.chats.size} 个聊天会话`); console.log(`[ChatManager] 聊天ID列表:`, Array.from(this.chats.keys())); // 恢复当前聊天ID if (savedCurrentChatId && this.chats.has(savedCurrentChatId)) { this.currentChatId = savedCurrentChatId; console.log(`[ChatManager] ✅ 成功恢复当前聊天: ${savedCurrentChatId}`); } else if (savedCurrentChatId) { console.log(`[ChatManager] ⚠️ 保存的聊天ID ${savedCurrentChatId} 不在聊天列表中`); } else { console.log(`[ChatManager] 没有保存的当前聊天ID`); } } else { console.log(`[ChatManager] 未找到保存的聊天记录`); } console.log(`[ChatManager] 加载完成,当前聊天ID: ${this.currentChatId}`); } catch (error) { console.error('[ChatManager] 加载聊天记录失败:', error); } } /** * 保存到本地存储 */ saveToStorage() { try { const currentUser = this.getCurrentUser(); if (!currentUser) { console.log('没有登录用户,跳过保存'); return; } const storageKey = `${this.storageKey}_${currentUser.id}`; const chatsArray = Array.from(this.chats.values()); console.log(`正在保存 ${chatsArray.length} 个聊天到 localStorage,键名: ${storageKey}`); localStorage.setItem(storageKey, JSON.stringify(chatsArray)); console.log(`聊天记录已保存 (用户: ${currentUser.username}, ID: ${currentUser.id})`); } catch (error) { console.error('保存聊天记录失败:', error); } } /** * 获取当前用户 */ getCurrentUser() { const userStr = localStorage.getItem(this.currentUserKey); return userStr ? JSON.parse(userStr) : null; } /** * 设置自动保存 */ setupAutoSave() { // 每30秒自动保存一次 setInterval(() => { if (this.currentChatId) { this.saveToStorage(); } }, 30000); // 页面卸载时保存 window.addEventListener('beforeunload', () => { this.saveToStorage(); }); } /** * 创建新的聊天会话 * @param {string} firstMessage - 第一条消息,用于生成标题 * @returns {string} 聊天ID */ createChat(firstMessage = '') { const chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const chat = { id: chatId, title: this.generateTitle(firstMessage), messages: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), metadata: { messageCount: 0, lastActive: new Date().toISOString() } }; this.chats.set(chatId, chat); this.currentChatId = chatId; // 保存当前聊天ID const currentUser = this.getCurrentUser(); if (currentUser) { const currentChatKey = `${this.storageKey}_current_${currentUser.id}`; localStorage.setItem(currentChatKey, chatId); } this.saveToStorage(); return chatId; } /** * 生成聊天标题 * @param {string} firstMessage - 第一条消息 * @returns {string} 标题 */ generateTitle(firstMessage) { if (!firstMessage) return '新对话'; // 移除多余的空格和换行 const cleaned = firstMessage.trim().replace(/\s+/g, ' '); // 如果消息太长,截取前30个字符 if (cleaned.length > 30) { return cleaned.substring(0, 30) + '...'; } return cleaned || '新对话'; } /** * 添加消息到当前聊天 * @param {string} content - 消息内容 * @param {string} type - 消息类型 ('user' 或 'ai') * @param {object} metadata - 额外的元数据 */ addMessage(content, type, metadata = {}) { if (!this.currentChatId) { console.error('没有活动的聊天会话'); return; } const chat = this.chats.get(this.currentChatId); if (!chat) { console.error('聊天会话不存在'); return; } const message = { id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, content, contentType: metadata.contentType || 'markdown', // 默认使用markdown type, timestamp: new Date().toISOString(), status: type === 'user' ? 'sent' : 'complete', metadata: { deviceInfo: navigator.userAgent, ...metadata } }; chat.messages.push(message); chat.updatedAt = new Date().toISOString(); chat.metadata.messageCount = chat.messages.length; chat.metadata.lastActive = new Date().toISOString(); // 如果是第一条消息,更新标题 if (chat.messages.length === 1 && type === 'user') { chat.title = this.generateTitle(content); } this.chats.set(this.currentChatId, chat); // 触发消息添加事件 this.dispatchEvent('messageAdded', { chatId: this.currentChatId, message }); // 保存到本地存储 this.saveToStorage(); return message; } /** * 获取聊天会话 * @param {string} chatId - 聊天ID * @returns {object|null} 聊天会话 */ getChat(chatId) { return this.chats.get(chatId) || null; } /** * 获取当前聊天会话 * @returns {object|null} 当前聊天会话 */ getCurrentChat() { return this.currentChatId ? this.getChat(this.currentChatId) : null; } /** * 切换到指定聊天 * @param {string} chatId - 聊天ID */ switchToChat(chatId) { if (this.chats.has(chatId)) { this.currentChatId = chatId; const chat = this.chats.get(chatId); chat.metadata.lastActive = new Date().toISOString(); // 保存当前聊天ID const currentUser = this.getCurrentUser(); if (currentUser) { const currentChatKey = `${this.storageKey}_current_${currentUser.id}`; localStorage.setItem(currentChatKey, chatId); console.log(`保存当前聊天ID: ${chatId}`); } // 触发聊天切换事件 this.dispatchEvent('chatSwitched', { chatId, chat }); return true; } return false; } /** * 删除聊天会话 * @param {string} chatId - 聊天ID */ deleteChat(chatId) { if (this.chats.has(chatId)) { this.chats.delete(chatId); // 如果删除的是当前聊天,清空当前聊天ID if (this.currentChatId === chatId) { this.currentChatId = null; // 清除保存的当前聊天ID const currentUser = this.getCurrentUser(); if (currentUser) { const currentChatKey = `${this.storageKey}_current_${currentUser.id}`; localStorage.removeItem(currentChatKey); } } this.saveToStorage(); // 触发聊天删除事件 this.dispatchEvent('chatDeleted', { chatId }); return true; } return false; } /** * 更新聊天标题 * @param {string} chatId - 聊天ID * @param {string} newTitle - 新标题 */ updateChatTitle(chatId, newTitle) { const chat = this.chats.get(chatId); if (chat) { chat.title = newTitle; chat.updatedAt = new Date().toISOString(); this.chats.set(chatId, chat); this.saveToStorage(); // 触发标题更新事件 this.dispatchEvent('chatTitleUpdated', { chatId, title: newTitle }); return true; } return false; } /** * 获取所有聊天列表 * @param {object} options - 选项 * @returns {array} 聊天列表 */ getAllChats(options = {}) { const { sortBy = 'updatedAt', order = 'desc', limit = null } = options; let chatsArray = Array.from(this.chats.values()); // 排序 chatsArray.sort((a, b) => { const aValue = a[sortBy]; const bValue = b[sortBy]; if (order === 'desc') { return bValue > aValue ? 1 : -1; } else { return aValue > bValue ? 1 : -1; } }); // 限制数量 if (limit) { chatsArray = chatsArray.slice(0, limit); } return chatsArray; } /** * 搜索聊天记录 * @param {string} query - 搜索关键词 * @returns {array} 匹配的聊天列表 */ searchChats(query) { const lowerQuery = query.toLowerCase(); const results = []; for (const chat of this.chats.values()) { // 搜索标题 if (chat.title.toLowerCase().includes(lowerQuery)) { results.push({ chat, matchType: 'title' }); continue; } // 搜索消息内容 const matchedMessages = chat.messages.filter(msg => msg.content.toLowerCase().includes(lowerQuery) ); if (matchedMessages.length > 0) { results.push({ chat, matchType: 'content', matchedMessages }); } } return results; } /** * 清空所有聊天记录 */ clearAllChats() { this.chats.clear(); this.currentChatId = null; this.saveToStorage(); // 触发清空事件 this.dispatchEvent('allChatsCleared'); } /** * 导出聊天记录 * @param {string} chatId - 聊天ID,如果不提供则导出所有 * @returns {string} JSON格式的聊天记录 */ exportChats(chatId = null) { if (chatId) { const chat = this.chats.get(chatId); return chat ? JSON.stringify(chat, null, 2) : null; } else { const allChats = Array.from(this.chats.values()); return JSON.stringify(allChats, null, 2); } } /** * 导入聊天记录 * @param {string} jsonData - JSON格式的聊天记录 */ importChats(jsonData) { try { const data = JSON.parse(jsonData); const chatsToImport = Array.isArray(data) ? data : [data]; for (const chat of chatsToImport) { if (chat.id && chat.messages) { this.chats.set(chat.id, chat); } } this.saveToStorage(); // 触发导入事件 this.dispatchEvent('chatsImported', { count: chatsToImport.length }); return true; } catch (error) { console.error('导入聊天记录失败:', error); return false; } } /** * 获取聊天统计信息 */ getStatistics() { const totalChats = this.chats.size; let totalMessages = 0; let userMessages = 0; let aiMessages = 0; for (const chat of this.chats.values()) { totalMessages += chat.messages.length; userMessages += chat.messages.filter(m => m.type === 'user').length; aiMessages += chat.messages.filter(m => m.type === 'ai').length; } return { totalChats, totalMessages, userMessages, aiMessages, averageMessagesPerChat: totalChats > 0 ? Math.round(totalMessages / totalChats) : 0 }; } /** * 触发自定义事件 * @param {string} eventName - 事件名称 * @param {object} detail - 事件详情 */ dispatchEvent(eventName, detail = {}) { const event = new CustomEvent(`chatManager:${eventName}`, { detail }); window.dispatchEvent(event); } /** * 开始新的聊天会话 */ startNewChat() { this.currentChatId = null; // 清除保存的当前聊天ID const currentUser = this.getCurrentUser(); if (currentUser) { const currentChatKey = `${this.storageKey}_current_${currentUser.id}`; localStorage.removeItem(currentChatKey); } this.dispatchEvent('newChatStarted'); } /** * 用户登录后重新加载聊天记录 */ reloadForUser() { console.log('用户登录状态变化,重新加载聊天记录'); this.loadFromStorage(); this.dispatchEvent('userChanged'); } } // 创建全局实例 window.chatManager = new ChatManager();