You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

474 lines
14 KiB

// pages/chat/index.js
import socketManager from '../../utils/websocket.js';
Page({
/**
* 页面的初始数据
*/
data: {
messages: [], // 初始为空数组,后续通过数据获取和WebSocket更新
activeTab: 'all',
webSocketUrl: '' // WebSocket服务器地址
},
// WebSocket消息处理函数
handleWebSocketMessage: function(message) {
console.log('聊天列表页面接收到消息:', message);
// 判断是否为新消息 - 支持'new_message'类型(服务器实际发送的类型)
if (message.type === 'new_message') {
const newMessage = message.payload;
this.updateMessageList(newMessage);
} else if (message.type === 'chat_message') {
// 保留原有的'chat_message'类型支持,兼容不同的消息格式
const newMessage = message.data;
this.updateMessageList(newMessage);
}
},
// 更新消息列表
updateMessageList: function(newMessage) {
console.log('更新消息列表:', newMessage);
const messages = [...this.data.messages];
// 确定消息发送者ID - 处理服务器返回的数据格式
const senderId = newMessage.senderId;
const existingIndex = messages.findIndex(item => item.id === senderId);
// 格式化消息时间 - 服务器使用createdAt字段
const now = new Date();
const messageDate = new Date(newMessage.createdAt || newMessage.timestamp || Date.now());
let displayTime = '';
if (messageDate.toDateString() === now.toDateString()) {
// 今天的消息只显示时间
displayTime = messageDate.getHours().toString().padStart(2, '0') + ':' +
messageDate.getMinutes().toString().padStart(2, '0');
} else if (messageDate.toDateString() === new Date(now.getTime() - 86400000).toDateString()) {
// 昨天的消息
displayTime = '昨天';
} else {
// 其他日期显示月日
displayTime = (messageDate.getMonth() + 1) + '月' + messageDate.getDate() + '日';
}
// 获取当前用户ID,确定消息方向
const app = getApp();
const currentUserId = app.globalData.userInfo?.userId || wx.getStorageSync('userId') || 'unknown';
// 确定显示的用户ID(如果是自己发送的消息,显示接收者ID)
const displayUserId = senderId === currentUserId ? newMessage.receiverId : senderId;
if (existingIndex >= 0) {
// 存在该用户的消息,更新内容和时间
messages[existingIndex] = {
...messages[existingIndex],
content: newMessage.content || '',
time: displayTime,
isRead: false
};
// 将更新的消息移到列表顶部
const [updatedMessage] = messages.splice(existingIndex, 1);
messages.unshift(updatedMessage);
} else {
// 新用户消息,添加到列表顶部
// 这里暂时使用ID作为用户名,实际应用中应该从用户信息中获取
const displayName = `用户${displayUserId}`;
messages.unshift({
id: displayUserId,
name: displayName,
avatar: displayName.charAt(0),
content: newMessage.content || '',
time: displayTime,
isRead: false
});
}
// 使用setData更新视图
this.setData({ messages });
// 触发消息提示振动(可选)
wx.vibrateShort();
// 更新TabBar未读消息数(如果需要)
this.updateTabBarBadge();
},
// 更新TabBar未读消息提示 - 使用自定义TabBar兼容方式
updateTabBarBadge: function() {
console.log('更新TabBar未读提示,当前消息数:', this.data.messages.length);
// 检查是否有未读消息
const hasUnread = this.data.messages.some(msg => !msg.isRead);
console.log('是否有未读消息:', hasUnread);
// 对于自定义TabBar,使用全局状态来管理未读标记
const app = getApp();
if (app && app.globalData) {
app.globalData.tabBarBadge = {
chat: hasUnread ? ' ' : ''
};
console.log('已更新全局TabBar未读标记状态:', hasUnread ? '显示' : '隐藏');
// 尝试通过getTabBar方法通知自定义TabBar更新
try {
const tabBar = this.getTabBar();
if (tabBar) {
tabBar.setData({
selected: 'buyer', // 假设聊天页是buyer tab
badge: hasUnread ? ' ' : ''
});
}
} catch (e) {
console.log('TabBar更新失败,将在下一次页面显示时自动更新');
}
}
},
// 清理所有未读消息状态
clearAllUnreadStatus: function() {
console.log('清理所有未读消息状态');
try {
// 1. 更新本地消息列表中的未读状态
const updatedMessages = this.data.messages.map(msg => ({
...msg,
isRead: true
}));
this.setData({
messages: updatedMessages
});
// 2. 对于自定义TabBar,使用全局状态来管理未读标记
const app = getApp();
if (app && app.globalData) {
app.globalData.tabBarBadge = {
chat: ''
};
console.log('已清理全局TabBar未读标记');
// 尝试通过getTabBar方法通知自定义TabBar更新
try {
const tabBar = this.getTabBar();
if (tabBar) {
tabBar.setData({
selected: 'buyer', // 假设聊天页是buyer tab
badge: ''
});
}
} catch (e) {
console.log('TabBar更新失败,将在下一次页面显示时自动更新');
}
}
// 3. 显示成功提示
wx.showToast({
title: '已清除所有未读提示',
icon: 'success',
duration: 2000
});
} catch (error) {
console.error('清理未读状态失败:', error);
wx.showToast({
title: '清理失败',
icon: 'none',
duration: 2000
});
}
},
// 初始化WebSocket连接
initWebSocket: function() {
try {
const app = getApp();
// 使用正确的WebSocket服务器地址 - 开发环境通常是ws://localhost:3003
// 动态构建WebSocket URL,基于全局配置或环境
let wsProtocol = 'ws://';
let wsHost = app.globalData.webSocketUrl || 'localhost:3003';
let wsUrl;
// 如果wsHost已经包含协议,直接使用
if (wsHost.startsWith('ws://') || wsHost.startsWith('wss://')) {
wsUrl = wsHost;
} else {
// 否则添加协议前缀
wsUrl = `${wsProtocol}${wsHost}`;
}
this.setData({ webSocketUrl: wsUrl });
console.log('WebSocket连接初始化,使用地址:', wsUrl);
// 连接WebSocket
socketManager.connect(wsUrl);
// 添加消息监听
socketManager.on('message', this.handleWebSocketMessage.bind(this));
// 添加状态监听,以便调试
socketManager.on('status', (status) => {
console.log('WebSocket状态更新:', status);
});
console.log('聊天列表页面WebSocket已初始化');
} catch (error) {
console.error('初始化WebSocket失败:', error);
wx.showToast({
title: 'WebSocket初始化失败',
icon: 'none'
});
}
},
// 清理WebSocket连接
cleanupWebSocket: function() {
socketManager.off('message', this.handleWebSocketMessage);
},
// 加载聊天列表数据
loadChatList: function() {
wx.showLoading({ title: '加载中' });
try {
// 从服务器获取真实的聊天列表数据
const app = getApp();
const token = app.globalData.token || wx.getStorageSync('token');
// 使用正确的API配置,兼容开发环境
const baseUrl = app.globalData.baseUrl || 'http://localhost:3003';
const currentUserId = app.globalData.userInfo?.userId || wx.getStorageSync('userId') || 'unknown';
console.log('使用API地址:', baseUrl);
console.log('当前用户ID:', currentUserId);
// 使用正确的API端点 - /api/conversations/user/:userId
wx.request({
url: `${baseUrl}/api/conversations/user/${currentUserId}`,
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];
}
if (chatData.length > 0) {
// 格式化聊天列表数据
const formattedMessages = chatData.map(item => {
// 格式化时间
const now = new Date();
const messageDate = new Date(item.lastMessageTime || item.createdAt || Date.now());
let displayTime = '';
if (messageDate.toDateString() === now.toDateString()) {
// 今天的消息只显示时间
displayTime = messageDate.getHours().toString().padStart(2, '0') + ':' +
messageDate.getMinutes().toString().padStart(2, '0');
} else if (messageDate.toDateString() === new Date(now.getTime() - 86400000).toDateString()) {
// 昨天的消息
displayTime = '昨天';
} else {
// 其他日期显示月日
displayTime = (messageDate.getMonth() + 1) + '月' + messageDate.getDate() + '日';
}
// 获取当前用户ID,确定显示哪个用户
const displayUserId = item.userId === currentUserId ? item.managerId : item.userId || item.id;
const displayName = `用户${displayUserId}`;
return {
id: displayUserId,
name: item.userName || item.name || displayName,
avatar: item.avatar || (item.userName || displayName).charAt(0) || '用',
content: item.lastMessage || item.content || '',
time: displayTime,
isRead: item.isRead || false,
unreadCount: item.unreadCount || 0
};
});
this.setData({ messages: formattedMessages });
} else {
console.log('暂无聊天消息');
this.setData({ messages: [] });
}
},
fail: (err) => {
console.error('网络请求失败:', err);
wx.showToast({
title: '网络请求失败,使用本地数据',
icon: 'none',
duration: 3000
});
// 失败时使用模拟数据,确保页面能够正常显示
this.setData({
messages: [
{
id: '1',
name: '系统消息',
avatar: '系',
content: '欢迎使用聊天功能',
time: '刚刚',
isRead: false
}
]
});
},
complete: () => {
wx.hideLoading();
}
});
} catch (error) {
console.error('加载聊天列表异常:', error);
wx.hideLoading();
wx.showToast({ title: '加载异常', icon: 'none' });
}
},
// 返回上一页
onBack: function() {
wx.navigateBack({
delta: 1
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.loadChatList();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
// 设置导航栏右侧按钮的点击事件
wx.showNavigationBarLoading();
},
// 导航栏左侧按钮点击事件
onNavigationBarButtonTap(e) {
if (e.type === 'left') {
this.onBack();
} else if (e.type === 'right') {
// 处理管理按钮点击
wx.showToast({
title: '管理功能待开发',
icon: 'none'
});
}
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
// 页面显示时初始化WebSocket连接
this.initWebSocket();
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
// 页面隐藏时清理WebSocket连接
this.cleanupWebSocket();
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
// 页面卸载时清理WebSocket连接
this.cleanupWebSocket();
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
// 页面分享配置
return {
title: '聊天列表',
path: '/pages/chat/index'
}
},
// 跳转到对话详情页面
navigateToChatDetail: function(e) {
const userId = e.currentTarget.dataset.userId;
const userName = e.currentTarget.dataset.userName;
// 将该聊天标记为已读
const messages = [...this.data.messages];
const messageIndex = messages.findIndex(item => item.id === userId);
if (messageIndex >= 0) {
messages[messageIndex].isRead = true;
messages[messageIndex].unreadCount = 0;
this.setData({ messages });
// 更新TabBar未读消息数
this.updateTabBarBadge();
// 通知服务器已读状态(可选)
this.markAsRead(userId);
}
wx.navigateTo({
url: `/pages/chat-detail/index?userId=${userId}&userName=${encodeURIComponent(userName)}`
});
},
// 通知服务器消息已读
markAsRead: function(userId) {
const app = getApp();
const token = app.globalData.token || wx.getStorageSync('token');
wx.request({
url: `${app.globalData.baseUrl || 'https://your-server.com'}/api/chat/read`,
method: 'POST',
header: {
'Authorization': `Bearer ${token}`,
'content-type': 'application/json'
},
data: {
userId: userId
},
success: (res) => {
console.log('标记消息已读成功:', res.data);
},
fail: (err) => {
console.error('标记消息已读失败:', err);
}
});
}
})