145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
|
|
/**
|
||
|
|
* 消息发送服务
|
||
|
|
* 处理消息发送相关逻辑
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { MessageResponse, MessageSegment, ConversationResponse } from '../../types/dto';
|
||
|
|
import { messageService } from '../../services/messageService';
|
||
|
|
import { saveMessage } from '../../services/database';
|
||
|
|
import type { IMessageSendService, IMessageStateManager } from './types';
|
||
|
|
|
||
|
|
export class MessageSendService implements IMessageSendService {
|
||
|
|
private stateManager: IMessageStateManager;
|
||
|
|
private getCurrentUserId: () => string | null;
|
||
|
|
|
||
|
|
constructor(stateManager: IMessageStateManager, getCurrentUserId: () => string | null) {
|
||
|
|
this.stateManager = stateManager;
|
||
|
|
this.getCurrentUserId = getCurrentUserId;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 发送消息
|
||
|
|
*/
|
||
|
|
async sendMessage(
|
||
|
|
conversationId: string,
|
||
|
|
segments: MessageSegment[],
|
||
|
|
options?: { replyToId?: string }
|
||
|
|
): Promise<MessageResponse | null> {
|
||
|
|
try {
|
||
|
|
// 调用API发送
|
||
|
|
const response = await messageService.sendMessage(conversationId, {
|
||
|
|
segments,
|
||
|
|
reply_to_id: options?.replyToId,
|
||
|
|
});
|
||
|
|
|
||
|
|
if (response) {
|
||
|
|
const currentUserId = this.getCurrentUserId();
|
||
|
|
|
||
|
|
// 添加到本地消息列表
|
||
|
|
const existingMessages = this.stateManager.getMessages(conversationId);
|
||
|
|
const newMessage: MessageResponse = {
|
||
|
|
id: response.id,
|
||
|
|
conversation_id: conversationId,
|
||
|
|
sender_id: currentUserId || '',
|
||
|
|
seq: response.seq,
|
||
|
|
segments,
|
||
|
|
created_at: new Date().toISOString(),
|
||
|
|
status: 'normal',
|
||
|
|
};
|
||
|
|
|
||
|
|
const updatedMessages = this.mergeMessagesById(existingMessages, [newMessage]);
|
||
|
|
this.stateManager.setMessages(conversationId, updatedMessages);
|
||
|
|
|
||
|
|
// 关键:立即广播消息列表更新
|
||
|
|
this.stateManager.notifySubscribers({
|
||
|
|
type: 'messages_updated',
|
||
|
|
payload: {
|
||
|
|
conversationId,
|
||
|
|
messages: updatedMessages,
|
||
|
|
newMessage,
|
||
|
|
source: 'send',
|
||
|
|
},
|
||
|
|
timestamp: Date.now(),
|
||
|
|
});
|
||
|
|
|
||
|
|
// 更新会话最后消息
|
||
|
|
this.updateConversationWithNewMessage(conversationId, newMessage);
|
||
|
|
|
||
|
|
// 通知消息已发送
|
||
|
|
this.stateManager.notifySubscribers({
|
||
|
|
type: 'message_sent',
|
||
|
|
payload: { conversationId, message: newMessage },
|
||
|
|
timestamp: Date.now(),
|
||
|
|
});
|
||
|
|
|
||
|
|
// 保存到本地数据库
|
||
|
|
const textContent = segments
|
||
|
|
?.filter((s: any) => s.type === 'text')
|
||
|
|
.map((s: any) => s.data?.text || '')
|
||
|
|
.join('') || '';
|
||
|
|
|
||
|
|
saveMessage({
|
||
|
|
id: response.id,
|
||
|
|
conversationId,
|
||
|
|
senderId: currentUserId || '',
|
||
|
|
content: textContent,
|
||
|
|
type: segments?.find((s: any) => s.type === 'image') ? 'image' : 'text',
|
||
|
|
isRead: true,
|
||
|
|
createdAt: newMessage.created_at,
|
||
|
|
seq: response.seq,
|
||
|
|
status: 'normal',
|
||
|
|
segments,
|
||
|
|
}).catch(console.error);
|
||
|
|
|
||
|
|
return newMessage;
|
||
|
|
}
|
||
|
|
|
||
|
|
return null;
|
||
|
|
} catch (error) {
|
||
|
|
console.error('[MessageSendService] 发送消息失败:', error);
|
||
|
|
this.stateManager.notifySubscribers({
|
||
|
|
type: 'error',
|
||
|
|
payload: { error, context: 'sendMessage' },
|
||
|
|
timestamp: Date.now(),
|
||
|
|
});
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 更新会话的最后消息信息
|
||
|
|
*/
|
||
|
|
private updateConversationWithNewMessage(
|
||
|
|
conversationId: string,
|
||
|
|
message: MessageResponse
|
||
|
|
): void {
|
||
|
|
const conversation = this.stateManager.getConversation(conversationId);
|
||
|
|
const createdAt = message.created_at || new Date().toISOString();
|
||
|
|
|
||
|
|
if (conversation) {
|
||
|
|
// 更新现有会话
|
||
|
|
const updatedConv: ConversationResponse = {
|
||
|
|
...conversation,
|
||
|
|
last_seq: message.seq,
|
||
|
|
last_message: message,
|
||
|
|
last_message_at: createdAt,
|
||
|
|
updated_at: createdAt,
|
||
|
|
};
|
||
|
|
|
||
|
|
this.stateManager.updateConversation(updatedConv);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 按 message_id 合并消息并按 seq 排序
|
||
|
|
*/
|
||
|
|
private mergeMessagesById(base: MessageResponse[], incoming: MessageResponse[]): MessageResponse[] {
|
||
|
|
if (incoming.length === 0) return base;
|
||
|
|
const merged = new Map<string, MessageResponse>();
|
||
|
|
[...base, ...incoming].forEach(msg => {
|
||
|
|
merged.set(String(msg.id), msg);
|
||
|
|
});
|
||
|
|
return Array.from(merged.values()).sort((a, b) => a.seq - b.seq);
|
||
|
|
}
|
||
|
|
}
|