dev_1.0.1
tangjie 2026-07-08 14:44:41 +08:00
parent bb5ec8bb67
commit 353e40b31a
3 changed files with 166 additions and 78 deletions

View File

@ -14,7 +14,7 @@ module.exports = {
}, },
production: { production: {
// 应用后端分支名称,部署上线需要 // 应用后端分支名称,部署上线需要
javaGitBranch: "<branch-name>", javaGitBranch: "dev",
// 接口服务地址 // 接口服务地址
API_HOST: "", API_HOST: "",
}, },

View File

@ -55,8 +55,8 @@ function toSelectedDept(node) {
} }
function DepartmentPositionPage(props) { function DepartmentPositionPage(props) {
const {orgPosition}=props; const { orgPosition } = props;
const {orgPositionLoading}=orgPosition; const { orgPositionLoading } = orgPosition;
const [selectedDept, setSelectedDept] = useState(null); const [selectedDept, setSelectedDept] = useState(null);
const [treeData, setTreeData] = useState([]); const [treeData, setTreeData] = useState([]);
const [deptModalOpen, setDeptModalOpen] = useState(false); const [deptModalOpen, setDeptModalOpen] = useState(false);
@ -318,6 +318,7 @@ function DepartmentPositionPage(props) {
</Form.Item>, </Form.Item>,
]} ]}
onFinish={() => fetchPositionData(1, 10)} onFinish={() => fetchPositionData(1, 10)}
onReset={() => fetchPositionData(1, 10)}
style={{ marginBottom: 16 }} style={{ marginBottom: 16 }}
/> />
<Table <Table
@ -547,6 +548,7 @@ function DeptFormModal({
setSubmitting(false); setSubmitting(false);
} }
}; };
return ( return (
<Modal <Modal
open={open} open={open}
@ -559,23 +561,25 @@ function DeptFormModal({
onOk={form.submit} onOk={form.submit}
> >
<Form form={form} layout="vertical" onFinish={handleSubmit}> <Form form={form} layout="vertical" onFinish={handleSubmit}>
<Form.Item {!currentId && (
name="parentId" <Form.Item
label="上级部门" name="parentId"
initialValue={selectedDeptId} label="上级部门"
> initialValue={selectedDeptId}
<TreeSelect >
treeData={treeData} <TreeSelect
allowClear treeData={treeData}
fieldNames={{ allowClear
label: "deptName", fieldNames={{
value: "id", label: "deptName",
children: "children", value: "id",
}} children: "children",
showSearch }}
placeholder="请选择上级部门" showSearch
/> placeholder="请选择上级部门"
</Form.Item> />
</Form.Item>
)}
<Form.Item <Form.Item
name="deptName" name="deptName"
label="部门名称" label="部门名称"

View File

@ -1,8 +1,13 @@
import { Button, Descriptions, Modal, Table, Upload } from "antd"; import { Button, Descriptions, Image, Modal, Table, Upload } from "antd";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import FilePreviewModal, { FilePreviewContent } from "~/components/FilePreviewModal"; import FilePreviewModal, {
FilePreviewContent,
} from "~/components/FilePreviewModal";
import { resolvePreviewSrc } from "~/components/CertPreviewImg"; import { resolvePreviewSrc } from "~/components/CertPreviewImg";
import { fetchStaffCertDetail, fetchStaffCertListByPersonnelId } from "~/api/staffCertificate"; import {
fetchStaffCertDetail,
fetchStaffCertListByPersonnelId,
} from "~/api/staffCertificate";
import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper"; import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper";
const GENDER_MAP = { 1: "男", 2: "女" }; const GENDER_MAP = { 1: "男", 2: "女" };
@ -41,26 +46,30 @@ export default function StaffViewModal({
const loadCertList = requestCertListRef.current; const loadCertList = requestCertListRef.current;
Promise.all([ Promise.all([
Promise.resolve(requestDetailsRef.current({ id: currentId })).catch((err) => { Promise.resolve(requestDetailsRef.current({ id: currentId })).catch(
console.warn("[StaffViewModal] load detail failed:", err); (err) => {
return { data: {} }; console.warn("[StaffViewModal] load detail failed:", err);
}), return { data: {} };
},
),
typeof loadCertList === "function" typeof loadCertList === "function"
? Promise.resolve(loadCertList(currentId)).catch((err) => { ? Promise.resolve(loadCertList(currentId)).catch((err) => {
console.warn("[StaffViewModal] load certificates failed:", err); console.warn("[StaffViewModal] load certificates failed:", err);
return []; return [];
}) })
: Promise.resolve([]), : Promise.resolve([]),
]).then(([detailRes, certList]) => { ])
if (!cancelled) { .then(([detailRes, certList]) => {
setInfo(detailRes?.data || {}); if (!cancelled) {
setCertificates(Array.isArray(certList) ? certList : []); setInfo(detailRes?.data || {});
} setCertificates(Array.isArray(certList) ? certList : []);
}).finally(() => { }
if (!cancelled) { })
setDetailLoading(false); .finally(() => {
} if (!cancelled) {
}); setDetailLoading(false);
}
});
return () => { return () => {
cancelled = true; cancelled = true;
}; };
@ -85,14 +94,18 @@ export default function StaffViewModal({
} }
}; };
const proofMaterialUrl = info.proofMaterialUrl
? JSON.parse(info.proofMaterialUrl)
: [];
const proofMaterialUrl= info.proofMaterialUrl? JSON.parse(info.proofMaterialUrl) : [];
const certPreviewFiles = certPreviewInfo?.certImgs?.length const certPreviewFiles = certPreviewInfo?.certImgs?.length
? certPreviewInfo.certImgs ? certPreviewInfo.certImgs
: certPreviewInfo?.certImgFiles || []; : certPreviewInfo?.certImgFiles || [];
const certPreviewUrl = resolvePreviewSrc(certPreviewFiles[0]); const certPreviewUrl = resolvePreviewSrc(certPreviewFiles[0]);
const certPreviewName = certPreviewFiles[0]?.fileName || certPreviewFiles[0]?.name || certPreviewInfo?.certName; const certPreviewName =
certPreviewFiles[0]?.fileName ||
certPreviewFiles[0]?.name ||
certPreviewInfo?.certName;
return ( return (
<> <>
@ -108,28 +121,57 @@ export default function StaffViewModal({
> >
<Descriptions bordered column={2} labelStyle={{ width: 120 }}> <Descriptions bordered column={2} labelStyle={{ width: 120 }}>
<Descriptions.Item label="姓名">{info.userName}</Descriptions.Item> <Descriptions.Item label="姓名">{info.userName}</Descriptions.Item>
<Descriptions.Item label="性别">{GENDER_MAP[info.genderCode]}</Descriptions.Item> <Descriptions.Item label="性别">
<Descriptions.Item label="出生日期">{info.birthDate}</Descriptions.Item> {GENDER_MAP[info.genderCode]}
</Descriptions.Item>
<Descriptions.Item label="出生日期">
{info.birthDate}
</Descriptions.Item>
<Descriptions.Item label="账号">{info.account}</Descriptions.Item> <Descriptions.Item label="账号">{info.account}</Descriptions.Item>
<Descriptions.Item label="部门">{info.deptName}</Descriptions.Item> <Descriptions.Item label="部门">{info.deptName}</Descriptions.Item>
<Descriptions.Item label="岗位">{info.postName}</Descriptions.Item> <Descriptions.Item label="岗位">{info.postName}</Descriptions.Item>
<Descriptions.Item label="人员类型">{info.personType || "基础人员"}</Descriptions.Item> <Descriptions.Item label="人员类型">
<Descriptions.Item label="资质范围">{info.qualScope || "-"}</Descriptions.Item> {info.personType || "基础人员"}
<Descriptions.Item label="职业等级">{info.professionalLevelName || "-"}</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="证书编号">{info.evaluatorCertNo || "-"}</Descriptions.Item> <Descriptions.Item label="资质范围">
<Descriptions.Item label="学历类型">{info.educationTypeName || "-"}</Descriptions.Item> {info.qualScope || "-"}
<Descriptions.Item label="学历层次">{info.educationLevelName || "-"}</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="职称">{info.titleName || "-"}</Descriptions.Item> <Descriptions.Item label="职业等级">
{info.professionalLevelName || "-"}
</Descriptions.Item>
<Descriptions.Item label="证书编号">
{info.evaluatorCertNo || "-"}
</Descriptions.Item>
<Descriptions.Item label="学历类型">
{info.educationTypeName || "-"}
</Descriptions.Item>
<Descriptions.Item label="学历层次">
{info.educationLevelName || "-"}
</Descriptions.Item>
<Descriptions.Item label="职称">
{info.titleName || "-"}
</Descriptions.Item>
<Descriptions.Item label="是否注册安全工程师"> <Descriptions.Item label="是否注册安全工程师">
{REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"} {REGISTER_ENGINEER_MAP[info.registerEngineerFlag] ?? "-"}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="身份证号">{info.idCardNo}</Descriptions.Item> <Descriptions.Item label="身份证号">
{info.idCardNo}
<Descriptions.Item label="现住地址" span={2}>{info.currentAddress}</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="办公地址" span={2}>{info.officeAddress}</Descriptions.Item>
<Descriptions.Item label="毕业院校">{info.graduateSchool}</Descriptions.Item> <Descriptions.Item label="现住地址" span={2}>
{info.currentAddress}
</Descriptions.Item>
<Descriptions.Item label="办公地址" span={2}>
{info.officeAddress}
</Descriptions.Item>
<Descriptions.Item label="毕业院校">
{info.graduateSchool}
</Descriptions.Item>
<Descriptions.Item label="专业">{info.major}</Descriptions.Item> <Descriptions.Item label="专业">{info.major}</Descriptions.Item>
<Descriptions.Item label="出版学术专著、专利、获奖、发表学术论文等" span={2}> <Descriptions.Item
label="出版学术专著、专利、获奖、发表学术论文等"
span={2}
>
{info.publications || "-"} {info.publications || "-"}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="自我申报的专业能力及认定方式" span={2}> <Descriptions.Item label="自我申报的专业能力及认定方式" span={2}>
@ -139,18 +181,32 @@ export default function StaffViewModal({
{info.workExperience || "-"} {info.workExperience || "-"}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="申报专业能力证明材料" span={2}> <Descriptions.Item label="申报专业能力证明材料" span={2}>
{proofMaterialUrl.length ? proofMaterialUrl.map((item) => ( {proofMaterialUrl.length
<div key={item.id}> ? proofMaterialUrl.map((item) => {
<a href={item.url} target="_blank" rel="noopener noreferrer"> const isImage = /\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i.test(item.url);
{item.fileName || item.name || item.url} return (
</a> <div key={item.id}>
</div> {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> <div style={{ marginTop: 16, marginBottom: 8, fontWeight: 600 }}>
证照信息
</div>
<Table <Table
size="small" size="small"
bordered bordered
@ -169,7 +225,13 @@ export default function StaffViewModal({
title: "操作", title: "操作",
width: 90, width: 90,
render: (_, record) => ( render: (_, record) => (
<Button type="link" size="small" onClick={() => openCertPreview(record)}>查看证书</Button> <Button
type="link"
size="small"
onClick={() => openCertPreview(record)}
>
查看证书
</Button>
), ),
}, },
]} ]}
@ -192,7 +254,9 @@ export default function StaffViewModal({
loading={certPreviewLoading} loading={certPreviewLoading}
cancelText="关闭" cancelText="关闭"
okText={certPreviewUrl ? "新窗口打开" : "关闭"} okText={certPreviewUrl ? "新窗口打开" : "关闭"}
okButtonProps={{ style: certPreviewUrl ? undefined : { display: "none" } }} okButtonProps={{
style: certPreviewUrl ? undefined : { display: "none" },
}}
onCancel={() => { onCancel={() => {
setCertPreview(null); setCertPreview(null);
setCertPreviewInfo(null); setCertPreviewInfo(null);
@ -207,18 +271,38 @@ export default function StaffViewModal({
> >
{certPreviewInfo && ( {certPreviewInfo && (
<div> <div>
<Descriptions bordered column={1} size="small" style={{ marginBottom: 12 }}> <Descriptions
<Descriptions.Item label="证照名称">{certPreviewInfo.certName}</Descriptions.Item> bordered
<Descriptions.Item label="证书编号">{certPreviewInfo.certNo}</Descriptions.Item> column={1}
<Descriptions.Item label="证书类别">{certPreviewInfo.certCategory || "-"}</Descriptions.Item> size="small"
<Descriptions.Item label="发证机关">{certPreviewInfo.issueOrg || "-"}</Descriptions.Item> style={{ marginBottom: 12 }}
<Descriptions.Item label="有效开始日期">{certPreviewInfo.validStartDate || "-"}</Descriptions.Item> >
<Descriptions.Item label="有效结束日期">{certPreviewInfo.validEndDate || "-"}</Descriptions.Item> <Descriptions.Item label="证照名称">
{certPreviewInfo.certName}
</Descriptions.Item>
<Descriptions.Item label="证书编号">
{certPreviewInfo.certNo}
</Descriptions.Item>
<Descriptions.Item label="证书类别">
{certPreviewInfo.certCategory || "-"}
</Descriptions.Item>
<Descriptions.Item label="发证机关">
{certPreviewInfo.issueOrg || "-"}
</Descriptions.Item>
<Descriptions.Item label="有效开始日期">
{certPreviewInfo.validStartDate || "-"}
</Descriptions.Item>
<Descriptions.Item label="有效结束日期">
{certPreviewInfo.validEndDate || "-"}
</Descriptions.Item>
</Descriptions> </Descriptions>
<FilePreviewContent url={certPreviewUrl} fileName={certPreviewName} /> <FilePreviewContent
url={certPreviewUrl}
fileName={certPreviewName}
/>
</div> </div>
)} )}
</Modal> </Modal>
</> </>
); );
} }