'use client' // src/app/admin/audit-logs/page.tsx — 审计日志 import { useState, useEffect, useCallback } from 'react' import { RotateCw } from 'lucide-react' interface AuditLog { id: number; username: string | null; action: string; entity_type: string details: string | null; ip_address: string | null; created_at: string } export default function AuditLogsPage() { const [logs, setLogs] = useState([]) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const [action, setAction] = useState('') const [entityType, setEntityType] = useState('') const [loading, setLoading] = useState(true) const pageSize = 20 const load = useCallback(async () => { setLoading(true) const params = new URLSearchParams({ page: String(page), pageSize: String(pageSize) }) if (action) params.set('action', action) if (entityType) params.set('entity_type', entityType) const res = await fetch(`/api/admin/audit-logs?${params}`) if (res.ok) { const data = await res.json() setLogs(data.data) setTotal(data.total) } setLoading(false) }, [page, action, entityType]) useEffect(() => { load() }, [load]) const totalPages = Math.ceil(total / pageSize) const renderDetails = (details: string | null) => { if (!details) return '—' try { return JSON.stringify(JSON.parse(details)).slice(0, 80) } catch { return details.slice(0, 80) } } return (

审计日志

系统操作与事件记录

{loading ? ( ) : logs.length === 0 ? ( ) : logs.map(log => ( ))}
时间 用户 操作 对象 详情 IP
加载中...
暂无数据
{log.created_at} {log.username || '—'} {log.action} {log.entity_type} {renderDetails(log.details)} {log.ip_address || '—'}
{totalPages > 1 && (
第 {page}/{totalPages} 页 (共 {total} 条)
)}
) }