Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,582 @@
/**
* 消息数据服务 - 真实 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
}
}