/** * 消息数据映射器 * 负责 Message 模型与 API 响应、数据库记录之间的转换 */ import { MessageModel, MessageSegment, UserModel, } from '../models'; import type { MessageResponse, UserDTO, } from '../../types/dto'; import { safeParseJsonOrUndefined } from '../../database/core/jsonUtils'; import type { CachedMessage } from '../../database/types/CachedMessage'; // 数据库消息记录类型 export interface MessageDbRecord { id: string; conversationId: string; senderId: string; content: string | null; type: string; isRead: number; createdAt: string; seq: number; status: string; segments: string | null; } export class MessageMapper { /** * 将 API 响应转换为应用模型 */ static fromApiResponse(response: MessageResponse): MessageModel { const textSegment = response.segments?.find(s => s.type === 'text'); const content = textSegment?.data?.text || textSegment?.data?.content || ''; return { id: String(response.id || ''), conversationId: String(response.conversation_id || ''), senderId: String(response.sender_id || ''), content, type: 'text', isRead: false, createdAt: new Date(response.created_at || Date.now()), seq: response.seq || 0, status: response.status || 'normal', segments: response.segments || [], replyToId: response.reply_to_id, sender: response.sender ? this.mapSenderFromApi(response.sender) : undefined, }; } /** * 将 API 响应数组转换为应用模型数组 */ static fromApiResponseList(responses: MessageResponse[]): MessageModel[] { return responses.map(r => this.fromApiResponse(r)); } /** * 将数据库记录转换为应用模型 */ static fromDbRecord(record: MessageDbRecord): MessageModel { return { id: record.id, conversationId: record.conversationId, senderId: record.senderId, content: record.content || undefined, type: record.type || 'text', isRead: record.isRead === 1, createdAt: new Date(record.createdAt), seq: record.seq || 0, status: record.status || 'normal', segments: record.segments ? safeParseJsonOrUndefined(record.segments) : undefined, }; } /** * 将数据库记录数组转换为应用模型数组 */ static fromDbRecordList(records: MessageDbRecord[]): MessageModel[] { return records.map(r => this.fromDbRecord(r)); } /** * 将应用模型转换为数据库记录 */ static toDbRecord(model: MessageModel): MessageDbRecord { return { id: model.id, conversationId: model.conversationId, senderId: model.senderId, content: model.content || null, type: model.type, isRead: model.isRead ? 1 : 0, createdAt: model.createdAt.toISOString(), seq: model.seq, status: model.status, segments: model.segments ? JSON.stringify(model.segments) : null, }; } /** * 将应用模型转换为 API 请求数据 */ static toApiRequest(model: Partial): Record { const request: Record = {}; if (model.segments) { request.segments = model.segments; } if (model.content) { request.content = model.content; } if (model.type) { request.message_type = model.type; } if (model.replyToId) { request.reply_to_id = model.replyToId; } return request; } /** * 创建发送消息请求体 */ static createSendRequest( detailType: 'private' | 'group', segments: MessageSegment[], replyToId?: string ): Record { const body: Record = { detail_type: detailType, segments, }; if (replyToId) { body.reply_to_id = replyToId; } return body; } /** * 创建文本消息段 */ static createTextSegment(text: string): MessageSegment { return { type: 'text', data: { text }, }; } /** * 创建图片消息段 */ static createImageSegment(url: string): MessageSegment { return { type: 'image', data: { url }, }; } private static mapSenderFromApi(sender: UserDTO): UserModel { return { id: String(sender.id || ''), username: sender.username || '', nickname: sender.nickname, avatar: sender.avatar || undefined, }; } static toCachedMessage(apiMessage: any, conversationId?: string): CachedMessage { return { id: apiMessage.id, conversationId: apiMessage.conversation_id || conversationId || '', senderId: apiMessage.sender_id, content: apiMessage.content, type: apiMessage.type || 'text', isRead: apiMessage.is_read || false, createdAt: apiMessage.created_at, seq: apiMessage.seq, status: apiMessage.status || 'normal', segments: apiMessage.segments, }; } static toCachedMessages(apiMessages: any[], conversationId?: string): CachedMessage[] { return apiMessages.map(m => this.toCachedMessage(m, conversationId)); } }