import { Permission } from "@cqsjjb/jjb-common-decorator/permission"; import { Connect } from "@cqsjjb/jjb-dva-runtime"; import { Button, Form, message, Modal, Space } from "antd"; import { useEffect, useRef, 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 Search from "zy-react-library/components/Search"; import DictionarySelect from "zy-react-library/components/Select/Dictionary"; import PersonnelSelect from "zy-react-library/components/Select/Personnel/Gwj"; 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 { UPLOAD_FILE_TYPE_ENUM } from "zy-react-library/enum/uploadFile/gwj"; import useDeleteFile from "zy-react-library/hooks/useDeleteFile"; import useGetFile from "zy-react-library/hooks/useGetFile"; import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery"; import useGetUserInfo from "zy-react-library/hooks/useGetUserInfo"; import useTable from "zy-react-library/hooks/useTable"; import useUploadFile from "zy-react-library/hooks/useUploadFile"; import { NS_USER_CERTIFICATE } from "~/enumerate/namespace"; import { useDebounce } from "~/utils"; import { useLocation } from 'react-router-dom'; const JOB_STATUS = { 1: "在职", 0: "离职", 2: "信息变更中", 3: "未入职", 4: "实习生", 5: "实习结束", 6: "退休", 7: "劳务派遣", 8: "劳务派遣结束", 11: "入职待审核", 10: "离职待审核", }; function List({ props, certificatePhotoType, displayType, personnelType, permissionAdd, permissionEdit, permissionView, permissionDel, dictionaryType }) { const [addModalOpen, setAddModalOpen] = useState(false); const [currentId, setCurrentId] = useState(""); const queryParams = useGetUrlQuery(); const { loading: getFileLoading, getFile } = useGetFile(); const [form] = Form.useForm(); const { tableProps, getData } = useTable(props["userCertificateList"], { form, transform: (formData) => { return { ...formData, eqCorpinfoId: queryParams["corpinfoId"], eqType: personnelType, }; }, }); const onDelete = async (row) => { props["projectHasUser"]({ eqUserId: row.userId }).then((res) => { console.log(res); if (res.data && res.data.length > 0) { const arr = []; const userArr = []; res.data.forEach((item) => { arr.push(item.projectName); userArr.push(item.userName); }); Modal.confirm({ title: "提示", content: (
【 {[...new Set(userArr)].join(",")} 】有正在进行的项目,包含【 { [...new Set(arr)].join(",") } 】确定删除吗?
删除可能会对正在进行的项目造成异常状态,请谨慎操作。
), onOk: () => { props["userCertificateRemove"]({ id: row.id, }).then((res) => { if (res.success) { message.success("删除成功"); getData(); } }); }, }); } else { Modal.confirm({ title: "提示", content: "确定删除吗?", onOk: () => { props["userCertificateRemove"]({ id: row.id, }).then((res) => { if (res.success) { message.success("删除成功"); getData(); } }); }, }); } }); }; const [fileCache, setFileCache] = useState({}); const [loadingKeys, setLoadingKeys] = useState(new Set()); const pendingLoadIdsRef = useRef(new Set()); const requestQueueRef = useRef([]); const activeRequestsRef = useRef(0); const MAX_CONCURRENT_REQUESTS = 3; // 最大并发请求数 const processQueue = () => { while ( requestQueueRef.current.length > 0 && activeRequestsRef.current < MAX_CONCURRENT_REQUESTS ) { const { id, resolve, reject } = requestQueueRef.current.shift(); activeRequestsRef.current++; getFile({ eqType: UPLOAD_FILE_TYPE_ENUM[certificatePhotoType], eqForeignKey: id, }) .then((res) => { setFileCache(prev => ({ ...prev, [id]: res || [], })); resolve(res); }) .catch((err) => { console.error("图片加载失败:", err); reject(err); }) .finally(() => { activeRequestsRef.current--; setLoadingKeys((prev) => { const newSet = new Set(prev); newSet.delete(id); return newSet; }); processQueue(); }); } }; const loadFileForRecord = (userQualificationinfoId) => { if (!userQualificationinfoId) return Promise.resolve(); if (fileCache[userQualificationinfoId]) return Promise.resolve(); if (loadingKeys.has(userQualificationinfoId)) return Promise.resolve(); if (pendingLoadIdsRef.current.has(userQualificationinfoId)) return Promise.resolve(); pendingLoadIdsRef.current.add(userQualificationinfoId); setLoadingKeys(prev => new Set([...prev, userQualificationinfoId])); return new Promise((resolve, reject) => { requestQueueRef.current.push({ id: userQualificationinfoId, resolve, reject }); processQueue(); }).finally(() => { pendingLoadIdsRef.current.delete(userQualificationinfoId); }); }; // 清除伪类 useEffect(() => { if (displayType === "View") { const style = document.createElement("style"); style.innerHTML = ` .search-layout::after { content: none !important; display: none !important; } `; document.head.appendChild(style); // 清理函数,在组件卸载时移除样式 return () => { document.head.removeChild(style); }; } }, []); // 缓存数据变化时清空图片缓存 useEffect(() => { if (tableProps.dataSource) { const currentIds = new Set(tableProps.dataSource.map(item => item.userCertificateId).filter(Boolean)); setFileCache((prev) => { const newCache = {}; Object.keys(prev).forEach((id) => { if (currentIds.has(id)) { newCache[id] = prev[id]; } }); return newCache; }); } }, [tableProps.dataSource]); // 记录已经触发过加载的 ID,避免 render 重复触发 const triggeredLoadIdsRef = useRef(new Set()); useEffect(() => { if (tableProps.dataSource) { tableProps.dataSource.forEach((record) => { const id = record.userCertificateId; if (id && !triggeredLoadIdsRef.current.has(id)) { triggeredLoadIdsRef.current.add(id); loadFileForRecord(id); } }); } // 组件卸载或数据源变化时重置 return () => { triggeredLoadIdsRef.current.clear(); }; }, [tableProps.dataSource]); return ( ( <> { (displayType !== "View" && props.permission(permissionAdd)) && ( ) } )} columns={[ { title: "姓名", dataIndex: "name", }, { title: "证书名称", dataIndex: "certificateName", }, { title: "证书编号", dataIndex: "certificateCode", }, { title: "岗位名称", dataIndex: "postName", }, { title: "有效期至", dataIndex: "certificateNo", width: 280, render: (_, record) =>
{`${record.certificateDateStart ?? ""} - ${record.certificateDateEnd ?? ""}`}
, }, { title: "就职状态", dataIndex: "certificateNo", render: (_, record) => (
{JOB_STATUS[record.employmentStatus] || "-"}
), }, { title: "图片", dataIndex: "name", render: (_, record) => { const id = record.userCertificateId; const files = fileCache[id] || []; if (!files.length) return ; return ; }, }, { title: "操作", width: 200, render: (_, record) => ( { props.permission(permissionView) && ( ) } { (displayType !== "View" && props.permission(permissionEdit)) && ( ) } { (displayType !== "View" && props.permission(permissionDel)) && ( ) } ), }, ]} {...tableProps} /> {addModalOpen && ( { setAddModalOpen(false); setCurrentId(""); }} onSuccess={(userQualificationinfoId) => { // 清除该记录的图片缓存,强制下次 render 时重新加载 setFileCache((prev) => { const newCache = { ...prev }; delete newCache[userQualificationinfoId]; return newCache; }); }} /> )} ); } function AddModalComponent(props) { const [form] = Form.useForm(); const [userQualificationinfoId, setUserQualificationinfoId] = useState(""); const [userObj, setUserObj] = useState({}); const { loading: deleteFileLoading, deleteFile } = useDeleteFile(); const { loading: uploadFileLoading, uploadFile } = useUploadFile(); const { loading: getFileLoading, getFile } = useGetFile(); const { getUserInfo } = useGetUserInfo(); const [deleteCardImageFiles, setDeleteCardImageFiles] = useState([]); const [CertificateCodeValue, setPertificateCodeValue] = useState(null); const debouncedCertificateCodeValue = useDebounce(CertificateCodeValue, 100); const [personnelData, setPersonnelData] = useState([]); const [isSubmit, setIsSubmit] = useState(true); const location = useLocation(); const getUserInfoFun = async () => { const userInfo = await getUserInfo(); setUserObj(userInfo); }; const getUserlistFun = async () => { props.getUserlistAll({menuPath:"/certificate"+location.pathname}).then(res => { if(res.data) { res.data.forEach(item => { item.bianma=item.id; }) setPersonnelData(res.data) } }) }; useEffect(() => { if (props.currentId) { const fetchData = async () => { const { data } = await props.requestDetails({ id: props.currentId, }); const certificateImgs = await getFile({ eqType: UPLOAD_FILE_TYPE_ENUM[props.certificatePhotoType], eqForeignKey: data.userCertificateId, }); data.certificateDate = [data.certificateDateStart, data.certificateDateEnd]; data.certificateImgs = certificateImgs; form.setFieldsValue(data); setUserQualificationinfoId(data.userCertificateId); }; fetchData(); } getUserInfoFun(); getUserlistFun() }, [props.currentId]); const onCancel = () => { form.resetFields(); props.onCancel(); }; const onSubmit = async (values) => { if (!isSubmit) { form.setFields([ { name: "certificateCode", errors: ["证书编号重复"], }, ]); return; } if (values.certificateImgs.length !== 2) { message.error("证照照片必须上传正反面两张"); return; } const maxSizeInBytes = 10 * 1024 * 1024; const isOverSize = values.certificateImgs.some(file => file.size > maxSizeInBytes); if (isOverSize) { message.error("选择的图片不能大于10MB"); return; } await deleteFile({ single: false, files: deleteCardImageFiles, }); const { id } = await uploadFile({ single: false, files: values.certificateImgs, params: { type: UPLOAD_FILE_TYPE_ENUM[props.certificatePhotoType], foreignKey: userQualificationinfoId, }, }); values.certificateDateStart = values.certificateDate[0]; values.certificateDateEnd = values.certificateDate[1]; values.type = props.personnelType; const personnelTypeMap = { tezhongzuoye: "特种作业人员", tzsbczry: "特种设备操作人员", zyfzr: "主要负责人", aqscglry: "安全生产管理人员", }; values.typeName = personnelTypeMap[props.personnelType]; if (props.currentId) { values.id = props.currentId; values.userCertificateId = userQualificationinfoId; await props.requestEdit(values).then((res) => { if (res.success) { onCancel(); props.getData(); props.onSuccess(userQualificationinfoId); message.success("编辑成功"); } }); } else { values.userCertificateId = id; await props.requestAdd(values).then((res) => { if (res.success) { onCancel(); props.getData(); props.onSuccess(userQualificationinfoId); message.success("新增成功"); } }); } }; // 校验重复 useEffect(() => { if (!debouncedCertificateCodeValue) { form.setFields([ { name: "certificateCode", errors: [], }, ]); return; } props["userCertificateIsExistCertNo"]({ certNo: debouncedCertificateCodeValue, id: props.currentId ?? "", }).then((res) => { if (res.data) { form.setFields([ { name: "certificateCode", errors: ["证书编号重复"], }, ]); setIsSubmit(false); } else { setIsSubmit(true); } }); }, [debouncedCertificateCodeValue]); const onValuesChange = (changedValues) => { if ("certificateCode" in changedValues) { setPertificateCodeValue(changedValues.certificateCode ?? ""); } }; return ( form.setFieldValue("postName", label)} /> ), }, { name: "postName", label: "岗位名称", onlyForLabel: true }, { name: "issuingAuthority", label: "发证机构", }, { name: "dateIssue", label: "发证日期", render: FORM_ITEM_RENDER_ENUM.DATE, }, { name: "certificateDate", label: "有效期", render: FORM_ITEM_RENDER_ENUM.DATE_RANGE, rules: [ { validator: (_, value) => { const allEmptyStrings = Array.isArray(value) && value.every(item => item === ""); if (allEmptyStrings) { return Promise.reject(new Error("请选择有效期")); } return Promise.resolve(); }, }, ], }, { name: "certificateImgs", label: "证照照片", render: ( { setDeleteCardImageFiles([...deleteCardImageFiles, file]); }} tipContent={(
温馨提示:用户要上传证照照片正反面(证照照片数量是2张)单张大小不超过10MB,支持jpg、jpeg、png格式。
)} /> ), }, ]} labelCol={{ span: 10, }} showActionButtons={false} onFinish={onSubmit} />
); } const AddModal = AddModalComponent; export default Connect([NS_USER_CERTIFICATE], true)(Permission(List));