Files
akmon/utils/msgDataServiceReal.uts
2026-01-20 08:04:15 +08:00

582 lines
15 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 消息数据服务 - 真实 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<AkReqResponse<Array<MessageType>>> {
try {
const response = await supa
.from('ak_message_types')
.select('*', {})
.eq('is_active', true)
.order('priority', { ascending: false })
.executeAs<MessageType>()
if (response.status >= 200 && response.status < 300 && response.data !== null) {
console.log(response)
return response
}
// 如果没有数据,返回默认的消息类型
return createErrorResponse<Array<MessageType>>([{
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<Array<MessageType>>([{
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<AkReqResponse<Array<Message>>> {
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<Message>()
// .execute()
console.log(response)
return response
} catch (error) {
console.log(error)
return createErrorResponse<Array<UTSJSONObject>>([],
typeof error === 'string' ? error : error?.message ?? '获取消息列表失败')
}
}
/**
* 获取单条消息详情
*/
static async getMessageById(id : string) : Promise<AkReqResponse<Message>> {
try {
const response = await supa
.from('ak_messages')
.select(`
*,
message_type:ak_message_types(*),
recipients:ak_message_recipients(*)
`, {})
.eq('id', id)
.single()
.executeAs<Message>()
return response
} catch (error) {
return {
status: 500,
data: null,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取消息内容失败'),
origin: null,
headers: {}
} as AkReqResponse<Message>
}
}
/**
* 发送消<E98081>?
*/
static async sendMessage(params : SendMessageParams) : Promise<AkReqResponse<Message>> {
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<Message>()
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<MessageRecipient>()
}
}
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<AkReqResponse<boolean>> {
try {
// 验证参数不能为空
if (messageId == null || messageId === '' || receiverId == null || receiverId === '' || receiverId.trim() === '') {
return createErrorResponse<boolean>(
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<Array<MessageRecipient>>()
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<boolean>(
false,
typeof error === 'string' ? error : error?.message ?? '标记已读失败'
)
}
}
/**
* 删除消息
*/
static async deleteMessage(messageId : string, userId : string) : Promise<AkReqResponse<boolean>> {
try {
// 软删除消息(对发送者)
await supa
.from('ak_messages')
.update({
is_deleted: true,
updated_at: new Date().toISOString()
})
.eq('id', messageId)
.eq('sender_id', userId)
.executeAs<Array<Message>>()
// 软删除接收记录(对接收者)
await supa
.from('ak_message_recipients')
.update({
is_deleted: true,
updated_at: new Date().toISOString()
})
.eq('message_id', messageId)
.eq('recipient_id', userId)
.executeAs<Array<MessageRecipient>>()
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<string>,
operation : string,
userId : string
) : Promise<AkReqResponse<boolean>> {
try {
// 验证参数不能为空
if (userId == null || userId === '' || userId.trim() === '') {
return createErrorResponse<boolean>(
false,
'参数错误用户ID不能为空'
)
}
if (messageIds == null || messageIds.length === 0) {
return createErrorResponse<boolean>(
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<Array<MessageRecipient>>()
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<Array<MessageRecipient>>()
break
default:
return {
status: 400,
data: false,
error: new UniError('不支持的批量操作'),
origin: null,
headers: {}
} as AkReqResponse<boolean>
}
return {
status: 200,
data: true,
error: null,
origin: null,
headers: {}
} as AkReqResponse<boolean>
} catch (error) {
return {
status: 500,
data: false,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '批量操作失败'),
origin: null,
headers: {}
} as AkReqResponse<boolean>
}
}
/**
* 获取消息统计信息
*/
static async getMessageStats(userId : string) : Promise<AkReqResponse<MessageStats>> {
try {
// 验证参数不能为空
if (userId == null || userId === '' || userId.trim() === '') {
return createErrorResponse<MessageStats>(
{
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<Array<MessageRecipient>>()
// 获取总消息数
const totalResponse = await supa
.from('ak_message_recipients')
.select('id', { count: 'exact' })
.eq('recipient_id', userId)
.eq('is_deleted', false)
.executeAs<Array<MessageRecipient>>()
// 获取紧急消息数
const urgentResponse = await supa
.from('ak_messages')
.select('id', { count: 'exact' })
.eq('receiver_id', userId)
.eq('is_urgent', true)
.eq('is_deleted', false)
.executeAs<Array<Message>>()
const stats : MessageStats = {
total_messages: Array.isArray(totalResponse.data) ? (totalResponse.data as Array<any>).length : 0,
unread_messages: Array.isArray(unreadResponse.data) ? (unreadResponse.data as Array<any>).length : 0,
urgent_messages: Array.isArray(urgentResponse.data) ? (urgentResponse.data as Array<any>).length : 0,
sent_messages: 0, // 可根据业务补充
received_messages: 0, // 可根据业务补充
draft_messages: 0 // 可根据业务补充
}
return {
status: 200,
data: stats,
error: null,
origin: null,
headers: {}
} as AkReqResponse<MessageStats>
} catch (error) {
return {
status: 500,
data: null,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取消息统计失败'),
origin: null,
headers: {}
} as AkReqResponse<MessageStats>
}
}
/**
* 搜索用户(用于消息接收者选择)
*/
static async searchUsers(keyword : string) : Promise<AkReqResponse<Array<UserOption>>> {
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<Array<UserOption>>()
return response
} catch (error) { return {
status: 500,
data: [] as Array<UserOption>,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '搜索失败'),
origin: null,
headers: {}
} as AkReqResponse<Array<UserOption>>
}
}
/**
* 获取群组列表
*/
static async getGroups() : Promise<AkReqResponse<Array<MessageGroup>>> {
try {
const response = await supa
.from('ak_message_groups')
.select('*', {})
.eq('is_active', true)
.executeAs<Array<MessageGroup>>()
return response
} catch (error) { return {
status: 500,
data: [] as Array<MessageGroup>,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取群组失败'),
origin: null,
headers: {}
} as AkReqResponse<Array<MessageGroup>>
}
}
/**
* 获取群组成员
*/
static async getGroupMembers(groupId : string) : Promise<AkReqResponse<Array<GroupMember>>> {
try {
const response = await supa
.from('ak_message_group_members')
.select('*', {})
.eq('group_id', groupId)
.executeAs<Array<GroupMember>>()
return response
} catch (error) { return {
status: 500,
data: [] as Array<GroupMember>,
error: new UniError(typeof error === 'string' ? error : error?.message ?? '获取群组成员失败'),
origin: null,
headers: {}
} as AkReqResponse<Array<GroupMember>>
}
}
}
/**
* 创建标准错误响应
*/
function createErrorResponse<T>(data : T, errorMessage : string, status : number = 500) : AkReqResponse<T> {
return {
status: status,
data: data,
headers: {},
error: new UniError(errorMessage),
total: null,
page: null,
limit: null,
hasmore: false,
origin: null
}
}