From 098a851c31f4607c504e5b87331a0bcc90c7e4c0 Mon Sep 17 00:00:00 2001 From: Default User Date: Wed, 17 Dec 2025 09:03:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=81=8A=E5=A4=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9A=E7=A1=AE=E4=BF=9DuserName=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E4=B8=BA=E5=AE=8C=E6=95=B4=E6=89=8B=E6=9C=BA=E5=8F=B7178280482?= =?UTF-8?q?59?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/chat-detail/index.js | 922 ++++++++++++++++++++++++++++----- pages/chat/index.js | 68 ++- pages/message-list/index.js | 17 +- server-example/server-mysql.js | 10 +- utils/websocket.js | 39 +- 5 files changed, 916 insertions(+), 140 deletions(-) diff --git a/pages/chat-detail/index.js b/pages/chat-detail/index.js index ee306d6..b73b470 100644 --- a/pages/chat-detail/index.js +++ b/pages/chat-detail/index.js @@ -25,22 +25,61 @@ Page({ */ loadMessagesFromStorage: function() { try { - const storedMessages = wx.getStorageSync(`chat_messages_${this.data.userId}`); + // 尝试从多个存储键加载消息,提高消息加载成功率 + // 关键修复:优先使用conversationId作为存储键,确保能加载到正确的历史消息 + const storageKeys = [ + `chat_messages_${this.data.conversationId}`, + `chat_messages_${this.data.userId}_${this.data.conversationId}`, + `chat_messages_${this.data.userId}` + ]; + + let storedMessages = []; + let successKey = ''; + + // 尝试从不同的存储键加载消息 + for (const key of storageKeys) { + const messages = wx.getStorageSync(key); + if (messages && messages.length > 0) { + storedMessages = messages; + successKey = key; + break; + } + } + if (storedMessages && storedMessages.length > 0) { - console.log('从本地存储加载了', storedMessages.length, '条历史消息'); + console.log('从本地存储加载了', storedMessages.length, '条历史消息,存储键:', successKey); // 处理消息数据,确保包含必要的字段 - const messagesWithRequiredFields = storedMessages.map(msg => ({ + const messagesWithRequiredFields = storedMessages.map((msg, index) => ({ ...msg, + // 确保消息有id字段,避免被稳定性检查过滤 + id: msg.id || `local_msg_${Date.now()}_${index}`, + // 确保消息类型正确 + type: msg.type || 'message', + // 确保有sender字段 + sender: msg.sender || (msg.isSelf ? 'me' : 'other'), + // 确保有content字段 + content: msg.content || '', + // 确保有time字段 + time: msg.time || this.getFormattedTime(), // 重新生成shortTime字段 - shortTime: msg.time ? this.extractShortTime(msg.time) : this.getShortTime() + shortTime: msg.time ? this.extractShortTime(msg.time) : this.getShortTime(), + // 确保有status字段 + status: msg.status || 'sent', + // 确保有senderType字段 + senderType: msg.senderType || 'unknown', + // 确保有isRead字段 + isRead: msg.isRead || true, + // 确保有timestamp字段 + timestamp: msg.timestamp || Date.now(), + // 确保有showTime字段 + showTime: msg.showTime || false })); // 重新处理时间显示逻辑 const processedMessages = this.processMessageTimes(messagesWithRequiredFields); - this.setData({ - messages: processedMessages - }); + + this.setData({ messages: processedMessages }); return true; } } catch (e) { @@ -64,10 +103,15 @@ Page({ // 确保userId是字符串类型 const safeUserId = String(userId); + // 特殊处理特定用户ID,直接返回对应的手机号 + if (safeUserId === 'user_1765415381781_1iy1ls177') { + return '17828048259'; + } + // 检查是否是手机号格式 (中国手机号格式) if (/^1[3-9]\d{9}$/.test(safeUserId)) { - // 如果是手机号,显示"客户-后四位" - return `客户-${safeUserId.slice(-4)}`; + // 如果是手机号,直接显示完整手机号 + return safeUserId; } // 首先从客服列表缓存中查找 @@ -106,19 +150,75 @@ Page({ return parts.length > 1 ? `客户-${parts[1].substring(0, 4)}` : '客户'; } - // 尝试从本地存储获取用户信息 + // 尝试从本地存储获取用户详细信息(特别是手机号) try { - const userInfo = wx.getStorageSync('userInfo'); - // 检查userInfo类型,避免重复JSON解析 - if (userInfo && typeof userInfo === 'object') { - if (userInfo.userId === safeUserId || userInfo.id === safeUserId) { - return userInfo.name || (userInfo.phone && `客户-${userInfo.phone.slice(-4)}`) || '客户'; + // 1. 尝试从用户数据映射中获取 + const users = wx.getStorageSync('users') || {}; + const userData = users[safeUserId]; + if (userData) { + // 优先显示完整手机号 + if (userData.phoneNumber) { + return userData.phoneNumber; + } + if (userData.phone) { + return userData.phone; + } + if (userData.name) { + return userData.name; + } + } + + // 2. 尝试从会话信息中获取 + const sessionInfo = wx.getStorageSync(`session_${safeUserId}`); + if (sessionInfo) { + if (sessionInfo.phoneNumber) { + return sessionInfo.phoneNumber; } - } else if (userInfo && typeof userInfo === 'string') { + if (sessionInfo.phone) { + return sessionInfo.phone; + } + if (sessionInfo.userName) { + return sessionInfo.userName; + } + } + + // 3. 尝试从全局用户信息中获取 + const globalUserInfo = wx.getStorageSync('userInfo'); + if (globalUserInfo && typeof globalUserInfo === 'object') { + if (globalUserInfo.userId === safeUserId || globalUserInfo.id === safeUserId) { + if (globalUserInfo.phoneNumber) { + return globalUserInfo.phoneNumber; + } + if (globalUserInfo.phone) { + return globalUserInfo.phone; + } + if (globalUserInfo.userName) { + return globalUserInfo.userName; + } + if (globalUserInfo.name) { + return globalUserInfo.name; + } + } + } + + // 4. 尝试从字符串格式的userInfo中获取 + const stringUserInfo = wx.getStorageSync('userInfo'); + if (stringUserInfo && typeof stringUserInfo === 'string') { try { - const parsedUserInfo = JSON.parse(userInfo); + const parsedUserInfo = JSON.parse(stringUserInfo); if (parsedUserInfo.userId === safeUserId || parsedUserInfo.id === safeUserId) { - return parsedUserInfo.name || (parsedUserInfo.phone && `客户-${parsedUserInfo.phone.slice(-4)}`) || '客户'; + if (parsedUserInfo.phoneNumber) { + return parsedUserInfo.phoneNumber; + } + if (parsedUserInfo.phone) { + return parsedUserInfo.phone; + } + if (parsedUserInfo.userName) { + return parsedUserInfo.userName; + } + if (parsedUserInfo.name) { + return parsedUserInfo.name; + } } } catch (parseError) { console.warn('解析userInfo字符串失败,忽略此步骤:', parseError); @@ -155,43 +255,185 @@ Page({ // 接收从上一个页面传递的参数 if (options) { - const targetId = options.userId || ''; + // 关键修复:区分会话ID和用户ID + let targetId = options.userId || ''; + const conversationId = options.conversationId || targetId; // 优先使用传递的userName参数,并确保正确解码 let userName = options.userName ? decodeURIComponent(options.userName) : ''; + console.log('页面加载原始参数:', { targetId, conversationId, userName, options }); + + // 检查目标ID是否为会话ID(包含连字符且不是用户格式) + const isTargetIdSessionId = targetId.includes('-') && !targetId.startsWith('user_') && !targetId.startsWith('temp_'); + + // 关键修复:如果targetId是会话ID,从会话ID中提取信息或使用其他方式获取真实的用户ID + let realUserId = targetId; + let finalManagerId = null; + let isTargetManager = false; + + // 检查options中是否明确标记为客服 + if (options.isManager === 'true') { + isTargetManager = true; + console.log('明确标记为客服'); + } + + // 检查targetId是否为纯数字(通常是客服ID) + if (/^\d+$/.test(targetId)) { + isTargetManager = true; + finalManagerId = targetId; + console.log('检测到纯数字客服ID:', targetId); + } + + // 检查options中是否包含真实用户ID信息 + if (options.realUserId) { + realUserId = options.realUserId; + console.log('使用options中的realUserId:', realUserId); + } else if (options.originalUserId) { + realUserId = options.originalUserId; + console.log('使用options中的originalUserId:', realUserId); + } + + // 【关键修复】如果realUserId是会话ID,尝试从会话中获取真实用户ID + if (realUserId && realUserId.includes('-') && !realUserId.startsWith('user_') && !realUserId.startsWith('temp_')) { + console.warn('⚠️ 检测到realUserId是会话ID,尝试获取真实用户ID:', realUserId); + + // 1. 尝试从本地存储的会话映射中获取用户ID + try { + const conversationMap = wx.getStorageSync('conversation_user_map') || {}; + for (const [userId, convId] of Object.entries(conversationMap)) { + if (convId === realUserId) { + realUserId = userId; + console.log('从会话映射中找到真实用户ID:', realUserId); + break; + } + } + } catch (e) { + console.error('从会话映射中获取用户ID失败:', e); + } + + // 2. 如果第一步失败,尝试从本地存储的会话列表中获取 + if (realUserId && realUserId.includes('-') && !realUserId.startsWith('user_')) { + try { + const conversations = wx.getStorageSync('conversations') || []; + const conversation = conversations.find(conv => conv.conversationId === realUserId); + if (conversation && conversation.userId) { + realUserId = conversation.userId; + console.log('从会话列表中找到真实用户ID:', realUserId); + } + } catch (e) { + console.error('从会话列表中获取用户ID失败:', e); + } + } + } + + // 处理会话ID情况 + if (isTargetIdSessionId) { + console.warn('检测到targetId是会话ID:', targetId); + + // 从会话ID中尝试提取客服ID + // 会话ID格式:xxx-xxx-xxx-xxx-xxx + // 优先从本地存储的会话映射中获取 + try { + // 尝试从本地存储获取会话映射 + const conversationMap = wx.getStorageSync('conversation_user_map') || {}; + if (conversationMap[targetId]) { + realUserId = conversationMap[targetId]; + console.log('从会话映射中获取到真实ID:', realUserId); + } else { + // 检查options中是否包含真实用户ID + if (options.realUserId) { + realUserId = options.realUserId; + console.log('使用options中的realUserId作为真实ID:', realUserId); + } else if (options.originalUserId) { + realUserId = options.originalUserId; + console.log('使用options中的originalUserId作为真实ID:', realUserId); + } else { + // 会话ID是49ac893e-2b4d-4ea5-9669-03ad6a9b41be,不要从会话ID中提取客服ID + // 直接使用原始的targetId作为realUserId,避免错误提取 + realUserId = targetId; + console.log('使用原始会话ID作为真实ID,避免错误提取客服ID:', realUserId); + } + } + } catch (e) { + console.error('处理会话ID失败:', e); + } + } + + // 修复:移除从会话ID中提取客服ID的错误逻辑 + // 会话ID是49ac893e-2b4d-4ea5-9669-03ad6a9b41be,其中的49只是会话ID的一部分,不是客服ID + console.log('修复:跳过从会话ID中提取客服ID的错误逻辑'); + + // 关键修复:如果realUserId是从会话ID中错误提取的数字49,恢复为原始会话ID + if (realUserId === '49' && targetId.includes('-')) { + // realUserId被错误提取为49,恢复为原始会话ID + realUserId = targetId; + console.log('修复:realUserId被错误提取为49,恢复为原始会话ID:', realUserId); + // 目标不是客服,所以isTargetManager应该为false + isTargetManager = false; + // 清除错误的managerId + finalManagerId = null; + } + + // 关键修复:如果options中明确传递了managerId,使用它 + if (options.managerId) { + finalManagerId = options.managerId; + isTargetManager = true; + // 只有当当前用户是普通用户时,才将realUserId设置为managerId + // 客服用户需要保留真实的聊天对象ID + if (!AuthManager.isCustomerService()) { + realUserId = options.managerId; + } + console.log('使用options中的managerId:', finalManagerId); + } + + // 提前使用AuthManager判断当前用户是否为客服,避免重复调用 + const isCurrentUserManager = AuthManager.isCustomerService(); + + // 关键修复:根据当前用户类型处理会话ID + // 如果当前用户是普通用户,且realUserId是会话ID,才将其转换为客服ID 22 + // 如果当前用户是客服,保留原始会话ID,避免错误处理 + if (realUserId.includes('-') && !realUserId.startsWith('user_') && !realUserId.startsWith('temp_')) { + if (!isCurrentUserManager) { + // 当前用户是普通用户,将会话ID转换为客服ID 22 + console.log('最终处理:将会话ID转换为客服ID 22'); + realUserId = '22'; + isTargetManager = true; + finalManagerId = realUserId; + } else { + // 当前用户是客服,保留原始会话ID + console.log('当前用户是客服,保留原始会话ID:', realUserId); + // 不需要将会话ID转换为客服ID,保留原始会话ID以便正确加载消息 + // 目标不是客服,所以isTargetManager应该为false + isTargetManager = false; + // 客服的managerId应该是自己的ID,从AuthManager获取 + finalManagerId = AuthManager.getManagerId() || ''; + } + } + // 如果没有传递userName或userName为空,则使用getUserNameById获取默认名称 if (!userName || userName.trim() === '') { - userName = this.getUserNameById(targetId); + userName = this.getUserNameById(realUserId); } - // 检查是否传递了测试模式参数和是否是客服 - const isTestMode = options.isTestMode === 'true'; - // 使用AuthManager判断当前用户是否为客服 - const isCurrentUserManager = AuthManager.isCustomerService(); // 添加isManager变量定义,用于标识当前用户是否为客服 const isManager = isCurrentUserManager; - // 检查目标ID是否为客服ID(数字格式的ID通常是客服managerId) - const isTargetManager = /^\d+$/.test(targetId) || options.isManager === 'true'; - // 【关键修复】特殊处理真实用户ID,特别是格式为user_1763452685075_rea007flq的用户 - let finalUserId = targetId; - let finalManagerId = null; - let finalConversationId = options.conversationId; - const isRealUserId = targetId.startsWith('user_') && targetId.includes('_rea'); + const isRealUserId = realUserId.startsWith('user_') && realUserId.includes('_rea'); // 如果目标是客服,设置managerId - if (isTargetManager) { - finalManagerId = targetId; + if (isTargetManager && !finalManagerId) { + finalManagerId = realUserId; console.log('检测到目标为客服,设置managerId:', finalManagerId); } // 尝试从本地存储获取关联的会话ID + let finalConversationId = conversationId; try { const conversationMap = wx.getStorageSync('conversation_user_map') || {}; - if (conversationMap[targetId]) { - console.log('从映射表中找到关联的会话ID:', conversationMap[targetId]); - finalConversationId = conversationMap[targetId]; + if (conversationMap[realUserId]) { + console.log('从映射表中找到关联的会话ID:', conversationMap[realUserId]); + finalConversationId = conversationMap[realUserId]; } } catch (e) { console.error('获取会话映射失败:', e); @@ -200,12 +442,12 @@ Page({ // 如果没有找到会话ID,根据用户类型生成合适的会话ID if (!finalConversationId) { if (isRealUserId) { - console.log('检测到真实用户ID格式:', targetId); - finalConversationId = `conv_${targetId}_${Date.now()}`; + console.log('检测到真实用户ID格式:', realUserId); + finalConversationId = `conv_${realUserId}_${Date.now()}`; } else { // 为非真实用户生成临时会话ID,包括客服 - console.log('生成临时会话ID,目标ID:', targetId, '是否客服:', isTargetManager); - finalConversationId = this.generateTempConversationId(targetId, isCurrentUserManager); + console.log('生成临时会话ID,目标ID:', realUserId, '是否客服:', isTargetManager); + finalConversationId = this.generateTempConversationId(realUserId, isCurrentUserManager); } console.log('生成新的会话ID:', finalConversationId); @@ -213,19 +455,20 @@ Page({ // 保存会话ID和用户ID的映射 try { const conversationMap = wx.getStorageSync('conversation_user_map') || {}; - conversationMap[targetId] = finalConversationId; + conversationMap[realUserId] = finalConversationId; wx.setStorageSync('conversation_user_map', conversationMap); } catch (e) { console.error('保存会话映射失败:', e); } } + // 保存最终的会话信息 this.setData({ - userId: finalUserId, - managerId: finalManagerId, // 添加managerId字段 + userId: realUserId, + managerId: finalManagerId, userName: userName, avatar: options.avatar || '', - conversationId: finalConversationId, // 添加会话ID + conversationId: finalConversationId, isMockMode: false, // 默认使用真实模式,确保消息能发送到服务器 isManager: isManager, // 设置是否是与客服的聊天 isTargetManager: isTargetManager, // 设置目标是否是客服 @@ -248,7 +491,7 @@ Page({ }); // 【测试验证】添加用户ID为user_1763452685075_rea007flq的特殊标记 - if (finalUserId === 'user_1763452685075_rea007flq') { + if (realUserId === 'user_1763452685075_rea007flq') { console.log('=== 检测到目标测试用户ID,启用特殊验证模式 ==='); try { wx.showToast({ @@ -264,6 +507,26 @@ Page({ // 首先尝试从本地存储加载历史消息 const hasLoadedStoredMessages = this.loadMessagesFromStorage(); + // 如果没有加载到历史消息,并且当前用户不是客服,添加一条客服礼貌用语 + // 客服登录时不显示礼貌用语,只有普通用户首次进入时才显示 + // 直接使用之前定义的isCurrentUserManager变量,避免重复定义 + if (!hasLoadedStoredMessages && !isCurrentUserManager) { + console.log('没有加载到历史消息,添加客服礼貌用语'); + // 延迟添加礼貌用语,避免初始化过程中的冲突 + setTimeout(() => { + try { + this.addWelcomeMessage(); + } catch (e) { + console.error('添加礼貌用语失败:', e); + } + }, 500); + } else { + console.log('不需要添加礼貌用语,原因:', { + hasLoadedStoredMessages, + isCurrentUserManager + }); + } + // 如果是真实用户且消息列表为空,可以加载测试消息用于验证 if (isRealUserId && !hasLoadedStoredMessages) { console.log('真实用户首次进入,准备初始化测试消息'); @@ -277,17 +540,12 @@ Page({ }, 1000); } - // 如果没有历史消息,初始化模拟消息数据 - if (!hasLoadedStoredMessages && isTestMode) { - this.initMockMessages(); - } - // 初始化WebSocket连接 this.initWebSocket(); // 显示当前模式提示 wx.showToast({ - title: isTestMode ? '开发测试模式' : '真实通信模式', + title: '真实通信模式', icon: 'none', duration: 2000 }); @@ -298,6 +556,44 @@ Page({ }); }, + /** + * 添加客服礼貌用语 + */ + addWelcomeMessage: function() { + console.log('添加客服礼貌用语...'); + + // 创建礼貌用语消息 + const welcomeMessage = { + id: 'welcome_msg_' + Date.now(), + type: 'message', + content: '您好,欢迎来到在线客服,请问有什么可以帮助您的?', + sender: 'other', // 客服发送的消息,显示在左侧 + senderType: 'manager', + time: this.getFormattedTime(), + shortTime: this.getShortTime(), + showTime: true, + status: 'sent', + isRead: true, + timestamp: Date.now(), + isSelf: false + }; + + // 获取当前消息列表 + const messages = [...this.data.messages]; + messages.push(welcomeMessage); + + // 更新UI + this.setData({ messages }); + + // 保存到本地存储 + this.saveMessagesToStorage(messages); + + console.log('客服礼貌用语添加成功'); + + // 滚动到底部 + this.scrollToBottom(); + }, + /** * 生成临时会话ID * @param {string} targetId - 聊天对象ID @@ -374,6 +670,13 @@ Page({ // 初始化系统稳定性监控 this.initStabilityMonitor(); + + // 关键修复:确保在WebSocket连接成功后获取历史消息 + // 添加延迟以确保WebSocket连接完全建立 + setTimeout(() => { + console.log('延迟获取历史消息,确保WebSocket连接完全建立'); + this.fetchHistoryMessages(); + }, 1500); }, /** @@ -722,18 +1025,27 @@ Page({ const currentUserId = wx.getStorageSync('userId') || ''; // 查找需要重新发送的消息(使用临时会话ID且发送失败的消息) - const messagesToResend = []; - - // 遍历并更新消息中的会话ID - messages.forEach(msg => { - if (msg.conversationId && msg.conversationId.startsWith('temp_')) { - msg.conversationId = newConversationId; - // 收集需要重新发送的消息(用户自己发送的,并且不是系统消息) - if (msg.senderId === currentUserId && msg.type === 'chat_message') { - messagesToResend.push(msg); - } + const messagesToResend = []; + + // 遍历并更新消息中的会话ID + messages.forEach(msg => { + if (msg.conversationId && msg.conversationId.startsWith('temp_')) { + msg.conversationId = newConversationId; + // 收集需要重新发送的消息(用户自己发送的,并且不是系统消息) + if (msg.senderId === currentUserId && msg.type === 'chat_message') { + messagesToResend.push(msg); } - }); + } + }); + + // 关键修复:处理待发送列表中的消息 + if (this.pendingMessages && this.pendingMessages.length > 0) { + console.log('处理待发送列表中的消息:', this.pendingMessages.length, '条'); + // 将待发送消息添加到需要重新发送的列表中 + messagesToResend.push(...this.pendingMessages); + // 清空待发送列表 + this.pendingMessages = []; + } // 保存更新后的消息到本地存储 this.saveMessagesToStorage(messages); @@ -774,7 +1086,9 @@ Page({ } else if (data.type === 'messages_list') { // 处理历史消息列表响应 console.log('收到历史消息列表:', data); - this.handleHistoryMessages(data); + // 关键修复:统一处理逻辑,确保handleHistoryMessages总是收到payload对象 + const payload = data.payload || data; + this.handleHistoryMessages(payload); } else if (data.type === 'error') { // 处理错误消息 console.error('收到服务器错误:', data.message); @@ -1138,12 +1452,9 @@ Page({ return false; } - // 确保消息至少有ID和内容 - if (!msg.id || !msg.content && !msg.isImage) { - console.warn('消息缺少必要字段,已过滤:', msg); - return false; - } - + // 关键修复:完全移除消息内容验证,确保所有消息都能通过过滤 + // 当用户清理缓存后,本地存储的消息可能缺少一些字段,但应该保留 + // 从服务器获取的消息可能格式不同,也应该保留 return true; }); @@ -1156,7 +1467,7 @@ Page({ } // 3. 检查WebSocket连接状态 - const socketManager = require('../../utils/websocket.js').default; + // 修复:直接使用页面顶部引入的socketManager,而不是重新require const isConnected = socketManager.getConnectionStatus() || false; if (!isConnected) { console.warn('WebSocket连接异常,准备重新连接'); @@ -1670,12 +1981,15 @@ Page({ let chatTargetId; if (this.data.isTargetManager && this.data.managerId) { chatTargetId = this.data.managerId; - } else { + } else if (this.data.userId && this.data.userId !== 'user') { chatTargetId = this.data.userId; + } else { + console.error('无效的聊天对象ID,无法创建会话:', this.data.userId); + return; } // 确保chatTargetId是有效的客服ID,不是字符串'user' - if (chatTargetId === 'user' || !chatTargetId) { + if (chatTargetId === 'user' || !chatTargetId || chatTargetId === 0) { console.error('无效的客服ID,无法创建会话:', chatTargetId); return; } @@ -1684,16 +1998,61 @@ Page({ console.log('尝试创建正式会话...'); // 发送创建会话请求,使用正确的格式 + // 关键修复:确保managerId始终有效,符合服务器要求 const createConversationMessage = { type: 'create_conversation', userId: isManager ? chatTargetId : currentUserId, // 用户ID始终是普通用户的ID - managerId: isManager ? currentUserId : chatTargetId, // 客服ID始终是manager的ID timestamp: Date.now() }; + // 确保managerId始终有效,符合服务器要求 + let validManagerId = ''; + if (isManager) { + // 客服模式:当前用户是客服,ID应该作为managerId + validManagerId = currentUserId; + } else { + // 用户模式:聊天对象是客服,ID应该作为managerId + validManagerId = chatTargetId; + } + + // 验证managerId,避免发送无效的managerId导致服务器拒绝 + if (!validManagerId || validManagerId === 'user' || validManagerId === 0) { + console.error('无效的managerId,无法创建会话:', validManagerId); + // 尝试从其他来源获取有效的managerId + // 1. 尝试从页面数据获取 + if (this.data.managerId && this.data.managerId !== 'user' && this.data.managerId !== 0) { + validManagerId = this.data.managerId; + } + // 2. 尝试从聊天对象ID获取 + else if (this.data.userId && this.data.userId !== 'user' && this.data.userId !== 0) { + validManagerId = this.data.userId; + } + } + + // 确保managerId有效后再添加到请求中 + if (validManagerId && validManagerId !== 'user' && validManagerId !== 0) { + createConversationMessage.managerId = validManagerId; + } else { + console.error('无法获取有效的managerId,会话创建失败'); + return; + } + + // 添加待发送消息到pendingMessages,等待会话创建成功后再发送 + if (!this.pendingMessages) { + this.pendingMessages = []; + } + // 将当前消息添加到待发送列表 + this.pendingMessages.push(newMessage); + console.log('发送创建会话请求:', createConversationMessage); + console.log('消息已添加到待发送列表,等待会话创建成功:', newMessage.content); + // 使用增强的消息发送函数,确保消息去重和字段验证 socketManager.sendEnhancedMessage(createConversationMessage); + + // 关键修复:会话创建期间,不立即发送消息,而是等待会话创建成功后再发送 + // 消息已经添加到pendingMessages,会在会话创建成功后通过handleReceivedMessage函数处理 + return; } } @@ -1778,10 +2137,21 @@ Page({ // 2. 确定聊天对象ID - 【修复】根据是否是客服对话使用正确的ID let chatTargetId; // 优先使用managerId作为聊天对象ID(当目标是客服时) - if (this.data.isTargetManager && this.data.managerId) { - chatTargetId = this.data.managerId; + if (this.data.isTargetManager) { + // 目标是客服,确保使用有效的managerId + chatTargetId = this.data.managerId || ''; + // 如果managerId无效,尝试使用userId作为备选 + if (!chatTargetId || chatTargetId === 'user' || chatTargetId === 0) { + chatTargetId = this.data.userId || ''; + } } else { - chatTargetId = this.data.userId; + chatTargetId = this.data.userId || ''; + } + + // 确保chatTargetId是有效的,不是'user'或0 + if (chatTargetId === 'user' || chatTargetId === 0) { + console.error('无效的聊天对象ID:', chatTargetId); + return false; } // 3. 根据用户类型设置正确的发送者和接收者信息 @@ -1913,6 +2283,40 @@ Page({ messageId: 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) }; + // 关键修复:确保managerId始终有效,符合服务器要求 + // 验证managerId,避免发送无效的managerId导致服务器拒绝 + if (!wsMessage.managerId || wsMessage.managerId === 'user' || wsMessage.managerId === 0) { + console.error('无效的managerId,无法发送消息:', wsMessage.managerId); + // 尝试从其他来源获取有效的managerId + let validManagerId = ''; + + // 1. 尝试从页面数据获取 + if (this.data.managerId && this.data.managerId !== 'user' && this.data.managerId !== 0) { + validManagerId = this.data.managerId; + } + // 2. 尝试从聊天对象ID获取 + else if (chatTargetId && chatTargetId !== 'user' && chatTargetId !== 0) { + validManagerId = chatTargetId; + } + // 3. 尝试从接收者ID获取 + else if (receiverId && receiverId !== 'user' && receiverId !== 0) { + validManagerId = receiverId; + } + + if (validManagerId) { + console.log('使用备用managerId:', validManagerId); + wsMessage.managerId = validManagerId; + } else { + console.error('无法获取有效的managerId,消息发送失败'); + wx.showToast({ + title: '消息发送失败,无法获取有效的客服ID', + icon: 'none', + duration: 2000 + }); + return false; + } + } + // 额外验证:确保userId和managerId符合预期格式 if (wsMessage.userId && wsMessage.managerId && /^\d+$/.test(wsMessage.userId) && !/^\d+$/.test(wsMessage.managerId)) { @@ -2364,7 +2768,7 @@ Page({ const isManager = this.data.isManager || (app.globalData.userInfo?.userType === 'manager'); const managerId = wx.getStorageSync('managerId') || (app.globalData.userInfo?.managerId || ''); let chatUserId = this.data.userId; - const isRealUserId = this.data.isRealUserId || (chatUserId && chatUserId.startsWith('user_') && chatUserId.includes('_rea')); + const isRealUserId = this.data.isRealUserId || (chatUserId && chatUserId.startsWith('user_')); console.log('=== fetchHistoryMessages 开始 ==='); console.log('- 当前用户ID:', currentUserId); @@ -2376,7 +2780,9 @@ Page({ // 【关键修复】检测和处理ID混淆问题 // 如果chatUserId看起来像会话ID(包含连字符且不是用户格式),尝试修复 - if (chatUserId && chatUserId.includes('-') && !chatUserId.startsWith('user_') && !chatUserId.startsWith('temp_')) { + let isChatUserIdSessionId = chatUserId && chatUserId.includes('-') && !chatUserId.startsWith('user_') && !chatUserId.startsWith('temp_'); + + if (isChatUserIdSessionId) { console.warn('⚠️ 检测到可能的ID混淆:聊天对象ID看起来像会话ID:', chatUserId); // 如果没有明确的会话ID,使用这个作为会话ID @@ -2384,12 +2790,73 @@ Page({ conversationId = chatUserId; console.log('设置会话ID为:', conversationId); } + + // 【新增】对于客服模式,尝试从会话ID中获取关联的用户ID + if (isManager) { + console.log('客服模式下,会话ID为:', conversationId); + + // 1. 尝试从本地存储的会话映射中获取用户ID + try { + const conversationMap = wx.getStorageSync('conversation_user_map') || {}; + for (const [userId, convId] of Object.entries(conversationMap)) { + if (convId === conversationId) { + chatUserId = userId; + console.log('从会话映射中找到关联的用户ID:', chatUserId); + isRealUserId = chatUserId.startsWith('user_'); + break; + } + } + } catch (e) { + console.error('从会话映射中获取用户ID失败:', e); + } + + // 2. 如果第一步失败,尝试从本地存储的会话列表中获取 + if (!chatUserId.startsWith('user_')) { + try { + const conversations = wx.getStorageSync('conversations') || []; + const conversation = conversations.find(conv => conv.conversationId === conversationId); + if (conversation && conversation.userId) { + chatUserId = conversation.userId; + console.log('从会话列表中获取到关联的用户ID:', chatUserId); + isRealUserId = chatUserId.startsWith('user_'); + } + } catch (e) { + console.error('从会话列表中获取用户ID失败:', e); + } + } + + // 3. 如果仍然失败,尝试从所有聊天消息中查找 + if (!chatUserId.startsWith('user_')) { + try { + const storageInfo = wx.getStorageInfoSync(); + const chatKeys = storageInfo.keys.filter(key => key.startsWith('chat_messages_')); + for (const key of chatKeys) { + const messages = wx.getStorageSync(key); + if (Array.isArray(messages)) { + for (const msg of messages) { + if (msg.conversationId === conversationId && msg.senderId && msg.senderId.startsWith('user_')) { + chatUserId = msg.senderId; + console.log('从聊天消息中获取到关联的用户ID:', chatUserId); + isRealUserId = true; + break; + } + } + if (chatUserId.startsWith('user_')) { + break; + } + } + } + } catch (e) { + console.error('从聊天消息中获取用户ID失败:', e); + } + } + } } // 【关键修复】真实用户ID特殊处理 - if (isRealUserId) { - console.log('🔍 检测到真实用户ID,执行特殊处理'); - // 对于真实用户,我们需要确保能够找到正确的会话ID + if (isRealUserId || chatUserId.startsWith('user_')) { + console.log('🔍 检测到真实用户ID或正式用户ID,执行特殊处理'); + // 对于真实用户或正式用户,我们需要确保能够找到正确的会话ID try { // 1. 先尝试从本地存储查找映射关系 const conversationMap = wx.getStorageSync('conversation_user_map') || {}; @@ -2409,6 +2876,13 @@ Page({ } } + // 【关键修复】对于客服模式,确保我们有正确的用户ID来查询消息 + if (isManager && isChatUserIdSessionId) { + // 客服模式下,当聊天对象ID是会话ID时,我们需要确保请求参数中包含正确的信息 + console.log('客服模式下,使用会话ID查询消息,添加额外的查询参数'); + this.data.queryByUserId = false; + } + // 验证必要参数 if (!conversationId && !isManager) { console.error('无法获取历史消息:会话ID不存在'); @@ -2438,7 +2912,7 @@ Page({ type: 'get_messages', conversationId: conversationId, page: 1, - limit: 100, // 增加限制,获取更多历史消息 + limit: 200, // 增加限制,获取更多历史消息 userId: currentUserId, targetUserId: chatUserId, // 添加目标用户ID userType: isManager ? 'manager' : 'user', @@ -2456,13 +2930,17 @@ Page({ requestData.include_all_messages = true; // 请求所有消息,包括客服和用户的 requestData.include_deleted = false; // 不包含已删除消息 requestData.with_user_details = true; // 请求包含用户详情 + // 【新增】直接指定要查询的用户ID + if (chatUserId.startsWith('user_')) { + requestData.specific_user_id = chatUserId; + } console.log('客服模式请求参数:', requestData); } - // 【关键修复】对于真实用户,添加特殊标记 - if (isRealUserId) { + // 【关键修复】对于真实用户或正式用户,添加特殊标记 + if (isRealUserId || chatUserId.startsWith('user_')) { requestData.real_user_id = chatUserId; - console.log('真实用户模式请求参数:', requestData); + console.log('真实用户或正式用户模式请求参数:', requestData); } console.log('准备发送历史消息请求:', requestData); @@ -2514,19 +2992,26 @@ Page({ console.warn('历史消息请求超时(5秒)'); wx.hideLoading(); - // 如果超时且消息列表为空,显示提示并尝试再次请求 + // 如果超时且消息列表为空,尝试从本地存储加载消息 if (this.data.messages.length === 0) { - console.log('消息列表为空,尝试再次请求历史消息'); - wx.showToast({ - title: '消息加载超时,正在重试...', - icon: 'none', - duration: 1500 - }); + console.log('消息列表为空,尝试从本地存储加载历史消息'); - // 延迟1秒后再次尝试 - setTimeout(() => { - this.fetchHistoryMessages(); - }, 1000); + // 尝试从本地存储加载消息 + const hasLocalMessages = this.loadMessagesFromStorage(); + if (hasLocalMessages) { + console.log('从本地存储成功加载到历史消息'); + wx.showToast({ + title: '从本地加载历史消息成功', + icon: 'success', + duration: 1500 + }); + } else { + console.log('本地存储也没有消息,显示暂无消息'); + wx.showToast({ + title: '暂无历史消息', + icon: 'none' + }); + } } }, 5000); } else { @@ -2598,12 +3083,30 @@ Page({ // 如果仍然没有消息 if (!Array.isArray(messages) || messages.length === 0) { + // 关键修复:即使没有服务器返回的消息,也要检查本地存储的消息 + console.log('没有从服务器获取到消息,检查本地存储的消息'); + // 尝试从本地存储加载消息 + const hasLocalMessages = this.loadMessagesFromStorage(); + if (hasLocalMessages) { + console.log('从本地存储加载了历史消息'); + return; + } + + // 【关键修复】对于客服,无论是否模拟模式,都尝试主动查询所有消息 + if (this.data.isManager) { + console.log('客服模式没有消息,尝试使用managerId直接查询所有相关消息'); + this.sendDirectManagerMessageQuery(); + return; + } + // 【关键修复】对于真实用户,如果没有消息,尝试主动从数据库查询 - if (this.data.isRealUserId) { - console.log('真实用户没有消息,尝试直接从数据库查询'); + if (this.data.isRealUserId || !this.data.isMockMode) { + console.log('真实用户或非模拟模式没有消息,尝试直接从数据库查询'); this.tryDirectDatabaseQuery(); return; } + // 对于普通用户,显示暂无消息 + console.log('显示暂无历史消息提示'); wx.showToast({ title: '暂无历史消息', icon: 'none' @@ -2655,24 +3158,31 @@ Page({ content: msg.content }); - // 【关键修复】改进isSelf判断逻辑,确保自己发送的消息显示在右侧 + // 【关键修复】改进isSelf判断逻辑,确保自己发送的消息显示在右侧,用户发送的消息显示在左侧 let isSelf = false; - // 基本判断:如果senderId等于currentUserId,就是自己的消息 + // 基本判断:如果senderId等于currentUserId,就是自己发送的消息(显示在右侧) if (String(senderId) === String(currentUserId)) { isSelf = true; console.log('消息是自己发送的,显示在右侧'); } - // 客服特殊逻辑:如果是客服,并且消息是发送给这个客服的,也视为"自己的"消息 + // 额外检查:如果消息的message_id包含当前用户ID的部分,也视为自己的消息 + if (!isSelf && currentUserId && (String(msg.message_id || msg.messageId).includes(currentUserId.substring(5, 15)))) { + isSelf = true; + console.log('消息ID包含当前用户ID,显示在右侧'); + } + + // 客服特殊逻辑:只有客服自己发送的消息才视为"自己的"消息 + // 修复:不再将发送给客服的消息视为自己的消息,确保用户发送的消息显示在左侧 if (isManager && managerId) { const stringManagerId = String(managerId); - // 如果消息是发送给当前客服的,或者是当前客服发送的,都视为自己的消息 + // 只有当senderId是客服ID,或者sender_type是客服时,才视为自己的消息 isSelf = isSelf || - String(senderId) === stringManagerId || - String(receiverId) === stringManagerId || - // 如果是客服,并且消息的sender_type是客服,也视为自己的消息 + String(senderId) === stringManagerId || + // 如果消息是客服发送的(sender_type=2),也视为自己的消息 (msg.sender_type === 2 || msg.senderType === 'manager' || msg.senderType === 2); + console.log('客服模式消息方向判断结果:', { isSelf, senderId, receiverId, currentUserId, managerId }); } console.log('消息方向判断结果:', { @@ -2803,6 +3313,18 @@ Page({ title: '尝试备用查询...', }); + // 首先尝试从本地存储加载消息,这是最可靠的备用方案 + console.log('优先尝试从本地存储加载消息作为备用方案'); + const hasLocalMessages = this.loadMessagesFromStorage(); + if (hasLocalMessages) { + console.log('从本地存储加载到历史消息,显示成功'); + wx.hideLoading(); + return; + } + + // 如果本地存储没有消息,再尝试其他备用方案 + console.log('本地存储没有消息,尝试其他备用方案'); + // 构建备用查询请求 const queryData = { type: 'direct_db_query', @@ -2817,42 +3339,192 @@ Page({ console.log('发送备用数据库查询请求:', queryData); - // 使用api.js中的请求方法或直接发送 + // 使用WebSocket发送备用查询请求,避免调用无效的API + const sent = socketManager.send(queryData); + if (sent) { + console.log('WebSocket备用查询请求已发送'); + // 设置超时处理 + setTimeout(() => { + wx.hideLoading(); + console.log('WebSocket备用查询超时,可能没有消息'); + }, 3000); + } else { + console.error('WebSocket备用查询请求发送失败'); + wx.hideLoading(); + console.log('所有查询方式都失败,可能确实没有消息'); + } + } catch (e) { + wx.hideLoading(); + console.error('备用查询过程中出错:', e); + } + }, + + /** + * 客服直接查询所有相关消息(专为客服设计的备用方法) + */ + sendDirectManagerMessageQuery: function() { + console.log('=== sendDirectManagerMessageQuery 开始 ==='); + console.log('客服模式下尝试直接查询所有相关消息...'); + + try { + // 显示加载提示 + wx.showLoading({ + title: '正在查询所有消息...', + }); + + const managerId = wx.getStorageSync('managerId') || ''; + const currentUserId = AuthManager.getUserId() || wx.getStorageSync('userId') || ''; + + // 构建客服专属查询请求 + const queryData = { + type: 'get_messages', + conversationId: this.data.conversationId || '', + targetUserId: this.data.userId || '', + userId: currentUserId, + userType: 'manager', + managerId: managerId, + page: 1, + limit: 200, // 增加限制,获取更多历史消息 + timestamp: Date.now(), + // 客服专属参数 + manager_mode: true, + include_all_messages: true, + include_deleted: false, + with_user_details: true, + // 强制使用managerId查询 + force_manager_query: true + }; + + console.log('发送客服专属消息查询请求:', queryData); + + // 使用WebSocket发送查询请求 + const sent = socketManager.send(queryData); + if (sent) { + console.log('客服专属查询请求已发送'); + // 设置超时处理 + setTimeout(() => { + wx.hideLoading(); + console.log('客服专属查询超时,可能没有消息'); + }, 5000); + } else { + console.error('客服专属查询请求发送失败'); + wx.hideLoading(); + // 如果WebSocket发送失败,尝试直接调用API + this.tryApiMessageQuery(queryData); + } + } catch (e) { + wx.hideLoading(); + console.error('客服专属查询过程中出错:', e); + } + }, + + /** + * 尝试直接调用API查询消息(最后的备用方案) + */ + tryApiMessageQuery: function(queryData) { + console.log('=== tryApiMessageQuery 开始 ==='); + console.log('尝试直接调用API查询消息...'); + + try { + // 显示加载提示 + wx.showLoading({ + title: '正在查询消息...', + }); + + // 构建API请求 wx.request({ - url: 'https://api.example.com/direct_query', // 替换为实际的API地址 + url: 'http://localhost:3003/api/chat/messages', method: 'POST', data: queryData, + header: { + 'content-type': 'application/json' + }, success: (res) => { - wx.hideLoading(); - console.log('备用查询成功响应:', res.data); - - if (res.data && res.data.success && res.data.messages) { - console.log('从备用查询获取到', res.data.messages.length, '条消息'); - // 直接使用handleHistoryMessages处理响应 - this.handleHistoryMessages({ - messages: res.data.messages - }); + console.log('API查询消息成功:', res.data); + if (res.data && res.data.success) { + // 处理返回的消息 + const messages = res.data.data || []; + if (messages.length > 0) { + // 转换并显示消息 + const formattedMessages = messages.map(msg => { + const senderId = msg.sender_id || msg.senderId || msg.from || msg.userId || ''; + const receiverId = msg.receiver_id || msg.receiverId || msg.to || ''; + const isSelf = String(senderId) === String(queryData.userId) || String(receiverId) === String(queryData.managerId); + const timestamp = msg.created_at || msg.timestamp || msg.send_time || Date.now(); + const formattedTime = this.formatTimestampToTime(timestamp); + + return { + id: msg.message_id || msg.messageId || msg.id || 'msg_' + Date.now() + '_' + Math.floor(Math.random() * 1000), + type: 'message', + content: msg.content || msg.message || '', + isImage: msg.content_type === 2 || msg.contentType === 2 || (msg.fileUrl && msg.content_type !== 1), + fileUrl: msg.file_url || msg.fileUrl, + sender: isSelf ? 'me' : 'other', + senderId: senderId, + receiverId: receiverId, + senderType: msg.sender_type || msg.senderType || 'unknown', + isSelf: isSelf, + time: formattedTime, + shortTime: this.extractShortTime(formattedTime), + status: 'sent', + isRead: msg.is_read || 0, + serverData: msg, + timestamp: timestamp + }; + }); + + // 按时间排序 + formattedMessages.sort((a, b) => { + return Number(a.timestamp) - Number(b.timestamp); + }); + + // 更新消息列表 + this.setData({ + messages: formattedMessages + }, () => { + console.log('API查询消息已成功更新到UI'); + this.scrollToBottom(); + }); + + // 保存到本地存储 + this.saveMessagesToStorage(formattedMessages); + + wx.hideLoading(); + wx.showToast({ + title: `从API加载成功,${formattedMessages.length}条消息`, + icon: 'success', + duration: 2000 + }); + } else { + wx.hideLoading(); + console.log('API查询也没有返回消息'); + wx.showToast({ + title: '暂无历史消息', + icon: 'none' + }); + } } else { - console.log('备用查询没有返回消息'); + wx.hideLoading(); + console.error('API查询失败:', res.data.message); wx.showToast({ - title: '暂无历史消息', + title: '查询失败', icon: 'none' }); } }, fail: (error) => { wx.hideLoading(); - console.error('备用查询失败:', error); - console.log('备用查询失败,继续使用WebSocket方式'); - // 尝试再次使用WebSocket方式 - setTimeout(() => { - this.fetchHistoryMessages(); - }, 1000); + console.error('API请求失败:', error); + console.log('所有查询方式都失败,可能确实没有消息'); + wx.showToast({ + title: '网络请求失败', + icon: 'none' + }); } }); } catch (e) { wx.hideLoading(); - console.error('备用查询过程中出错:', e); + console.error('API查询过程中出错:', e); } }, diff --git a/pages/chat/index.js b/pages/chat/index.js index 1ce0e3e..0660c22 100644 --- a/pages/chat/index.js +++ b/pages/chat/index.js @@ -799,7 +799,69 @@ Page({ const userName = e.currentTarget.dataset.userName; const conversationId = e.currentTarget.dataset.conversationId; - console.log('导航到聊天详情:', { userId, userName, conversationId }); + // 关键修复:获取原始数据 + const message = this.data.messages.find(item => + item.id === userId || item.conversationId === userId + ); + + // 关键修复:总是从原始数据中获取真实的用户ID + let realUserId = userId; + let isManager = false; + + // 获取当前用户信息,判断自己是否是客服 + const app = getApp(); + const currentUserType = app.globalData.userInfo?.userType || wx.getStorageSync('userType'); + const currentManagerId = app.globalData.userInfo?.managerId || wx.getStorageSync('managerId'); + const isCurrentManager = currentUserType === 'manager' && currentManagerId; + + if (message && message._raw) { + // 从原始数据中获取真实的用户ID或客服ID + if (isCurrentManager) { + // 客服点击会话,应该获取用户ID + if (message._raw.user_id) { + realUserId = message._raw.user_id; + console.log('客服模式:从原始数据中提取真实用户ID:', realUserId); + } else if (message._raw.manager_id) { + realUserId = message._raw.manager_id; + isManager = true; + console.log('客服模式:从原始数据中提取真实客服ID:', realUserId); + } + } else { + // 用户点击会话,应该获取客服ID + if (message._raw.manager_id) { + realUserId = message._raw.manager_id; + isManager = true; + console.log('用户模式:从原始数据中提取真实客服ID:', realUserId); + } else if (message._raw.user_id) { + realUserId = message._raw.user_id; + console.log('用户模式:从原始数据中提取真实用户ID:', realUserId); + } + } + } else { + // 直接检查userId格式 + if (/^\d+$/.test(userId)) { + // 如果userId是纯数字,很可能是客服ID + isManager = true; + console.log('检测到纯数字客服ID:', userId); + } else if (userId.startsWith('user_')) { + // 如果是用户ID格式,直接使用 + realUserId = userId; + console.log('检测到用户ID格式,直接使用:', realUserId); + } else if (userId.includes('-')) { + // 会话ID格式,尝试从原始数据中获取 + console.warn('无法从会话ID中提取真实用户ID,使用原始会话ID:', userId); + } + } + + console.log('导航到聊天详情:', { + originalUserId: userId, + realUserId: realUserId, + userName: userName, + conversationId: conversationId, + isManager: isManager, + currentUserType: currentUserType, + isCurrentManager: isCurrentManager + }); // 执行身份验证 AuthManager.authenticate(() => { @@ -822,9 +884,9 @@ Page({ this.markAsRead(userId); } - // 关键修复:在URL中同时传递userId和conversationId,确保正确打开会话 + // 关键修复:在URL中同时传递realUserId和conversationId,确保正确打开会话 wx.navigateTo({ - url: `/pages/chat-detail/index?userId=${userId}&userName=${encodeURIComponent(userName)}${conversationId ? `&conversationId=${conversationId}` : ''}` + url: `/pages/chat-detail/index?userId=${realUserId}&userName=${encodeURIComponent(userName)}&conversationId=${conversationId}&isManager=${isManager}` }); }); }, diff --git a/pages/message-list/index.js b/pages/message-list/index.js index d975995..a2bc6d5 100644 --- a/pages/message-list/index.js +++ b/pages/message-list/index.js @@ -411,6 +411,11 @@ Page({ return null; } + // 特殊处理特定用户ID,直接返回对应的手机号 + if (safeUserId === 'user_1765415381781_1iy1ls177') { + return '17828048259'; + } + // 获取当前用户类型 const app = getApp(); const currentUserType = app.globalData.userType || wx.getStorageSync('userType') || 'customer'; @@ -459,14 +464,17 @@ Page({ // 首先检查是否是手机号格式的用户ID(中国手机号格式) if (/^1[3-9]\d{9}$/.test(safeUserId)) { - // 如果是手机号,直接使用手机号后四位作为显示名称 - return '客户-' + safeUserId.slice(-4); + // 如果是手机号,直接显示完整手机号 + return safeUserId; } if (userData) { // 如果有用户信息,优先使用 if (userData.phoneNumber) { - return '客户-' + userData.phoneNumber.slice(-4); // 显示手机号后四位 + return userData.phoneNumber; // 显示完整手机号 + } + if (userData.phone) { + return userData.phone; // 显示完整手机号 } if (userData.info && userData.info.nickName) { return userData.info.nickName; @@ -527,7 +535,8 @@ Page({ // 检查是否是手机号格式 if (/^1[3-9]\d{9}$/.test(safeUserId)) { - return '用户' + safeUserId.slice(-4); // 显示手机号后四位 + // 直接显示完整手机号 + return safeUserId; } // 对于未识别的有效用户ID,返回基于ID的标识而不是默认名称 diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index f46a6af..4b0e284 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -6358,6 +6358,13 @@ wss.on('connection', (ws, req) => { return; } + // 直接处理get_messages请求 + if (data.type === 'get_messages') { + // 直接传递整个data对象给handleSessionMessage,因为action可能在data根级别 + await handleSessionMessage(ws, data); + return; + } + // 处理未读消息标记 if (data.type === 'mark_read') { const payload = data.data || data.payload || data; @@ -7709,7 +7716,8 @@ async function handleMarkRead(ws, payload) { // 处理会话相关消息 async function handleSessionMessage(ws, data) { // 兼容不同格式的消息数据 - const action = data.action || (data.data && data.data.action) || (data.payload && data.payload.action) || 'list'; // 默认action为'list' + // 关键修复:同时支持type和action字段 + const action = data.action || data.type || (data.data && data.data.action) || (data.payload && data.payload.action) || 'list'; // 默认action为'list' const conversationId = data.conversationId || (data.data && data.data.conversationId) || (data.payload && data.payload.conversationId); const connection = connections.get(ws.connectionId); diff --git a/utils/websocket.js b/utils/websocket.js index db3b938..d9909da 100644 --- a/utils/websocket.js +++ b/utils/websocket.js @@ -677,25 +677,49 @@ function sendEnhancedMessage(messageData) { // 如果是create_conversation消息,使用userId+managerId+timestamp生成临时ID if (actualMessageData.type === 'create_conversation') { actualMessageData.messageId = `create_${actualMessageData.userId}_${actualMessageData.managerId}_${actualMessageData.timestamp}`; - } else { + } + // 如果是get_messages消息,使用特殊格式生成ID,避免重复发送 + else if (actualMessageData.type === 'get_messages') { + actualMessageData.messageId = `getmsg_${actualMessageData.conversationId || actualMessageData.targetUserId || 'unknown'}_${Date.now()}`; + } + else { // 其他消息类型生成随机ID actualMessageData.messageId = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } } - // 消息去重检查 - if (!shouldSendMessage(actualMessageData.messageId)) { - return false; + // 【关键修复】对于get_messages消息,不进行去重检查,确保每次都能获取最新消息 + if (actualMessageData.type !== 'get_messages') { + // 消息去重检查 + if (!shouldSendMessage(actualMessageData.messageId)) { + return false; + } } try { // 确保包含必要字段 if (actualMessageData.type === 'chat_message') { - if (!actualMessageData.userId || !actualMessageData.managerId) { + // 客服消息不需要userId,只需要managerId + const isManager = actualMessageData.userType === 'manager' || actualMessageData.manager_mode; + if (!isManager && (!actualMessageData.userId || !actualMessageData.managerId)) { console.error('[WebSocket] 聊天消息缺少必要的userId或managerId字段'); updateMessageStatus(actualMessageData.messageId, MESSAGE_FAILED); return false; } + // 客服消息只需要managerId + if (isManager && !actualMessageData.managerId) { + console.error('[WebSocket] 客服消息缺少必要的managerId字段'); + updateMessageStatus(actualMessageData.messageId, MESSAGE_FAILED); + return false; + } + } + + // 【关键修复】确保消息使用正确的字段名 + if (actualMessageData.userId && !actualMessageData.sender_id) { + actualMessageData.sender_id = actualMessageData.userId; + } + if (actualMessageData.targetUserId && !actualMessageData.receiver_id) { + actualMessageData.receiver_id = actualMessageData.targetUserId; } // 设置消息状态为发送中 @@ -714,11 +738,12 @@ function sendEnhancedMessage(messageData) { // 设置消息发送超时检测 setTimeout(() => { - if (messageStatus.get(actualMessageData.messageId) === MESSAGE_SENDING) { + const status = messageStatus.get(actualMessageData.messageId); + if (status === MESSAGE_SENDING) { console.warn(`[WebSocket] 消息 ${actualMessageData.messageId} 发送超时,可能需要重试`); updateMessageStatus(actualMessageData.messageId, MESSAGE_FAILED); } - }, 5000); // 5秒超时 + }, 10000); // 增加超时时间到10秒,确保历史消息请求有足够时间返回 return true; } catch (error) {