import { Connect } from "@cqsjjb/jjb-dva-runtime"; import { Button, Form, message, Modal, Space, Spin, Tabs } from "antd"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; import { fetchQualFilingDetail } from "~/api/qualFiling"; import { NS_QUAL_FILING } from "~/enumerate/namespace"; import { FILING_FORM_MODE, isQualFilingEditable, } from "~/enumerate/qualFilingOptions"; import { createLocalMaterials } from "../filingMaterialTemplate"; import { clearLocalDraft, createEmptyFilingDetail, loadLocalDraft, saveLocalDraft, } from "../filingLocalDraft"; import { fetchOrgPersonnelOptions, mapEquipRowToFilingEquipment, mapStaffRowToFilingPersonnel, mergeDetailFromForms, persistFilingToBackend, } from "../filingPersist"; import { verifyFilingPrerequisites } from "../filingVerify"; import { toDayjs } from "~/utils/dateFormat"; import { resolveUploadFileId } from "~/utils/mockUpload"; import { goFilingList, parseFilingFormQuery } from "../filingPaths"; import BasicInfoStep from "./components/BasicInfoStep"; import CommitmentStep from "./components/CommitmentStep"; import EquipmentStep from "./components/EquipmentStep"; import MaterialStep from "./components/MaterialStep"; import PersonnelStep from "./components/PersonnelStep"; import PrerequisiteVerifyModal from "./components/PrerequisiteVerifyModal"; const STEP_ITEMS = [ { key: "basic", label: "1. 备案基本信息" }, { key: "materials", label: "2. 备案材料上传" }, { key: "commitment", label: "3. 法定代表人承诺书" }, { key: "personnel", label: "4. 备案人员管理" }, { key: "equipment", label: "5. 装备清单" }, ]; const MODE_TITLE = { [FILING_FORM_MODE.APPLICATION]: "资质备案申请", [FILING_FORM_MODE.FILED]: "资质备案填报", [FILING_FORM_MODE.CHANGE]: "修改备案信息", }; function syncForms(detail, basicForm, commitmentForm) { if (!detail) { return; } basicForm.setFieldsValue(detail); commitmentForm.setFieldsValue({ ...detail.commitment, filingUnitName: detail.commitment?.filingUnitName || detail.filingUnitName, signDate: toDayjs(detail.commitment?.signDate), }); } function FilingFormPage(props) { const query = useMemo( () => parseFilingFormQuery(window.location.search), [], ); const filingId = query.id; const mode = query.mode; const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [activeStep, setActiveStep] = useState("basic"); const [detail, setDetail] = useState(null); const [personnelOptions, setPersonnelOptions] = useState([]); const [verifyOpen, setVerifyOpen] = useState(false); const [verifyResult, setVerifyResult] = useState(null); const [basicForm] = Form.useForm(); const [commitmentForm] = Form.useForm(); const [activeFilingId] = useState(filingId); const detailRef = useRef(null); const readOnly = query.readOnly || (detail ? !isQualFilingEditable(detail.filingStatusCode) : false); const listMode = mode === FILING_FORM_MODE.FILED ? "filed" : mode === FILING_FORM_MODE.CHANGE ? "change" : "application"; const goBackList = useCallback(() => goFilingList(listMode), [listMode]); const saveActionHint = mode === FILING_FORM_MODE.FILED ? "请点击提交后保存" : "请点击暂存或提交后保存"; const loadInitialDetail = useCallback(async () => { if (activeFilingId) { const res = await fetchQualFilingDetail(activeFilingId); if (res?.success === false) { message.error(res.message || "加载备案详情失败"); return null; } const data = res?.data || null; if (data && !(data.materials || []).length) { data.materials = createLocalMaterials(); } return data; } const cached = loadLocalDraft(mode); if (cached) { return cached; } return createEmptyFilingDetail(); }, [activeFilingId, mode]); const loadPersonnelOptions = useCallback(async () => { if (personnelOptions.length) { return personnelOptions; } const options = await fetchOrgPersonnelOptions().catch(() => []); setPersonnelOptions(options); return options; }, [personnelOptions.length]); useEffect(() => { detailRef.current = detail; }, [detail]); useEffect(() => { let cancelled = false; (async () => { setLoading(true); try { const data = await loadInitialDetail(); if (cancelled || !data) { return; } setDetail(data); detailRef.current = data; syncForms(data, basicForm, commitmentForm); } finally { if (!cancelled) { setLoading(false); } } })(); return () => { cancelled = true; }; }, [basicForm, commitmentForm, loadInitialDetail]); useEffect(() => { if (!detail?.commitment?.legalRepPersonnelId && !detail?.commitment?.legalRepName) { return; } loadPersonnelOptions(); }, [detail?.commitment?.legalRepPersonnelId, detail?.commitment?.legalRepName, loadPersonnelOptions]); useEffect(() => { if (activeStep !== "commitment" && !detail?.commitment?.legalRepPersonnelId) { return; } if (personnelOptions.length) { return; } loadPersonnelOptions(); }, [activeStep, detail?.commitment?.legalRepPersonnelId, loadPersonnelOptions, personnelOptions.length]); useEffect(() => { if (!personnelOptions.length) { return; } const data = detailRef.current; const commitment = data?.commitment || {}; if (commitment.legalRepPersonnelId) { commitmentForm.setFieldValue("legalRepPersonnelId", String(commitment.legalRepPersonnelId)); return; } if (commitment.legalRepName) { const matched = personnelOptions.find((item) => item.staffName === commitment.legalRepName); if (matched) { commitmentForm.setFieldsValue({ legalRepPersonnelId: matched.value, legalRepName: matched.staffName || matched.label, }); } } }, [commitmentForm, personnelOptions]); const updateDetail = useCallback((updater) => { setDetail((prev) => { const next = typeof updater === "function" ? updater(prev) : { ...prev, ...updater }; detailRef.current = next; if (!activeFilingId && !readOnly) { saveLocalDraft(mode, next); } return next; }); }, [activeFilingId, mode, readOnly]); const collectCurrentDetail = useCallback(() => { const current = detailRef.current || detail; return mergeDetailFromForms(current, { basicValues: basicForm.getFieldsValue(true), commitmentValues: commitmentForm.getFieldsValue(true), }); }, [basicForm, commitmentForm, detail]); const handleSaveDraft = async () => { if (readOnly) { return; } setSubmitting(true); try { const currentDetail = collectCurrentDetail(); await persistFilingToBackend(props, currentDetail, mode); clearLocalDraft(mode); message.success("已暂存"); goBackList(); } catch (err) { message.error(err?.message || "暂存失败"); } finally { setSubmitting(false); } }; const handleSubmitRequest = () => { if (readOnly) { return; } const currentDetail = collectCurrentDetail(); const result = verifyFilingPrerequisites(currentDetail); setVerifyResult(result); setVerifyOpen(true); }; const handleVerifyConfirm = async () => { if (!verifyResult?.passed) { return; } setSubmitting(true); try { const currentDetail = collectCurrentDetail(); const saved = await persistFilingToBackend(props, currentDetail, mode); clearLocalDraft(mode); if (mode === FILING_FORM_MODE.CHANGE) { const res = await props.qualFilingChangeSubmit({ draftFilingId: saved.id }); if (res?.success === false) { message.error(res.message || "提交失败"); return; } } else { const res = await props.qualFilingSubmit({ id: saved.id }); if (res?.success === false) { message.error(res.message || "提交失败"); return; } } setVerifyOpen(false); message.success("提交成功"); goBackList(); } catch (err) { message.error(err?.message || "提交失败"); } finally { setSubmitting(false); } }; const handleMaterialUpload = (record, url) => { const attachmentUrl = url || resolveUploadFileId([]); updateDetail((prev) => ({ ...prev, materials: (prev.materials || []).map((item) => ( item.id === record.id || item.sortOrder === record.sortOrder ? { ...item, attachmentUrl, uploadStatusCode: 2, uploadStatusName: "已上传", } : item )), })); message.success(`材料已选择,${saveActionHint}`); }; const handleAttachmentChange = (url) => { updateDetail((prev) => ({ ...prev, attachmentUrl: url })); }; const handleSignatureChange = (url, files) => { commitmentForm.setFieldsValue({ signatureFiles: files, legalRepSignatureUrl: url }); updateDetail((prev) => ({ ...prev, commitment: { ...prev.commitment, legalRepSignatureUrl: url, signatureFiles: files, }, })); }; const handlePersonnelAdd = (sourcePersonnelIds, rows = []) => { const existing = new Set( (detailRef.current?.personnelList || []).map((item) => String(item.sourcePersonnelId)), ); const idsToAdd = sourcePersonnelIds.filter((id) => !existing.has(String(id))); if (!idsToAdd.length) { return; } const rowMap = new Map((rows || []).map((row) => [String(row.id), row])); const newRows = idsToAdd.map((id) => { const row = rowMap.get(String(id)); return row ? mapStaffRowToFilingPersonnel(row) : mapStaffRowToFilingPersonnel({ id }); }); updateDetail((prev) => ({ ...prev, personnelList: [...(prev.personnelList || []), ...newRows], })); message.success(`已添加至列表,${saveActionHint}`); }; const handlePersonnelRemove = (record) => { Modal.confirm({ title: "提示", content: `确认删除人员「${record.personName}」?`, onOk: () => { updateDetail((prev) => ({ ...prev, personnelList: (prev.personnelList || []).filter((item) => item.id !== record.id), })); }, }); }; const handleEquipmentAdd = (sourceEquipmentIds, rows = []) => { const existing = new Set( (detailRef.current?.equipmentList || []).map((item) => String(item.sourceEquipmentId)), ); const idsToAdd = sourceEquipmentIds.filter((id) => !existing.has(String(id))); if (!idsToAdd.length) { return; } const rowMap = new Map((rows || []).map((row) => [String(row.id), row])); const newRows = idsToAdd.map((id) => { const row = rowMap.get(String(id)); return row ? mapEquipRowToFilingEquipment(row) : mapEquipRowToFilingEquipment({ id }); }); updateDetail((prev) => ({ ...prev, equipmentList: [...(prev.equipmentList || []), ...newRows], })); message.success(`已添加至列表,${saveActionHint}`); }; const handleEquipmentRemove = (record) => { Modal.confirm({ title: "提示", content: `确认移除装备「${record.deviceName}」?`, onOk: () => { updateDetail((prev) => ({ ...prev, equipmentList: (prev.equipmentList || []).filter((item) => item.id !== record.id), })); }, }); }; const handleEquipmentCalibration = (record, url) => { updateDetail((prev) => ({ ...prev, equipmentList: (prev.equipmentList || []).map((item) => ( item.id === record.id ? { ...item, calibrationReportUrl: url } : item )), })); }; const stepIndex = STEP_ITEMS.findIndex((item) => item.key === activeStep); const isLastStep = stepIndex === STEP_ITEMS.length - 1; return ( goFilingList( mode === FILING_FORM_MODE.FILED ? "filed" : mode === FILING_FORM_MODE.CHANGE ? "change" : "application", )} > 返回列表 )} > { if (key === "commitment") { commitmentForm.setFieldsValue({ filingUnitName: basicForm.getFieldValue("filingUnitName") || detail?.filingUnitName, }); loadPersonnelOptions(); } setActiveStep(key); }} />
{activeStep === "basic" && ( )} {activeStep === "materials" && ( )} {activeStep === "commitment" && ( )} {activeStep === "personnel" && ( )} {activeStep === "equipment" && ( )}
{stepIndex > 0 && ( )} {!isLastStep && ( )} {!readOnly && isLastStep && ( <> {mode !== FILING_FORM_MODE.FILED && ( )} )}
setVerifyOpen(false)} onConfirm={handleVerifyConfirm} />
); } export default Connect([NS_QUAL_FILING], true)(FilingFormPage);