feat: complete reporting and filing workflows
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { ChevronDown, ChevronRight, Edit3, FileText, Info, Plus, Search, Trash2, Upload } from 'lucide-react';
|
||||
import { ChevronDown, ChevronRight, Edit3, FileSpreadsheet, FileText, Info, Plus, Search, Trash2, Upload } from 'lucide-react';
|
||||
import { adminApi, type ApplicationReportField, type ClientSmsApplication, type ClientSmsSignature, type FileRef, type TenantOption } from '@/api/adminApi';
|
||||
import { Breadcrumb, Button, DeleteRiskAction, FileActions, Input, Modal, Pagination, Select, Tabs, Tag, Textarea } from '@/components/ui';
|
||||
import { displayFileName } from '@/utils/fileName';
|
||||
import { formatDateTime } from '@/utils/dateTime';
|
||||
import { getSmsSignatureValidationError, hasForbiddenSmsSignatureCharacter, isCompleteSmsSignature, SMS_SIGNATURE_CHARACTER_ERROR } from '@/utils/smsSignature';
|
||||
import { ReportMaterialImportModal } from './ReportMaterialImportModal';
|
||||
|
||||
type CarrierStatus = 'approved' | 'pending' | 'rejected' | 'filing';
|
||||
|
||||
@@ -460,9 +461,9 @@ function DrainageFormModal({ applicationId, item, onClose, onSubmit }: { applica
|
||||
<section>
|
||||
<h3>基本信息</h3>
|
||||
<Input
|
||||
label="* 引流网址"
|
||||
label="* 引流url或号码"
|
||||
onChange={(event) => update('url', event.target.value)}
|
||||
placeholder="请输入引流网址"
|
||||
placeholder="请输入引流url或号码"
|
||||
required
|
||||
value={form.url}
|
||||
/>
|
||||
@@ -475,7 +476,6 @@ function DrainageFormModal({ applicationId, item, onClose, onSubmit }: { applica
|
||||
</ol>
|
||||
</div>
|
||||
<div className="signature-form-grid">
|
||||
<Input label="* 引流信息" onChange={(event) => update('siteName', event.target.value)} placeholder="请输入引流信息" value={form.siteName} />
|
||||
<Textarea className="signature-form-grid__wide" label="备注" onChange={(event) => update('remark', event.target.value)} rows={4} value={form.remark} />
|
||||
</div>
|
||||
<DynamicReportFields fields={reportFields} onChange={updateReportValue} title="引流信息报备资料(通用 + 通道)" values={form.reportValues} />
|
||||
@@ -541,7 +541,7 @@ function DrainageReportModal({ item, onClose, signature }: { item: DrainageInfo;
|
||||
return (
|
||||
<Modal footer={<Button onClick={onClose}>关闭</Button>} onClose={onClose} open size="xl" title="引流信息报备详情">
|
||||
<div className="detail-grid">
|
||||
<div><span>引流信息</span><strong>{item.siteName}</strong></div>
|
||||
<div><span>引流url或号码</span><strong>{item.url}</strong></div>
|
||||
<div><span>引流url或号码</span><strong>{item.url}</strong></div>
|
||||
<div><span>移动</span><CarrierReportTag summary={summary?.mobile} /></div>
|
||||
<div><span>联通</span><CarrierReportTag summary={summary?.unicom} /></div>
|
||||
@@ -616,6 +616,8 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
const [signatures, setSignatures] = useState<ClientSmsSignature[]>([]);
|
||||
const [tenants, setTenants] = useState<TenantOption[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [importOpen, setImportOpen] = useState(false);
|
||||
const [message, setMessage] = useState('');
|
||||
|
||||
async function loadData(filters = { enterpriseKeyword: appliedEnterpriseKeyword, applicationKeyword: appliedApplicationKeyword, signatureKeyword: appliedSignatureKeyword, drainageKeyword: appliedDrainageKeyword }) {
|
||||
try {
|
||||
@@ -693,7 +695,7 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
return;
|
||||
}
|
||||
const exists = readDrainagePayload(signature).links.some((current) => current.id === item.id);
|
||||
const body = { siteName: item.siteName, url: item.url, remark: item.remark, reportValues: item.reportValues };
|
||||
const body = { siteName: item.url.trim(), url: item.url.trim(), remark: item.remark, reportValues: item.reportValues };
|
||||
if (exists) await adminApi.updateDrainageInfo(item.id, body);
|
||||
else await adminApi.createDrainageInfo(signatureId, body);
|
||||
setDrainageModal(null);
|
||||
@@ -766,7 +768,7 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
<Button onClick={() => setDrainageReport({ signature, item })} size="sm" variant="ghost">报备详情</Button>
|
||||
<Button disabled={item.auditStatus !== 'approved'} onClick={() => setDrainageStatusTarget({ signature, item })} size="sm" variant="ghost">报备状态</Button>
|
||||
<Button onClick={() => setDrainageModal({ signatureId: signature.id, item })} size="sm" variant="ghost">编辑</Button>
|
||||
<Button onClick={() => setDeleteTarget({ kind: 'drainage', signatureId: signature.id, id: item.id, name: item.siteName })} size="sm" variant="danger">删除</Button>
|
||||
<Button onClick={() => setDeleteTarget({ kind: 'drainage', signatureId: signature.id, id: item.id, name: item.url })} size="sm" variant="danger">删除</Button>
|
||||
</span>
|
||||
</div>
|
||||
);})}
|
||||
@@ -803,7 +805,10 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
<Breadcrumb items={['客户管理', '企业签名管理']} />
|
||||
<h1>企业签名管理</h1>
|
||||
</div>
|
||||
<Button icon={<Plus size={16} />} onClick={() => setSignatureModal(activeTab === 'sms' ? 'new' : null)}>添加签名</Button>
|
||||
<div className="page-heading-actions">
|
||||
<Button icon={<FileSpreadsheet size={16} />} onClick={() => setImportOpen(true)} variant="ghost">批量导入签名及引流资料</Button>
|
||||
<Button icon={<Plus size={16} />} onClick={() => setSignatureModal(activeTab === 'sms' ? 'new' : null)}>添加签名</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-split-filter">
|
||||
@@ -836,6 +841,7 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
</div>
|
||||
|
||||
{error ? <p className="form-error">{error}</p> : null}
|
||||
{message ? <p className="form-success">{message}</p> : null}
|
||||
|
||||
<div className="surface section-stack">
|
||||
<Tabs
|
||||
@@ -857,6 +863,10 @@ export function AdminEnterpriseSignaturesPage() {
|
||||
tenants={tenants}
|
||||
/>
|
||||
) : null}
|
||||
{importOpen ? <ReportMaterialImportModal onClose={() => setImportOpen(false)} onCompleted={() => {
|
||||
setMessage('导入解析完成,合格资料已进入审核中心的导入批次');
|
||||
void loadData();
|
||||
}} /> : null}
|
||||
{signatureReport ? <SignatureReportModal item={signatureReport} onClose={() => setSignatureReport(null)} /> : null}
|
||||
{reportStatusTarget ? <ChannelReportStatusModal item={reportStatusTarget} onClose={() => setReportStatusTarget(null)} onSaved={() => { setReportStatusTarget(null); void loadData(); }} /> : null}
|
||||
{drainageModal ? (
|
||||
|
||||
Reference in New Issue
Block a user