Files
d8d-admin-mobile-starter-pu…/server/routes_io_messages.ts

324 lines
9.1 KiB
TypeScript

import { SocketWithUser , Variables} from './router_io.ts';
import { MessageType, MessageStatus } from '../client/share/types.ts'
import { APIClient } from "@d8d-appcontainer/api";
interface MessageSendData {
title: string;
content: string;
type: MessageType;
receiver_ids: number[];
}
interface MessageListData {
page?: number;
pageSize?: number;
type?: MessageType;
status?: MessageStatus;
}
export function setupMessageEvents({ socket , apiClient }:Variables) {
// 订阅频道
socket.on('message:subscribe', (channel: string) => {
try {
socket.join(channel);
socket.emit('message:subscribed', {
message: `成功订阅频道: ${channel}`,
channel
});
} catch (error) {
console.error('订阅频道失败:', error);
socket.emit('error', '订阅频道失败');
}
});
// 取消订阅
socket.on('message:unsubscribe', (channel: string) => {
try {
socket.leave(channel);
socket.emit('message:unsubscribed', {
message: `已取消订阅频道: ${channel}`,
channel
});
} catch (error) {
console.error('取消订阅失败:', error);
socket.emit('error', '取消订阅失败');
}
});
// 广播消息
socket.on('message:broadcast', async (data: {
channel?: string;
title: string;
content: string;
type: MessageType;
}) => {
try {
const { channel, title, content, type } = data;
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
// 创建广播消息
const [messageId] = await apiClient.database.table('messages').insert({
title,
content,
type,
sender_id: user.id,
sender_name: user.username,
is_broadcast: 1,
created_at: apiClient.database.fn.now(),
updated_at: apiClient.database.fn.now()
});
// 广播到所有客户端或特定频道
const broadcastTarget = channel ? socket.to(channel) : socket.broadcast;
broadcastTarget.emit('message:broadcasted', {
id: messageId,
title,
content,
type,
sender_id: user.id,
sender_name: user.username,
created_at: new Date().toISOString()
});
socket.emit('message:broadcasted', {
message: '广播消息发送成功',
data: { id: messageId }
});
} catch (error) {
console.error('广播消息失败:', error);
socket.emit('error', '广播消息失败');
}
});
// 发送消息
socket.on('message:send', async (data: MessageSendData) => {
try {
const { title, content, type, receiver_ids } = data;
if (!title || !content || !type || !receiver_ids?.length) {
socket.emit('error', '缺少必要参数');
return;
}
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
// 创建消息
const [messageId] = await apiClient.database.table('messages').insert({
title,
content,
type,
sender_id: user.id,
sender_name: user.username,
created_at: apiClient.database.fn.now(),
updated_at: apiClient.database.fn.now()
});
// 关联用户消息
const userMessages = receiver_ids.map((userId: number) => ({
user_id: userId,
message_id: messageId,
status: MessageStatus.UNREAD,
created_at: apiClient.database.fn.now(),
updated_at: apiClient.database.fn.now()
}));
await apiClient.database.table('user_messages').insert(userMessages);
// 根据消息类型推送到不同频道
const messageData = {
id: messageId,
title,
content,
type,
sender_id: user.id,
sender_name: user.username,
created_at: new Date().toISOString()
};
if (type === MessageType.SYSTEM) {
socket.to('system').emit('message:received', messageData);
} else if (type === MessageType.ANNOUNCE) {
socket.to('announce').emit('message:received', messageData);
} else if (type === MessageType.PRIVATE) {
receiver_ids.forEach(userId => {
socket.to(`user_${userId}`).emit('message:received', messageData);
});
}
socket.emit('message:sent', {
message: '消息发送成功',
data: { id: messageId }
});
} catch (error) {
console.error('发送消息失败:', error);
socket.emit('error', '发送消息失败');
}
});
// 获取消息列表
socket.on('message:list', async (data: MessageListData) => {
try {
const { page = 1, pageSize = 20, type, status } = data;
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
const query = apiClient.database.table('user_messages as um')
.select('m.*', 'um.status as user_status', 'um.read_at', 'um.id as user_message_id')
.leftJoin('messages as m', 'um.message_id', 'm.id')
.where('um.user_id', user.id)
.where('um.is_deleted', 0)
.orderBy('m.created_at', 'desc')
.limit(pageSize)
.offset((page - 1) * pageSize);
if (type) query.where('m.type', type);
if (status) query.where('um.status', status);
const countQuery = query.clone();
const messages = await query;
// 获取总数用于分页
const total = await countQuery.count();
const totalCount = Number(total);
const totalPages = Math.ceil(totalCount / pageSize);
socket.emit('message:list', {
data: messages,
pagination: {
total: totalCount,
current: page,
pageSize,
totalPages
}
});
} catch (error) {
console.error('获取消息列表失败:', error);
socket.emit('error', '获取消息列表失败');
}
});
// 获取消息详情
socket.on('message:detail', async (messageId: number) => {
try {
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
const message = await apiClient.database.table('user_messages as um')
.select('m.*', 'um.status as user_status', 'um.read_at')
.leftJoin('messages as m', 'um.message_id', 'm.id')
.where('um.user_id', user.id)
.where('um.message_id', messageId)
.first();
if (!message) {
socket.emit('error', '消息不存在或无权访问');
return;
}
// 标记为已读
if (message.user_status === MessageStatus.UNREAD) {
await apiClient.database.table('user_messages')
.where('user_id', user.id)
.where('message_id', messageId)
.update({
status: MessageStatus.READ,
read_at: apiClient.database.fn.now(),
updated_at: apiClient.database.fn.now()
});
}
socket.emit('message:detail', {
message: '获取消息成功',
data: message
});
} catch (error) {
console.error('获取消息详情失败:', error);
socket.emit('error', '获取消息详情失败');
}
});
// 删除消息
socket.on('message:delete', async (messageId: number) => {
try {
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
await apiClient.database.table('user_messages')
.where('user_id', user.id)
.where('message_id', messageId)
.update({
is_deleted: 1,
updated_at: apiClient.database.fn.now()
});
socket.emit('message:deleted', { message: '消息已删除' });
} catch (error) {
console.error('删除消息失败:', error);
socket.emit('error', '删除消息失败');
}
});
// 获取未读消息数
socket.on('message:count', async () => {
try {
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
const count = await apiClient.database.table('user_messages')
.where('user_id', user.id)
.where('status', MessageStatus.UNREAD)
.where('is_deleted', 0)
.count();
socket.emit('message:count', { count: Number(count) });
} catch (error) {
console.error('获取未读消息数失败:', error);
socket.emit('error', '获取未读消息数失败');
}
});
// 标记消息为已读
socket.on('message:read', async (messageId: number) => {
try {
const user = socket.user;
if (!user) {
socket.emit('error', '未授权访问');
return;
}
await apiClient.database.table('user_messages')
.where('user_id', user.id)
.where('message_id', messageId)
.update({
status: MessageStatus.READ,
read_at: apiClient.database.fn.now(),
updated_at: apiClient.database.fn.now()
});
socket.emit('message:read', { message: '消息已标记为已读' });
} catch (error) {
console.error('标记消息为已读失败:', error);
socket.emit('error', '标记消息为已读失败');
}
});
}