# 子流程与网关类型详解
## 1. 网关类型一览
| 用户描述 | BPMN 类型 | XML 元素 | 说明 |
|----------|----------|----------|------|
| 分支/条件判断/通过或拒绝 | 排他网关 | `exclusiveGateway` | 只走一条满足条件的路径 |
| 并行/同时 | 并行网关 | `parallelGateway` | 所有路径同时执行,全部完成后汇聚 |
| 包含/部分并行 | 包含网关 | `inclusiveGateway` | 满足条件的路径都走,全部完成后汇聚 |
> **注意:** JeecgBoot 设计器不支持事件网关(eventBasedGateway),实际只用上面三种。
---
## 2. 排他网关(exclusiveGateway)
只走一条路径,适用于"通过/拒绝"、"金额判断"等场景。
```xml
```
**BPMNShape:** 排他网关需要 `isMarkerVisible="true"`
```xml
```
---
## 3. 并行网关(parallelGateway)
所有路径同时执行,必须成对使用(fork + join)。连线**不需要条件表达式**。
```xml
```
---
## 4. 包含网关(inclusiveGateway)
满足条件的路径都会执行,也必须成对使用(分支 + 汇聚)。**连线需要条件表达式**。
### 4.1 基本用法(来自生产环境:包含网关测试)
```
开始 → 领取体检单 → 包含网关1(分支)
├─ 普通员工 (user_type=='1') → 常规体检 ──┐
├─ 全部 (user_type=='1'||'2') → 抽血化验 → 领取早餐 ──┤→ 包含网关2(汇聚)→ 结束
└─ 领导 (user_type=='2') → 深度体检 ──┘
```
```xml
${user_type=='1'}
${user_type=='1' || user_type=='2'}
${user_type=='2'}
```
### 4.2 包含网关 + 直通路径(来自生产环境:督办流程)
包含网关的一个分支可以直接连到汇聚网关(不经过任何任务),实现"无风险时跳过"的效果:
```
部门负责人审核 → 包含网关(分支)
├─ 有风险 (iz_danger=='1') → 风控审计负责 ──┐
├─ 有风险 (iz_danger=='1') → 部门分管领导 ──┤→ 包含网关(汇聚)→ 结束
└─ 无风险 (iz_danger=='0') ──────────────────┘
```
```xml
${iz_danger== '1' }
${iz_danger== '1' }
${iz_danger=='0'}
```
### 4.3 包含网关 vs 排他网关 vs 并行网关
| 特性 | 排他网关 | 并行网关 | 包含网关 |
|------|---------|---------|---------|
| 执行路径 | 只走1条 | 全部走 | 满足条件的都走 |
| 条件表达式 | 必需 | 不需要 | 必需 |
| 汇聚行为 | 等1个 | 等全部 | 等所有已激活的 |
| 适用场景 | 二选一/多选一 | 同时并行 | 条件并行 |
---
## 5. 内嵌子流程(subProcess)
内嵌子流程在主流程 XML 内部定义,拥有自己的开始和结束事件。适用于将一组相关节点打包为一个整体。
### 5.1 基本结构
```xml
Flow_in
Flow_out
```
### 5.2 完整示例(来自生产环境:测试嵌套子流程)
```
开始 → 入职(admin) → [内嵌子流程: 开始 → 经理(qinfeng) → 财务(vue3角色) → 结束] → 人力(admin角色) → 结束
```
**布局说明:** 内嵌子流程在图形上展开显示(`isExpanded="true"`),需要为整个子流程框指定 Bounds。
```xml
```
---
## 6. 调用子流程(callActivity)— 主子流程
调用子流程引用**另一个独立部署的流程定义**,主流程和子流程各自独立管理。
### 6.1 基本结构
```xml
```
### 6.2 必传变量
| 变量 | 方向 | 说明 |
|------|------|------|
| `applyUserId` | in + out | 流程发起人,子流程需要知道谁发起的 |
| `JG_LOCAL_PROCESS_ID` → `JG_SUB_MAIN_PROCESS_ID` | in | 主流程ID,子流程需要关联回主流程 |
### 6.3 完整示例(来自生产环境:出差申请主子流程)
```
开始 → 主管领导 → 部门领导 → 排他网关
├─ 预支借款 (travel_expenses_type=='1') → 借款申请 → callActivity(调用joa_loan子流程) → 归档 → 结束
└─ 个人垫付 (travel_expenses_type=='2') → 归档 → 结束
```
```xml
```
---
## 7. 会签子流程(callActivity + multiInstance)
会签子流程 = 调用子流程 + 多实例循环。每个审批人各执行一次完整的子流程。
### 7.1 结构
```xml
```
### 7.2 完整示例(来自生产环境:主流程会签主子流程)
```
开始 → 主流程经理审批(候选人) → callActivity(会签子流程, 顺序执行) → 主流程总监审批 → 结束
```
```xml
```
**关键区别:**
- 普通子流程:没有 `multiInstanceLoopCharacteristics`,只执行一次
- 会签子流程:有 `multiInstanceLoopCharacteristics`,按 `assigneeUserIdList` 中的人数循环执行
---
## 8. 分支条件表达式配置
### 8.1 排他网关条件
排他网关的每条出线都需要条件表达式(除了默认路径):
```xml
```
### 8.2 包含网关条件
包含网关的每条出线也需要条件表达式,可以多条同时满足:
```xml
${user_type=='1'}
${user_type=='1' || user_type=='2'}
```
### 8.3 常用条件表达式写法
| 场景 | 表达式 |
|------|--------|
| 审批通过 | `${result == 1}` |
| 审批拒绝 | `${result == 0}` |
| 字段等于值 | `${field_name == 'value'}` |
| 字段不等于 | `${field_name != 'value'}` |
| 数值比较 | `${amount > 10000}` |
| 多条件 OR | `${type=='1' \|\| type=='2'}` |
| 多条件 AND | `${type=='1' && level=='high'}` |
| 布尔判断 | `${iz_danger == '1'}` |
> **注意:** `conditionExpression` 中使用 `xsi:type="tFormalExpression"`(排他网关)或 `xsi:type="bpmn2:tFormalExpression"`(新版设计器),两种都可用。