JeecgBoot 里两个流程引擎,你用对了吗?

2026-05-20 24 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:12 分钟

JeecgBoot 低代码平台自带两个流程模块——"协同工作"和"Flowable 流程审批"。不少团队上线后第一反应是:这俩不都是审批吗,干嘛要两个?随便选一个不就行了?结果要么把临时协作硬塞进 BPMN 流程图,审批节点画得比业务还复杂;要么拿协同工作跑正式制度流程,三个月后流程记录一团乱,审计时谁也说不清审批链路。

两个模块的设计哲学完全不同,混用代价不小。下面把它们的本质差异拆开,再给一个选型决策的实操方法。

临时拉群 vs 正式流程:底层逻辑不一样

协同工作的设计隐喻是"临时拉群办事"——有人突然需要一件事走个审批,当场选人、当场发起、当场走完。没有预定义的流程图,发起人自己决定下一步给谁审批,审批人也可以继续往下指派。核心特征:

  • 无固定流程模板,发起时才确定路径
  • 审批人由发起人或当前处理人动态指定
  • 流程结束即归档,不强调长期复用
  • 适合低频、一次性、路径不确定的场景

Flowable 流程审批的设计隐喻是"制度流程"——流程图提前画好,每个节点绑定了角色或条件,发起人只填业务数据,路径由引擎按规则自动推进。核心特征:

  • 流程图(BPMN)必须预先设计并部署
  • 节点审批人由流程定义中的表达式或角色绑定决定
  • 支持条件分支、并行网关、子流程等复杂路由
  • 适合高频、制度性、路径确定的场景

一句话总结:协同工作是"人指路",Flowable 是"图指路"。

典型误用场景与后果

误用方式 后果
用 Flowable 跑一次性临时审批 每次都要先画流程图再部署,开发成本远超业务价值;流程模板堆积,维护负担重
用协同工作跑正式制度流程(如报销、合同审批) 每次审批链路不同,无法保证合规路径;历史记录碎片化,审计时无法追溯"谁在哪个节点批了什么"
两个模块混用同一个业务表单 数据分散在两套流程引擎的表中,统计报表拼不出来;用户不知道该从哪个入口发起

最典型的坑:一个报销流程,前半段用协同工作(因为"灵活"),后半段接入 Flowable(因为"要走财务制度节点")。结果是流程断在两个引擎的边界上,状态同步全靠手工补数据。

选型决策:一张图 + 一个检查清单

选型不需要纠结,问自己三个问题:

  1. 这个流程的路径是否每次都一样? → 是 → Flowable;否 → 协同工作
  2. 是否需要审计追溯"必须经过哪些节点"? → 是 → Flowable;否 → 协同工作
  3. 流程是否会被反复发起(高频复用)? → 是 → Flowable;否 → 协同工作

三个问题中有两个指向同一个答案,就用那个。如果 2:1 拿不准,默认选 Flowable——制度性流程的合规风险比临时流程的灵活性代价更严重。

下面用一个实际项目中的配置片段,展示如何在 JeecgBoot 中为同一个业务表单分别接入两种流程,并通过前端路由区分入口。

实操示例:同一表单,双入口分流

假设你有一个"出差申请"表单 biz_trip,制度性出差走 Flowable,临时性出差(比如紧急现场支援)走协同工作。核心思路是:表单数据只存一份,流程入口在前端分流,后端通过不同 Service 调用不同引擎。

1. 表单设计——只做一份

在 JeecgBoot 的 Online 表单设计中创建 biz_trip 表单,字段包括申请人、目的地、日期、事由、预算等。不要在表单层面区分流程类型,流程类型是运行时决策。

2. 后端 Service 分流

@Service
public class BizTripProcessService {

    @Autowired
    private FlowableProcessService flowableService;  // Flowable 流程服务

    @Autowired
    private CollaborativeWorkService collaborativeService;  // 协同工作服务

    /**
     * 发起出差审批——根据流程类型分流到不同引擎
     * @param tripId  出差申请ID
     * @param processType  "flowable" 或 "collaborative"
     * @param nextAssignee  协同工作模式下,下一步审批人账号
     */
    public void startProcess(String tripId, String processType, String nextAssignee) {
        if ("flowable".equals(processType)) {
            // Flowable:流程图已预部署,按定义key启动
            // 流程定义中已绑定各节点角色,不需要手动指定审批人
            flowableService.startProcessByKey("biz_trip_flowable", tripId);
        } else if ("collaborative".equals(processType)) {
            // 协同工作:无预定义流程,发起时指定第一个审批人
            collaborativeService.startAdhocProcess(
                "biz_trip", tripId, nextAssignee
            );
        } else {
            throw new IllegalArgumentException("未知的流程类型: " + processType);
        }
    }
}

关键点: - Flowable 入口只需要 processDefinitionKeybusinessKey,审批人由流程图中的表达式决定。 - 协同工作入口必须传入 nextAssignee,因为路径是发起人当场决定的。

3. Flowable 流程定义——出差制度流程

以下是出差制度流程的 BPMN XML(简化版),部署到 Flowable 后即可被上面的 Service 调用:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             targetNamespace="jeecgboot">

  <process id="biz_trip_flowable" name="出差申请-制度流程">

    <startEvent id="start" name="发起出差申请"/>

    <!-- 部门经理审批:绑定角色表达式 -->
    <userTask id="deptManagerApproval" name="部门经理审批">
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>role:dept_manager</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>

    <!-- 条件分支:预算超过5000走财务总监 -->
    <exclusiveGateway id="budgetGateway" name="预算判断"/>

    <userTask id="financeDirectorApproval" name="财务总监审批">
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>role:finance_director</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>

    <endEvent id="end" name="审批完成"/>

    <!-- 连线 -->
    <sequenceFlow sourceRef="start" targetRef="deptManagerApproval"/>
    <sequenceFlow sourceRef="deptManagerApproval" targetRef="budgetGateway"/>
    <sequenceFlow sourceRef="budgetGateway" targetRef="financeDirectorApproval">
      <conditionExpression>${budget > 5000}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow sourceRef="budgetGateway" targetRef="end">
      <conditionExpression>${budget <= 5000}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow sourceRef="financeDirectorApproval" targetRef="end"/>

  </process>
</definitions>

部署方式:在 JeecgBoot 的流程设计器中导入此 XML,或通过 Flowable 的 REST API 部署:

# 通过 Flowable REST API 部署流程定义
curl -X POST "http://localhost:8080/flowable/repository/deployments" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@biz_trip_flowable.bpmn20.xml"

4. 前端入口分流

在 JeecgBoot 的表单详情页中,根据业务场景提供两个按钮:

<template>
  <a-form-item label="流程类型">
    <a-radio-group v-model="processType">
      <a-radio value="flowable">制度性出差(固定审批链路)</a-radio>
      <a-radio value="collaborative">临时出差(自选审批人)</a-radio>
    </a-radio-group>
  </a-form-item>

  <!-- 协同工作模式下,显示审批人选择框 -->
  <a-form-item v-if="processType === 'collaborative'" label="下一步审批人">
    <j-select-user-by-dept v-model="nextAssignee" />
  </a-form-item>

  <a-button type="primary" @click="handleSubmit">提交审批</a-button>
</template>

<script setup>
import { ref } from 'vue';
import { postAction } from '@/api/manage';

const processType = ref('flowable');
const nextAssignee = ref('');

function handleSubmit() {
  postAction('/bizTrip/process/start', {
    tripId: formState.id,
    processType: processType.value,
    nextAssignee: nextAssignee.value,  // Flowable模式下此字段忽略
  }).then(res => {
    if (res.success) {
      message.success('审批已发起');
    }
  });
}
</script>

这样用户在提交时就能明确选择流程路径,后端自动分流到对应引擎,数据始终只存一份。

上线前的检查清单

在正式启用双流程之前,逐项确认:

  • [ ] 每个业务表单只接入一个流程引擎作为主流程,辅助性通知/催办可以用协同工作,但主审批链路不要跨引擎。
  • [ ] Flowable 流程图已部署并验证——至少跑一遍完整路径的测试发起,确认节点角色绑定和条件分支生效。
  • [ ] 协同工作的审批记录有归档机制——临时流程也要留存"谁批了什么",不能审批完就散。
  • [ ] 报表和统计只从主流程引擎取数据——避免两个引擎的数据拼在一起导致口径不一致。
  • [ ] 用户培训区分两个入口——前端按钮文案必须让普通用户一眼看出"制度流程"和"临时协作"的区别,不要用技术术语。

两个引擎不是冗余,是针对两种截然不同的协作模式。选对了,流程跑得顺、审计查得清;选错了,要么开发成本浪费在画一次性流程图上,要么合规风险藏在碎片化的审批记录里。别再混着用了。


相关推荐