/** * filekorolheader: 审核历史页面 - 企业审核记录查询和管理页面 * 功能:审核历史记录查询、搜索筛选、详情查看、数据分析 * 路径:/central-config/tenant/audit-history * 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,API集成,shadcn语义化样式 */ 'use client'; import { useReducer, useEffect, useMemo, useState, useRef, useCallback } from 'react'; import { toast } from 'sonner'; import { Card } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { History, Search, Calendar, FileText, AlertCircle, RefreshCw, ChevronLeft, ChevronRight, Building, User, CreditCard, Smartphone } from 'lucide-react'; import { fetchAuditLogs, transformAuditLogData, AuditLogsQueryParams, AuditLogData } from './components/auditHistoryApi'; // 审核历史状态管理 interface AuditHistoryState { records: AuditLogData[]; loading: boolean; error: string | null; pagination: { page: number; size: number; total: number; totalPages: number; hasNext: boolean; hasPrev: boolean; }; filters: { search_keyword: string; typeFilter: string; resultFilter: string; dateRange: string; }; sortBy?: string; sortOrder: 'asc' | 'desc'; selectedRecord: AuditLogData | null; showDetailDialog: boolean; } type AuditHistoryAction = | { type: 'SET_RECORDS'; payload: { data: AuditLogData[]; pagination: AuditHistoryState['pagination'] } } | { type: 'SET_LOADING'; payload: boolean } | { type: 'SET_ERROR'; payload: string | null } | { type: 'SET_FILTERS'; payload: Partial } | { type: 'SET_SORT'; payload: { sortBy?: string; sortOrder: 'asc' | 'desc' } } | { type: 'SET_PAGINATION'; payload: Partial } | { type: 'SET_SELECTED_RECORD'; payload: AuditLogData | null } | { type: 'TOGGLE_DETAIL_DIALOG'; payload: boolean } | { type: 'REFRESH_DATA' }; const auditHistoryReducer = (state: AuditHistoryState, action: AuditHistoryAction): AuditHistoryState => { switch (action.type) { case 'SET_RECORDS': return { ...state, records: action.payload.data, pagination: action.payload.pagination, loading: false, error: null, }; case 'SET_LOADING': return { ...state, loading: action.payload }; case 'SET_ERROR': return { ...state, error: action.payload, loading: false }; case 'SET_FILTERS': return { ...state, filters: { ...state.filters, ...action.payload } }; case 'SET_SORT': return { ...state, sortBy: action.payload.sortBy, sortOrder: action.payload.sortOrder }; case 'SET_PAGINATION': return { ...state, pagination: { ...state.pagination, ...action.payload } }; case 'SET_SELECTED_RECORD': return { ...state, selectedRecord: action.payload }; case 'TOGGLE_DETAIL_DIALOG': return { ...state, showDetailDialog: !state.showDetailDialog }; case 'REFRESH_DATA': return { ...state, error: null }; default: return state; } }; const initialState: AuditHistoryState = { records: [], loading: false, error: null, pagination: { page: 1, size: 10, total: 0, totalPages: 0, hasNext: false, hasPrev: false, }, filters: { search_keyword: '', typeFilter: 'all', resultFilter: 'all', dateRange: 'all', }, sortBy: 'action_time', sortOrder: 'desc', selectedRecord: null, showDetailDialog: false, }; export default function AuditHistoryPage() { const [state, dispatch] = useReducer(auditHistoryReducer, initialState); const isFirstLoad = useRef(true); // 加载审核历史数据 const loadAuditHistory = useCallback(async () => { try { dispatch({ type: 'SET_LOADING', payload: true }); const params: AuditLogsQueryParams = { search: state.filters.search_keyword || undefined, page: state.pagination.page, size: state.pagination.size }; const response = await fetchAuditLogs(params); const transformedRecords = response.data.map(transformAuditLogData); dispatch({ type: 'SET_RECORDS', payload: { data: transformedRecords, pagination: { page: response.page, size: response.size, total: response.total, totalPages: response.total_pages, hasNext: response.has_next, hasPrev: response.has_prev, } } }); } catch (error) { console.error('Failed to load audit history:', error); dispatch({ type: 'SET_ERROR', payload: error instanceof Error ? error.message : '加载审核历史失败' }); } }, []); // 空依赖数组,函数内部使用最新状态 // 搜索处理 const handleSearch = (value: string) => { dispatch({ type: 'SET_FILTERS', payload: { search_keyword: value } }); }; // 类型筛选 const handleTypeFilter = (value: string) => { dispatch({ type: 'SET_FILTERS', payload: { typeFilter: value } }); }; // 结果筛选 const handleResultFilter = (value: string) => { dispatch({ type: 'SET_FILTERS', payload: { resultFilter: value } }); }; // 时间筛选 const handleDateFilter = (value: string) => { dispatch({ type: 'SET_FILTERS', payload: { dateRange: value } }); }; // 排序处理 const handleSort = (sortBy: string) => { const newSortOrder = state.sortBy === sortBy && state.sortOrder === 'desc' ? 'asc' : 'desc'; dispatch({ type: 'SET_SORT', payload: { sortBy, sortOrder: newSortOrder } }); }; // 分页处理 const handlePageChange = (page: number) => { // 边界检查,确保页码在有效范围内 if (page < 1) { page = 1; } else if (page > state.pagination.totalPages && state.pagination.totalPages > 0) { page = state.pagination.totalPages; } dispatch({ type: 'SET_PAGINATION', payload: { page } }); }; // 查看详情 const handleViewDetail = (record: AuditLogData) => { dispatch({ type: 'SET_SELECTED_RECORD', payload: record }); dispatch({ type: 'TOGGLE_DETAIL_DIALOG', payload: true }); }; // 刷新数据 const handleRefresh = () => { dispatch({ type: 'REFRESH_DATA' }); dispatch({ type: 'SET_PAGINATION', payload: { page: 1 } }); toast.success('数据已刷新'); }; // 合并所有状态变化,统一处理数据加载 useEffect(() => { if (isFirstLoad.current) { // 首次加载 isFirstLoad.current = false; loadAuditHistory(); } else { // 后续状态变化,使用防抖 const timer = setTimeout(() => { loadAuditHistory(); }, 300); return () => clearTimeout(timer); } }, [ state.filters.search_keyword, state.filters.typeFilter, state.filters.resultFilter, state.filters.dateRange, state.sortBy, state.sortOrder, state.pagination.page, state.pagination.size ]); // 工具函数 const getActionBadge = (action: string) => { switch (action) { case 'register': return 注册审核; case 'update': return 变更审核; default: return {action}; } }; const getResultBadge = (result: string) => { switch (result) { case 'approved': return 已通过; case 'rejected': return 已驳回; case 'pending': return 待审核; default: return {result}; } }; return (
{/* Page Header */}

审核历史

追溯查询全部企业的历史审核记录

智能查询 时间筛选 详细记录
{/* Filters */}
handleSearch(e.target.value)} className="pl-10" />
{/* Time Range Filter */}
{[ { value: 'all', label: '全部' }, { value: 'today', label: '今天' }, { value: 'week', label: '近7天' }, { value: 'month', label: '近30天' }, { value: 'quarter', label: '近90天' }, ].map((option) => ( ))}
{/* Error Display */} {state.error && (
{state.error}
)} {/* Loading State */} {state.loading && (

加载中...

)} {/* Data Table */} {!state.loading && !state.error && (
handleSort('enterprise_name')} > 企业名称 {state.sortBy === 'enterprise_name' && ( {state.sortOrder === 'asc' ? '↑' : '↓'} )} handleSort('action')} > 操作类型 {state.sortBy === 'action' && ( {state.sortOrder === 'asc' ? '↑' : '↓'} )} 操作人 handleSort('action_time')} > 操作时间 {state.sortBy === 'action_time' && ( {state.sortOrder === 'asc' ? '↑' : '↓'} )} 结果 操作 {state.records.length === 0 ? ( 暂无审核记录 ) : ( state.records.map((record) => (
{record.snapshot_company_name}
{getActionBadge(record.action)}
{record.action_by}
{record.action_time} {getResultBadge(record.result)}
)) )}
{/* Pagination */} {state.pagination.totalPages > 1 && (
显示第 {state.pagination.page} 页,共 {state.pagination.totalPages} 页 总计 {state.pagination.total} 条记录
{state.pagination.page} / {state.pagination.totalPages}
)}
)} {/* Detail Dialog */} dispatch({ type: 'TOGGLE_DETAIL_DIALOG', payload: open })}> 审核记录详情 查看审核记录的详细信息和企业快照数据 {state.selectedRecord && ( 基本信息 企业快照 系统信息 {/* 基本信息 */}
{state.selectedRecord.snapshot_company_name}
{getActionBadge(state.selectedRecord.action)}
{state.selectedRecord.action_by}
{state.selectedRecord.action_time}
{getResultBadge(state.selectedRecord.result)}
{state.selectedRecord.action_summary || '-'}
{/* 企业快照 */}
{state.selectedRecord.snapshot_company_type || '-'}
{state.selectedRecord.snapshot_province} {state.selectedRecord.snapshot_city}
{state.selectedRecord.snapshot_address || '-'}
{state.selectedRecord.snapshot_registrant || '-'}
{state.selectedRecord.snapshot_contact_phone || '-'}
{/* 系统信息 */}
{state.selectedRecord.id}
{state.selectedRecord.tenant_id}
{state.selectedRecord.ip_address || '-'}
{state.selectedRecord.user_agent || '-'}
)}
); }