BPM 工作流
BPM 工作流
本平台自带一套自研轻量审批引擎(非 Flowable / Activiti),采用钉钉式 simpleModel JSON 驱动,支持单人审批、会签/或签、转办、委派、撤回、催办、加签等企业级审批场景,并能在流程终态时自动回写业务表 approval_status 列,将审批状态与业务数据状态机对齐。
阅读顺序
建议先读本篇了解引擎全貌,再读 理解 simpleModel JSON 结构,然后读 了解如何部署流程,接着按 -> 的顺序掌握审批操作,最后重点阅读 -- 这是连接 BPM 与业务系统的关键纽带。
模块一览
| 文档 | 说明 | 后端核心 |
|---|---|---|
| 📐 | SimpleProcessDesignerV2 钉钉式设计器,simpleModel JSON 结构 | BpmProcessDefinitionInfo.simpleModel |
| 📦 | 流程模型 CRUD、部署、发布、预览 | BpmModelController / BpmDefinitionController |
| 🔄 | 发起流程、审批/驳回、待办/已办 | BpmInstanceController / BpmTaskController / SimpleFlowEngine |
| ✍️ | 多人会签、转办、委派、撤回、催办、加签 | BpmTaskSignController / SimpleFlowEngine |
| 🔗 | 终态回写业务表 approval_status 列(重点) | BpmBusinessStatusCallback |
| 🌉 | 表单数据 + 发起审批一体化接口 | BizApprovalController |
| 🔔 | 审批记录、待办/抄送/催办通知 | BpmApprovalRecordController / NotificationService |
引擎定位
┌─────────────────────────────────────────────────────────────────┐
│ SimpleFlowEngine(自研引擎) │
│ │
│ startProcess ──> 创建 BpmInstance(running) │
│ ├─ 解析 simpleModel JSON (processList: start/approve/sign/copy)│
│ ├─ 抄送节点 -> NotificationService.sendCopyNotification │
│ ├─ 审批节点 -> resolveAssignees -> 创建 BpmTask(pending) │
│ └─ BpmBusinessStatusCallback.onStarted -> IN_PROGRESS │
│ │
│ completeTask ──> approve: task=completed -> 下一个节点 │
│ reject: instance=rejected -> 终态回调 │
│ 最后任务完成: instance=completed -> 终态回调 │
│ │
│ transfer / delegate / recall / addSign / follow ... │
└─────────────────────────────────────────────────────────────────┘平台没有引入 Flowable 或 Activiti 等重型 BPMN 引擎,而是基于 simpleModel JSON 自研了 SimpleFlowEngine,核心原因:
- 轻量:无需引擎表(ACT_* 系列),BPM 数据仅 8 张业务表。
- 钉钉式:前端使用 SimpleProcessDesignerV2(仿钉钉审批流设计器),非 BPMN 2.0 XML。
- 业务联动:通过
BpmBusinessStatusCallback在流程终态自动回写业务表,实现审批与业务状态机对齐。
simpleModel 钉钉式流程模型
流程设计器产出的 JSON 存储在 bpm_process_definition_info.simple_model 字段,核心结构:
{
"processList": [
{
"type": "start",
"id": "StartUserNode",
"name": "发起人"
},
{
"type": "approve",
"id": "node_1",
"name": "部门主管审批",
"candidateStrategy": 10,
"candidateParam": "1,2",
"childNode": {
"type": "sign",
"id": "node_2",
"name": "财务会签",
"candidateStrategy": 30,
"candidateParam": "3,4,5",
"signType": "AND",
"signRule": "ALL",
"passRatio": 100,
"childNode": {
"type": "copy",
"id": "node_3",
"name": "抄送总经理",
"candidateStrategy": 30,
"candidateParam": "6"
}
}
}
]
}节点类型对照
| type 字符串 | 数字编码 | 含义 |
|---|---|---|
start | 10 | 发起人节点 |
approve | 11 | 审批节点(单人或多人依次) |
sign | 13 | 会签节点(多人同时审批) |
copy | 12 | 抄送节点(仅通知,不产生任务) |
引擎在 SimpleFlowEngine.parseSimpleModel() 中同时接受字符串和数字编码。
候选人策略(candidateStrategy)
| 值 | 枚举名 | 含义 | candidateParam 格式 |
|---|---|---|---|
| 10 | ROLE | 指定角色 | roleId1,roleId2 |
| 20 | DEPT_MEMBER | 部门成员 | deptId1,deptId2 |
| 21 | DEPT_LEADER | 部门负责人 | deptId1,deptId2 |
| 23 | MULTI_LEVEL_DEPT_LEADER | 多级部门负责人 | deptIds|level |
| 30 | USER | 指定用户 | userId1,userId2 |
| 36 | START_USER | 发起人本人 | (无参数) |
引擎在 resolveAssignees() 中解析 candidateStrategy + candidateParam,通过 sys_user_role 表关联角色到用户,通过 sys_user.dept_id 关联部门到用户。
与表单/业务表的关系
┌──────────────┐ processModelId ┌──────────────────────────┐
│ LcForm │─────────────────────────►│ BpmProcessDefinitionInfo │
│ (表单设计器) │ │ (流程模型 + simpleModel)│
│ formCode │ │ key / status / formType │
│ tableId │ └────────────┬─────────────┘
│ approval │ │ startProcess
│ Enabled │ ▼
└──────┬───────┘ ┌──────────────────────────┐
│ tableId │ BpmInstance │
▼ │ businessType = formCode │
┌──────────────┐ approval_status 列 │ businessKey = formCode: │
│ LcTableMeta │◄─────────────────────────│ dataId │
│ tableName │ BpmBusinessStatusCallback│ status: running/ │
│ columns │ (终态回写) │ completed/rejected/ │
└──────────────┘ │ recalled │
└──────────────────────────┘- LcForm:低代码表单设计器产出的表单配置,
formCode对应业务表名,tableId指向LcTableMeta,approvalEnabled控制是否启用审批,processModelId绑定流程模型。 - BpmProcessDefinitionInfo:流程模型,
simpleModel字段存 JSON,status为draft或deployed,只有deployed的模型才能发起流程。 - BpmInstance:流程实例,
businessType存formCode,businessKey存formCode:dataId,用于关联业务数据行。 - BpmBusinessStatusCallback:在流程启动时写
IN_PROGRESS,终态时写APPROVED/REJECTED/WITHDRAWN到业务表的approval_status列(仅当表含此列时才回写)。
端口约定
| 服务 | 端口 | 说明 |
|---|---|---|
| 后端 Spring Boot | 52856 | 所有 /api/bpm/** 接口 |
| 前端 Vue3 + Vite | 3000 | Vite dev server,通过 proxy 透传 /api 到后端 |
API 路径约定
双重 /api 前缀陷阱
- 前端 axios
baseURL = '/api' - 后端控制器
@RequestMapping("/api/bpm/xxx") - 因此前端 api 模块的请求路径里不要再写
/api
| 写法 | 实际请求 | 结果 |
|---|---|---|
request.get('/bpm/model/list') | /api/bpm/model/list | 正确 |
request.get('/api/bpm/model/list') | /api/api/bpm/model/list | 404 |
后端代码组织
backend/src/main/java/com/lowcode/
├── service/bpm/
│ ├── SimpleFlowEngine.java ← 核心引擎(start/completeTask/sign/transfer/delegate/recall)
│ ├── BpmBusinessStatusCallback.java ← 审批状态回写业务表
│ ├── IBpmModelService.java ← 模型服务接口
│ ├── IBpmInstanceService.java ← 实例服务接口
│ ├── IBpmTaskService.java ← 任务服务接口
│ ├── IBpmTaskSignService.java ← 会签服务接口
│ ├── IBpmApprovalRecordService.java ← 审批记录服务接口
│ ├── IBpmFormService.java ← 表单服务接口
│ ├── IBpmCategoryService.java ← 分类服务接口
│ └── IBpmUserGroupService.java ← 用户组服务接口
├── service/impl/bpm/
│ ├── BpmModelServiceImpl.java ← 模型 CRUD + deploy + startProcess
│ ├── BpmInstanceServiceImpl.java
│ ├── BpmTaskServiceImpl.java
│ ├── BpmTaskSignServiceImpl.java
│ ├── BpmApprovalRecordServiceImpl.java
│ └── ...
├── controller/bpm/
│ ├── BpmModelController.java ← /api/bpm/model
│ ├── BpmDefinitionController.java ← /api/bpm/definition
│ ├── BpmInstanceController.java ← /api/bpm/instance
│ ├── BpmTaskController.java ← /api/bpm/task
│ ├── BpmTaskSignController.java ← /api/bpm/sign
│ ├── BpmApprovalRecordController.java ← /api/bpm/approval
│ ├── BpmFormController.java ← /api/bpm/form
│ ├── BpmCategoryController.java ← /api/bpm/category
│ └── BpmUserGroupController.java ← /api/bpm/user-group
├── controller/
│ ├── BpmController.java ← /api/bpm/design/* (旧版设计接口)
│ └── BizApprovalController.java ← /api/biz-approval (业务审批桥)
└── entity/bpm/
├── BpmBaseEntity.java ← 基类(creator/updater/deleted)
├── BpmProcessDefinitionInfo.java ← 流程模型(simpleModel JSON)
├── BpmDefinition.java ← 流程定义(BPMN XML)
├── BpmInstance.java ← 流程实例
├── BpmTask.java ← 审批任务
├── BpmTaskSign.java ← 会签子任务
├── BpmApprovalRecord.java ← 审批记录
├── BpmTaskFollow.java ← 任务关注
├── BpmTaskTransferRecord.java ← 转办/委派记录
├── BpmForm.java ← BPM 表单
├── BpmCategory.java ← 流程分类
├── BpmUserGroup.java ← 用户组
└── BpmProcessInstanceCopy.java ← 抄送记录前端代码组织
frontend/src/
├── views/bpm/
│ ├── model/
│ │ ├── index.vue ← 模型列表页
│ │ └── design.vue ← 模型设计页(嵌入 SimpleProcessDesignerV2)
│ ├── definition.vue ← 流程定义管理页
│ ├── todo.vue ← 待办任务页
│ ├── instance.vue ← 流程实例页
│ └── approval.vue ← 审批记录页
├── components/
│ ├── SimpleProcessDesignerV2/ ← 钉钉式简易流程设计器
│ │ └── src/
│ │ ├── SimpleProcessDesigner.vue ← 设计器主组件
│ │ ├── SimpleProcessViewer.vue ← 只读查看器
│ │ ├── ProcessNodeTree.vue ← 节点树渲染
│ │ ├── NodeHandler.vue ← 节点添加操作
│ │ ├── consts.ts ← 节点类型/候选人策略常量
│ │ ├── node.ts ← 节点表单逻辑
│ │ └── nodes/
│ │ ├── StartUserNode.vue ← 发起人节点
│ │ ├── UserTaskNode.vue ← 审批节点
│ │ ├── CopyTaskNode.vue ← 抄送节点
│ │ ├── EndEventNode.vue ← 结束节点
│ │ └── ...
│ └── BpmnDesigner/ ← bpmn-js 标准设计器(备用)
└── api/bpm/ ← BPM API 请求模块数据库表一览
| 表名 | 说明 | 核心字段 |
|---|---|---|
bpm_process_definition_info | 流程模型(simpleModel) | simple_model, status, key, form_type, form_id |
bpm_definition | 流程定义(BPMN XML) | def_key, def_name, bpmn_xml, status |
bpm_instance | 流程实例 | def_id, business_key, business_type, status, start_user_id |
bpm_task | 审批任务 | instance_id, assignee_id, status, is_sign, sign_type, sign_rule |
bpm_task_sign | 会签子任务 | task_id, assignee_id, sign_type, sign_rule, status |
bpm_approval_record | 审批记录 | instance_id, action_type, operator_id, opinion |
bpm_task_transfer_record | 转办/委派记录 | task_id, transfer_type, from_user_id, to_user_id |
bpm_task_follow | 任务关注 | task_id, user_id, notified |
bpm_form | BPM 表单 | name, conf, fields, status |
bpm_category | 流程分类 | name, code, sort |
bpm_user_group | 用户组 | name, member_user_ids, status |
bpm_process_instance_copy | 抄送记录 | process_instance_id, user_id |
接下来从 开始逐个讲解。
