一单四制优化及加入工作流
This commit is contained in:
383
components/hazardDetail/processChain.js
Normal file
383
components/hazardDetail/processChain.js
Normal file
@@ -0,0 +1,383 @@
|
||||
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
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user