import React, { useState, useEffect } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Button, Table, Space, Modal, Form, Input, Select, message } from 'antd'; import { io, Socket } from 'socket.io-client'; import type { TableProps } from 'antd'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; import { MessageAPI , UserAPI } from './api/index.ts'; import type { UserMessage } from '../share/types.ts'; import { MessageStatusNameMap , MessageStatus} from '../share/types.ts'; import { useAuth } from "./hooks_sys.tsx"; export const MessagesPage = () => { const { token } = useAuth(); const [socket, setSocket] = useState(null); const [isSocketConnected, setIsSocketConnected] = useState(false); const queryClient = useQueryClient(); const [form] = Form.useForm(); const [isModalVisible, setIsModalVisible] = useState(false); const [searchParams, setSearchParams] = useState({ page: 1, pageSize: 10, type: undefined, status: undefined, search: undefined }); // 获取消息列表 const { data: messages, isLoading } = useQuery({ queryKey: ['messages', searchParams], queryFn: () => MessageAPI.getMessages(searchParams), }); // 获取用户列表 const { data: users } = useQuery({ queryKey: ['users'], queryFn: () => UserAPI.getUsers({ page: 1, limit: 1000 }), }); // 获取未读消息数 const { data: unreadCount } = useQuery({ queryKey: ['unreadCount'], queryFn: () => MessageAPI.getUnreadCount(), }); // 标记消息为已读 const markAsReadMutation = useMutation({ mutationFn: (id: number) => MessageAPI.markAsRead(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['messages'] }); queryClient.invalidateQueries({ queryKey: ['unreadCount'] }); message.success('标记已读成功'); }, }); // 删除消息 const deleteMutation = useMutation({ mutationFn: (id: number) => MessageAPI.deleteMessage(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['messages'] }); message.success('删除成功'); }, }); // 发送消息 // 初始化Socket.IO连接 useEffect(() => { if (!token) return; const newSocket = io('/', { path: '/socket.io', transports: ['websocket'], autoConnect: false, query: { socket_token: token } }); newSocket.on('connect', () => { setIsSocketConnected(true); message.success('实时消息连接已建立'); }); newSocket.on('disconnect', () => { setIsSocketConnected(false); message.warning('实时消息连接已断开'); }); newSocket.on('error', (err) => { message.error(`实时消息错误: ${err}`); }); newSocket.connect(); setSocket(newSocket); return () => { newSocket.disconnect(); }; }, [token]); const sendMessageMutation = useMutation({ mutationFn: async (data: any) => { // 优先使用Socket.IO发送 if (isSocketConnected && socket) { return new Promise((resolve, reject) => { socket.emit('message:send', data, (response: any) => { if (response.error) { reject(new Error(response.error)); } else { resolve(response.data); } }); }); } // 回退到HTTP API return MessageAPI.sendMessage(data); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['messages'] }); queryClient.invalidateQueries({ queryKey: ['unreadCount'] }); message.success('发送成功'); setIsModalVisible(false); form.resetFields(); }, }); const columns: TableProps['columns'] = [ { title: '标题', dataIndex: 'title', key: 'title', }, { title: '类型', dataIndex: 'type', key: 'type', }, { title: '发送人', dataIndex: 'sender_name', key: 'sender_name', }, { title: '状态', dataIndex: 'user_status', key: 'user_status', render: (user_status: MessageStatus) => ( {MessageStatusNameMap[user_status]} ), }, { title: '发送时间', dataIndex: 'created_at', key: 'created_at', render: (date: string) => dayjs(date).format('YYYY-MM-DD HH:mm'), }, { title: '操作', key: 'action', render: (_: any, record) => ( ), }, ]; const handleSearch = (values: any) => { setSearchParams({ ...searchParams, ...values, page: 1 }); }; const handleTableChange = (pagination: any) => { setSearchParams({ ...searchParams, page: pagination.current, pageSize: pagination.pageSize }); }; const handleSendMessage = (values: any) => { sendMessageMutation.mutate(values); }; return (

消息管理

{unreadCount && unreadCount.count > 0 && ( {unreadCount.count}条未读 )}
setIsModalVisible(false)} footer={null} width={800} >
({ value: user.id, label: user.username, }))} />
); };