dev-tmp1
tangjie 2026-08-18 17:26:29 +08:00
parent 94e499646e
commit 58d0253691
7 changed files with 2945 additions and 4075 deletions

View File

@ -20,14 +20,14 @@
"test:enterprise-info:granular": "node docs/test-reports/测试用例/test-enterprise-info-granular.mjs"
},
"dependencies": {
"@ant-design/icons": "^5.0.0",
"@ant-design/icons": "latest",
"@cqsjjb/jjb-common-decorator": "latest",
"@cqsjjb/jjb-common-lib": "latest",
"@cqsjjb/jjb-dva-runtime": "latest",
"@cqsjjb/jjb-react-admin-component": "latest",
"@rc-component/motion": "^1.0.0",
"@rc-component/util": "^1.11.1",
"antd": "^5.29.2",
"antd": "^6.6.1",
"dayjs": "^1.11.7",
"docxtemplater": "latest",
"echarts": "^6.1.0",

File diff suppressed because it is too large Load Diff

View File

@ -81,6 +81,7 @@ export default function StaffViewModal({
const regCert = info.registeredSafetyEngineerCert;
const regCertLevelMap = CERT_LEVEL_LABEL_BY_TYPE.registered_safety_engineer;
const regCertFiles = parseFileList(regCert?.certAttachmentUrl);
const regPractisingFiles = parseFileList(regCert?.practisingCertUrl);
const evaluatorCert = info.evaluatorCert;
const evaluatorFlag = info.evaluatorFlag || (evaluatorCert ? 1 : 2);
@ -136,16 +137,14 @@ export default function StaffViewModal({
okButtonProps={{ style: { display: "none" } }}
onCancel={onCancel}
>
<Descriptions bordered column={2} labelStyle={{ width: 120 }}>
<div style={{ marginBottom: 8, fontWeight: 600 }}>基础信息</div>
<Descriptions bordered column={2} labelStyle={{ width: 120 }} size="small">
<Descriptions.Item label="姓名">{info.userName}</Descriptions.Item>
<Descriptions.Item label="性别">
{GENDER_MAP[info.genderCode]}
</Descriptions.Item>
<Descriptions.Item label="出生日期">
{info.birthDate}
</Descriptions.Item>
<Descriptions.Item label="参加工作时间">
{info.joinWorkDate}
<Descriptions.Item label="本行业工作年限">
{info.workDateAge}
</Descriptions.Item>
<Descriptions.Item label="账号">{info.account}</Descriptions.Item>
<Descriptions.Item label="部门">{info.deptName}</Descriptions.Item>
@ -159,18 +158,6 @@ export default function StaffViewModal({
<Descriptions.Item label="办公地址">
{info.officeAddress}
</Descriptions.Item>
<Descriptions.Item label="学历类型">
{info.educationTypeName || "-"}
</Descriptions.Item>
<Descriptions.Item label="毕业院校">
{info.graduateSchool}
</Descriptions.Item>
<Descriptions.Item label="学历层次">
{info.educationLevelName || "-"}
</Descriptions.Item>
<Descriptions.Item label="基础学科专业">
{info.basicDisciplineMajorName || "-"}
</Descriptions.Item>
<Descriptions.Item label="是否技术负责人">
{info.technicalDirectorFlag === true
? "是"
@ -191,6 +178,53 @@ export default function StaffViewModal({
<Descriptions.Item label="出版学术专著专利获奖论文等" span={2}>
{info.publications || "-"}
</Descriptions.Item>
</Descriptions>
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
专业能力信息
</div>
<Table
size="small"
bordered
pagination={false}
rowKey={(_, idx) => idx}
dataSource={capabilityList}
locale={{ emptyText: "暂无专业能力信息" }}
columns={[
{
title: "行业",
dataIndex: "industryCode",
width: 220,
ellipsis: true,
render: (code) =>
QUALIFICATION_INDUSTRY_OPTIONS_MAP[code] || code || "-",
},
{
title: "专业能力",
dataIndex: "capabilityName",
width: 80,
ellipsis: true,
},
{ title: "来源", dataIndex: "sourceName", width: 280 },
]}
/>
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
学历信息
</div>
<Descriptions bordered column={2} labelStyle={{ width: 120 }} size="small">
<Descriptions.Item label="学历类型">
{info.educationTypeName || "-"}
</Descriptions.Item>
<Descriptions.Item label="毕业院校">
{info.graduateSchool}
</Descriptions.Item>
<Descriptions.Item label="学历层次">
{info.educationLevelName || "-"}
</Descriptions.Item>
<Descriptions.Item label="基础学科专业">
{info.basicDisciplineMajorName || "-"}
</Descriptions.Item>
<Descriptions.Item label="学历证明材料" span={2}>
{renderFileList(proofMaterialFiles)}
</Descriptions.Item>
@ -199,7 +233,7 @@ export default function StaffViewModal({
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
注安信息
</div>
<Descriptions bordered column={2} labelStyle={{ width: 120 }}>
<Descriptions bordered column={2} labelStyle={{ width: 120 }} size="small">
<Descriptions.Item label="是否注册安全工程师">
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
</Descriptions.Item>
@ -212,15 +246,21 @@ export default function StaffViewModal({
<Descriptions.Item label="证书编号">
{regCert?.certNo || "-"}
</Descriptions.Item>
<Descriptions.Item label="执业证书编号">
{regCert?.practisingCertCode || "-"}
</Descriptions.Item>
<Descriptions.Item label="注安证书" span={2}>
{renderFileList(regCertFiles)}
</Descriptions.Item>
<Descriptions.Item label="注安执业证书" span={2}>
{renderFileList(regPractisingFiles)}
</Descriptions.Item>
</Descriptions>
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
评价师信息
</div>
<Descriptions bordered column={2} labelStyle={{ width: 120 }}>
<Descriptions bordered column={2} labelStyle={{ width: 120 }} size="small">
<Descriptions.Item label="是否评价师">
{EVALUATOR_MAP[evaluatorFlag] ?? "-"}
</Descriptions.Item>
@ -254,35 +294,6 @@ export default function StaffViewModal({
},
]}
/>
<div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
专业能力信息
</div>
<Table
size="small"
bordered
pagination={false}
rowKey={(_, idx) => idx}
dataSource={capabilityList}
locale={{ emptyText: "暂无专业能力信息" }}
columns={[
{
title: "行业",
dataIndex: "industryCode",
width: 220,
ellipsis: true,
render: (code) =>
QUALIFICATION_INDUSTRY_OPTIONS_MAP[code] || code || "-",
},
{
title: "专业能力",
dataIndex: "capabilityName",
width: 80,
ellipsis: true,
},
{ title: "来源", dataIndex: "sourceName", width: 280 },
]}
/>
</Modal>
);
}

View File

@ -588,9 +588,7 @@ function DepartmentPositionPage(props) {
<Modal
open={assignRoleModalOpen}
destroyOnHidden
mask={{
closable: false,
}}
title="分配系统角色"
width={480}
confirmLoading={orgPositionLoading}

View File

@ -2,9 +2,9 @@ import { Connect } from "@cqsjjb/jjb-dva-runtime";
import {
Alert,
Button,
DatePicker,
Form,
Input,
InputNumber,
message,
Modal,
Row,
@ -20,7 +20,6 @@ import {
import { InboxOutlined } from "@ant-design/icons";
import { Get } from "@cqsjjb/jjb-common-lib/http";
import { useEffect, useMemo, useRef, useState } from "react";
import dayjs from "dayjs";
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
import SearchForm from "~/components/SearchForm";
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
@ -45,7 +44,7 @@ import {
PROFESSIONAL_MAJOR_OPTIONS,
CERT_LEVEL_LABEL_BY_TYPE
} from "~/enumerate/constant";
import { getBirthDateFromIdCard, renderCapabilityList } from "~/utils";
import { renderCapabilityList } from "~/utils";
import { idCardRule, mobileRule } from "~/utils/validators";
import AttachmentUpload from "~/components/AttachmentUpload";
import StaffViewModal from "~/components/StaffViewModal";
@ -219,7 +218,7 @@ function PersonnelInfoPage(props) {
<div>
<span>员工信息管理</span>
<div className="pageLayout-extra">
机构管理员在系统中为本机构的人员进行信息录入包括姓名性别身份证号出生日期
机构管理员在系统中为本机构的人员进行信息录入包括姓名性别身份证号
</div>
</div>
}
@ -327,21 +326,21 @@ function PersonnelInfoPage(props) {
ellipsis: true,
render: renderCapabilityList,
},
{
title: "证照名称",
dataIndex: "personnelCertFilingPageCOList",
width: 280,
render: (_, record) => {
const arr = [];
if(record.registeredSafetyEngineerCert){
arr.push(<Tag color="blue">{TITLE_LEVEL_MAP[record.registeredSafetyEngineerCert.certLevel]}注册安全工程师</Tag>);
}
if(record.evaluatorCert){
arr.push(<Tag color="green">{evalCertLevelMap[record.evaluatorCert.certLevel]}注册安全评价师</Tag>);
}
return <Space size={4}>{arr}</Space>;
},
{
title: "证照名称",
dataIndex: "personnelCertFilingPageCOList",
width: 280,
render: (_, record) => {
const arr = [];
if (record.registeredSafetyEngineerCert) {
arr.push(<Tag color="blue">{TITLE_LEVEL_MAP[record.registeredSafetyEngineerCert.certLevel]}注册安全工程师</Tag>);
}
if (record.evaluatorCert) {
arr.push(<Tag color="green">{evalCertLevelMap[record.evaluatorCert.certLevel]}注册安全评价师</Tag>);
}
return <Space size={4}>{arr}</Space>;
},
},
{
title: "操作",
width: 200,
@ -594,9 +593,6 @@ function StaffFormModal({
const setFields = {
...data,
};
if (data.birthDate) setFields.birthDate = dayjs(data.birthDate);
if (data.joinWorkDate)
setFields.joinWorkDate = dayjs(data.joinWorkDate);
if (setFields.proofMaterialUrl) {
setFields.proofMaterialUrl = JSON.parse(setFields.proofMaterialUrl);
@ -606,7 +602,12 @@ function StaffFormModal({
if (cert?.certAttachmentUrl) {
try {
cert.certAttachmentUrl = JSON.parse(cert.certAttachmentUrl);
} catch {}
} catch { }
}
if (cert?.practisingCertUrl) {
try {
cert.practisingCertUrl = JSON.parse(cert.practisingCertUrl);
} catch { }
}
};
@ -665,12 +666,6 @@ function StaffFormModal({
};
const onValuesChange = (changed) => {
if ("idCardNo" in changed && changed.idCardNo) {
const birth = getBirthDateFromIdCard(changed.idCardNo);
if (birth) {
form.setFieldValue("birthDate", dayjs(birth));
}
}
if ("deptId" in changed) {
form.setFieldValue("postId", undefined);
loadPositionsByDept(changed.deptId);
@ -687,11 +682,14 @@ function StaffFormModal({
const stringifyCert = (cert) =>
cert
? {
...cert,
certAttachmentUrl: Array.isArray(cert.certAttachmentUrl)
? JSON.stringify(cert.certAttachmentUrl)
: undefined,
}
...cert,
certAttachmentUrl: Array.isArray(cert.certAttachmentUrl)
? JSON.stringify(cert.certAttachmentUrl)
: undefined,
practisingCertUrl: Array.isArray(cert.practisingCertUrl)
? JSON.stringify(cert.practisingCertUrl)
: undefined,
}
: undefined;
const payload = {
...values,
@ -723,18 +721,12 @@ function StaffFormModal({
: undefined,
capabilityAssessment: Array.isArray(values.capabilityAssessment)
? values.capabilityAssessment.filter(
(item) =>
item?.professionalCapabilityCode ||
item?.professionalCapabilitySourceCode,
)
(item) =>
item?.professionalCapabilityCode ||
item?.professionalCapabilitySourceCode,
)
: undefined,
};
if (payload.birthDate && typeof payload.birthDate !== "string") {
payload.birthDate = payload.birthDate.format("YYYY-MM-DD");
}
if (payload.joinWorkDate && typeof payload.joinWorkDate !== "string") {
payload.joinWorkDate = payload.joinWorkDate.format("YYYY-MM-DD");
}
if (currentId) payload.id = currentId;
const request = currentId ? staffInfoEdit : staffInfoAdd;
@ -771,220 +763,406 @@ function StaffFormModal({
onFinish={handleSubmit}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="userName"
label="姓名"
rules={[
{ required: true, message: "请输入姓名" },
{ max: 50, message: "姓名不能超过50个字符" },
]}
>
<Input placeholder="请输入姓名" maxLength={50} showCount />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="genderCode"
label="性别"
rules={[{ required: true, message: "请选择性别" }]}
>
<Select
placeholder="请选择性别"
options={[
{ label: "男", value: 1 },
{ label: "女", value: 2 },
]}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="birthDate"
label="出生日期"
rules={[{ required: true, message: "请选择出生日期" }]}
>
<DatePicker style={{ width: "100%" }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="joinWorkDate"
label="参加工作时间"
rules={[{ required: true, message: "请选择参加工作时间" }]}
>
<DatePicker style={{ width: "100%" }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="account"
label="账号"
rules={[mobileRule("账号", true)]}
>
<Input placeholder="请输入账号" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="deptId"
label="部门"
rules={[{ required: true, message: "请选择部门" }]}
>
<TreeSelect
placeholder="请选择部门"
treeData={orgDepartmentTreeData}
allowClear
fieldNames={{
label: "deptName",
value: "id",
key: "id",
}}
treeDefaultExpandAll
showSearch
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="postId"
label="岗位"
rules={[{ required: true, message: "请选择岗位" }]}
>
<Select
placeholder="请选择岗位"
options={deptPositionOptions}
loading={positionLoading}
disabled={!watchedDeptId}
allowClear
showSearch
optionFilterProp="label"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="idCardNo"
label="身份证号"
rules={[
idCardRule(true),
{ max: 18, message: "身份证号不能超过18个字符" },
]}
>
<Input placeholder="请输入身份证号" maxLength={18} />
</Form.Item>
<Col span={24}>
<div className="register-engineer-section">
<div className="register-engineer-section-title">基础信息</div>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="userName"
label="姓名"
rules={[
{ required: true, message: "请输入姓名" },
{ max: 50, message: "姓名不能超过50个字符" },
]}
>
<Input placeholder="请输入姓名" maxLength={50} showCount />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="genderCode"
label="性别"
rules={[{ required: true, message: "请选择性别" }]}
>
<Select
placeholder="请选择性别"
options={[
{ label: "男", value: 1 },
{ label: "女", value: 2 },
]}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="workDateAge"
label="本行业工作年限"
rules={[
{ required: true, message: "请输入本行业工作年限" },
]}
>
<InputNumber
min={0}
precision={0}
placeholder="请输入本行业工作年限"
max={100}
style={{ width: "100%" }}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="account"
label="账号"
rules={[mobileRule("账号", true)]}
>
<Input placeholder="请输入账号" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="deptId"
label="部门"
rules={[{ required: true, message: "请选择部门" }]}
>
<TreeSelect
placeholder="请选择部门"
treeData={orgDepartmentTreeData}
allowClear
fieldNames={{
label: "deptName",
value: "id",
key: "id",
}}
treeDefaultExpandAll
showSearch
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="postId"
label="岗位"
rules={[{ required: true, message: "请选择岗位" }]}
>
<Select
placeholder="请选择岗位"
options={deptPositionOptions}
loading={positionLoading}
disabled={!watchedDeptId}
allowClear
showSearch
optionFilterProp="label"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="idCardNo"
label="身份证号"
rules={[
idCardRule(true),
{ max: 18, message: "身份证号不能超过18个字符" },
]}
>
<Input placeholder="请输入身份证号" maxLength={18} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="currentAddress"
label="现住地址"
rules={[
{ max: 300, message: "现住地址不能超过300个字符" },
]}
>
<Input
placeholder="请输入现住地址"
maxLength={300}
showCount
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="officeAddress"
label="办公地址"
rules={[
{ max: 300, message: "办公地址不能超过300个字符" },
]}
>
<Input
placeholder="请输入办公地址"
maxLength={300}
showCount
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="technicalDirectorFlag"
label="是否技术负责人"
>
<Select
placeholder="请选择"
allowClear
options={[
{ label: "是", value: true },
{ label: "否", value: false },
]}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="processControlLeaderFlag"
label="是否过程控制负责人"
>
<Select
placeholder="请选择"
allowClear
options={[
{ label: "是", value: true },
{ label: "否", value: false },
]}
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item name="workExperience" label="主要学习工作经历">
<Input.TextArea
rows={3}
placeholder="请输入"
maxLength={500}
showCount
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="publications"
label="出版学术专著专利获奖论文等"
rules={[
{
max: 1000,
message: "出版学术专著等长度不能超过1000个字符",
},
]}
>
<Input.TextArea
rows={3}
placeholder="请输入"
maxLength={1000}
showCount
/>
</Form.Item>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
<Col span={24}>
<div className="register-engineer-section">
<Form.Item label="专业能力信息">
<Form.List name="capabilityAssessment" initialValue={[{}]}>
{(fields, { add, remove }) => (
<>
<Table
dataSource={fields}
rowKey={(field) => field.key}
pagination={false}
size="small"
bordered
columns={[
{
title: "行业",
width: 200,
render: (_, field) => (
<Form.Item
name={[field.name, "industryCode"]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择行业"
allowClear
showSearch
optionFilterProp="label"
options={QUALIFICATION_INDUSTRY_OPTIONS}
onChange={(code) => {
if (code) loadCapOptions(code);
form.setFieldValue(
["capabilityAssessment", field.name, "professionalCapabilityCode"],
undefined,
);
}}
/>
</Form.Item>
),
},
{
title: "专业能力",
render: (_, field) => {
const rowIndustryCode =
watchedCapList?.[field.name]?.industryCode;
const rowOptions = rowIndustryCode
? capOptionsCache[rowIndustryCode] || []
: [];
return (
<Form.Item
name={[field.name, "professionalCapabilityCode"]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择专业能力"
showSearch
optionFilterProp="label"
allowClear
options={rowOptions}
/>
</Form.Item>
);
},
},
{
title: "来源",
width: 280,
render: (_, field) => (
<Form.Item
name={[
field.name,
"professionalCapabilitySourceCode",
]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择来源"
allowClear
options={ABILITY_SOURCE_OPTIONS}
/>
</Form.Item>
),
},
{
title: "操作",
width: 80,
render: (_, field) => (
<Button
type="link"
danger
size="small"
disabled={fields.length <= 1}
onClick={() => remove(field.name)}
>
删除
</Button>
),
},
]}
/>
{fields.length < 2 && (
<Button
type="dashed"
onClick={() => add()}
block
style={{ marginTop: 12 }}
>
添加专业能力信息
</Button>
)}
</>
)}
</Form.List>
</Form.Item>
</div>
<Col span={12}>
<Form.Item
name="currentAddress"
label="现住地址"
rules={[{ max: 300, message: "现住地址不能超过300个字符" }]}
>
<Input placeholder="请输入现住地址" maxLength={300} showCount />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="officeAddress"
label="办公地址"
rules={[{ max: 300, message: "办公地址不能超过300个字符" }]}
>
<Input placeholder="请输入办公地址" maxLength={300} showCount />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="educationTypeCode" label="学历类型">
<Select
placeholder="请选择学历类型"
allowClear
options={EDUCATION_TYPE_OPTIONS}
onChange={(_val, option) => {
form.setFieldValue(
"educationTypeName",
option?.label || undefined,
);
}}
/>
</Form.Item>
<Form.Item name="educationTypeName" noStyle />
</Col>
<Col span={12}>
<Form.Item
name="graduateSchool"
label="毕业院校"
rules={[{ max: 200, message: "毕业院校不能超过200个字符" }]}
>
<Input placeholder="请输入毕业院校" maxLength={200} showCount />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="educationLevelCode" label="学历层次">
<Select
placeholder="请选择学历层次"
allowClear
options={EDUCATION_LEVEL_OPTIONS}
onChange={(val, option) => {
form.setFieldValue(
"educationLevelName",
option?.label || undefined,
);
}}
/>
</Form.Item>
<Form.Item name="educationLevelName" noStyle />
</Col>
<Col span={12}>
<Form.Item name="basicDisciplineMajorId" label="基础学科专业">
<Select
placeholder="请先选择资质范围"
allowClear
showSearch
optionFilterProp="label"
options={(staffInfo?.basicDisciplineMajorList || []).map(
(item) => ({
label: `${item.professionalName}`,
value: item.id,
}),
)}
loading={staffInfo?.staffInfoLoading}
disabled={!staffInfo?.basicDisciplineMajorList?.length}
/>
</Form.Item>
</Col>
<Col span={12}>
<AttachmentUpload
name="proofMaterialUrl"
label="学历证明材料"
extra={"最多上传5个pdf,doc,docx,图片格式文件"}
accept={".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"}
maxCount={5}
/>
</Col>
<Col span={12}>
<Form.Item name="technicalDirectorFlag" label="是否技术负责人">
<Select
placeholder="请选择"
allowClear
options={[
{ label: "是", value: true },
{ label: "否", value: false },
]}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="processControlLeaderFlag" label="是否过程控制负责人">
<Select
placeholder="请选择"
allowClear
options={[
{ label: "是", value: true },
{ label: "否", value: false },
]}
/>
</Form.Item>
</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="educationTypeCode" label="学历类型">
<Select
placeholder="请选择学历类型"
allowClear
options={EDUCATION_TYPE_OPTIONS}
onChange={(_val, option) => {
form.setFieldValue(
"educationTypeName",
option?.label || undefined,
);
}}
/>
</Form.Item>
<Form.Item name="educationTypeName" noStyle />
</Col>
<Col span={12}>
<Form.Item
name="graduateSchool"
label="毕业院校"
rules={[
{ max: 200, message: "毕业院校不能超过200个字符" },
]}
>
<Input
placeholder="请输入毕业院校"
maxLength={200}
showCount
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item name="educationLevelCode" label="学历层次">
<Select
placeholder="请选择学历层次"
allowClear
options={EDUCATION_LEVEL_OPTIONS}
onChange={(val, option) => {
form.setFieldValue(
"educationLevelName",
option?.label || undefined,
);
}}
/>
</Form.Item>
<Form.Item name="educationLevelName" noStyle />
</Col>
<Col span={12}>
<Form.Item
name="basicDisciplineMajorId"
label="基础学科专业"
>
<Select
placeholder="请选择基础学科专业"
allowClear
showSearch
optionFilterProp="label"
options={(staffInfo?.basicDisciplineMajorList || []).map(
(item) => ({
label: `${item.professionalName}`,
value: item.id,
}),
)}
loading={staffInfo?.staffInfoLoading}
disabled={!staffInfo?.basicDisciplineMajorList?.length}
/>
</Form.Item>
</Col>
<Col span={12}>
<AttachmentUpload
name="proofMaterialUrl"
label="学历证明材料"
extra={"最多上传5个pdf,doc,docx,图片格式文件"}
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
maxCount={5}
/>
</Col>
</Row>
</div>
</Col>
</Row>
<Row gutter={16}>
@ -1001,7 +1179,7 @@ function StaffFormModal({
<Select
placeholder="请选择"
options={REGISTER_ENGINEER_OPTIONS}
onChange={()=>{
onChange={() => {
form.setFieldsValue({
registeredSafetyEngineerCert: null,
})
@ -1056,7 +1234,7 @@ function StaffFormModal({
<Input placeholder="请输入证书编号" maxLength={50} />
</Form.Item>
</Col>
<Col span={24}>
<Col span={12}>
<AttachmentUpload
name={[
"registeredSafetyEngineerCert",
@ -1069,6 +1247,43 @@ function StaffFormModal({
rules={[{ required: true, message: "请上传注安证书" }]}
/>
</Col>
<Col span={12}>
<Form.Item
name={[
"registeredSafetyEngineerCert",
"practisingCertCode",
]}
label="执业证书编号"
rules={[
{ required: true, message: "请输入执业证书编号" },
{
max: 50,
message: "执业证书编号不能超过50个字符",
},
]}
>
<Input
placeholder="请输入执业证书编号"
maxLength={50}
/>
</Form.Item>
</Col>
<Col span={12}>
<AttachmentUpload
name={[
"registeredSafetyEngineerCert",
"practisingCertUrl",
]}
label="注安执业证书"
extra="最多上传10个pdf,doc,docx,图片格式文件"
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg,.bmp,.webp"
maxCount={10}
rules={[
{ required: true, message: "请上传注安执业证书" },
]}
/>
</Col>
</>
)}
</Row>
@ -1086,7 +1301,7 @@ function StaffFormModal({
label="是否评价师"
initialValue={2}
>
<Select placeholder="请选择" options={EVALUATOR_OPTIONS} onChange={()=>{
<Select placeholder="请选择" options={EVALUATOR_OPTIONS} onChange={() => {
form.setFieldsValue({
evaluatorCert: null,
})
@ -1185,144 +1400,6 @@ function StaffFormModal({
</Row>
</div>
</Col>
<Col span={24}>
<Form.Item label="专业能力信息">
<Form.List name="capabilityAssessment" initialValue={[{}]}>
{(fields, { add, remove }) => (
<>
<Table
dataSource={fields}
rowKey={(field) => field.key}
pagination={false}
size="small"
bordered
columns={[
{
title: "行业",
width: 200,
render: (_, field) => (
<Form.Item
name={[field.name, "industryCode"]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择行业"
allowClear
showSearch
optionFilterProp="label"
options={QUALIFICATION_INDUSTRY_OPTIONS}
onChange={(code) => {
if (code) loadCapOptions(code);
form.setFieldValue(
["capabilityAssessment", field.name, "professionalCapabilityCode"],
undefined,
);
}}
/>
</Form.Item>
),
},
{
title: "专业能力",
render: (_, field) => {
const rowIndustryCode =
watchedCapList?.[field.name]?.industryCode;
const rowOptions = rowIndustryCode
? capOptionsCache[rowIndustryCode] || []
: [];
return (
<Form.Item
name={[field.name, "professionalCapabilityCode"]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择专业能力"
showSearch
optionFilterProp="label"
allowClear
options={rowOptions}
/>
</Form.Item>
);
},
},
{
title: "来源",
width: 280,
render: (_, field) => (
<Form.Item
name={[
field.name,
"professionalCapabilitySourceCode",
]}
style={{ marginBottom: 0 }}
>
<Select
placeholder="请选择来源"
allowClear
options={ABILITY_SOURCE_OPTIONS}
/>
</Form.Item>
),
},
{
title: "操作",
width: 80,
render: (_, field) => (
<Button
type="link"
danger
size="small"
disabled={fields.length <= 1}
onClick={() => remove(field.name)}
>
删除
</Button>
),
},
]}
/>
{fields.length < 2 && (
<Button
type="dashed"
onClick={() => add()}
block
style={{ marginTop: 12 }}
>
添加专业能力信息
</Button>
)}
</>
)}
</Form.List>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item name="workExperience" label="主要学习工作经历">
<Input.TextArea
rows={3}
placeholder="请输入"
maxLength={500}
showCount
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="publications"
label="出版学术专著专利获奖论文等"
rules={[
{ max: 1000, message: "出版学术专著等长度不能超过1000个字符" },
]}
>
<Input.TextArea
rows={3}
placeholder="请输入"
maxLength={1000}
showCount
/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>

View File

@ -28,8 +28,8 @@
.register-engineer-section {
border: 1px dashed #d9d9d9;
border-radius: 8px;
padding: 16px 16px 0;
margin-bottom: 24px;
padding: 12px 12px 0;
margin-bottom: 20px;
&-title {
font-size: 14px;

View File

@ -54,6 +54,11 @@ export default class Container extends React.Component {
}}
locale={language}
prefixCls={window.process.env.app.antd["ant-prefix"]}
modal={{
mask: {
closable: false,
},
}}
>
<App style={{ height: "100%" }}>
<AppMiddle {...this.props} />