import { Button, Modal, message } from "antd"; import { useEffect, useRef, useState } from "react"; import html2canvas from "html2canvas"; import { jsPDF } from "jspdf"; import { fetchOrgPersonnelDetail } from "~/utils/qualFiling/personnelHelper"; import { ABILITY_SOURCE_MAP } from "~/enumerate/enterpriseOptions"; import { CERT_LEVEL_LABEL_BY_TYPE, CAPABILITY_MAP, } from "~/enumerate/constant"; import "./index.less"; const GENDER_MAP = { 1: "男", 2: "女" }; const parseFileList = (raw) => { if (!raw) return []; if (Array.isArray(raw)) return raw; try { const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch { return []; } }; const maskIdCard = (val) => { if (!val || String(val).length < 8) return val || "-"; const s = String(val); return `${s.slice(0, 14)}****`; }; const maskPhone = (val) => { if (!val || String(val).length < 7) return val || "-"; const s = String(val); return `${s.slice(0, 3)}****${s.slice(-4)}`; }; const display = (val) => { if (val === 0) return "0"; if (val == null || val === "") return "-"; return val; }; export default function StaffResumeModal({ open, currentId, requestDetails = fetchOrgPersonnelDetail, onCancel, }) { const [info, setInfo] = useState({}); const [detailLoading, setDetailLoading] = useState(false); const [downloading, setDownloading] = useState(false); const resumeRef = useRef(null); const requestDetailsRef = useRef(requestDetails); requestDetailsRef.current = requestDetails; useEffect(() => { if (!open || !currentId) { setInfo({}); return; } let cancelled = false; setDetailLoading(true); Promise.resolve(requestDetailsRef.current({ id: currentId })) .catch((err) => { console.warn("[StaffResumeModal] load detail failed:", err); return { data: {} }; }) .then((detailRes) => { if (!cancelled) { setInfo(detailRes?.data || {}); } }) .finally(() => { if (!cancelled) { setDetailLoading(false); } }); return () => { cancelled = true; }; }, [open, currentId]); const evalCert = info.evaluatorCert; const evalLevelMap = CERT_LEVEL_LABEL_BY_TYPE.evaluator; const evalLevelName = evalLevelMap[evalCert?.certLevel] || ""; const qualificationText = evalLevelName || evalCert?.certNo ? [evalLevelName, evalCert?.certNo].filter(Boolean).join(" / ") : "-"; const regCert = info.registeredSafetyEngineerCert; const regCertFiles = parseFileList(regCert?.certAttachmentUrl); const educationText = [info.educationTypeName, info.educationLevelName] .filter(Boolean) .join("") || "-"; const schoolMajorText = [info.graduateSchool, info.basicDisciplineMajorName] .filter(Boolean) .join(" / ") || "-"; const capabilityText = Array.isArray(info.capabilityAssessment) ? info.capabilityAssessment .map((item) => { const name = CAPABILITY_MAP[item.professionalCapabilityCode] || item.professionalCapabilityCode || ""; const source = ABILITY_SOURCE_MAP[item.professionalCapabilitySourceCode] || item.professionalCapabilitySourceCode || ""; if (!name && !source) return ""; return [name, source].filter(Boolean).join(" / "); }) .filter(Boolean) .join(";") || "-" : "-"; const handleDownload = async () => { if (!resumeRef.current) return; setDownloading(true); try { const canvas = await html2canvas(resumeRef.current, { scale: 2, useCORS: true, backgroundColor: "#ffffff", logging: false, }); const imgData = canvas.toDataURL("image/jpeg", 0.95); const pdf = new jsPDF({ orientation: "portrait", unit: "mm", format: "a4", }); const pageWidth = pdf.internal.pageSize.getWidth(); const pageHeight = pdf.internal.pageSize.getHeight(); const margin = 10; const contentWidth = pageWidth - margin * 2; const contentHeight = (canvas.height * contentWidth) / canvas.width; let heightLeft = contentHeight; let position = margin; pdf.addImage(imgData, "JPEG", margin, position, contentWidth, contentHeight); heightLeft -= pageHeight - margin * 2; while (heightLeft > 0) { position = margin - (contentHeight - heightLeft); pdf.addPage(); pdf.addImage(imgData, "JPEG", margin, position, contentWidth, contentHeight); heightLeft -= pageHeight - margin * 2; } const fileName = `安全评价师简历表_${info.userName || currentId || ""}.pdf`; pdf.save(fileName); message.success("简历下载成功"); } catch (err) { console.warn("[StaffResumeModal] download pdf failed:", err); message.error("简历下载失败"); } finally { setDownloading(false); } }; return ( 下载简历 , , ]} >
安全评价师简历表
姓名 {display(info.userName)} 性别 {GENDER_MAP[info.genderCode] || "-"}
出生日期 {display(info.birthDate)} 现住址 {display(info.currentAddress)}
办公地址 {display(info.officeAddress)} 职业资格等级及证书号码 {qualificationText}
注册安全工程师证书编号 {display(regCert?.certNo)} 身份证件号码 {maskIdCard(info.idCardNo)}
联系电话 {maskPhone(info.account)} 学历学位 {educationText}
毕业院校及专业 {schoolMajorText} 出版学术专著、专利、科技发明及获奖情况 {info.publications ? info.publications : "无"}
自我申报的专业能力及认定方式 {capabilityText}
申报专业能力证明材料 {regCertFiles.length ? regCertFiles.map((item) => ( )) : "-"}
主要学习工作经历 {display(info.workExperience)}
本人签字 从业机构确认
); }