diff --git a/jjb.config.js b/jjb.config.js index 04d4428..83eb003 100644 --- a/jjb.config.js +++ b/jjb.config.js @@ -10,7 +10,7 @@ module.exports = { javaGitBranch: "", // 本地联调 safety-eval-service(context-path: /safety-eval,默认端口 8095) // 可通过环境变量覆盖: SAFETY_EVAL_API_HOST=http://192.168.x.x:8095 - API_HOST: process.env.SAFETY_EVAL_API_HOST || "http://127.0.0.1:8095", + API_HOST: process.env.SAFETY_EVAL_API_HOST || "http://192.168.0.124:8095", }, production: { // 应用后端分支名称,部署上线需要 diff --git a/src/api/enterpriseInfo/adapter.js b/src/api/enterpriseInfo/adapter.js index fa5d6cd..76310fe 100644 --- a/src/api/enterpriseInfo/adapter.js +++ b/src/api/enterpriseInfo/adapter.js @@ -407,7 +407,7 @@ export function fromStaffForm(values = {}) { export function toStaffCertForm(data = {}) { const certImgs = data.certAttachmentUrl - ? [{ url: data.certAttachmentUrl, fileName: data.certName }] + ? parseAttachmentUrls(data.certAttachmentUrl, data.certName || "证书附件.jpg") : data.certImgFiles || []; return { id: asId(data.id), @@ -465,7 +465,7 @@ export function isQualificationEnabled(record = {}) { export function toQualificationForm(data = {}) { const certImgs = data.certImageUrl - ? [{ url: data.certImageUrl, fileName: data.certName }] + ? parseAttachmentUrls(data.certImageUrl, data.certName || "证书图片.jpg") : data.certImgFiles || []; return { id: asId(data.id), diff --git a/src/components/CertPreviewImg/index.js b/src/components/CertPreviewImg/index.js new file mode 100644 index 0000000..172a7bb --- /dev/null +++ b/src/components/CertPreviewImg/index.js @@ -0,0 +1,66 @@ +import { Image, Tooltip, Tag } from "antd"; +import { getFileUrl } from "zy-react-library/utils"; + +/** 解析附件对象的可访问地址,兼容 filePath(相对路径)与 url(绝对/相对) */ +export function resolvePreviewSrc(file = {}) { + const base = getFileUrl?.() || window.fileUrl || ""; + const path = file.filePath; + const url = file.url; + if (path) { + const p = String(path); + if (/^https?:\/\//i.test(p)) { + return p; + } + return base ? `${base}${p}` : p; + } + if (url) { + const u = String(url); + if (/^https?:\/\//i.test(u)) { + return u; + } + return base ? `${base}${u}` : u; + } + return ""; +} + +function CertPreviewImg({ files = [], width = 100, height = 100 }) { + const items = (files || []).filter(Boolean); + const srcList = items.map(resolvePreviewSrc).filter(Boolean); + if (!srcList.length) { + return 暂无图片; + } + return ( + + {srcList.map((src, index) => ( + + ))} + + ); +} + +export function CertTooltipPreviewImg({ files = [] }) { + const items = (files || []).filter(Boolean); + const srcList = items.map(resolvePreviewSrc).filter(Boolean); + return ( + + : 暂无图片} + > + 预览 + + ); +} + +CertPreviewImg.displayName = "CertPreviewImg"; +CertTooltipPreviewImg.displayName = "CertTooltipPreviewImg"; + +export default CertPreviewImg; diff --git a/src/pages/Container/EnterpriseInfo/PersonnelInfo/Certificate/index.js b/src/pages/Container/EnterpriseInfo/PersonnelInfo/Certificate/index.js index 60d4ea4..b902e1a 100644 --- a/src/pages/Container/EnterpriseInfo/PersonnelInfo/Certificate/index.js +++ b/src/pages/Container/EnterpriseInfo/PersonnelInfo/Certificate/index.js @@ -4,7 +4,7 @@ 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 CertPreviewImg from "~/components/CertPreviewImg"; import Search from "zy-react-library/components/Search"; import Table from "zy-react-library/components/Table"; import Upload from "zy-react-library/components/Upload"; @@ -334,7 +334,7 @@ function ViewModal({ open, currentId, requestDetails, onCancel }) { {info.validStartDate} {info.validEndDate} {info.reviewDate} - + ); diff --git a/src/pages/Container/EnterpriseInfo/PersonnelInfo/StaffViewModal.js b/src/pages/Container/EnterpriseInfo/PersonnelInfo/StaffViewModal.js index fb84f93..b9a1b1d 100644 --- a/src/pages/Container/EnterpriseInfo/PersonnelInfo/StaffViewModal.js +++ b/src/pages/Container/EnterpriseInfo/PersonnelInfo/StaffViewModal.js @@ -1,6 +1,7 @@ import { Button, Descriptions, Modal, Space, Table } from "antd"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import FilePreviewModal, { FilePreviewContent } from "~/components/FilePreviewModal"; +import { resolvePreviewSrc } from "~/components/CertPreviewImg"; import { fetchStaffCertDetail, fetchStaffCertListByPersonnelId } from "~/api/staffCertificate"; import { safeRequest } from "~/utils"; @@ -22,6 +23,12 @@ export default function StaffViewModal({ const [certPreview, setCertPreview] = useState(null); const [certPreviewLoading, setCertPreviewLoading] = useState(false); const [certPreviewInfo, setCertPreviewInfo] = useState(null); + const requestDetailsRef = useRef(requestDetails); + const requestCertListRef = useRef(requestCertList); + const requestCertDetailsRef = useRef(requestCertDetails); + requestDetailsRef.current = requestDetails; + requestCertListRef.current = requestCertList; + requestCertDetailsRef.current = requestCertDetails; useEffect(() => { if (!open || !currentId) { @@ -31,10 +38,11 @@ export default function StaffViewModal({ } let cancelled = false; setDetailLoading(true); + const loadCertList = requestCertListRef.current; Promise.all([ - safeRequest(requestDetails, { id: currentId }), - typeof requestCertList === "function" - ? Promise.resolve(requestCertList(currentId)).catch((err) => { + safeRequest(requestDetailsRef.current, { id: currentId }), + typeof loadCertList === "function" + ? Promise.resolve(loadCertList(currentId)).catch((err) => { console.warn("[StaffViewModal] load certificates failed:", err); return []; }) @@ -52,18 +60,18 @@ export default function StaffViewModal({ return () => { cancelled = true; }; - }, [open, currentId, requestDetails, requestCertList]); + }, [open, currentId]); const openCertPreview = async (record) => { setCertPreview(record); setCertPreviewInfo(null); - if (typeof requestCertDetails !== "function") { + if (typeof requestCertDetailsRef.current !== "function") { setCertPreviewInfo(record); return; } setCertPreviewLoading(true); try { - const res = await safeRequest(requestCertDetails, { id: record.id }); + const res = await safeRequest(requestCertDetailsRef.current, { id: record.id }); setCertPreviewInfo(res?.data || record); } finally { @@ -75,7 +83,7 @@ export default function StaffViewModal({ const certPreviewFiles = certPreviewInfo?.certImgs?.length ? certPreviewInfo.certImgs : certPreviewInfo?.certImgFiles || []; - const certPreviewUrl = certPreviewFiles[0]?.url; + const certPreviewUrl = resolvePreviewSrc(certPreviewFiles[0]); const certPreviewName = certPreviewFiles[0]?.fileName || certPreviewFiles[0]?.name || certPreviewInfo?.certName; return ( diff --git a/src/pages/Container/EnterpriseInfo/QualificationCert/index.js b/src/pages/Container/EnterpriseInfo/QualificationCert/index.js index 0fd99ea..42a3512 100644 --- a/src/pages/Container/EnterpriseInfo/QualificationCert/index.js +++ b/src/pages/Container/EnterpriseInfo/QualificationCert/index.js @@ -4,14 +4,13 @@ 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 TooltipPreviewImg from "zy-react-library/components/TooltipPreviewImg"; 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 useTable from "zy-react-library/hooks/useTable"; +import CertPreviewImg, { CertTooltipPreviewImg } from "~/components/CertPreviewImg"; import { NS_ORG_QUALIFICATION_CERT } from "~/enumerate/namespace"; import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions"; import { formSelectField } from "~/utils/enterpriseForm"; @@ -141,7 +140,7 @@ function QualificationCertPage(props) { width: 100, render: (_, record) => ( record.certImgFiles?.length - ? + ? : ), }, @@ -447,7 +446,7 @@ function CertViewModal({ open, currentId, requestDetails, onCancel }) { {info.remark || "-"} - + diff --git a/src/pages/Container/Layout/menuConfig.js b/src/pages/Container/Layout/menuConfig.js index af84429..28ef462 100644 --- a/src/pages/Container/Layout/menuConfig.js +++ b/src/pages/Container/Layout/menuConfig.js @@ -26,11 +26,6 @@ const menuItems = [ label: "监管端", icon: , children: [ - { - key: "/certificate/container/Supervision/test2", - label: "Test2 测试", - icon: , - }, { key: "/certificate/container/Supervision/BasicInfo", label: "基础信息管理", @@ -58,144 +53,7 @@ const menuItems = [ }, ], }, - { - key: "/certificate/container/Supervision/EnterpriseLicense", - label: "企业证照", - icon: , - children: [ - { - key: "/certificate/container/Supervision/EnterpriseLicense/EnterpriseLicense", - label: "企业证照管理", - icon: , - }, - { - key: "/certificate/container/Supervision/EnterpriseLicense/BranchStatistics/List", - label: "分公司统计", - icon: , - }, - { - key: "/certificate/container/Supervision/EnterpriseLicense/StakeholderStatistics/List", - label: "干系人统计", - icon: , - }, - ], - }, - { - key: "/certificate/container/Supervision/PersonnelLicense", - label: "人员证照", - icon: , - children: [ - { - key: "/certificate/container/Supervision/PersonnelLicense/PersonInCharge/List", - label: "负责人", - icon: , - }, - { - key: "/certificate/container/Supervision/PersonnelLicense/SecurityAdmini/List", - label: "安全管理员", - icon: , - }, - { - key: "/certificate/container/Supervision/PersonnelLicense/SpecialDevice/List", - label: "特种设备", - icon: , - }, - { - key: "/certificate/container/Supervision/PersonnelLicense/SpecialPersonnel/List", - label: "特种作业人员", - icon: , - }, - { - key: "/certificate/container/Supervision/PersonnelLicense/BranchCompanyStat/List", - label: "分公司人员统计", - icon: , - }, - { - key: "/certificate/container/Supervision/PersonnelLicense/StakeholderStat/List", - label: "干系人人员统计", - icon: , - }, - ], - }, - ], - }, - { - key: "/certificate/container/BranchCompany", - label: "分公司端", - icon: , - children: [ - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/EnterpriseLicense", - label: "企业证照管理", - icon: , - }, - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/PersonnelLicense", - label: "人员证照", - icon: , - children: [ - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/PersonnelLicense/PersonInCharge/List", - label: "负责人", - icon: , - }, - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/PersonnelLicense/SecurityAdmini/List", - label: "安全管理员", - icon: , - }, - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/PersonnelLicense/SpecialDevice/List", - label: "特种设备", - icon: , - }, - { - key: "/certificate/container/BranchCompany/EnterpriseLicense/PersonnelLicense/SpecialPersonnel/List", - label: "特种作业人员", - icon: , - }, - ], - }, - ], - }, - { - key: "/certificate/container/Stakeholder", - label: "干系人端", - icon: , - children: [ - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/EnterpriseLicense", - label: "企业证照管理", - icon: , - }, - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense", - label: "人员证照", - icon: , - children: [ - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense/PersonInCharge/List", - label: "负责人", - icon: , - }, - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense/SecurityAdmini/List", - label: "安全管理员", - icon: , - }, - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense/SpecialDevice/List", - label: "特种设备", - icon: , - }, - { - key: "/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense/SpecialPersonnel/List", - label: "特种作业人员", - icon: , - }, - ], - }, - ], + ] }, { key: "/certificate/container/EnterpriseInfo", @@ -238,12 +96,7 @@ const menuItems = [ icon: , }, ], - }, - { - key: "/certificate/container/Test", - label: "测试页面", - icon: , - }, + } ]; export default menuItems;