safety-eval-service-frontend/src/pages/Container/QualApplication/filingPersist.js

285 lines
8.8 KiB
JavaScript
Raw Normal View History

2026-06-30 17:32:29 +08:00
import { fetchQualFilingDetail } from "~/api/qualFiling";
2026-07-07 17:13:33 +08:00
import { fromPageResponse, toPageQuery, toStaffForm, toEquipForm } from "~/utils/enterpriseInfo/adapter";
import { apiGet } from "~/utils/enterpriseInfo/http";
import { asId } from "~/utils/enterpriseInfo/idUtil";
2026-06-30 17:32:29 +08:00
import { resolveUploadFileId } from "~/utils/mockUpload";
import { toApiDate } from "~/utils/dateFormat";
import { FILING_FORM_MODE } from "~/enumerate/qualFilingOptions";
import { buildCommitmentContent } from "./filingCommitment";
export async function fetchOrgPersonnelOptions() {
const query = toPageQuery({ current: 1, size: 500 }, { likeStaffName: "userName" });
2026-07-02 14:51:26 +08:00
const res = await apiGet("/safetyEval/org-personnel/page", query);
2026-06-30 17:32:29 +08:00
const page = fromPageResponse(res, toStaffForm);
return (page?.data || []).map((row) => ({
label: row.staffName,
value: String(row.id),
staffName: row.staffName,
positionName: row.positionName,
titleName: row.titleName,
personType: row.personType,
registerEngineerFlag: row.registerEngineerFlag,
workExperience: row.workExperience,
}));
}
export function mapStaffRowToFilingPersonnel(row = {}) {
const id = asId(row.id);
return {
id: `local-person-${id}`,
sourcePersonnelId: id,
personName: row.staffName,
personTypeName: row.personType,
positionName: row.positionName,
titleName: row.titleName,
registerEngineerFlag: row.registerEngineerFlag,
workExperience: row.workExperience,
};
}
export function mapEquipRowToFilingEquipment(row = {}) {
const id = asId(row.id);
return {
id: `local-equip-${id}`,
sourceEquipmentId: id,
deviceName: row.deviceName,
deviceModel: row.deviceModel,
manufacturer: row.manufacturer,
calibrationReportUrl: row.calibrationReportUrl || "",
};
}
function collectBasicValues(detail = {}) {
const {
materials,
commitment,
personnelList,
equipmentList,
...basic
} = detail;
return basic;
}
function buildCommitmentPayload(detail) {
const commitment = detail.commitment || {};
const filingUnitName = commitment.filingUnitName || detail.filingUnitName || "";
const legalRepName = commitment.legalRepName || "";
const legalRepPersonnelId = commitment.legalRepPersonnelId || "";
return {
id: commitment.id,
filingId: detail.id,
legalRepSignatureUrl: commitment.legalRepSignatureUrl,
signDate: toApiDate(commitment.signDate),
legalRepPersonnelId,
legalRepName,
commitmentContent: buildCommitmentContent({ legalRepName, filingUnitName }),
};
}
function hasCommitmentData(detail = {}) {
const c = detail.commitment || {};
return !!(c.legalRepName || c.legalRepPersonnelId || c.signDate || c.legalRepSignatureUrl);
}
async function ensureBackendMaterials(props, filingId, backendMaterials = []) {
if ((backendMaterials || []).length > 0) {
return backendMaterials;
}
await props.qualFilingMaterialInitTemplate({ filingId });
const res = await fetchQualFilingDetail(filingId);
return res?.data?.materials || [];
}
async function syncMaterialsUploads(props, localMaterials = [], backendMaterials = []) {
const uploads = [];
for (const localMat of localMaterials) {
if (!localMat?.attachmentUrl) {
continue;
}
const backendMat = backendMaterials.find((m) => Number(m.sortOrder) === Number(localMat.sortOrder));
if (backendMat?.id && backendMat.attachmentUrl !== localMat.attachmentUrl) {
uploads.push(props.qualFilingMaterialUpload({
id: backendMat.id,
attachmentUrl: localMat.attachmentUrl,
}));
}
}
if (uploads.length) {
await Promise.all(uploads);
}
}
async function syncPersonnel(props, filingId, localList = [], backendList = []) {
const backendMap = new Map(
(backendList || []).map((p) => [String(p.sourcePersonnelId), p]),
);
const localIds = new Set(
localList.map((p) => String(p.sourcePersonnelId)).filter(Boolean),
);
const deletes = (backendList || [])
.filter((p) => !localIds.has(String(p.sourcePersonnelId)))
.map((p) => props.qualFilingPersonnelDelete({ id: p.id }));
if (deletes.length) {
await Promise.all(deletes);
}
const toAdd = [...localIds].filter((id) => !backendMap.has(id));
if (toAdd.length) {
await props.qualFilingPersonnelBatchAdd({
filingId,
sourcePersonnelIds: toAdd,
});
}
}
async function syncEquipment(props, filingId, localList = [], backendList = []) {
const backendMap = new Map(
(backendList || []).map((e) => [String(e.sourceEquipmentId), e]),
);
const localIds = new Set(
localList.map((e) => String(e.sourceEquipmentId)).filter(Boolean),
);
const deletes = (backendList || [])
.filter((e) => !localIds.has(String(e.sourceEquipmentId)))
.map((e) => props.qualFilingEquipmentDelete({ id: e.id }));
if (deletes.length) {
await Promise.all(deletes);
}
const toAdd = [...localIds].filter((id) => !backendMap.has(id));
if (toAdd.length) {
await props.qualFilingEquipmentBatchAdd({
filingId,
sourceEquipmentIds: toAdd,
});
}
const needCalibration = localList.some((e) => e.calibrationReportUrl);
if (!needCalibration) {
return;
}
const refreshed = await fetchQualFilingDetail(filingId);
const backendAfter = refreshed?.data?.equipmentList || [];
const calibrations = [];
for (const localEquip of localList) {
if (!localEquip.calibrationReportUrl) {
continue;
}
const backendEquip = backendAfter.find(
(e) => String(e.sourceEquipmentId) === String(localEquip.sourceEquipmentId),
);
if (backendEquip?.id && backendEquip.calibrationReportUrl !== localEquip.calibrationReportUrl) {
calibrations.push(props.qualFilingEquipmentUploadCalibration({
id: backendEquip.id,
attachmentUrl: localEquip.calibrationReportUrl,
}));
}
}
if (calibrations.length) {
await Promise.all(calibrations);
}
}
/**
* 将本地表单全量同步到后端暂存 / 提交确认时调用
*/
export async function persistFilingToBackend(props, detail, mode) {
let filingId = detail.id;
const basicValues = collectBasicValues(detail);
if (!filingId) {
const createDraft = mode === FILING_FORM_MODE.FILED
? props.qualFilingFiledDraft
: props.qualFilingDraft;
const draftRes = await createDraft();
if (draftRes?.success === false || !draftRes?.data?.id) {
throw new Error(draftRes?.message || "创建草稿失败");
}
filingId = draftRes.data.id;
basicValues.id = filingId;
}
const saveRes = await props.qualFilingSaveDraft({ ...basicValues, id: filingId });
if (saveRes?.success === false) {
throw new Error(saveRes?.message || "暂存基本信息失败");
}
if (detail.attachmentUrl) {
await props.qualFilingUploadAttachment({
id: filingId,
attachmentUrl: detail.attachmentUrl,
});
}
let backendDetail = (await fetchQualFilingDetail(filingId))?.data || {};
const backendMaterials = await ensureBackendMaterials(
props,
filingId,
backendDetail.materials,
);
await syncMaterialsUploads(props, detail.materials || [], backendMaterials);
if (hasCommitmentData(detail)) {
const commitmentRes = await props.qualFilingCommitmentSaveOrUpdate(
buildCommitmentPayload({ ...detail, id: filingId }),
);
if (commitmentRes?.success === false) {
throw new Error(commitmentRes?.message || "暂存承诺书失败");
}
}
const hasPersonnel = (detail.personnelList || []).length > 0;
const hasEquipment = (detail.equipmentList || []).length > 0;
if (hasPersonnel || hasEquipment) {
backendDetail = (await fetchQualFilingDetail(filingId))?.data || backendDetail;
}
if (hasPersonnel) {
await syncPersonnel(
props,
filingId,
detail.personnelList || [],
backendDetail.personnelList || [],
);
}
if (hasEquipment) {
if (hasPersonnel) {
backendDetail = (await fetchQualFilingDetail(filingId))?.data || backendDetail;
}
await syncEquipment(
props,
filingId,
detail.equipmentList || [],
backendDetail.equipmentList || [],
);
}
const finalDetail = await fetchQualFilingDetail(filingId);
return finalDetail?.data || { id: filingId };
}
export function mergeDetailFromForms(detail, { basicValues, commitmentValues }) {
2026-07-01 17:57:42 +08:00
2026-06-30 17:32:29 +08:00
return {
...detail,
...basicValues,
2026-07-02 15:01:19 +08:00
attachmentUrl: Array.isArray(basicValues?.attachmentUrl) ? basicValues?.attachmentUrl?.map((file) => file.url).join(",") : basicValues?.attachmentUrl,
2026-06-30 17:32:29 +08:00
materials: detail.materials,
personnelList: detail.personnelList,
equipmentList: detail.equipmentList,
commitment: {
...detail.commitment,
...commitmentValues,
2026-07-02 15:01:19 +08:00
legalRepSignatureUrl: Array.isArray(commitmentValues?.legalRepSignatureUrl) ? commitmentValues?.legalRepSignatureUrl?.map((file) => file.url).join(",") : commitmentValues?.legalRepSignatureUrl,
2026-06-30 17:32:29 +08:00
},
};
}