/** * 消息数据服务 - 真实 supadb 集成版本 * 严格遵循 UTS Android 要求,使用真实的 AkSupa 组件 */ import supa from '@/components/supadb/aksupainstance.uts' import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts' import type { Message, MessageType, MessageRecipient, MessageGroup, MessageStats, MessageListParams, SendMessageParams, UserOption, MessageSenderType, MessageReceiverType, MessageContentType, MessageStatus, RecipientStatus, DeliveryMethod, GroupType, MemberRole, MemberStatus } from './msgTypes.uts' // 定义 GroupMember 类型,如果在 msgTypes.uts 中没有的话 type GroupMember = { id : string; group_id : string; user_id : string; role : MemberRole; status : MemberStatus; joined_at : string; updated_at : string; } /** * 消息数据服务- 真实 supadb 版本 * 提供消息系统的所有数据操作 * 统一使用 aksupainstance.uts */ export class MsgDataServiceReal { /** * 获取消息类型列表 */ static async getMessageTypes() : Promise>> { try { const response = await supa .from('ak_message_types') .select('*', {}) .eq('is_active', true) .order('priority', { ascending: false }) .executeAs() if (response.status >= 200 && response.status < 300 && response.data !== null) { console.log(response) return response } // 如果没有数据,返回默认的消息类型 return createErrorResponse>([{ id: 'default', code: 'default', name: '普通消息', description: '默认消息类型', icon: null, color: '#757575', priority: 50, is_system: false, is_active: true, auto_read_timeout: null, retention_days: 30, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }], '无消息类型数据', 200) } catch (error) { // 出错时也返回默认的消息类型 return createErrorResponse>([{ id: 'default', code: 'default', name: '普通消息', description: '默认消息类型', icon: null, color: '#757575', priority: 50, is_system: false, is_active: true, auto_read_timeout: null, retention_days: 30, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }], typeof error === 'string' ? error : error?.message ?? '获取消息类型失败', 200) } } /** * 获取消息列表 */ static async getMessages(params : MessageListParams) : Promise>> { try { let query = supa .from('ak_messages') .select(` *, message_type:ak_message_types(*), recipients:ak_message_recipients(*) `, {}) .eq('is_deleted', false) // 添加筛选条件 if (params.message_type != null) { query = query.eq('message_type', params.message_type as string) } if (params.sender_type != null) { query = query.eq('sender_type', params.sender_type as string) } if (params.sender_id != null) { query = query.eq('sender_id', params.sender_id as string) } if (params.receiver_type != null) { query = query.eq('receiver_type', params.receiver_type as string) } if (params.receiver_id != null) { query = query.eq('receiver_id', params.receiver_id as string) } if (params.status != null) { query = query.eq('status', params.status as string) } if (params.is_urgent != null) { query = query.eq('is_urgent', params.is_urgent as boolean) } const keyword = params.search if (keyword != null && keyword !== '') { query = query.or(`title.ilike.%${keyword}%,content.ilike.%${keyword}%`) } const limit = params.limit ?? 20 const offset = params.offset ?? 0 // 分页和排序 const page = Math.floor(offset / limit) + 1 const response = await query .order('created_at', { ascending: false }) .range(offset, offset + limit - 1) .executeAs() // .execute() console.log(response) return response } catch (error) { console.log(error) return createErrorResponse>([], typeof error === 'string' ? error : error?.message ?? '获取消息列表失败') } } /** * 获取单条消息详情 */ static async getMessageById(id : string) : Promise> { try { const response = await supa .from('ak_messages') .select(` *, message_type:ak_message_types(*), recipients:ak_message_recipients(*) `, {}) .eq('id', id) .single() .executeAs() return response } catch (error) { return { status: 500, data: null, error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取消息内容失败'), origin: null, headers: {} } as AkReqResponse } } /** * 发送消�? */ static async sendMessage(params : SendMessageParams) : Promise> { try { // 构建消息数据 const messageData = { message_type_id: params.message_type_id, sender_type: params.sender_type, sender_id: params.sender_id, sender_name: params.sender_name, receiver_type: params.receiver_type, receiver_id: params.receiver_id, title: params.title, content: params.content, content_type: params.content_type !== null ? params.content_type : 'text', attachments: params.attachments, media_urls: params.media_urls, metadata: params.metadata, is_urgent: params.is_urgent !== null ? params.is_urgent : false, scheduled_at: params.scheduled_at, expires_at: params.expires_at, status: 'pending', is_deleted: false, created_at: new Date().toISOString(), updated_at: new Date().toISOString() } // 插入消息 const response = await supa .from('ak_messages') .insert(messageData) .single() .executeAs() if (response.status >= 200 && response.status < 300) { const message = response.data as Message // 创建接收记录 // 批量接收人安全判断 const receiversArr = params.receivers ?? [] if (Array.isArray(receiversArr) && receiversArr.length > 0) { const recipients = receiversArr.map(receiverId => ({ message_id: message.id, receiver_type: params.receiver_type, receiver_id: receiverId, status: 'unread', is_deleted: false, created_at: new Date().toISOString(), updated_at: new Date().toISOString() })) for (const rec of recipients) { await supa .from('ak_message_recipients') .insert(rec) .executeAs() } } return response } else { return response } } catch (error) { return { status: 500, data: null, error: new UniError(typeof error === 'string' ? error : error?.message ?? '发送消息失败'), headers: {}, total: null, page: null, limit: null, hasmore: false, origin: null } } } /** * 标记消息为已读 */ static async markAsRead(messageId : string, receiverId : string) : Promise> { try { // 验证参数不能为空 if (messageId == null || messageId === '' || receiverId == null || receiverId === '' || receiverId.trim() === '') { return createErrorResponse( false, '参数错误:消息ID和接收者ID不能为空' ) } const response = await supa .from('ak_message_recipients') .update({ status: 'read', read_at: new Date().toISOString(), updated_at: new Date().toISOString() }) .eq('message_id', messageId) .eq('recipient_id', receiverId) .executeAs>() return { status: response.status, data: Array.isArray(response.data) , headers: response.headers, error: response.error, total: response.total, page: response.page, limit: response.limit, hasmore: response.hasmore, origin: response.origin } } catch (error) { return createErrorResponse( false, typeof error === 'string' ? error : error?.message ?? '标记已读失败' ) } } /** * 删除消息 */ static async deleteMessage(messageId : string, userId : string) : Promise> { try { // 软删除消息(对发送者) await supa .from('ak_messages') .update({ is_deleted: true, updated_at: new Date().toISOString() }) .eq('id', messageId) .eq('sender_id', userId) .executeAs>() // 软删除接收记录(对接收者) await supa .from('ak_message_recipients') .update({ is_deleted: true, updated_at: new Date().toISOString() }) .eq('message_id', messageId) .eq('recipient_id', userId) .executeAs>() const aaa = { status: 200, data: true, error: null, origin: null, headers: {} } return aaa } catch (error) { const aaa = { status: 500, data: false, error: new UniError(typeof error === 'string' ? error : error?.message ?? '删除消息失败'), origin: null, headers: {} } return aaa } } /** * 批量操作消息 */ static async batchOperation( messageIds : Array, operation : string, userId : string ) : Promise> { try { // 验证参数不能为空 if (userId == null || userId === '' || userId.trim() === '') { return createErrorResponse( false, '参数错误:用户ID不能为空' ) } if (messageIds == null || messageIds.length === 0) { return createErrorResponse( false, '参数错误:消息ID列表不能为空' ) } switch (operation) { case 'read': await supa .from('ak_message_recipients') .update({ status: 'read', read_at: new Date().toISOString(), updated_at: new Date().toISOString() }) .in('message_id', messageIds.map(x => x as any)) .eq('recipient_id', userId) .executeAs>() break case 'delete': await supa .from('ak_message_recipients') .update({ is_deleted: true, updated_at: new Date().toISOString() }) .in('message_id', messageIds.map(x => x as any)) .eq('recipient_id', userId) .executeAs>() break default: return { status: 400, data: false, error: new UniError('不支持的批量操作'), origin: null, headers: {} } as AkReqResponse } return { status: 200, data: true, error: null, origin: null, headers: {} } as AkReqResponse } catch (error) { return { status: 500, data: false, error: new UniError(typeof error === 'string' ? error : error?.message ?? '批量操作失败'), origin: null, headers: {} } as AkReqResponse } } /** * 获取消息统计信息 */ static async getMessageStats(userId : string) : Promise> { try { // 验证参数不能为空 if (userId == null || userId === '' || userId.trim() === '') { return createErrorResponse( { total_messages: 0, unread_messages: 0, sent_messages: 0, received_messages: 0, urgent_messages: 0, draft_messages: 0 }, '参数错误:用户ID不能为空' ) } // 获取未读消息 const unreadResponse = await supa .from('ak_message_recipients') .select('id', { count: 'exact' }) .eq('recipient_id', userId) .eq('status', 'unread') .eq('is_deleted', false) .executeAs>() // 获取总消息数 const totalResponse = await supa .from('ak_message_recipients') .select('id', { count: 'exact' }) .eq('recipient_id', userId) .eq('is_deleted', false) .executeAs>() // 获取紧急消息数 const urgentResponse = await supa .from('ak_messages') .select('id', { count: 'exact' }) .eq('receiver_id', userId) .eq('is_urgent', true) .eq('is_deleted', false) .executeAs>() const stats : MessageStats = { total_messages: Array.isArray(totalResponse.data) ? (totalResponse.data as Array).length : 0, unread_messages: Array.isArray(unreadResponse.data) ? (unreadResponse.data as Array).length : 0, urgent_messages: Array.isArray(urgentResponse.data) ? (urgentResponse.data as Array).length : 0, sent_messages: 0, // 可根据业务补充 received_messages: 0, // 可根据业务补充 draft_messages: 0 // 可根据业务补充 } return { status: 200, data: stats, error: null, origin: null, headers: {} } as AkReqResponse } catch (error) { return { status: 500, data: null, error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取消息统计失败'), origin: null, headers: {} } as AkReqResponse } } /** * 搜索用户(用于消息接收者选择) */ static async searchUsers(keyword : string) : Promise>> { try { const response = await supa .from('ak_users') .select('id, username, nickname, avatar', { count: 'exact' }) .or(`username.ilike.%${keyword}%,nickname.ilike.%${keyword}%`) .limit(20) .executeAs>() return response } catch (error) { return { status: 500, data: [] as Array, error: new UniError(typeof error === 'string' ? error : error?.message ?? '搜索失败'), origin: null, headers: {} } as AkReqResponse> } } /** * 获取群组列表 */ static async getGroups() : Promise>> { try { const response = await supa .from('ak_message_groups') .select('*', {}) .eq('is_active', true) .executeAs>() return response } catch (error) { return { status: 500, data: [] as Array, error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取群组失败'), origin: null, headers: {} } as AkReqResponse> } } /** * 获取群组成员 */ static async getGroupMembers(groupId : string) : Promise>> { try { const response = await supa .from('ak_message_group_members') .select('*', {}) .eq('group_id', groupId) .executeAs>() return response } catch (error) { return { status: 500, data: [] as Array, error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取群组成员失败'), origin: null, headers: {} } as AkReqResponse> } } } /** * 创建标准错误响应 */ function createErrorResponse(data : T, errorMessage : string, status : number = 500) : AkReqResponse { return { status: status, data: data, headers: {}, error: new UniError(errorMessage), total: null, page: null, limit: null, hasmore: false, origin: null } }