diff --git a/pages/chat-detail/index.js b/pages/chat-detail/index.js index 00009c8..a660bc5 100644 --- a/pages/chat-detail/index.js +++ b/pages/chat-detail/index.js @@ -16,8 +16,16 @@ Page({ this.setData({ chatId: options.id }); - // 获取聊天标题 - this.loadChatTitle(); + + // 如果有传递name参数,直接使用该名称作为聊天标题 + if (options.name) { + this.setData({ + chatTitle: decodeURIComponent(options.name) + }); + } else { + // 否则从API获取聊天标题 + this.loadChatTitle(); + } } this.loadMessages(); }, @@ -87,37 +95,119 @@ Page({ wx.navigateBack(); }, + // 格式化时间显示 + formatDateTime: function (dateString) { + if (!dateString) return '刚刚'; + + const now = new Date(); + const msgDate = new Date(dateString); + const diffMs = now - msgDate; + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) { + return '刚刚'; + } else if (diffMins < 60) { + return `${diffMins}分钟前`; + } else if (diffHours < 24) { + return `${diffHours}小时前`; + } else if (diffDays < 7) { + return `${diffDays}天前`; + } else { + // 超过一周显示具体日期 + const year = msgDate.getFullYear(); + const month = (msgDate.getMonth() + 1).toString().padStart(2, '0'); + const day = msgDate.getDate().toString().padStart(2, '0'); + const hours = msgDate.getHours().toString().padStart(2, '0'); + const minutes = msgDate.getMinutes().toString().padStart(2, '0'); + return `${year}-${month}-${day} ${hours}:${minutes}`; + } + }, + loadMessages: function () { this.setData({ loading: true }); - // 模拟加载聊天记录 - setTimeout(() => { - const messages = [ - { - id: 1, - content: '您好,有什么可以帮助您的吗?', - sender: 'other', - time: '刚刚' - }, - { - id: 2, - content: '你好,我想咨询一下产品信息', - sender: 'me', - time: '刚刚' - }, - { - id: 3, - content: '当然可以,请问您想了解哪种产品?', - sender: 'other', - time: '5分钟前' + // 获取当前用户的手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + let userPhone = null; + + // 尝试从users中获取手机号 + if (userId && users[userId]) { + if (users[userId].phoneNumber) { + userPhone = users[userId].phoneNumber; + } else if (users[userId].phone) { + userPhone = users[userId].phone; + } + } + + // 如果还没有获取到,尝试从全局用户信息获取 + if (!userPhone) { + const userInfo = wx.getStorageSync('userInfo'); + if (userInfo) { + if (userInfo.phoneNumber) { + userPhone = userInfo.phoneNumber; + } else if (userInfo.phone) { + userPhone = userInfo.phone; } - ]; - + } + } + + // 如果还没有获取到,尝试从直接存储获取 + if (!userPhone) { + if (wx.getStorageSync('phoneNumber')) { + userPhone = wx.getStorageSync('phoneNumber'); + } else if (wx.getStorageSync('phone')) { + userPhone = wx.getStorageSync('phone'); + } + } + + // 使用新添加的API获取聊天记录 + API.getChatMessages(this.data.chatId, userPhone).then(res => { + if (Array.isArray(res)) { + // 处理每条消息,确定发送者和格式化时间 + const processedMessages = res.map(message => { + // 判断消息是发送还是接收 + const sender = (message.sender_phone === userPhone) ? 'me' : 'other'; + + // 格式化时间 + const time = this.formatDateTime(message.created_at); + + return { + id: message.id, + content: message.content, + sender: sender, + time: time, + originalTime: message.created_at + }; + }); + + // 按时间顺序排序(升序) + processedMessages.sort((a, b) => { + return new Date(a.originalTime) - new Date(b.originalTime); + }); + + this.setData({ + messages: processedMessages, + loading: false + }); + } else { + this.setData({ + messages: [], + loading: false + }); + } + }).catch(error => { + console.error('加载聊天记录失败:', error); this.setData({ - messages: messages, loading: false }); - }, 1000); + wx.showToast({ + title: '加载聊天记录失败', + icon: 'none' + }); + }); }, loadMoreMessages: function () { @@ -126,28 +216,92 @@ Page({ this.setData({ loading: true }); - // 模拟加载更多历史消息 - setTimeout(() => { - const moreMessages = [ - { - id: 4, - content: '你好,我想了解一下你们的鸡蛋产品', - sender: 'me', - time: '1小时前' - }, - { - id: 5, - content: '您好,欢迎咨询我们的鸡蛋产品', - sender: 'other', - time: '1小时前' + // 获取当前用户的手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + let userPhone = null; + + // 尝试从users中获取手机号 + if (userId && users[userId]) { + if (users[userId].phoneNumber) { + userPhone = users[userId].phoneNumber; + } else if (users[userId].phone) { + userPhone = users[userId].phone; + } + } + + // 如果还没有获取到,尝试从全局用户信息获取 + if (!userPhone) { + const userInfo = wx.getStorageSync('userInfo'); + if (userInfo) { + if (userInfo.phoneNumber) { + userPhone = userInfo.phoneNumber; + } else if (userInfo.phone) { + userPhone = userInfo.phone; } - ]; - + } + } + + // 如果还没有获取到,尝试从直接存储获取 + if (!userPhone) { + if (wx.getStorageSync('phoneNumber')) { + userPhone = wx.getStorageSync('phoneNumber'); + } else if (wx.getStorageSync('phone')) { + userPhone = wx.getStorageSync('phone'); + } + } + + // 获取最早的消息时间,用于分页加载 + const earliestTime = this.data.messages.length > 0 ? this.data.messages[0].originalTime : null; + + // 使用API获取更多聊天记录(带分页参数) + API.getChatMessages(this.data.chatId, userPhone, { before: earliestTime }).then(res => { + if (Array.isArray(res) && res.length > 0) { + // 处理每条消息,确定发送者和格式化时间 + const processedMessages = res.map(message => { + // 判断消息是发送还是接收 + const sender = (message.sender_phone === userPhone) ? 'me' : 'other'; + + // 格式化时间 + const time = this.formatDateTime(message.created_at); + + return { + id: message.id, + content: message.content, + sender: sender, + time: time, + originalTime: message.created_at + }; + }); + + // 按时间顺序排序(升序) + processedMessages.sort((a, b) => { + return new Date(a.originalTime) - new Date(b.originalTime); + }); + + this.setData({ + messages: [...processedMessages, ...this.data.messages], + loading: false + }); + } else { + this.setData({ + loading: false + }); + wx.showToast({ + title: '没有更多消息了', + icon: 'none' + }); + } + }).catch(error => { + console.error('加载更多聊天记录失败:', error); this.setData({ - messages: [...moreMessages, ...this.data.messages], loading: false }); - }, 1000); + wx.showToast({ + title: '加载更多消息失败', + icon: 'none' + }); + }); }, onInputChange: function (e) { diff --git a/pages/chat-detail/index.wxml b/pages/chat-detail/index.wxml index 308ea8e..5d49a3a 100644 --- a/pages/chat-detail/index.wxml +++ b/pages/chat-detail/index.wxml @@ -13,27 +13,29 @@ - - - - + + 加载中... + + + 暂无聊天记录 + + + + + + + + + + {{item.content}} + {{item.time}} + + + + + - - 您好,有什么可以帮助您的吗? - 刚刚 - - - - - - - 你好,我想咨询一下产品信息 - 刚刚 - - - - - + diff --git a/pages/chat/index.js b/pages/chat/index.js index 2cb7d22..c4be354 100644 --- a/pages/chat/index.js +++ b/pages/chat/index.js @@ -189,11 +189,15 @@ Page({ // 聊天项点击事件 onChatItemTap: function (e) { - const chatId = e.currentTarget.dataset.id; + const index = e.currentTarget.dataset.index; + const chatItem = this.data.filteredChatList[index]; - // 跳转到聊天详情页 + // 使用对方的电话号码作为聊天ID,而不是会话ID + const chatId = chatItem.manager_phone; + + // 跳转到聊天详情页,传递chatId和name参数 wx.navigateTo({ - url: '/pages/chat-detail/index?id=' + chatId, + url: '/pages/chat-detail/index?id=' + chatId + '&name=' + encodeURIComponent(chatItem.name), success: function () { console.log('成功跳转到聊天详情页'); }, diff --git a/pages/chat/index.wxml b/pages/chat/index.wxml index f96a713..fbac199 100644 --- a/pages/chat/index.wxml +++ b/pages/chat/index.wxml @@ -19,6 +19,7 @@ wx:key="id" class="chat-item" data-id="{{item.id}}" + data-index="{{index}}" bindtap="onChatItemTap" > diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index 53d55a6..9bb968f 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -6318,6 +6318,103 @@ app.get('/api/conversations/:conversationId/messages', async (req, res) => { } }); +// REST API接口 - 获取聊天记录(兼容客户端接口) +app.post('/api/chat/messages', async (req, res) => { + try { + const { chat_id, user_phone, before, limit = 50 } = req.body; + + console.log('收到聊天记录请求:', { chat_id, user_phone, before, limit }); + + let query = `SELECT * FROM chat_messages + WHERE (sender_phone = ? AND receiver_phone = ?) + OR (sender_phone = ? AND receiver_phone = ?)`; + let replacements = [user_phone, chat_id, chat_id, user_phone]; + + // 如果有before参数,添加时间过滤 + if (before) { + query += ' AND created_at < ?'; + replacements.push(before); + } + + // 按时间排序,最新的消息在前 + query += ' ORDER BY created_at DESC LIMIT ?'; + replacements.push(parseInt(limit)); + + console.log('执行SQL:', query); + console.log('替换参数:', replacements); + + const [messages] = await sequelize.query(query, { replacements }); + + // 反转顺序,使最早的消息在前 + messages.reverse(); + + console.log('查询到的消息数量:', messages.length); + + res.status(200).json({ + success: true, + code: 200, + data: messages + }); + } catch (error) { + console.error('获取聊天记录失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '获取聊天记录失败: ' + error.message + }); + } +}); + +// REST API接口 - 发送聊天消息 +app.post('/api/chat/send', async (req, res) => { + try { + const { sender_phone, receiver_phone, content } = req.body; + + console.log('收到发送消息请求:', { sender_phone, receiver_phone, content }); + + // 验证必填字段 + if (!sender_phone || !receiver_phone || !content) { + return res.status(400).json({ + success: false, + code: 400, + message: '发送者电话、接收者电话和消息内容不能为空' + }); + } + + // 插入消息到数据库 + const query = `INSERT INTO chat_messages (sender_phone, receiver_phone, content, created_at) + VALUES (?, ?, ?, NOW())`; + const replacements = [sender_phone, receiver_phone, content]; + + console.log('执行SQL:', query); + console.log('替换参数:', replacements); + + const [result] = await sequelize.query(query, { replacements }); + + console.log('消息发送成功,插入结果:', result); + + res.status(200).json({ + success: true, + code: 200, + message: '消息发送成功', + data: { + id: result.insertId, + sender_phone, + receiver_phone, + content, + created_at: new Date().toISOString() + } + }); + } catch (error) { + console.error('发送消息失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '发送消息失败: ' + error.message + }); + } +}); + // REST API接口 - 标记消息已读 app.post('/api/conversations/:conversationId/read', async (req, res) => { try { diff --git a/utils/api.js b/utils/api.js index 8924e84..bd9c4d9 100644 --- a/utils/api.js +++ b/utils/api.js @@ -3508,6 +3508,86 @@ module.exports = { }); }, + // 获取聊天记录 + getChatMessages: function (chatId, userPhone, options = {}) { + return new Promise((resolve, reject) => { + console.log('API.getChatMessages - chatId:', chatId, 'userPhone:', userPhone, 'options:', options); + + // 如果没有传入手机号,尝试从本地存储获取 + if (!userPhone) { + // 获取用户信息,包含手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + + // 尝试从users中获取手机号 + if (userId && users[userId] && users[userId].phoneNumber) { + userPhone = users[userId].phoneNumber; + } else { + // 尝试从全局用户信息获取 + const userInfo = wx.getStorageSync('userInfo'); + if (userInfo && userInfo.phoneNumber) { + userPhone = userInfo.phoneNumber; + } else { + // 尝试从直接存储的phoneNumber获取 + userPhone = wx.getStorageSync('phoneNumber'); + } + } + } + + // 如果没有手机号,直接返回错误 + if (!userPhone) { + const error = new Error('请先登录并绑定手机号'); + console.error('API.getChatMessages - 错误:', error); + reject(error); + return; + } + + // 如果没有chatId,返回空数组 + if (!chatId) { + console.log('API.getChatMessages - 没有chatId,返回空数组'); + resolve([]); + return; + } + + const requestData = { + chat_id: chatId, + user_phone: userPhone + }; + + // 添加分页参数 + if (options.before) { + requestData.before = options.before; + } + if (options.limit) { + requestData.limit = options.limit; + } + + console.log('API.getChatMessages - 请求数据:', requestData); + + request('/api/chat/messages', 'POST', requestData).then(res => { + console.log('API.getChatMessages - 响应数据:', res); + + // 增强数据结构处理 + let messages = []; + if (Array.isArray(res)) { + messages = res; + } else if (res && Array.isArray(res.messages)) { + messages = res.messages; + } else if (res && Array.isArray(res.data)) { + messages = res.data; + } else if (res && res.data && Array.isArray(res.data.messages)) { + messages = res.data.messages; + } + + console.log('API.getChatMessages - 处理后的消息数量:', messages.length); + resolve(messages); + }).catch(error => { + console.error('API.getChatMessages - 请求失败:', error); + reject(error); + }); + }); + }, + // 获取聊天列表数据 getChatList: function (userPhone) { console.log('API.getChatList - userPhone:', userPhone);