应用开发平台集成工作流——流程建模功能办理节点转换设计与实现

背景

对于流程设置不友好的问题,国内钉钉另行设计与实现了一套流程建模模式,跟bpmn规范无关,有人仿照实现了下,并做了开源(https://github.com/StavinLi/Workflow-Vue3),效果图如下:

实现大致原理是基于无限嵌套的子节点,输出json数据,传给后端,后端进行解析后,调用Camunda引擎的api,转换成流程模型后持久化。

上篇搭建了模型转换框架,今天重点来说任务办理节点如何处理。这里的任务办理不仅包括审批审核,也包括任务的处理,使用任务办理,覆盖范围更大,从业务含义上也更准确,毕竟审批往往是领导对下级。

办理节点,对应着Camunda中的用户任务概念,是是最常见最常用的,模型转换的重要前置工作,实际得先把该类节点的要做的配置设计好。

基础属性

节点自身的标识id,名称name和类型type,这几个属性是通用的,也是Camunda模型中UserTask类的基本属性,关系明确,对应就可以了,不在赘述。

扩展属性

工作流引擎需要跟平台整合,特别是做一些特定的功能才能满足中国式审批,需要加一些额外属性,使其更友好和方便使用,例如:能够设置下一环节是会签,还是普通审批,是否需要用户指定处理人。
办理节点,很重要的一点就是需要配置处理模式。
早期采用Camunda自带的建模器,使用bpmn-js来操作前端,对于开发来说太麻烦了,而是采用自建库表来存储节点配置信息。
本次集成采用自定义前端的方式,与自建库表存储节点配置信息的模式更匹配,直接在流程建模的绘制界面,点击节点,即可进行配置。

办理节点设置

设计原则

办理节点核心是设置处理人,人员设置需要遵循几个原则:
1.为了系统运维方便,所有的环节设置处理人为角色,不指定具体处理人,因为人可能离职或调动,如果因为这个原因升级流程模板的版本很不合理,通过角色去维护人员,给系统带来很大的灵活性。
2.多人会签,仅使用并行处理,不使用串行功能,并行效率更高,也更符合业务情况,如需串行,通常是会签人做的事情不同,在流程模板设计时就做多个环节出来更合适,而且用户不需要指定处理人的先后次序,从流程查看与跟踪上,也更容易看出当前进度。
3.当环节处理人需要指定时,存在两种情况,一是由上一环节指定,通常是离着比较“近”,比如部门领导有多个,分管范围不同,单据上可能无法添加用于系统自动区分并分发的属性,因为实际业务没有明确的规则,需要人工选择;二是由流程发起人在填报环节即指定好,例如合同法务审核,虽然角色有多人,但往往是线下已经由某人专人处理,不适合抢单签核,还有分管的副总,同部门领导情况类似。
4.通过设置角色,角色下只有1人的情况,虽然当前是不需要人工指定,但运行过程中可能出现变数,比如某一天需要往角色下加人,这种情况,还是显示角色下人员,由用户选择,并可以从前端做人性化便捷化的处理,如取到的人只有1人,直接选择该人,无需用户再下拉指定。

场景梳理

根据上面原则,梳理下有哪些情况,具体如下:

根据上图进一步梳理需要设置的节点属性,从类型看,两大类,根据处理人的数量,分为多人会签和单人签核(普通),类别下,需要一个属性来区分,是否需要人工指定处理人员。
会签:需进一步设置是否指定人员,不指定则全员参与
单人签核:需进一步设置是否指定人员,不指定则为抢单签核

此外,还需要考虑申请人指定处理人的情况,技术实现上,实际与上一环节处理人指定人是一样的,无论是申请人还是上一环节处理人,指定人员都是设置流程变量,然后通过流程实例变量分配处理人。

抢单签核

该模式不指定具体处理人,而是将任务分配给角色,该角色下所有人员都可以看到,通常用于两种应用场景:
1.处理任务的角色对应的人员职责等同,对于流传过来的单据,谁都有能力处理,不再进一步区分,例如出纳,只是因为业务量大,需要设置多人同时来处理任务
2.处理任务的角色对应的人员职责不同,不同的人负责不同类型的单据,需要根据单据属性来最终决定应该由某个人或某几个人来处理,并且没有明确的业务分配规则(如有,则可以通过工作流和程序来实现自动派发),这种情况下相当于在一定人员范围内模糊派单,由各负责人自行查看领取任务并处理。

技术实现上,将环节候选组属性设置为角色,提交任务时,工作流引擎会生成成样在待办任务查询时,需要考虑两种情况:一是直接分配到人,另一种是分配到当前用户拥有的角色。

从业务使用角度出发,面临的问题:
1.普通任务和抢单任务,应该在同一个界面显示,并且最好按照同一维度排序(如任务到达时间),但抢单任务最好可标记,可过滤(从优先级上来说,已经分配到人的任务是“必办”任务,而分配到角色的是“可选”任务)

解决思路:
1.通过底层sql来实现,将按角色分配这种任务转换为可查询的数据
2.在应用层面单独处理抢单签核类型的单据,进行数据合并

环节人员设置实现

现状

前端开源项目环节设置如下图所示
image.png
按照我的设计,该界面属性会大幅调整,相应的数据结构也会大改。

改造

后端辅助

同一个流程模板,会有多个版本,而环节配置是隶属于某个流程模板的某个特定版本的,因此在流程模板编辑时,仅靠流程模板编码无法定位到相应的环节配置,还需要版本号。

原方案

之前集成工作流,使用Camunda modal时,采用的方案如下:
Camunda对应每个流程模板,有一个属性processDefinitionId,该值由三部分组成,流程编码+版本号+发布标识(一个uuid),因此可以将该属性作为环节设置的唯一性标识。
但这里有一个问题,发布标识只有在发布后才会产生,因此需要考虑几种场景的处理应对:
1.新增流程模板,进行环节配置,此时没有进行发布,有流程定义标识
2.修改流程模板,进行环节配置,此时已发布过,有流程定义标识,且流程标识与环节配置一致
3.升级流程模板,进行环节配置,此时已发布过,有流程定义标识,但流程标识与环节配置不一致(此时配置和修改的,实际是下一版本)

场景2属于常规的操作,直接操作即可。
场景1和场景3,需要生成临时的流程定义标识,并且在发布后,将临时标识更新为实际的标识。

既然流程编码+版本号能唯一确定一条流程,那么我们临时版本号流程定义标识就以这两部分组合产生。
并且深入想一下,如果在新增流程模板时,预先将版本号设置为1.0.0,那么场景1和场景3可以认为是同一个场景。

新方案

上面方案需要组合属性,意味着增加了额外的处理和解析,既然我们的前端已经不适用Camunda Modal 了,也意味着不再有限制,完全可以自由设计与实现,因此在环节配置实体中,直接使用流程模板编码和流程模板版本两个属性。

方案选择

在后续的实际改造过程中,Camunda在多处实体属性和api中都使用了processDefinitionId,如任务,采用新方案反而需要做很多的转换工作,因此采用原方案来实现。

具体实现

使用平台的低代码配置功能,实现后端环节配置实体的配置、库表生成、前后端代码生成,过程就不再展示了,只截图显示下结果。
image.png

环节名称也归到了环节配置里面,因为后面流程审批时,需要读取该表,显示下步流向哪个环节。
image.png

前端调整

用户任务环节单独处理

首先调整nodeWrap组件,将用户类型的组件单独拿出来处理。

 <div class="node-wrap" v-if="nodeConfig.type == 1">
    <div
      class="node-wrap-box"
      :class="
        (nodeConfig.type == 0 ? 'start-node ' : '') +
        (isTried && nodeConfig.error ? 'active error' : '')
      "
    >
      <div class="title" :style="`background: rgb(${bgColors[nodeConfig.type]});`">
        <span>{
   
   { nodeConfig.nodeName }}</span>
        <i class="anticon anticon-close close" @click="delNode"></i>
      </div>
      <div class="content" @click="setUserTaskNodeConfig">
        <div class="text">
          <span class="placeholder" v-if="!showText">请选择{
   
   { defaultText }}</span>
          {
   
   { showText }}
        </div>
        <i class="anticon anticon-right arrow"></i>
      </div>
      <div class="error_tip" v-if="isTried && nodeConfig.error">
        <i class="anticon anticon-exclamation-circle"></i>
      </div>
    </div>
    <addNode v-model:childNodeP="nodeConfig.childNode" />
  </div>

环节名称因为在环节配置里面有了,这里就取消了原有的点击取消功能。因为原项目涉及到很多地方使用type的属性,暂时保持用数字1,后面调试通了再修改为我们自己定义的有业务含义的USER_TASK.

新建自己的环节配置页面,UserTaskNodeConfig.vue,界面效果如下:
image.png

用户任务环节设置属性重定义

开源项目数据结构中新增属性userTaskNodeConfig,用于存放环节配置,与后端数据结构一致

   // 初始化数据
      defaultNodeConfig: {
        nodeName: '填报',
        nodeId: '1',
        type: 'FIRST_NODE',
        userTaskNodeConfig: {},
        conditionList: [],
        childNode: {}
      }

流程发起权限改造

原开源项目,首环节需要设置发起人,即控制流程启动权限。从设计角度而言,我认为这种方式是不合理的,权限控制放在了流程模板里,如果要变更流程发起人员范围的话,即使不需要升级流程版本,修改的入口放在这里也比较怪异。
我们应该追求更灵活的设计,实现像设置功能菜单权限一样来控制流程启动权限,这样方便运维。基于该设计,首环节就不再需要设置流程权限,因此对开源项目做了裁剪,主要涉及到以下几方面:
1.节点属性中去除相关属性flowPermission
2.移除人员选择组件promoterDrawer

抽屉组件更换为对话框

环节配置时,原开源项目使用抽屉组件,实际环节需要配置的内容项目有限,抽屉组件会大面积留空,影响美观,更换为对话框。

后面会增加表单权限的配置,因此咱不考虑更换。

移除状态管理

在组件内部使用状态管理,直观上比较重,一度考虑进行代码改造,使用props进行组件内传值。在深入了解代码结构后,节点是递归嵌套的,多层级组件使用状态管理共享属性和传递值反而是最合理的,因此移除改造取消。

开发平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。

Guess you like

Origin blog.csdn.net/seawaving/article/details/132082848