feat
parent
9908a0093a
commit
942fc4a55f
|
|
@ -13,9 +13,9 @@ module.exports = {
|
||||||
// API_HOST: "https://gbs-gateway.qhdsafety.com",
|
// API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||||
|
|
||||||
// API_HOST: "http://192.168.0.134",
|
// 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.152",
|
||||||
API_HOST: "http://192.168.0.103", //huwei
|
//API_HOST: "http://192.168.0.103", //huwei
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
// 应用后端分支名称,部署上线需要
|
// 应用后端分支名称,部署上线需要
|
||||||
|
|
|
||||||
|
|
@ -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 { 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 { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper";
|
||||||
import {
|
import {
|
||||||
QUALIFICATION_INDUSTRY_OPTIONS_MAP,
|
REGISTER_ENGINEER_CATEGORY_MAP,
|
||||||
|
PERSONNEL_POST_TYPE_MAP,
|
||||||
|
ABILITY_SOURCE_MAP,
|
||||||
TITLE_LEVEL_MAP,
|
TITLE_LEVEL_MAP,
|
||||||
} from "~/enumerate/enterpriseOptions";
|
} from "~/enumerate/enterpriseOptions";
|
||||||
|
import {
|
||||||
|
CERT_LEVEL_LABEL_BY_TYPE,
|
||||||
|
CAPABILITY_MAP,
|
||||||
|
} from "~/enumerate/constant";
|
||||||
|
|
||||||
const GENDER_MAP = { 1: "男", 2: "女" };
|
const GENDER_MAP = { 1: "男", 2: "女" };
|
||||||
const REGISTER_ENGINEER_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({
|
export default function StaffViewModal({
|
||||||
open,
|
open,
|
||||||
currentId,
|
currentId,
|
||||||
requestDetails = fetchOrgPersonnelDetail,
|
requestDetails = fetchOrgPersonnelDetail,
|
||||||
requestCertList = fetchStaffCertListByPersonnelId,
|
|
||||||
requestCertDetails = fetchStaffCertDetail,
|
|
||||||
onCancel,
|
onCancel,
|
||||||
}) {
|
}) {
|
||||||
const [info, setInfo] = useState({});
|
const [info, setInfo] = useState({});
|
||||||
const [certificates, setCertificates] = useState([]);
|
|
||||||
const [detailLoading, setDetailLoading] = useState(false);
|
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 requestDetailsRef = useRef(requestDetails);
|
||||||
const requestCertListRef = useRef(requestCertList);
|
|
||||||
const requestCertDetailsRef = useRef(requestCertDetails);
|
|
||||||
requestDetailsRef.current = requestDetails;
|
requestDetailsRef.current = requestDetails;
|
||||||
requestCertListRef.current = requestCertList;
|
|
||||||
requestCertDetailsRef.current = requestCertDetails;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open || !currentId) {
|
if (!open || !currentId) {
|
||||||
setInfo({});
|
setInfo({});
|
||||||
setCertificates([]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
setDetailLoading(true);
|
setDetailLoading(true);
|
||||||
|
|
||||||
const loadCertList = requestCertListRef.current;
|
Promise.resolve(requestDetailsRef.current({ id: currentId }))
|
||||||
Promise.all([
|
.catch((err) => {
|
||||||
Promise.resolve(requestDetailsRef.current({ id: currentId })).catch(
|
|
||||||
(err) => {
|
|
||||||
console.warn("[StaffViewModal] load detail failed:", err);
|
console.warn("[StaffViewModal] load detail failed:", err);
|
||||||
return { data: {} };
|
return { data: {} };
|
||||||
},
|
|
||||||
),
|
|
||||||
typeof loadCertList === "function"
|
|
||||||
? Promise.resolve(loadCertList(currentId)).catch((err) => {
|
|
||||||
console.warn("[StaffViewModal] load certificates failed:", err);
|
|
||||||
return [];
|
|
||||||
})
|
})
|
||||||
: Promise.resolve([]),
|
.then((detailRes) => {
|
||||||
])
|
|
||||||
.then(([detailRes, certList]) => {
|
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
setInfo(detailRes?.data || {});
|
setInfo(detailRes?.data || {});
|
||||||
setCertificates(Array.isArray(certList) ? certList : []);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|
@ -79,51 +66,35 @@ export default function StaffViewModal({
|
||||||
};
|
};
|
||||||
}, [open, currentId]);
|
}, [open, currentId]);
|
||||||
|
|
||||||
const openCertPreview = async (record) => {
|
const proofMaterialFiles = parseFileList(info.proofMaterialUrl);
|
||||||
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 proofMaterialUrl = info.proofMaterialUrl
|
const titleInfo = Array.isArray(info.titleCodeArr)
|
||||||
? JSON.parse(info.proofMaterialUrl)
|
? info.titleCodeArr.map((item) => ({
|
||||||
|
titleName: TITLE_LEVEL_MAP[item.titleCode] || item.titleCode || "-",
|
||||||
|
proveUrlList: parseFileList(item.proveUrl),
|
||||||
|
}))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const titleCodeArr = Array.isArray(info.titleCodeArr)
|
const regCert = info.registeredSafetyEngineerCert;
|
||||||
? info.titleCodeArr.map((item) => {
|
const regCertLevelMap = CERT_LEVEL_LABEL_BY_TYPE.registered_safety_engineer;
|
||||||
let proveUrlList = [];
|
const regCertFiles = parseFileList(regCert?.certAttachmentUrl);
|
||||||
if (item.proveUrl) {
|
|
||||||
try {
|
const evaluatorCert = info.evaluatorCert;
|
||||||
proveUrlList =
|
const evaluatorFlag = info.evaluatorFlag || (evaluatorCert ? 1 : 2);
|
||||||
typeof item.proveUrl === "string"
|
const evalCertLevelMap = CERT_LEVEL_LABEL_BY_TYPE.evaluator;
|
||||||
? JSON.parse(item.proveUrl)
|
const evalCertFiles = parseFileList(evaluatorCert?.certAttachmentUrl);
|
||||||
: item.proveUrl;
|
|
||||||
} catch {
|
const capabilityList = Array.isArray(info.capabilityAssessment)
|
||||||
proveUrlList = [];
|
? info.capabilityAssessment.map((item) => ({
|
||||||
}
|
capabilityName:
|
||||||
}
|
CAPABILITY_MAP[item.professionalCapabilityCode] ||
|
||||||
return {
|
item.professionalCapabilityCode ||
|
||||||
industryName:
|
|
||||||
QUALIFICATION_INDUSTRY_OPTIONS_MAP[item.industryCode] ||
|
|
||||||
item.industryCode ||
|
|
||||||
"-",
|
"-",
|
||||||
titleName: TITLE_LEVEL_MAP[item.titleCode] || item.titleCode || "-",
|
sourceName:
|
||||||
proveUrlList,
|
ABILITY_SOURCE_MAP[item.professionalCapabilitySourceCode] ||
|
||||||
};
|
item.professionalCapabilitySourceCode ||
|
||||||
})
|
"-",
|
||||||
|
}))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const renderFileList = (files) => {
|
const renderFileList = (files) => {
|
||||||
|
|
@ -150,17 +121,7 @@ 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 (
|
return (
|
||||||
<>
|
|
||||||
<Modal
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
|
|
@ -206,67 +167,56 @@ export default function StaffViewModal({
|
||||||
<Descriptions.Item label="基础学科专业">
|
<Descriptions.Item label="基础学科专业">
|
||||||
{info.basicDisciplineMajorName || "-"}
|
{info.basicDisciplineMajorName || "-"}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="人员岗位类型">
|
||||||
<Descriptions.Item label="是否注册安全工程师">
|
{PERSONNEL_POST_TYPE_MAP[info.personnelPositionType] || "-"}
|
||||||
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="是否技术负责人">
|
|
||||||
{info.technicalDirectorFlag === true
|
|
||||||
? "是"
|
|
||||||
: info.technicalDirectorFlag === false
|
|
||||||
? "否"
|
|
||||||
: "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="是否过程控制负责人">
|
|
||||||
{info.processControlLeaderFlag === true
|
|
||||||
? "是"
|
|
||||||
: info.processControlLeaderFlag === false
|
|
||||||
? "否"
|
|
||||||
: "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
|
|
||||||
|
|
||||||
<Descriptions.Item
|
|
||||||
label="出版学术专著、专利、获奖、发表学术论文等"
|
|
||||||
span={2}
|
|
||||||
>
|
|
||||||
{info.publications || "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="自我申报的专业能力及认定方式" span={2}>
|
|
||||||
{info.abilityDeclaration || "-"}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="主要学习工作经历" span={2}>
|
<Descriptions.Item label="主要学习工作经历" span={2}>
|
||||||
{info.workExperience || "-"}
|
{info.workExperience || "-"}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="学历证明材料" span={2}>
|
<Descriptions.Item label="学历证明材料" span={2}>
|
||||||
{proofMaterialUrl.length
|
{renderFileList(proofMaterialFiles)}
|
||||||
? proofMaterialUrl.map((item) => {
|
|
||||||
const isImage =
|
|
||||||
/\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i.test(item.url);
|
|
||||||
return (
|
|
||||||
<div key={item.id}>
|
|
||||||
{isImage ? (
|
|
||||||
<Image
|
|
||||||
src={item.url}
|
|
||||||
style={{ maxWidth: 200, cursor: "pointer" }}
|
|
||||||
preview={{
|
|
||||||
mask: item.fileName || item.name || "预览",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
onClick={() => window.open(item.url)}
|
|
||||||
>
|
|
||||||
{item.fileName || item.name || item.url}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: "-"}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
|
|
||||||
|
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
||||||
|
注安信息
|
||||||
|
</div>
|
||||||
|
<Descriptions bordered column={2} labelStyle={{ width: 120 }}>
|
||||||
|
<Descriptions.Item label="是否注册安全工程师">
|
||||||
|
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="注安专业类别">
|
||||||
|
{REGISTER_ENGINEER_CATEGORY_MAP[regCert?.certCategoryCode] || "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="注安等级">
|
||||||
|
{regCertLevelMap[regCert?.certLevel] || "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="证书编号">
|
||||||
|
{regCert?.certNo || "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="注安证书" span={2}>
|
||||||
|
{renderFileList(regCertFiles)}
|
||||||
|
</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
|
||||||
|
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
||||||
|
评价师信息
|
||||||
|
</div>
|
||||||
|
<Descriptions bordered column={2} labelStyle={{ width: 120 }}>
|
||||||
|
<Descriptions.Item label="是否评价师">
|
||||||
|
{EVALUATOR_MAP[evaluatorFlag] ?? "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="评价师等级">
|
||||||
|
{evalCertLevelMap[evaluatorCert?.certLevel] || "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="证书编号">
|
||||||
|
{evaluatorCert?.certNo || "-"}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="评价师证书" span={2}>
|
||||||
|
{renderFileList(evalCertFiles)}
|
||||||
|
</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
|
||||||
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
||||||
职称信息
|
职称信息
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -275,10 +225,9 @@ export default function StaffViewModal({
|
||||||
bordered
|
bordered
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowKey={(_, idx) => idx}
|
rowKey={(_, idx) => idx}
|
||||||
dataSource={titleCodeArr}
|
dataSource={titleInfo}
|
||||||
columns={[
|
columns={[
|
||||||
{ title: "行业", dataIndex: "industryName", width: 150 },
|
{ title: "职称", dataIndex: "titleName", width: 120 },
|
||||||
{ title: "职称", dataIndex: "titleName", width: 100 },
|
|
||||||
{
|
{
|
||||||
title: "证明材料",
|
title: "证明材料",
|
||||||
dataIndex: "proveUrlList",
|
dataIndex: "proveUrlList",
|
||||||
|
|
@ -288,120 +237,20 @@ export default function StaffViewModal({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
|
||||||
证照信息
|
专业能力信息
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
size="small"
|
size="small"
|
||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
|
||||||
pagination={false}
|
pagination={false}
|
||||||
dataSource={certificates}
|
rowKey={(_, idx) => idx}
|
||||||
locale={{ emptyText: "暂无证照信息" }}
|
dataSource={capabilityList}
|
||||||
|
locale={{ emptyText: "暂无专业能力信息" }}
|
||||||
columns={[
|
columns={[
|
||||||
{ title: "证照名称", dataIndex: "certName", ellipsis: true },
|
{ title: "专业能力", dataIndex: "capabilityName" },
|
||||||
{ title: "证书编号", dataIndex: "certNo", ellipsis: true },
|
{ title: "来源", dataIndex: "sourceName", width: 280 },
|
||||||
{ title: "证书类别", dataIndex: "certTypeName", ellipsis: true },
|
|
||||||
{ title: "发证机关", dataIndex: "issueOrg", ellipsis: true },
|
|
||||||
{ title: "有效开始日期", dataIndex: "validStartDate", width: 120 },
|
|
||||||
{ title: "有效结束日期", dataIndex: "validEndDate", width: 120 },
|
|
||||||
{
|
|
||||||
title: "操作",
|
|
||||||
width: 90,
|
|
||||||
render: (_, record) => (
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
onClick={() => openCertPreview(record)}
|
|
||||||
>
|
|
||||||
查看证书
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<FilePreviewModal
|
|
||||||
open={!!attachmentPreview}
|
|
||||||
title="附件预览"
|
|
||||||
fileName={attachmentPreview?.fileName}
|
|
||||||
url={attachmentPreview?.url}
|
|
||||||
onCancel={() => setAttachmentPreview(null)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
open={!!certPreview}
|
|
||||||
destroyOnHidden
|
|
||||||
title="证书预览"
|
|
||||||
width={720}
|
|
||||||
loading={certPreviewLoading}
|
|
||||||
cancelText="关闭"
|
|
||||||
okText={certPreviewUrl ? "新窗口打开" : "关闭"}
|
|
||||||
okButtonProps={{
|
|
||||||
style: certPreviewUrl ? undefined : { display: "none" },
|
|
||||||
}}
|
|
||||||
onCancel={() => {
|
|
||||||
setCertPreview(null);
|
|
||||||
setCertPreviewInfo(null);
|
|
||||||
}}
|
|
||||||
onOk={() => {
|
|
||||||
if (certPreviewUrl) {
|
|
||||||
window.open(certPreviewUrl, "_blank");
|
|
||||||
}
|
|
||||||
setCertPreview(null);
|
|
||||||
setCertPreviewInfo(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{certPreviewInfo && (
|
|
||||||
<div>
|
|
||||||
<Descriptions
|
|
||||||
bordered
|
|
||||||
column={1}
|
|
||||||
size="small"
|
|
||||||
style={{ marginBottom: 12 }}
|
|
||||||
>
|
|
||||||
<Descriptions.Item label="证照名称">
|
|
||||||
{certPreviewInfo.certName}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="证书编号">
|
|
||||||
{certPreviewInfo.certNo}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="证书类别">
|
|
||||||
{certPreviewInfo.certTypeName || "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="发证机关">
|
|
||||||
{certPreviewInfo.issueOrg || "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="有效开始日期">
|
|
||||||
{certPreviewInfo.validStartDate || "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="有效结束日期">
|
|
||||||
{certPreviewInfo.validEndDate || "-"}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="查看证书">
|
|
||||||
{certPreviewInfo.certAttachmentUrl &&
|
|
||||||
certPreviewInfo.certAttachmentUrl.split(",").map((item) => {
|
|
||||||
const isImage =
|
|
||||||
/\.(png|jpe?g|gif|bmp|webp|svg)(\?|#|$)/i.test(item);
|
|
||||||
return (
|
|
||||||
<div key={item} style={{ marginBottom: 4 }}>
|
|
||||||
{isImage ? (
|
|
||||||
<Image
|
|
||||||
src={item}
|
|
||||||
width={100}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<a onClick={() => window.open(item)}>{item}</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Descriptions.Item>
|
|
||||||
</Descriptions>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,50 @@ export const REGISTER_ENGINEER_OPTIONS = [
|
||||||
{ label: "否", value: 2 },
|
{ 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 = [
|
export const TITLE_LEVEL_OPTIONS = [
|
||||||
{ value: "SENIOR", label: "高级" },
|
{ value: "SENIOR", label: "高级" },
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
Table,
|
Table,
|
||||||
TreeSelect,
|
TreeSelect,
|
||||||
Upload,
|
Upload,
|
||||||
|
Divider,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { InboxOutlined } from "@ant-design/icons";
|
import { InboxOutlined } from "@ant-design/icons";
|
||||||
import { Get } from "@cqsjjb/jjb-common-lib/http";
|
import { Get } from "@cqsjjb/jjb-common-lib/http";
|
||||||
|
|
@ -29,14 +30,19 @@ import { NS_STAFF_INFO, NS_ORG_DEPARTMENT } from "~/enumerate/namespace";
|
||||||
import {
|
import {
|
||||||
EDUCATION_LEVEL_OPTIONS,
|
EDUCATION_LEVEL_OPTIONS,
|
||||||
EDUCATION_TYPE_OPTIONS,
|
EDUCATION_TYPE_OPTIONS,
|
||||||
QUALIFICATION_INDUSTRY_OPTIONS,
|
|
||||||
REGISTER_ENGINEER_OPTIONS,
|
REGISTER_ENGINEER_OPTIONS,
|
||||||
|
REGISTER_ENGINEER_CATEGORY_OPTIONS,
|
||||||
|
PERSONNEL_POST_TYPE_OPTIONS,
|
||||||
|
ABILITY_SOURCE_OPTIONS,
|
||||||
|
EVALUATOR_OPTIONS,
|
||||||
TITLE_LEVEL_OPTIONS,
|
TITLE_LEVEL_OPTIONS,
|
||||||
} from "~/enumerate/enterpriseOptions";
|
} from "~/enumerate/enterpriseOptions";
|
||||||
|
import { CERT_LEVEL_OPTIONS_BY_TYPE, CAPABILITY_OPTIONS } from "~/enumerate/constant";
|
||||||
import { getBirthDateFromIdCard } from "~/utils";
|
import { getBirthDateFromIdCard } from "~/utils";
|
||||||
import { idCardRule, mobileRule } from "~/utils/validators";
|
import { idCardRule, mobileRule } from "~/utils/validators";
|
||||||
import AttachmentUpload from "~/components/AttachmentUpload";
|
import AttachmentUpload from "~/components/AttachmentUpload";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
const API_HOST = window.process?.env?.app?.API_HOST || "";
|
const API_HOST = window.process?.env?.app?.API_HOST || "";
|
||||||
|
|
@ -218,7 +224,7 @@ function PersonnelInfoPage(props) {
|
||||||
width: 260,
|
width: 260,
|
||||||
dataIndex: "abilityNames",
|
dataIndex: "abilityNames",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text) => text || '暂无',
|
render: (text) => text || "暂无",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
|
|
@ -245,16 +251,7 @@ function PersonnelInfoPage(props) {
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
|
||||||
setCurrentId(record.id);
|
|
||||||
goCertificate(record.id, record.userName);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
证书能力
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
|
|
@ -361,6 +358,11 @@ function StaffFormModal({
|
||||||
const [deptPositionOptions, setDeptPositionOptions] = useState([]);
|
const [deptPositionOptions, setDeptPositionOptions] = useState([]);
|
||||||
const [positionLoading, setPositionLoading] = useState(false);
|
const [positionLoading, setPositionLoading] = useState(false);
|
||||||
const watchedDeptId = Form.useWatch("deptId", form);
|
const watchedDeptId = Form.useWatch("deptId", form);
|
||||||
|
const watchedRegisterEngineerFlag = Form.useWatch(
|
||||||
|
"registerEngineerFlag",
|
||||||
|
form,
|
||||||
|
);
|
||||||
|
const watchedEvaluatorFlag = Form.useWatch("evaluatorFlag", form);
|
||||||
const wasOpenRef = useRef(false);
|
const wasOpenRef = useRef(false);
|
||||||
const inflightDeptRef = useRef(null);
|
const inflightDeptRef = useRef(null);
|
||||||
|
|
||||||
|
|
@ -396,7 +398,6 @@ function StaffFormModal({
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadBasicDisciplineMajors = async () => {
|
const loadBasicDisciplineMajors = async () => {
|
||||||
|
|
||||||
await queryBasicDisciplineMajor({ pageSize: 999 });
|
await queryBasicDisciplineMajor({ pageSize: 999 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -438,21 +439,37 @@ function StaffFormModal({
|
||||||
setFields.proofMaterialUrl = JSON.parse(setFields.proofMaterialUrl);
|
setFields.proofMaterialUrl = JSON.parse(setFields.proofMaterialUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(setFields.titleCodeArr)) {
|
const parseCertAttachment = (cert) => {
|
||||||
setFields.titleCodeArr = setFields.titleCodeArr.map((item) => {
|
if (cert?.certAttachmentUrl) {
|
||||||
if (item.proveUrl && typeof item.proveUrl === "string") {
|
|
||||||
try {
|
try {
|
||||||
return { ...item, proveUrl: JSON.parse(item.proveUrl) };
|
cert.certAttachmentUrl = JSON.parse(cert.certAttachmentUrl);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (setFields.registeredSafetyEngineerCert) {
|
||||||
|
parseCertAttachment(setFields.registeredSafetyEngineerCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setFields.evaluatorCert) {
|
||||||
|
setFields.evaluatorFlag = 1;
|
||||||
|
parseCertAttachment(setFields.evaluatorCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(setFields.titleCodeArr) && setFields.titleCodeArr[0]) {
|
||||||
|
const first = setFields.titleCodeArr[0];
|
||||||
|
setFields.titleCode = first.titleCode;
|
||||||
|
if (first.proveUrl) {
|
||||||
|
try {
|
||||||
|
setFields.proveUrl = JSON.parse(first.proveUrl);
|
||||||
} catch {
|
} catch {
|
||||||
return item;
|
setFields.proveUrl = first.proveUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return item;
|
delete setFields.titleCodeArr;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form.setFieldsValue(setFields);
|
form.setFieldsValue(setFields);
|
||||||
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
if (!cancelled) setDetailLoading(false);
|
if (!cancelled) setDetailLoading(false);
|
||||||
|
|
@ -488,6 +505,15 @@ function StaffFormModal({
|
||||||
const handleSubmit = async (values) => {
|
const handleSubmit = async (values) => {
|
||||||
try {
|
try {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
const stringifyCert = (cert) =>
|
||||||
|
cert
|
||||||
|
? {
|
||||||
|
...cert,
|
||||||
|
certAttachmentUrl: Array.isArray(cert.certAttachmentUrl)
|
||||||
|
? JSON.stringify(cert.certAttachmentUrl)
|
||||||
|
: undefined,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
const payload = {
|
const payload = {
|
||||||
...values,
|
...values,
|
||||||
genderName:
|
genderName:
|
||||||
|
|
@ -499,13 +525,28 @@ function StaffFormModal({
|
||||||
proofMaterialUrl: Array.isArray(values.proofMaterialUrl)
|
proofMaterialUrl: Array.isArray(values.proofMaterialUrl)
|
||||||
? JSON.stringify(values.proofMaterialUrl)
|
? JSON.stringify(values.proofMaterialUrl)
|
||||||
: undefined,
|
: undefined,
|
||||||
titleCodeArr: Array.isArray(values.titleCodeArr)
|
titleCodeArr: [
|
||||||
? values.titleCodeArr.map((item) => ({
|
{
|
||||||
...item,
|
titleCode: values.titleCode,
|
||||||
proveUrl: Array.isArray(item.proveUrl)
|
proveUrl: Array.isArray(values.proveUrl)
|
||||||
? JSON.stringify(item.proveUrl)
|
? JSON.stringify(values.proveUrl)
|
||||||
: item.proveUrl,
|
: undefined,
|
||||||
}))
|
},
|
||||||
|
],
|
||||||
|
registeredSafetyEngineerCert:
|
||||||
|
values.registerEngineerFlag === 1
|
||||||
|
? stringifyCert(values.registeredSafetyEngineerCert)
|
||||||
|
: undefined,
|
||||||
|
evaluatorCert:
|
||||||
|
values.evaluatorFlag === 1
|
||||||
|
? stringifyCert(values.evaluatorCert)
|
||||||
|
: undefined,
|
||||||
|
capabilityAssessment: Array.isArray(values.capabilityAssessment)
|
||||||
|
? values.capabilityAssessment.filter(
|
||||||
|
(item) =>
|
||||||
|
item?.professionalCapabilityCode ||
|
||||||
|
item?.professionalCapabilitySourceCode,
|
||||||
|
)
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
if (payload.birthDate && typeof payload.birthDate !== "string") {
|
if (payload.birthDate && typeof payload.birthDate !== "string") {
|
||||||
|
|
@ -515,7 +556,6 @@ function StaffFormModal({
|
||||||
payload.joinWorkDate = payload.joinWorkDate.format("YYYY-MM-DD");
|
payload.joinWorkDate = payload.joinWorkDate.format("YYYY-MM-DD");
|
||||||
}
|
}
|
||||||
if (currentId) payload.id = currentId;
|
if (currentId) payload.id = currentId;
|
||||||
delete payload.proofMaterials;
|
|
||||||
|
|
||||||
const request = currentId ? staffInfoEdit : staffInfoAdd;
|
const request = currentId ? staffInfoEdit : staffInfoAdd;
|
||||||
const res = await request(payload);
|
const res = await request(payload);
|
||||||
|
|
@ -540,14 +580,6 @@ function StaffFormModal({
|
||||||
confirmLoading={submitting}
|
confirmLoading={submitting}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
const titleArr = form.getFieldValue("titleCodeArr") || [];
|
|
||||||
const hasTitleInfo = titleArr.some(
|
|
||||||
(item) => item?.industryCode && item?.titleCode,
|
|
||||||
);
|
|
||||||
if (!hasTitleInfo) {
|
|
||||||
message.warning("请添加职称信息");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
form.submit();
|
form.submit();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -586,7 +618,11 @@ function StaffFormModal({
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="birthDate" label="出生日期" rules={[{ required: true, message: "请选择出生日期" }]}>
|
<Form.Item
|
||||||
|
name="birthDate"
|
||||||
|
label="出生日期"
|
||||||
|
rules={[{ required: true, message: "请选择出生日期" }]}
|
||||||
|
>
|
||||||
<DatePicker style={{ width: "100%" }} />
|
<DatePicker style={{ width: "100%" }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -745,7 +781,21 @@ function StaffFormModal({
|
||||||
maxCount={5}
|
maxCount={5}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item name="personnelPositionType" label="人员岗位类型">
|
||||||
|
<Select
|
||||||
|
placeholder="请选择人员岗位类型"
|
||||||
|
allowClear
|
||||||
|
options={PERSONNEL_POST_TYPE_OPTIONS}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={24}>
|
||||||
|
<div className="register-engineer-section">
|
||||||
|
<div className="register-engineer-section-title">注安信息</div>
|
||||||
|
<Row gutter={16}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="registerEngineerFlag"
|
name="registerEngineerFlag"
|
||||||
|
|
@ -758,39 +808,163 @@ function StaffFormModal({
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
{watchedRegisterEngineerFlag === 1 && (
|
||||||
|
<>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="technicalDirectorFlag" label="是否技术负责人">
|
<Form.Item
|
||||||
|
name={["registeredSafetyEngineerCert", "certCategoryCode"]}
|
||||||
|
label="注安专业类别"
|
||||||
|
rules={[{ required: true, message: "请选择注安专业类别" }]}
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择"
|
placeholder="请选择注安专业类别"
|
||||||
allowClear
|
allowClear
|
||||||
options={[
|
options={REGISTER_ENGINEER_CATEGORY_OPTIONS}
|
||||||
{ label: "是", value: true },
|
|
||||||
{ label: "否", value: false },
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="processControlLeaderFlag"
|
name={["registeredSafetyEngineerCert", "certLevel"]}
|
||||||
label="是否过程控制负责人"
|
label="注安等级"
|
||||||
|
rules={[{ required: true, message: "请选择注安等级" }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择"
|
placeholder="请选择注安等级"
|
||||||
allowClear
|
allowClear
|
||||||
options={[
|
options={TITLE_LEVEL_OPTIONS}
|
||||||
{ label: "是", value: true },
|
|
||||||
{ label: "否", value: false },
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name={["registeredSafetyEngineerCert", "certNo"]}
|
||||||
|
label="证书编号"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "请输入证书编号" },
|
||||||
|
{ max: 50, message: "证书编号不能超过50个字符" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入证书编号" maxLength={50} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Item label="职称信息" required>
|
<AttachmentUpload
|
||||||
|
name={["registeredSafetyEngineerCert", "certAttachmentUrl"]}
|
||||||
|
label="注安证书"
|
||||||
|
extra="最多上传10个pdf,doc,docx,图片格式文件"
|
||||||
|
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
|
||||||
|
maxCount={10}
|
||||||
|
rules={[{ required: true, message: "请上传注安证书" }]}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={24}>
|
||||||
|
<div className="register-engineer-section">
|
||||||
|
<div className="register-engineer-section-title">
|
||||||
|
评价师信息
|
||||||
|
</div>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="evaluatorFlag"
|
||||||
|
label="是否评价师"
|
||||||
|
initialValue={2}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择"
|
||||||
|
options={EVALUATOR_OPTIONS}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
{watchedEvaluatorFlag === 1 && (
|
||||||
|
<>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name={["evaluatorCert", "certLevel"]}
|
||||||
|
label="评价师等级"
|
||||||
|
rules={[{ required: true, message: "请选择评价师等级" }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择评价师等级"
|
||||||
|
allowClear
|
||||||
|
options={CERT_LEVEL_OPTIONS_BY_TYPE.evaluator}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name={["evaluatorCert", "certNo"]}
|
||||||
|
label="证书编号"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "请输入证书编号" },
|
||||||
|
{ max: 50, message: "证书编号不能超过50个字符" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入证书编号" maxLength={50} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
<AttachmentUpload
|
||||||
|
name={["evaluatorCert", "certAttachmentUrl"]}
|
||||||
|
label="评价师证书"
|
||||||
|
extra="最多上传10个pdf,doc,docx,图片格式文件"
|
||||||
|
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
|
||||||
|
maxCount={10}
|
||||||
|
rules={[{ required: true, message: "请上传评价师证书" }]}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={24}>
|
||||||
|
<div className="register-engineer-section">
|
||||||
|
<div className="register-engineer-section-title">
|
||||||
|
职称信息
|
||||||
|
</div>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="titleCode"
|
||||||
|
label="职称"
|
||||||
|
rules={[{ required: true, message: "请选择职称" }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择职称"
|
||||||
|
allowClear
|
||||||
|
options={TITLE_LEVEL_OPTIONS}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<AttachmentUpload
|
||||||
|
name="proveUrl"
|
||||||
|
label="证明材料"
|
||||||
|
extra="最多上传1个pdf,doc,docx,图片格式文件"
|
||||||
|
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
|
||||||
|
maxCount={1}
|
||||||
|
rules={[{ required: true, message: "请上传证明材料" }]}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
<Form.Item label="专业能力信息">
|
||||||
<Form.List
|
<Form.List
|
||||||
name="titleCodeArr"
|
name="capabilityAssessment"
|
||||||
initialValue={[{}]}
|
initialValue={[{}]}
|
||||||
rules={[{ required: true, message: "请添加职称信息" }]}
|
|
||||||
>
|
>
|
||||||
{(fields, { add, remove }) => (
|
{(fields, { add, remove }) => (
|
||||||
<>
|
<>
|
||||||
|
|
@ -800,60 +974,38 @@ function StaffFormModal({
|
||||||
pagination={false}
|
pagination={false}
|
||||||
size="small"
|
size="small"
|
||||||
bordered
|
bordered
|
||||||
locale={{ emptyText: "暂无职称信息,点击下方按钮添加" }}
|
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
title: "行业",
|
title: "专业能力",
|
||||||
width: 200,
|
|
||||||
render: (_, field) => (
|
render: (_, field) => (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={[field.name, "industryCode"]}
|
name={[field.name, "professionalCapabilityCode"]}
|
||||||
style={{ marginBottom: 0 }}
|
style={{ marginBottom: 0 }}
|
||||||
rules={[
|
|
||||||
{ required: true, message: "请选择行业" },
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择行业"
|
placeholder="请选择专业能力"
|
||||||
allowClear
|
allowClear
|
||||||
options={QUALIFICATION_INDUSTRY_OPTIONS}
|
options={CAPABILITY_OPTIONS}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "职称",
|
title: "来源",
|
||||||
width: 120,
|
width: 280,
|
||||||
render: (_, field) => (
|
render: (_, field) => (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={[field.name, "titleCode"]}
|
name={[field.name, "professionalCapabilitySourceCode"]}
|
||||||
style={{ marginBottom: 0 }}
|
style={{ marginBottom: 0 }}
|
||||||
rules={[
|
|
||||||
{ required: true, message: "请选择职称" },
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择职称"
|
placeholder="请选择来源"
|
||||||
allowClear
|
allowClear
|
||||||
options={TITLE_LEVEL_OPTIONS}
|
options={ABILITY_SOURCE_OPTIONS}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "证明材料",
|
|
||||||
render: (_, field) => (
|
|
||||||
<AttachmentUpload
|
|
||||||
name={[field.name, "proveUrl"]}
|
|
||||||
rules={[
|
|
||||||
{ required: true, message: "请上传证明材料" },
|
|
||||||
]}
|
|
||||||
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
|
|
||||||
maxCount={1}
|
|
||||||
style={{ marginBottom: 0 }}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 80,
|
width: 80,
|
||||||
|
|
@ -871,47 +1023,21 @@ function StaffFormModal({
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
{fields.length < 2 && (
|
||||||
<Button
|
<Button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
onClick={() => add()}
|
onClick={() => add()}
|
||||||
block
|
block
|
||||||
style={{ marginTop: 12 }}
|
style={{ marginTop: 12 }}
|
||||||
>
|
>
|
||||||
添加职称信息
|
添加专业能力信息
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
|
||||||
name="publications"
|
|
||||||
label="出版学术专著、专利、获奖、发表学术论文等"
|
|
||||||
rules={[{ max: 500, message: "不能超过1000个字符" }]}
|
|
||||||
>
|
|
||||||
<Input.TextArea
|
|
||||||
rows={2}
|
|
||||||
placeholder="请输入"
|
|
||||||
maxLength={500}
|
|
||||||
showCount
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.Item
|
|
||||||
name="abilityDeclaration"
|
|
||||||
label="自我申报的专业能力及认定方式"
|
|
||||||
rules={[{ max: 500, message: "不能超过1000个字符" }]}
|
|
||||||
>
|
|
||||||
<Input.TextArea
|
|
||||||
rows={2}
|
|
||||||
placeholder="请输入"
|
|
||||||
maxLength={500}
|
|
||||||
showCount
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.Item name="workExperience" label="主要学习工作经历">
|
<Form.Item name="workExperience" label="主要学习工作经历">
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
|
|
@ -1073,7 +1199,12 @@ function StaffImportModal({ open, onCancel, onSuccess }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ResetPasswordModal({ open, currentId, staffInfoResetPassword, onCancel }) {
|
function ResetPasswordModal({
|
||||||
|
open,
|
||||||
|
currentId,
|
||||||
|
staffInfoResetPassword,
|
||||||
|
onCancel,
|
||||||
|
}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
.register-engineer-section {
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px 16px 0;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue