feat: add report material workflows and gateway safeguards
This commit is contained in:
@@ -4,8 +4,9 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { adminApi, type AdminChannel, type ChannelReportField, type ClientSmsSignature, type DictionaryItem, type ReportRecord, type ReportTask } from '@/api/adminApi';
|
||||
import { Breadcrumb, Button, Input, Modal, Select, Tag, Textarea } from '@/components/ui';
|
||||
import { formatDateTime } from '@/utils/dateTime';
|
||||
import { ReportFieldMappingModal } from './ReportFieldMappingModal';
|
||||
|
||||
type ReportType = 'signature' | 'drainage' | 'both';
|
||||
type ReportType = 'signature' | 'drainage';
|
||||
type DrainageItem = Record<string, unknown> & { id?: string; url?: string; siteName?: string; submittedAt?: string; remark?: string };
|
||||
|
||||
const statusMeta: Record<string, { label: string; tone: 'success' | 'danger' | 'warning' | 'neutral' }> = {
|
||||
@@ -22,8 +23,6 @@ const statusMeta: Record<string, { label: string; tone: 'success' | 'danger' | '
|
||||
filing: { label: '报备中', tone: 'warning' },
|
||||
};
|
||||
|
||||
const fieldTypeLabel: Record<string, string> = { string: '字符串', image: '图片', file: '文件' };
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> {
|
||||
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
||||
}
|
||||
@@ -81,9 +80,6 @@ export function AdminChannelReportPage() {
|
||||
const [nextStatus, setNextStatus] = useState('approved');
|
||||
const [statusReason, setStatusReason] = useState('');
|
||||
const [configType, setConfigType] = useState<ReportType>();
|
||||
const [drainageFieldId, setDrainageFieldId] = useState('');
|
||||
const [required, setRequired] = useState(false);
|
||||
const [description, setDescription] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
function loadData() {
|
||||
@@ -119,11 +115,10 @@ export function AdminChannelReportPage() {
|
||||
return records.find((record) => record.taskId === taskId && record.action === action);
|
||||
}
|
||||
|
||||
function createField() {
|
||||
if (!configType || !drainageFieldId) return;
|
||||
adminApi.createChannelReportField({ channelId, drainageFieldId, reportType: configType, required, description, status: 'active' })
|
||||
.then(() => { setConfigType(undefined); setDrainageFieldId(''); setRequired(false); setDescription(''); loadData(); })
|
||||
.catch((failure: Error) => setError(failure.message || '报备字段保存失败'));
|
||||
async function saveFieldMapping(nextFields: Parameters<typeof adminApi.replaceChannelReportFields>[2]) {
|
||||
if (!configType) return;
|
||||
await adminApi.replaceChannelReportFields(channelId, configType, nextFields);
|
||||
loadData();
|
||||
}
|
||||
|
||||
function saveTaskStatus() {
|
||||
@@ -180,13 +175,7 @@ export function AdminChannelReportPage() {
|
||||
|
||||
{detail ? <DetailModal {...detail} onClose={() => setDetail(undefined)} /> : null}
|
||||
<Modal footer={<><Button onClick={() => setStatusTask(undefined)} variant="ghost">取消</Button><Button onClick={saveTaskStatus}>保存</Button></>} onClose={() => setStatusTask(undefined)} open={Boolean(statusTask)} title="修改当前通道报备状态"><div className="admin-system-modal-form"><Select label="报备状态" onChange={(event) => setNextStatus(event.target.value)} options={[{label:'未报备',value:'pending'},{label:'资料待补充',value:'waiting_material'},{label:'报备中',value:'reporting'},{label:'报备通过',value:'approved'},{label:'报备失败',value:'failed'},{label:'放弃报备',value:'abandoned'}]} value={nextStatus}/><Textarea label="修改原因" onChange={(event) => setStatusReason(event.target.value)} rows={3} value={statusReason}/></div></Modal>
|
||||
<Modal footer={<><Button onClick={() => setConfigType(undefined)} variant="ghost">取消</Button><Button disabled={!drainageFieldId} onClick={createField}>保存</Button></>} onClose={() => setConfigType(undefined)} open={Boolean(configType)} title={configType === 'drainage' ? '配置引流信息报备字段' : '配置签名报备字段'}>
|
||||
<div className="admin-system-modal-form">
|
||||
<Select label="报备字段库字段" onChange={(event) => setDrainageFieldId(event.target.value)} options={[{ label: '请选择字段', value: '' }, ...libraryFields.map((field) => ({ label: `${field.name ?? field.code}(${fieldTypeLabel[String(field.fieldType)] ?? field.fieldType})`, value: field.id }))]} value={drainageFieldId} />
|
||||
<Select label="是否必填" onChange={(event) => setRequired(event.target.value === 'true')} options={[{ label: '选填', value: 'false' }, { label: '必填', value: 'true' }]} value={String(required)} />
|
||||
<Textarea label="通道报备说明" onChange={(event) => setDescription(event.target.value)} rows={4} value={description} />
|
||||
</div>
|
||||
</Modal>
|
||||
{configType ? <ReportFieldMappingModal fields={fields} libraryFields={libraryFields} onClose={() => setConfigType(undefined)} onSave={saveFieldMapping} reportType={configType} /> : null}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user