Initial CMPP frontend prototype
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Check, FileSearch, Search, X } from 'lucide-react';
|
||||
import { Button, Input, Select, Table, Tag, type TableColumn } from '@/components/ui';
|
||||
|
||||
type EnterpriseAuditStatus = 'pending' | 'approved' | 'rejected';
|
||||
|
||||
type EnterpriseAuditRecord = {
|
||||
id: string;
|
||||
companyName: string;
|
||||
creditCode: string;
|
||||
contactName: string;
|
||||
contactPhone: string;
|
||||
submittedAt: string;
|
||||
status: EnterpriseAuditStatus;
|
||||
};
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '全部状态', value: 'all' },
|
||||
{ label: '待审核', value: 'pending' },
|
||||
{ label: '已通过', value: 'approved' },
|
||||
{ label: '已拒绝', value: 'rejected' },
|
||||
];
|
||||
|
||||
const statusTextMap: Record<EnterpriseAuditStatus, string> = {
|
||||
pending: '待审核',
|
||||
approved: '已通过',
|
||||
rejected: '已拒绝',
|
||||
};
|
||||
|
||||
const statusToneMap: Record<EnterpriseAuditStatus, 'warning' | 'success' | 'danger'> = {
|
||||
pending: 'warning',
|
||||
approved: 'success',
|
||||
rejected: 'danger',
|
||||
};
|
||||
|
||||
const initialEnterpriseAudits: EnterpriseAuditRecord[] = [
|
||||
{ id: 'ENT-20260319-001', companyName: '北京星云科技有限公司', creditCode: '91110000X12345678A', contactName: '张伟', contactPhone: '13800138000', submittedAt: '2026-03-19 10:23:45', status: 'pending' },
|
||||
{ id: 'ENT-20260319-002', companyName: '上海蓝海科技有限公司', creditCode: '91310000X87654321B', contactName: '李娜', contactPhone: '13900139000', submittedAt: '2026-03-18 15:45:12', status: 'pending' },
|
||||
{ id: 'ENT-20260318-001', companyName: '广州飞跃文化传媒有限公司', creditCode: '91440100X11223344C', contactName: '王强', contactPhone: '13700137000', submittedAt: '2026-03-17 09:12:30', status: 'approved' },
|
||||
{ id: 'ENT-20260317-001', companyName: '深圳前海贸易有限公司', creditCode: '91440300X55667788D', contactName: '陈杰', contactPhone: '13600136000', submittedAt: '2026-03-16 11:30:22', status: 'rejected' },
|
||||
];
|
||||
|
||||
export function AdminEnterpriseAuditPage() {
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [status, setStatus] = useState('all');
|
||||
const [records, setRecords] = useState(initialEnterpriseAudits);
|
||||
|
||||
const filteredRecords = useMemo(
|
||||
() => records.filter((record) => {
|
||||
const matchesKeyword = !keyword || `${record.companyName}${record.creditCode}`.includes(keyword);
|
||||
const matchesStatus = status === 'all' || record.status === status;
|
||||
return matchesKeyword && matchesStatus;
|
||||
}),
|
||||
[keyword, records, status],
|
||||
);
|
||||
|
||||
function updateStatus(id: string, nextStatus: EnterpriseAuditStatus) {
|
||||
setRecords((items) => items.map((item) => (item.id === id ? { ...item, status: nextStatus } : item)));
|
||||
}
|
||||
|
||||
const columns: Array<TableColumn<EnterpriseAuditRecord>> = [
|
||||
{ key: 'id', title: '申请单号', render: (record) => <span className="muted">{record.id}</span> },
|
||||
{ key: 'companyName', title: '企业名称', render: (record) => <strong>{record.companyName}</strong> },
|
||||
{ key: 'creditCode', title: '统一社会信用代码', render: (record) => record.creditCode },
|
||||
{ key: 'contactName', title: '联系人', render: (record) => record.contactName },
|
||||
{ key: 'contactPhone', title: '联系电话', render: (record) => record.contactPhone },
|
||||
{ key: 'submittedAt', title: '提交时间', render: (record) => record.submittedAt },
|
||||
{
|
||||
key: 'status',
|
||||
title: '状态',
|
||||
render: (record) => <Tag tone={statusToneMap[record.status]}>{statusTextMap[record.status]}</Tag>,
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
title: '操作',
|
||||
align: 'right',
|
||||
render: (record) => (
|
||||
<div className="audit-actions">
|
||||
{record.status === 'pending' ? (
|
||||
<>
|
||||
<button className="audit-link audit-link--success" onClick={() => updateStatus(record.id, 'approved')} type="button">通过</button>
|
||||
<button className="audit-link audit-link--danger" onClick={() => updateStatus(record.id, 'rejected')} type="button">拒绝</button>
|
||||
</>
|
||||
) : null}
|
||||
<button className="audit-link" type="button">详情</button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-audit-page">
|
||||
<div className="breadcrumb-line"><span>审核中心</span><span>/</span><strong>企业认证审核</strong></div>
|
||||
<div className="surface audit-filter-card">
|
||||
<div className="audit-filter-grid audit-filter-grid--enterprise">
|
||||
<Input label="企业名称/信用代码" onChange={(event) => setKeyword(event.target.value)} placeholder="请输入企业名称或统一社会信用代码" value={keyword} />
|
||||
<Select label="审核状态" onChange={(event) => setStatus(event.target.value)} options={statusOptions} value={status} />
|
||||
<div className="audit-filter-actions">
|
||||
<Button icon={<Search size={17} />}>查询</Button>
|
||||
<Button onClick={() => { setKeyword(''); setStatus('all'); }} variant="ghost">重置</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="surface audit-table-card">
|
||||
<Table columns={columns} data={filteredRecords} rowKey="id" />
|
||||
<div className="audit-pagination">
|
||||
<span>共 {filteredRecords.length} 条</span>
|
||||
<Button disabled icon={<FileSearch size={16} />} size="sm" variant="ghost">更多</Button>
|
||||
<Button disabled icon={<Check size={15} />} size="sm" variant="secondary">1</Button>
|
||||
<Button disabled icon={<X size={15} />} size="sm" variant="ghost">下一页</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user