import React, { useState, useEffect } from "react"; import { Form, Button, Flex, Typography, Steps, Tag, Card, Table, message } from "antd"; import { CheckCircleFilled, DownloadOutlined } from "@ant-design/icons"; import { Connect } from "@cqsjjb/jjb-dva-runtime"; import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace"; import { tools } from "@cqsjjb/jjb-common-lib"; import AttachmentUpload from "~/components/AttachmentUpload"; import {ROLE_DEFINITIONS_MAP} from '~/enumerate/constant' import "./index.less"; import dayjs from "dayjs"; const { router } = tools; const STAGES = [ { key: "notice", index: "01", label: "从业告知" }, { key: "inspection", index: "02", label: "现场勘查" }, { key: "rectification", index: "03", label: "整改通知" }, { key: "enterprise", index: "04", label: "企业整改" }, { key: "review", index: "05", label: "整改复查" }, ]; const ATTACH_TYPE = { notice: "PRACTICE_NOTIFICATION", inspection: "SITE_INSPECTION_FORM", rectification: "RECTIFICATION_NOTICE", enterprise: "ENTERPRISE_RECTIFICATION", review: "RECTIFICATION_REVIEW", }; const downloadTemplate = async () => { try { const res = await fetch("https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a608cb30dc53ed98d0b13ae.pdf"); const blob = await res.blob(); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "从业告知书模板.pdf"; a.click(); URL.revokeObjectURL(url); } catch { message.error("下载失败,请重试"); } }; const NoticePanel = () => (
01 安全评价检测检验机构从业告知书 支持在线填写后打印;阶段试行期间,以机构盖章版上传归档作为完成依据。
办理方式 在线填写用于生成、打印标准告知书 打印盖章后上传扫描件或清晰照片 完成节点必须留存盖章件
📄
从业告知书模板
PDF 格式,可下载后在线填写并打印盖章
); const InspectionPanel = ({ dataSource = [], evalProjectDetailData = {} }) => { const calcDuration = (signIn, signOut) => { if (!signIn || !signOut) return '-'; const start = new Date(signIn); const end = new Date(signOut); const diff = (end - start) / 60000; if (diff <= 0) return '-'; return `${Math.floor(diff / 60)}h${Math.round(diff % 60)}m`; }; return (
02 现场人员打卡与检查表 主要核验项目组人员是否真实到场,留存APP人脸、GPS、签到签退、现场照片及本人签字记录。
打卡与检查表完整
Array.isArray(v) ? v.map(item => ROLE_DEFINITIONS_MAP[item]).join('、') : v,ellipsis: true }, { title: "人脸识别", dataIndex: "faceState", render: (v) => {v === 1 ? "通过" : "未通过"} }, { title: "GPS定位", dataIndex: "gpsState", render: (v) => {v === 1 ? "正常" : "异常"} }, { title: "签到时间", dataIndex: "singInTime" }, { title: "签退时间", dataIndex: "signOutTime" }, { title: "在场时长", render: (_, r) => calcDuration(r.singInTime, r.signOutTime) }, { title: "现场照片", dataIndex: "sceneUrl", render: (v) => { const count = v ? v.split(',').filter(Boolean).length : 0; return ; }}, { title: "本人签字", dataIndex: "signatureUrl", render: (v) => {v ? "已签字" : "未签字"} }, ]} rowKey="id" pagination={false} size="small" />
打卡企业地址:{evalProjectDetailData?.customerAddress || '-'} 允许打卡范围:企业地址周边{evalProjectDetailData?.checkinRadiusMeters || '-'}米 签到日期:{dataSource?.[0]?.singInTime ? dayjs(dataSource?.[0]?.singInTime).format('YYYY-MM-DD') : '-'}
); }; const SimpleUploadPanel = ({ index, title, desc }) => (
{index} {title} {desc}
); const SurveyContent = (props) => { const [form] = Form.useForm(); const [activeStage, setActiveStage] = useState("notice"); const [attachMap, setAttachMap] = useState({}); const [surveyPersonnel, setSurveyPersonnel] = useState([]); const { evalSurveyListLoading, evalSurveySaveAttachLoading, evalProjectDetailData } = props.safetyEvalBusiness; const projectId = router.query?.id; const currentIdx = STAGES.findIndex((s) => s.key === activeStage); const isFirst = currentIdx === 0; const isLast = currentIdx === STAGES.length - 1; const loadAttachments = async () => { if (!projectId) return; const res = await props.evalSurveyList({ projectId }); if (res?.success !== false) { const map = {}; (res?.data || []).forEach((item) => { const key = item.attachTypeCode; try { const parsed = JSON.parse(item.fileUrl); map[key] = Array.isArray(parsed) ? parsed : []; } catch { map[key] = []; } }); setAttachMap(map); // 回填所有步骤的附件到表单 const values = {}; Object.entries(ATTACH_TYPE).forEach(([, typeCode]) => { values[typeCode] = map[typeCode] || []; }); form.setFieldsValue(values); } }; useEffect(() => { loadAttachments(); }, []); useEffect(() => { if (projectId) { props.evalSurveyPage({ projectId, size: 100 }).then((res) => { if (res?.success) { setSurveyPersonnel(res.data || []); } }); } }, [projectId]); const goPrev = () => { if (currentIdx > 0) setActiveStage(STAGES[currentIdx - 1].key); }; const goNext = () => { if (currentIdx < STAGES.length - 1) setActiveStage(STAGES[currentIdx + 1].key); }; const handleSave = async () => { const values = form.getFieldsValue(); const payload = []; for (const [key, typeCode] of Object.entries(ATTACH_TYPE)) { const fileList = values[typeCode] || []; const validFiles = fileList.filter((f) => f.status === "done" && f.url); if (validFiles.length === 0) { setActiveStage(key); message.warning(`请先在"${STAGES.find((s) => s.key === key).label}"步骤上传附件`); return; } payload.push({ projectId, attachTypeCode: typeCode, fileUrl: JSON.stringify(fileList), }); } const res = await props.evalSurveySaveAttach(payload); if (res?.success !== false) { message.success("保存成功"); props.getDetail(); } }; return (
setActiveStage(STAGES[idx].key)} style={{ marginBottom: 16 }} items={STAGES.map((s) => ({ title: s.label }))} /> {activeStage === "notice" && } {activeStage === "inspection" && } {activeStage === "rectification" && ( )} {activeStage === "enterprise" && ( )} {activeStage === "review" && ( )}
{Object.entries(ATTACH_TYPE).map(([key, typeCode]) => (
))} {!isFirst && } {isLast ? ( ) : ( )}
); }; export default Connect( [NS_SAFETY_EVAL_BUSINESS], true, )(SurveyContent);