LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)

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

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

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

  1. LiteFlow逻辑可视化编排设计与实现 01-先导篇
  2. LiteFlow逻辑可视化编排设计与实现 02-数据模型篇(Model)
  3. LiteFlow逻辑可视化编排设计与实现 03-视图呈现篇(View)
  4. LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)

以下是《LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)》的文章正文。

04-操作逻辑篇(Control)

回顾一下我们在《先导篇》中提到过的内容,作为一名前端开发,我们需要特别关注的要素有三个------数据(Model)、视图(View)和逻辑(Control),即"MVC"------我接下来也是使用"MVC三要素"的知识框架来进行LiteFlow逻辑可视化编排系统的拆解、组合、设计和实现的:

在《数据模型篇》,我们完成了EL表达式的操作符(Operator)的建模工作,最终我们将EL表达式建模成了由ELNode组成的一棵树:

在《视图呈现篇》,我们完成了使用AntV X6的节点(Node)和边(Edge)进行ELNode的逻辑可视化呈现:

接下来,我们将实现LiteFlow逻辑可视化编排的"编排"部分实现了:

我们对"编排"的操作逻辑做进一步的拆解,也就是我们常说的"增删改查"(CRUD)操作了,在这里的具体实现,就是对ELNode模型的树型结构进行"增删改查":

1、ELNode模型的增删改查

我们实现的LiteFlow逻辑可视化编排的增删改查,最终是通过调用ELNode模型的相应方法来实现的,其中定义的部分方法如下:

typescript 复制代码
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逻辑可视化编辑器的功能原型,页面大体是经典的"左中右"3栏布局,内容由以下4个面板组成:左侧的"物料区"、中间的"画布区"、右侧的"设置区",以及顶部的"工具栏":

    1. 物料区:在页面的左侧是"物料区",这里提供了可供选择的各类逻辑组件,主要包括:
      ① 节点类:在实际项目中,节点将会是最多的,这里为了方便只放了一个节点组件,组件的id属性会随机生成为"Placeholder[1-9]"形式;
      ② 顺序类:串行编排THEN、并行编排WHEN;
      ③ 分支类:选择编排SWITCH、条件编排IF;
      ④ 循环类:FOR循环、WHILE循环。
      通过拖拽左侧物料区的各个逻辑组件到中间画布,可以实现组件节点的新增和修改。
    1. 画布区:页面中间最大的区域是画布区,整个LiteFlow的逻辑可视化在这里进行的呈现,除了逻辑可视化的主要内容"节点"和"边"之外,同时在节点和边上有相关的操作按钮,可以方便进行逻辑组件的"增删改查"操作,目前主要包括的可用操作如下: ① 节点上的可用操作:在节点前面/后面插入节点,替换当前节点,删除当前节点; ② 边上的可用操作:在边所在的位置插入节点(相当于在边前面的节点后面插入新节点)。
    1. 设置区:在页面右侧是设置区,默认显示LiteFlow的EL表达式;在选中某个逻辑节点组件之后,则显示该组件可设置的属性,比如LiteFlow常用的id和tag等属性;
    1. 工具栏:在页面顶部是工具栏,包含LiteFlow逻辑可视化编排时常用的画布缩放、撤销/重做等等功能。

接下来,我们对LiteFlow逻辑可视化编排的"增删改"分别进行讲解。

2、新增(Create)

2.1 通过拖拽新增

在左侧物料区,可以通过拖拽需要的逻辑组件到中间的画布区、实现逻辑组件的新增:

这里的拖拽节点到画布的实现,是使用了AntV X6的Addon.Dnd,简化后的实现方法如下:

typescript 复制代码
const dnd = useMemo(
    () =>
      new Addon.Dnd({
        target: flowGraph,
        scaled: true,
        validateNode: (droppingNode: Node) => {
          const position = droppingNode.getPosition();
          const { node } = droppingNode.getData();
          const cellViewsFromPoint = flowGraph.findViewsFromPoint(
            position.x,
            position.y,
          );
          let cellViews =
            cellViewsFromPoint.filter((cellView) => cellView.isEdgeView()) ||
            [];
          if (cellViews && cellViews.length) {
            const currentEdge = flowGraph.getCellById(
              cellViews[0].cell.id,
            ) as Edge | null;
            let targetNode = currentEdge.getTargetNode();
            let { model: targetModel } = targetNode?.getData<INodeData>() || {};
            targetModel?.append(
              ELBuilder.createELNode(node.type, targetModel),
            );
          }
          
          return false;
        },
      }),
    [flowGraph],
  );

在这里我们做了这么一个设计------只有拖拽节点到画布中的边上、才能新增节点------因此在上面validateNode方法的最后、返回了false

2.2 通过快捷面板(ContextPad)新增

在中间的画布区的节点和边上,有相关的操作按钮,可以方便进行逻辑组件的新增操作: ① 节点附近新增:在节点前面/后面插入节点;

② 边上新增:在边所在的位置插入节点(相当于在边前面的节点后面插入新节点)。

这里我们设计了一个ContextPad组件、用来快捷插入节点------这样就实现了不通过拖拽、而是直接在画布中进行组件的新增。

这里ContextPad组件的实现,是通过使用AntV X6的自定义事件机制,唤起ContextPad组件的实现代码如下:

typescript 复制代码
const showContextPad = debounce((info: any) => {
  node.model?.graph?.trigger('graph:showContextPad', info);
}, 100);
const onPrepend = (event: any) => {
  showContextPad({
    x: event.clientX,
    y: event.clientY,
    node,
    scene: 'prepend',
    title: '前面插入节点',
    edge: null,
  });
};
const onAppend = (event: any) => {
  showContextPad({
    x: event.clientX,
    y: event.clientY,
    node,
    scene: 'append',
    title: '后面插入节点',
    edge: null,
  });
};

3、修改(Update)

2.1 通过拖拽修改

在左侧物料区,可以通过拖拽需要的逻辑组件到中间的画布区的组件节点上、实现该组件节点的替换:

2.2 通过快捷面板(ContextPad)修改

在中间的画布区,节点的工具栏上有一个替换按钮,可以方便进行逻辑组件的替换操作:

2.3 通过设置面板修改

在页面右侧是设置区,在选中某个逻辑节点组件之后,可以设置该组件的LiteFlow属性,比如id和tag等等:

4、删除(Delete)

4.1 通过工具栏删除

在中间的画布区,节点的工具栏上有一个删除按钮,可以方便进行逻辑组件的删除操作:

4.2 通过快捷键删除

在中间的画布区,我们可以通过快捷键backspace或者delete进行删除,比如这里我通过ctrl + a进行组件全选,然后按delete键进行了删除:

这里的实现比较简单,实现代码如下:

typescript 复制代码
flowGraph.bindKey(['backspace', 'del'], () => {
  const toDelCells = flowGraph
    .getSelectedCells()
    .filter((cell) => cell.isNode());
  if (toDelCells.length) {
    Modal.confirm({
      title: `确认要删除选中的节点?`,
      content: '点击确认按钮进行删除,点击取消按钮返回',
      onOk() {
        toDelCells.forEach((node) => {
          const { model } = node.getData() || {};
          model?.remove?.();
        });
        history.push();
      },
    });
  }
  return false;
});

需要注意的是,我们在使用AntV X6进行以上交互实现时,关键的API的是都是通过调用Graph的相关方法实现的。如果大家也使用AntV X6进行类似的图可视化编辑器实现时,所以推荐大家对Graph的相关API一定要熟悉。

以上是我们《LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)》的内容,我们完成了------不光可以通过拖拽,而且也可以通过ContextPad快捷面板,以及节点和边上的工具栏的操作按钮------实现LiteFlow的逻辑可视化编排的"增删改查"操作。

相关推荐
Fan_web9 分钟前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常10 分钟前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇1 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr1 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho2 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常3 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记4 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java4 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele4 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范