708 lines
28 KiB
TypeScript
708 lines
28 KiB
TypeScript
/**
|
||
* filekorolheader: 企业管理 - 企业信息管理与维护页面
|
||
* 功能:企业列表查询、详情查看、状态管理、分页筛选
|
||
* 路径:/central-config/tenant/enterprise-management
|
||
* 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,API集成,shadcn语义化样式
|
||
*/
|
||
'use client';
|
||
|
||
import { useEffect, useMemo, useState, useCallback } from 'react';
|
||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
|
||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-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 { Building2, Eye, Power, PowerOff, Plus, FileText, CreditCard, User, Search } from 'lucide-react';
|
||
import { toast } from 'sonner';
|
||
|
||
import SearchFormPagination, {
|
||
type SearchFieldConfig,
|
||
type TableColumnConfig
|
||
} from '@/components/common/searchFormPagination';
|
||
|
||
import { fetchTenants, transformTenantData, enableTenant, disableTenant, createEnterprise, TenantsQueryParams, Enterprise } from './components/enterpriseApi';
|
||
import { CreateEnterpriseDialog } from './components/CreateEnterpriseDialog';
|
||
|
||
// Utility functions
|
||
const getStatusBadge = (status: 'active' | 'inactive') => {
|
||
if (status === 'active') {
|
||
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>
|
||
);
|
||
}
|
||
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>
|
||
);
|
||
};
|
||
|
||
const getAuditStatusBadge = (auditStatus: Enterprise['auditStatus']) => {
|
||
switch (auditStatus) {
|
||
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>
|
||
);
|
||
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 '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>
|
||
);
|
||
default:
|
||
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>
|
||
);
|
||
}
|
||
};
|
||
|
||
export default function EnterpriseManagement() {
|
||
// 对话框状态管理
|
||
const [dialogs, setDialogs] = useState({
|
||
showViewDialog: false,
|
||
showAddDialog: false,
|
||
showStatusDialog: false,
|
||
selectedEnterprise: null as Enterprise | null,
|
||
statusAction: 'enable' as 'enable' | 'disable'
|
||
});
|
||
|
||
const dispatch = (action: any) => {
|
||
switch (action.type) {
|
||
case 'SET_SELECTED_ENTERPRISE':
|
||
setDialogs(prev => ({ ...prev, selectedEnterprise: action.payload }));
|
||
break;
|
||
case 'TOGGLE_VIEW_DIALOG':
|
||
setDialogs(prev => ({ ...prev, showViewDialog: action.payload }));
|
||
break;
|
||
case 'TOGGLE_ADD_DIALOG':
|
||
setDialogs(prev => ({ ...prev, showAddDialog: action.payload }));
|
||
break;
|
||
case 'TOGGLE_STATUS_DIALOG':
|
||
setDialogs(prev => ({ ...prev, showStatusDialog: action.payload }));
|
||
break;
|
||
case 'SET_STATUS_ACTION':
|
||
setDialogs(prev => ({ ...prev, statusAction: action.payload }));
|
||
break;
|
||
case 'RESET_FORM_DATA':
|
||
setDialogs(prev => ({ ...prev, selectedEnterprise: null }));
|
||
break;
|
||
}
|
||
};
|
||
|
||
// 搜索字段配置
|
||
const searchFields: SearchFieldConfig[] = [
|
||
{
|
||
key: 'search',
|
||
label: '搜索',
|
||
type: 'text',
|
||
placeholder: '搜索企业名称、编码...',
|
||
},
|
||
{
|
||
key: 'audit_status',
|
||
label: '审核状态',
|
||
type: 'select',
|
||
placeholder: '审核状态',
|
||
defaultValue: 'all',
|
||
options: [
|
||
{ value: 'all', label: '全部状态' },
|
||
{ value: '草稿', label: '草稿' },
|
||
{ value: '待审核', label: '待审核' },
|
||
{ value: '已通过', label: '审核通过' },
|
||
{ value: '已拒绝', label: '已拒绝' },
|
||
],
|
||
},
|
||
];
|
||
|
||
// 表格列配置
|
||
const columns: TableColumnConfig[] = [
|
||
{
|
||
key: 'code',
|
||
label: '企业编码',
|
||
width: '120px',
|
||
},
|
||
{
|
||
key: 'name',
|
||
label: '企业名称',
|
||
render: (value: string) => (
|
||
<div className="flex items-center gap-2">
|
||
<Building2 className="w-4 h-4 text-blue-500" />
|
||
<span className="font-medium">{value}</span>
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
key: 'type',
|
||
label: '企业类型',
|
||
render: (value: string) => (
|
||
<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">
|
||
{value}
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
key: 'registrant',
|
||
label: '登记人',
|
||
render: (value?: string) => value || '-',
|
||
},
|
||
{
|
||
key: 'contactPhone',
|
||
label: '联系电话',
|
||
render: (value?: string) => value || '-',
|
||
},
|
||
{
|
||
key: 'createdAt',
|
||
label: '创建时间',
|
||
width: '160px',
|
||
},
|
||
{
|
||
key: 'auditStatus',
|
||
label: '审核状态',
|
||
render: (value: Enterprise['auditStatus']) => getAuditStatusBadge(value),
|
||
},
|
||
{
|
||
key: 'status',
|
||
label: '状态',
|
||
render: (value: Enterprise['status']) => getStatusBadge(value),
|
||
},
|
||
{
|
||
key: 'actions',
|
||
label: '操作',
|
||
render: (_: any, row: Enterprise) => (
|
||
<div className="flex gap-2">
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
onClick={() => handleView(row)}
|
||
>
|
||
<Eye className="w-3 h-3 mr-1" />
|
||
查看
|
||
</Button>
|
||
{row.status === 'active' ? (
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
className="text-gray-600 dark:text-gray-400 border-gray-300 dark:border-gray-600"
|
||
onClick={() => handleStatusChange(row, 'disable')}
|
||
>
|
||
<PowerOff className="w-3 h-3 mr-1" />
|
||
禁用
|
||
</Button>
|
||
) : (
|
||
<Button
|
||
size="sm"
|
||
variant="outline"
|
||
className="text-green-600 dark:text-green-400 border-green-300 dark:border-green-600"
|
||
onClick={() => handleStatusChange(row, 'enable')}
|
||
>
|
||
<Power className="w-3 h-3 mr-1" />
|
||
启用
|
||
</Button>
|
||
)}
|
||
</div>
|
||
),
|
||
},
|
||
];
|
||
|
||
|
||
// 简化的状态管理 - 只需要存储数据和加载状态
|
||
const [enterprises, setEnterprises] = useState<Enterprise[]>([]);
|
||
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<string | null>(null);
|
||
const [searchFilters, setSearchFilters] = useState<Record<string, string>>({
|
||
search: '',
|
||
audit_status: 'all'
|
||
});
|
||
|
||
// 数据加载函数 - 移除不必要的依赖避免重复调用
|
||
const loadEnterprises = useCallback(async (params?: {
|
||
filters?: Record<string, string>;
|
||
pagination?: { page: number; size: number };
|
||
sort?: { sortBy?: string; sortOrder?: 'asc' | 'desc' };
|
||
}) => {
|
||
try {
|
||
console.log('调用了loadEnterprises')
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
const finalParams: TenantsQueryParams = {
|
||
search: (params?.filters?.search ?? searchFilters.search) || undefined,
|
||
audit_status: params?.filters?.audit_status ?? searchFilters.audit_status,
|
||
page: params?.pagination?.page || pagination.page,
|
||
size: params?.pagination?.size || pagination.size,
|
||
order_by: params?.sort?.sortBy,
|
||
sort_order: params?.sort?.sortOrder,
|
||
};
|
||
|
||
// 处理audit_status,如果为'all'则不传该参数
|
||
if (finalParams.audit_status === 'all') {
|
||
finalParams.audit_status = undefined;
|
||
}
|
||
const response = await fetchTenants(finalParams);
|
||
const transformedData = response.data.map(transformTenantData);
|
||
|
||
setEnterprises(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 = useCallback((filters: Record<string, string>) => {
|
||
setSearchFilters(filters);
|
||
// 搜索时重置到第一页
|
||
loadEnterprises({
|
||
filters,
|
||
pagination: { page: 1, size: pagination.size }
|
||
});
|
||
}, [loadEnterprises, pagination.size]);
|
||
|
||
const handleSort = useCallback((sortBy: string, sortOrder: 'asc' | 'desc') => {
|
||
// 排序时重置到第一页
|
||
loadEnterprises({
|
||
pagination: { page: 1, size: pagination.size },
|
||
sort: { sortBy, sortOrder }
|
||
});
|
||
}, [loadEnterprises, pagination.size]);
|
||
|
||
const handlePageChange = useCallback((page: number) => {
|
||
setPagination(prev => ({ ...prev, page }));
|
||
loadEnterprises({
|
||
pagination: { page, size: pagination.size }
|
||
});
|
||
}, [loadEnterprises, pagination.size]);
|
||
|
||
const handleSizeChange = useCallback((size: number) => {
|
||
setPagination(prev => ({ ...prev, size, page: 1 }));
|
||
loadEnterprises({
|
||
pagination: { page: 1, size }
|
||
});
|
||
}, [loadEnterprises]);
|
||
|
||
// 初始化数据加载
|
||
// useEffect(() => {
|
||
// loadEnterprises();
|
||
// }, []);
|
||
|
||
// 计算统计数据
|
||
const stats = useMemo(() => {
|
||
if (enterprises.length === 0) {
|
||
return { total: pagination.total, active: 0, inactive: 0 };
|
||
}
|
||
const active = enterprises.filter(e => e.status === 'active').length;
|
||
const inactive = enterprises.filter(e => e.status === 'inactive').length;
|
||
return { total: pagination.total, active, inactive };
|
||
}, [enterprises, pagination.total]);
|
||
|
||
// 业务事件处理器
|
||
const handleView = (enterprise: Enterprise) => {
|
||
dispatch({ type: 'SET_SELECTED_ENTERPRISE', payload: enterprise });
|
||
dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: true });
|
||
};
|
||
|
||
const handleStatusChange = (enterprise: Enterprise, action: 'enable' | 'disable') => {
|
||
dispatch({ type: 'SET_SELECTED_ENTERPRISE', payload: enterprise });
|
||
dispatch({ type: 'SET_STATUS_ACTION', payload: action });
|
||
dispatch({ type: 'TOGGLE_STATUS_DIALOG', payload: true });
|
||
};
|
||
|
||
const confirmStatusChange = async () => {
|
||
if (!dialogs.selectedEnterprise) return;
|
||
|
||
try {
|
||
setLoading(true);
|
||
|
||
const tenantId = dialogs.selectedEnterprise.id;
|
||
let updatedTenant;
|
||
|
||
if (dialogs.statusAction === 'enable') {
|
||
updatedTenant = await enableTenant(tenantId);
|
||
toast.success('企业已启用');
|
||
} else {
|
||
updatedTenant = await disableTenant(tenantId);
|
||
toast.success('企业已禁用');
|
||
}
|
||
|
||
// 状态更新成功后关闭对话框
|
||
dispatch({ type: 'TOGGLE_STATUS_DIALOG', payload: false });
|
||
|
||
// 重新加载数据来反映状态变化
|
||
const reloadParams: any = {
|
||
filters: searchFilters,
|
||
pagination: {
|
||
page: pagination.page,
|
||
size: pagination.size
|
||
}
|
||
};
|
||
|
||
loadEnterprises(reloadParams);
|
||
} catch (error) {
|
||
console.error('Status change failed:', error);
|
||
const errorMessage = error instanceof Error ? error.message : '状态更新失败';
|
||
toast.error(errorMessage);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleCreateNew = () => {
|
||
dispatch({ type: 'RESET_FORM_DATA' });
|
||
dispatch({ type: 'TOGGLE_ADD_DIALOG', payload: true });
|
||
};
|
||
|
||
const handleCreateSuccess = () => {
|
||
// 创建成功后需要手动刷新页面数据
|
||
window.location.reload();
|
||
};
|
||
|
||
// 操作按钮配置
|
||
const actionButtons = (
|
||
<Button onClick={handleCreateNew} disabled={loading}>
|
||
<Plus className="w-4 h-4 mr-2" />
|
||
新建企业
|
||
</Button>
|
||
);
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* Page Header - 自定义页面头部 */}
|
||
<Card className="p-6 bg-gradient-to-r from-blue-50 dark:from-blue-950 to-indigo-50 dark:to-indigo-950 border-blue-200 dark:border-blue-800">
|
||
<div className="flex items-start justify-between">
|
||
<div className="flex items-start gap-3">
|
||
<Building2 className="w-6 h-6 text-blue-600 dark:text-blue-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">
|
||
<Power 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">
|
||
<Eye className="w-3 h-3 mr-1" />
|
||
详情查看
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* Statistics Cards - 保持原有统计功能 */}
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<div className="p-6 bg-card hover:bg-muted transition-colors border rounded-lg">
|
||
<div className="flex items-center justify-between mb-2">
|
||
<div className="text-sm text-muted-foreground">企业总数</div>
|
||
<Building2 className="w-5 h-5 text-blue-500" />
|
||
</div>
|
||
<div className="text-3xl font-bold mb-1">{pagination.total}</div>
|
||
<div className="text-xs text-muted-foreground">
|
||
全部企业数量
|
||
</div>
|
||
</div>
|
||
|
||
<div className="p-6 bg-card hover:bg-muted transition-colors border rounded-lg">
|
||
<div className="flex items-center justify-between mb-2">
|
||
<div className="text-sm text-muted-foreground">启用企业</div>
|
||
<Power className="w-5 h-5 text-green-500" />
|
||
</div>
|
||
<div className="text-3xl font-bold mb-1 text-green-600 dark:text-green-400">{stats.active}</div>
|
||
<div className="text-xs text-green-600 dark:text-green-400">
|
||
正常运营中
|
||
</div>
|
||
</div>
|
||
|
||
<div className="p-6 bg-card hover:bg-muted transition-colors border rounded-lg">
|
||
<div className="flex items-center justify-between mb-2">
|
||
<div className="text-sm text-muted-foreground">禁用企业</div>
|
||
<PowerOff className="w-5 h-5 text-gray-500" />
|
||
</div>
|
||
<div className="text-3xl font-bold mb-1 text-gray-600 dark:text-gray-400">{stats.inactive}</div>
|
||
<div className="text-xs text-muted-foreground">
|
||
已暂停使用
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 使用SearchFormPagination组件替换原有的企业列表 */}
|
||
<SearchFormPagination
|
||
formTitle="企业列表"
|
||
formRightContent={actionButtons}
|
||
searchFields={searchFields}
|
||
columns={columns}
|
||
data={enterprises}
|
||
loading={loading}
|
||
error={error}
|
||
pagination={pagination}
|
||
onPageChange={handlePageChange}
|
||
onSizeChange={handleSizeChange}
|
||
onSearch={handleSearch}
|
||
onSort={handleSort}
|
||
emptyIcon={<Building2 className="w-12 h-12 mx-auto mb-4 opacity-20" />}
|
||
emptyText="暂无企业数据"
|
||
/>
|
||
|
||
{/* View Enterprise Details Dialog */}
|
||
<Dialog open={dialogs.showViewDialog} onOpenChange={(open) => dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: open })}>
|
||
<DialogContent className="w-[80vw] max-w-6xl max-h-[90vh]">
|
||
<DialogHeader>
|
||
<div className="flex items-center justify-between pr-8">
|
||
<DialogTitle>企业详情</DialogTitle>
|
||
{dialogs.selectedEnterprise && (
|
||
<div className="flex gap-2">
|
||
{getAuditStatusBadge(dialogs.selectedEnterprise.auditStatus)}
|
||
{getStatusBadge(dialogs.selectedEnterprise.status)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
<DialogDescription className="sr-only">
|
||
查看企业的详细信息
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
{dialogs.selectedEnterprise && (
|
||
<ScrollArea className="max-h-[calc(90vh-200px)]">
|
||
<Tabs defaultValue="basic" className="space-y-4">
|
||
<TabsList className="grid grid-cols-4 w-full">
|
||
<TabsTrigger value="basic">
|
||
<Building2 className="w-4 h-4 mr-2" />
|
||
基本信息
|
||
</TabsTrigger>
|
||
<TabsTrigger value="other">
|
||
<FileText className="w-4 h-4 mr-2" />
|
||
其他信息
|
||
</TabsTrigger>
|
||
<TabsTrigger value="bank">
|
||
<CreditCard className="w-4 h-4 mr-2" />
|
||
开户信息
|
||
</TabsTrigger>
|
||
<TabsTrigger value="legal">
|
||
<User className="w-4 h-4 mr-2" />
|
||
法人信息
|
||
</TabsTrigger>
|
||
</TabsList>
|
||
|
||
{/* Basic Information */}
|
||
<TabsContent value="basic" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>企业名称</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.name}</div>
|
||
</div>
|
||
<div>
|
||
<Label>企业编码</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.code}</div>
|
||
</div>
|
||
<div>
|
||
<Label>企业类型</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.type}</div>
|
||
</div>
|
||
<div>
|
||
<Label>所在地区</Label>
|
||
<div className="field-value p-2 bg-muted rounded">
|
||
{dialogs.selectedEnterprise.province || '-'} {dialogs.selectedEnterprise.city || ''} {dialogs.selectedEnterprise.district || ''}
|
||
</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>详细地址</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.address || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>登记人</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.registrant || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>联系电话</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.contactPhone || '-'}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
{/* Other Information */}
|
||
<TabsContent value="other" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>公司规模</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.companySize || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>注册资本</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.registeredCapital || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>成立时间</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.establishmentDate || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>发票类型</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.invoiceType || '-'}</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>社会信用代码</Label>
|
||
<div className="field-value p-2 bg-muted rounded">
|
||
{dialogs.selectedEnterprise.socialCreditCode ? (
|
||
<code className="text-sm font-mono">
|
||
{dialogs.selectedEnterprise.socialCreditCode}
|
||
</code>
|
||
) : '-'}
|
||
</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>经营范围</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.businessScope || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>提交时间</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.submitTime || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核时间</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.auditTime || '-'}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
{/* Bank Information */}
|
||
<TabsContent value="bank" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>银行账号</Label>
|
||
<div className="field-value p-2 bg-muted rounded">
|
||
{dialogs.selectedEnterprise.bankAccount ? (
|
||
<code className="text-sm font-mono">
|
||
{dialogs.selectedEnterprise.bankAccount}
|
||
</code>
|
||
) : '-'}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<Label>开户行</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.bankName || '-'}</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>开户行全称</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.bankFullName || '-'}</div>
|
||
</div>
|
||
<div className="col-span-2">
|
||
<Label>开户行地址</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.bankAddress || '-'}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
{/* Legal Person Information */}
|
||
<TabsContent value="legal" className="space-y-4">
|
||
<div className="grid grid-cols-2 gap-6">
|
||
<div>
|
||
<Label>法人姓名</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.legalPerson || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>联系人</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.registrant || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核人</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.auditor || '-'}</div>
|
||
</div>
|
||
<div>
|
||
<Label>审核意见</Label>
|
||
<div className="field-value p-2 bg-muted rounded">{dialogs.selectedEnterprise.auditComment || '-'}</div>
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</ScrollArea>
|
||
)}
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => dispatch({ type: 'TOGGLE_VIEW_DIALOG', payload: false })}>
|
||
关闭
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
|
||
{/* Status Change Confirmation Dialog */}
|
||
<AlertDialog open={dialogs.showStatusDialog} onOpenChange={(open) => dispatch({ type: 'TOGGLE_STATUS_DIALOG', payload: open })}>
|
||
<AlertDialogContent className="w-[80vw] max-w-md">
|
||
<AlertDialogHeader>
|
||
<AlertDialogTitle>
|
||
确认{dialogs.statusAction === 'enable' ? '启用' : '禁用'}企业
|
||
</AlertDialogTitle>
|
||
<AlertDialogDescription>
|
||
{dialogs.statusAction === 'enable' ? (
|
||
<>
|
||
启用企业 <strong>{dialogs.selectedEnterprise?.name}</strong> 后,该企业用户将恢复正常登录和使用权限。
|
||
</>
|
||
) : (
|
||
<>
|
||
禁用企业 <strong>{dialogs.selectedEnterprise?.name}</strong> 后,该企业所有用户将无法登录系统。此操作不会删除企业数据,可随时重新启用。
|
||
</>
|
||
)}
|
||
</AlertDialogDescription>
|
||
</AlertDialogHeader>
|
||
<AlertDialogFooter>
|
||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||
<AlertDialogAction
|
||
onClick={confirmStatusChange}
|
||
className={dialogs.statusAction === 'enable' ? 'bg-green-600 hover:bg-green-700' : 'bg-gray-600 hover:bg-gray-700'}
|
||
>
|
||
确认{dialogs.statusAction === 'enable' ? '启用' : '禁用'}
|
||
</AlertDialogAction>
|
||
</AlertDialogFooter>
|
||
</AlertDialogContent>
|
||
</AlertDialog>
|
||
|
||
{/* Create Enterprise Dialog */}
|
||
<CreateEnterpriseDialog
|
||
open={dialogs.showAddDialog}
|
||
onOpenChange={(open) => dispatch({ type: 'TOGGLE_ADD_DIALOG', payload: open })}
|
||
onSuccess={handleCreateSuccess}
|
||
/>
|
||
</div>
|
||
);
|
||
} |