diff --git a/jjb.config.js b/jjb.config.js index faa0bb3..0a97931 100644 --- a/jjb.config.js +++ b/jjb.config.js @@ -13,9 +13,9 @@ module.exports = { // API_HOST: "https://gbs-gateway.qhdsafety.com", // API_HOST: "http://192.168.0.134", - // API_HOST: "http://192.168.0.150", //太浅 + API_HOST: "http://192.168.0.150", //太浅 // API_HOST: "http://192.168.0.152", - API_HOST: "http://192.168.0.103", //huwei + //API_HOST: "http://192.168.0.103", //huwei }, production: { // 应用后端分支名称,部署上线需要 diff --git a/src/components/StaffViewModal/index.js b/src/components/StaffViewModal/index.js index 3b20254..99adb1c 100644 --- a/src/components/StaffViewModal/index.js +++ b/src/components/StaffViewModal/index.js @@ -1,72 +1,59 @@ -import { Button, Descriptions, Image, Modal, Table, Upload } from "antd"; +import { Button, Descriptions, Image, Modal, Table } from "antd"; import { useEffect, useRef, useState } from "react"; -import FilePreviewModal, { - FilePreviewContent, -} from "~/components/FilePreviewModal"; -import { resolvePreviewSrc } from "~/components/CertPreviewImg"; -import { - fetchStaffCertDetail, - fetchStaffCertListByPersonnelId, -} from "~/api/staffCertificate"; import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper"; import { - QUALIFICATION_INDUSTRY_OPTIONS_MAP, + REGISTER_ENGINEER_CATEGORY_MAP, + PERSONNEL_POST_TYPE_MAP, + ABILITY_SOURCE_MAP, TITLE_LEVEL_MAP, } from "~/enumerate/enterpriseOptions"; +import { + CERT_LEVEL_LABEL_BY_TYPE, + CAPABILITY_MAP, +} from "~/enumerate/constant"; const GENDER_MAP = { 1: "男", 2: "女" }; const REGISTER_ENGINEER_MAP = { 1: "是", 2: "否" }; +const EVALUATOR_MAP = { 1: "是", 2: "否" }; + +const parseFileList = (raw) => { + if (!raw) return []; + if (Array.isArray(raw)) return raw; + try { + const parsed = JSON.parse(raw); + return Array.isArray(parsed) ? parsed : []; + } catch { + return []; + } +}; export default function StaffViewModal({ open, currentId, requestDetails = fetchOrgPersonnelDetail, - requestCertList = fetchStaffCertListByPersonnelId, - requestCertDetails = fetchStaffCertDetail, onCancel, }) { const [info, setInfo] = useState({}); - const [certificates, setCertificates] = useState([]); const [detailLoading, setDetailLoading] = useState(false); - const [attachmentPreview, setAttachmentPreview] = useState(null); - const [certPreview, setCertPreview] = useState(null); - const [certPreviewLoading, setCertPreviewLoading] = useState(false); - const [certPreviewInfo, setCertPreviewInfo] = useState(null); const requestDetailsRef = useRef(requestDetails); - const requestCertListRef = useRef(requestCertList); - const requestCertDetailsRef = useRef(requestCertDetails); requestDetailsRef.current = requestDetails; - requestCertListRef.current = requestCertList; - requestCertDetailsRef.current = requestCertDetails; useEffect(() => { if (!open || !currentId) { setInfo({}); - setCertificates([]); return; } let cancelled = false; setDetailLoading(true); - const loadCertList = requestCertListRef.current; - Promise.all([ - Promise.resolve(requestDetailsRef.current({ id: currentId })).catch( - (err) => { - console.warn("[StaffViewModal] load detail failed:", err); - return { data: {} }; - }, - ), - typeof loadCertList === "function" - ? Promise.resolve(loadCertList(currentId)).catch((err) => { - console.warn("[StaffViewModal] load certificates failed:", err); - return []; - }) - : Promise.resolve([]), - ]) - .then(([detailRes, certList]) => { + Promise.resolve(requestDetailsRef.current({ id: currentId })) + .catch((err) => { + console.warn("[StaffViewModal] load detail failed:", err); + return { data: {} }; + }) + .then((detailRes) => { if (!cancelled) { setInfo(detailRes?.data || {}); - setCertificates(Array.isArray(certList) ? certList : []); } }) .finally(() => { @@ -79,51 +66,35 @@ export default function StaffViewModal({ }; }, [open, currentId]); - const openCertPreview = async (record) => { - setCertPreview(record); - setCertPreviewInfo(null); - if (typeof requestCertDetailsRef.current !== "function") { - setCertPreviewInfo(record); - return; - } - setCertPreviewLoading(true); - try { - const res = await requestCertDetailsRef.current({ id: record.id }); - setCertPreviewInfo(res?.data || record); - } catch (err) { - console.warn("[StaffViewModal] load cert detail failed:", err); - setCertPreviewInfo(record); - } finally { - setCertPreviewLoading(false); - } - }; + const proofMaterialFiles = parseFileList(info.proofMaterialUrl); - const proofMaterialUrl = info.proofMaterialUrl - ? JSON.parse(info.proofMaterialUrl) + const titleInfo = Array.isArray(info.titleCodeArr) + ? info.titleCodeArr.map((item) => ({ + titleName: TITLE_LEVEL_MAP[item.titleCode] || item.titleCode || "-", + proveUrlList: parseFileList(item.proveUrl), + })) : []; - const titleCodeArr = Array.isArray(info.titleCodeArr) - ? info.titleCodeArr.map((item) => { - let proveUrlList = []; - if (item.proveUrl) { - try { - proveUrlList = - typeof item.proveUrl === "string" - ? JSON.parse(item.proveUrl) - : item.proveUrl; - } catch { - proveUrlList = []; - } - } - return { - industryName: - QUALIFICATION_INDUSTRY_OPTIONS_MAP[item.industryCode] || - item.industryCode || - "-", - titleName: TITLE_LEVEL_MAP[item.titleCode] || item.titleCode || "-", - proveUrlList, - }; - }) + const regCert = info.registeredSafetyEngineerCert; + const regCertLevelMap = CERT_LEVEL_LABEL_BY_TYPE.registered_safety_engineer; + const regCertFiles = parseFileList(regCert?.certAttachmentUrl); + + const evaluatorCert = info.evaluatorCert; + const evaluatorFlag = info.evaluatorFlag || (evaluatorCert ? 1 : 2); + const evalCertLevelMap = CERT_LEVEL_LABEL_BY_TYPE.evaluator; + const evalCertFiles = parseFileList(evaluatorCert?.certAttachmentUrl); + + const capabilityList = Array.isArray(info.capabilityAssessment) + ? info.capabilityAssessment.map((item) => ({ + capabilityName: + CAPABILITY_MAP[item.professionalCapabilityCode] || + item.professionalCapabilityCode || + "-", + sourceName: + ABILITY_SOURCE_MAP[item.professionalCapabilitySourceCode] || + item.professionalCapabilitySourceCode || + "-", + })) : []; const renderFileList = (files) => { @@ -150,258 +121,136 @@ export default function StaffViewModal({ }); }; - const certPreviewFiles = certPreviewInfo?.certImgs?.length - ? certPreviewInfo.certImgs - : certPreviewInfo?.certImgFiles || []; - const certPreviewUrl = resolvePreviewSrc(certPreviewFiles[0]); - const certPreviewName = - certPreviewFiles[0]?.fileName || - certPreviewFiles[0]?.name || - certPreviewInfo?.certName; - return ( - <> - - - {info.userName} - - {GENDER_MAP[info.genderCode]} - - - {info.birthDate} - - - {info.joinWorkDate} - - {info.account} - {info.deptName} - {info.postName} - - {info.idCardNo} - - - {info.currentAddress} - - - {info.officeAddress} - - - {info.educationTypeName || "-"} - - - {info.graduateSchool} - - - {info.educationLevelName || "-"} - - - {info.basicDisciplineMajorName || "-"} - + + + {info.userName} + + {GENDER_MAP[info.genderCode]} + + + {info.birthDate} + + + {info.joinWorkDate} + + {info.account} + {info.deptName} + {info.postName} + + {info.idCardNo} + + + {info.currentAddress} + + + {info.officeAddress} + + + {info.educationTypeName || "-"} + + + {info.graduateSchool} + + + {info.educationLevelName || "-"} + + + {info.basicDisciplineMajorName || "-"} + + + {PERSONNEL_POST_TYPE_MAP[info.personnelPositionType] || "-"} + + + {info.workExperience || "-"} + + + {renderFileList(proofMaterialFiles)} + + - - {REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"} - - - {info.technicalDirectorFlag === true - ? "是" - : info.technicalDirectorFlag === false - ? "否" - : "-"} - - - {info.processControlLeaderFlag === true - ? "是" - : info.processControlLeaderFlag === false - ? "否" - : "-"} - - +
+ 注安信息 +
+ + + {REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"} + + + {REGISTER_ENGINEER_CATEGORY_MAP[regCert?.certCategoryCode] || "-"} + + + {regCertLevelMap[regCert?.certLevel] || "-"} + + + {regCert?.certNo || "-"} + + + {renderFileList(regCertFiles)} + + - - {info.publications || "-"} - - - {info.abilityDeclaration || "-"} - - - {info.workExperience || "-"} - - - {proofMaterialUrl.length - ? proofMaterialUrl.map((item) => { - const isImage = - /\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i.test(item.url); - return ( -
- {isImage ? ( - - ) : ( - - )} -
- ); - }) - : "-"} -
-
-
- 职称信息 -
- idx} - dataSource={titleCodeArr} - columns={[ - { title: "行业", dataIndex: "industryName", width: 150 }, - { title: "职称", dataIndex: "titleName", width: 100 }, - { - title: "证明材料", - dataIndex: "proveUrlList", - render: renderFileList, - }, - ]} - /> +
+ 评价师信息 +
+ + + {EVALUATOR_MAP[evaluatorFlag] ?? "-"} + + + {evalCertLevelMap[evaluatorCert?.certLevel] || "-"} + + + {evaluatorCert?.certNo || "-"} + + + {renderFileList(evalCertFiles)} + + -
- 证照信息 -
-
( - - ), - }, - ]} - /> - - - setAttachmentPreview(null)} +
+ 职称信息 +
+
idx} + dataSource={titleInfo} + columns={[ + { title: "职称", dataIndex: "titleName", width: 120 }, + { + title: "证明材料", + dataIndex: "proveUrlList", + render: renderFileList, + }, + ]} /> - { - setCertPreview(null); - setCertPreviewInfo(null); - }} - onOk={() => { - if (certPreviewUrl) { - window.open(certPreviewUrl, "_blank"); - } - setCertPreview(null); - setCertPreviewInfo(null); - }} - > - {certPreviewInfo && ( -
- - - {certPreviewInfo.certName} - - - {certPreviewInfo.certNo} - - - {certPreviewInfo.certTypeName || "-"} - - - {certPreviewInfo.issueOrg || "-"} - - - {certPreviewInfo.validStartDate || "-"} - - - {certPreviewInfo.validEndDate || "-"} - - - {certPreviewInfo.certAttachmentUrl && - certPreviewInfo.certAttachmentUrl.split(",").map((item) => { - const isImage = - /\.(png|jpe?g|gif|bmp|webp|svg)(\?|#|$)/i.test(item); - return ( -
- {isImage ? ( - - ) : ( - window.open(item)}>{item} - )} -
- ); - })} -
-
-
- )} -
- +
+ 专业能力信息 +
+
idx} + dataSource={capabilityList} + locale={{ emptyText: "暂无专业能力信息" }} + columns={[ + { title: "专业能力", dataIndex: "capabilityName" }, + { title: "来源", dataIndex: "sourceName", width: 280 }, + ]} + /> + ); } diff --git a/src/enumerate/enterpriseOptions.js b/src/enumerate/enterpriseOptions.js index b4d239e..f0a2d37 100644 --- a/src/enumerate/enterpriseOptions.js +++ b/src/enumerate/enterpriseOptions.js @@ -162,6 +162,50 @@ export const REGISTER_ENGINEER_OPTIONS = [ { label: "否", value: 2 }, ]; +/** 注安专业类别 */ +export const REGISTER_ENGINEER_CATEGORY_OPTIONS = [ + { label: "煤矿安全", value: "COAL_MINE" }, + { label: "金属非金属矿山安全", value: "METAL_NONMETAL_MINE" }, + { label: "化工安全", value: "CHEMICAL" }, + { label: "金属冶炼安全", value: "METAL_SMELTING" }, + { label: "建筑施工安全", value: "CONSTRUCTION" }, + { label: "道路运输安全", value: "ROAD_TRANSPORT" }, + { label: "其他安全", value: "OTHER" }, +]; +export const REGISTER_ENGINEER_CATEGORY_MAP = + REGISTER_ENGINEER_CATEGORY_OPTIONS.reduce( + (acc, cur) => ({ ...acc, [cur.value]: cur.label }), + {}, + ); + +/** 人员岗位类型 */ +export const PERSONNEL_POST_TYPE_OPTIONS = [ + { label: "技术负责人", value: "TECHNICAL_LEADER" }, + { label: "过程控制负责人", value: "PROCESS_CONTROL_LEADER" }, +]; +export const PERSONNEL_POST_TYPE_MAP = PERSONNEL_POST_TYPE_OPTIONS.reduce( + (acc, cur) => ({ ...acc, [cur.value]: cur.label }), + {}, +); + +/** 能力来源 */ +export const ABILITY_SOURCE_OPTIONS = [ + { label: "注册安全工程师", value: "REGISTERED_SAFETY_ENGINEER" }, + { label: "学历", value: "EDUCATION" }, + { label: "职称", value: "PROFESSIONAL_TITLE" }, + { label: "出版学术专著、专利、获奖、发表学术论文等", value: "ACADEMIC_ACHIEVEMENT" }, +]; +export const ABILITY_SOURCE_MAP = ABILITY_SOURCE_OPTIONS.reduce( + (acc, cur) => ({ ...acc, [cur.value]: cur.label }), + {}, +); + +/** 是否评价师 */ +export const EVALUATOR_OPTIONS = [ + { label: "是", value: 1 }, + { label: "否", value: 2 }, +]; + /** 职称等级 */ export const TITLE_LEVEL_OPTIONS = [ { value: "SENIOR", label: "高级" }, diff --git a/src/pages/Container/EnterpriseInfo/PersonnelInfo/List/index.js b/src/pages/Container/EnterpriseInfo/PersonnelInfo/List/index.js index f9fd68c..d6ff505 100644 --- a/src/pages/Container/EnterpriseInfo/PersonnelInfo/List/index.js +++ b/src/pages/Container/EnterpriseInfo/PersonnelInfo/List/index.js @@ -14,6 +14,7 @@ import { Table, TreeSelect, Upload, + Divider, } from "antd"; import { InboxOutlined } from "@ant-design/icons"; import { Get } from "@cqsjjb/jjb-common-lib/http"; @@ -29,14 +30,19 @@ import { NS_STAFF_INFO, NS_ORG_DEPARTMENT } from "~/enumerate/namespace"; import { EDUCATION_LEVEL_OPTIONS, EDUCATION_TYPE_OPTIONS, - QUALIFICATION_INDUSTRY_OPTIONS, REGISTER_ENGINEER_OPTIONS, + REGISTER_ENGINEER_CATEGORY_OPTIONS, + PERSONNEL_POST_TYPE_OPTIONS, + ABILITY_SOURCE_OPTIONS, + EVALUATOR_OPTIONS, TITLE_LEVEL_OPTIONS, } from "~/enumerate/enterpriseOptions"; +import { CERT_LEVEL_OPTIONS_BY_TYPE, CAPABILITY_OPTIONS } from "~/enumerate/constant"; import { getBirthDateFromIdCard } from "~/utils"; import { idCardRule, mobileRule } from "~/utils/validators"; import AttachmentUpload from "~/components/AttachmentUpload"; import StaffViewModal from "~/components/StaffViewModal"; +import "./index.less"; const { router } = tools; const API_HOST = window.process?.env?.app?.API_HOST || ""; @@ -213,12 +219,12 @@ function PersonnelInfoPage(props) { ellipsis: true, render: (text) => text || "-", }, - { + { title: "能力", width: 260, dataIndex: "abilityNames", ellipsis: true, - render: (text) => text || '暂无', + render: (text) => text || "暂无", }, { title: "操作", @@ -245,16 +251,7 @@ function PersonnelInfoPage(props) { > 编辑 - + - + @@ -745,52 +781,190 @@ function StaffFormModal({ maxCount={5} /> - - + - + + + +
+
注安信息
+ +
+ + + + + + + + + + + + + + )} + + - - - + + + {watchedEvaluatorFlag === 1 && ( + <> + + + + + + + + + + )} + + + + + + + +
+
+ 职称信息 +
+ +
+ + ), }, { - title: "职称", - width: 120, + title: "来源", + width: 280, render: (_, field) => (