import { useEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Building2, DollarSign, Plus, Trash2, TrendingDown, TrendingUp } from 'lucide-react'; import { adminApi, type TenantManagementRow } from '@/api/adminApi'; import { Breadcrumb, Button, Input, ManualRechargeDialog, Modal, Select, Table, Tag, type TableColumn } from '@/components/ui'; import { formatCents } from '@/utils/currency'; type AdminCustomersPageProps = { basePath?: string; }; type CustomerRow = TenantManagementRow; function ConfirmModal({ error, isSubmitting, message, onCancel, onConfirm, type, }: { error: string; isSubmitting: boolean; message: string; onCancel: () => void; onConfirm: () => void; type: 'toggle' | 'delete'; }) { return ( } onClose={() => { if (!isSubmitting) onCancel(); }} open title={type === 'delete' ? '删除企业' : '变更企业状态'} >

{message}

{error ?

{error}

: null}
); } export function AdminCustomersPage({ basePath = '/admin/customers' }: AdminCustomersPageProps) { const navigate = useNavigate(); const [records, setRecords] = useState([]); const [queryName, setQueryName] = useState(''); const [queryStatus, setQueryStatus] = useState('all'); const [filters, setFilters] = useState({ name: '', status: 'all' }); const [confirmAction, setConfirmAction] = useState<{ type: 'toggle' | 'delete'; record: CustomerRow } | null>(null); const [confirmError, setConfirmError] = useState(''); const [confirming, setConfirming] = useState(false); const [rechargeTarget, setRechargeTarget] = useState(null); const [error, setError] = useState(''); function loadData() { adminApi.listTenantManagementRows() .then((items) => { setRecords(items); setError(''); }) .catch((failure: Error) => setError(failure.message || '企业列表加载失败')); } useEffect(() => { loadData(); }, []); const filteredRecords = useMemo(() => records.filter((record) => { const matchName = filters.name ? record.name.includes(filters.name) : true; const matchStatus = filters.status === 'all' ? true : record.status === filters.status; return matchName && matchStatus; }), [filters, records]); const activeCount = records.filter((record) => record.status === 'active').length; const disabledCount = records.filter((record) => record.status === 'disabled').length; const totalBalance = records.reduce((sum, record) => sum + (record.account?.balanceCents ?? 0), 0); const columns: Array> = [ { key: 'name', title: '企业名称', width: '260px', render: (record) => {record.name} }, { key: 'balance', title: '当前余额', width: '150px', align: 'right', render: (record) => { const balance = record.account?.balanceCents ?? 0; return ( ¥{formatCents(balance)} {balance < 0 ? 欠费 : null} ); }, }, { key: 'creditLimit', title: '授信额度', width: '150px', align: 'right', render: (record) => `¥${formatCents(record.account?.creditCents ?? 0)}` }, { key: 'todaySpend', title: '今日消费', width: '150px', align: 'right', render: (record) => `¥${formatCents(record.todaySpendCents)}` }, { key: 'todayRefund', title: '今日返还', width: '150px', align: 'right', render: (record) => `¥${formatCents(record.todayRefundCents)}` }, { key: 'status', title: '企业状态', width: '130px', render: (record) => {record.status === 'active' ? '正常' : '已禁用'} }, { key: 'actions', title: '操作', align: 'right', width: '300px', render: (record) => (
), }, ]; function openRechargeModal(record: CustomerRow) { setRechargeTarget(record); } function openConfirmAction(action: { type: 'toggle' | 'delete'; record: CustomerRow }) { setConfirmError(''); setConfirmAction(action); } async function submitConfirmAction() { if (!confirmAction) return; setConfirming(true); setConfirmError(''); try { if (confirmAction.type === 'delete') { await adminApi.deleteTenant(confirmAction.record.id); } else { await adminApi.changeTenantStatus(confirmAction.record.id, confirmAction.record.status === 'active' ? 'disabled' : 'active'); } } catch (failure) { const detail = failure instanceof Error ? failure.message : '企业操作失败'; setConfirmError(`${confirmAction.type === 'delete' ? '删除' : '状态变更'}失败:${detail}`); setConfirming(false); return; } setConfirmAction(null); try { await loadData(); } catch (failure) { setError(failure instanceof Error ? failure.message : '企业列表刷新失败'); } finally { setConfirming(false); } } return (
{error ?

{error}

: null}
企业总数{records.length}真实租户数量。
正常运营{activeCount}可正常提交发送任务。
已禁用{disabledCount}已暂停发送能力。
账户余额¥{formatCents(totalBalance)}企业账户余额汇总。

查询条件

setQueryName(event.target.value)} placeholder="请输入企业名称" value={queryName} />