news 2026/5/1 6:23:01

LogicFlow 进阶实战:自定义节点连线规则与动态样式控制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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函数,它接收三个参数:

  1. sourceNode:连线起始节点
  2. targetNode:连线目标节点
  3. 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表节点的实现,它要求:

  1. 只能从右侧锚点连出线
  2. 只能连接到左侧锚点
  3. 每个表字段都有独立的锚点
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中重写getAnchorShape:

class 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; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 0:43:07

数据库优化器到底难在哪 揭秘核心技术挑战

于数据库范畴之内,优化器技术一直都被看成是极具挑战性的难题,它就好像是数据库的“大脑”,肩负着把SQL查询转变为最高效执行计划的重大责任。一个优秀的优化器能够直接判定数据库的性能上限,可是,去设计一个健壮又智能…

作者头像 李华
网站建设 2026/4/15 0:10:51

FastLEDManager:ESP32多层LED序列化混合渲染框架

1. FastLEDManager:面向嵌入式实时控制的多层LED序列管理框架FastLEDManager并非一个简单的FastLED封装库,而是一个为资源受限嵌入式平台(尤其是ESP32)深度定制的LED序列化任务调度与混合渲染引擎。其核心设计哲学是将LED视觉效果…

作者头像 李华
网站建设 2026/4/11 0:33:09

ZynqMP双存储启动优化:QSPI与eMMC的分区策略与升级实践

1. ZynqMP双存储启动架构解析 第一次接触ZynqMP的启动流程时,我被它的灵活性惊到了。这颗芯片居然能像变形金刚一样,根据不同的存储介质组合出多种启动方式。最经典的组合就是QSPI Flash eMMC这对黄金搭档——QSPI负责存放引导程序,eMMC承载…

作者头像 李华
网站建设 2026/4/11 0:25:32

Blazor Server项目CSS隔离失效?检查_Host.cshtml这个关键文件

Blazor Server项目CSS隔离失效的深度排查指南 当你在Blazor Server项目中精心设计了Razor组件的CSS隔离样式,却发现它们像被施了隐身咒一样毫无效果时,这种挫败感我深有体会。上周三凌晨两点,我正为一个客户项目赶工,突然发现整个…

作者头像 李华
网站建设 2026/4/11 0:24:56

[具身智能-332]:ollam工作原理

Ollama 是一个专为在本地设备上简化大语言模型(LLM)部署与运行而设计的开源框架。其核心工作原理可以概括为 客户端-服务端(C/S)架构,并结合了高效的模型管理和推理技术。🏗️ 核心架构Ollama 的整体架构由…

作者头像 李华