import { useState, useEffect } from 'react'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Badge } from '@/components/ui/badge'; import { Search, RefreshCw } from 'lucide-react'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { auditApi } from '@/api'; import type { OperationLog } from '@/types'; import type { JsonData } from '@/types/common'; import { useTranslation } from 'react-i18next'; interface SystemLogsTabProps { searchQuery: string; setSearchQuery: (v: string) => void; } // 将后端审计日志规范化为前端 OperationLog 类型 // Logan.Li function normalizeLog(raw: JsonData): OperationLog { return { id: String(raw.id ?? ''), userId: String(raw.user_id ?? raw.userId ?? ''), username: raw.username ?? '', module: raw.module ?? raw.resource ?? '', action: raw.action ?? '', resource: raw.resource ?? '', ip: raw.ip ?? '', userAgent: raw.user_agent ?? raw.userAgent ?? '', // 后端审计日志使用 status=1/0 表示成功/失败,同时兼容旧 result 字段。 // Logan.Li result: raw.result === 'failure' || raw.status === 0 || raw.status === 'failed' ? 'failure' : 'success', message: raw.message ?? raw.detail ?? raw.error, createdAt: raw.createdAt ?? raw.created_at ?? '', }; } export function SystemLogsTab({ searchQuery, setSearchQuery }: SystemLogsTabProps) { const { t } = useTranslation(); const [logs, setLogs] = useState([]); const [loading, setLoading] = useState(true); const fetchLogs = async () => { setLoading(true); try { const resp = await auditApi.getLogs({ page: 1, page_size: 50 }); const list = resp?.list ?? []; setLogs(list.map(normalizeLog)); } catch { setLogs([]); } finally { setLoading(false); } }; useEffect(() => { fetchLogs(); }, []); const filteredLogs = logs.filter( (log) => log.username.toLowerCase().includes(searchQuery.toLowerCase()) || log.module.toLowerCase().includes(searchQuery.toLowerCase()) || log.action.toLowerCase().includes(searchQuery.toLowerCase()) ); const getLogResultBadge = (result: OperationLog['result']) => { return result === 'success' ? ( {t('system.auditSuccess')} ) : ( {t('system.auditFailed')} ); }; return ( <> {/* Filters */}
setSearchQuery(e.target.value)} className="pl-9 h-9 dg-input" />
{/* Logs Table */}
{loading ? (
) : filteredLogs.length === 0 ? (

{t('audit.operations.noData')}

) : ( {t('system.auditTime')} {t('system.roleUsers')} {t('system.auditModule')} {t('system.auditAction')} {t('system.auditResource')} {t('server.csv.ip')} {t('system.auditResult')} {filteredLogs.map((log) => ( {log.createdAt ? new Date(log.createdAt).toLocaleString() : '--'} {log.username || '--'} {log.module || '--'} {log.action || '--'} {log.resource || '--'} {log.ip || '--'} {getLogResultBadge(log.result)} ))}
)}
); }