LiteFlow逻辑可视化编排设计与实现 01-先导篇

4,796 阅读6分钟

背景:我之前写过一篇文章:《Liteflow逻辑编排可视化设计》,分享了我们对LiteFlow这个规则引擎的逻辑可视化设计,而我们这个可视化项目的目标不仅仅只是实现LiteFlow的逻辑可视化,而是实现LiteFlow的逻辑可视化编排。

接下来,我将通过系列文章的形式,进行LiteFlow逻辑可视化编排设计与实现的开发经验分享。

LiteFlow ContextPad.gif

《LiteFlow逻辑可视化编排设计与实现》会以系列文章的形式,有步骤、有重点地分享我们对LiteFlow逻辑可视化编排的实现,目前该系列文章有如下5篇:

  1. LiteFlow逻辑可视化编排设计与实现 01-先导篇
  2. LiteFlow逻辑可视化编排设计与实现 02-数据模型篇(Model)
  3. LiteFlow逻辑可视化编排设计与实现 03-视图呈现篇(View)
  4. LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)
  5. LiteFlow逻辑可视化编排设计与实现 05-后记篇(前端代码已开源,文末有仓库地址)

以下是《LiteFlow逻辑可视化编排设计与实现 01-先导篇》的文章正文。

01-先导篇

作为一名前端开发,我们需要特别关注的前端开发要素有三个——数据(Model)、视图(View)和逻辑(Control),即“MVC”——而在实现LiteFlow逻辑可视化编排时,我们也可以使用“MVC三要素”的知识框架来进行系统的拆解、组合、设计和实现。

LiteFlow逻辑可视化编排设计与实现.png

  1. 数据模型(Model):将EL表达式的操作符(Operator)进行建模,在这个项目里,我们将EL表达式建模成了由ELNode组成的一棵树;
  2. 视图呈现(View):使用AntV X6的节点(Node)和边(Edge)进行ELNode的可视化呈现,即通过Nodes & Edges实现LiteFlow的逻辑可视化;
  3. 操作逻辑(Control):实现ELNode模型的增删改查(CRUD)操作。

我个人非常喜欢这个“MVC三要素”的知识框架,通过它、我可以很方便地进行系统的拆解和组合,所以本篇文章、以及本系列文章,都会以这个“MVC三要素”的知识框架进行分享。

在本篇先导篇中,我们先简单地过一下LiteFlow逻辑可视化编排的“MVC三要素”:

1、数据模型(Model)

LiteFlow对可执行的逻辑流程进行建模,主要包括以下2个部分:

Liteflow流程建模:逻辑组件 + 逻辑编排.png

  • 1、逻辑组件(组件节点):逻辑组件类型包括:
    ① 顺序组件:用于THEN、WHEN;
    ② 分支组件:用于SWITCH、IF ...;
    ③ 循环组件:用于FOR、WHILE ...。

  • 2、逻辑编排:通过EL表达式进行组件编排:
    ① 串行编排:THEN;
    ② 并行编排:WHEN;
    ③ 选择编排:SWITCH;
    ④ 条件编排:IF;
    ⑤ 循环编排:FOR、WHILE等等。

而对以上“逻辑组件”的“逻辑编排”,都是通过EL表达式来实现,比如一个EL表达式的例子:

<chain name="chain1">
    THEN(
        a,
        WHEN(b, c, d),
        e
    );
</chain>

其中“THEN”和“WHEN”是EL表达式的关键字,分别表示串行编排和并行编排,而“a”“b”“c”“d”“e”则是5个逻辑组件,由此组成了一个串行和并行编排的组合——即先执行“a”组件,然后并行执行“b”“c”“d”组件,最后执行“e”组件。

而我们数据模型(Model),就是将EL表达式的操作符(Operator)进行建模:

LiteFlow逻辑可视化编排设计与实现 1. 数据模型(Model).png

  • EL表达式:LiteFlow的逻辑编排是通过EL表达式来实现的,比如我们之前提到过的这个例子:
<chain name="chain1">
    THEN(
        a,
        WHEN(b, c, d),
        e
    );
</chain>
  • 树形结构:将LiteFlow进行文本拆解,我们其实能得到一个树形结构(即AST抽象语法树);
  • JSON表示:我们可以把这棵树进行简化,得到一个简化版的JSON表示:
{
  type: "THEN",
  children: [
    { type: "NodeComponent", id: "a" },
    {
      type: "WHEN",
      children: [
        { type: "NodeComponent", id: "b" },
        { type: "NodeComponent", id: "c" },
        { type: "NodeComponent", id: "d" },
      ],
    },
    { type: "NodeComponent", id: "e" },
  ]
}
  • 建立模型:经过以上步骤的分析,我们可以建立这么一个ELNode模型:
/**
 * EL表达式的模型表示:数据结构本质上是一个树形结构。
 * 例如一个串行编排(THEN):
  {
    type: ConditionTypeEnum.THEN,
    children: [
      { type: NodeTypeEnum.COMMON, id: 'a' },
      { type: NodeTypeEnum.COMMON, id: 'b' },
      { type: NodeTypeEnum.COMMON, id: 'c' },
      { type: NodeTypeEnum.COMMON, id: 'd' },
    ],
  }
 */
export default abstract class ELNode {
  // 节点类型:可以是编排类型,也可以是组件类型
  public type: ConditionTypeEnum | NodeTypeEnum;
  // 当前节点的子节点:编排类型有子节点,组件类型没有子节点
  public children?: ELNode[];
  // 当前节点的父节点
  public parent?: ELNode;
  // 判断类节点类型:主要用于SWITCH/IF/FOR/WHILE等编排类型
  public condition?: ELNode;
  // 组件节点的id
  public id?: string;
  // 编排节点的属性:可以设置id/tag等等
  public properties?: Properties;
}

2、视图呈现(View)

在实现LiteFlow逻辑可视化编排时,我们使用的图编辑引擎是AntV X6——不光因为它足够好用、我们很常用,而且我们用起来也挺有心得,感兴趣的朋友可以看我之前写的文章:「AntV X6」从5个核心要素出发,快速上手AntV X6图可视化编排

Liteflow逻辑编排可视化设计.png

我们目前初步实现了LiteFlow的以下3类/6种逻辑可视化:

  • 1、顺序类:串行编排(THEN)、并行编排(WHEN);
  • 2、分支类:选择编排(SWITCH)、条件编排(IF);
  • 3、循环类:FOR循环、WHILE循环。

我之前写过一篇文章:《Liteflow逻辑编排可视化设计》,感兴趣的朋友可以先看一看。

3、操作逻辑(Control)

LiteFlow逻辑可视化编排-操作逻辑篇(Control)-增删改查CRUD.png

LiteFlow的逻辑可视化编排,主要是实现对ELNode模型的增删改查操作:

LiteFlow ContextPad.gif

为了方便使用,我们不光实现了通过拖拽(Drag & Drop)添加节点,而且在画布中也实现了通过快捷面板(ContextPad),在节点和边上快速新增节点。

而针对ELNode的“增删改查”,我们可以在ELNode中通过定义如下相应的方法进行实现:

export default abstract class ELNode {
  /////// 接着上面步骤 1.数据模型(Model)
  /**
   * 添加子节点
   * @param child 子节点
   * @param index 指定位置
   */
  public appendChild(child: ELNode, index?: number);

  /**
   * 删除指定的子节点
   * @param child 子节点
   */
  public removeChild(child: ELNode): boolean;
  
  /**
   * 创建新的节点
   * @param parent 父节点
   */
  public create(parent: ELNode, type?: NodeTypeEnum): ELNode

  /**
   * 删除当前节点
   */
  public remove(): boolean;

  /**
   * 转换为X6的图数据格式
   */
  public toCells(
    previous?: Node,
    cells?: Cell[],
    options?: Record<string, any>,
  ): Cell[] | Node;
  
  /**
   * 转换为EL表达式字符串
   */
  public toEL(): string;
}

以上是我们《LiteFlow逻辑可视化编排设计与实现 01-先导篇》的内容,是我们接下来系列文章的一个概览,希望能帮到有同样需求的朋友。