103 lines
6.8 KiB
TypeScript
103 lines
6.8 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react';
|
|
import { useNavigate, useParams } from 'react-router-dom';
|
|
import { ArrowLeft, FileText, MessageSquare, Server } from 'lucide-react';
|
|
import { adminApi, type ClientSmsSignature, type ClientSmsTemplate, type EnterpriseApplication, type TenantAccount, type TenantOption } from '@/api/adminApi';
|
|
import { Breadcrumb, Button, Table, Tag, type TableColumn } from '@/components/ui';
|
|
|
|
export function AdminCustomerDetailPage() {
|
|
const navigate = useNavigate();
|
|
const { enterpriseId } = useParams();
|
|
const [tenant, setTenant] = useState<TenantOption | null>(null);
|
|
const [account, setAccount] = useState<TenantAccount | null>(null);
|
|
const [applications, setApplications] = useState<EnterpriseApplication[]>([]);
|
|
const [signatures, setSignatures] = useState<ClientSmsSignature[]>([]);
|
|
const [templates, setTemplates] = useState<ClientSmsTemplate[]>([]);
|
|
const [error, setError] = useState('');
|
|
|
|
useEffect(() => {
|
|
if (!enterpriseId) return;
|
|
Promise.all([
|
|
adminApi.getTenant(enterpriseId),
|
|
adminApi.listAccounts(),
|
|
adminApi.listEnterpriseApplications({ tenantId: enterpriseId }),
|
|
adminApi.listEnterpriseSignatures({ tenantId: enterpriseId }),
|
|
adminApi.listEnterpriseTemplates({ tenantId: enterpriseId }),
|
|
])
|
|
.then(([tenantItem, accounts, applicationItems, signatureItems, templateItems]) => {
|
|
setTenant(tenantItem);
|
|
setAccount(accounts.find((item) => item.tenantId === enterpriseId) ?? null);
|
|
setApplications(applicationItems);
|
|
setSignatures(Array.isArray(signatureItems) ? signatureItems : []);
|
|
setTemplates(Array.isArray(templateItems) ? templateItems : []);
|
|
setError('');
|
|
})
|
|
.catch((failure: Error) => setError(failure.message || '企业详情加载失败'));
|
|
}, [enterpriseId]);
|
|
|
|
const appColumns = useMemo<Array<TableColumn<EnterpriseApplication>>>(() => [
|
|
{ key: 'name', title: '应用名称', render: (record) => <strong>{record.name}</strong> },
|
|
{ key: 'scene', title: '场景', render: (record) => record.scene ?? '-' },
|
|
{ key: 'status', title: '状态', render: (record) => <Tag tone={record.status === 'active' ? 'success' : 'warning'}>{record.status}</Tag> },
|
|
{ key: 'cmpp', title: 'CMPP 状态', render: (record) => record.cmppStatus ?? '-' },
|
|
], []);
|
|
|
|
const signatureColumns = useMemo<Array<TableColumn<ClientSmsSignature>>>(() => [
|
|
{ key: 'name', title: '签名', render: (record) => <strong>{record.name}</strong> },
|
|
{ key: 'purpose', title: '用途', render: (record) => record.purpose ?? '-' },
|
|
{ key: 'status', title: '审核状态', render: (record) => <Tag tone={record.auditStatus === 'approved' ? 'success' : record.auditStatus === 'rejected' ? 'danger' : 'info'}>{record.auditStatus}</Tag> },
|
|
], []);
|
|
|
|
const templateColumns = useMemo<Array<TableColumn<ClientSmsTemplate>>>(() => [
|
|
{ key: 'name', title: '模板', render: (record) => <strong>{record.name}</strong> },
|
|
{ key: 'content', title: '内容', render: (record) => <span className="table-long-text">{record.content}</span> },
|
|
{ key: 'status', title: '审核状态', render: (record) => <Tag tone={record.auditStatus === 'approved' ? 'success' : record.auditStatus === 'rejected' ? 'danger' : 'info'}>{record.auditStatus}</Tag> },
|
|
], []);
|
|
|
|
return (
|
|
<section className="page-stack enterprise-detail-page">
|
|
<div className="page-heading">
|
|
<div>
|
|
<Breadcrumb items={['企业管理', tenant?.name ?? '企业详情']} />
|
|
<h1>{tenant?.name ?? '企业详情'}</h1>
|
|
</div>
|
|
<Button icon={<ArrowLeft size={16} />} onClick={() => navigate('/admin/customers')} variant="ghost">返回</Button>
|
|
</div>
|
|
{error ? <p className="form-error">{error}</p> : null}
|
|
|
|
<div className="dashboard-grid enterprise-summary-grid">
|
|
<div className="surface mini-status-card"><Server size={22} /><div><span>企业编码</span><strong>{tenant?.code ?? '-'}</strong><small>{tenant?.status ?? '-'}</small></div></div>
|
|
<div className="surface mini-status-card"><MessageSquare size={22} /><div><span>短信余量</span><strong>{(account?.smsUnits ?? 0).toLocaleString('zh-CN')}</strong><small>真实账户余量</small></div></div>
|
|
<div className="surface mini-status-card"><FileText size={22} /><div><span>现金余额</span><strong>¥{((account?.balanceCents ?? 0) / 100).toLocaleString('zh-CN')}</strong><small>真实账户余额</small></div></div>
|
|
</div>
|
|
|
|
<div className="surface section-stack">
|
|
<div className="section-heading"><div><h2>企业档案</h2><p className="muted">来自真实企业档案接口。</p></div></div>
|
|
<div className="ui-detail-info-grid">
|
|
<div className="ui-detail-info-grid__item"><span>统一社会信用代码</span><strong>{tenant?.enterpriseProfile?.creditCode || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item"><span>省/市</span><strong>{[tenant?.enterpriseProfile?.province, tenant?.enterpriseProfile?.city].filter(Boolean).join(' / ') || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item ui-detail-info-grid__item--full"><span>通讯地址</span><strong>{tenant?.enterpriseProfile?.address || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item"><span>联系人</span><strong>{tenant?.enterpriseProfile?.contactName || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item"><span>手机号</span><strong>{tenant?.enterpriseProfile?.contactPhone || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item"><span>身份证号</span><strong>{tenant?.enterpriseProfile?.contactIdCard || '-'}</strong></div>
|
|
<div className="ui-detail-info-grid__item"><span>电子邮箱</span><strong>{tenant?.enterpriseProfile?.contactEmail || '-'}</strong></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="surface section-stack">
|
|
<div className="section-heading"><div><h2>短信应用</h2><p className="muted">来自企业应用真实接口。</p></div><Tag tone="info">{applications.length} 个</Tag></div>
|
|
<Table columns={appColumns} data={applications} emptyText="暂无短信应用" rowKey="id" />
|
|
</div>
|
|
|
|
<div className="surface section-stack">
|
|
<div className="section-heading"><div><h2>短信签名</h2><p className="muted">来自企业签名真实接口。</p></div><Tag tone="info">{signatures.length} 个</Tag></div>
|
|
<Table columns={signatureColumns} data={signatures} emptyText="暂无签名" rowKey="id" />
|
|
</div>
|
|
|
|
<div className="surface section-stack">
|
|
<div className="section-heading"><div><h2>短信模板</h2><p className="muted">来自企业模板真实接口。</p></div><Tag tone="info">{templates.length} 个</Tag></div>
|
|
<Table columns={templateColumns} data={templates} emptyText="暂无模板" rowKey="id" />
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|