与牧同行-小程序用户端
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.
 

1208 lines
31 KiB

import http from '../../../utils/api'
const baseUrl = require('../../../utils/baseUrl')
// WebSocket实例
let socketOpen = false
let socketMsgQueue = []
let heartbeatInterval = null
let reconnectTimer = null
let isManualClose = false // 是否手动关闭
let heartBeatTimer = null // 心跳定时器
Page({
data: {
baseUrl: baseUrl,
// 专家信息
expertInfo: {},
// 用户信息
userInfo: {
user: {} // 完整用户信息
},
// 对话信息
conversation: {},
// 消息列表
messageList: [],
scrollTop: 0,
scrollAnimate: false,
// 输入相关
inputValue: '',
inputFocus: false,
// 多媒体
showMediaSheet: false,
// 页面状态
showDateDivider: true,
todayDate: '',
loading: false,
loadingMore: false,
// 滚动相关
isScrolling: false,
lastScrollTop: 0,
// 当前对话ID和对方用户ID
currentExpertId: '',
conversationId: '',
otherUserId: '',
// 分页相关
page: 1,
pageSize: 20,
hasMore: true,
total: 0,
// 时间显示间隔
timeInterval: 5,
lastShowTimeStamp: 0,
// 键盘高度
keyboardHeight: 0,
// WebSocket状态
socketConnected: false,
reconnectCount: 0,
maxReconnectCount: 5
},
onLoad: function(options) {
console.log('接收到的参数:', options);
// 设置今天日期
this.setTodayDate();
// 加载用户信息
this.loadUserInfo();
// 获取对方用户ID
if (options.id) {
this.setData({
otherUserId: options.id,
currentExpertId: options.id
});
// 先创建对话,然后获取聊天记录
this.createConversation(options.id);
}
// 监听键盘高度变化
wx.onKeyboardHeightChange(this.onKeyboardHeightChange.bind(this));
},
onShow: function() {
// 页面显示时连接WebSocket
isManualClose = false;
// 确保用户ID和对话ID都存在再连接
const userId = this.getCurrentUserId();
if (userId && this.data.conversationId) {
console.log('页面显示,准备连接WebSocket,用户ID:', userId);
this.connectWebSocket();
} else {
console.log('用户ID或对话ID不存在,稍后再连接', {
userId: userId,
conversationId: this.data.conversationId
});
}
},
onHide: function() {
// 页面隐藏时暂停心跳检查但不关闭连接
console.log('页面隐藏,暂停心跳检查');
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
heartBeatTimer = null;
}
},
onUnload: function() {
// 页面卸载时关闭WebSocket并清理资源
isManualClose = true;
this.closeWebSocket();
wx.offKeyboardHeightChange();
// 清理定时器
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
heartBeatTimer = null;
}
},
// 获取当前用户ID的辅助方法
getCurrentUserId: function() {
const userId = this.data.userInfo?.user?.userId;
console.log('获取到的用户ID:', userId);
return userId;
},
// 创建一对一聊天
createConversation(id) {
wx.showLoading({ title: '加载中...' });
http.create({
data: {
otherUserId: id
},
success: res => {
console.log('创建对话响应:', res);
if (res && res.data) {
// 保存对话ID
const conversationData = res.data;
this.setData({
conversationId: conversationData.id || conversationData.conversationId || id,
conversation: conversationData,
otherUserId: id // 确保对方用户ID正确
});
// 获取聊天记录
this.getChatHistory(id);
// 连接WebSocket(确保用户ID已加载)
const userId = this.getCurrentUserId();
if (userId) {
console.log('用户ID已存在,立即连接WebSocket');
this.connectWebSocket();
} else {
console.log('用户ID尚未加载,等待用户信息加载完成');
}
} else {
wx.hideLoading();
wx.showToast({
title: '创建对话失败',
icon: 'none'
});
}
},
fail: err => {
console.error('创建对话失败:', err);
wx.hideLoading();
wx.showToast({
title: '网络错误',
icon: 'none'
});
}
});
},
// 获取聊天记录
getChatHistory(id) {
http.direct({
data: {
otherUserId: id,
page: this.data.page,
pageSize: this.data.pageSize
},
success: res => {
console.log('获取聊天记录响应:', res);
wx.hideLoading();
if (res && res.code === 200) {
// 处理返回的消息数据
this.processChatHistory(res);
} else {
// 如果没有聊天记录,显示空状态
this.setData({
messageList: [],
loading: false,
hasMore: false
});
}
},
fail: err => {
console.error('获取聊天记录失败:', err);
wx.hideLoading();
wx.showToast({
title: '获取聊天记录失败',
icon: 'none'
});
this.setData({
messageList: [],
loading: false
});
}
});
},
// 处理聊天历史数据
processChatHistory(response) {
let messages = [];
let total = 0;
let hasMore = false;
// 根据实际返回的数据结构调整这里
if (response.rows && Array.isArray(response.rows)) {
messages = response.rows;
total = response.total || messages.length;
} else if (response.data && Array.isArray(response.data)) {
messages = response.data;
total = response.total || messages.length;
} else if (Array.isArray(response)) {
messages = response;
total = messages.length;
}
// 格式化消息数据,适配页面渲染
const formattedMessages = this.formatMessages(messages);
// 处理消息时间显示
const processedMessages = this.processMessageTimes(formattedMessages);
// 判断是否还有更多数据
hasMore = this.data.page * this.data.pageSize < total;
this.setData({
messageList: processedMessages,
loading: false,
loadingMore: false,
hasMore: hasMore,
total: total
}, () => {
// 滚动到底部
setTimeout(() => {
this.scrollToBottom(true);
}, 100);
});
},
// 格式化消息数据
formatMessages(messages) {
if (!messages || messages.length === 0) return [];
const userId = this.getCurrentUserId();
console.log('格式化消息使用的用户ID:', userId);
return messages.map(msg => {
// 判断消息类型
let contentType = msg.contentType || 'text';
let type = msg.type || 'text';
let content = msg.content || '';
// 判断发送者
const isMe = msg.senderId === userId ||
msg.fromUserId === userId ||
msg.userId === userId ||
msg.sendId === userId;
return {
id: msg.id || 'msg_' + Date.now() + Math.random(),
isMe: isMe,
sender: isMe ? 'user' : 'expert',
senderId: msg.senderId || msg.fromUserId || msg.userId,
contentType: contentType,
type: type,
content: content,
timestamp: msg.createTime || msg.timestamp || Date.now(),
status: msg.status || 'success',
...msg
};
});
},
// 加载用户信息
loadUserInfo: function() {
try {
const userInfo = wx.getStorageSync('userInfo');
console.log('从缓存加载的用户信息:', userInfo);
if (userInfo) {
// 处理用户信息,确保正确的结构
let processedUserInfo = { ...this.data.userInfo };
if (userInfo.user) {
// 如果已经有user结构
processedUserInfo = userInfo;
} else if (userInfo.userId) {
// 如果是直接返回的用户数据
processedUserInfo = {
user: userInfo
};
}
// 确保有user对象
if (!processedUserInfo.user) {
processedUserInfo.user = {};
}
// 确保userId存在
if (userInfo.userId && !processedUserInfo.user.userId) {
processedUserInfo.user.userId = userInfo.userId;
}
// 设置用户ID
const userId = processedUserInfo.user?.userId || userInfo.userId;
if (userId) {
processedUserInfo.id = userId;
}
console.log('处理后的用户信息:', processedUserInfo);
this.setData({ userInfo: processedUserInfo });
// 用户信息加载完成后,如果对话ID已存在,连接WebSocket
if (this.data.conversationId && !this.data.socketConnected) {
console.log('用户信息加载完成,连接WebSocket');
this.connectWebSocket();
}
}
} catch (e) {
console.error('加载用户信息失败:', e);
}
},
// 加载更多消息
loadMoreMessages: function() {
if (this.data.loadingMore || !this.data.hasMore || !this.data.otherUserId) return;
this.setData({
loadingMore: true,
page: this.data.page + 1
}, () => {
this.getChatHistory(this.data.otherUserId);
});
},
// ========== WebSocket相关方法 ==========
// 连接WebSocket
connectWebSocket() {
// 如果已有连接,先检查是否可用
if (socketOpen) {
console.log('WebSocket已连接,无需重复连接');
return;
}
const userId = this.getCurrentUserId();
console.log('准备连接WebSocket,用户ID:', userId);
if (!userId) {
console.error('用户ID不存在,无法连接WebSocket');
wx.showToast({
title: '用户信息加载中,请稍后',
icon: 'none'
});
return;
}
// WebSocket连接URL
const basurl = '192.168.101.111:8081'; // 从配置文件获取
const wsUrl = `ws://${basurl}/ws/mini/chat?userId=${userId}`;
console.log('开始连接WebSocket:', wsUrl);
wx.connectSocket({
url: wsUrl,
success: () => {
console.log('WebSocket连接初始化成功');
},
fail: (err) => {
console.error('WebSocket连接初始化失败:', err);
this.reconnectWebSocket();
}
});
// 监听连接打开
wx.onSocketOpen(() => {
console.log('WebSocket连接已打开');
socketOpen = true;
this.setData({ socketConnected: true, reconnectCount: 0 });
// 发送队列中的消息
while (socketMsgQueue.length > 0) {
const msg = socketMsgQueue.shift();
this.sendWebSocketMessage(msg);
}
// 开始心跳
this.startHeartbeat();
});
// 监听收到消息
wx.onSocketMessage((res) => {
try {
console.log('收到原始WebSocket消息:', res.data);
const data = JSON.parse(res.data);
console.log('解析后的消息:', data);
// 处理不同类型的消息
this.handleWebSocketMessage(data);
} catch (e) {
console.error('解析消息失败:', e, '原始数据:', res.data);
}
});
// 监听连接关闭
wx.onSocketClose(() => {
console.log('WebSocket连接已关闭');
socketOpen = false;
this.setData({ socketConnected: false });
// 停止心跳
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
heartBeatTimer = null;
}
// 如果不是手动关闭,尝试重连
if (!isManualClose) {
this.reconnectWebSocket();
}
});
// 监听错误
wx.onSocketError((err) => {
console.error('WebSocket错误:', err);
socketOpen = false;
this.setData({ socketConnected: false });
});
},
// 关闭WebSocket
closeWebSocket() {
if (socketOpen) {
wx.closeSocket({
success: () => {
console.log('WebSocket连接已主动关闭');
}
});
socketOpen = false;
this.setData({ socketConnected: false });
}
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
heartBeatTimer = null;
}
},
// 重连WebSocket
reconnectWebSocket() {
if (this.data.reconnectCount >= this.data.maxReconnectCount) {
console.log('达到最大重连次数,停止重连');
return;
}
if (reconnectTimer) {
clearTimeout(reconnectTimer);
}
reconnectTimer = setTimeout(() => {
console.log(`尝试第${this.data.reconnectCount + 1}次重连`);
this.setData({
reconnectCount: this.data.reconnectCount + 1
});
this.connectWebSocket();
}, 3000); // 3秒后重连
},
// 开始心跳
startHeartbeat() {
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
}
heartBeatTimer = setInterval(() => {
if (socketOpen) {
console.log('发送心跳');
this.sendWebSocketMessage(JSON.stringify({
type: 'heartbeat',
userId: this.getCurrentUserId(),
timestamp: Date.now()
}));
}
}, 30000); // 30秒发送一次心跳
},
// 发送WebSocket消息
sendWebSocketMessage(data) {
if (socketOpen) {
wx.sendSocketMessage({
data: typeof data === 'string' ? data : JSON.stringify(data),
success: () => {
console.log('WebSocket消息发送成功:', data);
},
fail: (err) => {
console.error('WebSocket消息发送失败:', err);
// 加入队列,等待重发
socketMsgQueue.push(data);
}
});
} else {
console.log('WebSocket未连接,消息加入队列');
// 队列存储
socketMsgQueue.push(data);
// 尝试重连
if (!isManualClose) {
this.connectWebSocket();
}
}
},
// 处理WebSocket消息
handleWebSocketMessage(data) {
console.log('处理消息类型:', data.type);
switch (data.type) {
case 'chat': // 聊天消息
case 'message': // 兼容其他类型
// 新消息
this.handleNewMessage(data);
break;
case 'message_status':
// 消息状态更新(已读、送达等)
this.handleMessageStatus(data);
break;
case 'typing':
// 对方正在输入
this.handleTypingStatus(data);
break;
case 'online_status':
// 在线状态变更
this.handleOnlineStatus(data);
break;
case 'heartbeat_ack':
// 心跳响应
console.log('收到心跳响应');
break;
default:
console.log('未知消息类型:', data);
}
},
// 处理新消息
handleNewMessage(data) {
console.log('处理新消息:', data);
// 获取当前用户ID
const currentUserId = this.getCurrentUserId();
// 检查消息是否属于当前对话
const conversationId = data.conversationId || data.chatId || data.roomId;
const senderId = data.senderId || data.fromUserId || data.userId;
const receiverId = data.receiverId || data.toUserId;
console.log('消息归属检查:', {
currentConversationId: this.data.conversationId,
messageConversationId: conversationId,
currentUserId: currentUserId,
senderId: senderId,
receiverId: receiverId,
otherUserId: this.data.otherUserId
});
// 判断是否属于当前对话
let isCurrentConversation = false;
if (conversationId && conversationId === this.data.conversationId) {
isCurrentConversation = true;
} else if (!conversationId) {
// 如果没有对话ID,则根据发送者和接收者判断
// 消息发送者是我,接收者是对方
if (senderId === currentUserId && receiverId === this.data.otherUserId) {
isCurrentConversation = true;
}
// 消息发送者是对方,接收者是我
else if (senderId === this.data.otherUserId && receiverId === currentUserId) {
isCurrentConversation = true;
}
}
if (!isCurrentConversation) {
console.log('消息不属于当前对话,忽略');
return;
}
// 判断发送者是否是当前用户
const isMe = senderId === currentUserId;
console.log('消息归属判断结果:', { isMe, isCurrentConversation });
// 如果是自己发送的消息,检查是否已存在
if (isMe) {
// 检查是否已存在相同ID的消息
const exists = this.data.messageList.some(msg =>
msg.id === data.messageId || msg.id === data.id
);
if (exists) {
console.log('消息已存在,忽略重复添加');
return;
}
}
const newMessage = {
id: data.messageId || data.id || 'msg_' + Date.now() + Math.random(),
isMe: isMe,
sender: isMe ? 'user' : 'expert',
senderId: senderId,
contentType: data.contentType || 'text',
type: data.contentType || 'text',
content: data.content,
timestamp: data.timestamp || Date.now(),
status: 'success'
};
console.log('添加新消息到列表:', newMessage);
// 处理消息时间显示
const { messageList } = this.data;
const processedMessage = this.processSingleMessageTime(newMessage, messageList);
// 添加新消息
messageList.push(processedMessage);
this.setData({ messageList }, () => {
this.scrollToBottom();
// 如果不是自己发的消息,发送已读回执
if (!newMessage.isMe) {
this.sendReadReceipt(newMessage.id);
// 播放提示音
this.playNotificationSound();
// 震动提示
wx.vibrateShort({
type: 'light'
});
}
});
},
// 处理消息状态
handleMessageStatus(data) {
const { messageList } = this.data;
const messageId = data.messageId || data.id;
const index = messageList.findIndex(msg => msg.id === messageId);
if (index !== -1) {
messageList[index].status = data.status || 'success';
this.setData({ messageList });
}
},
// 处理正在输入状态
handleTypingStatus(data) {
const userId = data.userId || data.senderId;
if (userId === this.data.otherUserId) {
this.setData({
'expertInfo.typing': true
});
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(() => {
this.setData({
'expertInfo.typing': false
});
}, 3000);
}
},
// 处理在线状态
handleOnlineStatus(data) {
const userId = data.userId || data.senderId;
if (userId === this.data.otherUserId) {
this.setData({
'expertInfo.online': data.online || data.status === 'online'
});
}
},
// 发送消息 - 修复用户ID获取
sendMessageToServer: function(content, type, messageId) {
const receiverId = this.data.otherUserId;
const senderId = this.getCurrentUserId();
console.log('发送消息参数:', {
senderId: senderId,
receiverId: receiverId,
content: content,
type: type,
messageId: messageId
});
if (!receiverId || !senderId) {
console.error('发送者或接收者ID不存在', { senderId, receiverId });
wx.showToast({
title: '发送失败,用户信息错误',
icon: 'none'
});
return;
}
const message = {
type: 'chat', // 指定为chat类型
receiverId: receiverId, // 接收者ID,就是对方的ID
senderId: senderId, // 发送者ID
content: content, // 消息内容
contentType: type || 'text', // 内容类型
timestamp: Date.now()
};
const messageStr = JSON.stringify(message);
console.log('发送消息到服务器:', JSON.parse(messageStr));
if (!socketOpen) {
console.log('WebSocket未连接,尝试连接');
wx.showToast({
title: '连接中,请稍后',
icon: 'none'
});
// 尝试重连
this.connectWebSocket();
// 加入队列
socketMsgQueue.push(messageStr);
return;
}
this.sendWebSocketMessage(messageStr);
},
// 发送已读回执
sendReadReceipt(messageId) {
if (!socketOpen) return;
this.sendWebSocketMessage(JSON.stringify({
type: 'message_status',
messageId: messageId,
status: 'read',
userId: this.getCurrentUserId(),
receiverId: this.data.otherUserId,
conversationId: this.data.conversationId,
timestamp: Date.now()
}));
},
// 发送正在输入状态
sendTypingStatus() {
if (!socketOpen || !this.data.inputValue) return;
this.sendWebSocketMessage(JSON.stringify({
type: 'typing',
userId: this.getCurrentUserId(),
receiverId: this.data.otherUserId,
conversationId: this.data.conversationId,
timestamp: Date.now()
}));
},
// ========== 消息发送相关方法 ==========
// 发送文本消息
sendTextMessage: function() {
const content = this.data.inputValue.trim();
if (!content) return;
const messageId = 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
console.log('发送文本消息,ID:', messageId);
// 创建本地消息
const newMessage = {
id: messageId,
isMe: true,
sender: 'user',
senderId: this.getCurrentUserId(),
contentType: 'text',
type: 'text',
content: content,
timestamp: Date.now(),
status: 'sending'
};
// 添加到列表
this.addMessageToList(newMessage);
// 清空输入框
this.setData({
inputValue: ''
});
// 通过WebSocket发送到服务器
this.sendMessageToServer(content, 'text', messageId);
// 模拟发送成功回调(实际应该通过WebSocket接收消息状态)
setTimeout(() => {
this.updateMessageStatus(messageId, 'success');
}, 500);
},
// 上传图片后发送
uploadImages: function(tempFilePaths) {
tempFilePaths.forEach((tempFilePath, index) => {
const fileName = `image_${Date.now()}_${index}.jpg`;
this.uploadFile(tempFilePath, fileName, 0, 'image');
});
},
// 上传视频后发送
uploadVideo: function(tempFilePath, thumbPath) {
const fileName = `video_${Date.now()}.mp4`;
this.uploadFile(tempFilePath, fileName, 0, 'video', thumbPath);
},
// 通用文件上传
uploadFile: function(tempFilePath, fileName, fileSize = 0, type = 'file', thumbPath = '') {
const messageId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
const message = {
id: messageId,
isMe: true,
sender: 'user',
type: type,
contentType: type,
content: tempFilePath,
thumb: thumbPath,
fileName: fileName,
fileSize: fileSize,
extension: fileName.split('.').pop().toLowerCase(),
timestamp: Date.now(),
status: 'uploading',
progress: 0
};
this.addMessageToList(message);
this.simulateUpload(messageId, type, tempFilePath);
},
// 上传
simulateUpload: function(messageId, type, tempFilePath) {
let progress = 0;
const uploadInterval = setInterval(() => {
progress += Math.random() * 20 + 10;
if (progress >= 100) {
progress = 100;
clearInterval(uploadInterval);
setTimeout(() => {
// 上传完成,更新消息状态
this.updateMessageStatus(messageId, 'success');
const { messageList } = this.data;
const index = messageList.findIndex(msg => msg.id === messageId);
if (index !== -1) {
delete messageList[index].progress;
this.setData({ messageList });
// 上传完成后,通过WebSocket发送消息
const fileUrl = tempFilePath; // 上传后的URL
this.sendMessageToServer(fileUrl, type, messageId);
}
}, 200);
}
const { messageList } = this.data;
const index = messageList.findIndex(msg => msg.id === messageId);
if (index !== -1) {
messageList[index].progress = Math.min(Math.floor(progress), 100);
this.setData({ messageList });
}
}, 100);
},
// 添加消息到列表
addMessageToList: function(message) {
const { messageList } = this.data;
const processedMessage = this.processSingleMessageTime(message, messageList);
messageList.push(processedMessage);
this.setData({ messageList }, () => {
this.scrollToBottom();
});
},
// 更新消息状态
updateMessageStatus: function(messageId, status) {
const { messageList } = this.data;
const index = messageList.findIndex(msg => msg.id === messageId);
if (index !== -1) {
messageList[index].status = status;
this.setData({ messageList });
}
},
// 输入处理(带防抖)
onInput: function(e) {
this.setData({
inputValue: e.detail.value
});
// 发送正在输入状态(防抖)
clearTimeout(this.typingDebounce);
this.typingDebounce = setTimeout(() => {
this.sendTypingStatus();
}, 500);
},
// 输入框获得焦点
onInputFocus: function() {
this.setData({
inputFocus: true
}, () => {
setTimeout(() => {
this.scrollToBottom();
}, 200);
});
},
// 输入框失去焦点
onInputBlur: function() {
this.setData({
inputFocus: false
});
},
// 清除输入
clearInput: function() {
this.setData({
inputValue: '',
inputFocus: true
});
},
// 滚动事件
onScroll: function(e) {
const scrollTop = e.detail.scrollTop;
this.setData({
lastScrollTop: scrollTop,
isScrolling: true
});
clearTimeout(this.scrollTimer);
this.scrollTimer = setTimeout(() => {
this.setData({ isScrolling: false });
}, 200);
// 加载更多
if (scrollTop <= 100 && !this.data.loadingMore && this.data.hasMore) {
this.loadMoreMessages();
}
},
// 滚动到底部
scrollToBottom: function(animate = true) {
if (this.data.isScrolling) return;
this.setData({
scrollAnimate: animate
}, () => {
setTimeout(() => {
this.setData({
scrollTop: 999999
});
}, 50);
});
},
// 键盘高度变化
onKeyboardHeightChange: function(res) {
this.setData({
keyboardHeight: res.height
});
if (res.height > 0) {
this.setData({ showMediaSheet: false });
setTimeout(() => {
this.scrollToBottom();
}, 100);
}
},
// 显示多媒体选择面板
showMediaActionSheet: function() {
this.setData({
showMediaSheet: true,
inputFocus: false
});
},
// 隐藏多媒体选择面板
hideMediaActionSheet: function() {
this.setData({
showMediaSheet: false
});
},
// 选择图片
chooseImage: function() {
this.hideMediaActionSheet();
wx.chooseImage({
count: 9,
sizeType: ['compressed'],
sourceType: ['album'],
success: (res) => {
this.uploadImages(res.tempFilePaths);
},
fail: () => {
wx.showToast({
title: '选择图片失败',
icon: 'none'
});
}
});
},
// 选择视频
chooseVideo: function() {
this.hideMediaActionSheet();
wx.chooseVideo({
sourceType: ['album'],
compressed: true,
maxDuration: 60,
success: (res) => {
this.uploadVideo(res.tempFilePath, res.thumbTempFilePath);
},
fail: () => {
wx.showToast({
title: '选择视频失败',
icon: 'none'
});
}
});
},
// 预览图片
previewImage: function(e) {
const url = e.currentTarget.dataset.url;
wx.previewImage({
current: url,
urls: [url]
});
},
// 设置今天日期
setTodayDate: function() {
const now = new Date();
const month = now.getMonth() + 1;
const date = now.getDate();
const week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
this.setData({
todayDate: `${month}${date}日 星期${week}`
});
},
// 处理消息时间显示
processMessageTimes: function(messages) {
if (!messages || messages.length === 0) return [];
const sortedMessages = [...messages].sort((a, b) => a.timestamp - b.timestamp);
const processedMessages = [];
let lastShowTime = null;
for (let i = 0; i < sortedMessages.length; i++) {
const msg = { ...sortedMessages[i] };
if (i === 0) {
msg.showTime = true;
lastShowTime = msg.timestamp;
} else {
const timeDiffMinutes = (msg.timestamp - lastShowTime) / (1000 * 60);
msg.showTime = timeDiffMinutes >= this.data.timeInterval;
if (msg.showTime) lastShowTime = msg.timestamp;
}
processedMessages.push(msg);
}
if (lastShowTime) {
this.setData({ lastShowTimeStamp: lastShowTime });
}
return processedMessages;
},
// 处理单条消息时间
processSingleMessageTime: function(message, messageList) {
const msg = { ...message };
if (messageList.length === 0) {
msg.showTime = true;
this.setData({ lastShowTimeStamp: msg.timestamp });
return msg;
}
const lastShowTime = this.data.lastShowTimeStamp;
const timeDiffMinutes = (msg.timestamp - lastShowTime) / (1000 * 60);
msg.showTime = timeDiffMinutes >= this.data.timeInterval;
if (msg.showTime) {
this.setData({ lastShowTimeStamp: msg.timestamp });
}
return msg;
},
// 格式化时间
formatTime: function(timestamp) {
if (!timestamp) return '';
const date = new Date(Number(timestamp));
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
},
// 格式化文件大小
formatFileSize: function(bytes) {
if (!bytes || bytes === 0) return '0B';
const units = ['B', 'KB', 'MB', 'GB'];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return size.toFixed(1) + units[unitIndex];
},
// 播放提示音
playNotificationSound() {
try {
const innerAudioContext = wx.createInnerAudioContext();
innerAudioContext.src = '/assets/sounds/notification.mp3';
innerAudioContext.play();
innerAudioContext.onEnded(() => {
innerAudioContext.destroy();
});
} catch (e) {
console.log('播放提示音失败:', e);
}
},
// 阻止事件冒泡
stopPropagation: function() {}
});