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, MoneyText, 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 ( 取消{isSubmitting ? '处理中...' : '确认'}>} 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) => ( } onClick={() => openRechargeModal(record)} size="sm" variant="ghost">充值 navigate(`${basePath}/${record.id}/edit`)} size="sm" variant="ghost">编辑 openConfirmAction({ type: 'toggle', record })} size="sm" variant={record.status === 'active' ? 'warning' : 'success'}> {record.status === 'active' ? '禁用' : '启用'} } onClick={() => openConfirmAction({ type: 'delete', record })} size="sm" variant="danger">删除 ), }, ]; 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 ( } onClick={() => navigate(`${basePath}/new`)}>添加企业 {error ? {error} : null} 企业总数{records.length}真实租户数量。 正常运营{activeCount}可正常提交发送任务。 已禁用{disabledCount}已暂停发送能力。 账户余额¥{formatCents(totalBalance)}企业账户余额汇总。 查询条件 setQueryName(event.target.value)} placeholder="请输入企业名称" value={queryName} /> setQueryStatus(event.target.value)} options={[{ label: '全部状态', value: 'all' }, { label: '正常', value: 'active' }, { label: '禁用', value: 'disabled' }]} value={queryStatus} /> setFilters({ name: queryName, status: queryStatus })} variant="secondary">查询 { setQueryName(''); setQueryStatus('all'); setFilters({ name: '', status: 'all' }); }} variant="ghost">重置 企业列表{filteredRecords.length} 条 {confirmAction ? ( { setConfirmAction(null); setConfirmError(''); }} onConfirm={() => void submitConfirmAction()} type={confirmAction.type} /> ) : null} setRechargeTarget(null)} onCompleted={loadData} open={Boolean(rechargeTarget)} targets={rechargeTarget ? [{ id: rechargeTarget.id, name: rechargeTarget.name, code: rechargeTarget.code, balanceCents: rechargeTarget.account?.balanceCents ?? 0, }] : []} /> ); }
{message}
{error}