2026-06-23 18:07:30 +08:00
|
|
|
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
2026-06-30 18:30:30 +08:00
|
|
|
|
import { Button, Descriptions, Form, message, Modal, Table, Upload } from "antd";
|
2026-06-23 18:07:30 +08:00
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
|
import FormBuilder from "zy-react-library/components/FormBuilder";
|
|
|
|
|
|
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
2026-06-29 16:45:58 +08:00
|
|
|
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
2026-06-30 18:30:30 +08:00
|
|
|
|
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
|
|
|
|
|
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
|
|
|
|
|
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
|
|
|
|
|
|
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
|
|
|
|
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
2026-06-23 18:07:30 +08:00
|
|
|
|
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
|
|
|
|
|
import useGetFile from "zy-react-library/hooks/useGetFile";
|
2026-06-29 11:59:34 +08:00
|
|
|
|
import CertPreviewImg, { CertTooltipPreviewImg } from "~/components/CertPreviewImg";
|
2026-06-23 18:07:30 +08:00
|
|
|
|
import { NS_ORG_QUALIFICATION_CERT } from "~/enumerate/namespace";
|
2026-06-26 14:27:49 +08:00
|
|
|
|
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
|
|
|
|
|
|
import { formSelectField } from "~/utils/enterpriseForm";
|
|
|
|
|
|
import { isQualificationEnabled } from "~/api/enterpriseInfo/adapter";
|
2026-06-30 18:30:30 +08:00
|
|
|
|
import { safeGetFiles, safeRequest } from "~/utils";
|
2026-06-23 18:07:30 +08:00
|
|
|
|
import { toDayjs } from "~/utils/dateFormat";
|
|
|
|
|
|
import { mockUploadFileList, resolveUploadFileId } from "~/utils/mockUpload";
|
|
|
|
|
|
import { dateRangeRule } from "~/utils/validators";
|
|
|
|
|
|
|
2026-06-30 18:30:30 +08:00
|
|
|
|
const { router } = tools;
|
|
|
|
|
|
|
2026-06-23 18:07:30 +08:00
|
|
|
|
function QualificationCertPage(props) {
|
|
|
|
|
|
const [addModalOpen, setAddModalOpen] = useState(false);
|
|
|
|
|
|
const [viewModalOpen, setViewModalOpen] = useState(false);
|
|
|
|
|
|
const [currentId, setCurrentId] = useState("");
|
|
|
|
|
|
const [form] = Form.useForm();
|
2026-06-30 18:30:30 +08:00
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
const [dataSource, setDataSource] = useState([]);
|
|
|
|
|
|
const [total, setTotal] = useState(0);
|
|
|
|
|
|
|
|
|
|
|
|
const getData = async () => {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
try {
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
...router.query,
|
|
|
|
|
|
current: router.query.current || 1,
|
|
|
|
|
|
pageSize: router.query.pageSize || 10,
|
|
|
|
|
|
};
|
|
|
|
|
|
const res = await props.orgQualificationCertList(params);
|
|
|
|
|
|
if (res?.success !== false) {
|
|
|
|
|
|
setDataSource(res?.data?.records || res?.data || []);
|
|
|
|
|
|
setTotal(res?.data?.total || 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.warn("[QualificationCert] list failed:", err);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleReset = (values) => {
|
|
|
|
|
|
router.query = { ...router.query, ...values, current: 1, pageSize: 10 };
|
|
|
|
|
|
getData();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
form.setFieldsValue(router.query);
|
|
|
|
|
|
getData();
|
|
|
|
|
|
}, []);
|
2026-06-23 18:07:30 +08:00
|
|
|
|
|
|
|
|
|
|
const onDelete = (id) => {
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "数据将会删除,您是否确认删除?",
|
|
|
|
|
|
okText: "是",
|
|
|
|
|
|
cancelText: "否",
|
|
|
|
|
|
onOk: async () => {
|
|
|
|
|
|
const res = await props.orgQualificationCertRemove({ id });
|
|
|
|
|
|
if (res?.success !== false) {
|
|
|
|
|
|
message.success("删除成功");
|
|
|
|
|
|
getData();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onDisable = (id) => {
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "是否停用该证书?",
|
|
|
|
|
|
okText: "是",
|
|
|
|
|
|
cancelText: "否",
|
|
|
|
|
|
onOk: async () => {
|
|
|
|
|
|
const res = await props.orgQualificationCertDisable({ id });
|
|
|
|
|
|
if (res?.success !== false) {
|
|
|
|
|
|
message.success("操作成功");
|
2026-06-26 14:27:49 +08:00
|
|
|
|
await getData();
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} else {
|
2026-06-26 14:27:49 +08:00
|
|
|
|
message.error(res?.message || "操作失败");
|
2026-06-23 18:07:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onEnable = (id) => {
|
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "是否启用该证书?",
|
|
|
|
|
|
okText: "是",
|
|
|
|
|
|
cancelText: "否",
|
|
|
|
|
|
onOk: async () => {
|
|
|
|
|
|
const res = await props.orgQualificationCertEnable({ id });
|
|
|
|
|
|
if (res?.success !== false) {
|
|
|
|
|
|
message.success("操作成功");
|
2026-06-26 14:27:49 +08:00
|
|
|
|
await getData();
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} else {
|
2026-06-26 14:27:49 +08:00
|
|
|
|
message.error(res?.message || "操作失败");
|
2026-06-23 18:07:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2026-06-30 18:30:30 +08:00
|
|
|
|
<PageLayout
|
|
|
|
|
|
title={
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span>安全评价资质证书管理</span>
|
|
|
|
|
|
<div className="pageLayout-extra">
|
|
|
|
|
|
机构需将自身拥有的安全评价资质证书信息录入系统,包括资质等级、发证机关、发证日期、有效期等。
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
}
|
|
|
|
|
|
>
|
|
|
|
|
|
<SearchForm
|
|
|
|
|
|
style={{ marginBottom: 24 }}
|
2026-06-23 18:07:30 +08:00
|
|
|
|
form={form}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
loading={loading}
|
|
|
|
|
|
formLine={[
|
|
|
|
|
|
<Form.Item key="likeCertName" name="likeCertName">
|
|
|
|
|
|
<ControlWrapper.Input label="证书名称" placeholder="请输入证书名称" allowClear />
|
|
|
|
|
|
</Form.Item>,
|
|
|
|
|
|
<Form.Item key="validDate" name="validDate">
|
|
|
|
|
|
<ControlWrapper.DatePicker.RangePicker label="证书有效期" />
|
|
|
|
|
|
</Form.Item>,
|
2026-06-23 18:07:30 +08:00
|
|
|
|
]}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
onReset={handleReset}
|
|
|
|
|
|
onFinish={(values) => {
|
|
|
|
|
|
router.query = {
|
|
|
|
|
|
...router.query,
|
|
|
|
|
|
...values,
|
|
|
|
|
|
current: 1,
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
};
|
|
|
|
|
|
getData();
|
|
|
|
|
|
}}
|
2026-06-23 18:07:30 +08:00
|
|
|
|
/>
|
2026-06-30 18:30:30 +08:00
|
|
|
|
|
|
|
|
|
|
<div style={{ marginBottom: 16, display: "flex", justifyContent: "flex-end" }}>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
icon={<AddIcon />}
|
|
|
|
|
|
onClick={() => {
|
|
|
|
|
|
setCurrentId("");
|
|
|
|
|
|
setAddModalOpen(true);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
新增证书
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-06-23 18:07:30 +08:00
|
|
|
|
<Table
|
2026-06-30 18:30:30 +08:00
|
|
|
|
rowKey="id"
|
2026-06-23 18:07:30 +08:00
|
|
|
|
columns={[
|
|
|
|
|
|
{ title: "证照类别", dataIndex: "certType" },
|
|
|
|
|
|
{ title: "证书名称", dataIndex: "certName" },
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "证书有效期",
|
|
|
|
|
|
width: 220,
|
|
|
|
|
|
render: (_, record) => `${record.validStartDate ?? ""} ~ ${record.validEndDate ?? ""}`,
|
|
|
|
|
|
},
|
|
|
|
|
|
{ title: "证书编号", dataIndex: "certNo" },
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "状态",
|
|
|
|
|
|
width: 80,
|
2026-06-26 14:27:49 +08:00
|
|
|
|
render: (_, record) => (isQualificationEnabled(record) ? "启用" : "禁用"),
|
2026-06-23 18:07:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "照片",
|
|
|
|
|
|
width: 100,
|
2026-06-30 18:30:30 +08:00
|
|
|
|
render: (_, record) =>
|
|
|
|
|
|
record.certImgFiles?.length ? <CertTooltipPreviewImg files={record.certImgFiles} /> : <span>无</span>,
|
2026-06-23 18:07:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "操作",
|
2026-06-30 18:30:30 +08:00
|
|
|
|
width: 200,
|
|
|
|
|
|
fixed: "right",
|
2026-06-23 18:07:30 +08:00
|
|
|
|
render: (_, record) => (
|
2026-06-30 18:30:30 +08:00
|
|
|
|
<TableAction>
|
2026-06-23 18:07:30 +08:00
|
|
|
|
<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>
|
2026-06-26 14:27:49 +08:00
|
|
|
|
{isQualificationEnabled(record) ? (
|
2026-06-23 18:07:30 +08:00
|
|
|
|
<Button type="link" onClick={() => onDisable(record.id)}>
|
|
|
|
|
|
禁用
|
|
|
|
|
|
</Button>
|
2026-06-26 14:27:49 +08:00
|
|
|
|
) : (
|
|
|
|
|
|
<Button type="link" onClick={() => onEnable(record.id)}>
|
|
|
|
|
|
启用
|
|
|
|
|
|
</Button>
|
2026-06-23 18:07:30 +08:00
|
|
|
|
)}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
</TableAction>
|
2026-06-23 18:07:30 +08:00
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
dataSource={dataSource}
|
|
|
|
|
|
scroll={{ y: props.scrollY }}
|
|
|
|
|
|
loading={loading}
|
|
|
|
|
|
pagination={{
|
|
|
|
|
|
total,
|
|
|
|
|
|
showSizeChanger: true,
|
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
|
showTotal: (t) => `共 ${t} 条`,
|
|
|
|
|
|
current: router.query.current || 1,
|
|
|
|
|
|
pageSize: router.query.pageSize || 10,
|
|
|
|
|
|
onChange: (page, pageSize) => {
|
|
|
|
|
|
router.query = { ...router.query, current: page, pageSize };
|
|
|
|
|
|
getData();
|
|
|
|
|
|
},
|
|
|
|
|
|
}}
|
2026-06-23 18:07:30 +08:00
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{addModalOpen && (
|
|
|
|
|
|
<CertFormModal
|
|
|
|
|
|
open={addModalOpen}
|
|
|
|
|
|
currentId={currentId}
|
|
|
|
|
|
requestAdd={props.orgQualificationCertAdd}
|
|
|
|
|
|
requestEdit={props.orgQualificationCertEdit}
|
|
|
|
|
|
requestDetails={props.orgQualificationCertInfo}
|
|
|
|
|
|
onCancel={() => {
|
|
|
|
|
|
setAddModalOpen(false);
|
|
|
|
|
|
setCurrentId("");
|
|
|
|
|
|
}}
|
|
|
|
|
|
onSuccess={getData}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{viewModalOpen && (
|
|
|
|
|
|
<CertViewModal
|
|
|
|
|
|
open={viewModalOpen}
|
|
|
|
|
|
currentId={currentId}
|
|
|
|
|
|
requestDetails={props.orgQualificationCertInfo}
|
|
|
|
|
|
onCancel={() => {
|
|
|
|
|
|
setViewModalOpen(false);
|
|
|
|
|
|
setCurrentId("");
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
2026-06-29 16:45:58 +08:00
|
|
|
|
</PageLayout>
|
2026-06-23 18:07:30 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function CertFormModal({
|
|
|
|
|
|
open,
|
|
|
|
|
|
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.issueDate = toDayjs(data.issueDate);
|
|
|
|
|
|
data.validDate = [toDayjs(data.validStartDate), toDayjs(data.validEndDate)];
|
|
|
|
|
|
data.certImgs = data.certImgFiles?.length ? data.certImgFiles : mockUploadFileList("证书图片.jpg");
|
|
|
|
|
|
form.setFieldsValue(data);
|
|
|
|
|
|
setDetailLoading(false);
|
|
|
|
|
|
|
|
|
|
|
|
const files = await safeGetFiles(
|
|
|
|
|
|
getFile,
|
|
|
|
|
|
{ eqType: "org_cert", eqForeignKey: data.id },
|
|
|
|
|
|
data.certImgFiles || [],
|
|
|
|
|
|
);
|
|
|
|
|
|
if (!cancelled && files.length) {
|
|
|
|
|
|
form.setFieldValue("certImgs", files);
|
|
|
|
|
|
}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} catch (err) {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
console.warn("[QualificationCert] load detail failed:", err);
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} finally {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
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.certImageUrl = resolveUploadFileId(values.certImgs);
|
|
|
|
|
|
if (currentId) {
|
|
|
|
|
|
values.id = currentId;
|
|
|
|
|
|
}
|
|
|
|
|
|
const request = currentId ? requestEdit : requestAdd;
|
|
|
|
|
|
const res = await request(values);
|
|
|
|
|
|
if (res?.success !== false) {
|
|
|
|
|
|
message.success(currentId ? "编辑成功" : "添加成功");
|
|
|
|
|
|
handleCancel();
|
|
|
|
|
|
onSuccess();
|
|
|
|
|
|
}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} finally {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
setSubmitting(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Modal
|
|
|
|
|
|
open={open}
|
|
|
|
|
|
destroyOnClose
|
|
|
|
|
|
maskClosable={false}
|
|
|
|
|
|
title={currentId ? "编辑证书" : "添加证书"}
|
|
|
|
|
|
width={800}
|
|
|
|
|
|
loading={detailLoading}
|
|
|
|
|
|
confirmLoading={submitting}
|
|
|
|
|
|
onOk={form.submit}
|
|
|
|
|
|
onCancel={handleCancel}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div style={{ color: "#999", marginBottom: 16, fontSize: 12 }}>
|
|
|
|
|
|
严谨在本互联网非涉密平台处理、传输国家秘密和工作秘密,请确认扫描、传输的文件资料不涉及国家秘密和工作秘密
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<FormBuilder
|
|
|
|
|
|
form={form}
|
|
|
|
|
|
span={24}
|
|
|
|
|
|
showActionButtons={false}
|
|
|
|
|
|
onFinish={handleSubmit}
|
|
|
|
|
|
options={[
|
2026-06-26 14:27:49 +08:00
|
|
|
|
formSelectField("certType", "证照类型", QUALIFICATION_INDUSTRY_OPTIONS, {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
rules: [{ required: true, message: "请选择证照类型" }],
|
2026-06-26 14:27:49 +08:00
|
|
|
|
colProps: { span: 24 },
|
|
|
|
|
|
}),
|
2026-06-23 18:07:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
name: "certName",
|
|
|
|
|
|
label: "证书名称",
|
|
|
|
|
|
rules: [{ required: true, message: "请输入证书名称" }],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "certNo",
|
|
|
|
|
|
label: "证明编号",
|
|
|
|
|
|
rules: [{ required: true, message: "请输入证明编号" }],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "issueOrg",
|
|
|
|
|
|
label: "发证机关",
|
|
|
|
|
|
rules: [{ required: true, message: "请输入发证机关" }],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "issueDate",
|
|
|
|
|
|
label: "发证日期",
|
|
|
|
|
|
render: FORM_ITEM_RENDER_ENUM.DATE,
|
|
|
|
|
|
rules: [{ required: true, message: "请选择发证日期" }],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "validDate",
|
|
|
|
|
|
label: "证书有效期",
|
|
|
|
|
|
render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
|
|
|
|
|
|
rules: [{ required: true, message: "请选择证书有效期" }, dateRangeRule()],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "remark",
|
|
|
|
|
|
label: "备注",
|
|
|
|
|
|
required: false,
|
|
|
|
|
|
render: FORM_ITEM_RENDER_ENUM.TEXTAREA,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: "certImgs",
|
|
|
|
|
|
label: "证书图片",
|
|
|
|
|
|
rules: [{ required: true, message: "请上传证书图片" }],
|
2026-06-30 18:30:30 +08:00
|
|
|
|
render: <Upload maxCount={3} />,
|
2026-06-23 18:07:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
labelCol={{ span: 8 }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Modal>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function CertViewModal({ 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: "org_cert", eqForeignKey: data.id },
|
|
|
|
|
|
data.certImgFiles || [],
|
|
|
|
|
|
);
|
|
|
|
|
|
if (!cancelled && files.length) {
|
|
|
|
|
|
setInfo((prev) => ({ ...prev, certImgs: files }));
|
|
|
|
|
|
}
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} catch (err) {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
console.warn("[QualificationCert] load view failed:", err);
|
2026-06-30 18:30:30 +08:00
|
|
|
|
} finally {
|
2026-06-23 18:07:30 +08:00
|
|
|
|
if (!cancelled) {
|
|
|
|
|
|
setDetailLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})();
|
|
|
|
|
|
return () => {
|
|
|
|
|
|
cancelled = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
}, [open, currentId]);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Modal
|
|
|
|
|
|
open={open}
|
|
|
|
|
|
destroyOnClose
|
|
|
|
|
|
maskClosable={false}
|
|
|
|
|
|
title="证书详情"
|
|
|
|
|
|
width={800}
|
|
|
|
|
|
loading={detailLoading}
|
|
|
|
|
|
cancelText="返回"
|
|
|
|
|
|
okButtonProps={{ style: { display: "none" } }}
|
|
|
|
|
|
onCancel={onCancel}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Descriptions bordered column={1} labelStyle={{ width: 160 }}>
|
|
|
|
|
|
<Descriptions.Item label="证照类型">{info.certType}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="证书名称">{info.certName}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="证明编号">{info.certNo}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="发证机关">{info.issueOrg}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="发证日期">{info.issueDate}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="证书有效期">
|
|
|
|
|
|
{`${info.validStartDate ?? ""} ~ ${info.validEndDate ?? ""}`}
|
|
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="备注">{info.remark || "-"}</Descriptions.Item>
|
|
|
|
|
|
<Descriptions.Item label="证书图片">
|
2026-06-29 11:59:34 +08:00
|
|
|
|
<CertPreviewImg files={info.certImgs} />
|
2026-06-23 18:07:30 +08:00
|
|
|
|
</Descriptions.Item>
|
|
|
|
|
|
</Descriptions>
|
|
|
|
|
|
</Modal>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-30 18:30:30 +08:00
|
|
|
|
export default Connect([NS_ORG_QUALIFICATION_CERT], true)(AntdTableFuncControl(QualificationCertPage));
|