feat: complete signature and drainage reporting workflows
This commit is contained in:
@@ -10,6 +10,10 @@ const statusMeta: Record<string, { label: string; tone: 'neutral' | 'info' | 'su
|
||||
reporting: { label: '报备中', tone: 'warning' },
|
||||
partial: { label: '部分完成', tone: 'info' },
|
||||
completed: { label: '已完成', tone: 'success' },
|
||||
approved: { label: '报备通过', tone: 'success' },
|
||||
waiting_material: { label: '资料待补充', tone: 'warning' },
|
||||
exporting: { label: '报备中', tone: 'warning' },
|
||||
abandoned: { label: '已放弃', tone: 'neutral' },
|
||||
failed: { label: '有失败', tone: 'danger' },
|
||||
};
|
||||
|
||||
@@ -21,6 +25,14 @@ type ReceiptImportPayload = {
|
||||
remark: string;
|
||||
};
|
||||
|
||||
function taskTargetLabel(task: ReportTask) {
|
||||
if (task.reportType !== 'drainage') return task.signature?.name ?? task.signatureId;
|
||||
const payload = task.signature?.drainageInfo;
|
||||
const links = payload && Array.isArray(payload.links) ? payload.links as Array<Record<string, unknown>> : [];
|
||||
const item = links.find((link) => String(link.id ?? '') === task.drainageItemId);
|
||||
return String(item?.siteName ?? item?.url ?? task.drainageItemId ?? '引流信息');
|
||||
}
|
||||
|
||||
function ReceiptImportModal({ onClose, onSubmit, task }: { onClose: () => void; onSubmit: (payload: ReceiptImportPayload) => void; task: ReportTask }) {
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [fileObject, setFileObject] = useState<FileObject | null>(null);
|
||||
@@ -97,7 +109,7 @@ function TaskDetailModal({ task, onClose }: { task: ReportTask; onClose: () => v
|
||||
<Modal footer={<Button onClick={onClose}>关闭</Button>} onClose={onClose} open size="xl" title={<div className="template-modal-title"><h2>报备任务详情</h2><p>{task.id}</p></div>}>
|
||||
<div className="admin-task-detail report-task-detail">
|
||||
<div className="admin-task-metrics">
|
||||
<div className="admin-task-metric"><span>签名</span><strong>{task.signature?.name ?? task.signatureId}</strong></div>
|
||||
<div className="admin-task-metric"><span>{task.reportType === 'drainage' ? '引流信息' : '签名'}</span><strong>{taskTargetLabel(task)}</strong></div>
|
||||
<div className="admin-task-metric admin-task-metric--primary"><span>通道</span><strong>{task.channel?.name ?? task.channelId}</strong></div>
|
||||
<div className="admin-task-metric admin-task-metric--success"><span>当前状态</span><strong>{status.label}</strong></div>
|
||||
</div>
|
||||
@@ -131,7 +143,7 @@ export function AdminReportTasksPage() {
|
||||
}, []);
|
||||
|
||||
const filteredTasks = useMemo(() => tasks.filter((task) => {
|
||||
const text = `${task.id}${task.channel?.name ?? task.channelId}${task.signature?.name ?? task.signatureId}`;
|
||||
const text = `${task.id}${task.channel?.name ?? task.channelId}${task.signature?.name ?? task.signatureId}${task.drainageItemId ?? ''}`;
|
||||
const date = task.createdAt?.slice(0, 10) ?? '';
|
||||
return (!keyword || text.includes(keyword))
|
||||
&& (!dateRange.start || date >= dateRange.start)
|
||||
@@ -162,14 +174,14 @@ export function AdminReportTasksPage() {
|
||||
|
||||
function saveTaskStatus() {
|
||||
if (!statusTask) return;
|
||||
adminApi.changeReportTaskStatuses({ items: [{ signatureId: statusTask.signatureId, channelId: statusTask.channelId, status: nextStatus }], reason: statusReason })
|
||||
adminApi.changeReportTaskStatuses({ items: [{ signatureId: statusTask.signatureId, channelId: statusTask.channelId, reportType: statusTask.reportType, drainageItemId: statusTask.drainageItemId ?? undefined, status: nextStatus }], reason: statusReason })
|
||||
.then(() => { setStatusTask(null); setStatusReason(''); loadData(); })
|
||||
.catch((failure: Error) => setError(failure.message || '报备状态保存失败'));
|
||||
}
|
||||
|
||||
const columns: Array<TableColumn<ReportTask>> = [
|
||||
{ key: 'id', title: '任务编号', width: '190px', render: (record) => <strong className="admin-task-id">{record.id}</strong> },
|
||||
{ key: 'scope', title: '通道/签名', width: '280px', render: (record) => <div className="admin-task-enterprise"><strong>{record.channel?.name ?? record.channelId}</strong><span>{record.signature?.name ?? record.signatureId}</span></div> },
|
||||
{ key: 'scope', title: '通道/报备对象', width: '300px', render: (record) => <div className="admin-task-enterprise"><strong>{record.channel?.name ?? record.channelId}</strong><span>{record.reportType === 'drainage' ? `引流信息 · ${taskTargetLabel(record)}` : `签名 · ${taskTargetLabel(record)}`}</span></div> },
|
||||
{ key: 'status', title: '状态', width: '130px', render: (record) => <Tag tone={(statusMeta[record.status] ?? { tone: 'info' as const }).tone}>{(statusMeta[record.status] ?? { label: record.status }).label}</Tag> },
|
||||
{ key: 'time', title: '创建时间', width: '190px', render: (record) => record.createdAt ?? '-' },
|
||||
{
|
||||
@@ -192,14 +204,14 @@ export function AdminReportTasksPage() {
|
||||
<section className="page-stack admin-sms-task-page report-task-page">
|
||||
<div className="page-heading">
|
||||
<div>
|
||||
<Breadcrumb items={['报备任务', '签名通道报备']} />
|
||||
<h1>签名通道报备任务</h1>
|
||||
<Breadcrumb items={['报备任务']} />
|
||||
<h1>签名与引流信息报备任务</h1>
|
||||
</div>
|
||||
</div>
|
||||
{error ? <p className="form-error">{error}</p> : null}
|
||||
|
||||
<div className="surface admin-task-filter">
|
||||
<Input label="任务/通道/签名" onChange={(event) => setKeyword(event.target.value)} placeholder="请输入关键字" value={keyword} />
|
||||
<Input label="任务/通道/报备对象" onChange={(event) => setKeyword(event.target.value)} placeholder="请输入关键字" value={keyword} />
|
||||
<DateRangeInput label="创建时间" onChange={setDateRange} value={dateRange} />
|
||||
<div className="admin-task-filter__actions">
|
||||
<Button icon={<Search size={16} />} onClick={loadData}>查询</Button>
|
||||
|
||||
Reference in New Issue
Block a user