- 修复消息组件JSX.Element类型错误,改为React.ReactNode - 完善审核历史页面类型定义和API接口调用 - 优化验证码组件,移除备用验证码逻辑避免无限循环 - 简化系统设置页面,仅保留基本设置和外观设置 - 修复用户管理页面编辑模态框数据加载和CRUD操作 - 移除废弃的作物推荐组件文件 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
716 lines
26 KiB
TypeScript
716 lines
26 KiB
TypeScript
/**
|
||
* 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 (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400 border border-blue-200 dark:border-blue-800">
|
||
提交审核
|
||
</div>
|
||
);
|
||
case 'AUDIT':
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-orange-50 dark:bg-orange-950 text-orange-600 dark:text-orange-400 border border-orange-200 dark:border-orange-800">
|
||
审核操作
|
||
</div>
|
||
);
|
||
default:
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium border border-gray-200 dark:border-gray-800">
|
||
{action}
|
||
</div>
|
||
);
|
||
}
|
||
};
|
||
|
||
const getResultBadge = (result: string) => {
|
||
switch (result) {
|
||
case 'approved':
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-green-50 dark:bg-green-950 text-green-600 dark:text-green-400 border border-green-200 dark:border-green-800">
|
||
已通过
|
||
</div>
|
||
);
|
||
case 'rejected':
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-red-50 dark:bg-red-950 text-red-600 dark:text-red-400 border border-red-200 dark:border-red-800">
|
||
已拒绝
|
||
</div>
|
||
);
|
||
case 'pending':
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-yellow-50 dark:bg-yellow-950 text-yellow-600 dark:text-yellow-400 border border-yellow-200 dark:border-yellow-800">
|
||
待审核
|
||
</div>
|
||
);
|
||
case 'draft':
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-gray-50 dark:bg-gray-950 text-gray-600 dark:text-gray-400 border border-gray-200 dark:border-gray-800">
|
||
草稿
|
||
</div>
|
||
);
|
||
default:
|
||
return (
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium border border-gray-200 dark:border-gray-800">
|
||
{result}
|
||
</div>
|
||
);
|
||
}
|
||
};
|
||
|
||
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) => (
|
||
<div className="flex items-center gap-2">
|
||
<Building className="w-4 h-4 text-blue-500" />
|
||
<span className="font-medium">{value}</span>
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
key: 'action',
|
||
label: '审核类型',
|
||
render: (value: string) => getActionBadge(value),
|
||
},
|
||
{
|
||
key: 'submitTime',
|
||
label: '提交时间',
|
||
render: (value: string, record: AuditLogData) => (
|
||
<div className="text-sm text-muted-foreground">
|
||
{record.action === 'SUBMIT' ? value : '-'}
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
key: 'actionTime',
|
||
label: '审核时间',
|
||
render: (value: string, record: AuditLogData) => (
|
||
<div className="text-sm text-muted-foreground">
|
||
{record.action === 'AUDIT' ? value : '-'}
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
key: 'actionBy',
|
||
label: '审核人',
|
||
render: (value: string) => value ? (
|
||
<div className="flex items-center gap-2">
|
||
<User className="w-4 h-4 text-gray-500" />
|
||
<span>{value}</span>
|
||
</div>
|
||
) : '-',
|
||
},
|
||
{
|
||
key: 'result',
|
||
label: '审核结果',
|
||
render: (value: string) => getResultBadge(value),
|
||
},
|
||
{
|
||
key: 'actions',
|
||
label: '操作',
|
||
render: (_: any, row: AuditLogData) => (
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
onClick={() => handleView(row)}
|
||
>
|
||
<FileText className="w-3 h-3 mr-1" />
|
||
详情
|
||
</Button>
|
||
),
|
||
},
|
||
];
|
||
// 简化的状态管理 - 只需要存储数据和加载状态
|
||
const [records, setRecords] = useState<AuditRecord[]>([]);
|
||
const [pagination, setPagination] = useState<PaginationState>({
|
||
page: 1,
|
||
size: 10,
|
||
total: 0,
|
||
totalPages: 0,
|
||
hasNext: false,
|
||
hasPrev: false,
|
||
});
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [searchFilters, setSearchFilters] = useState<Record<string, string>>({
|
||
search: '',
|
||
action: 'all',
|
||
audit_status: 'all',
|
||
date_range: 'all'
|
||
});
|
||
|
||
// 数据加载函数 - 优先从浏览器URL参数读取
|
||
const loadAuditHistory = useCallback(async (options: {
|
||
resetPage?: boolean;
|
||
filters?: Record<string, string>;
|
||
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<string, string>) => {
|
||
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<string, string>;
|
||
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 (
|
||
<div className="space-y-6">
|
||
{/* Page Header - 自定义页面头部 */}
|
||
<Card className="p-6 bg-gradient-to-r from-green-50 dark:from-green-950 to-emerald-50 dark:to-emerald-950 border-green-200 dark:border-green-800">
|
||
<div className="flex items-start justify-between">
|
||
<div className="flex items-start gap-3">
|
||
<FileText className="w-6 h-6 text-green-600 dark:text-green-400 flex-shrink-0 mt-1" />
|
||
<div className="flex-1">
|
||
<h2 className="mb-2">审核历史</h2>
|
||
<p className="text-sm text-muted-foreground mb-3">
|
||
追溯查询全部企业的历史审核记录,支持搜索筛选和详情查看
|
||
</p>
|
||
<div className="flex flex-wrap gap-2">
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800">
|
||
<Search className="w-3 h-3 mr-1" />
|
||
智能查询
|
||
</div>
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800">
|
||
<AlertCircle className="w-3 h-3 mr-1" />
|
||
状态筛选
|
||
</div>
|
||
<div className="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800">
|
||
<FileText className="w-3 h-3 mr-1" />
|
||
详情查看
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* 使用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: <FileText className="w-12 h-12 mx-auto mb-4 opacity-20" />,
|
||
emptyText: "暂无审核记录",
|
||
sizeOptions: [10, 20, 50, 100]
|
||
})}
|
||
|
||
{/* View Audit Record Details Dialog */}
|
||
<Dialog open={dialogs.showViewDialog} onOpenChange={(open) => dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: open })}>
|
||
<DialogContent className="w-[90vw] max-w-6xl max-h-[90vh]">
|
||
<DialogHeader>
|
||
<DialogTitle>审核记录详情</DialogTitle>
|
||
<DialogDescription>
|
||
查看审核记录的详细信息和企业快照数据
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
{dialogs.selectedRecord && (
|
||
<ScrollArea className="max-h-[calc(90vh-200px)]">
|
||
<Tabs defaultValue="basic" className="space-y-4">
|
||
<TabsList className="grid grid-cols-3 w-full">
|
||
<TabsTrigger value="basic">
|
||
<FileText className="w-4 h-4 mr-2" />
|
||
基本信息
|
||
</TabsTrigger>
|
||
<TabsTrigger value="snapshot">
|
||
<Building className="w-4 h-4 mr-2" />
|
||
企业快照
|
||
</TabsTrigger>
|
||
<TabsTrigger value="system">
|
||
<Smartphone className="w-4 h-4 mr-2" />
|
||
系统信息
|
||
</TabsTrigger>
|
||
</TabsList>
|
||
|
||
{/* 基本信息 */}
|
||
<TabsContent value="basic" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>企业名称</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.enterpriseName}</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核类型</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{getActionBadge(dialogs.selectedRecord.action)}</div>
|
||
</div>
|
||
<div>
|
||
<Label>提交时间</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
{dialogs.selectedRecord.action === 'SUBMIT' ? dialogs.selectedRecord.submitTime : '-'}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核时间</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
{dialogs.selectedRecord.action === 'AUDIT' ? dialogs.selectedRecord.actionTime : '-'}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核人</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.actionBy || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核结果</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{getResultBadge(dialogs.selectedRecord.result)}</div>
|
||
</div>
|
||
<div>
|
||
<Label>变更摘要</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md min-h-[80px] whitespace-pre-wrap">
|
||
{dialogs.selectedRecord.changeSummary || '-'}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核备注</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md min-h-[80px] whitespace-pre-wrap">
|
||
{dialogs.selectedRecord.auditComment || '-'}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
{/* 企业快照 */}
|
||
<TabsContent value="snapshot" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>企业类型</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.companyType || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>所在地区</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
{dialogs.selectedRecord.snapshot?.province} {dialogs.selectedRecord.snapshot?.city}
|
||
</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>详细地址</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.detailedAddress || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>登记人</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.registrant || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>联系电话</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.contactPhone || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>企业规模</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.companyScale || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>注册资本</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.registeredCapital || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>社会信用代码</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
<code className="text-sm">{dialogs.selectedRecord.snapshot?.socialCreditCode || '-'}</code>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>法人名称</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.legalPersonName || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>银行账号</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
<code className="text-sm">{dialogs.selectedRecord.snapshot?.bankAccount || '-'}</code>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>开户行</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.bankName || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>开户行全称</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.bankFullName || '-'}</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>开户行地址</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.snapshot?.bankAddress || '-'}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
{/* 系统信息 */}
|
||
<TabsContent value="system" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>记录ID</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
<code className="text-sm">{dialogs.selectedRecord.id}</code>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>企业ID</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
<code className="text-sm">{dialogs.selectedRecord.enterpriseId || '-'}</code>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>IP地址</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.ipAddress || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>用户代理</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md text-sm">
|
||
{dialogs.selectedRecord.userAgent || '-'}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>请求ID</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">
|
||
<code className="text-sm">{dialogs.selectedRecord.requestId || '-'}</code>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>创建时间</Label>
|
||
<div className="field-value p-3 bg-muted rounded-md">{dialogs.selectedRecord.createdAt}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</ScrollArea>
|
||
)}
|
||
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: false })}>
|
||
关闭
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</div>
|
||
);
|
||
} |