384 lines
12 KiB
JavaScript
384 lines
12 KiB
JavaScript
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
|
||
};
|
||
};
|