344 lines
11 KiB
JavaScript
344 lines
11 KiB
JavaScript
|
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||
|
|
import { Button, Descriptions, Form, message, Modal, Space } from "antd";
|
||
|
|
import { useEffect, useState } from "react";
|
||
|
|
import FormBuilder from "zy-react-library/components/FormBuilder";
|
||
|
|
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
||
|
|
import Page from "zy-react-library/components/Page";
|
||
|
|
import PreviewImg from "zy-react-library/components/PreviewImg";
|
||
|
|
import Search from "zy-react-library/components/Search";
|
||
|
|
import Table from "zy-react-library/components/Table";
|
||
|
|
import Upload from "zy-react-library/components/Upload";
|
||
|
|
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||
|
|
import useGetFile from "zy-react-library/hooks/useGetFile";
|
||
|
|
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||
|
|
import useTable from "zy-react-library/hooks/useTable";
|
||
|
|
import { NS_STAFF_CERTIFICATE } from "~/enumerate/namespace";
|
||
|
|
import { safeGetFiles, safeListRequest, safeRequest } from "~/utils";
|
||
|
|
import { mockUploadFileList, resolveUploadFileId } from "~/utils/mockUpload";
|
||
|
|
import { dateRangeRule } from "~/utils/validators";
|
||
|
|
import PageHeader from "../../components/PageHeader";
|
||
|
|
|
||
|
|
function StaffCertificatePage(props) {
|
||
|
|
const query = useGetUrlQuery();
|
||
|
|
const staffId = query.staffId;
|
||
|
|
const staffName = query.staffName;
|
||
|
|
const [addModalOpen, setAddModalOpen] = useState(false);
|
||
|
|
const [viewModalOpen, setViewModalOpen] = useState(false);
|
||
|
|
const [currentId, setCurrentId] = useState("");
|
||
|
|
const [form] = Form.useForm();
|
||
|
|
|
||
|
|
const { tableProps, getData } = useTable(safeListRequest(props.staffCertificateList), {
|
||
|
|
form,
|
||
|
|
transform: (formData) => ({
|
||
|
|
...formData,
|
||
|
|
eqStaffId: staffId,
|
||
|
|
}),
|
||
|
|
});
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (staffId) {
|
||
|
|
getData();
|
||
|
|
}
|
||
|
|
}, [staffId]);
|
||
|
|
|
||
|
|
const goBack = () => {
|
||
|
|
window.location.href = window.location.pathname.replace(/\/Certificate.*$/, "/List");
|
||
|
|
};
|
||
|
|
|
||
|
|
const onDelete = (id) => {
|
||
|
|
Modal.confirm({
|
||
|
|
title: "提示",
|
||
|
|
content: "数据将会删除,您是否确认删除?",
|
||
|
|
okText: "是",
|
||
|
|
cancelText: "否",
|
||
|
|
onOk: async () => {
|
||
|
|
const res = await props.staffCertificateRemove({ id });
|
||
|
|
if (res?.success !== false) {
|
||
|
|
message.success("删除成功");
|
||
|
|
getData();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Page isShowAllAction={false}>
|
||
|
|
<PageHeader title={`人员证书 - ${staffName || ""}`} />
|
||
|
|
<Button style={{ marginBottom: 16 }} onClick={goBack}>返回</Button>
|
||
|
|
<Search
|
||
|
|
form={form}
|
||
|
|
options={[
|
||
|
|
{ name: "likeCertNo", label: "证书编号", placeholder: "请输入证书编号" },
|
||
|
|
{ name: "certCategory", label: "证书类别" },
|
||
|
|
{ name: "certWorkCategory", label: "证书作业类别" },
|
||
|
|
]}
|
||
|
|
onFinish={getData}
|
||
|
|
/>
|
||
|
|
<Table
|
||
|
|
toolBarRender={() => (
|
||
|
|
<Button
|
||
|
|
type="primary"
|
||
|
|
icon={<AddIcon />}
|
||
|
|
onClick={() => {
|
||
|
|
setCurrentId("");
|
||
|
|
setAddModalOpen(true);
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
添加证书
|
||
|
|
</Button>
|
||
|
|
)}
|
||
|
|
columns={[
|
||
|
|
{ title: "证书类型", dataIndex: "certCategory" },
|
||
|
|
{ title: "证书作业类别", dataIndex: "certWorkCategory" },
|
||
|
|
{ title: "证书编号", dataIndex: "certNo" },
|
||
|
|
{
|
||
|
|
title: "操作",
|
||
|
|
width: 200,
|
||
|
|
render: (_, record) => (
|
||
|
|
<Space>
|
||
|
|
<Button type="link" onClick={() => { setCurrentId(record.id); setViewModalOpen(true); }}>
|
||
|
|
查看
|
||
|
|
</Button>
|
||
|
|
<Button type="link" onClick={() => { setCurrentId(record.id); setAddModalOpen(true); }}>
|
||
|
|
编辑
|
||
|
|
</Button>
|
||
|
|
<Button danger type="link" onClick={() => onDelete(record.id)}>删除</Button>
|
||
|
|
</Space>
|
||
|
|
),
|
||
|
|
},
|
||
|
|
]}
|
||
|
|
{...tableProps}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{addModalOpen && (
|
||
|
|
<CertModal
|
||
|
|
open={addModalOpen}
|
||
|
|
staffId={staffId}
|
||
|
|
currentId={currentId}
|
||
|
|
requestAdd={props.staffCertificateAdd}
|
||
|
|
requestEdit={props.staffCertificateEdit}
|
||
|
|
requestDetails={props.staffCertificateInfo}
|
||
|
|
onCancel={() => {
|
||
|
|
setAddModalOpen(false);
|
||
|
|
setCurrentId("");
|
||
|
|
}}
|
||
|
|
onSuccess={getData}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
{viewModalOpen && (
|
||
|
|
<ViewModal
|
||
|
|
open={viewModalOpen}
|
||
|
|
currentId={currentId}
|
||
|
|
requestDetails={props.staffCertificateInfo}
|
||
|
|
onCancel={() => {
|
||
|
|
setViewModalOpen(false);
|
||
|
|
setCurrentId("");
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</Page>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function CertModal({
|
||
|
|
open, staffId, currentId, requestAdd, requestEdit, requestDetails, onCancel, onSuccess,
|
||
|
|
}) {
|
||
|
|
const [form] = Form.useForm();
|
||
|
|
const [submitting, setSubmitting] = useState(false);
|
||
|
|
const [detailLoading, setDetailLoading] = useState(false);
|
||
|
|
const { getFile } = useGetFile();
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!open) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!currentId) {
|
||
|
|
form.resetFields();
|
||
|
|
form.setFieldsValue({ certImgs: mockUploadFileList("证书附件.jpg") });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let cancelled = false;
|
||
|
|
(async () => {
|
||
|
|
setDetailLoading(true);
|
||
|
|
try {
|
||
|
|
const res = await safeRequest(requestDetails, { id: currentId });
|
||
|
|
if (cancelled || !res?.data) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const data = { ...res.data };
|
||
|
|
data.validDate = [data.validStartDate, data.validEndDate];
|
||
|
|
data.certImgs = data.certImgFiles?.length ? data.certImgFiles : mockUploadFileList("证书附件.jpg");
|
||
|
|
form.setFieldsValue(data);
|
||
|
|
setDetailLoading(false);
|
||
|
|
|
||
|
|
const files = await safeGetFiles(
|
||
|
|
getFile,
|
||
|
|
{ eqType: "staff_cert", eqForeignKey: data.id },
|
||
|
|
data.certImgFiles || [],
|
||
|
|
);
|
||
|
|
if (!cancelled && files.length) {
|
||
|
|
form.setFieldValue("certImgs", files);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (err) {
|
||
|
|
console.warn("[StaffCertificate] load detail failed:", err);
|
||
|
|
}
|
||
|
|
finally {
|
||
|
|
if (!cancelled) {
|
||
|
|
setDetailLoading(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})();
|
||
|
|
return () => {
|
||
|
|
cancelled = true;
|
||
|
|
};
|
||
|
|
}, [open, currentId]);
|
||
|
|
|
||
|
|
const handleCancel = () => {
|
||
|
|
form.resetFields();
|
||
|
|
onCancel();
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleSubmit = async (values) => {
|
||
|
|
try {
|
||
|
|
setSubmitting(true);
|
||
|
|
values.validStartDate = values.validDate?.[0];
|
||
|
|
values.validEndDate = values.validDate?.[1];
|
||
|
|
values.staffId = staffId;
|
||
|
|
values.certAttachmentUrl = resolveUploadFileId(values.certImgs);
|
||
|
|
const request = currentId ? requestEdit : requestAdd;
|
||
|
|
if (currentId) {
|
||
|
|
values.id = currentId;
|
||
|
|
}
|
||
|
|
const res = await request(values);
|
||
|
|
if (res?.success !== false) {
|
||
|
|
message.success(currentId ? "编辑成功" : "添加成功");
|
||
|
|
handleCancel();
|
||
|
|
onSuccess();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
finally {
|
||
|
|
setSubmitting(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Modal
|
||
|
|
open={open}
|
||
|
|
destroyOnClose
|
||
|
|
title={currentId ? "编辑证书" : "添加证书"}
|
||
|
|
width={800}
|
||
|
|
loading={detailLoading}
|
||
|
|
confirmLoading={submitting}
|
||
|
|
onCancel={handleCancel}
|
||
|
|
onOk={form.submit}
|
||
|
|
>
|
||
|
|
<FormBuilder
|
||
|
|
form={form}
|
||
|
|
span={24}
|
||
|
|
showActionButtons={false}
|
||
|
|
onFinish={handleSubmit}
|
||
|
|
options={[
|
||
|
|
{ name: "certName", label: "证照名称", rules: [{ required: true, message: "请输入证照名称" }] },
|
||
|
|
{ name: "certCategory", label: "证书类别", rules: [{ required: true, message: "请选择证书类别" }] },
|
||
|
|
{ name: "certWorkCategory", label: "证书作业类别" },
|
||
|
|
{ name: "certNo", label: "证书编号", rules: [{ required: true, message: "请输入证书编号" }] },
|
||
|
|
{ name: "issueOrg", label: "发证机关", rules: [{ required: true, message: "请输入发证机关" }] },
|
||
|
|
{
|
||
|
|
name: "validDate",
|
||
|
|
label: "证书有效开始/结束日期",
|
||
|
|
render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
|
||
|
|
rules: [{ required: true, message: "请选择证书有效期" }, dateRangeRule()],
|
||
|
|
},
|
||
|
|
{ name: "reviewDate", label: "复合日期", render: FORM_ITEM_RENDER_ENUM.DATE },
|
||
|
|
{
|
||
|
|
name: "certImgs",
|
||
|
|
label: "证书附件",
|
||
|
|
render: (
|
||
|
|
<Upload
|
||
|
|
maxCount={3}
|
||
|
|
onGetRemoveFile={(file) => setDeleteFiles(prev => [...prev, file])}
|
||
|
|
/>
|
||
|
|
),
|
||
|
|
},
|
||
|
|
]}
|
||
|
|
labelCol={{ span: 24 }}
|
||
|
|
wrapperCol={{ span: 24 }}
|
||
|
|
/>
|
||
|
|
</Modal>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function ViewModal({ open, currentId, requestDetails, onCancel }) {
|
||
|
|
const [info, setInfo] = useState({});
|
||
|
|
const [detailLoading, setDetailLoading] = useState(false);
|
||
|
|
const { getFile } = useGetFile();
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!open || !currentId) {
|
||
|
|
setInfo({});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let cancelled = false;
|
||
|
|
(async () => {
|
||
|
|
setDetailLoading(true);
|
||
|
|
try {
|
||
|
|
const res = await safeRequest(requestDetails, { id: currentId });
|
||
|
|
if (cancelled || !res?.data) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const data = { ...res.data };
|
||
|
|
data.certImgs = data.certImgFiles || [];
|
||
|
|
setInfo(data);
|
||
|
|
setDetailLoading(false);
|
||
|
|
|
||
|
|
const files = await safeGetFiles(
|
||
|
|
getFile,
|
||
|
|
{ eqType: "staff_cert", eqForeignKey: data.id },
|
||
|
|
data.certImgFiles || [],
|
||
|
|
);
|
||
|
|
if (!cancelled && files.length) {
|
||
|
|
setInfo((prev) => ({ ...prev, certImgs: files }));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (err) {
|
||
|
|
console.warn("[StaffCertificate] load view failed:", err);
|
||
|
|
}
|
||
|
|
finally {
|
||
|
|
if (!cancelled) {
|
||
|
|
setDetailLoading(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})();
|
||
|
|
return () => {
|
||
|
|
cancelled = true;
|
||
|
|
};
|
||
|
|
}, [open, currentId]);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Modal
|
||
|
|
open={open}
|
||
|
|
destroyOnClose
|
||
|
|
title="证书详情"
|
||
|
|
width={800}
|
||
|
|
loading={detailLoading}
|
||
|
|
cancelText="返回"
|
||
|
|
okButtonProps={{ style: { display: "none" } }}
|
||
|
|
onCancel={onCancel}
|
||
|
|
>
|
||
|
|
<Descriptions bordered column={1} labelStyle={{ width: 160 }}>
|
||
|
|
<Descriptions.Item label="证照名称">{info.certName}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="证书类别">{info.certCategory}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="证书编号">{info.certNo}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="发证机关">{info.issueOrg}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="证书有效开始日期">{info.validStartDate}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="证书有效结束日期">{info.validEndDate}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="复合日期">{info.reviewDate}</Descriptions.Item>
|
||
|
|
<Descriptions.Item label="证书图片"><PreviewImg files={info.certImgs} /></Descriptions.Item>
|
||
|
|
</Descriptions>
|
||
|
|
</Modal>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export default Connect([NS_STAFF_CERTIFICATE], true)(StaffCertificatePage);
|