import React, { useEffect, useState, useMemo, useCallback } from 'react'; import { Table, Select, DatePicker, Space, Tag, Tooltip } from 'antd'; import dayjs from 'dayjs'; import api from '../../api'; import { message } from '../../ui/app-message'; const { RangePicker } = DatePicker; const moduleColorMap: Record = { 学生: 'blue', 宿舍: 'green', 入住: 'cyan', 费用: 'orange', 账单: 'red', 账号: 'purple', 认证: 'magenta', }; const statusMap: Record = { success: { text: '成功', color: 'green' }, fail: { text: '失败', color: 'red' }, }; const OperationLogsPage: React.FC = () => { const [data, setData] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(20); const [filterModule, setFilterModule] = useState(); const [dateRange, setDateRange] = useState<[string, string] | null>(null); const fetchData = useCallback(async () => { setLoading(true); try { const params: any = { page, pageSize }; if (filterModule) params.module = filterModule; if (dateRange) { params.startDate = dateRange[0]; params.endDate = dateRange[1]; } const res: any = await api.get('/operation-logs', { params }); setData(res.data); setTotal(res.total); } catch (e: unknown) { const err = e as { message?: string }; message.error(err?.message || '加载失败,请稍后重试'); } setLoading(false); }, [page, pageSize, filterModule, dateRange]); useEffect(() => { fetchData(); }, [fetchData]); const columns = useMemo( () => [ { title: '时间', dataIndex: 'createdAt', width: 170, render: (v: string) => dayjs(v).format('YYYY-MM-DD HH:mm:ss'), }, { title: '操作人', dataIndex: 'username', width: 100 }, { title: '模块', dataIndex: 'module', width: 100, render: (v: string) => {v}, }, { title: '操作', dataIndex: 'action', width: 150 }, { title: '状态', dataIndex: 'status', width: 80, render: (v: string) => { const s = statusMap[v] || statusMap['success']; return {s.text}; }, }, { title: '详情', width: 200, dataIndex: 'detail', ellipsis: true, render: (v: string) => v ? ( {v} ) : ( '-' ), }, { title: 'IP地址', dataIndex: 'ipAddress', width: 130, render: (v: string) => v || '-' }, { title: '终端', dataIndex: 'userAgent', width: 120, ellipsis: true, render: (v: string) => { if (!v) return '-'; if (v.includes('Mobile')) return 手机; if (v.includes('Windows')) return Windows; if (v.includes('Mac')) return Mac; if (v.includes('Linux')) return Linux; return ( 其他 ); }, }, ], [], ); return (

操作日志