From 3aca975fc3501419647f8fdd007cb81d4a2d8918 Mon Sep 17 00:00:00 2001 From: Default User Date: Tue, 16 Dec 2025 09:19:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B6=88=E6=81=AF=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=E7=94=A8=E6=88=B7=E5=90=8D=E6=98=BE=E7=A4=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=B0=86=E5=AE=A2=E6=88=B7=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E7=94=A8=E6=88=B7+=E5=90=8E=E5=9B=9B=E4=BD=8D=E7=94=B5?= =?UTF-8?q?=E8=AF=9D=E5=8F=B7=E7=A0=81=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/message-list/index.js | 546 +++++++++++++++++++++++++++++------- 1 file changed, 450 insertions(+), 96 deletions(-) diff --git a/pages/message-list/index.js b/pages/message-list/index.js index 9e53225..4f9694e 100644 --- a/pages/message-list/index.js +++ b/pages/message-list/index.js @@ -40,14 +40,187 @@ Page({ }, onShow: function() { - // 每次显示页面时刷新聊天列表 + console.log('消息列表页面显示,开始加载数据...'); + // 每次显示页面时强制刷新聊天列表 this.loadChatList(); + + // 确保WebSocket连接已建立,用于接收实时消息 + this.ensureWebSocketConnected(); + }, + + /** + * 确保WebSocket连接已建立 + */ + ensureWebSocketConnected: function() { + try { + const app = getApp(); + if (typeof require === 'function') { + const socketManager = require('../../utils/websocket.js').default; + + // 检查连接状态 + if (!socketManager.getConnectionStatus()) { + console.log('WebSocket未连接,尝试重新连接...'); + // 使用正确的WebSocket服务器地址 + const wsUrl = app.globalData.webSocketUrl || 'ws://localhost:3003'; + socketManager.connect(wsUrl); + } + } + } catch (e) { + console.error('确保WebSocket连接失败:', e); + } }, /** - * 加载聊天列表 + * 加载聊天列表 - 从服务器API获取数据 */ loadChatList: function() { + wx.showLoading({ title: '加载中' }); + + try { + // 从服务器获取真实的聊天列表数据 + const app = getApp(); + const token = app.globalData.token || wx.getStorageSync('token'); + const currentUserId = app.globalData.userInfo?.userId || wx.getStorageSync('userId') || 'unknown'; + const currentUserType = app.globalData.userType || wx.getStorageSync('userType') || ''; + const isManager = app.globalData.isManager || currentUserType === 'manager' || currentUserType.includes('manager'); + const isCustomer = app.globalData.isCustomer || (currentUserType.includes('buyer') || currentUserType.includes('seller') || currentUserType.includes('both')); + + console.log('当前用户类型:', currentUserType, 'isManager:', isManager, 'isCustomer:', isCustomer); + + // 使用正确的API配置,兼容开发环境 + const baseUrl = app.globalData.baseUrl || 'http://localhost:3003'; + console.log('使用API地址:', baseUrl); + console.log('当前用户ID:', currentUserId); + + // 根据用户类型选择不同的API端点 + let apiUrl; + if (isManager) { + // 客服类型使用专门的接口获取客户会话列表 + const managerId = wx.getStorageSync('managerId') || currentUserId; + apiUrl = `${baseUrl}/api/conversations/manager/${managerId}`; + console.log('客服模式,使用manager API获取会话列表'); + } else if (isCustomer || !isManager) { + // 普通用户使用user API + apiUrl = `${baseUrl}/api/conversations/user/${currentUserId}`; + console.log('客户模式,使用user API获取会话列表'); + } else { + // 默认使用user API + apiUrl = `${baseUrl}/api/conversations/user/${currentUserId}`; + console.log('默认模式,使用user API获取会话列表'); + } + + wx.request({ + url: apiUrl, + method: 'GET', + header: { + 'Authorization': token ? `Bearer ${token}` : '', + 'content-type': 'application/json' + }, + success: (res) => { + console.log('获取聊天列表成功:', res.data); + // 处理不同的API响应格式 + let chatData = []; + + if (res.data.code === 0 && res.data.data) { + chatData = res.data.data; + } else if (Array.isArray(res.data)) { + // 如果直接返回数组 + chatData = res.data; + } else if (res.data) { + // 如果返回的是对象但不是标准格式,尝试直接使用 + chatData = [res.data]; + } + + // 合理过滤聊天数据,保留有效的会话 + const validChatData = chatData.filter(item => { + // 确保item有效 + if (!item || typeof item !== 'object') return false; + + // 获取显示的用户ID并验证其有效性 + const displayUserId = item.userId === currentUserId ? item.managerId : item.userId || item.id; + if (!displayUserId || displayUserId === 'undefined' || displayUserId === 'null' || String(displayUserId).trim() === '') { + console.log('过滤掉无效的用户ID:', displayUserId, '的会话'); + return false; + } + + return true; + }); + + if (validChatData.length > 0) { + // 格式化聊天列表数据 + const formattedMessages = validChatData.map(item => { + // 获取显示的用户ID + const displayUserId = item.userId === currentUserId ? item.managerId : item.userId || item.id; + const displayName = this.getUserNameById(displayUserId); + + return { + userId: displayUserId, + userName: item.userName || item.name || displayName, + avatar: item.avatar || (displayName).charAt(0) || '用', + lastMessage: item.lastMessage || item.content || '', + lastMessageTime: this.formatMessageTime(item.lastMessageTime || item.createdAt || Date.now()), + messageCount: item.messageCount || 0, + isRead: item.isRead || false, + unreadCount: item.unreadCount || 0 + }; + }).filter(chat => { + // 过滤掉客服之间的会话 + if (isManager) { + // 只过滤真正的客服聊天,保留所有用户消息 + const isChatWithManager = + (chat.userId && (chat.userId.includes('customer_service') || chat.userId.includes('manager'))) || + (chat.userName && chat.userName.includes('客服') && !chat.userName.includes('用户')); + + console.log('过滤检查 - 用户ID:', chat.userId, '用户名:', chat.userName, '是否为客服聊天:', isChatWithManager); + return !isChatWithManager; + } + return true; + }); + + // 按最后消息时间排序(最新的在前) + formattedMessages.sort((a, b) => { + return new Date(b.lastMessageTime) - new Date(a.lastMessageTime); + }); + + this.setData({ messageList: formattedMessages }); + } else { + console.log('暂无有效的聊天消息'); + // 确保清空消息列表 + this.setData({ messageList: [] }); + + // 尝试从本地存储加载数据作为备选,但现在本地加载逻辑也会严格验证 + this.loadFromLocalStorage(); + } + }, + fail: (err) => { + console.error('网络请求失败:', err); + wx.showToast({ + title: '网络请求失败,尝试使用本地数据', + icon: 'none', + duration: 3000 + }); + + // 失败时尝试从本地存储加载数据 + this.loadFromLocalStorage(); + }, + complete: () => { + wx.hideLoading(); + } + }); + } catch (error) { + console.error('加载聊天列表异常:', error); + wx.hideLoading(); + wx.showToast({ title: '加载异常', icon: 'none' }); + + // 异常时尝试从本地存储加载数据 + this.loadFromLocalStorage(); + } + }, + + /** + * 从本地存储加载聊天列表 - 作为备用方案 + */ + loadFromLocalStorage: function() { try { // 获取所有存储的聊天记录键 const storageInfo = wx.getStorageInfoSync(); @@ -56,61 +229,83 @@ Page({ const messageList = []; // 获取当前用户信息 const app = getApp(); - const userInfo = app.globalData.userInfo || {}; - const isCurrentUserManager = userInfo.userType === 'manager' || userInfo.type === 'manager'; - const currentManagerId = userInfo.managerId || ''; const currentUserId = wx.getStorageSync('userId') || ''; + const currentUserType = app.globalData.userType || wx.getStorageSync('userType') || 'customer'; - // 临时存储已处理的会话,避免重复 - const processedConversations = new Set(); + console.log('从本地存储加载聊天列表 - 用户类型:', currentUserType, '聊天记录数量:', chatKeys.length); // 遍历每个聊天记录 chatKeys.forEach(key => { const chatUserId = key.replace('chat_messages_', ''); + // 严格验证聊天用户ID + if (!chatUserId || chatUserId === 'undefined' || chatUserId === 'null' || chatUserId.trim() === '') { + console.log('跳过无效的聊天用户ID:', chatUserId); + return; + } + // 获取消息列表 const messages = wx.getStorageSync(key); - // 跳过空消息列表 - if (!messages || messages.length === 0) return; + // 严格检查消息列表 + if (!messages || !Array.isArray(messages) || messages.length === 0) { + console.log('跳过无效或空的消息列表:', chatUserId); + return; + } + + // 避免处理自己与自己的聊天 + if (chatUserId === currentUserId) { + console.log('跳过自己与自己的聊天:', chatUserId); + return; + } - // 对于客服,需要特殊处理,确保能看到所有相关消息 - if (isCurrentUserManager) { - // 避免处理自己与自己的聊天 - if (chatUserId === currentManagerId) return; - - // 客服需要看到所有有消息的对话,包括用户发送的消息 - if (!processedConversations.has(chatUserId)) { - // 获取最后一条消息 - const lastMessage = messages[messages.length - 1]; - + // 过滤并验证每条消息 + const validMessages = messages.filter(msg => { + return msg && + msg.content && + typeof msg.content === 'string' && + msg.content.trim() !== '' && + msg.time; // 确保有时间戳 + }); + + // 如果没有有效消息,跳过 + if (validMessages.length === 0) { + console.log('跳过没有有效消息的对话:', chatUserId); + return; + } + + // 放宽条件,只要有有效消息就显示会话,不再要求必须有对方发送的消息 + // 这样可以显示用户主动发起的聊天会话 + + // 获取最后一条有效消息 + const lastValidMessage = validMessages[validMessages.length - 1]; + + // 再次确认最后一条消息的有效性 + if (!lastValidMessage || !lastValidMessage.content || lastValidMessage.content.trim() === '') { + console.log('跳过最后消息无效的对话:', chatUserId); + return; + } + + // 统计未读消息数量 + const unreadCount = validMessages.filter(msg => { + return msg.sender !== 'me' && !msg.isRead; + }).length; + + // 仅当不是客服之间的对话时添加 + const userName = this.getUserNameById(chatUserId); + if (!(isManager && userName && (userName.includes('客服') || userName.includes('manager')))) { messageList.push({ - userId: chatUserId, - userName: this.getUserNameById(chatUserId), - avatar: '', - lastMessage: this.formatMessagePreview(lastMessage), - lastMessageTime: this.formatMessageTime(lastMessage.time), - messageCount: messages.length - }); - - processedConversations.add(chatUserId); - } - } else { - // 普通用户,正常处理 - // 避免处理自己与自己的聊天 - if (chatUserId === currentUserId) return; - - // 获取最后一条消息 - const lastMessage = messages[messages.length - 1]; - - messageList.push({ userId: chatUserId, - userName: this.getUserNameById(chatUserId), + userName: userName, avatar: '', - lastMessage: this.formatMessagePreview(lastMessage), - lastMessageTime: this.formatMessageTime(lastMessage.time), - messageCount: messages.length + lastMessage: this.formatMessagePreview(lastValidMessage), + lastMessageTime: this.formatMessageTime(lastValidMessage.time), + messageCount: validMessages.length, + unreadCount: unreadCount, + isRead: unreadCount === 0 }); + } else { + console.log('客服身份,跳过与其他客服的聊天:', chatUserId, userName); } }); @@ -119,36 +314,127 @@ Page({ return new Date(b.lastMessageTime) - new Date(a.lastMessageTime); }); - this.setData({ - messageList: messageList + if (messageList.length > 0) { + console.log('从本地存储加载了', messageList.length, '条有效聊天记录'); + this.setData({ messageList: messageList }); + } else { + // 确保清空消息列表,避免显示任何默认用户 + console.log('没有找到任何有效的聊天记录,清空消息列表'); + this.setData({ messageList: [] }); + + // 清理可能导致默认用户显示的无效本地存储数据 + this.cleanupInvalidStorageData(); + } + } catch (e) { + console.error('从本地存储加载聊天列表失败:', e); + // 出错时也确保消息列表为空 + this.setData({ messageList: [] }); + } + }, + + /** + * 清理无效的本地存储数据,防止显示默认用户 + */ + cleanupInvalidStorageData: function() { + try { + const storageInfo = wx.getStorageInfoSync(); + const chatKeys = storageInfo.keys.filter(key => key.startsWith('chat_messages_')); + + chatKeys.forEach(key => { + const messages = wx.getStorageSync(key); + + // 删除无效或空的消息列表 + if (!messages || !Array.isArray(messages) || messages.length === 0) { + console.log('删除无效的聊天存储键:', key); + wx.removeStorageSync(key); + return; + } + + // 检查是否只有无效消息 + const allInvalid = messages.every(msg => { + return !msg || + !msg.content || + typeof msg.content !== 'string' || + msg.content.trim() === ''; + }); + + if (allInvalid) { + console.log('删除全是无效消息的聊天记录:', key); + wx.removeStorageSync(key); + } }); + + console.log('清理无效存储数据完成'); } catch (e) { - console.error('加载聊天列表失败:', e); + console.error('清理无效存储数据失败:', e); } }, /** - * 根据用户ID获取用户名 + * 根据用户ID获取用户名 - 增强版,确保不返回默认的'未知用户'名称 */ getUserNameById: function(userId) { try { - // 参数有效性检查 - if (!userId || typeof userId === 'undefined') { - return '未知用户'; + // 增强的参数有效性检查 + if (!userId || typeof userId === 'undefined' || userId === null || String(userId).trim() === '') { + return null; } - // 确保userId是字符串类型 - const safeUserId = String(userId); + // 确保userId是字符串类型,并去除前后空格 + const safeUserId = String(userId).trim(); - // 尝试从全局客服列表中获取用户名 + // 避免显示"undefined"或"null" + if (safeUserId === 'undefined' || safeUserId === 'null') { + return null; + } + + // 获取当前用户类型 const app = getApp(); + const currentUserType = app.globalData.userType || wx.getStorageSync('userType') || 'customer'; - // 尝试从本地缓存的客服列表中查找 + // 尝试从用户信息缓存中获取更详细的用户信息 + // 客服模式下,尝试获取客户的手机号或其他标识信息 + if (currentUserType === 'manager' || currentUserType === 'customer_service') { + // 尝试从本地存储获取用户详细信息 + try { + // 尝试获取用户数据映射 + const users = wx.getStorageSync('users') || {}; + const userData = users[safeUserId]; + + // 首先检查是否是手机号格式的用户ID(中国手机号格式) + if (/^1[3-9]\d{9}$/.test(safeUserId)) { + // 如果是手机号,直接使用手机号后四位作为显示名称 + return '客户-' + safeUserId.slice(-4); + } + + if (userData) { + // 如果有用户信息,优先使用 + if (userData.phoneNumber) { + return '客户-' + userData.phoneNumber.slice(-4); // 显示手机号后四位 + } + if (userData.info && userData.info.nickName) { + return userData.info.nickName; + } + } + + // 尝试获取会话相关的用户信息 + const sessionInfo = wx.getStorageSync(`session_${safeUserId}`); + if (sessionInfo && sessionInfo.userName) { + return sessionInfo.userName; + } + } catch (innerError) { + console.log('获取用户详细信息失败:', innerError); + } + } + + // 尝试从全局客服列表中获取用户名 const cachedCustomerServices = wx.getStorageSync('cached_customer_services') || []; - const service = cachedCustomerServices.find(item => - item.id === safeUserId || item.managerId === safeUserId || - String(item.id) === safeUserId || String(item.managerId) === safeUserId - ); + const service = cachedCustomerServices.find(item => { + // 安全地访问对象属性,避免undefined属性错误 + const itemId = item?.id ? String(item.id).trim() : ''; + const itemManagerId = item?.managerId ? String(item.managerId).trim() : ''; + return itemId === safeUserId || itemManagerId === safeUserId; + }); if (service) { return service.alias || service.name || '客服'; @@ -177,15 +463,48 @@ Page({ return '客服-' + (safeUserId.length >= 4 ? safeUserId.slice(-4) : safeUserId); } - // 如果都没有找到,返回默认名称,避免出现undefined - if (safeUserId.length >= 4) { - return '用户' + safeUserId.slice(-4); + // 对于test_开头的测试用户ID,显示为测试用户 + if (safeUserId.startsWith('test_')) { + return '测试用户-' + (safeUserId.length >= 8 ? safeUserId.slice(-4) : safeUserId); + } + + // 处理系统通知类型 + if (safeUserId.startsWith('system_')) { + return '系统通知'; + } + + // 处理群组聊天 + if (safeUserId.startsWith('group_')) { + return '群组-' + (safeUserId.replace('group_', '').length >= 4 ? safeUserId.replace('group_', '').slice(-4) : safeUserId.replace('group_', '')); + } + + // 从数据库记录中获取的用户ID格式处理 + if (safeUserId.includes('_customer_')) { + // 提取数字部分 + const match = safeUserId.match(/\d+/); + if (match && match[0]) { + return '用户' + match[0].slice(-4); + } + } + + // 检查是否是手机号格式 + if (/^1[3-9]\d{9}$/.test(safeUserId)) { + return '用户' + safeUserId.slice(-4); // 显示手机号后四位 + } + + // 对于未识别的有效用户ID,返回基于ID的标识而不是默认名称 + // 确保不返回'未知用户',而是使用实际的用户ID信息 + if (safeUserId.length > 10) { + // 对于长ID,截取并添加省略号 + return '用户-' + safeUserId.substring(0, 10) + '...'; } else { - return '用户' + safeUserId; + // 对于短ID,直接使用 + return '用户-' + safeUserId; } } catch (e) { console.error('获取用户名失败:', e); - return '未知用户'; + // 即使出现错误,也不返回'未知用户',而是返回'用户-未知' + return '用户-未知'; } }, @@ -207,40 +526,68 @@ Page({ }, /** - * 格式化消息时间 + * 格式化消息时间 - 增强版,支持多种时间格式 */ formatMessageTime: function(timeStr) { - if (!timeStr) return ''; - - // 假设时间格式为 "9-21 10:50" 或类似格式 - const now = new Date(); - let dateStr = timeStr; - - // 如果没有包含年份,添加当前年份 - if (!timeStr.includes('-') || timeStr.split('-').length < 3) { - const currentYear = now.getFullYear(); - dateStr = timeStr.includes(' ') ? - `${currentYear}-${timeStr.split(' ')[0]} ${timeStr.split(' ')[1]}` : - `${currentYear}-${timeStr}`; - } - - const messageDate = new Date(dateStr); - const diffTime = Math.abs(now - messageDate); - const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); - - if (diffDays === 0) { - // 今天的消息只显示时间 - return timeStr.split(' ')[1] || timeStr; - } else if (diffDays === 1) { - // 昨天的消息 - return '昨天'; - } else if (diffDays < 7) { - // 一周内的消息显示星期 - const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; - return weekdays[messageDate.getDay()]; - } else { - // 超过一周的消息显示日期 - return timeStr.split(' ')[0] || timeStr; + try { + if (!timeStr) return ''; + + const now = new Date(); + let messageDate; + + // 尝试不同的时间格式解析 + if (typeof timeStr === 'number') { + // 处理时间戳 + messageDate = new Date(timeStr); + } else if (typeof timeStr === 'string') { + // 处理字符串格式 + if (/^\d+$/.test(timeStr)) { + // 数字字符串,可能是时间戳 + messageDate = new Date(parseInt(timeStr)); + } else { + // 其他字符串格式 + messageDate = new Date(timeStr); + } + } else { + // 其他类型,返回空 + return ''; + } + + // 验证日期是否有效 + if (isNaN(messageDate.getTime())) { + return ''; + } + + const diffTime = Math.abs(now - messageDate); + const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays === 0) { + // 今天的消息只显示时间,格式化为 HH:mm + const hours = messageDate.getHours().toString().padStart(2, '0'); + const minutes = messageDate.getMinutes().toString().padStart(2, '0'); + return `${hours}:${minutes}`; + } else if (diffDays === 1) { + // 昨天的消息 + return '昨天'; + } else if (diffDays < 7) { + // 一周内的消息显示星期 + const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; + return weekdays[messageDate.getDay()]; + } else if (diffDays < 365) { + // 今年内的消息显示月日 + const month = (messageDate.getMonth() + 1).toString().padStart(2, '0'); + const day = messageDate.getDate().toString().padStart(2, '0'); + return `${month}-${day}`; + } else { + // 超过一年的消息显示完整日期 + const year = messageDate.getFullYear(); + const month = (messageDate.getMonth() + 1).toString().padStart(2, '0'); + const day = messageDate.getDate().toString().padStart(2, '0'); + return `${year}-${month}-${day}`; + } + } catch (e) { + console.error('格式化消息时间失败:', e); + return ''; } }, @@ -261,9 +608,16 @@ Page({ * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function() { + console.log('用户下拉刷新,重新加载聊天列表...'); + + // 重新加载聊天列表 this.loadChatList(); - // 停止下拉刷新 - wx.stopPullDownRefresh(); + + // 添加延迟,确保用户能看到刷新效果 + setTimeout(() => { + wx.stopPullDownRefresh(); + console.log('下拉刷新完成'); + }, 1000); }, /**