import React, { useState, useEffect } from 'react'; import { Card, Table, Tag, Space, Button, DatePicker, Select, Input, message, Popconfirm, Typography, Drawer, Descriptions, Timeline } from 'antd'; import { ReloadOutlined, DeleteOutlined, EyeOutlined, FileTextOutlined } from '@ant-design/icons'; import { operationLogAPI } from '../api'; import dayjs from 'dayjs'; const { Title } = Typography; const { RangePicker } = DatePicker; const OperationLogs = () => { const [logs, setLogs] = useState([]); const [loading, setLoading] = useState(false); const [pagination, setPagination] = useState({ current: 1, pageSize: 20, total: 0 }); const [filters, setFilters] = useState({}); const [actions, setActions] = useState([]); const [modules, setModules] = useState([]); const [detailVisible, setDetailVisible] = useState(false); const [selectedLog, setSelectedLog] = useState(null); useEffect(() => { fetchLogs(); fetchOptions(); }, [pagination.current, filters]); const fetchLogs = async () => { setLoading(true); try { const params = { page: pagination.current, pageSize: pagination.pageSize, ...filters }; const response = await operationLogAPI.list(params); if (response.success) { setLogs(response.data.logs); setPagination(prev => ({ ...prev, total: response.data.total })); } } catch (error) { message.error('获取操作日志失败'); } finally { setLoading(false); } }; const fetchOptions = async () => { try { const [actionsRes, modulesRes] = await Promise.all([ operationLogAPI.getActions(), operationLogAPI.getModules() ]); if (actionsRes.success) setActions(actionsRes.data); if (modulesRes.success) setModules(modulesRes.data); } catch (error) { console.error('获取选项失败:', error); } }; const handleFilterChange = (key, value) => { setFilters(prev => ({ ...prev, [key]: value })); setPagination(prev => ({ ...prev, current: 1 })); }; const handleDateChange = (dates) => { if (dates) { setFilters(prev => ({ ...prev, startDate: dates[0].toISOString(), endDate: dates[1].toISOString() })); } else { setFilters(prev => ({ ...prev, startDate: undefined, endDate: undefined })); } setPagination(prev => ({ ...prev, current: 1 })); }; const handleClear = async () => { try { const response = await operationLogAPI.clear({ days: 30 }); if (response.success) { message.success('已清理30天前的日志'); fetchLogs(); } } catch (error) { message.error('清理失败'); } }; const showDetail = (log) => { setSelectedLog(log); setDetailVisible(true); }; const getActionColor = (action) => { if (action.includes('删除')) return 'red'; if (action.includes('创建')) return 'green'; if (action.includes('修改')) return 'blue'; if (action.includes('登录')) return 'purple'; return 'default'; }; const getModuleColor = (module) => { const colors = { user: 'blue', role: 'green', device: 'orange', consumable: 'purple', system: 'cyan' }; return colors[module] || 'default'; }; const columns = [ { title: '操作时间', dataIndex: 'operateTime', key: 'operateTime', width: 180, sorter: (a, b) => new Date(b.operateTime) - new Date(a.operateTime), render: (time) => time ? dayjs(time).format('YYYY-MM-DD HH:mm:ss') : '-' }, { title: '操作人', key: 'operator', width: 150, render: (_, record) => (
{record.realName || record.username}
@{record.username}
) }, { title: '操作类型', dataIndex: 'action', key: 'action', width: 120, render: (action) => ( {action || '-'} ) }, { title: '模块', dataIndex: 'module', key: 'module', width: 100, render: (module) => ( {module === 'user' ? '用户' : module === 'role' ? '角色' : module === 'device' ? '设备' : module === 'consumable' ? '耗材' : module === 'system' ? '系统' : module} ) }, { title: '描述', dataIndex: 'description', key: 'description', ellipsis: true }, { title: '目标', key: 'target', width: 120, render: (_, record) => record.targetName || record.targetId || '-' }, { title: 'IP', dataIndex: 'ip', key: 'ip', width: 130, render: (ip) => ip || '-' }, { title: '状态', dataIndex: 'status', key: 'status', width: 80, render: (status) => ( {status === 'success' ? '成功' : '失败'} ) }, { title: '操作', key: 'action', width: 80, render: (_, record) => ( handleFilterChange('username', value)} allowClear /> handleFilterChange('module', value)} options={modules} fieldNames={{ label: 'label', value: 'value' }} /> `共 ${total} 条记录` }} onChange={(newPagination) => { setPagination(prev => ({ ...prev, ...newPagination })); }} /> setDetailVisible(false)} > {selectedLog && ( {selectedLog.operateTime ? dayjs(selectedLog.operateTime).format('YYYY-MM-DD HH:mm:ss') : '-'} {selectedLog.realName || selectedLog.username} (@{selectedLog.username}) {selectedLog.action} {selectedLog.module} {selectedLog.description || '-'} {selectedLog.targetName || selectedLog.targetId || '-'} {selectedLog.ip || '-'} {selectedLog.status === 'success' ? '成功' : '失败'} {selectedLog.errorMessage && ( {selectedLog.errorMessage} )} )} {(selectedLog?.oldValue || selectedLog?.newValue) && (
变更内容 {selectedLog.oldValue && (
                    {JSON.stringify(JSON.parse(selectedLog.oldValue), null, 2)}
                  
)} {selectedLog.newValue && (
                    {JSON.stringify(JSON.parse(selectedLog.newValue), null, 2)}
                  
)}
)}
); }; export default OperationLogs;