/** 隐患详情历史节点类型 */ export const HAZARD_NODE_TYPES = { SUBMIT: 'submit', ASSIGN: 'assign', RECTIFY: 'rectify', VERIFY: 'verify', WRITEOFF: 'writeoff' }; export const HAZARD_STATUS_CLASS_MAP = { 1: 'status-blue', 2: 'status-orange', 3: 'status-red', 4: 'status-yellow', 5: 'status-green' }; const STATUS_NAME_CLASS_MAP = { 待交办: 'status-blue', 待整改: 'status-orange', 整改中: 'status-orange', 待验收: 'status-red', 待销号: 'status-yellow', 已完成: 'status-green', 已销号: 'status-green' }; const LEVEL_NAME_MAP = { 2: '一般隐患', 3: '重大隐患' }; export function getLevelName(level) { return LEVEL_NAME_MAP[level] || '未知'; } export function getStatusClass(status, statusName) { if (statusName && STATUS_NAME_CLASS_MAP[statusName]) { return STATUS_NAME_CLASS_MAP[statusName]; } return HAZARD_STATUS_CLASS_MAP[status] || ''; } const LEVEL_CLASS_MAP = { 2: 'level-normal', 3: 'level-major' }; const LEVEL_NAME_CLASS_MAP = { 一般: 'level-normal', 一般隐患: 'level-normal', 重大: 'level-major', 重大隐患: 'level-major' }; export function getStepIconPath(type, active = false) { const baseMap = { submit: 'tijiao', assign: 'jiaoban', rectify: 'zhenggai', verify: 'yanshou', writeoff: 'xiaohao' }; const base = baseMap[type] || 'tijiao'; if (base === 'zhenggai') { return active ? '/static/yinhuan_detail/zhenggai_selected.png' : '/static/yinhuan_detail/zhenggai__unselected.png'; } return `/static/yinhuan_detail/${base}__${active ? 'selected' : 'unselected'}.png`; } export function getLevelClass(level, levelName) { if (level != null && LEVEL_CLASS_MAP[level]) { return LEVEL_CLASS_MAP[level]; } if (levelName && LEVEL_NAME_CLASS_MAP[levelName]) { return LEVEL_NAME_CLASS_MAP[levelName]; } return ''; } /** 将姓名数组或字符串格式化为「a、b、c」 */ export function formatNameList(names, fallback = '-') { if (Array.isArray(names) && names.length) { return names.join('、'); } if (typeof names === 'string' && names.trim()) { const parts = names.split(/[,,、]/).map((s) => s.trim()).filter(Boolean); return parts.length ? parts.join('、') : names; } return fallback; } /** 判断是否为销号记录(type=2 或 typeName=销号) */ export function isWriteoffRecord(record) { if (!record) return false; return record.type === 2 || record.typeName === '销号'; } function buildVerifyNode(record) { return { type: HAZARD_NODE_TYPES.VERIFY, nodeName: '验收', titlePrefix: '验收', operator: record.verifierName || '-', time: record.verifyTime || '-', content: { resultName: record.resultName || '-', remark: record.remark || '', attachments: record.attachments || [], signPath: record.signPath || '', verifyDeptName: record.verifyDeptName || '-' } }; } function buildWriteoffNode(record) { return { type: HAZARD_NODE_TYPES.WRITEOFF, nodeName: '销号', titlePrefix: '销号', operator: record.verifierName || '-', time: record.verifyTime || '-', content: { resultName: record.resultName || '-', remark: record.remark || '', attachments: record.attachments || [], signPath: record.signPath || '', writeoffDeptName: record.writeoffDeptName || '-' } }; } /** 合并验收/销号记录,按 verifyId 去重 */ function appendAuditNodes(list, records, seenIds) { (records || []).forEach((record) => { if (!record) return; const key = record.verifyId ?? record.id; if (key != null) { if (seenIds.has(key)) return; seenIds.add(key); } list.push(isWriteoffRecord(record) ? buildWriteoffNode(record) : buildVerifyNode(record)); }); } function resolveWriteoffRecords(flow) { return flow.writeOffs || flow.writeoffs || []; } /** 解析整改责任人(兼容数组、逗号分隔字符串、单人字段) */ export function resolveRectifierNames(rectify) { if (!rectify) return '-'; if (Array.isArray(rectify.rectifierNames) && rectify.rectifierNames.length) { return rectify.rectifierNames.join('、'); } if (Array.isArray(rectify.memberNames) && rectify.memberNames.length) { return rectify.memberNames.join('、'); } return formatNameList(rectify.rectifierName, '-'); } /** * 将隐患详情转为步骤历史列表(与后台 HazardDetailDrawer 保持一致) * @param {Object} data 隐患详情 * @returns {Array} */ export function generateHazardHistory(data) { if (!data) return []; const list = []; list.push({ type: HAZARD_NODE_TYPES.SUBMIT, nodeName: '提交', titlePrefix: '提交', operator: data.reporterName || '-', time: data.createdAt || '-', content: { code: data.code || '-', title: data.title || '-', source: data.source || '-', hazardSourceName: data.hazardSourceName || '-', areaName: data.areaName || '-', areaColor: data.areaColor || '', address: data.address || '-', level: data.level, levelName: data.levelName || getLevelName(data.level), tagName: data.tagName || '-', description: data.description || '-', attachments: data.attachments || [], legalBasis: data.legalBasis || data.regulationName || '-', reporterPhone: data.reporterPhone || '-', reportDeptName: data.reportDeptName || '-' } }); if (data.assignFlows && data.assignFlows.length > 0) { data.assignFlows.forEach((flow) => { if (flow.assignId) { list.push({ type: HAZARD_NODE_TYPES.ASSIGN, nodeName: '交办', titlePrefix: '交办', operator: flow.assignerName || '-', time: flow.assignTime || '-', content: { assigneeName: flow.assigneeName || '-', deadline: flow.deadline || '-', assignDeptName: flow.assignDeptName || '-', assignRemark: flow.assignRemark || '-', priorityName: flow.priorityName || '-' } }); } if (flow.rectify) { list.push({ type: HAZARD_NODE_TYPES.RECTIFY, nodeName: '整改', titlePrefix: '整改', operator: flow.rectify.rectifierName || '-', time: flow.rectify.rectifyTime || '-', content: { rectifyPlan: flow.rectify.rectifyPlan || '-', rectifyResult: flow.rectify.rectifyResult || '-', rectificationMeasures: flow.rectify.rectificationMeasures || '-', controlMeasures: flow.rectify.controlMeasures || '-', deadline: flow.deadline || '-', rectifierNames: resolveRectifierNames(flow.rectify), managerNames: formatNameList(flow.rectify.managerNames, '-'), planCost: flow.rectify.planCost, actualCost: flow.rectify.actualCost, attachments: flow.rectify.attachments || [], signPath: flow.rectify.signPath || '', rectifyStatusName: flow.rectify.rectifyStatusName || '-' } }); } const seenAuditIds = new Set(); appendAuditNodes(list, flow.verifies || [], seenAuditIds); appendAuditNodes(list, resolveWriteoffRecords(flow), seenAuditIds); }); } return list; } const LONG_DESCRIPTION = '消防通道内堆放大量纸箱及杂物,影响疏散通道畅通,存在火灾安全隐患。' + '现场检查发现通道宽度不足1.2米,部分区域被临时物料占用,紧急情况下可能影响人员撤离。' + '建议立即清理并建立日常巡查机制,防止问题反弹。'; /** 开发联调前使用的 mock 详情数据(各节点均含完整假数据) */ export const MOCK_HAZARD_DETAIL = { id: 'mock-hazard-001', status: 2, statusName: '整改中', reporterName: '张三', reporterPhone: '13800138000', reportDeptName: '安全管理部', createdAt: '2026-06-01 09:30:00', code: '2026U1SL', title: '消防通道堆放杂物', level: 2, levelName: '一般隐患', source: '部门检查', hazardSource: 1, hazardSourceName: '本单位检查发现', areaName: '生产车间A区', areaColor: '#409EFF', address: '办公楼3层东侧消防通道', tagName: '消防安全', description: LONG_DESCRIPTION, legalBasis: '《中华人民共和国消防法》第二十八条', regulationName: '《中华人民共和国消防法》第二十八条', attachments: [ { fileName: 'hazard-1.jpg', filePath: 'https://picsum.photos/seed/hazard1/200/200', fileType: 'image' }, { fileName: 'hazard-2.jpg', filePath: 'https://picsum.photos/seed/hazard2/200/200', fileType: 'image' }, { fileName: 'hazard-3.jpg', filePath: 'https://picsum.photos/seed/hazard3/200/200', fileType: 'image' } ], assignFlows: [ { assignId: 'mock-assign-001', assignerName: '李主管', assignTime: '2026-06-02 10:00:00', assigneeName: '王整改', assignDeptName: '设备保障部', assignRemark: '该隐患位于主疏散通道,请优先处理,务必在整改期限内完成闭环。', priorityName: '高', deadline: '2026-06-10 18:00:00', rectify: { rectifyId: 'mock-rectify-001', rectifierName: '王整改', rectifyTime: '2026-06-08 15:20:00', rectifyStatusName: '已完成', rectifyPlan: '立即清理消防通道杂物,并设置警示标识,后续每周巡查一次。' + '对责任区域进行划分,明确禁止堆放物料的范围,同时组织一次消防安全培训。', rectifyResult: '已完成清理,通道恢复畅通,现场已张贴禁止堆放标识。', rectificationMeasures: '组织人员清理杂物,划定禁止堆放区域,增加日常巡检频次。', controlMeasures: '安装监控并纳入日常巡检清单,发现反弹情况立即上报。', rectifierNames: ['王整改', '赵协助'], managerNames: ['李主管'], planCost: 500, actualCost: 380, attachments: [ { fileName: 'rectify-1.jpg', filePath: 'https://picsum.photos/seed/rectify1/200/200', fileType: 'image' }, { fileName: 'rectify-2.jpg', filePath: 'https://picsum.photos/seed/rectify2/200/200', fileType: 'image' } ], signPath: 'https://picsum.photos/seed/sign1/300/120' }, verifies: [ { verifierName: '陈验收', verifyTime: '2026-06-09 11:00:00', verifyDeptName: '安全监察组', resultName: '通过', remark: '现场复查通道畅通,整改到位,未发现反弹迹象。', attachments: [ { fileName: 'verify-1.jpg', filePath: 'https://picsum.photos/seed/verify1/200/200', fileType: 'image' }, { fileName: 'verify-2.jpg', filePath: 'https://picsum.photos/seed/verify2/200/200', fileType: 'image' } ], signPath: 'https://picsum.photos/seed/sign2/300/120' } ], writeOffs: [ { verifierName: '刘销号', verifyTime: '2026-06-10 16:30:00', writeoffDeptName: '公司安委会', resultName: '通过', remark: '隐患已消除,整改资料齐全,同意销号。', attachments: [ { fileName: 'writeoff-1.jpg', filePath: 'https://picsum.photos/seed/writeoff1/200/200', fileType: 'image' } ], signPath: 'https://picsum.photos/seed/sign3/300/120' } ] } ] };