/**
* filekorolheader: 企业管理 - 企业信息管理与维护页面
* 功能:企业列表查询、详情查看、状态管理、分页筛选
* 路径:/central-config/tenant/enterprise-management
* 规范:遵循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 { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-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 { Building2, Eye, Power, PowerOff, Search, FileText, CreditCard, User, RefreshCw, AlertCircle, ChevronLeft, ChevronRight, Plus } from 'lucide-react';
import { toast } from 'sonner';
import { enterpriseReducer, initialState, EnterpriseState, EnterpriseAction } from './components/enterpriseReducer';
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 启用;
}
return 禁用;
};
const getAuditStatusBadge = (auditStatus: Enterprise['auditStatus']) => {
switch (auditStatus) {
case 'draft':
return 草稿;
case 'pending':
return 待审核;
case 'approved':
return 审核通过;
case 'rejected':
return 已拒绝;
default:
return 草稿;
}
};
export default function EnterpriseManagement() {
const [state, dispatch] = useReducer(enterpriseReducer, initialState);
// 加载企业数据
const loadEnterprises = async (resetPage = false) => {
try {
dispatch({ type: 'SET_LOADING', payload: true });
const params: TenantsQueryParams = {
search: state.filters.search || undefined,
audit_status: state.filters.audit_status || undefined,
page: resetPage ? 1 : state.pagination.page,
size: state.pagination.size,
order_by: state.sortBy,
sort_order: state.sortOrder,
};
const response = await fetchTenants(params);
const transformedData = response.data.map(transformTenantData);
console.log('API Response:', response);
console.log('Transformed Data:', transformedData);
dispatch({
type: 'SET_ENTERPRISES',
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 enterprises:', error);
const errorMessage = error instanceof Error ? error.message : '加载企业数据失败';
dispatch({ type: 'SET_ERROR', payload: errorMessage });
toast.error(errorMessage);
}
};
// 初始加载
useEffect(() => {
loadEnterprises(true);
}, [state.filters.search, state.filters.audit_status, state.sortBy, state.sortOrder]);
// 分页加载
useEffect(() => {
if (state.pagination.page > 1) {
loadEnterprises(false);
}
}, [state.pagination.page]);
// 计算统计数据
const stats = useMemo(() => ({
total: state.enterprises.length,
active: state.enterprises.filter(e => e.status === 'active').length,
inactive: state.enterprises.filter(e => e.status === 'inactive').length,
}), [state.enterprises]);
// 事件处理器
const handleSearch = (value: string) => {
dispatch({ type: 'SET_FILTERS', payload: { search: value } });
};
const handleAuditStatusFilter = (value: string) => {
dispatch({ type: 'SET_FILTERS', payload: { audit_status: value === 'all' ? '' : 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 handleRefresh = () => {
dispatch({ type: 'REFRESH_DATA' });
loadEnterprises(true);
toast.success('数据已刷新');
};
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 handleCreateNew = () => {
dispatch({ type: 'RESET_FORM_DATA' });
dispatch({ type: 'TOGGLE_ADD_DIALOG', payload: true });
};
const handleCreateSuccess = () => {
// 创建成功后刷新数据
loadEnterprises(true);
};
const confirmStatusChange = async () => {
if (!state.selectedEnterprise) return;
try {
dispatch({ type: 'SET_LOADING', payload: true });
const tenantId = state.selectedEnterprise.id;
let updatedTenant;
if (state.statusAction === 'enable') {
updatedTenant = await enableTenant(tenantId);
toast.success('企业已启用');
} else {
updatedTenant = await disableTenant(tenantId);
toast.success('企业已禁用');
}
// 验证返回的数据是否正确更新了状态
console.log('API返回的更新数据:', updatedTenant);
// 更新本地状态
const updatedEnterprise = transformTenantData(updatedTenant);
dispatch({
type: 'SET_ENTERPRISES',
payload: {
data: state.enterprises.map(ent =>
ent.id === tenantId ? updatedEnterprise : ent
),
pagination: state.pagination
}
});
dispatch({ type: 'TOGGLE_STATUS_DIALOG', payload: false });
// 不需要立即刷新,因为本地状态已经更新
// 如果用户需要看到最新数据,可以手动点击刷新按钮
} catch (error) {
console.error('Status change failed:', error);
const errorMessage = error instanceof Error ? error.message : '状态更新失败';
toast.error(errorMessage);
} finally {
dispatch({ type: 'SET_LOADING', payload: false });
}
};
return (
{/* Page Header */}
企业管理
管理平台所有企业信息,支持查询、查看详情、启用/禁用企业
{/* Statistics Cards */}
{state.pagination.total}
全部企业数量
{stats.active}
正常运营中
{stats.inactive}
已暂停使用
{/* Enterprise List */}
{/* Error Display */}
{state.error && (
)}
{/* Loading State */}
{state.loading && (
)}
{/* Data Table */}
{!state.loading && !state.error && (
<>
handleSort('tenant_code')}
>
企业编码
{state.sortBy === 'tenant_code' && (
{state.sortOrder === 'asc' ? '↑' : '↓'}
)}
handleSort('company_name')}
>
企业名称
{state.sortBy === 'company_name' && (
{state.sortOrder === 'asc' ? '↑' : '↓'}
)}
企业类型
登记人
联系电话
handleSort('created_at')}
>
创建时间
{state.sortBy === 'created_at' && (
{state.sortOrder === 'asc' ? '↑' : '↓'}
)}
审核状态
状态
操作
{state.enterprises.map((enterprise) => (
{enterprise.code}
{enterprise.name}
{enterprise.type}
{enterprise.registrant || '-'}
{enterprise.contactPhone || '-'}
{enterprise.createdAt}
{getAuditStatusBadge(enterprise.auditStatus)}
{getStatusBadge(enterprise.status)}
{enterprise.status === 'active' ? (
) : (
)}
))}
{state.enterprises.length === 0 && (
)}
{/* Pagination */}
{state.pagination.totalPages > 1 && (
显示第 {state.pagination.page} 页,共 {state.pagination.totalPages} 页
总计 {state.pagination.total} 条记录
{state.pagination.page} / {state.pagination.totalPages}
)}
>
)}
{/* View Enterprise Details Dialog */}
{/* Status Change Confirmation Dialog */}
dispatch({ type: 'TOGGLE_STATUS_DIALOG', payload: open })}>
确认{state.statusAction === 'enable' ? '启用' : '禁用'}企业
{state.statusAction === 'enable' ? (
<>
启用企业 {state.selectedEnterprise?.name} 后,该企业用户将恢复正常登录和使用权限。
>
) : (
<>
禁用企业 {state.selectedEnterprise?.name} 后,该企业所有用户将无法登录系统。此操作不会删除企业数据,可随时重新启用。
>
)}
取消
确认{state.statusAction === 'enable' ? '启用' : '禁用'}
{/* Create Enterprise Dialog */}
dispatch({ type: 'TOGGLE_ADD_DIALOG', payload: open })}
onSuccess={handleCreateSuccess}
/>
);
}