Skip to content

选择审批人 ​

这篇解决什么 ​

改用户任务上的审批人规则:设计器里选哪种人、参数怎么落到 XML / SIMPLE JSON,运行时怎么算出办理人。读完能对上 candidateStrategy / candidateParam、各策略实现,以及发起人自选为什么必须带 startUserSelectAssignees。

默认端口 48080,管理端前缀 /admin-api。PC 开发页 http://127.0.0.1:5800。规则配在流程中心 → 流程设置 → 流程模型,第三步点开审批节点。画布本身见 流程设计器(BPMN)。

示意图:设计器只写规则。创建任务时由 Invoker 调策略,再交给 Flowable 落 assignee。

从哪改 ​

名称说明仓库路径
策略枚举整数码,前后端同一套ruoyi-office/yudao-module-bpm/.../enums/BpmTaskCandidateStrategyEnum.java
策略接口calculateUsers / ByTask / ByActivity.../candidate/BpmTaskCandidateStrategy.java
调用入口发布校验、算人、空人兜底.../candidate/BpmTaskCandidateInvoker.java
单人任务候选人里随机一人当办理人.../behavior/BpmUserTaskActivityBehavior.java
行为工厂把 Invoker 注入 UserTask / 会签.../behavior/BpmActivityBehaviorFactory.java
扩展属性名candidateStrategy / candidateParamyudao-module-bpm-api/.../BpmnModelConstants.java
自选变量PROCESS_START_USER_SELECT_ASSIGNEES.../enums/BpmnVariableConstants.java
PC 枚举与后端码一致ruoyi-office-vben/packages/constants/src/biz-bpm-enum.ts
SIMPLE 下拉界面文案顺序,不读字典.../simple-process-design/consts.ts 的 CANDIDATE_STRATEGY
BPMN 面板右侧「用户任务」里的规则类型.../bpmn-process-designer/.../UserTask.vue
SIMPLE 抽屉「审批人设置」单选.../nodes-config/user-task-node-config.vue

官方菜单:1185 流程中心,1186 流程设置,1193 流程模型。改图、发布要 bpm:model:update、bpm:model:deploy。字典 bpm_task_candidate_strategy 给列表翻译用,设计器选项写死在 CANDIDATE_STRATEGY。

新增策略做成 Spring Bean 即可,BpmFlowableConfiguration 会把全部 BpmTaskCandidateStrategy 收进 Invoker,不要重复注册同一个枚举。

规则写到节点上 ​

标准 UserTask 没有「按角色 / 按部门」这类属性。设计器把规则写进 Flowable 命名空间:candidateStrategy 是类型,candidateParam 是参数。

名称说明仓库路径
写入addCandidateElements.../util/BpmnModelUtils.java
读取先看节点属性,没有再读 extensionElements#parseCandidateStrategy / #parseCandidateParam
SIMPLE 节点BpmSimpleModelNodeVO.candidateStrategy.../vo/model/simple/BpmSimpleModelNodeVO.java
发布前校验人工审批且策略为空 → 发布失败BpmTaskCandidateInvoker#validateBpmnConfig

BPMN 面板改规则时,走 flowable:CandidateStrategy / flowable:CandidateParam 扩展元素,不再写到元素根属性上。读的时候两套都认,老图还能开。

isParamRequired() 默认 true。发起人自选、审批人自选、发起人本人不需要参数。自动通过 / 自动拒绝的节点不算人工审批,发布时不查候选人。

SIMPLE 设计器的审批人设置

本系统截图:用车申请单 → 流程设计,点开「部门负责人」。抽屉里是审批人设置;当前是指定角色,并按单据公司过滤。

BPMN 设计器的规则类型

本系统截图:BPMN 画布选中用户任务,右侧「用户任务」折叠项里是规则类型和跳过表达式。

策略清单 ​

BpmTaskCandidateStrategyEnum 的整数码。界面文案以 CANDIDATE_STRATEGY 为准。

名称说明仓库路径
USER 30指定用户,逗号分隔用户编号.../strategy/user/BpmTaskCandidateUserStrategy.java
ROLE 10指定角色。参数 roleIds 或 roleIds|scope.../strategy/user/BpmTaskCandidateRoleStrategy.java
POST 22指定岗位,编码方式同角色.../strategy/user/BpmTaskCandidatePostStrategy.java
DEPT_MEMBER 20指定部门的成员,含负责人.../strategy/dept/BpmTaskCandidateDeptMemberStrategy.java
DEPT_LEADER 21指定部门的负责人.../strategy/dept/BpmTaskCandidateDeptLeaderStrategy.java
MULTI_DEPT_LEADER_MULTI 23连续多级部门负责人,参数带 |层级.../strategy/dept/BpmTaskCandidateDeptLeaderMultiStrategy.java
START_USER_SELECT 35发起人自选.../strategy/dept/BpmTaskCandidateStartUserSelectStrategy.java
APPROVE_USER_SELECT 34当前审批人指定下一节点.../strategy/dept/BpmTaskCandidateApproveUserSelectStrategy.java
START_USER 36发起人本人.../strategy/user/BpmTaskCandidateStartUserStrategy.java
START_USER_DEPT_LEADER 37发起人部门负责人,参数是层级.../strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java
START_USER_DEPT_LEADER_MULTI 38发起人连续多级部门负责人.../strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java
USER_GROUP 40用户组,表 bpm_user_group.../strategy/user/BpmTaskCandidateGroupStrategy.java
FORM_USER 50表单里某个用户字段.../strategy/form/BpmTaskCandidateFormUserStrategy.java
FORM_DEPT_LEADER 51表单里部门字段 + 层级,字段|层级.../strategy/form/BpmTaskCandidateFormDeptLeaderStrategy.java
EXPRESSION 60流程表达式,结果转成用户编号集合.../strategy/other/BpmTaskCandidateExpressionStrategy.java
ASSIGN_EMPTY 1候选人为空时的兜底,不是设计器选项.../strategy/other/BpmTaskCandidateAssignEmptyStrategy.java

角色、岗位先收组织范围再匹配

ROLE / POST 的 candidateParam 可带后缀 company / dept / none。先算出单据公司或部门上的任职,再在这些人里找角色或岗位。不要先取全租户并集再按部门滤:总部管理员兼职子公司时,会被子公司单据捞成审批人。

组织范围编码见 BpmCandidateOrgScopeUtils,枚举 BpmCandidateOrgScopeEnum。老模型没有后缀,按 none(不过滤)。

角色、部门、用户 ​

日常单据这三种最多。

指定用户:参数就是用户编号列表。validateParam 调 AdminUserApi.validateUserList。算出的集合不再按组织过滤。

指定部门成员 / 负责人:参数是部门编号列表。成员走 getUserListByDeptIds;负责人取部门的 leaderUserId。部门不存在,发布阶段就会被拦住。

指定角色:PermissionApi.getUserRoleIdListByRoleIds。带组织范围时改走 getUserRoleIdListByRoleIdsAndDeptIds,结果进 BpmCandidateResolveCache,同一组角色不要反复打权限服务。

名称说明仓库路径
组织过滤按流程变量里的公司 / 部门收窄.../candidate/BpmCandidateOrgScopeFilter.java
解析缓存角色、岗位按范围缓存候选人.../candidate/BpmCandidateResolveCache.java
前端后缀formatCandidateIdsWithScope.../simple-process-design/helpers.ts
角色多选BpmCandidateMultiPicker type=roleBPMN UserTask.vue、SIMPLE user-task-node-config.vue

部门负责人、发起人部门负责人还要填层级。发起人部门从流程变量的部门编号取,没有再回落到发起人档案部门。

发起人自选 ​

节点策略是 35 时,发起当时就要把这个节点的人带上。后端只认流程变量里、按节点 id 分组的用户编号。

示意图:人选是实例变量,不是节点上的固定名单。策略只按当前节点 id 取值。

名称说明仓库路径
流程表单发起POST /bpm/process-instance/createBpmProcessInstanceController#createProcessInstance
入参 Mapkey 是节点 id,value 是用户编号数组.../vo/instance/BpmProcessInstanceCreateReqVO.java
业务 RPCBpmProcessInstanceCreateReqDTO.startUserSelectAssigneesyudao-module-bpm-api/.../BpmProcessInstanceCreateReqDTO.java
写入变量createProcessInstance0BpmProcessInstanceServiceImpl
发起校验只校验预测会走到的自选节点#validateStartUserSelectAssignees
未选人PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIGErrorCodeConstants
流程表单页右侧时间线点选.../processInstance/create/modules/form.vue
业务表单底栏提交前弹自选.../components/basic-form/basic-form.vue
示例请假单key oa_leave,提交时带上 Map.../views/bpm/oa/leave/create.vue

预测用 getApprovalDetail,入参带当前表单变量。分支还没走到的自选节点,这次可以不选。发起后变量里已经有该节点的人,审批通过时 validateAndSetNextAssignees 不会覆盖。

业务单据按用印、用车那样:submit 接收 { startUserSelectAssignees },再传给 submitProcessInstance。不要自己造一套字段名。

审批人自选(34)是下一节点的人,存在 PROCESS_APPROVE_USER_SELECT_ASSIGNEES。当前人点通过时用 nextAssignees 补上。第一个用户任务不能配这个策略,发布会失败。

自选节点空着发不出去

validateStartUserSelectAssignees 按节点名称报「任务(xx)的候选人未配置」。流程表单在提交前就会提示「请选择xx的候选人」;业务表单走 basic-form 的提交气泡。不要只在后端兜。

运行时怎么落到办理人 ​

创建 UserTask 时,Flowable 调自定义 Behavior,不再用 BPMN 里写死的 assignee。

示意图:单人任务责任到人,集合里只留一个办理人。多人同时批,走会签行为,见 会签、或签、依次审批。

名称说明仓库路径
算人@DataPermission(enable = false),避免数据权限把人滤空BpmTaskCandidateInvoker#calculateUsersByTask
预览未走节点calculateUsersByActivity,给时间线、发起预览同上
空人指定人 / 转流程管理员;都不配就仍为空BpmUserTaskAssignEmptyHandlerTypeEnum
与发起人相同配置了跳过且候选多于 1 人,才去掉发起人#removeStartUserIfSkip

Invoker 包在 FlowableUtils.execute(tenantId) 里,避免异步触发时租户丢了。禁用用户先删掉;空人策略不再删,免得兜底也被掏空。

表达式策略用 FlowableUtils.getExpressionValue。预览未运行节点时,变量不齐会 PropertyNotFoundException,这时返回空集合,不要把整单预测打挂。

单人任务会随机挑人

ROLE、DEPT_MEMBER 常算出一堆人。没开会签时,Behavior 用 RandomUtil.randomInt 只留一个。要部门里人人都能批,配或签;要按顺序批,配依次审批。

加一种策略 ​

  1. 在 BpmTaskCandidateStrategyEnum 加码和文案。
  2. 写一个 @Component 实现 BpmTaskCandidateStrategy:getStrategy、validateParam、至少一种 calculateUsers*。
  3. SIMPLE / BPMN 的 CANDIDATE_STRATEGY 和 CandidateStrategy 补同一数字。
  4. 字典 bpm_task_candidate_strategy 补一项,给已办、详情翻译。
  5. 需要参数就保持 isParamRequired() 默认值;像自选那样没有参数就重写成 false。

发布时 Invoker 会调 validateParam。角色、用户、部门这类要在这里调 API 校验,不要拖到运行时才发现编号是空的。

配置与操作 ​

管理员在模型第三步点开审批节点,选 candidateStrategy 和 candidateParam(角色可带 company / dept 后缀),保存后发布。只改未发布草稿不影响在途单。

发起人自选(35)要在提交时带 startUserSelectAssignees,员工在发起页或业务表单底栏选人。空着发不出去。

开启见 流程功能设计。截图见上文 SIMPLE 抽屉和 BPMN 面板。

相关篇 ​

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版