miniprogramme/utils/chat-message-handler.js

301 lines
8.9 KiB
JavaScript
Raw Normal View History

2025-09-12 16:08:17 +08:00
/**
* 聊天消息处理器
* 专门处理WebSocket接收到的聊天相关消息
*/
class ChatMessageHandler {
constructor() {
this.messageListeners = new Map();
this.statusListeners = new Map();
this.conversationListeners = new Map();
}
// 处理WebSocket消息
handleMessage(message) {
console.log('🔄 聊天消息处理器收到消息:', message.type);
switch (message.type) {
case 'new_message':
this.handleNewMessage(message.data);
break;
case 'message_status_update':
this.handleMessageStatusUpdate(message.data);
break;
case 'message_recalled':
this.handleMessageRecalled(message.data);
break;
case 'conversation_update':
this.handleConversationUpdate(message.data);
break;
case 'typing_status':
this.handleTypingStatus(message.data);
break;
case 'read_receipt':
this.handleReadReceipt(message.data);
break;
default:
console.log('未处理的聊天消息类型:', message.type);
}
}
// 处理新消息
handleNewMessage(messageData) {
console.log('📨 收到新消息:', messageData);
// 格式化消息数据
const formattedMessage = this.formatMessage(messageData);
// 通知所有监听器
this.notifyMessageListeners('new_message', formattedMessage);
// 更新会话信息
this.updateConversationLastMessage(formattedMessage);
}
// 处理消息状态更新
handleMessageStatusUpdate(statusData) {
console.log('📊 消息状态更新:', statusData);
this.notifyStatusListeners('status_update', statusData);
}
// 处理消息撤回
handleMessageRecalled(recallData) {
console.log('↩️ 消息被撤回:', recallData);
this.notifyMessageListeners('message_recalled', recallData);
}
// 处理会话更新
handleConversationUpdate(conversationData) {
console.log('💬 会话更新:', conversationData);
this.notifyConversationListeners('conversation_update', conversationData);
}
// 处理输入状态
handleTypingStatus(typingData) {
console.log('⌨️ 输入状态:', typingData);
this.notifyMessageListeners('typing_status', typingData);
}
// 处理已读回执
handleReadReceipt(readData) {
console.log('✅ 已读回执:', readData);
this.notifyStatusListeners('read_receipt', readData);
}
// 格式化消息数据
formatMessage(messageData) {
return {
messageId: messageData.messageId,
senderId: messageData.senderId,
receiverId: messageData.receiverId,
conversationId: messageData.conversationId || this.generateConversationId(messageData.senderId, messageData.receiverId),
chatType: messageData.chatType || 0,
msgType: messageData.msgType || 1,
content: messageData.content || '',
status: messageData.status || 1,
sendTime: messageData.sendTime || new Date().toISOString(),
senderName: messageData.senderName || '',
senderAvatar: messageData.senderAvatar || '',
replyTo: messageData.replyTo || '',
atUsers: messageData.atUsers || [],
extra: messageData.extra || '',
// 客户端扩展字段
isOwn: false, // 需要在使用时设置
displayTime: this.formatDisplayTime(messageData.sendTime),
contentType: this.getContentType(messageData.msgType),
parsedContent: this.parseContent(messageData.content, messageData.msgType)
};
}
// 生成会话ID
generateConversationId(senderId, receiverId) {
// 单聊会话ID生成规则较小的ID在前
const ids = [senderId, receiverId].sort();
return `conv_${ids[0]}_${ids[1]}`;
}
// 格式化显示时间
formatDisplayTime(timeString) {
if (!timeString) return '';
const messageTime = new Date(timeString);
const now = new Date();
const diffMs = now - messageTime;
const diffMinutes = Math.floor(diffMs / (1000 * 60));
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffMinutes < 1) {
return '刚刚';
} else if (diffMinutes < 60) {
return `${diffMinutes}分钟前`;
} else if (diffHours < 24) {
return messageTime.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
} else if (diffDays < 7) {
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return weekdays[messageTime.getDay()];
} else {
return messageTime.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' });
}
}
// 获取内容类型
getContentType(msgType) {
const typeMap = {
1: 'text',
2: 'image',
3: 'voice',
4: 'video',
5: 'file',
6: 'emoji',
7: 'location',
8: 'system',
9: 'recall',
10: 'redpacket'
};
return typeMap[msgType] || 'text';
}
// 解析消息内容
parseContent(content, msgType) {
try {
switch (msgType) {
case 2: // 图片
return { url: content, type: 'image' };
case 3: // 语音
const voiceData = JSON.parse(content);
return { url: voiceData.url, duration: voiceData.duration, type: 'voice' };
case 4: // 视频
const videoData = JSON.parse(content);
return { url: videoData.url, duration: videoData.duration, thumbnail: videoData.thumbnail, type: 'video' };
case 5: // 文件
const fileData = JSON.parse(content);
return { url: fileData.url, name: fileData.name, size: fileData.size, type: 'file' };
case 7: // 位置
const locationData = JSON.parse(content);
return { latitude: locationData.latitude, longitude: locationData.longitude, address: locationData.address, type: 'location' };
default:
return { text: content, type: 'text' };
}
} catch (error) {
console.warn('解析消息内容失败:', error);
return { text: content, type: 'text' };
}
}
// 更新会话最后消息
updateConversationLastMessage(message) {
const conversationUpdate = {
conversationId: message.conversationId,
lastMessage: {
content: this.getDisplayContent(message),
sendTime: message.sendTime,
senderId: message.senderId,
senderName: message.senderName
},
unreadCount: message.isOwn ? 0 : 1 // 如果是自己发的消息未读数为0
};
this.notifyConversationListeners('last_message_update', conversationUpdate);
}
// 获取显示内容
getDisplayContent(message) {
switch (message.msgType) {
case 1: return message.content;
case 2: return '[图片]';
case 3: return '[语音]';
case 4: return '[视频]';
case 5: return '[文件]';
case 6: return '[表情]';
case 7: return '[位置]';
case 8: return message.content;
case 9: return '撤回了一条消息';
case 10: return '[红包]';
default: return message.content;
}
}
// 注册消息监听器
onMessage(event, listener) {
if (!this.messageListeners.has(event)) {
this.messageListeners.set(event, []);
}
this.messageListeners.get(event).push(listener);
}
// 注册状态监听器
onStatus(event, listener) {
if (!this.statusListeners.has(event)) {
this.statusListeners.set(event, []);
}
this.statusListeners.get(event).push(listener);
}
// 注册会话监听器
onConversation(event, listener) {
if (!this.conversationListeners.has(event)) {
this.conversationListeners.set(event, []);
}
this.conversationListeners.get(event).push(listener);
}
// 通知消息监听器
notifyMessageListeners(event, data) {
const listeners = this.messageListeners.get(event);
if (listeners) {
listeners.forEach(listener => {
try {
listener(data);
} catch (error) {
console.error(`消息监听器错误 [${event}]:`, error);
}
});
}
}
// 通知状态监听器
notifyStatusListeners(event, data) {
const listeners = this.statusListeners.get(event);
if (listeners) {
listeners.forEach(listener => {
try {
listener(data);
} catch (error) {
console.error(`状态监听器错误 [${event}]:`, error);
}
});
}
}
// 通知会话监听器
notifyConversationListeners(event, data) {
const listeners = this.conversationListeners.get(event);
if (listeners) {
listeners.forEach(listener => {
try {
listener(data);
} catch (error) {
console.error(`会话监听器错误 [${event}]:`, error);
}
});
}
}
// 清理监听器
removeAllListeners() {
this.messageListeners.clear();
this.statusListeners.clear();
this.conversationListeners.clear();
}
}
// 创建全局实例
const chatMessageHandler = new ChatMessageHandler();
module.exports = chatMessageHandler;