Compare commits

..

No commits in common. "4950605bffb7720bf649f8a6fb16f61ca9972db3" and "9073e492bcf26fa14e4dbdb37b981c5780fbf090" have entirely different histories.

5 changed files with 247 additions and 184 deletions

View File

@ -1,45 +1,54 @@
import { declareRequest } from "@cqsjjb/jjb-dva-runtime"; import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
import {
fromPageResponse,
fromQualificationForm,
fromSingleResponse,
toPageQuery,
toQualificationForm,
} from "../enterpriseInfo/adapter";
import { apiGet, apiPost, apiPostDelete, safeAction, safePageResult } from "../enterpriseInfo/http";
// 分页查询 export const orgQualificationCertList = declareRequest("orgQualificationCertLoading", safePageResult(async (params) => {
export const orgQualificationCertList = declareRequest( const query = toPageQuery(params, { likeCertName: "certName" });
"orgQualificationCertLoading", const res = await apiGet("/safetyEval/org-qualification/page", query);
"Get > /safetyEval/org-qualification/page", return fromPageResponse(res, toQualificationForm);
"orgQualificationCertList: [] | res.data?.records || res.data || [] & orgQualificationCertTotal: 0 | res.data?.total || 0", }));
);
// 新增 export const orgQualificationCertInfo = declareRequest("orgQualificationCertLoading", safeAction(async (params) => {
export const orgQualificationCertAdd = declareRequest( const res = await apiGet("/safetyEval/org-qualification/get", { id: params.id });
"orgQualificationCertLoading", return fromSingleResponse(res, toQualificationForm);
"Post > @/safetyEval/org-qualification/save", }));
);
// 查询详情 export const orgQualificationCertAdd = declareRequest("orgQualificationCertLoading", safeAction(async (values) => {
export const orgQualificationCertInfo = declareRequest( const res = await apiPost("/safetyEval/org-qualification/save", fromQualificationForm(values));
"orgQualificationCertLoading", return fromSingleResponse(res, toQualificationForm);
"Get > /safetyEval/org-qualification/get", }));
"orgQualificationCertDetail: {} | res.data || {}",
);
// 修改 export const orgQualificationCertEdit = declareRequest("orgQualificationCertLoading", safeAction(async (values) => {
export const orgQualificationCertEdit = declareRequest( const res = await apiPost("/safetyEval/org-qualification/modify", fromQualificationForm(values));
"orgQualificationCertLoading", return fromSingleResponse(res, toQualificationForm);
"Post > @/safetyEval/org-qualification/modify", }));
);
// 删除 export const orgQualificationCertRemove = declareRequest("orgQualificationCertLoading", safeAction(async ({ id }) => {
export const orgQualificationCertRemove = declareRequest( return apiPostDelete("/safetyEval/org-qualification/delete", id);
"orgQualificationCertLoading", }));
"Post > @/safetyEval/org-qualification/delete",
);
// 禁用 export const orgQualificationCertDisable = declareRequest("orgQualificationCertLoading", safeAction(async ({ id }) => {
export const orgQualificationCertDisable = declareRequest( const res = await apiGet("/safetyEval/org-qualification/get", { id });
"orgQualificationCertLoading", const data = res?.data || {};
"Post > @/safetyEval/org-qualification/disable", return apiPost("/safetyEval/org-qualification/modify", {
); ...data,
id,
enableFlag: 2,
});
}));
// 启用 export const orgQualificationCertEnable = declareRequest("orgQualificationCertLoading", safeAction(async ({ id }) => {
export const orgQualificationCertEnable = declareRequest( const res = await apiGet("/safetyEval/org-qualification/get", { id });
"orgQualificationCertLoading", const data = res?.data || {};
"Post > @/safetyEval/org-qualification/enable", return apiPost("/safetyEval/org-qualification/modify", {
); ...data,
id,
enableFlag: 1,
});
}));

View File

@ -1,8 +1,9 @@
import { Image, Tooltip, Tag } from "antd"; import { Image, Tooltip, Tag } from "antd";
import { getFileUrl } from "zy-react-library/utils";
/** 解析附件对象的可访问地址,兼容 filePath相对路径与 url绝对/相对) */ /** 解析附件对象的可访问地址,兼容 filePath相对路径与 url绝对/相对) */
export function resolvePreviewSrc(file = {}) { export function resolvePreviewSrc(file = {}) {
const base = window.fileUrl || ""; const base = getFileUrl?.() || window.fileUrl || "";
const path = file.filePath; const path = file.filePath;
const url = file.url; const url = file.url;
if (path) { if (path) {

View File

@ -26,7 +26,7 @@ import { NS_EQUIP_INFO } from "~/enumerate/namespace";
import { positiveNumberRule } from "~/utils/validators"; import { positiveNumberRule } from "~/utils/validators";
const { router } = tools; const { router } = tools;
const DUAL_CHANNEL_MAP = { 1: "是", 2: "否" }; const DUAL_CHANNEL_MAP = { 1: "是", 0: "否" };
function EquipInfoPage(props) { function EquipInfoPage(props) {
const [formModalOpen, setFormModalOpen] = useState(false); const [formModalOpen, setFormModalOpen] = useState(false);
@ -58,7 +58,7 @@ function EquipInfoPage(props) {
okText: "是", okText: "是",
cancelText: "否", cancelText: "否",
onOk: async () => { onOk: async () => {
const res = await props.equipInfoRemove({ data: id }); const res = await props.equipInfoRemove({ id });
if (res?.success !== false) { if (res?.success !== false) {
message.success("删除成功"); message.success("删除成功");
handleSearch(); handleSearch();
@ -111,7 +111,7 @@ function EquipInfoPage(props) {
form={searchForm} form={searchForm}
loading={loading} loading={loading}
formLine={[ formLine={[
<Form.Item key="likeDeviceName" name="deviceName"> <Form.Item key="likeDeviceName" name="likeDeviceName">
<ControlWrapper.Input <ControlWrapper.Input
label="设备名称" label="设备名称"
placeholder="请输入" placeholder="请输入"
@ -473,7 +473,7 @@ function EquipFormModal({
placeholder="请选择" placeholder="请选择"
options={[ options={[
{ label: "是", value: 1 }, { label: "是", value: 1 },
{ label: "否", value: 2 }, { label: "否", value: 0 },
]} ]}
/> />
</Form.Item> </Form.Item>

View File

@ -11,7 +11,6 @@ import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
import { tools } from "@cqsjjb/jjb-common-lib"; import { tools } from "@cqsjjb/jjb-common-lib";
import { NS_STAFF_CERTIFICATE } from "~/enumerate/namespace"; import { NS_STAFF_CERTIFICATE } from "~/enumerate/namespace";
import CertPreviewImg from "~/components/CertPreviewImg"; import CertPreviewImg from "~/components/CertPreviewImg";
import AttachmentUpload from "~/components/AttachmentUpload";
import { dateRangeRule } from "~/utils/validators"; import { dateRangeRule } from "~/utils/validators";
const { router } = tools; const { router } = tools;
@ -313,8 +312,26 @@ function CertModal({
<Form.Item name="reviewDate" label="复核日期"> <Form.Item name="reviewDate" label="复核日期">
<DatePicker style={{ width: "100%" }} /> <DatePicker style={{ width: "100%" }} />
</Form.Item> </Form.Item>
<AttachmentUpload name="certAttachmentUrl" label="证书附件" maxCount={3} /> <Form.Item
name="certAttachmentUrl"
label="证书附件"
valuePropName="fileList"
getValueFromEvent={(e) => {
if (Array.isArray(e)) return e;
return e?.fileList;
}}
>
<Upload
action="/api/upload"
maxCount={3}
fileList={uploadFileList}
onChange={(info) => {
setUploadFileList(info.fileList);
}}
>
<Button icon={<UploadOutlined />}>上传文件</Button>
</Upload>
</Form.Item>
</Form> </Form>
</Modal> </Modal>
); );

View File

@ -1,47 +1,37 @@
import { Connect } from "@cqsjjb/jjb-dva-runtime"; import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { import {
Button, Button,
DatePicker,
Descriptions, Descriptions,
Form, Form,
Image,
Input,
message, message,
Modal, Modal,
Select,
Table, Table,
Upload,
} from "antd"; } from "antd";
import AttachmentUpload from "~/components/AttachmentUpload";
import { PlusOutlined } from "@ant-design/icons";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import FormBuilder from "zy-react-library/components/FormBuilder";
import AddIcon from "zy-react-library/components/Icon/AddIcon";
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm"; import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper"; import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction"; import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction";
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd"; import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
import { tools } from "@cqsjjb/jjb-common-lib"; import { tools } from "@cqsjjb/jjb-common-lib";
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
import useGetFile from "zy-react-library/hooks/useGetFile";
import CertPreviewImg, {
CertTooltipPreviewImg,
} from "~/components/CertPreviewImg";
import { NS_ORG_QUALIFICATION_CERT } from "~/enumerate/namespace"; import { NS_ORG_QUALIFICATION_CERT } from "~/enumerate/namespace";
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions"; import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
import { formSelectField } from "~/utils/enterpriseForm";
import { isQualificationEnabled } from "~/api/enterpriseInfo/adapter";
import { safeGetFiles, safeRequest } from "~/utils";
import { toDayjs } from "~/utils/dateFormat"; import { toDayjs } from "~/utils/dateFormat";
import { mockUploadFileList, resolveUploadFileId } from "~/utils/mockUpload";
import { dateRangeRule } from "~/utils/validators"; import { dateRangeRule } from "~/utils/validators";
const { router } = tools; const { router } = tools;
const { TextArea } = Input;
const { RangePicker } = DatePicker;
/** certImageUrl逗号分隔URL↔ 文件列表({ url }[] */
function parseCertImageUrl(str) {
if (!str) return [];
return String(str).split(",").filter(Boolean).map((url, i) => ({
url: url.trim(),
name: `证书图片${i + 1}.jpg`,
}));
}
function stringifyCertImageUrl(files) {
if (!files?.length) return undefined;
return files.map((f) => f.url || f.response?.data?.url).filter(Boolean).join(",");
}
function QualificationCertPage(props) { function QualificationCertPage(props) {
const [addModalOpen, setAddModalOpen] = useState(false); const [addModalOpen, setAddModalOpen] = useState(false);
@ -62,8 +52,8 @@ function QualificationCertPage(props) {
}; };
const res = await props.orgQualificationCertList(params); const res = await props.orgQualificationCertList(params);
if (res?.success !== false) { if (res?.success !== false) {
setDataSource(res?.data || []); setDataSource(res?.data?.records || res?.data || []);
setTotal(res?.total || 0); setTotal(res?.data?.total || 0);
} }
} catch (err) { } catch (err) {
console.warn("[QualificationCert] list failed:", err); console.warn("[QualificationCert] list failed:", err);
@ -73,18 +63,12 @@ function QualificationCertPage(props) {
}; };
const handleReset = (values) => { const handleReset = (values) => {
router.query = { ...values, validStartDate: undefined, validEndDate: undefined, current: 1, pageSize: 10 }; router.query = { ...router.query, ...values, current: 1, pageSize: 10 };
getData(); getData();
}; };
useEffect(() => { useEffect(() => {
const params = { form.setFieldsValue(router.query);
...router.query
};
if (params.validStartDate && params.validEndDate) {
params.validDate = [toDayjs(params.validStartDate), toDayjs(params.validEndDate)];
}
form.setFieldsValue(params);
getData(); getData();
}, []); }, []);
@ -104,16 +88,32 @@ function QualificationCertPage(props) {
}); });
}; };
const onToggleStatus = (record) => { const onDisable = (id) => {
const enabled = record.enableFlag === 1;
Modal.confirm({ Modal.confirm({
title: "提示", title: "提示",
content: enabled ? "是否停用该证书?" : "是否启用该证书?", content: "是否停用该证书?",
okText: "是", okText: "是",
cancelText: "否", cancelText: "否",
onOk: async () => { onOk: async () => {
const action = enabled ? props.orgQualificationCertDisable : props.orgQualificationCertEnable; const res = await props.orgQualificationCertDisable({ id });
const res = await action({ id: record.id }); if (res?.success !== false) {
message.success("操作成功");
await getData();
} else {
message.error(res?.message || "操作失败");
}
},
});
};
const onEnable = (id) => {
Modal.confirm({
title: "提示",
content: "是否启用该证书?",
okText: "是",
cancelText: "否",
onOk: async () => {
const res = await props.orgQualificationCertEnable({ id });
if (res?.success !== false) { if (res?.success !== false) {
message.success("操作成功"); message.success("操作成功");
await getData(); await getData();
@ -137,7 +137,7 @@ function QualificationCertPage(props) {
extra={ extra={
<Button <Button
type="primary" type="primary"
icon={<PlusOutlined />} icon={<AddIcon />}
onClick={() => { onClick={() => {
setCurrentId(""); setCurrentId("");
setAddModalOpen(true); setAddModalOpen(true);
@ -165,12 +165,8 @@ function QualificationCertPage(props) {
]} ]}
onReset={handleReset} onReset={handleReset}
onFinish={(values) => { onFinish={(values) => {
if (values.validDate) {
values.validStartDate = values.validDate?.[0]?.format("YYYY-MM-DD");
values.validEndDate = values.validDate?.[1]?.format("YYYY-MM-DD");
delete values.validDate;
}
router.query = { router.query = {
...router.query,
...values, ...values,
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -182,7 +178,7 @@ function QualificationCertPage(props) {
<Table <Table
rowKey="id" rowKey="id"
columns={[ columns={[
{ title: "证照类别", dataIndex: "licenseTypeName" }, { title: "证照类别", dataIndex: "certType" },
{ title: "证书名称", dataIndex: "certName" }, { title: "证书名称", dataIndex: "certName" },
{ {
title: "证书有效期", title: "证书有效期",
@ -195,14 +191,14 @@ function QualificationCertPage(props) {
title: "状态", title: "状态",
width: 80, width: 80,
render: (_, record) => render: (_, record) =>
record.enableFlag === 1 ? "启用" : "禁用", isQualificationEnabled(record) ? "启用" : "禁用",
}, },
{ {
title: "照片", title: "照片",
width: 100, width: 100,
render: (_, record) => render: (_, record) =>
record.certImageUrl ? ( record.certImgFiles?.length ? (
<Image width={60} height={60} style={{ objectFit: "cover" }} src={record.certImageUrl.split(",")[0]?.trim()} preview={{ mask: "查看" }} /> <CertTooltipPreviewImg files={record.certImgFiles} />
) : ( ) : (
<span></span> <span></span>
), ),
@ -234,9 +230,15 @@ function QualificationCertPage(props) {
<Button danger type="link" onClick={() => onDelete(record.id)}> <Button danger type="link" onClick={() => onDelete(record.id)}>
删除 删除
</Button> </Button>
<Button type="link" onClick={() => onToggleStatus(record)}> {isQualificationEnabled(record) ? (
{record.enableFlag === 1 ? "禁用" : "启用"} <Button type="link" onClick={() => onDisable(record.id)}>
禁用
</Button> </Button>
) : (
<Button type="link" onClick={() => onEnable(record.id)}>
启用
</Button>
)}
</TableAction> </TableAction>
), ),
}, },
@ -299,31 +301,56 @@ function CertFormModal({
const [form] = Form.useForm(); const [form] = Form.useForm();
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [detailLoading, setDetailLoading] = useState(false); const [detailLoading, setDetailLoading] = useState(false);
const { getFile } = useGetFile();
useEffect(() => { useEffect(() => {
if (!open) return; if (!open) {
return;
}
if (!currentId) { if (!currentId) {
form.resetFields(); form.resetFields();
form.setFieldsValue({ certImgs: mockUploadFileList("证书图片.jpg") });
return; return;
} }
let cancelled = false; let cancelled = false;
(async () => { (async () => {
setDetailLoading(true); setDetailLoading(true);
try { try {
const res = await requestDetails({ id: currentId }); const res = await safeRequest(requestDetails, { id: currentId });
if (cancelled || !res?.data) return; if (cancelled || !res?.data) {
return;
}
const data = { ...res.data }; const data = { ...res.data };
data.issueDate = toDayjs(data.issueDate); data.issueDate = toDayjs(data.issueDate);
data.validDate = [toDayjs(data.validStartDate), toDayjs(data.validEndDate)]; data.validDate = [
data.certImageUrl = parseCertImageUrl(data.certImageUrl); toDayjs(data.validStartDate),
toDayjs(data.validEndDate),
];
data.certImgs = data.certImgFiles?.length
? data.certImgFiles
: mockUploadFileList("证书图片.jpg");
form.setFieldsValue(data); 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);
}
} catch (err) { } catch (err) {
console.warn("[QualificationCert] load detail failed:", err); console.warn("[QualificationCert] load detail failed:", err);
} finally { } finally {
if (!cancelled) setDetailLoading(false); if (!cancelled) {
setDetailLoading(false);
}
} }
})(); })();
return () => { cancelled = true; }; return () => {
cancelled = true;
};
}, [open, currentId]); }, [open, currentId]);
const handleCancel = () => { const handleCancel = () => {
@ -336,8 +363,10 @@ function CertFormModal({
setSubmitting(true); setSubmitting(true);
values.validStartDate = values.validDate?.[0]; values.validStartDate = values.validDate?.[0];
values.validEndDate = values.validDate?.[1]; values.validEndDate = values.validDate?.[1];
values.certImageUrl = stringifyCertImageUrl(values.certImageUrl); values.certImageUrl = resolveUploadFileId(values.certImgs);
if (currentId) values.id = currentId; if (currentId) {
values.id = currentId;
}
const request = currentId ? requestEdit : requestAdd; const request = currentId ? requestEdit : requestAdd;
const res = await request(values); const res = await request(values);
if (res?.success !== false) { if (res?.success !== false) {
@ -365,63 +394,66 @@ function CertFormModal({
<div style={{ color: "#999", marginBottom: 16, fontSize: 12 }}> <div style={{ color: "#999", marginBottom: 16, fontSize: 12 }}>
严谨在本互联网非涉密平台处理传输国家秘密和工作秘密请确认扫描传输的文件资料不涉及国家秘密和工作秘密 严谨在本互联网非涉密平台处理传输国家秘密和工作秘密请确认扫描传输的文件资料不涉及国家秘密和工作秘密
</div> </div>
<Form form={form} layout="horizontal" onFinish={handleSubmit} labelCol={{ span: 4 }}> <FormBuilder
<Form.Item form={form}
name="licenseTypeName" span={24}
label="证照类型" showActionButtons={false}
rules={[{ required: true, message: "请选择证照类型" }]} onFinish={handleSubmit}
> options={[
<Select placeholder="请选择证照类型"> formSelectField(
{QUALIFICATION_INDUSTRY_OPTIONS.map((opt) => ( "certType",
<Select.Option key={opt.value} value={opt.label}> "证照类型",
{opt.label} QUALIFICATION_INDUSTRY_OPTIONS,
</Select.Option> {
))} rules: [{ required: true, message: "请选择证照类型" }],
</Select> colProps: { span: 24 },
</Form.Item> },
<Form.Item ),
name="certName" {
label="证书名称" name: "certName",
rules={[{ required: true, message: "请输入证书名称" }]} label: "证书名称",
> rules: [{ required: true, message: "请输入证书名称" }],
<Input placeholder="请输入证书名称" /> },
</Form.Item> {
<Form.Item name: "certNo",
name="certNo" label: "证明编号",
label="证明编号" rules: [{ required: true, message: "请输入证明编号" }],
rules={[{ required: true, message: "请输入证明编号" }]} },
> {
<Input placeholder="请输入证明编号" /> name: "issueOrg",
</Form.Item> label: "发证机关",
<Form.Item rules: [{ required: true, message: "请输入发证机关" }],
name="issueOrg" },
label="发证机关" {
rules={[{ required: true, message: "请输入发证机关" }]} name: "issueDate",
> label: "发证日期",
<Input placeholder="请输入发证机关" /> render: FORM_ITEM_RENDER_ENUM.DATE,
</Form.Item> rules: [{ required: true, message: "请选择发证日期" }],
<Form.Item },
name="issueDate" {
label="发证日期" name: "validDate",
rules={[{ required: true, message: "请选择发证日期" }]} label: "证书有效期",
> render: FORM_ITEM_RENDER_ENUM.DATE_RANGE,
<DatePicker style={{ width: "100%" }} placeholder="请选择发证日期" /> rules: [
</Form.Item>
<Form.Item
name="validDate"
label="证书有效期"
rules={[
{ required: true, message: "请选择证书有效期" }, { required: true, message: "请选择证书有效期" },
dateRangeRule(), dateRangeRule(),
],
},
{
name: "remark",
label: "备注",
required: false,
render: FORM_ITEM_RENDER_ENUM.TEXTAREA,
},
{
name: "certImgs",
label: "证书图片",
rules: [{ required: true, message: "请上传证书图片" }],
render: <Upload maxCount={3} />,
},
]} ]}
> labelCol={{ span: 8 }}
<RangePicker style={{ width: "100%" }} /> />
</Form.Item>
<Form.Item name="remark" label="备注">
<TextArea rows={3} placeholder="请输入备注" />
</Form.Item>
<AttachmentUpload name="certImageUrl" label="证书图片" maxCount={3} />
</Form>
</Modal> </Modal>
); );
} }
@ -429,6 +461,7 @@ function CertFormModal({
function CertViewModal({ open, currentId, requestDetails, onCancel }) { function CertViewModal({ open, currentId, requestDetails, onCancel }) {
const [info, setInfo] = useState({}); const [info, setInfo] = useState({});
const [detailLoading, setDetailLoading] = useState(false); const [detailLoading, setDetailLoading] = useState(false);
const { getFile } = useGetFile();
useEffect(() => { useEffect(() => {
if (!open || !currentId) { if (!open || !currentId) {
@ -439,16 +472,34 @@ function CertViewModal({ open, currentId, requestDetails, onCancel }) {
(async () => { (async () => {
setDetailLoading(true); setDetailLoading(true);
try { try {
const res = await requestDetails({ id: currentId }); const res = await safeRequest(requestDetails, { id: currentId });
if (cancelled || !res?.data) return; if (cancelled || !res?.data) {
setInfo({ ...res.data, certImageUrlList: parseCertImageUrl(res.data.certImageUrl) }); 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 }));
}
} catch (err) { } catch (err) {
console.warn("[QualificationCert] load view failed:", err); console.warn("[QualificationCert] load view failed:", err);
} finally { } finally {
if (!cancelled) setDetailLoading(false); if (!cancelled) {
setDetailLoading(false);
}
} }
})(); })();
return () => { cancelled = true; }; return () => {
cancelled = true;
};
}, [open, currentId]); }, [open, currentId]);
return ( return (
@ -464,7 +515,7 @@ function CertViewModal({ open, currentId, requestDetails, onCancel }) {
onCancel={onCancel} onCancel={onCancel}
> >
<Descriptions bordered column={1} labelStyle={{ width: 160 }}> <Descriptions bordered column={1} labelStyle={{ width: 160 }}>
<Descriptions.Item label="证照类型">{info.licenseTypeName}</Descriptions.Item> <Descriptions.Item label="证照类型">{info.certType}</Descriptions.Item>
<Descriptions.Item label="证书名称">{info.certName}</Descriptions.Item> <Descriptions.Item label="证书名称">{info.certName}</Descriptions.Item>
<Descriptions.Item label="证明编号">{info.certNo}</Descriptions.Item> <Descriptions.Item label="证明编号">{info.certNo}</Descriptions.Item>
<Descriptions.Item label="发证机关">{info.issueOrg}</Descriptions.Item> <Descriptions.Item label="发证机关">{info.issueOrg}</Descriptions.Item>
@ -474,22 +525,7 @@ function CertViewModal({ open, currentId, requestDetails, onCancel }) {
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="备注">{info.remark || "-"}</Descriptions.Item> <Descriptions.Item label="备注">{info.remark || "-"}</Descriptions.Item>
<Descriptions.Item label="证书图片"> <Descriptions.Item label="证书图片">
{info.certImageUrlList?.length ? ( <CertPreviewImg files={info.certImgs} />
<Image.PreviewGroup>
{info.certImageUrlList.map((file, idx) => (
<Image
key={idx}
src={file.url}
alt="证书图片"
width={100}
height={100}
style={{ objectFit: "cover", marginRight: 8 }}
/>
))}
</Image.PreviewGroup>
) : (
<span>暂无图片</span>
)}
</Descriptions.Item> </Descriptions.Item>
</Descriptions> </Descriptions>
</Modal> </Modal>