import { useEffect, useMemo, useState } from 'react'; import { Eye, Search, X } from 'lucide-react'; import { adminApi, type ClientSmsSignature, type FileRef } from '@/api/adminApi'; import { Breadcrumb, Button, FileActions, Input, Modal, RiskAction, Select, Table, Tag, Textarea, type TableColumn } from '@/components/ui'; import { formatDateTime } from '@/utils/dateTime'; const statusMeta: Record = { draft: { label: '草稿', tone: 'neutral' }, pending: { label: '待审核', tone: 'info' }, approved: { label: '已通过', tone: 'success' }, rejected: { label: '已驳回', tone: 'danger' }, }; function asRecord(value: unknown): Record { return value && typeof value === 'object' && !Array.isArray(value) ? value as Record : {}; } function fileRef(value: unknown): FileRef | null { const item = asRecord(value); return item.fileObjectId && item.fileName ? { fileObjectId: String(item.fileObjectId), fileName: String(item.fileName), contentType: item.contentType ? String(item.contentType) : undefined, } : null; } function canReviewSignature(item: ClientSmsSignature) { return ['draft', 'pending'].includes(item.auditStatus); } function SignatureDetail({ item, onClose }: { item: ClientSmsSignature; onClose: () => void }) { const payload = asRecord(item.drainageInfo); const profile = asRecord(payload.signatureProfile); const values = asRecord(payload.signatureReportValues); const profileFiles = ['credentialFile', 'legalFrontFile', 'legalBackFile', 'responsibleFrontFile', 'responsibleBackFile'] .map((key) => fileRef(profile[key])) .filter((value): value is FileRef => Boolean(value)); const materialFiles: FileRef[] = (item.materials ?? []).flatMap((value) => { const material = asRecord(value); return material.fileObjectId ? [{ fileObjectId: String(material.fileObjectId), fileName: String(material.title ?? material.fileName ?? material.fileObjectId), contentType: material.contentType ? String(material.contentType) : undefined, }] : []; }); const files = [...new Map([...profileFiles, ...materialFiles].map((file) => [file.fileObjectId, file])).values()]; return 关闭} onClose={onClose} open size="xl" title="签名审核详情">
企业{item.tenant?.name ?? item.tenantId}
应用{item.application?.name ?? '-'}
签名{item.name}
审核状态{(statusMeta[item.auditStatus] ?? statusMeta.draft).label}
签名依据{String(profile.basis ?? '-')}
公司名称{String(profile.companyName ?? '-')}
统一社会信用代码{String(profile.creditCode ?? '-')}
法人{String(profile.legalPersonName ?? '-')}
责任人{String(profile.responsibleName ?? '-')}
责任人手机{String(profile.responsiblePhone ?? '-')}
{item.rejectReason ?
驳回原因{item.rejectReason}
: null}
资质文件
{files.length ? files.map((file) => ) : }
通道动态报备资料
{Object.entries(values).length ? Object.entries(values).map(([key, value]) =>
{key}{fileRef(value) ? : String(value ?? '-')}
) : }
; } export function AdminSignatureAuditPage() { const [items, setItems] = useState([]); const [keyword, setKeyword] = useState(''); const [status, setStatus] = useState('pending'); const [detail, setDetail] = useState(); const [rejectTarget, setRejectTarget] = useState(); const [reason, setReason] = useState(''); const [error, setError] = useState(''); function loadData() { adminApi.listEnterpriseSignatures({ keyword, status: status === 'all' ? undefined : status }) .then((records) => { setItems(records); setError(''); }) .catch((failure: Error) => setError(failure.message || '签名审核列表加载失败')); } useEffect(loadData, [keyword, status]); const visible = useMemo(() => items.filter((item) => status === 'all' || item.auditStatus === status), [items, status]); async function reject() { if (!rejectTarget || !reason.trim()) return; try { await adminApi.rejectSignature(rejectTarget.id, reason.trim()); setRejectTarget(undefined); setReason(''); loadData(); } catch (failure) { setError(failure instanceof Error ? failure.message : '签名审核驳回失败'); } } const columns = useMemo>>(() => [ { key: 'name', title: '签名', render: (record) => {record.name} }, { key: 'tenant', title: '企业', render: (record) => record.tenant?.name ?? record.tenantId }, { key: 'application', title: '应用', render: (record) => record.application?.name ?? '-' }, { key: 'submittedAt', title: '提交时间', render: (record) => formatDateTime(record.updatedAt) }, { key: 'status', title: '状态', render: (record) => {(statusMeta[record.auditStatus] ?? statusMeta.draft).label} }, { key: 'actions', title: '操作', align: 'right', render: (record) =>
}, ], []); return

短信签名审核

{error ?

{error}

: null}
setKeyword(event.target.value)} placeholder="搜索企业、应用或签名" prefix={} value={keyword} />