流程设计

willian fu 2022 ~

流程设计

流程设计是用来设计审批所需要经过的那些步骤,在此处进行设计

配置流程/节点监听器

流程监听器

有时候我们需要在流程产生事件时执行自定义的业务逻辑,那么就可以在此处进行配置

image-20231216181529868

支持的事件配置

  • 当流程启动成功时
  • 当流程审批通过时
  • 当流程被驳回导致流程结束时
  • 当流程被撤销时

每个事件点都可以配置多个事件

image-20231216181853914

节点监听器

当流程经过节点时我们可对某个节点设置监听器执行自定义逻辑。

支持的事件类型

  • 流程进入该节点时
  • 流程离开该节点时

支持的节点类型

  • 发起人节点
  • 审批节点
  • 办理人节点

配置使用方式

支持调用java调用js代码发起http请求

📢📢 以上监听器配置方法请参考事件执行

支持的节点类型

image-20231217220732434

审批人节点

审批人节点是用来设置该处需要人来进行审批的,当流程到此处时,将会给节点内设置匹配到的人员创建审批任务,当本节点审批通过时则继续进入下一步

支持的审批人规则

image-20221229145749301

指定人员

顾名思义,直接指定该节点的审批人为某些人,这样就是把人员定死了

发起人自选

选则本项时,该节点的审批人将由发起人在发起流程填表单时,手动选择,效果如下图

image-20221110224715810

多级部门主管

首先每个部门都可以设置一个主管,也就是部门负责人,做为该审批选项的基础,部门层级可能存在多级,通过本选项可以设置一级一级的领导依次进行审批

image-20221110225414691

🖐审批终点

利用审批终点设置,可以控制多级领导依次审批,限制在多少级,比如可以设置第3级领导审批后就截至

📌 提取规则

有时候中间某个部门没有设置部门主管/负责人,那么可以通过该选项指定是否一定要匹配到负责人才算ok,还是没有设置负责人本部门就按空处理

部门主管

也就是部门负责人,可以设置为发起人的指定级别的主管,如果级别为1,那么就是发起人的直接主管

如果发起人本身就是部门主管,那么他的直接主管就是他上级部门的主管

指定角色

指定审批人为系统内的拥有某些角色的人员

发起人自己

发起人自己作为审批人进行审批

表单内联系人

当设置为表单内联系人时,需要表单内至少存在一个选人组件,审批人将会提取选人组件内选择的人员进行审批

指定部门的主管

指定选择几个部门,审批人为该选择的部门的主管

表单内部门的主管

将表单内部门选择组件,选中的部门的主管,作为审批人,需要改部门存在部门主管才能取到人

系统(自动拒绝)

当流程走到该处时,将会被系统自动拒绝,让流程直接被驳回,然后结束

某些情况下,当流程满足某个条件时,需要流程被直接驳回,此时就可以利用该选项实现。它应当被使用在包含多条件分支的流程分支中,否则流程设置没有意义啊

抄送人节点

发送消息通知,告知相关用户,抄送的话可以设置选择抄送指定部门下的人员以及指定具体的人

注意,选择抄送部门时,只会选中该部门下的人,但是如果该部门内部还有部门的话,不会选中这个内部部门的人!

条件分支

当流程到达条件分支时,会选择第一条满足条件的分支执行,可以用来实现通过不同的条件走不同的流程。

image-20231215161917602

条件分支的条件支持4种简单模式逻辑表达式js解析网络请求,基本能覆盖到100%的业务场景

简单模式

简单模式提供了简易的UI界面,给普通用户构造审批条件

概念

  • 条件组:可以包含多个子条件的分组
  • 子条件:单个的条件
  • 条件组关系:条件组之间的逻辑关系(与、或)
  • 组内条件关系:当前条件组内的子条件之间的逻辑关系(与、或)

设置方法

在简单模式下,我们可以为条件组设置条件关系

image-20231215162936860

如图,点击 + 弹出添加条件的弹框,勾选要添加的条件后,对应条件即可出现在条件组面板内

image-20231215163207823

如何添加备选条件?

📢📢 默认只有 流程发起人 这一个可选条件,如果需要更多的条件请在表单设计器中,将对应字段设置为必填 ,即可加入条件判断

目前简单模式支持如下类型表单字段组件【人员选择、部门选择、数字输入、金额输入、计算公式、单选框】

逻辑表达式

逻辑表达式使用了spring的EL表达式,利用其强大特性,我们可以实现任意自由度的条件判断需求

image-20231215164031275

设置方法

😘 举一些设置案例给大家参考

📢 注意:实际使用时,我们需要让表达式的值为 true / false,否则条件无效

调用被spring托管对象内的方法

@userService.isAdmin('张三')

其中 userService 注册到了spring容器内,isAdmin 是它里面的方法

我们要使用 @ + bean的name 来引用这个对象即可

调用指定类的静态成员及方法
T(Integer).parseInt('100')
T(com.test.Print).print('打印内容')    

使用 T(),传入类名或类全路径即可获取对应类

取上下文变量值

我们的表单内字段值是全部注册到了上下文内,通过表单id即可取到

#fieldxxxxxx > 3 && #fieldxxxxxxx < 10

使用 # + 表单字段ID / 上下文变量名 来取该变量的值,然后即可随意构造表达式

我们再演示一个表单字段值是个对象的栗子

对象类型的表单字段值,在系统上下文内是个Map,所以我们要使用取map值的语法

#fieldxxxxx['user']
#fieldxxxxx['user']['name']

先通过#fieldxxxxx 拿到该字段值,再通过 ['user'],取到该字段内user对象值,如果还要往下取继续这个写法即可

注意事项

请务必保证表达式的值,或者其返回的值类似是 true / false,否则条件无效!!!

JS解析

我们还为熟悉JS的同学提供了JS代码判断条件的方案,构造一段返回值为 true / false 的代码

image-20231215171141591

该段代码默认注入了一个上下文对象,名称为 ctx

ctx值可参考后端 com.wflow.workflow.UELTools.conditionCompare(ConditionProps props, Map<String, Object> ctx)

通过ctx,我们可以直接拿到表单及其他上下文变量,然后利用其进行代码逻辑判断,最终return一个比较结果给系统。

WARNING

该js是后端执行,所以与浏览器交互的相关Api不可调用

调用java类静态成员或方法

由于该段JS是在后端运行的,所以我们为了实现更加灵活的功能,加入了java代码调用的功能,调用方式如下:

Java.type("java.lang.System").out.prinln("hello world")

通过Java.type() ,传入对应类的全路径可以索引到该类,并调用静态成员或方法

注意事项:

为了放置用户编写恶意JS代码,影响系统稳定运行,wflow对用户输入的js做了沙箱环境隔离,限制了js代码的CPU占用时间、最大占用内存、对Java类的访问权限

具体参考 com.wflow.workflow.execute.JsExecute

需要暴露给js的java类可以在 JsExecute.alowJsCallJavaClass[] 中注册

网络请求

有时候我们需要通过调用外部接口,通过外部接口返回的结果来判断这个条件是否满足,这时候我们就能使用该设置项来完成了。

image-20231216140606980

这个界面相信大家都知道怎么设置了,主要讲下前置处理后置处理这个使用

前置处理

前置处理是为了在发起请求前执行一段js逻辑,该段js也是由后端执行的

image-20231216140955584

在函数preHandler中编写处理逻辑,这个ctx参数为后端com.wflow.workflow.bean.process.HttpDefinition对象,如下结构

{
    url: '请求地址',
    method: '请求方法',
    headers: [ //请求头
        {name: '', value: ''}
    ],
    contentType: '类型',
    params:[ //url里面的参数
         {name: '', value: ''}
    ],
    data: {}, //body里面的参数
    preHandler: 'function preHandler(ctx){}', //前置处理函数
    aftHandler: 'function aftHandler(rsp){}' //后置处理函数
}

在前置处理内,可以自由修改该数据,修改后后端将使用该结构参数发起请求,拿到请求结果后就进入后置处理函数中。

后置处理

后置处理是为了在发起请求并拿到接口响应后执行一段js逻辑,该段js也是由后端执行的

image-20231216142026093

在函数 aftHandler(rsp) 中可对请求结果进行处理,最后要return一个布尔值,该条件节点将以该布尔值为依据决定该条件节点是否满足条件。

rsp 参数结构如下:

{
	statusCode: 200, //http状态码,
    headers: {}, //响应头, {key: value}结构
    data: {}, //接口返回的内容对象
}

设置else默认条件

有时候由于设置的数据或者流程条件设置不合理,导致所有的条件都无法满足,流程走不下去卡死,我们要设置一个默认条件,当所有条件都不满足时,流程将会走默认条件分支。

默认条件设置目前需要切换条件模式为 简单模式,然后删除所有条件组就行,如下:

image-20231216143100402

并行分支

流程到达并行分支时,会直接执行所有的分支,并在分支结束会和处等待所有分支执行完毕后继续下一步

包容分支

包容分支与条件分支一样,可以给每个分支都设置流转条件

但是与条件分支不同之处在于,条件分支只会按顺序执行第一个满足条件的路径,其他分支就算满足条件也不会执行

而包容分支会同时执行所有满足条件的分支,每个条件都会进行判断,注意包容分支也可以设置默认条件。

子流程

有时候我们需要实现流程的复用功能,比如有一段审批步骤在很多流程里面都需要,那么我们就可以将其作为子流程单独设计,实现一段流程的复用功能。

image-20231216171051627

子流程需要单独在子流程管理页面进行设计,子流程不需要设计表单,将使用主流程的表单。

选择子流程

子流程与普通主流程不在一个地方,子流程在子流程管理菜单单独设计

image-20231216175035783

设计完的子流程需要发布才能生效,未发布的新版本子流程将会在版本号上方出现一个小黄点,每发布一次子流程将会生成一个新版本。

image-20231216175222156

如图示:在此处选中对应的子流程即可

子流程发起人

选择子流程的发起人,选中后发起的子流程将在对应人的 我发起的 列表中展示

是否每次使用新版本子流程

子流程与主流程是分开发布的,例如主流程发布的时候,子流程版本是v1 ,随后子流程进行了修改发布了版本 v2

如果选择使用最新版本子流程,那么主流程在调用子流程时,每次都会调用最新版v2

如果不选择最新版本,则会调用主流程发布时候的子流程版本,也就是初始v1

主子流程相互传递变量

设置主子流程之间变量传递

image-20231216180105306image-20231216180213381

注意事项

此处务必保证变量名与主子流程内需要使用的变量名一致

延迟等待

阻塞流程一段时间后继续

触发器

当流程到达此处时触发一个预设的动作