Files
AIEC-new/AIEC-server/js/chat-manager.js
2025-10-17 09:31:28 +08:00

513 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 对话管理器 - 负责管理聊天会话的保存、加载和持久化
*/
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();