/**
* filekorolheader: 审核历史页面 - 企业审核记录查询和管理页面
* 功能:审核历史记录查询、搜索筛选、详情查看、数据分析
* 路径:/central-config/tenant/audit-history
* 规范:遵循crop-x-new/docs/开发项目规范.md,使用SearchFormPagination组件,API集成,shadcn语义化样式
*/
'use client';
import React, { useState, useCallback, useEffect ,useRef} from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import {
FileText,
AlertCircle,
RefreshCw,
Building,
User,
Smartphone,
Search
} from 'lucide-react';
import { toast } from 'sonner';
import SearchFormPagination, {
type SearchFieldConfig,
type TableColumnConfig
} from '@/components/common/searchFormPagination';
import { fetchAuditLogs, transformAuditLogData, AuditLogsQueryParams, AuditRecord, AuditLogData } from './components/auditHistoryApi';
// URL参数类型定义
interface UrlParams {
search?: string;
action?: string;
audit_status?: string;
date_range?: string;
page?: number;
size?: number;
}
// 分页状态类型定义
interface PaginationState {
page: number;
size: number;
total: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
}
// Utility functions
const getActionBadge = (action: string) => {
switch (action) {
case 'SUBMIT':
return (
提交审核
);
case 'AUDIT':
return (
审核操作
);
default:
return (
{action}
);
}
};
const getResultBadge = (result: string) => {
switch (result) {
case 'approved':
return (
已通过
);
case 'rejected':
return (
已拒绝
);
case 'pending':
return (
待审核
);
case 'draft':
return (
草稿
);
default:
return (
{result}
);
}
};
export default function AuditHistoryPage() {
// 对话框状态管理
const [dialogs, setDialogs] = useState({
showViewDialog: false,
selectedRecord: null as AuditRecord | null
});
const dispatch = (action: any) => {
switch (action.type) {
case 'SET_SELECTED_RECORD':
setDialogs(prev => ({ ...prev, selectedRecord: action.payload }));
break;
case 'TOGGLE_VIEW_DIALOG':
setDialogs(prev => ({ ...prev, showViewDialog: action.payload }));
break;
case 'RESET_FORM_DATA':
setDialogs(prev => ({ ...prev, selectedRecord: null }));
break;
}
};
// 搜索字段配置
const searchFields: SearchFieldConfig[] = [
{
key: 'search',
label: '搜索',
type: 'text',
placeholder: '搜索企业名称、变更摘要...',
},
{
key: 'action',
label: '审核类型',
type: 'select',
defaultValue: 'all',
options: [
{ value: 'all', label: '全部类型' },
{ value: 'SUBMIT', label: '提交审核' },
{ value: 'AUDIT', label: '审核操作' },
],
},
{
key: 'audit_status',
label: '审核结果',
type: 'select',
defaultValue: 'all',
options: [
{ value: 'all', label: '全部结果' },
{ value: 'approved', label: '已通过' },
{ value: 'rejected', label: '已拒绝' },
{ value: 'pending', label: '待审核' },
{ value: 'draft', label: '草稿' },
],
},
{
key: 'date_range',
label: '时间范围',
type: 'select',
defaultValue: 'all',
options: [
{ value: 'all', label: '全部' },
{ value: 'today', label: '今天' },
{ value: 'week', label: '近7天' },
{ value: 'month', label: '近30天' },
{ value: 'quarter', label: '近90天' },
],
},
];
// 表格列配置
const columns: TableColumnConfig[] = [
{
key: 'enterpriseName',
label: '企业名称',
render: (value: string) => (
{value}
),
},
{
key: 'action',
label: '审核类型',
render: (value: string) => getActionBadge(value),
},
{
key: 'submitTime',
label: '提交时间',
render: (value: string, record: AuditLogData) => (
{record.action === 'SUBMIT' ? value : '-'}
),
},
{
key: 'actionTime',
label: '审核时间',
render: (value: string, record: AuditLogData) => (
{record.action === 'AUDIT' ? value : '-'}
),
},
{
key: 'actionBy',
label: '审核人',
render: (value: string) => value ? (
{value}
) : '-',
},
{
key: 'result',
label: '审核结果',
render: (value: string) => getResultBadge(value),
},
{
key: 'actions',
label: '操作',
render: (_: any, row: AuditLogData) => (
),
},
];
// 简化的状态管理 - 只需要存储数据和加载状态
const [records, setRecords] = useState([]);
const [pagination, setPagination] = useState({
page: 1,
size: 10,
total: 0,
totalPages: 0,
hasNext: false,
hasPrev: false,
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [searchFilters, setSearchFilters] = useState>({
search: '',
action: 'all',
audit_status: 'all',
date_range: 'all'
});
// 数据加载函数 - 优先从浏览器URL参数读取
const loadAuditHistory = useCallback(async (options: {
resetPage?: boolean;
filters?: Record;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
page?: number;
size?: number;
} = {}) => {
try {
// 优先从URL读取参数
let urlParams: UrlParams = {};
if (typeof window !== 'undefined') {
const params = new URLSearchParams(window.location.search);
urlParams = {
search: params.get('search') || undefined,
action: params.get('action') || undefined,
audit_status: params.get('audit_status') || undefined,
date_range: params.get('date_range') || undefined,
page: params.get('page') ? parseInt(params.get('page')!, 10) : undefined,
size: params.get('size') ? parseInt(params.get('size')!, 10) : undefined
};
console.log('从URL读取的参数:', urlParams);
}
console.log('========================================');
setLoading(true);
setError(null);
// 解构选项参数,提供默认值
const {
resetPage = false,
filters,
sortBy,
sortOrder,
page,
size
} = options;
// 优先级:URL参数 > 传入参数 > 父组件状态
const finalPage = resetPage ? 1 : (urlParams.page || page || pagination.page);
const finalSize = urlParams.size || size || pagination.size;
const params: AuditLogsQueryParams = {
page: finalPage,
size: finalSize,
};
// 使用正确的优先级:URL参数 > 传入参数 > 父组件状态
const currentFilters = {
search: urlParams.search || (filters?.search) || searchFilters.search,
action: urlParams.action || (filters?.action) || searchFilters.action,
audit_status: urlParams.audit_status || (filters?.audit_status) || searchFilters.audit_status,
date_range: urlParams.date_range || (filters?.date_range) || searchFilters.date_range
};
const currentSortBy = sortBy || 'created_at';
const currentSortOrder = sortOrder || 'desc';
// 添加搜索条件
if (currentFilters.search) {
params.search_keyword = currentFilters.search;
}
// 添加排序条件
if (currentSortBy) {
params.order_by = currentSortBy;
params.sort_order = currentSortOrder;
}
if (currentFilters.action && currentFilters.action !== 'all') {
params.action = currentFilters.action;
}
if (currentFilters.audit_status && currentFilters.audit_status !== 'all') {
params.audit_status = currentFilters.audit_status;
}
if (currentFilters.date_range && currentFilters.date_range !== 'all') {
params.date_range = currentFilters.date_range;
}
if (currentSortBy) {
params.order_by = currentSortBy;
params.sort_order = currentSortOrder;
}
console.log('=== 审核历史页面 - 最终API参数 ===');
console.log('API调用参数 params:', params);
console.log('参数优先级正确: URL参数 > 函数传递参数 > 父组件状态');
console.log('当前currentFilters:', currentFilters);
console.log('==================================');
const response = await fetchAuditLogs(params);
const transformedData = response.data.map(transformAuditLogData);
setRecords(transformedData);
setPagination({
page: response.page,
size: response.size,
total: response.total,
totalPages: response.total_pages,
hasNext: response.has_next,
hasPrev: response.has_prev,
});
} catch (err) {
const errorMessage = err instanceof Error ? err.message : '加载审核历史失败';
setError(errorMessage);
toast.error(errorMessage);
} finally {
setLoading(false);
}
}, []); // 移除依赖项,通过参数传递
const didFetchRef = useRef(false)
useEffect(() => {
if (didFetchRef.current) return
didFetchRef.current = true
loadAuditHistory()
}, [])
// 搜索处理 - 保持传统的简洁方式
const handleSearch = useCallback((filters: Record) => {
console.log('审核历史页面 - 收到搜索条件:', filters);
// 更新过滤器状态
setSearchFilters(filters);
// 搜索时重置到第1页
setPagination(prev => ({ ...prev, page: 1 }));
// 执行查询
loadAuditHistory({
resetPage: true,
page: 1,
filters: filters,
size: pagination.size
});
console.log('触发审核历史查询 - 参数:', {
resetPage: true,
page: 1,
filters: filters,
size: pagination.size
});
}, [pagination.size, loadAuditHistory]);
// 排序处理
const handleSort = useCallback((sortBy: string, sortOrder: 'asc' | 'desc') => {
// 排序时重置到第一页
setPagination(prev => ({ ...prev, page: 1 }));
loadAuditHistory({
resetPage: true,
page: 1,
filters: searchFilters,
sortBy,
sortOrder,
size: pagination.size
});
}, [searchFilters, pagination.size, loadAuditHistory]);
// 分页处理
const handlePageChange = useCallback((page: number) => {
if (page < 1) {
page = 1;
} else if (page > pagination.totalPages && pagination.totalPages > 0) {
page = pagination.totalPages;
}
setPagination(prev => ({ ...prev, page }));
loadAuditHistory({
page,
filters: searchFilters,
size: pagination.size
});
}, [searchFilters, pagination.size, pagination.totalPages, loadAuditHistory]);
// 每页条数变化处理
const handleSizeChange = useCallback((size: number) => {
setPagination(prev => ({ ...prev, size, page: 1 }));
loadAuditHistory({
resetPage: true,
page: 1,
size,
filters: searchFilters
});
}, [searchFilters, loadAuditHistory]);
// URL状态变化处理 - 处理浏览器前进后退时的参数恢复
const handleUrlStateChange = useCallback((urlState: {
filters: Record;
pagination: { page: number; size: number };
}) => {
console.log('审核历史页面 - URL状态变化:', urlState);
// 更新内部状态
setSearchFilters(urlState.filters);
setPagination(prev => ({
...prev,
page: urlState.pagination.page,
size: urlState.pagination.size
}));
// 触发数据加载
loadAuditHistory({
page: urlState.pagination.page,
size: urlState.pagination.size,
filters: urlState.filters
});
}, [loadAuditHistory]);
// 业务事件处理器
const handleView = (record: AuditLogData) => {
dispatch({ type: 'SET_SELECTED_RECORD', payload: record });
dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: true });
};
return (
{/* Page Header - 自定义页面头部 */}
审核历史
追溯查询全部企业的历史审核记录,支持搜索筛选和详情查看
{/* 使用SearchFormPagination组件 */}
{React.createElement(SearchFormPagination as any, {
formTitle: "审核历史记录",
searchFields,
columns,
data: records,
loading,
error,
pagination: pagination as any,
onPageChange: handlePageChange,
onSizeChange: handleSizeChange,
onSearch: handleSearch,
onSort: handleSort,
emptyIcon:
,
emptyText: "暂无审核记录",
sizeOptions: [10, 20, 50, 100]
})}
{/* View Audit Record Details Dialog */}
);
}