一单四制优化及加入工作流

This commit is contained in:
王利强
2026-07-27 09:27:22 +08:00
parent 455fd4fc07
commit 7c3285ed5a
725 changed files with 19668 additions and 2921 deletions

View 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
};
};