Browse Source

修复聊天切换联系人发送消息问题,统一时间显示格式

pull/1/head
徐飞洋 3 months ago
parent
commit
6c7b081c70
  1. 419
      pages/chat-detail/index.js
  2. 4
      pages/chat-detail/index.wxml
  3. 2
      pages/chat-detail/index.wxss
  4. 180
      pages/chat/index.js
  5. 38
      utils/api.js

419
pages/chat-detail/index.js

@ -8,13 +8,15 @@ Page({
inputValue: '', inputValue: '',
loading: false, loading: false,
chatTitle: '聊天对象', chatTitle: '聊天对象',
managerPhone: null managerPhone: null,
timer: null
}, },
onLoad: function (options) { onLoad: function (options) {
if (options.id) { if (options.id) {
this.setData({ this.setData({
chatId: options.id chatId: options.id,
managerPhone: options.id // 直接将chatId作为managerPhone使用,因为聊天列表页传递的是manager_phone
}); });
// 如果有传递name参数,直接使用该名称作为聊天标题 // 如果有传递name参数,直接使用该名称作为聊天标题
@ -23,70 +25,35 @@ Page({
chatTitle: decodeURIComponent(options.name) chatTitle: decodeURIComponent(options.name)
}); });
} else { } else {
// 否则从API获取聊天标题 // 如果没有传递name参数,加载聊天标题
this.loadChatTitle(); this.loadChatTitle();
} }
} }
this.loadMessages(); this.loadMessages();
},
// 加载聊天标题
loadChatTitle: function () {
// 从本地存储获取聊天列表
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;
}
}
// 如果还没有获取到,尝试从全局用户信息获取 // 设置定时器,每5秒查询一次数据库同步内容
if (!userPhone) { this.startTimer();
const userInfo = wx.getStorageSync('userInfo'); },
if (userInfo) {
if (userInfo.phoneNumber) {
userPhone = userInfo.phoneNumber;
} else if (userInfo.phone) {
userPhone = userInfo.phone;
}
}
}
// 如果还没有获取到,尝试从直接存储获取 // 页面显示时重新启动定时器
if (!userPhone) { onShow: function () {
if (wx.getStorageSync('phoneNumber')) { if (!this.data.timer) {
userPhone = wx.getStorageSync('phoneNumber'); this.startTimer();
} else if (wx.getStorageSync('phone')) {
userPhone = wx.getStorageSync('phone');
}
} }
},
if (userPhone) { // 加载聊天标题
// 获取聊天列表 loadChatTitle: function () {
API.getChatList(userPhone).then(chatList => { // 直接使用已有的managerPhone获取业务员信息
if (Array.isArray(chatList)) { const managerPhone = this.data.managerPhone;
// 找到当前聊天项 if (managerPhone) {
const currentChat = chatList.find(item => item.id === this.data.chatId); // 获取业务员信息
if (currentChat && currentChat.manager_phone) { API.getSalesPersonnelInfo(managerPhone).then(personnelInfo => {
this.setData({ managerPhone: currentChat.manager_phone }); if (personnelInfo && personnelInfo.alias) {
// 获取业务员信息 this.setData({ chatTitle: personnelInfo.alias });
API.getSalesPersonnelInfo(currentChat.manager_phone).then(personnelInfo => {
if (personnelInfo && personnelInfo.alias) {
this.setData({ chatTitle: personnelInfo.alias });
}
}).catch(error => {
console.error('获取业务员信息失败:', error);
});
}
} }
}).catch(error => { }).catch(error => {
console.error('获取聊天列表失败:', error); console.error('获取业务员信息失败:', error);
}); });
} }
}, },
@ -126,6 +93,108 @@ Page({
}, },
loadMessages: function () { loadMessages: function () {
return new Promise((resolve, reject) => {
this.setData({ loading: true });
// 获取当前用户的手机号
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,
sender_phone: message.sender_phone,
receiver_phone: message.receiver_phone
};
});
// 按时间顺序排序(升序)
processedMessages.sort((a, b) => {
return new Date(a.originalTime) - new Date(b.originalTime);
});
this.setData({
messages: processedMessages,
loading: false,
scrollToView: processedMessages.length > 0 ? 'latest-message' : ''
});
// 如果managerPhone尚未设置,尝试从聊天记录中获取
if (!this.data.managerPhone && processedMessages.length > 0) {
const firstMessage = processedMessages[0];
const managerPhone = (firstMessage.sender_phone === userPhone) ? firstMessage.receiver_phone : firstMessage.sender_phone;
this.setData({ managerPhone: managerPhone });
}
} else {
this.setData({
messages: [],
loading: false
});
}
resolve();
}).catch(error => {
console.error('加载聊天记录失败:', error);
this.setData({
loading: false
});
wx.showToast({
title: '加载聊天记录失败',
icon: 'none'
});
reject(error);
});
});
},
loadMoreMessages: function () {
// 加载更多历史消息
if (this.data.loading) return;
this.setData({ loading: true }); this.setData({ loading: true });
// 获取当前用户的手机号 // 获取当前用户的手机号
@ -163,9 +232,12 @@ Page({
} }
} }
// 使用新添加的API获取聊天记录 // 获取最早的消息时间,用于分页加载
API.getChatMessages(this.data.chatId, userPhone).then(res => { const earliestTime = this.data.messages.length > 0 ? this.data.messages[0].originalTime : null;
if (Array.isArray(res)) {
// 使用API获取更多聊天记录(带分页参数)
API.getChatMessages(this.data.chatId, userPhone, { before: earliestTime }).then(res => {
if (Array.isArray(res) && res.length > 0) {
// 处理每条消息,确定发送者和格式化时间 // 处理每条消息,确定发送者和格式化时间
const processedMessages = res.map(message => { const processedMessages = res.map(message => {
// 判断消息是发送还是接收 // 判断消息是发送还是接收
@ -189,32 +261,39 @@ Page({
}); });
this.setData({ this.setData({
messages: processedMessages, messages: [...processedMessages, ...this.data.messages],
loading: false loading: false
}); });
} else { } else {
this.setData({ this.setData({
messages: [],
loading: false loading: false
}); });
wx.showToast({
title: '没有更多消息了',
icon: 'none'
});
} }
}).catch(error => { }).catch(error => {
console.error('加载聊天记录失败:', error); console.error('加载更多聊天记录失败:', error);
this.setData({ this.setData({
loading: false loading: false
}); });
wx.showToast({ wx.showToast({
title: '加载聊天记录失败', title: '加载更多消息失败',
icon: 'none' icon: 'none'
}); });
}); });
}, },
loadMoreMessages: function () { onInputChange: function (e) {
// 加载更多历史消息 this.setData({
if (this.data.loading) return; inputValue: e.detail.value
});
},
this.setData({ loading: true }); sendMessage: function () {
const content = this.data.inputValue.trim();
if (!content) return;
// 获取当前用户的手机号 // 获取当前用户的手机号
const users = wx.getStorageSync('users') || {}; const users = wx.getStorageSync('users') || {};
@ -251,93 +330,173 @@ Page({
} }
} }
// 获取最早的消息时间,用于分页加载 // 获取客服手机号
const earliestTime = this.data.messages.length > 0 ? this.data.messages[0].originalTime : null; let managerPhone = this.data.managerPhone;
// 使用API获取更多聊天记录(带分页参数) if (!userPhone) {
API.getChatMessages(this.data.chatId, userPhone, { before: earliestTime }).then(res => { wx.showToast({
if (Array.isArray(res) && res.length > 0) { title: '获取用户手机号失败,请重新登录',
// 处理每条消息,确定发送者和格式化时间 icon: 'none'
const processedMessages = res.map(message => { });
// 判断消息是发送还是接收 return;
const sender = (message.sender_phone === userPhone) ? 'me' : 'other'; }
// 格式化时间 // 如果managerPhone尚未设置,尝试从聊天记录中获取
const time = this.formatDateTime(message.created_at); if (!managerPhone && this.data.messages && this.data.messages.length > 0) {
// 从第一条消息中提取与当前用户不同的手机号作为managerPhone
const firstMessage = this.data.messages[0];
if (firstMessage && firstMessage.sender_phone) {
managerPhone = (firstMessage.sender_phone === userPhone) ? firstMessage.receiver_phone : firstMessage.sender_phone;
this.setData({ managerPhone: managerPhone });
}
}
return { // 如果managerPhone仍然不存在,尝试直接从API获取
id: message.id, if (!managerPhone) {
content: message.content, // 显示加载提示
sender: sender, wx.showLoading({
time: time, title: '获取客服信息中...',
originalTime: message.created_at });
};
});
// 按时间顺序排序(升序) // 先尝试从聊天列表获取
processedMessages.sort((a, b) => { API.getChatList(userPhone).then(chatList => {
return new Date(a.originalTime) - new Date(b.originalTime); if (Array.isArray(chatList)) {
// 找到当前聊天项
const currentChat = chatList.find(item => item.id === this.data.chatId);
if (currentChat && currentChat.manager_phone) {
managerPhone = currentChat.manager_phone;
this.setData({ managerPhone: managerPhone });
// 获取到managerPhone后立即发送消息
this.sendMessageAfterGetManagerPhone(userPhone, managerPhone, content);
} else {
// 如果聊天列表中没有找到,尝试直接从聊天记录获取
this.loadMessages().then(() => {
if (this.data.messages.length > 0) {
const firstMessage = this.data.messages[0];
managerPhone = (firstMessage.sender_phone === userPhone) ? firstMessage.receiver_phone : firstMessage.sender_phone;
this.setData({ managerPhone: managerPhone });
this.sendMessageAfterGetManagerPhone(userPhone, managerPhone, content);
} else {
wx.hideLoading();
wx.showToast({
title: '获取客服信息失败,请稍候重试',
icon: 'none'
});
}
}).catch(() => {
wx.hideLoading();
wx.showToast({
title: '获取客服信息失败,请稍候重试',
icon: 'none'
});
});
}
} else {
wx.hideLoading();
wx.showToast({
title: '获取客服信息失败,请稍候重试',
icon: 'none'
});
}
}).catch(() => {
wx.hideLoading();
wx.showToast({
title: '获取客服信息失败,请稍候重试',
icon: 'none'
}); });
});
return;
}
this.setData({ // 正常发送消息
messages: [...processedMessages, ...this.data.messages], this.sendMessageAfterGetManagerPhone(userPhone, managerPhone, content);
loading: false },
// 当获取到managerPhone后发送消息
sendMessageAfterGetManagerPhone: function (userPhone, managerPhone, content) {
// 隐藏加载提示
wx.hideLoading();
// 创建临时消息
const tempId = Date.now();
const newMessage = {
id: tempId,
content: content,
sender: 'me',
time: '刚刚'
};
// 先在本地显示消息
this.setData({
messages: [...this.data.messages, newMessage],
inputValue: '',
scrollToView: 'latest-message'
});
// 调用API发送消息到数据库
API.sendMessage(userPhone, managerPhone, content).then(res => {
console.log('消息发送成功:', res);
// 如果需要,可以更新消息的id为服务器返回的id
if (res && res.data && res.data.id) {
const updatedMessages = this.data.messages.map(msg => {
if (msg.id === tempId) {
return {
...msg,
id: res.data.id
};
}
return msg;
}); });
} else {
this.setData({ this.setData({
loading: false messages: updatedMessages
});
wx.showToast({
title: '没有更多消息了',
icon: 'none'
}); });
} }
}).catch(error => { }).catch(error => {
console.error('加载更多聊天记录失败:', error); console.error('消息发送失败:', error);
this.setData({
loading: false
});
wx.showToast({ wx.showToast({
title: '加载更多消息失败', title: '消息发送失败,请稍后重试',
icon: 'none' icon: 'none'
}); });
}); });
},
onInputChange: function (e) { // 移除模拟对方回复的代码,改为定时器同步数据库内容
this.setData({
inputValue: e.detail.value
});
}, },
sendMessage: function () { // 启动定时器
const content = this.data.inputValue.trim(); startTimer: function () {
if (!content) return; // 清除之前的定时器(如果有)
if (this.data.timer) {
clearInterval(this.data.timer);
}
const newMessage = { // 设置新的定时器,每5秒调用一次loadMessages方法
id: Date.now(), const timer = setInterval(() => {
content: content, this.loadMessages();
sender: 'me', }, 5000);
time: '刚刚'
};
this.setData({ this.setData({
messages: [...this.data.messages, newMessage], timer: timer
inputValue: ''
}); });
},
// 模拟对方回复 // 页面隐藏时清除定时器
setTimeout(() => { onHide: function () {
const reply = { if (this.data.timer) {
id: Date.now() + 1, clearInterval(this.data.timer);
content: '这是一条自动回复', this.setData({
sender: 'other', timer: null
time: '刚刚' });
}; }
},
// 页面卸载时清除定时器
onUnload: function () {
if (this.data.timer) {
clearInterval(this.data.timer);
this.setData({ this.setData({
messages: [...this.data.messages, reply] timer: null
}); });
}, 1000); }
} },
}); });

4
pages/chat-detail/index.wxml

@ -11,7 +11,7 @@
</view> </view>
</view> </view>
<scroll-view class="chat-content" scroll-y bindscrolltolower="loadMoreMessages"> <scroll-view class="chat-content" scroll-y bindscrolltolower="loadMoreMessages" scroll-into-view="{{scrollToView}}" scroll-with-animation="true">
<view class="chat-messages"> <view class="chat-messages">
<block wx:if="{{loading && messages.length === 0}}"> <block wx:if="{{loading && messages.length === 0}}">
<view class="loading">加载中...</view> <view class="loading">加载中...</view>
@ -21,7 +21,7 @@
</block> </block>
<block wx:else> <block wx:else>
<!-- 动态渲染聊天消息 --> <!-- 动态渲染聊天消息 -->
<view wx:for="{{messages}}" wx:key="id" class="message-item {{item.sender}}"> <view wx:for="{{messages}}" wx:key="id" class="message-item {{item.sender}}" id="{{index === messages.length - 1 ? 'latest-message' : 'message-' + item.id}}">
<!-- 对方消息 --> <!-- 对方消息 -->
<view wx:if="{{item.sender === 'other'}}" class="avatar"> <view wx:if="{{item.sender === 'other'}}" class="avatar">
<image src="https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0" mode="aspectFill"></image> <image src="https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0" mode="aspectFill"></image>

2
pages/chat-detail/index.wxss

@ -41,7 +41,7 @@
.chat-content { .chat-content {
flex: 1; flex: 1;
padding: 20rpx; padding: 20rpx 20rpx 120rpx 20rpx; /* 增加底部padding,避免被输入框遮挡 */
overflow-y: auto; overflow-y: auto;
} }

180
pages/chat/index.js

@ -5,18 +5,83 @@ Page({
data: { data: {
chatList: [], chatList: [],
searchKeyword: '', searchKeyword: '',
filteredChatList: [] filteredChatList: [],
timer: null,
debugCount: 0, // 调试信息输出计数器
loginToastShown: false // 登录提示是否已显示
}, },
onLoad: function (options) { onLoad: function (options) {
this.loadChatList(); this.loadChatList();
}, },
loadChatList: function () { // 检查用户是否已登录(与loadChatList中的手机号检查逻辑保持一致)
// 显示加载提示 isUserLoggedIn: function () {
wx.showLoading({ const users = wx.getStorageSync('users') || {};
title: '加载中...', const userId = wx.getStorageSync('userId');
let userPhone = null;
// 与loadChatList中的手机号检查逻辑完全一致
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) {
userPhone = wx.getStorageSync('phoneNumber') || wx.getStorageSync('phone');
}
if (!userPhone) {
const loginInfo = wx.getStorageSync('loginInfo');
if (loginInfo) {
if (loginInfo.phoneNumber) {
userPhone = loginInfo.phoneNumber;
} else if (loginInfo.phone) {
userPhone = loginInfo.phone;
}
}
}
// 只有获取到手机号才视为已登录
return !!userPhone;
},
onShow: function () {
// 只有已登录用户才启动定时器
if (!this.data.timer && this.isUserLoggedIn()) {
this.startTimer();
}
},
startTimer: function () {
// 设置5秒刷新定时器
this.setData({
timer: setInterval(() => {
this.loadChatList();
}, 5000)
}); });
},
loadChatList: function () {
// 增加调试信息计数器
const newDebugCount = this.data.debugCount + 1;
this.setData({ debugCount: newDebugCount });
// 获取用户手机号 - 增强版,增加更多获取途径和调试信息 // 获取用户手机号 - 增强版,增加更多获取途径和调试信息
const users = wx.getStorageSync('users') || {}; const users = wx.getStorageSync('users') || {};
@ -24,12 +89,13 @@ Page({
let userPhone = null; let userPhone = null;
// 添加调试信息,显示当前存储的用户信息 // 添加调试信息,显示当前存储的用户信息
console.log('调试信息 - 登录用户:', { console.log('调试信息 - 登录用户 (第' + newDebugCount + '次):', {
userId: userId, userId: userId,
users: users, users: users,
userInfo: wx.getStorageSync('userInfo'), userInfo: wx.getStorageSync('userInfo'),
phoneNumber: wx.getStorageSync('phoneNumber'), phoneNumber: wx.getStorageSync('phoneNumber'),
phone: wx.getStorageSync('phone') phone: wx.getStorageSync('phone'),
debugCount: newDebugCount
}); });
// 尝试从users中获取手机号(支持不同的键名) // 尝试从users中获取手机号(支持不同的键名)
@ -85,10 +151,35 @@ Page({
// 如果没有手机号,显示错误提示 // 如果没有手机号,显示错误提示
if (!userPhone) { if (!userPhone) {
wx.hideLoading(); wx.hideLoading();
wx.showToast({
title: '请先登录并绑定手机号', // 登录提示只显示一次
icon: 'none' if (!this.data.loginToastShown) {
}); wx.showToast({
title: '请先登录并绑定手机号',
icon: 'none'
});
this.setData({ loginToastShown: true });
}
// 调试信息输出3次后返回首页并关闭定时器
if (newDebugCount >= 3) {
console.log('调试信息已输出3次,准备返回首页并关闭定时器');
// 关闭定时器
if (this.data.timer) {
clearInterval(this.data.timer);
this.setData({ timer: null });
}
// 返回首页
wx.navigateBack({
delta: 1,
success: function() {
console.log('已成功返回首页');
}
});
}
return; return;
} }
@ -119,9 +210,22 @@ Page({
} }
// 确保消息内容存在 // 确保消息内容存在
chatItem.content = chatItem.content || '暂无消息内容'; if (!chatItem.content) {
// 确保时间存在 // 如果没有消息内容,尝试获取该聊天会话的最新消息
chatItem.time = chatItem.time || '刚刚'; try {
const messages = await API.getChatMessages(chatItem.manager_phone, userPhone, { limit: 1 });
if (messages.length > 0) {
chatItem.content = messages[0].content || '暂无消息内容';
} else {
chatItem.content = '暂无消息内容';
}
} catch (error) {
console.error('获取聊天消息失败:', error);
chatItem.content = '暂无消息内容';
}
}
// 格式化时间
chatItem.time = this.formatDateTime(chatItem.time || null);
// 确保unread字段存在 // 确保unread字段存在
chatItem.unread = chatItem.unread || false; chatItem.unread = chatItem.unread || false;
@ -214,5 +318,53 @@ Page({
onPullDownRefresh: function () { onPullDownRefresh: function () {
this.loadChatList(); this.loadChatList();
wx.stopPullDownRefresh(); wx.stopPullDownRefresh();
},
onHide: function () {
if (this.data.timer) {
clearInterval(this.data.timer);
this.setData({
timer: null
});
}
},
onUnload: function () {
if (this.data.timer) {
clearInterval(this.data.timer);
this.setData({
timer: null
});
}
},
// 格式化时间显示
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}`;
}
} }
}); });

38
utils/api.js

@ -3588,6 +3588,44 @@ module.exports = {
}); });
}, },
// 发送聊天消息
sendMessage: function (senderPhone, receiverPhone, content) {
return new Promise((resolve, reject) => {
console.log('API.sendMessage - senderPhone:', senderPhone, 'receiverPhone:', receiverPhone, 'content:', content);
// 验证必要参数
if (!senderPhone || !receiverPhone || !content) {
const error = new Error('发送者电话、接收者电话和消息内容不能为空');
console.error('API.sendMessage - 错误:', error);
reject(error);
return;
}
const requestData = {
sender_phone: senderPhone,
receiver_phone: receiverPhone,
content: content
};
console.log('API.sendMessage - 请求数据:', requestData);
request('/api/chat/send', 'POST', requestData).then(res => {
console.log('API.sendMessage - 响应数据:', res);
// 处理不同格式的响应
if (res && (res.success || res.code === 200)) {
resolve(res);
} else {
const errorMessage = res && res.message ? res.message : '发送消息失败';
reject(new Error(errorMessage));
}
}).catch(error => {
console.error('API.sendMessage - 请求失败:', error);
reject(error);
});
});
},
// 获取聊天列表数据 // 获取聊天列表数据
getChatList: function (userPhone) { getChatList: function (userPhone) {
console.log('API.getChatList - userPhone:', userPhone); console.log('API.getChatList - userPhone:', userPhone);

Loading…
Cancel
Save