/** * 流程设计器 —— LogicFlow 自定义节点注册。 * * 7 种画布节点与 wf_node.b_node_type 一一映射(§19.5): * fms-start / fms-user-task / fms-cc-task / fms-exclusive-gateway * fms-parallel-gateway / fms-service-task / fms-end * * 形状与尺寸在模型层用 setAttributes() 定(矩形 width/height、圆 r、菱形 rx/ry), * 配色覆写 getNodeStyle()。本项目没装 @logicflow/vue-node-registry, * 因此节点一律用 LogicFlow 原生 SVG 形状渲染,不内嵌 Vue 组件。 */ import { CircleNode, CircleNodeModel, DiamondNode, DiamondNodeModel, RectNode, RectNodeModel, } from '@logicflow/core' import { CANVAS_TO_NODE_TYPE, NODE_META } from './constants' const TEXT_STYLE = { color: '#1f2329', fontSize: 12, overflowMode: 'autoWrap', wrapPadding: '6,8', } /** 画布类型 → 节点元数据 */ function metaOf(canvasType) { return NODE_META[CANVAS_TO_NODE_TYPE[canvasType]] } /** * 连线规则(§19.6 编辑器侧的即时校验): * 开始节点只能作为起点,结束节点只能作为终点,避免连出语义不成立的流程。 * 返回值是 LogicFlow 的 ConnectRule:{ message, validate }。 */ function connectionRules(canvasType) { if (canvasType === 'fms-start') { return { target: { message: '开始节点不能作为连线目标', validate: () => false } } } if (canvasType === 'fms-end') { return { source: { message: '结束节点不能有出线', validate: () => false } } } return {} } /** 圆形节点(开始 / 结束) */ function circleConfig(canvasType) { const meta = metaOf(canvasType) const rules = connectionRules(canvasType) class Model extends CircleNodeModel { setAttributes() { this.r = meta.size.r } getNodeStyle() { return { ...super.getNodeStyle(), ...meta.style, strokeWidth: 2 } } getTextStyle() { return { ...super.getTextStyle(), ...TEXT_STYLE } } getConnectedSourceRules() { const base = super.getConnectedSourceRules() return rules.source ? [...base, rules.source] : base } getConnectedTargetRules() { const base = super.getConnectedTargetRules() return rules.target ? [...base, rules.target] : base } } class View extends CircleNode {} return { type: canvasType, view: View, model: Model } } /** 矩形节点(人工审批 / 抄送 / 服务节点) */ function rectConfig(canvasType) { const meta = metaOf(canvasType) class Model extends RectNodeModel { setAttributes() { this.width = meta.size.width this.height = meta.size.height this.radius = 6 } getNodeStyle() { return { ...super.getNodeStyle(), ...meta.style, strokeWidth: 2 } } getTextStyle() { return { ...super.getTextStyle(), ...TEXT_STYLE } } } class View extends RectNode {} return { type: canvasType, view: View, model: Model } } /** 菱形节点(条件分支 / 并行分支) */ function diamondConfig(canvasType) { const meta = metaOf(canvasType) class Model extends DiamondNodeModel { setAttributes() { this.rx = meta.size.rx this.ry = meta.size.ry } getNodeStyle() { return { ...super.getNodeStyle(), ...meta.style, strokeWidth: 2 } } getTextStyle() { return { ...super.getTextStyle(), ...TEXT_STYLE } } } class View extends DiamondNode {} return { type: canvasType, view: View, model: Model } } /** 把 7 种工作流节点注册到 LogicFlow 实例 */ export function registerWorkflowNodes(lf) { lf.batchRegister([ circleConfig('fms-start'), circleConfig('fms-end'), rectConfig('fms-user-task'), rectConfig('fms-cc-task'), rectConfig('fms-service-task'), diamondConfig('fms-exclusive-gateway'), diamondConfig('fms-parallel-gateway'), ]) }