221 lines
6.0 KiB
TypeScript
221 lines
6.0 KiB
TypeScript
|
|
/**
|
|||
|
|
* MessageRepository - 消息仓库实现
|
|||
|
|
* 封装所有SQLite数据库操作,不依赖任何UI或状态管理
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import {
|
|||
|
|
saveMessage as dbSaveMessage,
|
|||
|
|
saveMessagesBatch as dbSaveMessagesBatch,
|
|||
|
|
getMessagesByConversation as dbGetMessagesByConversation,
|
|||
|
|
getMaxSeq as dbGetMaxSeq,
|
|||
|
|
getMinSeq as dbGetMinSeq,
|
|||
|
|
getMessagesBeforeSeq as dbGetMessagesBeforeSeq,
|
|||
|
|
markConversationAsRead as dbMarkConversationAsRead,
|
|||
|
|
updateConversationCacheUnreadCount as dbUpdateConversationCacheUnreadCount,
|
|||
|
|
getUserCache as dbGetUserCache,
|
|||
|
|
saveUserCache as dbSaveUserCache,
|
|||
|
|
deleteConversation as dbDeleteConversation,
|
|||
|
|
updateMessageStatus as dbUpdateMessageStatus,
|
|||
|
|
CachedMessage,
|
|||
|
|
} from '../../services/database';
|
|||
|
|
import { Message, Conversation, createMessage, createConversation } from '../../core/entities/Message';
|
|||
|
|
|
|||
|
|
// 数据库消息到领域实体的转换
|
|||
|
|
const cachedMessageToMessage = (cached: CachedMessage): Message => ({
|
|||
|
|
id: cached.id,
|
|||
|
|
conversationId: cached.conversationId,
|
|||
|
|
senderId: cached.senderId,
|
|||
|
|
seq: cached.seq,
|
|||
|
|
segments: cached.segments || [],
|
|||
|
|
createdAt: cached.createdAt,
|
|||
|
|
status: cached.status as Message['status'],
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 领域实体到数据库消息的转换
|
|||
|
|
const messageToCachedMessage = (message: Message, isRead: boolean): CachedMessage => ({
|
|||
|
|
id: message.id,
|
|||
|
|
conversationId: message.conversationId,
|
|||
|
|
senderId: message.senderId,
|
|||
|
|
content: message.segments
|
|||
|
|
.filter((s) => s.type === 'text')
|
|||
|
|
.map((s) => s.data?.text || '')
|
|||
|
|
.join(''),
|
|||
|
|
type: message.segments.find((s) => s.type === 'image') ? 'image' : 'text',
|
|||
|
|
isRead,
|
|||
|
|
createdAt: message.createdAt,
|
|||
|
|
seq: message.seq,
|
|||
|
|
status: message.status,
|
|||
|
|
segments: message.segments,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
class MessageRepository {
|
|||
|
|
// ==================== 消息操作 ====================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 保存单条消息
|
|||
|
|
*/
|
|||
|
|
async saveMessage(message: Message, isRead: boolean): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
const cachedMessage = messageToCachedMessage(message, isRead);
|
|||
|
|
await dbSaveMessage(cachedMessage);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 保存消息失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 批量保存消息
|
|||
|
|
*/
|
|||
|
|
async saveMessages(messages: Message[], isRead: boolean): Promise<void> {
|
|||
|
|
if (!messages || messages.length === 0) return;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const cachedMessages = messages.map((m) => messageToCachedMessage(m, isRead));
|
|||
|
|
await dbSaveMessagesBatch(cachedMessages);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 批量保存消息失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取会话的消息
|
|||
|
|
*/
|
|||
|
|
async getMessagesByConversation(
|
|||
|
|
conversationId: string,
|
|||
|
|
limit: number = 20
|
|||
|
|
): Promise<Message[]> {
|
|||
|
|
try {
|
|||
|
|
const cachedMessages = await dbGetMessagesByConversation(conversationId, limit);
|
|||
|
|
return cachedMessages.map(cachedMessageToMessage);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 获取消息失败:', error);
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取会话的最大消息序号
|
|||
|
|
*/
|
|||
|
|
async getMaxSeq(conversationId: string): Promise<number> {
|
|||
|
|
try {
|
|||
|
|
return await dbGetMaxSeq(conversationId);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 获取最大序号失败:', error);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取会话的最小消息序号
|
|||
|
|
*/
|
|||
|
|
async getMinSeq(conversationId: string): Promise<number> {
|
|||
|
|
try {
|
|||
|
|
return await dbGetMinSeq(conversationId);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 获取最小序号失败:', error);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取指定seq之前的历史消息
|
|||
|
|
*/
|
|||
|
|
async getMessagesBeforeSeq(
|
|||
|
|
conversationId: string,
|
|||
|
|
beforeSeq: number,
|
|||
|
|
limit: number = 20
|
|||
|
|
): Promise<Message[]> {
|
|||
|
|
try {
|
|||
|
|
const cachedMessages = await dbGetMessagesBeforeSeq(conversationId, beforeSeq, limit);
|
|||
|
|
return cachedMessages.map(cachedMessageToMessage);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 获取历史消息失败:', error);
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 标记会话的所有消息为已读
|
|||
|
|
*/
|
|||
|
|
async markConversationAsRead(conversationId: string): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
await dbMarkConversationAsRead(conversationId);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 标记会话已读失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新会话缓存的未读数
|
|||
|
|
*/
|
|||
|
|
async updateConversationUnreadCount(
|
|||
|
|
conversationId: string,
|
|||
|
|
count: number
|
|||
|
|
): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
await dbUpdateConversationCacheUnreadCount(conversationId, count);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 更新会话未读数失败:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新消息状态(如撤回)
|
|||
|
|
*/
|
|||
|
|
async updateMessageStatus(
|
|||
|
|
messageId: string,
|
|||
|
|
status: string,
|
|||
|
|
clearContent: boolean = false
|
|||
|
|
): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
await dbUpdateMessageStatus(messageId, status, clearContent);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 更新消息状态失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 删除会话及其所有消息
|
|||
|
|
*/
|
|||
|
|
async deleteConversation(conversationId: string): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
await dbDeleteConversation(conversationId);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 删除会话失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==================== 用户缓存操作 ====================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取用户缓存
|
|||
|
|
*/
|
|||
|
|
async getUserCache(userId: string): Promise<any | null> {
|
|||
|
|
try {
|
|||
|
|
return await dbGetUserCache(userId);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 获取用户缓存失败:', error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 保存用户缓存
|
|||
|
|
*/
|
|||
|
|
async saveUserCache(user: any): Promise<void> {
|
|||
|
|
try {
|
|||
|
|
await dbSaveUserCache(user);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[MessageRepository] 保存用户缓存失败:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const messageRepository = new MessageRepository();
|
|||
|
|
export default messageRepository;
|