Files
threeonecheck_web/components/hazardDetail/processChain.js
2026-07-27 09:27:22 +08:00

384 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { formatNameList } from './hazardDetail.js';
export const PENDING_LABEL = '待处理';
/** completed 未传时视为已完成(兼容旧数据) */
export const isNodeCompleted = (node) => node?.completed !== false;
/** 空值:已完成显示 -,未完成显示待处理 */
export const resolveFieldDisplay = (value, completed = true) => {
if (value != null && value !== '') return value;
return completed ? '-' : PENDING_LABEL;
};
export const PROCESS_NODE_TYPES = {
ADD: 'add',
ASSIGN: 'assign',
RECTIFY: 'rectify',
RECTIFY_ASSIGN: 'rectifyAssign',
VERIFY: 'verify',
VERIFY_SUB: 'verify_sub',
WRITEOFF_APPLY: 'writeoff_apply',
WRITEOFF_APPROVE: 'writeoff_approve',
WRITEOFF_SUB: 'writeoff_sub',
APPROVAL: 'approval'
};
const SUB_TYPE_SUFFIX_MAP = {
verify: '验收',
writeoff: '销号'
};
const TITLE_PREFIX_MAP = {
add: '提交',
assign: '交办',
rectify: '整改',
rectifyAssign: '交办',
verify: '验收',
verify_sub: '审批',
writeoff_apply: '销号申请',
writeoff_approve: '销号审核',
writeoff_sub: '审批'
};
const APPROVAL_TASK_KEY_ICON = {
department_review: 'bumenshenpi',
section_chief_review: 'fenguanshenpi',
supervising_executive_review: 'fenguanshenpi',
supervising_leader_review_1: 'zhuguanshenpi',
supervising_leader_review_2: 'zhuguanshenpi'
};
const NODE_TYPE_ICON = {
add: 'tijiao',
assign: 'jiaoban',
rectifyAssign: 'jiaoban',
rectify: 'zhenggai',
verify: 'yanshou',
writeoff_apply: 'xiaohao',
writeoff_approve: 'xiaohao'
};
const resolveTaskKey = (node) => {
return node?.taskKey || node?.subProcessApprovalInfo?.taskKey || '';
};
/** null/undefined 等非对象值统一转为 {},避免默认参数对 null 不生效 */
const toSafeObject = (value) => (value && typeof value === 'object' ? value : {});
/** null/undefined/空字符串展示为空 */
const toDisplayText = (value) => {
if (value == null || value === '') return '';
return value;
};
export const getProcessStepDisplayName = (node) => {
if (!node) return '';
const nodeType = node.nodeType;
if (nodeType === 'verify_sub' || nodeType === 'writeoff_sub') {
const subType = node.subProcessApprovalInfo?.subType;
const suffix = SUB_TYPE_SUFFIX_MAP[subType];
return suffix ? `${node.nodeName}${suffix}` : node.nodeName;
}
return node.nodeName || '';
};
export const getProcessStepIconPath = (item, active = false) => {
const type = item?.type;
const taskKey = item?.taskKey || '';
const state = active ? 'selected' : 'unselected';
if (type === PROCESS_NODE_TYPES.APPROVAL) {
const iconBase = APPROVAL_TASK_KEY_ICON[taskKey] || 'bumenshenpi';
return `/static/yinhuan_detail/${iconBase}_${state}.png`;
}
const base = NODE_TYPE_ICON[item?.rawType] || NODE_TYPE_ICON[type] || 'tijiao';
if (base === 'zhenggai') {
return active
? '/static/yinhuan_detail/zhenggai_selected.png'
: '/static/yinhuan_detail/zhenggai__unselected.png';
}
return `/static/yinhuan_detail/${base}__${state}.png`;
};
const resolveOperator = (node, nodeType) => {
const completed = isNodeCompleted(node);
const fallback = completed ? '-' : '';
if (nodeType === PROCESS_NODE_TYPES.ADD) {
return node.hazardInfo?.reporterName || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.ASSIGN) {
return node.assignInfo?.assignerName || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.RECTIFY) {
return node.rectifyInfo?.rectifierName || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.VERIFY || nodeType === PROCESS_NODE_TYPES.WRITEOFF_APPROVE) {
return node.verifyInfo?.verifierName || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.WRITEOFF_APPLY) {
return node.writeOffApplyInfo?.applicantName || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.APPROVAL) {
const info = node.subProcessApprovalInfo || {};
return info.operatorName || info.assigneeName || fallback;
}
return fallback;
};
const resolveTime = (node, nodeType) => {
const completed = isNodeCompleted(node);
const fallback = completed ? '-' : '';
if (nodeType === PROCESS_NODE_TYPES.ADD) {
return node.hazardInfo?.createdAt || node.completedAt || node.occurredAt || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.ASSIGN) {
return node.assignInfo?.assignTime || node.completedAt || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.RECTIFY) {
return node.rectifyInfo?.rectifyTime || node.completedAt || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.VERIFY || nodeType === PROCESS_NODE_TYPES.WRITEOFF_APPROVE) {
return node.verifyInfo?.verifyTime || node.completedAt || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.WRITEOFF_APPLY) {
return node.writeOffApplyInfo?.applyTime || node.completedAt || fallback;
}
if (nodeType === PROCESS_NODE_TYPES.APPROVAL) {
return node.subProcessApprovalInfo?.endTime || node.completedAt || fallback;
}
return node.completedAt || node.occurredAt || fallback;
};
const mapAddContent = (info) => {
const data = toSafeObject(info);
return {
code: toDisplayText(data.code),
title: toDisplayText(data.title),
source: toDisplayText(data.source),
hazardSourceName: toDisplayText(data.hazardSourceName),
areaName: toDisplayText(data.areaName),
address: toDisplayText(data.address),
level: data.level ?? null,
levelName: toDisplayText(data.levelName),
tagName: toDisplayText(data.tagName),
description: toDisplayText(data.description),
attachments: Array.isArray(data.attachments) ? data.attachments : [],
legalBasis: toDisplayText(data.legalBasis)
};
};
const mapAssignContent = (info) => {
const data = toSafeObject(info);
return {
assigneeName: toDisplayText(data.assigneeName),
deadline: toDisplayText(data.deadline),
assignRemark: toDisplayText(data.assignRemark),
assignStatusName: toDisplayText(data.assignStatusName)
};
};
const mapRectifyContent = (info) => {
const data = toSafeObject(info);
return {
rectifyStatusName: toDisplayText(data.rectifyStatusName),
rectifyPlan: toDisplayText(data.rectifyPlan),
rectifyResult: toDisplayText(data.rectifyResult),
rectificationMeasures: toDisplayText(data.rectificationMeasures),
controlMeasures: toDisplayText(data.controlMeasures),
rectifierName: toDisplayText(data.rectifierName),
managerNames: formatNameList(data.managerNames, ''),
memberNames: formatNameList(data.memberNames, ''),
planCost: data.planCost ?? null,
actualCost: data.actualCost ?? null,
attachments: Array.isArray(data.attachments) ? data.attachments : [],
signPath: toDisplayText(data.signPath)
};
};
const mapVerifyContent = (info) => {
const data = toSafeObject(info);
return {
resultName: toDisplayText(data.resultName),
remark: toDisplayText(data.remark),
attachments: Array.isArray(data.attachments) ? data.attachments : [],
signPath: toDisplayText(data.signPath)
};
};
const mapApprovalContent = (info) => {
const data = toSafeObject(info);
return {
approveTypeName: toDisplayText(data.approveTypeName),
pass: data.pass ?? null,
comment: toDisplayText(data.comment),
nextStepName: toDisplayText(data.nextStepName),
nextAssigneeName: toDisplayText(data.nextAssigneeName),
sendMsgFlag: data.sendMsgFlag ?? null,
signPath: toDisplayText(data.signPath)
};
};
const mapWriteoffApplyContent = (info) => {
const data = toSafeObject(info);
return {
rectifyDeadline: toDisplayText(data.rectifyDeadline),
responsibleDeptName: toDisplayText(data.responsibleDeptName),
responsiblePerson: toDisplayText(data.responsiblePerson),
mainTreatmentContent: toDisplayText(data.mainTreatmentContent),
treatmentResult: toDisplayText(data.treatmentResult),
selfVerifyContent: toDisplayText(data.selfVerifyContent),
signPath: toDisplayText(data.signPath)
};
};
const resolveNodeType = (node) => {
const nodeType = node?.nodeType;
if (nodeType === 'verify_sub' || nodeType === 'writeoff_sub') {
return PROCESS_NODE_TYPES.APPROVAL;
}
return nodeType || PROCESS_NODE_TYPES.ADD;
};
const hasRectifyData = (rectifyInfo) => {
if (!rectifyInfo || typeof rectifyInfo !== 'object') {
return false;
}
return Boolean(
rectifyInfo.rectifyId
|| rectifyInfo.rectifyPlan
|| rectifyInfo.rectifyResult
|| rectifyInfo.rectifyTime
|| rectifyInfo.rectifierName
);
};
const hasAssignData = (assignInfo) => {
if (!assignInfo || typeof assignInfo !== 'object') {
return false;
}
return Boolean(
assignInfo.assignId
|| assignInfo.assigneeName
|| assignInfo.assignerName
|| assignInfo.assignTime
);
};
/** 交办 / 整改转派节点 */
const isAssignLikeNodeType = (nodeType) => (
nodeType === PROCESS_NODE_TYPES.ASSIGN
|| nodeType === PROCESS_NODE_TYPES.RECTIFY_ASSIGN
);
/** 交办/整改节点:有整改数据展示整改,否则有交办数据展示交办 */
export const resolveAssignRectifyDisplayType = (node) => {
if (hasRectifyData(node?.rectifyInfo)) {
return PROCESS_NODE_TYPES.RECTIFY;
}
if (hasAssignData(node?.assignInfo)) {
return PROCESS_NODE_TYPES.ASSIGN;
}
return null;
};
const resolveDisplayType = (node, nodeType) => {
// assign隐患交办 → assignInfo
// rectifyAssign整改转派 → assignInfo若同节点附带整改数据则展示整改
if (isAssignLikeNodeType(nodeType)) {
return resolveAssignRectifyDisplayType(node) || PROCESS_NODE_TYPES.ASSIGN;
}
// rectify隐患整改 → rectifyInfo未整改前可能只有转派信息
if (nodeType === PROCESS_NODE_TYPES.RECTIFY) {
return resolveAssignRectifyDisplayType(node) || PROCESS_NODE_TYPES.RECTIFY;
}
return nodeType;
};
const resolveTitlePrefix = (rawType, displayType, node) => {
if (displayType === PROCESS_NODE_TYPES.ASSIGN) {
return TITLE_PREFIX_MAP[rawType] || TITLE_PREFIX_MAP.assign;
}
if (displayType === PROCESS_NODE_TYPES.RECTIFY) {
return TITLE_PREFIX_MAP.rectify;
}
return TITLE_PREFIX_MAP[displayType] || TITLE_PREFIX_MAP[rawType] || node.nodeName || '处理';
};
const mapNodeContent = (node, displayType) => {
switch (displayType) {
case PROCESS_NODE_TYPES.ADD:
return mapAddContent(node.hazardInfo);
case PROCESS_NODE_TYPES.ASSIGN:
return mapAssignContent(node.assignInfo);
case PROCESS_NODE_TYPES.RECTIFY:
return mapRectifyContent(node.rectifyInfo);
case PROCESS_NODE_TYPES.VERIFY:
case PROCESS_NODE_TYPES.WRITEOFF_APPROVE:
return mapVerifyContent(node.verifyInfo);
case PROCESS_NODE_TYPES.WRITEOFF_APPLY:
return mapWriteoffApplyContent(node.writeOffApplyInfo);
case PROCESS_NODE_TYPES.APPROVAL:
return mapApprovalContent(node.subProcessApprovalInfo);
default:
return {};
}
};
export const mapProcessNodeToHistoryItem = (node) => {
if (!node || typeof node !== 'object') {
return {
type: PROCESS_NODE_TYPES.ADD,
rawType: '',
taskKey: '',
nodeName: '',
titlePrefix: '处理',
operator: '',
time: '',
content: {},
flowTaskId: '',
completed: true
};
}
const nodeType = resolveNodeType(node);
const rawType = node.nodeType || nodeType;
const displayType = resolveDisplayType(node, nodeType);
return {
type: displayType,
rawType,
taskKey: resolveTaskKey(node),
nodeName: getProcessStepDisplayName(node),
titlePrefix: resolveTitlePrefix(rawType, displayType, node),
operator: resolveOperator(node, displayType),
time: resolveTime(node, displayType),
content: mapNodeContent(node, displayType),
flowTaskId: node.flowTaskId || '',
completed: isNodeCompleted(node)
};
};
export const mapProcessChainNodes = (nodes = []) => {
if (!Array.isArray(nodes) || nodes.length === 0) return [];
return nodes.map((node) => mapProcessNodeToHistoryItem(node));
};
export const resolveProcessChainSummary = (data) => {
if (!data) {
return {
statusName: '-',
createdAt: '-'
};
}
const addNode = (data.nodes || []).find((item) => item.nodeType === 'add');
const createdAt = addNode?.hazardInfo?.createdAt || '-';
return {
statusName: data.statusName || '-',
createdAt
};
};