开源工作流引擎方案复盘

科技   2024-10-17 08:31   重庆  

嗨, 大家好, 我是徐小夕.

之前一直在社区分享零代码&低代码的技术实践,也陆陆续续设计并开发了多款可视化搭建产品,比如:

最近一直在研究可视化工作流, 也开源了自己基于 react-flow 实现的工作流编辑器:

开源地址:

https://github.com/MrXujiang/flowmix-flow

接下来就来和大家分享一下市面上常用的开源工作流项目, 以及如何快速上手实现自己的工作流引擎.

市面上开源的工作流引擎都有哪些

在搜索引擎刷了一圈, 找到几个还算比较靠谱的开源方案:

  • mxgraph
  • antv/g6
  • antv/x6
  • react-flow
  • logicFlow

接下来我会一一和大家介绍一下.

1. mxgraph

mxGraph 是一个 JavaScript 图表库,可以快速创建交互式图形和图表应用程序,这些应用程序可以在主流浏览器中运行。mxGraph 提供图形绘制、图形可视化、图形交互、图形布局、图形分析等能力, 适用于工作流程图、BPMN图、网络图、UML图、循环图、组织结构图、MindMap图、机架图、甘特图、信息图、平面图等绘制。

mxGraph创建于2005年,作为商业项目一直持续到2016年,2016年创建者以 Apache 2.0 开源协议在 GitHub 上公布源码。

github地址: https://github.com/jgraph/mxgraph 文档地址: http://jgraph.github.io/mxgraph/docs/js-api

我们熟悉的 draw.io 就是基于这个库来实现的, 惊不惊喜, 意不意外~

2. antv/g6

antv/g6 是我4年前在公司项目中使用过的, 虽然当时文档非常“难啃”, 好在后面把技术攻克了, 项目也顺利上线, 所以这里给大家分享一下. 它是阿里开源的一款图形引擎, 我们可以使用它实现各种图编辑器:

不过我觉得最近更新的版本中对老版本做了毁灭性升级, 导致老项目可能会出现升级成本, 加上文档中一些API都是过时的, 所以建议官方团队对文档准确性和及时性提供一定的保障.

github地址: https://github.com/antvis/G6

3. antv/x6

antv/x6 是一款流程编排解决方案, 之前的项目中虽然也使用过, 但是个人觉得灵活度还是不够, 感兴趣的朋友也可以参考研究一下:

github地址: https://github.com/antvis/X6

4. react-flow

react-flow 是我用下来使用体验最好的一款流程引擎, 从性能和灵活度上, 我觉得都非常适合作为底层流程引擎来使用, 所以我今年花了3个月的时间研究这款项目, 也设计了一款工作流引擎, 同时基于自己的实践, 开源了一款工作流编辑器:

开源地址:

https://github.com/MrXujiang/flowmix-flow

我强烈推荐大家学习一下这款开源项目.

5. logicFlow

logicFlow 是滴滴团队开源的一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow 支持前端自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码平台流程配置都有较好的应用。

虽然早期版本我之前体验了还是很难满足我的需求, 但是最新的版本提供了更灵活的配置, 所以大家感兴趣也可以尝试一下~

github地址: https://github.com/didi/LogicFlow

工作流引擎的应用场景

这里分享一下我对工作流应用的一些看法.

1. OA审批流程

从我们用的办公软件比如钉钉, 飞书, 里面有各种审批, 其实都可以用可视化工作流来配置, 工作流目前在OA领域的应用我觉得是最明显的.

2. AI领域的Workflow

这两年AI无疑是一个非常热门的话题, 业界比较知名的AI应用 Dify, 底层的工作流就是采用React-flow 来实现, 所以我们可以基于workflow, 来构建我们的AI应用.

3. 低代码/零代码产品的流程引擎

这块也是我主要研究的方向, 目前很多知名低代码平台基本上都配备的流程引擎, 来实现业务逻辑的可视化设计.

如果大家对工作流感兴趣, 也可以在群里交流讨论:

如何基于react-flow, 开发自己的工作流引擎

接下来我会和大家分享一下如何基于react-flow, 来实现自己的工作流引擎.

1. 快速上手 react-flow

React Flow 是一个用于构建基于节点的应用程序的库。这些应用程序可以是从简单的静态图表到数据可视化再到复杂的可视化编辑器的任何场景。我们可以实现自定义节点类型和边,并且它自带了一些组件,如迷你地图和视口控件。

亮点

  • 👌 易于使用React Flow 已经自带了许多你想要的开箱即用的功能。拖拽节点、缩放和平移、选择多个节点和边,以及添加/删除边等都已内置。

  • 🎨 可定制React Flow 支持自定义节点类型和边类型。因为自定义节点只是 React 组件,所以你可以实现任何你想要的需求:你不会被限制在内置节点类型上。自定义边允许你在节点边上添加标签、控件和定制逻辑。

  • ⚡️ 快速渲染React Flow 只渲染已改变的节点,并确保只有在视口中的节点才会被完全显示出来。

  • 🧩 内置插件:我们在 React Flow 中自带了一些插件:

    • <Background /> 插件实现了一些基本的可定制背景图案。
    • <MiniMap /> 插件在屏幕的角落显示图形的一个缩略图。
    • <Controls /> 插件添加了缩放、居中以及锁定视口的控制功能。
    • <Panel /> 插件让你可以轻松地在视口顶部放置内容。
    • <NodeToolbar /> 插件允许你渲染附加在节点上的工具栏。
    • <NodeResizer /> 插件让你可以轻松地为你的节点添加缩放功能。
  • 💪 可靠React Flow 完全是用 TypeScript 编写的,以便及早发现错误并使修复容易。对于其他方面,我们有一个强大的压测支持,这样你就可以更自信地使用 React Flow 了。

2. 核心理念

React Flow 核心理念始终围绕下面3个模块展开.

  • nodes 节点

React Flow 中的节点是一个 React 组件。这意味着它可以渲染我们喜欢的任何内容。每个节点都有一个 x 和 y 坐标,这指明了节点在视口中的位置, 我们可以根据自身需求自定义节点, 并支持任何 React 组件。

实现自定义节点的案例如下:

import { useCallback } from 'react';
import { Handle, Position } from '@xyflow/react';
 
const handleStyle = { left10 };
 
function TextUpdaterNode({ data }{
  const onChange = useCallback((evt) => {
    console.log(evt.target.value);
  }, []);
 
  return (
    <>
      <Handle type="target" position={Position.Top} />
      <div>
        <label htmlFor="text">Text:</label>
        <input id="text" name="text" onChange={onChange} className="nodrag" />
      </div>
      <Handle type="source" position={Position.Bottom} id="a" />
      <Handle
        type="source"
        position={Position.Bottom}
        id="b"
        style={handleStyle}
      />

    </>

  );
}

实现完自定义节点之后, 只需要在 flow 中注册即可使用.

  • edges 边

一条边连接两个节点。每条边都需要一个目标节点和一个源节点。 React Flow 具有四种内置边缘类型:

  • 默认(贝塞尔曲线)
  • smoothstep
  • step
  • Straight

边缘是 SVG 路径,可以使用 CSS 进行样式设置,并且是完全可定制的。如果我们使用多个句柄,则可以单独引用它们来为一个节点创建多个连接。

边对我们的工作流非常重要, 复杂的流程图的边需要支持多种类型, 动效, 好在React-flow提供了足够的边定制能力.

  • handles 句柄

句柄(在其他库中也称为“端口”)是边连接到节点的地方。手柄可放置在任何地方,并可根据我们的喜好设计风格。它只是一个 div 元素。默认情况下,它在节点的顶部、底部、左侧或右侧显示为灰色圆圈。创建自定义节点时,我们可以在节点中拥有所需数量的句柄。

一个实际使用 handles 的代码案例:

const CustomNode = ({ data }) => {
  return (
    <>
      <div style={style}>
        {data.label}
      </div>
 
      <Handle type="target" position={Position.Left} />
      <Handle type="source" position={Position.Right} />
    </>

  );
};

代码中我们可以看到, 我们可以在节点的任意位置来设置句柄, 并设置“源” 或者“目标”.

大家想深入研究可以参考我翻译的中文文档:

文档地址: http://react-flow.com

3. 设计一款符合自身业务的工作流引擎

要想设计一款工作流编辑器, 可以参考低代码或者零代码的设计思路,规则优先, 其次是做组件化的封装.

上面演示的就是我基于 react-flow 实现的工作流引擎,

demo演示地址: http://flowmix.turntip.cn/flow-v0

我们可以基于它轻松实现自身业务的工作流, 编辑器我已经封装好了大量的技术实践, 比如:

  • 流程排序
  • 节点拖拽
  • 自动创建/编辑节点
  • 节点连线
  • 拖拽参考线/吸附
  • 画布模式
  • 节点数据存储
  • 画布缩略图
  • 导出流程JSON

节点创建与编辑

我们可以轻松添加节点, 并通过双击节点来快速编辑节点, 同时编辑模式还能二次扩展.

边的自定义连线

我们可以轻松对不同节点进行自定义连线, 并且点击节点的“+”号之后, 可以自动创建连线节点, 来轻松创建工作流.

节点拖拽参考线

节点拖拽时会显示参考线, 来提高搭建体验, 这块我采用了 refline 来实现参考线吸附, 并且封装了一个组件, 这里和大家分享一下具体的实现:

import { RefLine } from "./index";
import { Rect, Point } from "./types";

interface Props {
  current: Rect;
  nodes: Rect[];
  points?: Point[];
  scale?: number;
  offsetX?: number;
  offsetY?: number;
}
export default function Line(
  nodes, 
  points = [], 
  current, 
  scale = 1,
  offsetX = 0,
  offsetY = 0
}: Props
{
  if (!current) return null;

  const refline = new RefLine({
    rects: nodes,
    points,
    current
  });

  // 获取水平、垂直参考线
  const lines = refline.getAllRefLines();

  return (
    <>
      {lines.map((line, i) => {
        return line.type === "vertical" ? (
          <div
            key={i}
            className="line"
            style={{
              position: "absolute",
              left: line.left * scale + offsetX,
              top: line.top * scale + offsetY,
              width: 1,
              height: line.size * scale,
              borderLeft: "1px dashed blue"
            }}
          >
</div>
        ) : (
          <div
            key={i}
            className="line"
            style={{
              position: "absolute",
              left: line.left * scale + offsetX,
              top: line.top * scale + offsetY,
              height: 1,
              width: line.size * scale,
              borderTop: "1px dashed blue"
            }}
          >
</div>
        );
      })}
    </>

  );
}

节点多选

双向图层面板

我们选择节点之后, 图层面板会对应的激活, 同时支持多选激活. 当我们选择图层面板的节点之后, 画布中的节点也会对应的激活, 来提高操作效率.

数据管理机制

数据状态管理我采用了轻量且高性能的zustand, 这款状态管理库目前已有47k star, 很多知名项目都在使用它, 建议大家可以学习一下.

如果大家对工作流感兴趣, 也可以在群里交流讨论:

后续我会持续迭代工作流引擎, 如果大家感兴趣, 也可以关注下面的公众号:

如果你有好的想法和建议, 也欢迎随时留言区交流讨论~

往期精彩:


趣谈前端
徐小夕【知乎专栏作家】掘金签约作者,定期分享前端工程化,可视化,企业实战项目知识,深度复盘企业中经常遇到的500+技术问题解决方案。【关注趣谈前端,前端路上不迷茫】
 最新文章