diff --git a/crop-x-new/docs/开发项目规范.md b/crop-x-new/docs/开发项目规范.md index 069d686..838acb9 100644 --- a/crop-x-new/docs/开发项目规范.md +++ b/crop-x-new/docs/开发项目规范.md @@ -23,7 +23,7 @@ * filekorolheader: 物联设备数据接入页面 - IoT设备数据管理中心 * 功能:设备列表管理、实时数据监控、数据对比分析、报告生成 * 路径:/ai-crop-model/data-sense-center/iot - * 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,shadcn语义化样式 + * 规范:遵循crop-x-new/docs/开发项目规范.md,使用useReducer状态管理,shadcn语义化样式 */ ``` @@ -216,7 +216,7 @@ src/app/(app)/land-information/archive/statistics/ ### 9.注意乱码原则 生成的代码注意看看有没有乱码,必须遵守utf-8编码 ### 10.接口调用原则。 -接口必须调用 D:\code\repotest\smart-crop-ui\crop-x\src\lib\api\sdk.gen.ts 这个里面的接口 +接口必须调用 D:\code\repotest\smart-crop-ui\crop-x-new\src\lib\api\sdk.gen.ts 这个里面的接口 比如 /api/v1/departments/tree 这个路径,就是要调用export const getDepartmentTreeApiV1DepartmentsDepartmentsTreeGet = (options?: Options) => { return (options?.client ?? client).get({ security: [ @@ -229,7 +229,7 @@ src/app/(app)/land-information/archive/statistics/ ...options }); }; -实际使用的时候,要参考D:\code\repotest\smart-crop-ui\crop-x\src\app\(app)\central-config\tenant\audit-history\components\auditHistoryApi.ts 里面 +实际使用的时候,要参考D:\code\repotest\smart-crop-ui\crop-x-new\src\app\(app)\central-config\tenant\audit-history\components\auditHistoryApi.ts 里面 import { getTenantAuditLogsApiV1TenantsAuditLogsGet, } from "@/lib/api/sdk.gen"; 这个引入和用法。 diff --git a/crop-x-new/next-env.d.ts b/crop-x-new/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/crop-x-new/next-env.d.ts +++ b/crop-x-new/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/components/auditHistoryApi.ts b/crop-x-new/src/app/(app)/central-config/tenant/audit-history/components/auditHistoryApi.ts index ca6d40b..db1c5aa 100644 --- a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/components/auditHistoryApi.ts +++ b/crop-x-new/src/app/(app)/central-config/tenant/audit-history/components/auditHistoryApi.ts @@ -119,7 +119,7 @@ export async function fetchAuditLogs(params: AuditLogsQueryParams = {}): Promise if (params.size) queryParams.size = params.size; if (params.order_by) queryParams.order_by = params.order_by; if (params.sort_order) queryParams.sort_order = params.sort_order; - + if (params.search_keyword) queryParams.search = params.search_keyword; // 默认参数 if (!params.page) queryParams.page = 1; if (!params.size) queryParams.size = 10; diff --git a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx b/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx index c8bc1b0..5f74aa3 100644 --- a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx +++ b/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx @@ -2,481 +2,404 @@ * filekorolheader: 审核历史页面 - 企业审核记录查询和管理页面 * 功能:审核历史记录查询、搜索筛选、详情查看、数据分析 * 路径:/central-config/tenant/audit-history - * 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,API集成,shadcn语义化样式 + * 规范:遵循crop-x-new/docs/开发项目规范.md,使用SearchFormPagination组件,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 { useMemo, useState, useCallback } 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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Label } from '@/components/ui/label'; +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; import { - Search, - Calendar, FileText, AlertCircle, RefreshCw, - ChevronLeft, - ChevronRight, Building, User, - CreditCard, - Smartphone + Smartphone, + Search } from 'lucide-react'; +import { toast } from 'sonner'; + +import SearchFormPagination, { + type SearchFieldConfig, + type TableColumnConfig +} from '@/components/common/searchFormPagination'; 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 }; +// Utility functions +const getActionBadge = (action: string) => { + switch (action) { + case 'SUBMIT': + return ( +
+ 提交审核 +
+ ); + case 'AUDIT': + return ( +
+ 审核操作 +
+ ); default: - return state; + return ( +
+ {action} +
+ ); } }; -const initialState: AuditHistoryState = { - records: [], - loading: false, - error: null, - pagination: { +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 AuditLogData | 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, - }, - filters: { - search_keyword: '', - typeFilter: 'all', - resultFilter: 'all', - dateRange: 'all', - }, - sortBy: 'action_time', - sortOrder: 'desc', - selectedRecord: null, - showDetailDialog: false, -}; + }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [searchFilters, setSearchFilters] = useState>({ + search: '', + action: 'all', + audit_status: 'all', + date_range: 'all' + }); -export default function AuditHistoryPage() { - const [state, dispatch] = useReducer(auditHistoryReducer, initialState); - const isFirstLoad = useRef(true); - - // 加载审核历史数据 - const loadAuditHistory = useCallback(async () => { + // 数据加载函数 - 移除不必要的依赖避免重复调用 + const loadAuditHistory = useCallback(async (params?: { + filters?: Record; + pagination?: { page: number; size: number }; + sort?: { sortBy?: string; sortOrder?: 'asc' | 'desc' }; + }) => { try { - dispatch({ type: 'SET_LOADING', payload: true }); + console.log('调用了loadAuditHistory'); + setLoading(true); + setError(null); - const params: AuditLogsQueryParams = { - page: state.pagination.page, - size: state.pagination.size + const finalParams: AuditLogsQueryParams = { + search_keyword: (params?.filters?.search ?? searchFilters.search) || undefined, + action: params?.filters?.action ?? searchFilters.action, + audit_status: params?.filters?.audit_status ?? searchFilters.audit_status, + date_range: params?.filters?.date_range ?? searchFilters.date_range, + page: params?.pagination?.page || pagination.page, + size: params?.pagination?.size || pagination.size, + order_by: params?.sort?.sortBy, + sort_order: params?.sort?.sortOrder, }; - const response = await fetchAuditLogs(params); - const transformedRecords = response.data.map(transformAuditLogData); + // 处理筛选条件,如果为'all'则不传该参数 + if (finalParams.action === 'all') { + finalParams.action = undefined; + } + if (finalParams.audit_status === 'all') { + finalParams.audit_status = undefined; + } + if (finalParams.date_range === 'all') { + finalParams.date_range = undefined; + } - 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 response = await fetchAuditLogs(finalParams); + 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 handleSearch = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { search_keyword: value } }); - }; + // 事件处理器 + const handleSearch = useCallback((filters: Record) => { + setSearchFilters(filters); + // 搜索时重置到第一页 + loadAuditHistory({ + filters, + pagination: { page: 1, size: pagination.size } + }); + }, [loadAuditHistory, pagination.size]); - // 类型筛选 - const handleTypeFilter = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { typeFilter: value } }); - }; + const handleSort = useCallback((sortBy: string, sortOrder: 'asc' | 'desc') => { + // 排序时重置到第一页 + loadAuditHistory({ + pagination: { page: 1, size: pagination.size }, + sort: { sortBy, sortOrder } + }); + }, [loadAuditHistory, pagination.size]); - // 结果筛选 - const handleResultFilter = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { resultFilter: value } }); - }; + // 统一的数据重载函数 - 避免重复代码 + const reloadData = useCallback(() => { + const reloadParams = { + filters: searchFilters, + pagination: { + page: pagination.page, + size: pagination.size + } + }; + loadAuditHistory(reloadParams); + }, [loadAuditHistory, searchFilters, pagination]); - // 时间筛选 - const handleDateFilter = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { dateRange: value } }); - }; + const handlePageChange = useCallback((page: number) => { + setPagination(prev => ({ ...prev, page })); + loadAuditHistory({ + filters: searchFilters, + pagination: { page, size: pagination.size } + }); + }, [loadAuditHistory, searchFilters, pagination.size]); - // 排序处理 - const handleSort = (sortBy: string) => { - const newSortOrder = state.sortBy === sortBy && state.sortOrder === 'desc' ? 'asc' : 'desc'; - dispatch({ type: 'SET_SORT', payload: { sortBy, sortOrder: newSortOrder } }); - }; + const handleSizeChange = useCallback((size: number) => { + setPagination(prev => ({ ...prev, size, page: 1 })); + loadAuditHistory({ + filters: searchFilters, + pagination: { page: 1, size } + }); + }, [loadAuditHistory, searchFilters]); - // 分页处理 - 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) => { + // 业务事件处理器 + const handleView = (record: AuditLogData) => { dispatch({ type: 'SET_SELECTED_RECORD', payload: record }); - dispatch({ type: 'TOGGLE_DETAIL_DIALOG', payload: true }); - }; - - - // 合并所有状态变化,统一处理数据加载 - 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 '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}; - } + dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: true }); }; return (
- {/* Page Header */} -
-
-

审核历史

-

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

-
-
- - {/* Filters */} - -
-
- -
- - handleSearch(e.target.value)} - className="pl-10" - /> -
-
- -
-
- - -
- -
- - + {/* Page Header - 自定义页面头部 */} + +
+
+ +
+

审核历史

+

+ 追溯查询全部企业的历史审核记录,支持搜索筛选和详情查看 +

+
+
+ + 智能查询 +
+
+ + 状态筛选 +
+
+ + 详情查看 +
+
- {/* Time Range Filter */} - - -
- {[ - { value: 'all', label: '全部' }, - { value: 'today', label: '今天' }, - { value: 'week', label: '近7天' }, - { value: 'month', label: '近30天' }, - { value: 'quarter', label: '近90天' }, - ].map((option) => ( - - ))} -
-
+ {/* 使用SearchFormPagination组件 */} + } + emptyText="暂无审核记录" + sizeOptions={[10, 20, 50, 100]} + /> - {/* 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' ? '↑' : '↓'} - )} - - 提交时间 - 审核时间 - 审核人 - 审核结果 - 操作 - - - - {state.records.length === 0 ? ( - - - 暂无审核记录 - - - ) : ( - state.records.map((record) => ( - - -
- - {record.enterpriseName} -
-
- {getActionBadge(record.action)} - - {record.action === 'SUBMIT' ? record.submitTime : '-'} - - - {record.action === 'AUDIT' ? record.actionTime : '-'} - - -
- - {record.actionBy || '-'} -
-
- {getResultBadge(record.auditStatus)} - - - -
- )) - )} -
-
-
- - {/* 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 })}> + {/* View Audit Record Details Dialog */} + dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: open })}> 审核记录详情 @@ -485,7 +408,7 @@ export default function AuditHistoryPage() { - {state.selectedRecord && ( + {dialogs.selectedRecord && ( @@ -508,42 +431,42 @@ export default function AuditHistoryPage() {
-
{state.selectedRecord.enterpriseName}
+
{dialogs.selectedRecord.enterpriseName}
-
{getActionBadge(state.selectedRecord.action)}
+
{getActionBadge(dialogs.selectedRecord.action)}
-
- {state.selectedRecord.action === 'SUBMIT' ? state.selectedRecord.submitTime : '-'} +
+ {dialogs.selectedRecord.action === 'SUBMIT' ? dialogs.selectedRecord.submitTime : '-'}
-
- {state.selectedRecord.action === 'AUDIT' ? state.selectedRecord.actionTime : '-'} +
+ {dialogs.selectedRecord.action === 'AUDIT' ? dialogs.selectedRecord.actionTime : '-'}
-
{state.selectedRecord.actionBy || '-'}
+
{dialogs.selectedRecord.actionBy || '-'}
-
{getResultBadge(state.selectedRecord.result)}
+
{getResultBadge(dialogs.selectedRecord.result)}
-
- {state.selectedRecord.changeSummary || '-'} +
+ {dialogs.selectedRecord.changeSummary || '-'}
-
- {state.selectedRecord.auditComment || '-'} +
+ {dialogs.selectedRecord.auditComment || '-'}
@@ -554,61 +477,61 @@ export default function AuditHistoryPage() {
-
{state.selectedRecord.snapshot.companyType || '-'}
+
{dialogs.selectedRecord.snapshot?.companyType || '-'}
-
- {state.selectedRecord.snapshot.province} {state.selectedRecord.snapshot.city} +
+ {dialogs.selectedRecord.snapshot?.province} {dialogs.selectedRecord.snapshot?.city}
-
{state.selectedRecord.snapshot.detailedAddress || '-'}
+
{dialogs.selectedRecord.snapshot?.detailedAddress || '-'}
-
{state.selectedRecord.snapshot.registrant || '-'}
+
{dialogs.selectedRecord.snapshot?.registrant || '-'}
-
{state.selectedRecord.snapshot.contactPhone || '-'}
+
{dialogs.selectedRecord.snapshot?.contactPhone || '-'}
-
{state.selectedRecord.snapshot.companyScale || '-'}
+
{dialogs.selectedRecord.snapshot?.companyScale || '-'}
-
{state.selectedRecord.snapshot.registeredCapital || '-'}
+
{dialogs.selectedRecord.snapshot?.registeredCapital || '-'}
-
- {state.selectedRecord.snapshot.socialCreditCode || '-'} +
+ {dialogs.selectedRecord.snapshot?.socialCreditCode || '-'}
-
{state.selectedRecord.snapshot.legalPersonName || '-'}
+
{dialogs.selectedRecord.snapshot?.legalPersonName || '-'}
-
- {state.selectedRecord.snapshot.bankAccount || '-'} +
+ {dialogs.selectedRecord.snapshot?.bankAccount || '-'}
-
{state.selectedRecord.snapshot.bankName || '-'}
+
{dialogs.selectedRecord.snapshot?.bankName || '-'}
-
{state.selectedRecord.snapshot.bankFullName || '-'}
+
{dialogs.selectedRecord.snapshot?.bankFullName || '-'}
-
{state.selectedRecord.snapshot.bankAddress || '-'}
+
{dialogs.selectedRecord.snapshot?.bankAddress || '-'}
@@ -618,35 +541,35 @@ export default function AuditHistoryPage() {
-
- {state.selectedRecord.id} +
+ {dialogs.selectedRecord.id}
-
- {state.selectedRecord.enterpriseId || '-'} +
+ {dialogs.selectedRecord.enterpriseId || '-'}
-
{state.selectedRecord.ipAddress || '-'}
+
{dialogs.selectedRecord.ipAddress || '-'}
-
- {state.selectedRecord.userAgent || '-'} +
+ {dialogs.selectedRecord.userAgent || '-'}
-
- {state.selectedRecord.requestId || '-'} +
+ {dialogs.selectedRecord.requestId || '-'}
-
{state.selectedRecord.createdAt}
+
{dialogs.selectedRecord.createdAt}
@@ -655,7 +578,7 @@ export default function AuditHistoryPage() { )} - diff --git a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx.tmp b/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx.tmp deleted file mode 100644 index 73be5d9..0000000 --- a/crop-x-new/src/app/(app)/central-config/tenant/audit-history/page.tsx.tmp +++ /dev/null @@ -1,525 +0,0 @@ -/** - * filekorolheader: 审核历史 - 企业审核记录查询与详情查看页面 - * 功能:审核历史查询、筛选过滤、详情查看、数据导出、分页控制 - * 路径:/central-config/tenant/audit-history - * 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,API集成,shadcn语义化样式 - */ -'use client'; - -import { useReducer, useEffect, useMemo } from 'react'; -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, DialogHeader, DialogTitle, DialogDescription, 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, - Download, - Search, - Eye, - AlertCircle, - ChevronLeft, - ChevronRight, - Calendar, - Clock, - User, - FileText, - Building2, - MapPin, - CreditCard, - Phone -} from 'lucide-react'; -import { toast } from 'sonner'; - -import { auditHistoryReducer, initialState, AuditHistoryState, AuditHistoryAction } from './components/auditHistoryReducer'; -import { fetchAuditLogs, transformAuditLogData, AuditLogsQueryParams } from './components/auditHistoryApi'; -import { AuditRecord, FilterOptions, AuditStatus } from './types'; - -// Utility functions -const getStatusBadge = (status: AuditStatus) => { - switch (status) { - case 'draft': - return 草稿; - case 'pending': - return 待审核; - case 'approved': - return 审核通过; - case 'rejected': - return 审核拒绝; - default: - return 未知; - } -}; - -const getActionBadge = (action: string) => { - if (action === 'SUBMIT') { - return 提交; - } else if (action === 'AUDIT') { - return 审核; - } - return {action}; -}; - -export default function AuditHistoryPage() { - const [state, dispatch] = useReducer(auditHistoryReducer, initialState); - - // 加载审核历史数据 - const loadAuditHistory = async (resetPage = false) => { - try { - dispatch({ type: 'SET_LOADING', payload: true }); - - const params: AuditLogsQueryParams = { - page: resetPage ? 1 : state.pagination.page, - size: state.pagination.size, - order_by: state.sortBy, - sort_order: state.sortOrder, - }; - - const response = await fetchAuditLogs(params); - const transformedData = response.data.map(transformAuditLogData); - - console.log('Audit Logs API Response:', response); - console.log('Transformed Audit Data:', transformedData); - - dispatch({ - type: 'SET_RECORDS', - payload: { - data: transformedData, - 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); - const errorMessage = error instanceof Error ? error.message : '加载审核历史失败'; - dispatch({ type: 'SET_ERROR', payload: errorMessage }); - toast.error(errorMessage); - } - }; - - // 初始加载 - useEffect(() => { - loadAuditHistory(true); - }, [state.sortBy, state.sortOrder]); - - // 分页加载 - useEffect(() => { - if (state.pagination.page > 1) { - loadAuditHistory(false); - } - }, [state.pagination.page]); - - // 计算统计数据 - 按照参考组件的顺序 - const stats = useMemo(() => [ - { - label: '审核总数', - value: state.records.length, - color: 'text-blue-600 dark:text-blue-400', - bg: 'bg-blue-50 dark:bg-blue-950', - borderColor: 'border-blue-200 dark:border-blue-800', - }, - { - label: '已通过', - value: state.records.filter(r => r.result === 'approved').length, - color: 'text-green-600 dark:text-green-400', - bg: 'bg-green-50 dark:bg-green-950', - borderColor: 'border-green-200 dark:border-green-800', - }, - { - label: '已驳回', - value: state.records.filter(r => r.result === 'rejected').length, - color: 'text-red-600 dark:text-red-400', - bg: 'bg-red-50 dark:bg-red-950', - borderColor: 'border-red-200 dark:border-red-800', - }, - { - label: '待审核', - value: state.records.filter(r => r.result === 'pending').length, - color: 'text-yellow-600 dark:text-yellow-400', - bg: 'bg-yellow-50 dark:bg-yellow-950', - borderColor: 'border-yellow-200 dark:border-yellow-800', - }, - ], [state.records]); - - // 筛选记录 - const filteredRecords = useMemo(() => { - return state.records.filter(record => { - const matchKeyword = !state.filters.searchKeyword || - record.enterpriseName.toLowerCase().includes(state.filters.searchKeyword.toLowerCase()) || - record.changeSummary.toLowerCase().includes(state.filters.searchKeyword.toLowerCase()); - - const matchResult = state.filters.resultFilter === 'all' || record.result === state.filters.resultFilter; - const matchType = state.filters.typeFilter === 'all' || record.auditType === state.filters.typeFilter; - - // 日期筛选 - let matchDate = true; - if (state.filters.dateRange !== 'all' && record.actionTime) { - const auditDate = new Date(record.actionTime); - const now = new Date(); - const diffDays = Math.floor((now.getTime() - auditDate.getTime()) / (1000 * 60 * 60 * 24)); - - switch (state.filters.dateRange) { - case 'today': - matchDate = diffDays === 0; - break; - case 'week': - matchDate = diffDays <= 7; - break; - case 'month': - matchDate = diffDays <= 30; - break; - case 'quarter': - matchDate = diffDays <= 90; - break; - } - } - - return matchKeyword && matchResult && matchType && matchDate; - }); - }, [state.records, state.filters]); - - // 事件处理器 - const handleSearch = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { searchKeyword: value } }); - }; - - const handleResultFilter = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { resultFilter: value } }); - }; - - const handleTypeFilter = (value: string) => { - dispatch({ type: 'SET_FILTERS', payload: { typeFilter: 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: AuditRecord) => { - dispatch({ type: 'SET_SELECTED_RECORD', payload: record }); - dispatch({ type: 'TOGGLE_DETAIL_DIALOG', payload: true }); - }; - - const handleExport = () => { - const exportData = filteredRecords.map(record => ({ - 企业名称: record.enterpriseName, - 操作类型: record.action === 'SUBMIT' ? '提交' : '审核', - 审核类型: record.auditType === 'register' ? '注册' : '更新', - 操作时间: record.actionTime, - 操作人: record.actionBy, - 审核结果: record.result === 'approved' ? '审核通过' : - record.result === 'rejected' ? '审核拒绝' : - record.result === 'pending' ? '待审核' : '草稿', - 变更摘要: record.changeSummary, - })); - - const dataStr = JSON.stringify(exportData, null, 2); - const dataBlob = new Blob([dataStr], { type: 'application/json' }); - const url = URL.createObjectURL(dataBlob); - const link = document.createElement('a'); - link.href = url; - link.download = `audit_history_${new Date().getTime()}.json`; - link.click(); - toast.success('审核历史数据导出成功'); - }; - - return ( -
- {/* Page Header */} - -
-
- -
-

审核历史

-

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

-
- - - 智能查询 - - - - 时间筛选 - - - - 详情查看 - -
-
-
-
- -
-
-
- - {/* Statistics Cards */} -
- {stats.map((stat, index) => ( - -
-
{stat.label}
- -
-
{stat.value}
-
- 条记录 -
-
- ))} -
- - {/* 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' ? '↑' : '↓'} - )} - - 审核结果 - 变更摘要 - 操作 - - - - {filteredRecords.map((record) => ( - - -
- - {record.enterpriseName} -
-
- -
- {getActionBadge(record.action)} - {record.auditType === 'register' && ( - 注册 - )} - {record.auditType === 'update' && ( - 更新 - )} -
-
- -
- - {record.actionBy} -
-
- {record.actionTime} - {getStatusBadge(record.result)} - - {record.changeSummary} - - - - -
- ))} -
-
-
- - {filteredRecords.length === 0 && ( -
- -

暂无审核历史记录

-
- )} - - {/* Pagination */} - {state.pagination.totalPages > 1 && ( -
-
- 显示第 {state.pagination.page} 页,共 {state.pagination.totalPages} 页 - 总计 {state.pagination.total} 条记录 -
-
- - - {state.pagination.page} / {state.pagination.totalPages} - - -
-
- )} - - )} - diff --git a/crop-x-new/src/app/(app)/central-config/tenant/enterprise-audit/page.tsx b/crop-x-new/src/app/(app)/central-config/tenant/enterprise-audit/page.tsx index 09c6c37..9dd588a 100644 --- a/crop-x-new/src/app/(app)/central-config/tenant/enterprise-audit/page.tsx +++ b/crop-x-new/src/app/(app)/central-config/tenant/enterprise-audit/page.tsx @@ -271,19 +271,6 @@ export default function EnterpriseAuditPage() { } }, []); // 移除所有依赖,使用参数传递状态变化 - // 首次加载数据 - 使用事件驱动,避免useEffect - const initializeData = useCallback(() => { - if (isFirstLoad.current) { - isFirstLoad.current = false; - loadEnterprises({ resetPage: true }); - } - }, [loadEnterprises]); - - // 页面加载时初始化数据 - useEffect(() => { - initializeData(); - }, []); // 只在组件挂载时执行一次 - // 计算统计数据 const stats = useMemo(() => ({ total: state.pagination.total,