fix
parent
425dfde6c9
commit
4b0678087e
|
|
@ -9,6 +9,7 @@ import {
|
||||||
fetchStaffCertListByPersonnelId,
|
fetchStaffCertListByPersonnelId,
|
||||||
} from "~/api/staffCertificate";
|
} from "~/api/staffCertificate";
|
||||||
import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper";
|
import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper";
|
||||||
|
import { TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
||||||
|
|
||||||
const GENDER_MAP = { 1: "男", 2: "女" };
|
const GENDER_MAP = { 1: "男", 2: "女" };
|
||||||
const REGISTER_ENGINEER_MAP = { 1: "是", 2: "否" };
|
const REGISTER_ENGINEER_MAP = { 1: "是", 2: "否" };
|
||||||
|
|
@ -152,7 +153,7 @@ export default function StaffViewModal({
|
||||||
{info.educationLevelName || "-"}
|
{info.educationLevelName || "-"}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="职称">
|
<Descriptions.Item label="职称">
|
||||||
{info.titleName || "-"}
|
{TITLE_LEVEL_MAP[info.titleCode] ?? (info.titleCode || "-")}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="是否注册安全工程师">
|
<Descriptions.Item label="是否注册安全工程师">
|
||||||
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
|
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
|
||||||
|
|
|
||||||
|
|
@ -173,3 +173,15 @@ export const REGISTER_ENGINEER_OPTIONS = [
|
||||||
{ label: "是", value: 1 },
|
{ label: "是", value: 1 },
|
||||||
{ label: "否", value: 2 },
|
{ label: "否", value: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** 职称等级 */
|
||||||
|
export const TITLE_LEVEL_OPTIONS = [
|
||||||
|
{ value: "SENIOR", label: "高级" },
|
||||||
|
{ value: "MIDDLE", label: "中级" },
|
||||||
|
{ value: "JUNIOR", label: "初级" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const TITLE_LEVEL_MAP = TITLE_LEVEL_OPTIONS.reduce(
|
||||||
|
(acc, cur) => ({ ...acc, [cur.value]: cur.label }),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import {
|
||||||
PROFESSIONAL_LEVEL_OPTIONS,
|
PROFESSIONAL_LEVEL_OPTIONS,
|
||||||
QUALIFICATION_INDUSTRY_OPTIONS,
|
QUALIFICATION_INDUSTRY_OPTIONS,
|
||||||
REGISTER_ENGINEER_OPTIONS,
|
REGISTER_ENGINEER_OPTIONS,
|
||||||
|
TITLE_LEVEL_OPTIONS,
|
||||||
} from "~/enumerate/enterpriseOptions";
|
} from "~/enumerate/enterpriseOptions";
|
||||||
import { getBirthDateFromIdCard } from "~/utils";
|
import { getBirthDateFromIdCard } from "~/utils";
|
||||||
import { idCardRule, mobileRule } from "~/utils/validators";
|
import { idCardRule, mobileRule } from "~/utils/validators";
|
||||||
|
|
@ -689,11 +690,11 @@ function StaffFormModal({
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="titleName"
|
name="titleCode"
|
||||||
label="职称"
|
label="职称"
|
||||||
rules={[{ max: 50, message: "职称不能超过50个字符" }]}
|
rules={[{ required: false, message: "请选择职称" }]}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入职称" maxLength={50} showCount />
|
<Select placeholder="请选择职称" allowClear options={TITLE_LEVEL_OPTIONS} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { Button, Form, Input, Modal, Table } from "antd";
|
import { Button, Form, Input, Modal, Table } from "antd";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { NS_STAFF_INFO } from "~/enumerate/namespace";
|
import { NS_STAFF_INFO } from "~/enumerate/namespace";
|
||||||
|
import { TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
|
|
||||||
function OrgPersonnelSelectModalInner(props) {
|
function OrgPersonnelSelectModalInner(props) {
|
||||||
|
|
@ -97,7 +98,7 @@ function OrgPersonnelSelectModalInner(props) {
|
||||||
{ title: "人员姓名", dataIndex: "userName", ellipsis: true },
|
{ title: "人员姓名", dataIndex: "userName", ellipsis: true },
|
||||||
{ title: "类型", dataIndex: "personTypeName" },
|
{ title: "类型", dataIndex: "personTypeName" },
|
||||||
|
|
||||||
{ title: "职称", dataIndex: "titleName", ellipsis: true },
|
{ title: "职称", dataIndex: "titleName", ellipsis: true, render: (_, record) => TITLE_LEVEL_MAP[record.titleCode] ?? (record.titleCode || "-") },
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 80,
|
width: 80,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Button, Modal, Space, Table } from "antd";
|
import { Button, Modal, Space, Table } from "antd";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
import OrgPersonnelSelectModal from "./OrgPersonnelSelectModal";
|
import OrgPersonnelSelectModal from "./OrgPersonnelSelectModal";
|
||||||
|
|
||||||
|
|
@ -38,7 +39,7 @@ const PersonnelStep=({
|
||||||
{ title: "人员姓名", dataIndex: "userName", render: (_, record) => record.userName || record.personName },
|
{ title: "人员姓名", dataIndex: "userName", render: (_, record) => record.userName || record.personName },
|
||||||
{ title: "类型", dataIndex: "personTypeName" },
|
{ title: "类型", dataIndex: "personTypeName" },
|
||||||
|
|
||||||
{ title: "职称", dataIndex: "titleName" },
|
{ title: "职称", dataIndex: "titleName", render: (_, record) => TITLE_LEVEL_MAP[record.titleCode] ?? (record.titleCode || "-") },
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 140,
|
width: 140,
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ import { FILING_MATERIAL_TEMPLATE } from "../filingMaterialTemplate";
|
||||||
import {
|
import {
|
||||||
fetchOrgPersonnelOptions,
|
fetchOrgPersonnelOptions,
|
||||||
mapEquipRowToFilingEquipment,
|
mapEquipRowToFilingEquipment,
|
||||||
mapStaffRowToFilingPersonnel,
|
|
||||||
mergeDetailFromForms,
|
mergeDetailFromForms,
|
||||||
persistFilingToBackend,
|
|
||||||
} from "../filingPersist";
|
} from "../filingPersist";
|
||||||
import { verifyFilingPrerequisites } from "../filingVerify";
|
import { verifyFilingPrerequisites } from "../filingVerify";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,23 @@
|
||||||
import { fetchQualFilingDetail } from "~/api/qualFiling";
|
import { fromPageResponse, toPageQuery } from "~/utils/enterpriseInfo/adapter";
|
||||||
import { fromPageResponse, toPageQuery, toStaffForm, toEquipForm } from "~/utils/enterpriseInfo/adapter";
|
|
||||||
import { apiGet } from "~/utils/enterpriseInfo/http";
|
import { apiGet } from "~/utils/enterpriseInfo/http";
|
||||||
import { asId } from "~/utils/enterpriseInfo/idUtil";
|
import { asId } from "~/utils/enterpriseInfo/idUtil";
|
||||||
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() {
|
export async function fetchOrgPersonnelOptions() {
|
||||||
const query = toPageQuery({ current: 1, size: 500 }, { likeStaffName: "userName" });
|
const query = toPageQuery({ current: 1, size: 500 }, { likeStaffName: "userName" });
|
||||||
const res = await apiGet("/safetyEval/org-personnel/page", query);
|
const res = await apiGet("/safetyEval/org-personnel/page", query);
|
||||||
const page = fromPageResponse(res, toStaffForm);
|
const page = fromPageResponse(res);
|
||||||
return (page?.data || []).map((row) => ({
|
return (page?.data || []).map((data) => ({
|
||||||
label: row.staffName,
|
label: data.userName,
|
||||||
value: String(row.id),
|
value: String(data.id),
|
||||||
staffName: row.staffName,
|
staffName: data.userName,
|
||||||
positionName: row.positionName,
|
positionName: data.postName ?? data.positionName,
|
||||||
titleName: row.titleName,
|
titleName: data.titleName,
|
||||||
personType: row.personType,
|
personType: data.personTypeName ?? "基础人员",
|
||||||
registerEngineerFlag: row.registerEngineerFlag,
|
registerEngineerFlag: data.registerEngineerFlag ?? 2,
|
||||||
workExperience: row.workExperience,
|
workExperience: data.workExperience,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapStaffRowToFilingPersonnel(row = {}) {
|
|
||||||
const id = asId(row.id);
|
|
||||||
return {
|
|
||||||
id: `local-person-${id}`,
|
|
||||||
sourcePersonnelId: id,
|
|
||||||
personName: row.staffName,
|
|
||||||
userName: row.staffName,
|
|
||||||
personTypeName: row.personType,
|
|
||||||
positionName: row.positionName,
|
|
||||||
titleName: row.titleName,
|
|
||||||
registerEngineerFlag: row.registerEngineerFlag,
|
|
||||||
workExperience: row.workExperience,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapEquipRowToFilingEquipment(row = {}) {
|
export function mapEquipRowToFilingEquipment(row = {}) {
|
||||||
const id = asId(row.id);
|
const id = asId(row.id);
|
||||||
return {
|
return {
|
||||||
|
|
@ -50,227 +30,6 @@ export function mapEquipRowToFilingEquipment(row = {}) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将本地表单全量同步到后端(暂存 / 提交确认时调用)
|
|
||||||
*/
|
|
||||||
function getApiErrorMessage(res, fallback) {
|
|
||||||
return res?.message || res?.errMessage || fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(getApiErrorMessage(draftRes, "创建草稿失败"));
|
|
||||||
}
|
|
||||||
filingId = draftRes.data.id;
|
|
||||||
basicValues.id = filingId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveRes = await props.qualFilingSaveDraft({ ...basicValues, id: filingId });
|
|
||||||
if (saveRes?.success === false) {
|
|
||||||
throw new Error(getApiErrorMessage(saveRes, "暂存基本信息失败"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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(getApiErrorMessage(commitmentRes, "暂存承诺书失败"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 }) {
|
export function mergeDetailFromForms(detail, { basicValues, commitmentValues }) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ function ratio(count, total) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function includesSeniorTitle(titleName = "") {
|
function includesSeniorTitle(titleName = "") {
|
||||||
return String(titleName).includes("高级");
|
return titleName === "SENIOR";
|
||||||
}
|
}
|
||||||
|
|
||||||
function includesMidTitle(titleName = "") {
|
function includesMidTitle(titleName = "") {
|
||||||
return String(titleName).includes("中级") || includesSeniorTitle(titleName);
|
return titleName === "MIDDLE" || titleName === "SENIOR";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRegisterEngineer(record = {}) {
|
function isRegisterEngineer(record = {}) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { NS_QUAL_REVIEW } from "~/enumerate/namespace";
|
import { NS_QUAL_REVIEW } from "~/enumerate/namespace";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
import PreviewUrlButton from "~/components/PreviewUrlButton/index";
|
import PreviewUrlButton from "~/components/PreviewUrlButton/index";
|
||||||
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP, TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -153,7 +153,7 @@ const FilingTabs = ({
|
||||||
{ title: "人员姓名", dataIndex: "personName", width: 100 },
|
{ title: "人员姓名", dataIndex: "personName", width: 100 },
|
||||||
{ title: "类型", dataIndex: "personTypeName", width: 100 },
|
{ title: "类型", dataIndex: "personTypeName", width: 100 },
|
||||||
|
|
||||||
{ title: "职称", dataIndex: "titleName", width: 100 },
|
{ title: "职称", dataIndex: "titleName", width: 100, render: (_, record) => TITLE_LEVEL_MAP[record.titleCode] ?? (record.titleCode || "-") },
|
||||||
{ title: "操作", width: 80,
|
{ title: "操作", width: 80,
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Button type="link" size="small" onClick={() => setViewId(record.sourcePersonnelId)}>
|
<Button type="link" size="small" onClick={() => setViewId(record.sourcePersonnelId)}>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,8 @@
|
||||||
/** 企业信息管理:前后端字段与分页格式适配 */
|
/** 企业信息管理:前后端字段与分页格式适配 */
|
||||||
|
|
||||||
import { formatDate, formatDateTime, normalizeDateValue, toApiDate, toApiDateTime } from "../../utils/dateFormat";
|
|
||||||
import { resolveUploadFileIds } from "../../utils/mockUpload";
|
|
||||||
import { asId, isIdFieldName, normalizeQueryIds } from "./idUtil";
|
import { asId, isIdFieldName, normalizeQueryIds } from "./idUtil";
|
||||||
import { withOrgId } from "./orgContext";
|
import { withOrgId } from "./orgContext";
|
||||||
|
|
||||||
const GENDER_NAME = { 1: "男", 2: "女" };
|
|
||||||
const RESIGN_AUDIT_STATUS_NAME = { 0: "未审核", 1: "已审核", 2: "已退回" };
|
|
||||||
const ENTERPRISE_STATUS_CODE = { 正常: 1, 停业: 2, 注销: 3 };
|
|
||||||
const FILING_TYPE_CODE = { 审核备案: "1", 确认备案: "2" };
|
|
||||||
const FILING_RECORD_STATUS_CODE = { 已备案: 1, 未备案: 2 };
|
|
||||||
const PERSON_TYPE_CODE = { 基础人员: "1", 专职评价师: "2" };
|
|
||||||
|
|
||||||
function parseAttachmentUrls(urls, defaultName = "附件.pdf") {
|
function parseAttachmentUrls(urls, defaultName = "附件.pdf") {
|
||||||
if (!urls) {
|
if (!urls) {
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -27,7 +18,10 @@ function parseAttachmentUrls(urls, defaultName = "附件.pdf") {
|
||||||
.filter((item) => item?.url)
|
.filter((item) => item?.url)
|
||||||
.map((item) => ({
|
.map((item) => ({
|
||||||
name: item.name || `${defaultName.replace(".pdf", "")}1`,
|
name: item.name || `${defaultName.replace(".pdf", "")}1`,
|
||||||
fileName: item.fileName || item.name || `${defaultName.replace(".pdf", "")}1`,
|
fileName:
|
||||||
|
item.fileName ||
|
||||||
|
item.name ||
|
||||||
|
`${defaultName.replace(".pdf", "")}1`,
|
||||||
url: item.url,
|
url: item.url,
|
||||||
uid: item.uid || undefined,
|
uid: item.uid || undefined,
|
||||||
status: item.status || "done",
|
status: item.status || "done",
|
||||||
|
|
@ -87,652 +81,8 @@ export function fromSingleResponse(res, mapItem) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function pick(obj, keys) {
|
|
||||||
const next = {};
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (obj[key] !== undefined) {
|
|
||||||
next[key] = isIdFieldName(key) ? asId(obj[key]) : obj[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 机构信息 ───
|
|
||||||
|
|
||||||
export function toOrgInfoForm(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
orgName: data.unitName,
|
|
||||||
creditCode: data.creditCode,
|
|
||||||
safetyIndustryCategory: data.safetyIndustryCategoryName,
|
|
||||||
regionCountyName: data.districtName,
|
|
||||||
regionStreetName: data.townStreet,
|
|
||||||
regionCommunityName: data.villageCommunity,
|
|
||||||
longitude: data.longitude,
|
|
||||||
latitude: data.latitude,
|
|
||||||
registerAddress: data.registerAddress,
|
|
||||||
businessAddress: data.businessAddress,
|
|
||||||
ownershipType: data.ownershipTypeName,
|
|
||||||
gbIndustryCode: data.economyIndustryCode,
|
|
||||||
legalRepresentative: data.legalRepresentative,
|
|
||||||
legalRepPhone: data.legalRepresentativePhone,
|
|
||||||
principal: data.principalName,
|
|
||||||
principalPhone: data.principalPhone,
|
|
||||||
safetyDeptHead: data.safetyDeptManager,
|
|
||||||
safetyDeptPhone: data.safetyDeptManagerPhone,
|
|
||||||
safetyVpPhone: data.safetyDeputyPhone,
|
|
||||||
productionDate: data.productionDate,
|
|
||||||
businessStatus: data.businessStatusName,
|
|
||||||
disclosureUrl: data.infoDisclosureUrl,
|
|
||||||
workplaceArea: data.workplaceArea,
|
|
||||||
archiveRoomArea: data.archiveRoomArea,
|
|
||||||
fullTimeEvaluatorCount: data.fulltimeEvaluatorCount,
|
|
||||||
registeredSafetyEngineerCount: data.registeredEngineerCount,
|
|
||||||
authStatusCode: data.authStatusCode,
|
|
||||||
enterpriseStatus: data.enterpriseStatusName,
|
|
||||||
enterpriseScale: data.enterpriseScaleName,
|
|
||||||
filingType: data.filingTypeName ?? "确认备案",
|
|
||||||
filingRecordStatus: data.filingRecordStatusName ?? "未备案",
|
|
||||||
attachments: parseAttachmentUrls(data.attachmentUrls),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromOrgInfoForm(values = {}, options = {}) {
|
|
||||||
const { isDraft = false } = options;
|
|
||||||
const enterpriseStatus = values.enterpriseStatus;
|
|
||||||
const filingType = values.filingType ?? "确认备案";
|
|
||||||
const filingRecordStatus = values.filingRecordStatus ?? "未备案";
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
unitName: values.orgName,
|
|
||||||
creditCode: values.creditCode,
|
|
||||||
safetyIndustryCategoryName: values.safetyIndustryCategory,
|
|
||||||
districtCode: values.regionCountyName,
|
|
||||||
districtName: values.regionCountyName,
|
|
||||||
townStreet: values.regionStreetName,
|
|
||||||
villageCommunity: values.regionCommunityName,
|
|
||||||
longitude: values.longitude,
|
|
||||||
latitude: values.latitude,
|
|
||||||
registerAddress: values.registerAddress,
|
|
||||||
businessAddress: values.businessAddress,
|
|
||||||
ownershipTypeName: values.ownershipType,
|
|
||||||
economyIndustryCode: values.gbIndustryCode,
|
|
||||||
legalRepresentative: values.legalRepresentative,
|
|
||||||
legalRepresentativePhone: values.legalRepPhone,
|
|
||||||
principalName: values.principal,
|
|
||||||
principalPhone: values.principalPhone,
|
|
||||||
safetyDeptManager: values.safetyDeptHead,
|
|
||||||
safetyDeptManagerPhone: values.safetyDeptPhone,
|
|
||||||
safetyDeputyPhone: values.safetyVpPhone,
|
|
||||||
productionDate: values.productionDate,
|
|
||||||
businessStatusName: values.businessStatus,
|
|
||||||
infoDisclosureUrl: values.disclosureUrl,
|
|
||||||
workplaceArea: values.workplaceArea,
|
|
||||||
archiveRoomArea: values.archiveRoomArea,
|
|
||||||
fulltimeEvaluatorCount: values.fullTimeEvaluatorCount,
|
|
||||||
registeredEngineerCount: values.registeredSafetyEngineerCount,
|
|
||||||
authStatusCode: isDraft ? 0 : 1,
|
|
||||||
authStatusName: isDraft ? "草稿" : "已提交",
|
|
||||||
enterpriseStatusCode: ENTERPRISE_STATUS_CODE[enterpriseStatus],
|
|
||||||
enterpriseStatusName: enterpriseStatus,
|
|
||||||
enterpriseScaleCode: values.enterpriseScale,
|
|
||||||
enterpriseScaleName: values.enterpriseScale,
|
|
||||||
filingTypeCode: FILING_TYPE_CODE[filingType] ?? filingType,
|
|
||||||
filingTypeName: filingType,
|
|
||||||
filingRecordStatusCode: FILING_RECORD_STATUS_CODE[filingRecordStatus],
|
|
||||||
filingRecordStatusName: filingRecordStatus,
|
|
||||||
attachmentUrls: resolveUploadFileIds(values.attachments),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 监管端机构账号:后端 state 0=启用,1=禁用 */
|
/** 监管端机构账号:后端 state 0=启用,1=禁用 */
|
||||||
export function isOrgAccountEnabled(record = {}) {
|
export function isOrgAccountEnabled(record = {}) {
|
||||||
return Number(record.state) === 0;
|
return Number(record.state) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toOrgAccountRow(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
orgName: data.unitName,
|
|
||||||
district: data.districtName,
|
|
||||||
state: data.state,
|
|
||||||
createTime: formatDate(normalizeDateValue(data.createTime)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 监管端分页查询(不带 orgInfoId;部分筛选项需后端 OrgInfoPageQuery 扩展后生效) */
|
|
||||||
export function toRegulatorOrgAccountPageQuery(params = {}) {
|
|
||||||
const query = {
|
|
||||||
current: params.pageIndex ?? params.current ?? 1,
|
|
||||||
size: params.pageSize ?? params.size ?? 10,
|
|
||||||
};
|
|
||||||
if (params.orgName) {
|
|
||||||
query.unitName = params.orgName;
|
|
||||||
}
|
|
||||||
if (params.district) {
|
|
||||||
query.districtName = params.district;
|
|
||||||
}
|
|
||||||
const state = params.state;
|
|
||||||
if (state !== undefined && state !== null && state !== "" && state !== "全部") {
|
|
||||||
query.state = Number(state);
|
|
||||||
}
|
|
||||||
const range = params.openTimeRange;
|
|
||||||
if (Array.isArray(range) && range.length === 2 && range[0] && range[1]) {
|
|
||||||
query.createTimeStart = range[0].format ? range[0].format("YYYY-MM-DD") : range[0];
|
|
||||||
query.createTimeEnd = range[1].format ? range[1].format("YYYY-MM-DD") : range[1];
|
|
||||||
}
|
|
||||||
return normalizeQueryIds(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 监管端已备案机构列表行 */
|
|
||||||
export function toRegisteredOrgRow(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
orgName: data.unitName,
|
|
||||||
registerAddress: data.registerAddress,
|
|
||||||
serviceEnterpriseCount: 0,
|
|
||||||
evalProjectCount: 0,
|
|
||||||
filingType: data.filingTypeName,
|
|
||||||
filingRecordStatusCode: data.filingRecordStatusCode,
|
|
||||||
filingRecordStatusName: data.filingRecordStatusName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 监管端已备案机构分页查询 */
|
|
||||||
export function toRegisteredOrgPageQuery(params = {}) {
|
|
||||||
const query = {
|
|
||||||
current: params.pageIndex ?? params.current ?? 1,
|
|
||||||
size: params.pageSize ?? params.size ?? 10,
|
|
||||||
};
|
|
||||||
if (params.orgName) {
|
|
||||||
query.unitName = params.orgName;
|
|
||||||
}
|
|
||||||
if (params.registerAddress) {
|
|
||||||
query.registerAddress = params.registerAddress;
|
|
||||||
}
|
|
||||||
const filingTypeCode = params.filingType;
|
|
||||||
if (filingTypeCode !== undefined && filingTypeCode !== null && filingTypeCode !== "") {
|
|
||||||
query.filingTypeCode = String(filingTypeCode);
|
|
||||||
}
|
|
||||||
const filingRecordStatusCode = params.filingRecordStatus;
|
|
||||||
if (filingRecordStatusCode !== undefined && filingRecordStatusCode !== null && filingRecordStatusCode !== "") {
|
|
||||||
query.filingRecordStatusCode = Number(filingRecordStatusCode);
|
|
||||||
}
|
|
||||||
return normalizeQueryIds(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromRegulatorOrgInfoModify(values = {}, existing = {}) {
|
|
||||||
const merged = {
|
|
||||||
...toOrgInfoForm(existing),
|
|
||||||
...values,
|
|
||||||
id: asId(values.id ?? existing.id),
|
|
||||||
};
|
|
||||||
const payload = fromOrgInfoForm(merged, { isDraft: false });
|
|
||||||
return {
|
|
||||||
...payload,
|
|
||||||
id: asId(values.id ?? existing.id),
|
|
||||||
authStatusCode: existing.authStatusCode ?? payload.authStatusCode,
|
|
||||||
authStatusName: existing.authStatusName ?? payload.authStatusName,
|
|
||||||
tenantId: existing.tenantId ?? payload.tenantId,
|
|
||||||
filingTypeCode: existing.filingTypeCode ?? payload.filingTypeCode,
|
|
||||||
filingTypeName: existing.filingTypeName ?? payload.filingTypeName,
|
|
||||||
filingRecordStatusCode: existing.filingRecordStatusCode ?? payload.filingRecordStatusCode,
|
|
||||||
filingRecordStatusName: existing.filingRecordStatusName ?? payload.filingRecordStatusName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 部门 / 岗位 ───
|
|
||||||
|
|
||||||
export function toDepartmentForm(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
parentId: asId(data.parentId),
|
|
||||||
deptName: data.deptName,
|
|
||||||
leaderName: data.managerName,
|
|
||||||
leaderAccount: data.managerAccount,
|
|
||||||
deptLevel: data.deptLevelName ?? data.deptLevelCode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromDepartmentForm(values = {}) {
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "parentId", "tenantId"]),
|
|
||||||
deptName: values.deptName,
|
|
||||||
managerName: values.leaderName,
|
|
||||||
managerAccount: values.leaderAccount,
|
|
||||||
deptLevelName: values.deptLevel,
|
|
||||||
deptLevelCode: values.deptLevel,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildDepartmentTree(departments = []) {
|
|
||||||
const map = new Map();
|
|
||||||
departments.forEach((item) => {
|
|
||||||
map.set(asId(item.id), { ...toDepartmentForm(item), children: [] });
|
|
||||||
});
|
|
||||||
const roots = [];
|
|
||||||
departments.forEach((item) => {
|
|
||||||
const node = map.get(asId(item.id));
|
|
||||||
const parentId = asId(item.parentId);
|
|
||||||
if (parentId != null && parentId !== "0" && map.has(parentId)) {
|
|
||||||
map.get(parentId).children.push(node);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
roots.push(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return roots;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toPositionForm(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
deptId: asId(data.deptId),
|
|
||||||
deptName: data.deptName,
|
|
||||||
positionName: data.positionName,
|
|
||||||
dutyDesc: data.dutyDesc,
|
|
||||||
remark: data.remark ?? data.remarks,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromPositionForm(values = {}) {
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
deptId: asId(values.deptId),
|
|
||||||
positionName: values.positionName,
|
|
||||||
dutyDesc: values.dutyDesc,
|
|
||||||
remark: values.remark,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 人员 ───
|
|
||||||
|
|
||||||
export function toStaffForm(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
staffName: data.userName,
|
|
||||||
account: data.account,
|
|
||||||
gender: data.genderCode,
|
|
||||||
birthDate: data.birthDate,
|
|
||||||
deptId: asId(data.deptId),
|
|
||||||
positionId: asId(data.postId),
|
|
||||||
idCardNo: data.idCardNo,
|
|
||||||
homeAddress: data.currentAddress,
|
|
||||||
officeAddress: data.officeAddress,
|
|
||||||
educationType: data.educationTypeName,
|
|
||||||
educationLevel: data.educationLevelName,
|
|
||||||
education: data.educationName ?? data.educationCode,
|
|
||||||
graduateSchool: data.graduateSchool,
|
|
||||||
major: data.major,
|
|
||||||
employmentStatus: data.employmentStatusCode,
|
|
||||||
personType: data.personTypeName ?? "基础人员",
|
|
||||||
qualScope: data.qualScope,
|
|
||||||
professionalLevel: data.professionalLevelName,
|
|
||||||
evaluatorCertNo: data.evaluatorCertNo,
|
|
||||||
titleName: data.titleName,
|
|
||||||
registerEngineerFlag: data.registerEngineerFlag ?? 2,
|
|
||||||
publications: data.publications,
|
|
||||||
abilityDeclaration: data.abilityDeclaration,
|
|
||||||
workExperience: data.workExperience,
|
|
||||||
proofMaterials: parseAttachmentUrls(data.proofMaterialUrl, "专业能力证明.pdf"),
|
|
||||||
deptName: data.deptName,
|
|
||||||
positionName: data.postName ?? data.positionName,
|
|
||||||
certNames: data.certNames,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromStaffForm(values = {}) {
|
|
||||||
const genderCode = values.gender;
|
|
||||||
const personType = values.personType ?? "基础人员";
|
|
||||||
const educationType = values.educationType;
|
|
||||||
const educationLevel = values.educationLevel;
|
|
||||||
const educationName = educationType && educationLevel
|
|
||||||
? `${educationType}-${educationLevel}`
|
|
||||||
: values.education;
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
userName: values.staffName,
|
|
||||||
account: values.account,
|
|
||||||
genderCode,
|
|
||||||
genderName: GENDER_NAME[genderCode] ?? values.genderName,
|
|
||||||
birthDate: toApiDate(values.birthDate),
|
|
||||||
deptId: asId(values.deptId),
|
|
||||||
postId: asId(values.positionId ?? values.postId),
|
|
||||||
idCardNo: values.idCardNo,
|
|
||||||
currentAddress: values.homeAddress,
|
|
||||||
officeAddress: values.officeAddress,
|
|
||||||
educationName,
|
|
||||||
educationCode: educationName,
|
|
||||||
educationTypeCode: educationType,
|
|
||||||
educationTypeName: educationType,
|
|
||||||
educationLevelCode: educationLevel,
|
|
||||||
educationLevelName: educationLevel,
|
|
||||||
graduateSchool: values.graduateSchool,
|
|
||||||
major: values.major,
|
|
||||||
employmentStatusCode: values.employmentStatus ?? 1,
|
|
||||||
employmentStatusName: values.employmentStatus === 2 ? "离职" : "在职",
|
|
||||||
personTypeCode: PERSON_TYPE_CODE[personType] ?? personType,
|
|
||||||
personTypeName: personType,
|
|
||||||
qualScope: values.qualScope,
|
|
||||||
professionalLevelCode: values.professionalLevel,
|
|
||||||
professionalLevelName: values.professionalLevel,
|
|
||||||
evaluatorCertNo: values.evaluatorCertNo,
|
|
||||||
titleName: values.titleName,
|
|
||||||
registerEngineerFlag: values.registerEngineerFlag ?? 2,
|
|
||||||
publications: values.publications,
|
|
||||||
abilityDeclaration: values.abilityDeclaration,
|
|
||||||
workExperience: values.workExperience,
|
|
||||||
proofMaterialUrl: resolveUploadFileIds(values.proofMaterials),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 人员证书 ───
|
|
||||||
|
|
||||||
export function toStaffCertForm(data = {}) {
|
|
||||||
const certImgs = data.certAttachmentUrl
|
|
||||||
? parseAttachmentUrls(data.certAttachmentUrl, data.certName || "证书附件.jpg")
|
|
||||||
: data.certImgFiles || [];
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
staffId: asId(data.personnelId),
|
|
||||||
certName: data.certName,
|
|
||||||
certCategory: data.certCategoryName ?? data.certCategoryCode,
|
|
||||||
certWorkCategory: data.operationCategoryName ?? data.operationCategoryCode,
|
|
||||||
certNo: data.certNo,
|
|
||||||
issueOrg: data.issueOrg,
|
|
||||||
validStartDate: data.validStartDate,
|
|
||||||
validEndDate: data.validEndDate,
|
|
||||||
reviewDate: data.reviewDate,
|
|
||||||
certImgFiles: certImgs,
|
|
||||||
certImgs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromStaffCertForm(values = {}) {
|
|
||||||
const certAttachmentUrl = values.certAttachmentUrl
|
|
||||||
|| values.certImgs?.[0]?.url
|
|
||||||
|| values.certImgFiles?.[0]?.url;
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
personnelId: asId(values.staffId),
|
|
||||||
certName: values.certName,
|
|
||||||
certCategoryName: values.certCategory,
|
|
||||||
certCategoryCode: values.certCategory,
|
|
||||||
operationCategoryName: values.certWorkCategory,
|
|
||||||
operationCategoryCode: values.certWorkCategory,
|
|
||||||
certNo: values.certNo,
|
|
||||||
issueOrg: values.issueOrg,
|
|
||||||
validStartDate: values.validStartDate,
|
|
||||||
validEndDate: values.validEndDate,
|
|
||||||
reviewDate: values.reviewDate,
|
|
||||||
certAttachmentUrl,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 机构资质证书 ───
|
|
||||||
|
|
||||||
/** 资质证书 enableFlag(1启用/2禁用) ↔ 前端 enableStatus(1启用/0禁用) */
|
|
||||||
export function mapQualificationEnableStatus(flag) {
|
|
||||||
return Number(flag) === 1 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapQualificationEnableFlag(status) {
|
|
||||||
return Number(status) === 1 ? 1 : 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 列表/表单统一判断:优先 enableFlag,兼容 enableStatus */
|
|
||||||
export function isQualificationEnabled(record = {}) {
|
|
||||||
const flag = record.enableFlag ?? record.enableStatus;
|
|
||||||
return mapQualificationEnableStatus(flag) === 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toQualificationForm(data = {}) {
|
|
||||||
const certImgs = data.certImageUrl
|
|
||||||
? parseAttachmentUrls(data.certImageUrl, data.certName || "证书图片.jpg")
|
|
||||||
: data.certImgFiles || [];
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
certType: data.licenseTypeName ?? data.licenseTypeCode,
|
|
||||||
certName: data.certName,
|
|
||||||
certNo: data.certNo,
|
|
||||||
issueOrg: data.issueOrg,
|
|
||||||
issueDate: data.issueDate,
|
|
||||||
validStartDate: data.validStartDate,
|
|
||||||
validEndDate: data.validEndDate,
|
|
||||||
remark: data.remark ?? data.remarks,
|
|
||||||
enableFlag: data.enableFlag,
|
|
||||||
enableStatus: mapQualificationEnableStatus(data.enableFlag),
|
|
||||||
issueDate: formatDate(data.issueDate),
|
|
||||||
validStartDate: formatDate(data.validStartDate),
|
|
||||||
validEndDate: formatDate(data.validEndDate),
|
|
||||||
certImgFiles: certImgs,
|
|
||||||
certImgs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromQualificationForm(values = {}) {
|
|
||||||
const certImageUrl = values.certImageUrl
|
|
||||||
|| values.certImgs?.[0]?.url
|
|
||||||
|| values.certImgFiles?.[0]?.url;
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
licenseTypeName: values.certType,
|
|
||||||
licenseTypeCode: values.certType,
|
|
||||||
certName: values.certName,
|
|
||||||
certNo: values.certNo,
|
|
||||||
issueOrg: values.issueOrg,
|
|
||||||
issueDate: toApiDate(values.issueDate),
|
|
||||||
validStartDate: toApiDate(values.validStartDate ?? values.validDate?.[0]),
|
|
||||||
validEndDate: toApiDate(values.validEndDate ?? values.validDate?.[1]),
|
|
||||||
certImageUrl,
|
|
||||||
remark: values.remark,
|
|
||||||
enableFlag: mapQualificationEnableFlag(values.enableStatus),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function isQualificationExpireWarning(dateStr) {
|
|
||||||
if (!dateStr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const end = new Date(String(dateStr).replace(/-/g, "/"));
|
|
||||||
if (Number.isNaN(end.getTime())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const diff = end.getTime() - Date.now();
|
|
||||||
return diff > 0 && diff < 90 * 24 * 3600 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** classGet 分组 Map → 已备案机构详情「申请清单材料」结构 */
|
|
||||||
export function fromQualificationClassGetResponse(res) {
|
|
||||||
const map = res?.data;
|
|
||||||
if (!map || typeof map !== "object") {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return Object.entries(map).map(([code, list], index) => {
|
|
||||||
const items = (Array.isArray(list) ? list : []).map(toQualificationForm);
|
|
||||||
const scopeName = items[0]?.certType || code || `资质${index + 1}`;
|
|
||||||
const expireDate = items.reduce((latest, item) => {
|
|
||||||
const d = item.validEndDate;
|
|
||||||
if (!d) {
|
|
||||||
return latest;
|
|
||||||
}
|
|
||||||
return !latest || d > latest ? d : latest;
|
|
||||||
}, "");
|
|
||||||
return {
|
|
||||||
id: code || String(index),
|
|
||||||
scopeName,
|
|
||||||
expireDate: expireDate || "-",
|
|
||||||
expireWarning: isQualificationExpireWarning(expireDate),
|
|
||||||
materials: items.map((item, idx) => {
|
|
||||||
const previewUrl = item.certImgFiles?.[0]?.url || item.certImgs?.[0]?.url;
|
|
||||||
return {
|
|
||||||
id: item.id || `${code}-${idx}`,
|
|
||||||
name: item.certName || item.certType || "-",
|
|
||||||
required: true,
|
|
||||||
status: previewUrl ? "uploaded" : "pending",
|
|
||||||
previewUrl,
|
|
||||||
raw: item,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 已备案机构详情人员列表行 */
|
|
||||||
export function toRegisteredOrgPersonnelRow(data = {}) {
|
|
||||||
const form = toStaffForm(data);
|
|
||||||
return {
|
|
||||||
id: form.id,
|
|
||||||
name: form.staffName,
|
|
||||||
gender: GENDER_NAME[form.gender] || "-",
|
|
||||||
position: form.positionName,
|
|
||||||
qualScope: form.qualScope,
|
|
||||||
education: form.education || form.educationLevel,
|
|
||||||
registerEngineer: form.registerEngineerFlag === 1 ? 1 : 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 装备 ───
|
|
||||||
|
|
||||||
/** 装备 enableFlag(1启用/2禁用) ↔ 前端 enableStatus(1启用/0禁用) */
|
|
||||||
export function mapEquipEnableStatus(flag) {
|
|
||||||
return Number(flag) === 1 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapEquipEnableFlag(status) {
|
|
||||||
return Number(status) === 1 ? 1 : 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isEquipEnabled(record = {}) {
|
|
||||||
const flag = record.enableFlag ?? record.enableStatus;
|
|
||||||
return mapEquipEnableStatus(flag) === 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toEquipForm(data = {}) {
|
|
||||||
const instrumentType = data.instrumentTypeName ?? data.instrumentTypeCode;
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
instrumentType,
|
|
||||||
instrumentCategory: instrumentType,
|
|
||||||
deviceType: data.deviceTypeName ?? data.deviceTypeCode,
|
|
||||||
deviceName: data.deviceName,
|
|
||||||
model: data.deviceModel,
|
|
||||||
flowDesc: data.flowDesc,
|
|
||||||
manufacturer: data.manufacturer,
|
|
||||||
minFlow: data.minFlow,
|
|
||||||
maxFlow: data.maxFlow,
|
|
||||||
calibrationUnit: data.calibrationUnit,
|
|
||||||
calibrationInitialValue: data.calibrationInitValue,
|
|
||||||
onSiteCalibrationType: data.fieldCalibrationTypeName ?? data.fieldCalibrationTypeCode,
|
|
||||||
isDualChannel: data.dualChannelFlag,
|
|
||||||
enableFlag: data.enableFlag,
|
|
||||||
enableStatus: mapEquipEnableStatus(data.enableFlag),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromEquipForm(values = {}) {
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
deviceName: values.deviceName,
|
|
||||||
deviceModel: values.model,
|
|
||||||
instrumentTypeName: values.instrumentCategory,
|
|
||||||
instrumentTypeCode: values.instrumentCategory,
|
|
||||||
deviceTypeName: values.deviceType,
|
|
||||||
deviceTypeCode: values.deviceType,
|
|
||||||
manufacturer: values.manufacturer,
|
|
||||||
flowDesc: values.flowDesc,
|
|
||||||
minFlow: values.minFlow,
|
|
||||||
maxFlow: values.maxFlow,
|
|
||||||
calibrationUnit: values.calibrationUnit,
|
|
||||||
calibrationInitValue: values.calibrationInitialValue,
|
|
||||||
fieldCalibrationTypeName: values.onSiteCalibrationType,
|
|
||||||
fieldCalibrationTypeCode: values.onSiteCalibrationType,
|
|
||||||
dualChannelFlag: values.isDualChannel,
|
|
||||||
enableFlag: mapEquipEnableFlag(values.enableStatus),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 人员变更 / 离职 ───
|
|
||||||
|
|
||||||
export function toChangeLogForm(data = {}) {
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
staffId: asId(data.personnelId),
|
|
||||||
changeItem: data.changeItem,
|
|
||||||
changeTime: formatDateTime(data.changeTime),
|
|
||||||
createBy: data.operatorName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toResignApplyForm(data = {}) {
|
|
||||||
const auditStatus = data.auditStatusCode ?? data.auditStatus ?? 0;
|
|
||||||
return {
|
|
||||||
id: asId(data.id),
|
|
||||||
personnelId: asId(data.personnelId),
|
|
||||||
applicantName: data.applicantName,
|
|
||||||
applyTime: formatDateTime(data.applyTime),
|
|
||||||
expectedLeaveDate: formatDate(data.expectedResignDate),
|
|
||||||
leaveReason: data.resignReason,
|
|
||||||
remark: data.remark ?? data.remarks,
|
|
||||||
rejectReason: data.rejectReason,
|
|
||||||
auditStatus,
|
|
||||||
auditStatusName: data.auditStatusName ?? RESIGN_AUDIT_STATUS_NAME[auditStatus] ?? "未审核",
|
|
||||||
attachmentId: data.reportFileUrl,
|
|
||||||
account: data.account,
|
|
||||||
deptName: data.deptName,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromResignApplyForm(values = {}) {
|
|
||||||
return {
|
|
||||||
...pick(values, ["id", "tenantId"]),
|
|
||||||
personnelId: asId(values.personnelId),
|
|
||||||
applicantName: values.applicantName,
|
|
||||||
applyTime: toApiDateTime(values.applyTime),
|
|
||||||
expectedResignDate: toApiDate(values.expectedLeaveDate),
|
|
||||||
resignReason: values.leaveReason,
|
|
||||||
remark: values.remark,
|
|
||||||
reportFileUrl: values.attachmentId ?? values.reportFileUrl,
|
|
||||||
auditStatusCode: values.auditStatus ?? 0,
|
|
||||||
auditStatusName: values.auditStatus === 1 ? "已审核" : values.auditStatus === 2 ? "已退回" : "未审核",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fromResignAuditForm(values = {}) {
|
|
||||||
const auditStatus = values.auditStatus;
|
|
||||||
return {
|
|
||||||
id: asId(values.id),
|
|
||||||
personnelId: asId(values.personnelId),
|
|
||||||
auditStatusCode: auditStatus,
|
|
||||||
auditStatusName: auditStatus === 1 ? "已审核" : auditStatus === 2 ? "已退回" : "未审核",
|
|
||||||
rejectReason: values.rejectReason,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toStaffChangeSummary(personnel = {}) {
|
|
||||||
const employmentCode = Number(personnel.employmentStatusCode ?? personnel.employmentStatus ?? 1);
|
|
||||||
const hasResignApply = personnel.resignApplyId != null && personnel.resignApplyId !== "";
|
|
||||||
const resignStatusRaw = personnel.resignAuditStatus;
|
|
||||||
let resignStatus = null;
|
|
||||||
if (hasResignApply) {
|
|
||||||
resignStatus = resignStatusRaw === null || resignStatusRaw === undefined
|
|
||||||
? 0
|
|
||||||
: Number(resignStatusRaw);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: asId(personnel.id),
|
|
||||||
staffId: asId(personnel.id),
|
|
||||||
account: personnel.account,
|
|
||||||
staffName: personnel.userName ?? personnel.staffName,
|
|
||||||
deptName: personnel.deptName || "",
|
|
||||||
employmentStatus: employmentCode,
|
|
||||||
employmentStatusCode: employmentCode,
|
|
||||||
employmentStatusName: personnel.employmentStatusName
|
|
||||||
|| (employmentCode === 2 ? "离职" : "在职"),
|
|
||||||
changeCount: Number(personnel.changeCount ?? 0),
|
|
||||||
resignApplyId: asId(personnel.resignApplyId),
|
|
||||||
resignAuditStatus: resignStatus,
|
|
||||||
resignAuditStatusName: personnel.resignAuditStatusName
|
|
||||||
?? (resignStatus !== null ? RESIGN_AUDIT_STATUS_NAME[resignStatus] : undefined),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,102 +2,22 @@
|
||||||
* 浼佷笟淇℃伅妯″潡鍒濆鍖栦笌涓嬫媺鏁版嵁鎷夊彇锛堢粫杩?DVA锛岄伩鍏?loading 鐘舵€佸鑷撮〉闈㈤噸娓叉煋姝诲惊鐜級
|
* 浼佷笟淇℃伅妯″潡鍒濆鍖栦笌涓嬫媺鏁版嵁鎷夊彇锛堢粫杩?DVA锛岄伩鍏?loading 鐘舵€佸鑷撮〉闈㈤噸娓叉煋姝诲惊鐜級
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
|
||||||
fromPageResponse,
|
|
||||||
fromSingleResponse,
|
|
||||||
toDepartmentForm,
|
|
||||||
toOrgInfoForm,
|
|
||||||
toPageQuery,
|
|
||||||
toPositionForm,
|
|
||||||
} from "./adapter";
|
|
||||||
import { apiGet } from "./http";
|
|
||||||
import { clearOrgInfoId, getOrgInfoId, setOrgInfoId } from "./orgContext";
|
|
||||||
|
|
||||||
/** 鏈烘瀯淇℃伅绠$悊椤佃矾寰勶紙鏃犳満鏋勬暟鎹椂鍞竴鍙闂〉锛?*/
|
/** 鏈烘瀯淇℃伅绠$悊椤佃矾寰勶紙鏃犳満鏋勬暟鎹椂鍞竴鍙闂〉锛?*/
|
||||||
export const ORG_INFO_PAGE_PATH = "/certificate/container/EnterpriseInfo/OrgInfo";
|
export const ORG_INFO_PAGE_PATH = "/certificate/container/EnterpriseInfo/OrgInfo";
|
||||||
export const MATERIAL_REPORT_PAGE_PATH = "/certificate/container/EnterpriseInfo/MaterialReport";
|
export const MATERIAL_REPORT_PAGE_PATH = "/certificate/container/EnterpriseInfo/MaterialReport";
|
||||||
|
|
||||||
let ensureOrgPromise = null;
|
|
||||||
/** 鏈€杩戜竴娆?getInfo 杞崲缁撴灉锛屼緵鏈烘瀯淇℃伅椤靛鐢紝閬垮厤閲嶅璇锋眰 */
|
|
||||||
let lastOrgInfoDetail = null;
|
|
||||||
|
|
||||||
export function isOrgInfoPage(path = window.location.pathname) {
|
|
||||||
return path === ORG_INFO_PAGE_PATH || path.startsWith(`${ORG_INFO_PAGE_PATH}/`) || path === MATERIAL_REPORT_PAGE_PATH || path.startsWith(`${MATERIAL_REPORT_PAGE_PATH}/`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getOrgInfoDetail() {
|
|
||||||
return lastOrgInfoDetail;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setOrgInfoDetailCache(detail) {
|
|
||||||
lastOrgInfoDetail = detail;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchOrgInfoContext() {
|
|
||||||
const cachedBefore = getOrgInfoId();
|
|
||||||
return apiGet("/safetyEval/org-info/getInfo", {}, {}, { includeOrgContext: false })
|
|
||||||
.then((res) => {
|
|
||||||
lastOrgInfoDetail = fromSingleResponse(res, toOrgInfoForm);
|
|
||||||
const id = lastOrgInfoDetail?.data?.id ?? res?.data?.id;
|
|
||||||
if (id) {
|
|
||||||
setOrgInfoId(id);
|
|
||||||
return { hasOrg: true, orgInfoId: String(id), detail: lastOrgInfoDetail };
|
|
||||||
}
|
|
||||||
// 本地联调:getInfo 无 SSO 关联时,保留 session 中已有 orgInfoId
|
|
||||||
if (cachedBefore) {
|
|
||||||
return { hasOrg: true, orgInfoId: cachedBefore, detail: lastOrgInfoDetail };
|
|
||||||
}
|
|
||||||
clearOrgInfoId();
|
|
||||||
return { hasOrg: false, orgInfoId: null, detail: lastOrgInfoDetail };
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.warn("[ensureOrgContext] getInfo failed:", err);
|
|
||||||
clearOrgInfoId();
|
|
||||||
lastOrgInfoDetail = { success: false, data: null };
|
|
||||||
return { hasOrg: false, orgInfoId: null, detail: lastOrgInfoDetail, networkError: true };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 纭繚宸茬紦瀛樻満鏋?id锛堝瓙琛ㄥ垎椤?璇锋眰澶?orgInfoId 渚濊禆姝ゅ€硷級
|
|
||||||
* @param {{ force?: boolean }} options force=true 鏃跺拷鐣ョ紦瀛樺苟閲嶆柊 getInfo锛堣繘鍏ヤ紒涓氫俊鎭ā鍧楁椂浣跨敤锛?
|
|
||||||
* @returns {Promise<{ hasOrg: boolean, orgInfoId: string|null, detail?: object, networkError?: boolean }>}
|
|
||||||
*/
|
|
||||||
export function ensureOrgContext(options = {}) {
|
|
||||||
const { force = false } = options;
|
|
||||||
|
|
||||||
if (!force) {
|
|
||||||
const cached = getOrgInfoId();
|
|
||||||
if (cached) {
|
|
||||||
return Promise.resolve({ hasOrg: true, orgInfoId: cached, detail: lastOrgInfoDetail });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ensureOrgPromise) {
|
|
||||||
return ensureOrgPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureOrgPromise = fetchOrgInfoContext().finally(() => {
|
|
||||||
ensureOrgPromise = null;
|
|
||||||
});
|
|
||||||
return ensureOrgPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchOrgDepartmentPage(params = {}) {
|
|
||||||
await ensureOrgContext();
|
|
||||||
const query = toPageQuery(params, { likeDeptName: "deptName" });
|
|
||||||
const res = await apiGet("/safetyEval/org-department/page", query);
|
|
||||||
return fromPageResponse(res, toDepartmentForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchOrgPositionPage(params = {}) {
|
|
||||||
await ensureOrgContext();
|
|
||||||
const query = toPageQuery(params, {
|
|
||||||
eqDeptId: "deptId",
|
|
||||||
likePositionName: "positionName",
|
|
||||||
});
|
|
||||||
const res = await apiGet("/safetyEval/org-position/page", query);
|
|
||||||
return fromPageResponse(res, toPositionForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue