加载中...

LogicFlow+vue3搭建流程图编排

场景

平时有些场景,有绘制流程图或工作流、流程图编辑等需求,例如低代码平台、审批流程等。

技术选型

进行技术选型,主要从下面几个方面进行考量:
1、功能是否基本满足需求,文档是否齐全
2、用户是否足够多,有足够的issue得到处理
3、使用场景中是否存在一些特殊情况,比如存在大量节点导致性能问题
4、是否具备扩展性,便于扩展新的功能

最后主要对比了两个库,AntV X6LogicFlow,其它的相关的库还有很多,例如jsPlumbmxGraph等,可是由于文档老旧,或者需要付费等没有考虑。

  • AntV X6
    传送门

    X6相较于G6,更适用于图编辑类应用的需求,而G6更适用于图表绘制类的需求。

    1、X6的文档、示例丰富,并且涵盖众多场景
    2、核心功能稳定,并且在持续更新
    3、开箱即用,组件和插件完备,便于定制,也可通过相应注册机制灵活扩展能力

  • LogicFlow
    传送门
    1、文档、示例丰富,专注于流程图、工作流绘制与编排场景,但是其它功能简陋
    2、API设计比较简洁,封装程度更高,上手速度快
    3、基础组件和插件完备,具备注册机制扩展能力
    4、针对流程图绘制场景,封装了一些实用的API

最后考虑到目前的应用场景是一个工作流编排器,使用LogicFlow基本可以搞定所有需求,并且LogicFlow针对流程图绘制场景,封装了不少实用的API,直接就能用:
例如,通过getConnectedSourceRules可以方便地添加当前节点作为边开始节点的校验规则
例如,在对两个节点进行连线时,会有anchor:dropanchor:dragend两个事件用来区分,是否成功进行了连线。
于是最终我采用了LogicFlow来进行开发。

实现的功能

1、基于Vue3、Logicflow,通过拖拽创建、编辑流程图
2、自定义属性面板、属性面板和画板节点属性同步
3、自定义工具栏
4、自定义右键菜单
5、节点编辑、暂存

一些问题:

1、自动生成的节点id或者边id长度很长,不一定满足需求,LogicFlow支持对其重写:createId

注意

  1. 请保证此方法返回 id 的唯一性。
  2. 此方法为同步方法,如果想要异步修改节点 id, 请参考#272
scala
代码解读
复制代码
import { v4 as uuidv4 } from "uuid"; class UserTaskModel extends RectNodeModel { createId() { return uuidv4(); } }

2、根据数据进行流程图回显时,需要手动设置properties,不然properties会丢失。为什么会丢失?原因目前还没发现:

javascript
代码解读
复制代码
logicFlow.render({ nodes, edges }) nextTick(() => { nodes.forEach(l => updateProperty(l.id, l.properties)) edges.forEach(k => updateProperty(k.id, k.properties)) }) function updateProperty (id, data){ const node = lf.value.graphModel.nodesMap[id]; const edge = lf.value.graphModel.edgesMap[id]; if (node) { node.model.setProperties(data); } else if (edge) { edge.model.setProperties(Object.assign(edge.model.properties, data)); } }

3、内置的节点文本支持设置文字溢出模式

  • overflowMode: 用于控制节点文本超出节点后的显示效果:

    • default为默认,即超出不处理。
    • autoWrap为超出了自动换行。
    • ellipsis为超出了隐藏,显示省略符号。
less
代码解读
复制代码
lf.setTheme({ nodeText: { color: "#000000", overflowMode: "default", lineHeight: 1.2, fontSize: 12, }, });

4、定义节点间的连接校验规则

在某些时候,我们可能需要控制边的连接方式,比如 A 节点不能作为边的起点、B 节点不能作为边的终点、C 节点后面必须是 A 节点等等。LogicFlow 提供了自定义节点规则功能来实现这个需求。

LogicFlow 内部有getConnectedSourceRulesgetConnectedTargetRules两个公共方法,分别返回当前节点作为边开始点和作为连接目标点时的校验规则。当在面板上进行边操作的时候,会判断所有的规则是否通过,只有通过了才能连接。

scala
代码解读
复制代码
class CnodeModel extends RectModel { /* ignore other code*/ // 判断这个节点的下一个节点是否符合自定义要求 getConnectedSourceRules(): ConnectRule[] { const rules = super.getConnectedSourceRules(); const gateWayOnlyAsTarget = { message: ''C节点下一个节点只能是A节点'', validate: (source: BaseNodeModel, target: BaseNodeModel) => { let isValid = true; if (target.type !== ''a-node '') { isValid = false; } return isValid; }, }; rules.push(gateWayOnlyAsTarget); return rules; } // 判断这个节点的上一个节点是否符合自定义要求 getConnectedTargetRules() {} }

5、连线
anchor:drop只有在创建连线成功的时候才触发,anchor:dragend则不管是否成功都会触发,因此如果要确认在连线成功后再触发事件,应该使用前者。

DEMO

代码仓库
demo预览