全部文档
文档中心工作流最佳实践

最佳实践

由于流程配置的特殊性,单纯的配置项很难理解工作流编排要如何实现一个具体的需求,因此对于在流程编排中需要经常用的配置方式,此处进行统一整理和归纳。


下方示例的配置方式即为工作流组件推荐的配置方式,同时也建议在流程编排时能够尽量考虑流程图的可读性,尽量保证流程图的整齐显示,方便在复杂情况下后续进行需求的调整,也尽量注意相关逻辑的说明,以便于其他人在查看时能够快速获取流程图的相关含义。

详细的配置信息在对应节点中进行查看,此处只讲解配置的思路和最终配置后的流程图。

工作流中普通的用户任务配置,推荐使用「单人任务」节点进行配置,需要进行会签/或签时,需要使用「多人任务」节点。



在多人任务节点中,配置多个输出结果,然后在完成规则中选择会签/或签/等待特定应答,可实现对应需求

  • 会签:会等待当前节点的所有任务完成,最终根据完成情况,按照不同输出结果的数量,确定当前节点的数量

    • 默认输出应答数量最多的结果,当出现两种最高的应答结果数量相同时,输出首先应答的那个结果

  • 或签:等待当前节点的第一个任务完成,然后输出第一个任务的应答结果

  • 等待特定应答:等待设置的等待应答结果,然后输出约定的应答内容

    • 可以利用此配置实现一票否决的操作,等待否决应答,然后结束当前节点,输出配置的应答结果

在平行网关中,已经对此部分进行了讲解,但是鉴于该场景较为常见,因此此处再次单独说明。

  • 平行网关可以进行流程的分支拆分和合并,拆分操作可以将流程拆分成多个平行进行的流程分支,合并可以将多个分支合并到一起继续向下运行。

  • 示例如下,先利用「调用子流程」节点进行多个分部分的分开审批,然后进行合并后的统一审批

大部分审批场景中,后续审批节点需要在某些情况下驳回流程,使得前置节点重新完成任务。以下将通过几个简单的例子描述如何实现驳回逻辑。

驳回在DeepFlow中不是一个固定的配置,需要多个节点结合后共同实现。实现一个驳回逻辑,需要以下几个配置。

  • 一个用户任务节点(审批节点),用来进行操作

  • 一个网关节点,用来判断审批结果(是否驳回/继续向下执行)

  • 一个跳转节点,根据逻辑跳转回到目标节点继续执行

示例如下:


提交节点后,涉及A、B、C三个审批节点:

  • A节点处理时,可驳回至提交

  • B节点处理时,可驳回至提交A节点

  • C节点处理时,可驳回至提交A节点B节点

在基础驳回操作中增加跳转操作,A、B、C节点可跳转的范围依次为:[提交]、[提交A节点]、[提交A节点B节点]



示例如下:


使用态(跳转动作不支持快速处理,需进入任务处理页面):

拓展:若涉及到数据状态变更,例如提交后(A审批前),数据状态为“submitted”,A审批后(B审批前)为“A_approved”,则可以在节点配置监听,当任务创建时/开始后,执行用于更改数据状态的工作流,这样每次驳回后,例如从C驳回A,数据状态则会从“B_approved”更改为“submitted”。


工作流示例:


平行网关的驳回较上述的一条分支的驳回较为特殊

  • 上述基础驳回场景下,可以直接驳回到需要驳回的节点

  • 平行网关中的驳回,按照同样的逻辑,似乎应该驳回到平行网关处,但是,平行网关作为合并时,会等待所有分支流程的到达,如果直接配置跳转到平行网关,会导致流程运行到平行网关时,由于一直等不到跳转节点的运行,而卡死在平行网关处

  • 因此,对于涉及平行网关的驳回,可参考以下流程图

    • 会签驳回之,需要驳回到平行网关之前,因此在平行网关前面配置一个空的没有任何条件的排他网关专门用来做驳回的跳转使用

多实例子流程通过数组变量动态下发流程,因此有两种情况

  • 全部驳回时,和普通的驳回一致,只需要跳转回到「多实例子流程」节点,然后按照之前的数组重新下发流程就好

  • 部分驳回时,由于「多实例子流程」节点具体执行多少条子流程只和数组变量内的成员数量有关,因此只需要想办法修改数组变量中的成员即可

    • 推荐1:目前最直接的方法,就是通过PY节点查询关联的业务数据状态,查询当前全部审批的流程中有多少条驳回了,然后返回对应的已经驳回的业务数据数组,只有驳回的数组进行多实例子流程的下发即可

    • 推荐2:后续会增加直接在任务完成时从UX中获取参数,即可直接从UX中获取想要驳回的数组数量

撤回在工作流中需要通过一系列的配置实现,主要是因为在财务场景中,经常涉及到对业务数据状态的变更,有时候也需要做一些业务数据的校验和其他操作,因此会比简单的OA等场景中的撤回复杂一些。


常见的撤回包括:

  • 用户提交任务之后基础撤回:目前已经支持,下方将进行演示

  • 用户发起流程之后撤回:配置与上述类似,但是需要在流程全局设置齿轮中配置(暂未开发完成)

  • 其他情况:多人任务单实例的撤回、平行网关内任务的撤回等复杂场景的撤回,暂不支持

撤回依靠流程引擎中的边界事件实现,可以这样理解:

  • 后置的审批节点需要配置边界事件订阅撤回,在未完成之前,只要接收到撤回消息,就会终止当前节点并触发跳转事件,例如跳转回提交节点

  • 前置的提交节点需要配置撤回动作,例如在本节点完成后,展示撤回动作的按钮,点击后会发送撤回消息至后置的审批节点审批节点接收到撤回消息,终止当前节点并触发跳转。

基础的撤回示例如下,需要在提交节点配置撤回动作,在将要撤回的审批节点配置撤回的边界事件,当提交节点完成、审批节点还未完成时,可以进行撤回操作

  • 流程图

  • 审批节点配置

  • 提交节点配置:在任务完成后展示撤回按钮,点击可以撤回进行到审批节点的流程

背景: 提交后,流转到多人任务-审核节点(选择了3位用户并行审核),然后流转到单人任务-复核节点。


**要求: **流转到多人任务节点和单人任务节点时,只要该节点还未完成,都可以由提交节点触发撤回,撤回到提交节点。

  • 流程图

  • 审批节点配置:都在监听中配置订阅撤回,一旦接收到撤回消息,执行goto提交节点,goto提交节点则跳转回提交节点

  • 提交节点配置:在任务完成后展示撤回按钮,用于对目标审批节点发送撤回消息,目标节点接收到订阅的撤回消息后,触发goto提交节点,撤回进行到提交节点(与审批节点配置形成闭环)

  • 针对可撤回多人任务节点的特殊说明:

    • 如果撤回的执行条件为【无条件】:只要多人任务整体节点未完成,都可以撤回

    • 如果撤回的执行条件为【自定义】:条件中选择了多人任务节点,仅当多人任务中没有任何一个任务实例被完成,该条件才为true(满足撤回条件),否则为false(不满足撤回条件)


      **举例说明: **多人任务为会签,需要三个人处理

  1. 撤回的执行条件为【无条件】

  • 提交后,多人任务还未开始:允许撤回

  • 提交后,多人任务中已有一人处理、还有两人未处理:允许撤回

  1. 撤回的执行条件为【自定义】,执行条件中配置了**多人任务**节点

  • 提交后,多人任务还未开始:允许撤回

  • 提交后,多人任务中已有一人处理、还有两人未处理:不允许撤回

用户任务在任务的生成和到期时,需要进行任务的相关信息提醒,此时需要用到用户任务的监听配置。

  • 用户任务的生命周期不能在当前流程中进行干预,因此只能通过监听这种方式在用户任务的进程中,通过启动隔壁专门的通知工作流,实现通知的功能

通过用户任务「任务开始后」监听,可以实现用户任务开始时对相关执行人进行用户任务开始提醒

  • 首先需要配置一个单独的提醒工作流

    • 发送人采用动态配置,读取流程启动参数重传递进来的参数

    • 其他相关配置见「通知」节点的配置说明

  • 用户任务的监听中配置启动工作流

    • 激活计时器配置的首次激活时间为变量:acp$start_time,表示在任务开始时进行用户任务提醒,重复激活等配置根据需要配置

    • 启动工作流选择配置的通知用的工作流

    • 通知人通过启动参数传递给需要启动的工作流

      • 对于单人任务,可以考虑将candidate数组传递给通知工作流,因为assign的生成需要时间,且在候选人有多人的情况下,不会自动生成assign的值

      • 对于多人任务,可以直接传递assign

任务到期的提醒与任务开始的提醒实现方式一致,将激活计时器配置的首次激活时间为变量:acp$due_time即可。

  • 多个通知可以在一个子流程中实现,通过启动参数中传递一个通知类型的字段用来区分,然后在子流程中通过网关判断后走不同分支即可。

综上所述,可以在用户任务的任务进行中,通过监听的方式实现很多自定义的需求,不仅可以用来启动通知的流程进行消息通知,也可以启动一个其他流程,实现其他相关操作,包括记录一些自定义的和业务数据相关的日志等。

工作流中任务数据的状态和业务数据的状态是相互不关联的,因此如果需要修改数据状态,需要通过「PY脚本」「更新数据表」「领域模型」「DeepQL」等节点调用对应数据表的服务,修改对应数据的状态。


对于基础的修改,比如流程开始修改数据状态,可以直接将对应节点关联到流程图中即可,对于单人任务完成后修改状态,也可以直接在流程图中通过节点进行操作。

但是有一下一些问题:

  • 多人任务在任务完成后如果需要修改数据状态或者修改数据,直接配置不能实现

  • 每个单人任务后均配置一个修改数据的节点

    • 极大增加了当前业务流程的复杂度,每增加一个用户任务节点就要增加一个修改数据的节点,同时这种自动化的节点对于流程逻辑的查看没有明显帮助,只会干扰到正常业务逻辑的查看

    • 如果遇到修改逻辑,需要将每一个修改数据的节点均进行调整

基于上述的问题和其他问题,我们推荐通过「用户任务完成后监听」来实现用户任务完成后进行业务数据修改的需求。


同任务提醒一样,这种方式也是通过启动隔壁的工作流来实现的,也就是说需要有一个单独的工作流来配置任务数据的处理,业务主键和要进行的操作应当作为子流程的启动参数传递给数据修改工作流,然后此工作流根据启动参数进行对应的数据修改操作。

  • 关于如何修改数据状态,可根据需要查看「PY脚本」「领域模型」「更新数据表」相关节点的配置说明

  • 任务后的监听配置如下图所示

目前多实例执行方式只有并行,执行时会根据启动多实例的数组,对数组变量中的每个成员,创建1个子流程实例,但创建子流程实例的先后顺序无法指定。


若对子流程实例内的任务/服务的处理顺序有要求,可参考如下思路,在子流程的开始节点后增加等待计时节点,以达到控制顺序的目的。

业务场景举例:主流程中利用多实例子流程节点为HR用户,生成结算各部门工资的子流程任务,但各部门间的任务处理有先后顺序。

  1. 需要存储部门的处理顺序,本例中用对象举例

  2. 启动多实例的数组:department_code

  3. 子流程中定义全局变量

定义的全局变量都基于启动参数department_code作为查询条件。


  • 定义全局变量department_name(string),初始值为查询部门名称的JS,用作任务名称:

Copy
var a = fn$queryByDeepQL(
  "select department{*} filter .department_code = <str>$department_code", 
  {"department_code":wfi$department_code});

a[0].department_name["zh-cn"]
  • 定义全局变量order(integer),初始值为查询处理顺序的JS,用作计算等待时间:

Copy
var a = fn$queryByDeepQL(
  "select department{*} filter .department_code = <str>$department_code", 
  {"department_code":wfi$department_code});

a[0].order
  • 定义全局变量cal_time(datetime),基于流程实例开始时间和order,计算等待时间,流程实例开始后需要等待order-1分钟:

Copy
// 基于流程实例的开始时间
var currentDate = new Date(wfp$start_time);
 
// 要增加的分钟数=oder-1
var minutesToAdd = (wfv$order-1);
 
// 增加分钟数后
currentDate.setMinutes(currentDate.getMinutes() + minutesToAdd)

currentDate
  1. 子流程中,在开始节点后,增加等待计时节点,基准时间设为**cal_time**

  2. 子流程中,后续任务节点的名称展示部门名称和顺序号,以备检查

  3. 效果展示

    1. 发起主流程,数组是[“PURCHASE_2”,”PURCHASE_1”,”SALES_1”,”SALES_2”]

    2. 维护好的顺序是

    3. 进入待办,查看子流程的任务开始时间:确实按照设定的顺序生成

业务场景举例:


主流程中利用多实例子流程节点发起一系列表单的预算填报,调用的子流程中仅包含一个单人任务节点,当对应预算员提交后,完成此子流程。

需求:

预算员在子流程中提交预算后,可随时撤回,一旦撤回,则全部表单重新发起,需要全部重新填报。

核心实现逻辑:

  • 子流程的UX-任务处理界面中配置按钮,关联发起消息事件(用来向主流程发送撤回消息)

  • 主流程中配置等待消息节点(用来等待撤回消息)

  • 主流程中配置发送消息节点(用来终止其他预算填报的子流程)

  • 子流程中配置等待消息节点(用来接收到消息后终止当前流程)

具体配置:

  1. 主流程设计

    1. 创建消息budget_withdraw,添加参数withdraw(boolean),用来接收撤回消息

    2. 增加全局变量submit_count(integer)、budget_withdraw(boolean),分别用来记录已提交的预算数量、是否有预算员撤回

    3. (多实例子流程)预算员填报节点:增加完成时映射

      1. wfv$submit_count=如下JS表达式

Copy
var result = macr$list_of_submit_result
var result1 = result.filter(function(item) {
  return item !== null;
})
var count = result1.length
count
Copy
  2. `wfv$budget_withdraw`=如下JS表达式
Copy
!(wfv$submit_count == macp$nr_of_instances)
  1. (排他网关)是否有撤回节点:

    1. 条件1(有人撤回):wfv$budget_withdraw=true(静态值)

    2. 条件1跳转至节点:重新发起预算员填报

    3. ELSE跳转至节点:更新提交状态-已填报待部门提交

  2. (跳转)重新发起预算员填报节点:

    1. 跳转目标:重置任务状态-待提交

  3. (等待消息)等待撤回消息节点:

    1. 订阅消息budget_withdraw

    2. 完成时映射wfv$submit_count= true(表达式)

  4. (发送消息)终止进行中的所有子流程节点:

    1. 发送目标是:其他流程-预算员填报的子流程

    2. 发送消息:在子流程中定义的消息terminate_msg

    3. 消息参数:true(表达式)

    4. 发送范围:广播(因为需要所有子流程实例都终止)

  5. 原本主线流程中的结束节点更改为终止节点,防止因为等待消息节点一直在进行中而无法结束流程

  6. 子流程设计

    1. 创建消息terminate_msg,添加参数terminate(boolean),用来接收终止消息(节点内编排的终止节点,用于完成整个流程实例)

    2. (等待消息)等待终止消息节点:订阅消息terminate_msg

    3. (单人任务)预算员填报节点:待办跳转界面增加跳转参数parent_proc_id=wfp$parent_proc_id,用来向主流程发送撤回消息

    4. 原本主线流程中的结束节点更改为终止节点,防止因为等待消息节点一直在进行中而无法结束流程

  7. UX-任务处理页面设计(这是子流程中单人任务预算员填报节点的待办跳转界面):

    1. 增加数据源DeepQL,QL语句中的space编码需替换:

Copy
# 仅当该流程实例中,已完成的任务、当前用户是任务处理人时、父流程还在进行中,才可以看到撤回按钮
select DFTask{*}
filter
    .process.proc_inst_id = <str>$proc_id
    and .task_status = "Completed"
    and .assignee.system_user = global spacehreevs::current_user
    and .process.parent.state = "ACTIVE"
order by .start_time desc
limit 1

  1. 增加撤回按钮

    1. 隐藏条件(条件中的数据源编码需替换):($var.task_id == null) || ($dataSources.data_query3_EMcZ.data?.[0].task_inst_id != $var.task_id)

    2. 事件为发起消息事件,向主流程发送budget_withdraw消息,消息参数withdraw赋值true(表达式),发送范围的流程实例ID是$urlQuery.parent_proc_id

需求:


PY脚本节点为同步执行,但因脚本执行时间过长导致超时报错。

核心实现逻辑:

  • PY脚本改为【异步】执行

  • PY脚本后增加【等待消息】节点

  • PY脚本中增加入参流程实例ID、增加【发送消息】

具体配置:

  1. 流程设计

    1. 创建消息py_completed,无需添加参数

    2. PY脚本节点:

      1. 添加所需参数proc_id=wfp$proc_id

      2. 调用方式改为异步

    3. PY脚本节点后增加等待消息节点,等待消息py_completed

  2. PY脚本设计

    1. 添加入参proc_id,用来接收工作流传出的流程实例ID

    2. 执行完业务逻辑后,执行发送消息,API文档见:工作流元素 — DeepFOS,send_msg_to_processes的三个参数说明

      1. msg_code:消息编码,本例中为'py_completed'

      2. msg_body:消息体内参数和值,因为本例中未定义消息内的参数,给空即可

      3. processes:要发送的流程实例ID列表

  3. 效果展示

回到顶部

咨询热线

400-821-9199

我们使用 ChatGPT,基于文档中心的内容以及对话上下文回答您的问题。

ctrl+Enter to send