class ChatService { constructor() { this.messages = []; this.welcomeMessageShown = false; // 生成或获取用户唯一标识符 this.userId = this.getOrCreateUserId(); this.init(); } // 生成或获取用户唯一标识符 getOrCreateUserId() { let userId = localStorage.getItem('chatUserId'); if (!userId) { // 生成唯一标识符 userId = 'user_' + Date.now() + '_' + Math.floor(Math.random() * 1000000); localStorage.setItem('chatUserId', userId); } return userId; } init() { // 确保userId已正确生成 if (!this.userId) { this.userId = this.getOrCreateUserId(); } console.log('Chat service initialized with userId:', this.userId); // 先从本地存储加载消息并显示 this.loadFromLocalStorage(); // 显示本地消息 this.displayMessages(); // 然后从服务器加载最新消息 this.loadMessages(); this.setupEventListeners(); // 添加语言变更事件监听,更新欢迎消息 window.addEventListener('languageChanged', () => { console.log('Language changed, updating welcome message...'); this.showWelcomeMessage(); }); // 在页面加载完成后,延迟执行欢迎消息显示,确保语言管理器已加载 // 这样可以确保在页面刷新后显示正确语言的欢迎消息 setTimeout(() => { console.log('Page load complete, checking welcome message...'); this.showWelcomeMessage(); }, 1000); } // 从本地存储加载消息 loadFromLocalStorage() { const storedMessages = localStorage.getItem('chatMessages'); if (storedMessages) { try { const parsedMessages = JSON.parse(storedMessages); // 只保留: // 1. 当前设备的消息和针对该设备的回复 // 2. 当天的欢迎语(不按语言过滤,让showWelcomeMessage处理) this.messages = parsedMessages.filter(msg => { // 首先检查是否是当前设备的消息 if (msg.userId !== this.userId) { return false; } // 如果是欢迎消息,只保留当天的,不按语言过滤 if (msg.id.startsWith('welcome_')) { return this.isTodayMessage(msg); } // 非欢迎消息全部保留 return true; }); console.log('Loaded messages from localStorage:', this.messages.length); } catch (error) { console.error('Failed to parse stored messages:', error); this.messages = []; } } else { this.messages = []; } } async loadMessages() { // 保存本地所有消息,防止从服务器加载时丢失 const localMessages = [...this.messages]; console.log('Loading messages for userId:', this.userId); try { // 从服务器加载消息,包含userId const response = await fetch(`/api/chat?userId=${this.userId}`); if (response.ok) { const data = await response.json(); if (data.success && data.data) { console.log('Server returned', data.data.length, 'messages'); // 只保留: // 1. 当前设备的消息和针对该设备的客服回复 // 2. 过滤掉非当天的欢迎语 const serverMessages = data.data.filter(msg => { // 确保消息有userId字段,并且与当前设备的userId匹配 const msgUserId = msg.userId || msg.sessionId; if (msgUserId !== this.userId) { return false; } // 如果是欢迎消息,只保留当天的,不按语言过滤 if (msg.id.startsWith('welcome_')) { return this.isTodayMessage(msg); } // 非欢迎消息全部保留 return true; }); console.log('Filtered to', serverMessages.length, 'messages for this device'); // 获取当前语言的欢迎语 let currentWelcomeText = '您好!欢迎访问无穷智能自动售货机官网,有什么可以帮助您的吗?'; if (window.languageManager && window.languageManager.isLoaded) { const translatedWelcome = window.languageManager.getTranslation('chat_welcome'); if (translatedWelcome) { currentWelcomeText = translatedWelcome; } } // 合并本地消息和服务器消息,然后再次过滤确保只有当前设备的消息和当天的欢迎语 const mergedMessages = [...localMessages, ...serverMessages]; // 确保只有当前设备的消息和当天的欢迎语被保留(不按语言过滤) const filteredMergedMessages = mergedMessages.filter(msg => { const msgUserId = msg.userId || msg.sessionId; if (msgUserId !== this.userId) { return false; } // 如果是欢迎消息,只保留当天的,不按语言过滤 if (msg.id.startsWith('welcome_')) { return this.isTodayMessage(msg); } // 非欢迎消息全部保留 return true; }); // 去重,保留最新的消息 const uniqueMessages = this.removeDuplicateMessages(filteredMergedMessages); // 检查消息是否有变化 if (!this.messagesEqual(this.messages, uniqueMessages)) { console.log('Message updates detected, refreshing display...'); this.messages = uniqueMessages; this.saveToLocalStorage(); this.displayMessages(); } else { console.log('No message updates'); } return; } } } catch (error) { console.error('Failed to load messages from server:', error); } // 获取当前语言的欢迎语 let currentWelcomeText = '您好!欢迎访问无穷智能自动售货机官网,有什么可以帮助您的吗?'; if (window.languageManager && window.languageManager.isLoaded) { const translatedWelcome = window.languageManager.getTranslation('chat_welcome'); if (translatedWelcome) { currentWelcomeText = translatedWelcome; } } // 如果服务器加载失败,使用本地存储的消息 const storedMessages = localStorage.getItem('chatMessages'); if (storedMessages) { try { const parsedMessages = JSON.parse(storedMessages); // 只保留: // 1. 当前设备的消息和针对该设备的客服回复 // 2. 当天的欢迎语(不按语言过滤) const filteredMessages = parsedMessages.filter(msg => { const msgUserId = msg.userId || msg.sessionId; if (msgUserId !== this.userId) { return false; } // 如果是欢迎消息,只保留当天的,不按语言过滤 if (msg.id.startsWith('welcome_')) { return this.isTodayMessage(msg); } // 非欢迎消息全部保留 return true; }); // 合并本地消息和过滤后的本地存储消息 const finalMessages = [...localMessages, ...filteredMessages]; const uniqueMessages = this.removeDuplicateMessages(finalMessages); if (!this.messagesEqual(this.messages, uniqueMessages)) { this.messages = uniqueMessages; this.displayMessages(); } } catch (error) { console.error('Failed to parse stored messages:', error); // 如果解析失败,只保留本地消息 this.displayMessages(); } } else { // 如果没有本地存储,只使用本地消息 this.displayMessages(); } } // 移除重复消息,保留最新的 removeDuplicateMessages(messages) { const uniqueMessages = []; const seenMessages = new Map(); // 按时间戳降序排序,确保最新的消息在前面 const sortedMessages = messages.sort((a, b) => { return new Date(b.timestamp) - new Date(a.timestamp); }); for (const message of sortedMessages) { // 使用消息内容、用户类型、时间戳和userId的组合作为唯一标识 // 确保不同设备的相同消息不会被误判为重复消息 const messageKey = `${message.message}-${message.userType}-${message.timestamp}-${message.userId || message.sessionId}`; if (!seenMessages.has(messageKey)) { seenMessages.set(messageKey, true); uniqueMessages.push(message); } } // 按时间戳升序排序,确保消息按时间顺序显示 return uniqueMessages.sort((a, b) => { return new Date(a.timestamp) - new Date(b.timestamp); }); } // 比较两个消息数组是否相等 messagesEqual(arr1, arr2) { if (arr1.length !== arr2.length) return false; for (let i = 0; i < arr1.length; i++) { if (arr1[i].id !== arr2[i].id || arr1[i].message !== arr2[i].message || arr1[i].userType !== arr2[i].userType || arr1[i].timestamp !== arr2[i].timestamp || arr1[i].status !== arr2[i].status || arr1[i].userId !== arr2[i].userId) { return false; } } return true; } saveToLocalStorage() { // 保存前过滤掉非当天的欢迎语,只保留: // 1. 当天的欢迎语 // 2. 所有非欢迎语消息(用户发送的和客服回复的) const filteredMessages = this.messages.filter(msg => { // 如果是欢迎消息,只保留当天的 if (msg.id.startsWith('welcome_')) { return this.isTodayMessage(msg); } // 非欢迎消息全部保留 return true; }); localStorage.setItem('chatMessages', JSON.stringify(filteredMessages)); } setupEventListeners() { const setupListeners = () => { const chatSend = document.getElementById('chat-send'); const chatInput = document.getElementById('chat-input'); if (chatSend) { chatSend.addEventListener('click', () => { const message = chatInput.value.trim(); if (message) { this.sendMessage(message); chatInput.value = ''; } }); } if (chatInput) { chatInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { const message = chatInput.value.trim(); if (message) { this.sendMessage(message); chatInput.value = ''; } } }); } const chatButton = document.getElementById('chat-button'); const chatBox = document.getElementById('chat-box'); const chatClose = document.getElementById('chat-close'); if (chatButton && chatBox) { chatButton.addEventListener('click', () => { chatBox.classList.add('open'); chatButton.style.display = 'none'; this.showWelcomeMessage(); }); } if (chatClose && chatBox) { chatClose.addEventListener('click', () => { chatBox.classList.remove('open'); const chatButton = document.getElementById('chat-button'); if (chatButton) { chatButton.style.display = 'flex'; } }); } }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', setupListeners); } else { setupListeners(); } } // 获取当前日期(YYYY-MM-DD格式) getCurrentDate() { const now = new Date(); return now.toISOString().split('T')[0]; } // 检查消息是否是当天的 isTodayMessage(message) { if (!message.timestamp) return false; const messageDate = new Date(message.timestamp).toISOString().split('T')[0]; const currentDate = this.getCurrentDate(); return messageDate === currentDate; } showWelcomeMessage() { // 获取对应语言的欢迎语 let welcomeText = '您好!欢迎访问无穷智能自动售货机官网,有什么可以帮助您的吗?'; // 检查语言管理器是否可用,获取对应语言的欢迎语 if (window.languageManager && window.languageManager.isLoaded) { const translatedWelcome = window.languageManager.getTranslation('chat_welcome'); if (translatedWelcome) { welcomeText = translatedWelcome; } } else { console.log('Language manager not loaded yet, using default welcome text'); // 如果语言管理器还没有加载,使用默认欢迎语 // 但仍然需要显示欢迎消息,因为语言可能会在页面加载后切换 } // 检查当天是否已经发送过欢迎消息 const today = this.getCurrentDate(); const todayWelcomeMessage = this.messages.find(msg => msg.id.startsWith('welcome_') && this.isTodayMessage(msg) ); // 强制更新欢迎消息,无论是否已经存在 // 这样可以确保在语言切换后显示正确的欢迎消息 console.log('Forcing welcome message update for current language'); // 移除所有欢迎消息 this.messages = this.messages.filter(msg => !msg.id.startsWith('welcome_')); const welcomeMessage = { id: 'welcome_' + Date.now(), message: welcomeText, userType: 'bot', timestamp: new Date().toISOString(), status: 'sent', userId: this.userId }; this.messages.push(welcomeMessage); this.saveToLocalStorage(); this.displayMessages(); // 重新显示所有消息,确保欢迎消息正确显示 this.welcomeMessageShown = true; console.log('Welcome message displayed for language:', window.languageManager ? window.languageManager.currentLang : 'unknown'); } async sendMessage(message) { const newMessage = { id: 'msg_' + Date.now() + '_' + Math.floor(Math.random() * 1000), message: message, userType: 'user', timestamp: new Date().toISOString(), status: 'sending', userId: this.userId }; // 先添加到本地并显示 this.messages.push(newMessage); this.saveToLocalStorage(); this.displayMessage(newMessage); try { // 发送到服务器,包含userId const response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: message, userType: 'user', timestamp: newMessage.timestamp, userId: this.userId }) }); if (response.ok) { const data = await response.json(); if (data.success) { // 更新消息状态 newMessage.status = 'sent'; this.saveToLocalStorage(); this.updateMessageDisplay(newMessage); // 发送成功后重新加载消息,确保获取最新的回复 await this.loadMessages(); } } } catch (error) { console.error('Failed to send message to server:', error); newMessage.status = 'failed'; this.saveToLocalStorage(); this.updateMessageDisplay(newMessage); } } displayMessage(message) { const chatMessages = document.getElementById('chat-messages'); if (!chatMessages) return; const messageElement = document.createElement('div'); messageElement.id = 'msg_' + message.id; messageElement.className = `chat-message ${message.userType === 'user' ? 'user' : 'bot'}`; let statusIndicator = ''; if (message.userType === 'user') { if (message.status === 'sending') { statusIndicator = ''; } else if (message.status === 'failed') { statusIndicator = ''; } } messageElement.innerHTML = `
`; chatMessages.appendChild(messageElement); chatMessages.scrollTop = chatMessages.scrollHeight; } updateMessageDisplay(message) { const messageElement = document.getElementById('msg_' + message.id); if (!messageElement) return; let statusIndicator = ''; if (message.userType === 'user') { if (message.status === 'sent') { statusIndicator = ''; } else if (message.status === 'failed') { statusIndicator = ''; } } const footerElement = messageElement.querySelector('.chat-message-footer'); if (footerElement) { footerElement.innerHTML = ` ${statusIndicator} `; } } displayMessages() { const chatMessages = document.getElementById('chat-messages'); if (!chatMessages) return; chatMessages.innerHTML = ''; this.messages.forEach(message => { this.displayMessage(message); }); if (this.messages.length === 0) { this.welcomeMessageShown = false; } else { // 检查是否存在当天的欢迎消息 this.welcomeMessageShown = this.messages.some(msg => msg.id.startsWith('welcome_') && this.isTodayMessage(msg) ); } } formatTime(timestamp) { const date = new Date(timestamp); return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } clearMessages() { // 只清除欢迎消息,保留其他消息 this.messages = this.messages.filter(msg => !msg.id.startsWith('welcome_')); this.welcomeMessageShown = false; this.saveToLocalStorage(); this.displayMessages(); } // 定期检查服务器消息更新 startPolling() { console.log('Starting message polling...'); // 初始加载 this.loadMessages(); // 每5秒检查一次 this.pollingInterval = setInterval(() => { console.log('Polling for message updates...'); this.loadMessages(); }, 5000); // 缩短轮询间隔到5秒 } stopPolling() { if (this.pollingInterval) { clearInterval(this.pollingInterval); console.log('Stopped message polling'); } } } if (typeof window !== 'undefined') { // 确保DOM完全加载后再初始化聊天服务 const initChatService = () => { console.log('Initializing chat service...'); window.chatService = new ChatService(); // 启动消息轮询 window.chatService.startPolling(); // 确保消息正确加载 window.chatService.loadMessages(); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChatService); } else { initChatService(); } }