feat: unify signature channel reporting status
This commit is contained in:
@@ -544,6 +544,39 @@ function SignatureReportModal({ item, onClose }: { item: ClientSmsSignature; onC
|
||||
);
|
||||
}
|
||||
|
||||
const reportStatusOptions = [
|
||||
{ label: '未报备', value: 'pending' }, { label: '资料待补充', value: 'waiting_material' },
|
||||
{ label: '报备中', value: 'reporting' }, { label: '报备通过', value: 'approved' },
|
||||
{ label: '报备失败', value: 'failed' }, { label: '放弃报备', value: 'abandoned' },
|
||||
];
|
||||
|
||||
function ChannelReportStatusModal({ item, onClose, onSaved }: { item: ClientSmsSignature; onClose: () => void; onSaved: () => void }) {
|
||||
const targets = item.reportTargets ?? [];
|
||||
const [statuses, setStatuses] = useState<Record<string, string>>(() => Object.fromEntries(targets.map((target) => [target.channelId, target.status])));
|
||||
const [reason, setReason] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
async function save() {
|
||||
setSaving(true);
|
||||
try {
|
||||
await adminApi.changeReportTaskStatuses({ items: targets.map((target) => ({ signatureId: item.id, channelId: target.channelId, status: statuses[target.channelId] ?? target.status })), reason });
|
||||
onSaved();
|
||||
} catch (failure) { setError(failure instanceof Error ? failure.message : '报备状态保存失败'); } finally { setSaving(false); }
|
||||
}
|
||||
return <Modal footer={<><Button onClick={onClose} variant="ghost">取消</Button><Button disabled={!targets.length || saving} onClick={() => void save()}>{saving ? '保存中...' : '保存状态'}</Button></>} onClose={onClose} open size="xl" title="按通道修改签名报备状态">
|
||||
<div className="page-stack"><div className="signature-alert"><Info size={18} /><span>企业签名只展示汇总结果;这里修改的是每个具体通道的报备任务,保存后会同步通道详情、报备任务和企业签名三网状态。</span></div>
|
||||
{error ? <p className="form-error">{error}</p> : null}
|
||||
{targets.length ? targets.map((target) => <div className="surface" key={target.channelId} style={{ display: 'grid', gap: 16, gridTemplateColumns: '1fr 220px', padding: 16 }}><div><strong>{target.channel.name}</strong><div className="muted">{target.channel.carrier ?? '未标注运营商'} · {target.channel.code}</div></div><Select onChange={(event) => setStatuses((current) => ({ ...current, [target.channelId]: event.target.value }))} options={reportStatusOptions} value={statuses[target.channelId] ?? target.status} /></div>) : <div className="empty-state">该企业应用当前没有配置目标通道。</div>}
|
||||
<Textarea label="修改原因" onChange={(event) => setReason(event.target.value)} placeholder="请输入运营商工单、确认依据或人工处理说明" rows={3} value={reason} />
|
||||
</div>
|
||||
</Modal>;
|
||||
}
|
||||
|
||||
function summaryStatus(signature: ClientSmsSignature, carrier: 'mobile' | 'unicom' | 'telecom'): CarrierStatus {
|
||||
const status = signature.carrierReportSummary?.[carrier]?.status;
|
||||
return status === 'approved' ? 'approved' : status === 'failed' ? 'rejected' : status === 'reporting' ? 'pending' : 'filing';
|
||||
}
|
||||
|
||||
function DrainageReportModal({ item, onClose }: { item: DrainageInfo; onClose: () => void }) {
|
||||
return (
|
||||
<Modal footer={<Button onClick={onClose}>关闭</Button>} onClose={onClose} open title="引流信息报备详情">
|
||||
@@ -592,6 +625,7 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
const [appliedSignatureKeyword, setAppliedSignatureKeyword] = useState('');
|
||||
const [signatureModal, setSignatureModal] = useState<ClientSmsSignature | 'new' | null>(null);
|
||||
const [signatureReport, setSignatureReport] = useState<ClientSmsSignature | null>(null);
|
||||
const [reportStatusTarget, setReportStatusTarget] = useState<ClientSmsSignature | null>(null);
|
||||
const [signatures, setSignatures] = useState<ClientSmsSignature[]>([]);
|
||||
const [tenants, setTenants] = useState<TenantOption[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
@@ -703,9 +737,10 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
<div className="signature-list admin-enterprise-signature-list">
|
||||
{visibleSignatures.map((signature) => {
|
||||
const payload = readDrainagePayload(signature);
|
||||
const effectiveCarrierStatus = { mobile: summaryStatus(signature, 'mobile'), unicom: summaryStatus(signature, 'unicom'), telecom: summaryStatus(signature, 'telecom') };
|
||||
const expanded = expandedSignatureId === signature.id;
|
||||
return (
|
||||
<article className={`signature-card signature-card--${signatureCardTone(payload.carrierStatus)}`} key={signature.id}>
|
||||
<article className={`signature-card signature-card--${signatureCardTone(effectiveCarrierStatus)}`} key={signature.id}>
|
||||
<div className="signature-summary">
|
||||
<button aria-label="展开签名" onClick={() => setExpandedSignatureId(expanded ? '' : signature.id)} type="button">
|
||||
{expanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}
|
||||
@@ -713,12 +748,13 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
<div><span>签名名称</span><strong>{signature.name}</strong></div>
|
||||
<div><span>企业</span><strong>{signature.tenant?.name ?? signature.tenantId}</strong></div>
|
||||
<div><span>应用</span><strong>{signature.application?.name ?? '-'}</strong></div>
|
||||
<div><span>移动</span><StatusTag status={payload.carrierStatus.mobile} /></div>
|
||||
<div><span>联通</span><StatusTag status={payload.carrierStatus.unicom} /></div>
|
||||
<div><span>电信</span><StatusTag status={payload.carrierStatus.telecom} /></div>
|
||||
<div><span>移动</span><StatusTag status={effectiveCarrierStatus.mobile} /></div>
|
||||
<div><span>联通</span><StatusTag status={effectiveCarrierStatus.unicom} /></div>
|
||||
<div><span>电信</span><StatusTag status={effectiveCarrierStatus.telecom} /></div>
|
||||
<div><span>引流信息</span><strong>{payload.links.length} 条</strong></div>
|
||||
<div className="signature-actions">
|
||||
<Button icon={<FileText size={16} />} onClick={() => setSignatureReport(signature)} size="sm" variant="ghost">报备详情</Button>
|
||||
<Button icon={<Edit3 size={16} />} onClick={() => setReportStatusTarget(signature)} size="sm" variant="ghost">报备状态</Button>
|
||||
<Button icon={<Edit3 size={16} />} onClick={() => setSignatureModal(signature)} size="sm" variant="ghost">编辑</Button>
|
||||
<Button icon={<Trash2 size={16} />} onClick={() => setDeleteTarget({ kind: 'signature', id: signature.id, name: signature.name })} size="sm" variant="danger">删除</Button>
|
||||
</div>
|
||||
@@ -832,6 +868,7 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
/>
|
||||
) : null}
|
||||
{signatureReport ? <SignatureReportModal item={signatureReport} onClose={() => setSignatureReport(null)} /> : null}
|
||||
{reportStatusTarget ? <ChannelReportStatusModal item={reportStatusTarget} onClose={() => setReportStatusTarget(null)} onSaved={() => { setReportStatusTarget(null); void loadData(); }} /> : null}
|
||||
{drainageModal ? (
|
||||
<DrainageFormModal
|
||||
applicationId={signatures.find((item) => item.id === drainageModal.signatureId)?.applicationId}
|
||||
|
||||
Reference in New Issue
Block a user