LogicFlow 进阶实战:自定义节点连线规则与动态样式控制
1. LogicFlow自定义节点连线规则实战LogicFlow作为一款专业的流程图编辑框架最强大的特性之一就是可以精确控制节点间的连接规则。在实际业务流程建模中我们经常需要限制某些节点的连接方式比如开始节点不能被其他节点连接结束节点不能连接其他节点审批节点后面必须接分支节点特定业务节点只能与指定类型的节点相连这些业务规则都可以通过sourceRules和targetRules两个关键属性来实现。我最近在开发一个OA审批流系统时就遇到了这样的需求报销申请节点后面只能连接财务审批节点而财务审批节点后面只能连接出纳付款节点。下面分享我的实现方法。首先我们来看基础实现。假设我们需要创建一个正方形节点要求它只能连接到圆形节点import { RectNode, RectNodeModel } from logicflow/core; class SquareModel extends RectNodeModel { initNodeData(data) { super.initNodeData(data); const circleOnlyAsTarget { message: 正方形节点下一个节点只能是圆形节点, validate: (sourceNode, targetNode) { return targetNode.type circle; }, }; this.sourceRules.push(circleOnlyAsTarget); } }这段代码的关键点在于validate函数它接收三个参数sourceNode连线起始节点targetNode连线目标节点sourceAnchor/targetAnchor连接的锚点信息进阶用法当我们在画布上拖动连线时LogicFlow会自动执行这些校验规则。如果校验不通过会触发connection:not-allowed事件我们可以监听这个事件给出友好提示lf.on(connection:not-allowed, (error) { alert(error.message); // 显示正方形节点下一个节点只能是圆形节点 });2. 动态样式反馈与状态管理单纯的校验提示还不够直观好的用户体验应该提供实时视觉反馈。LogicFlow的节点model中有个state属性专门用于这种场景 - 当连接规则校验不通过时state会被设为5。我们可以利用这个特性实现动态样式变化。下面是一个六边形节点的实现示例当连接不合法时会变成红色class CustomHexagonModel extends PolygonNodeModel { getNodeStyle() { const style super.getNodeStyle(); // 连接不合法时显示红色 if (this.state 5) { style.fill red; } // 悬停状态 if (this.isHovered) { style.stroke blue; } // 选中状态 if (this.properties.isSelected) { style.strokeWidth 3; } return style; } }在实际项目中我推荐使用CSS类名而不是直接修改样式这样更易于维护getNodeStyle() { const style super.getNodeStyle(); if (this.state 5) { this.addClassName(connection-error); } else { this.removeClassName(connection-error); } return style; }对应的CSS可以这样定义.lf-node.connection-error { fill: #ffebee; stroke: #f44336; animation: pulse 0.5s infinite alternate; } keyframes pulse { from { opacity: 0.8; } to { opacity: 1; } }3. 锚点的高级控制技巧很多复杂场景需要更精细的连线控制比如只允许从节点右侧锚点连出只允许连接到节点左侧锚点不同业务字段使用不同颜色的锚点这需要我们自定义锚点逻辑。下面是一个SQL表节点的实现它要求只能从右侧锚点连出线只能连接到左侧锚点每个表字段都有独立的锚点class SqlNodeModel extends HtmlNodeModel { setAttributes() { // 从右侧锚点连出的规则 this.sourceRules.push({ message: 只允许从右边的锚点连出, validate: (sourceNode, targetNode, sourceAnchor) { return sourceAnchor.type right; } }); // 连接到左侧锚点的规则 this.targetRules.push({ message: 只允许连接左边的锚点, validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) { return targetAnchor.type left; } }); } getDefaultAnchor() { return this.properties.fields.map((field, index) { return [ // 左侧输入锚点 { x: this.x - this.width/2 10, y: this.y - this.height/2 60 index * 24, id: ${this.id}_${field.key}_left, type: left }, // 右侧输出锚点 { x: this.x this.width/2 - 10, y: this.y - this.height/2 60 index * 24, id: ${this.id}_${field.key}_right, type: right } ]; }).flat(); } }锚点的样式也可以完全自定义比如在view中重写getAnchorShapeclass SqlNode extends HtmlNode { getAnchorShape(anchorData) { const { x, y, type } anchorData; // 左侧锚点显示为红色矩形 if(type left) { return h(rect, { x: x-5, y: y-5, width: 10, height: 10, fill: #ff0000 }); } // 右侧锚点显示为绿色圆形 return h(circle, { cx: x, cy: y, r: 5, fill: #00ff00 }); } }4. 复杂业务规则的综合应用在实际ERP系统开发中我遇到过这样一个需求采购订单需要依次经过部门审批→财务审批→总经理审批三个环节每个环节的审批人不同且不能跳过任何环节。这种复杂业务流程可以通过组合多种规则来实现。首先定义三种审批节点模型// 部门审批节点 class DeptApprovalModel extends RectNodeModel { initNodeData(data) { super.initNodeData(data); // 只能连接到财务审批节点 this.sourceRules.push({ validate: (source, target) target.type finance-approval }); // 必须从采购订单节点连接过来 this.targetRules.push({ validate: (source) source.type purchase-order }); } } // 财务审批节点 class FinanceApprovalModel extends RectNodeModel { initNodeData(data) { super.initNodeData(data); // 只能连接到总经理审批 this.sourceRules.push({ validate: (source, target) target.type ceo-approval }); // 必须从部门审批连接过来 this.targetRules.push({ validate: (source) source.type dept-approval }); } } // 总经理审批节点 class CEOApprovalModel extends RectNodeModel { initNodeData(data) { super.initNodeData(data); // 不能连接其他节点终审节点 this.sourceRules.push({ validate: () false }); // 必须从财务审批连接过来 this.targetRules.push({ validate: (source) source.type finance-approval }); } }然后我们可以添加全局校验逻辑确保流程完整性lf.on(connection:add, ({sourceNode, targetNode}) { // 检查是否跳过环节 const validPaths { purchase-order: [dept-approval], dept-approval: [finance-approval], finance-approval: [ceo-approval] }; if(!validPaths[sourceNode.type]?.includes(targetNode.type)) { lf.graphModel.removeEdge(edge.id); alert(流程环节不完整请按照规范连接节点); return false; } });为了让规则配置更灵活我通常会把这些校验规则提取到业务配置文件中// workflow-rules.js export const APPROVAL_RULES { purchase-order: { nextSteps: [dept-approval], color: #FF9800 }, dept-approval: { nextSteps: [finance-approval], requiredPrev: [purchase-order], color: #2196F3 }, // ...其他规则 }; // 在节点模型中动态应用 class DynamicApprovalModel extends RectNodeModel { initNodeData(data) { const rules APPROVAL_RULES[this.type]; this.sourceRules.push({ validate: (_, target) rules.nextSteps.includes(target.type) }); if(rules.requiredPrev) { this.targetRules.push({ validate: (source) rules.requiredPrev.includes(source.type) }); } this.fill rules.color; } }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2504534.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!