Commit 4e9583fae4ea6d7de60704dd861694b844624f43
Merge branch 'feature/bpm' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17
Showing
21 changed files
with
460 additions
and
224 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java
| @@ -199,4 +199,12 @@ public class JsonUtils { | @@ -199,4 +199,12 @@ public class JsonUtils { | ||
| 199 | return JSONUtil.isTypeJSON(text); | 199 | return JSONUtil.isTypeJSON(text); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | + /** | ||
| 203 | + * 判断字符串是否为 JSON 类型的字符串 | ||
| 204 | + * @param str 字符串 | ||
| 205 | + */ | ||
| 206 | + public static boolean isJsonObject(String str) { | ||
| 207 | + return JSONUtil.isTypeJSONObject(str); | ||
| 208 | + } | ||
| 209 | + | ||
| 202 | } | 210 | } |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
| @@ -16,7 +16,8 @@ import java.util.Arrays; | @@ -16,7 +16,8 @@ import java.util.Arrays; | ||
| 16 | @AllArgsConstructor | 16 | @AllArgsConstructor |
| 17 | public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { | 17 | public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { |
| 18 | 18 | ||
| 19 | - HTTP_REQUEST(1, "发起 HTTP 请求"); | 19 | + HTTP_REQUEST(1, "发起 HTTP 请求"), |
| 20 | + UPDATE_NORMAL_FORM(2, "更新流程表单"); // TODO @jason:FORM_UPDATE | ||
| 20 | 21 | ||
| 21 | /** | 22 | /** |
| 22 | * 触发器执行动作类型 | 23 | * 触发器执行动作类型 |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
| @@ -32,6 +32,7 @@ public enum BpmReasonEnum { | @@ -32,6 +32,7 @@ public enum BpmReasonEnum { | ||
| 32 | ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"), | 32 | ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"), |
| 33 | APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), | 33 | APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"), |
| 34 | APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), | 34 | APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"), |
| 35 | + CANCEL_BY_PROCESS_CLEAN("进程清理自动取消"), | ||
| 35 | ; | 36 | ; |
| 36 | 37 | ||
| 37 | private final String reason; | 38 | private final String reason; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| 1 | package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple; | 1 | package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; | 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 5 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 5 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
| @@ -157,6 +158,7 @@ public class BpmSimpleModelNodeVO { | @@ -157,6 +158,7 @@ public class BpmSimpleModelNodeVO { | ||
| 157 | @Schema(description = "值", example = "xxx") | 158 | @Schema(description = "值", example = "xxx") |
| 158 | @NotEmpty(message = "值不能为空") | 159 | @NotEmpty(message = "值不能为空") |
| 159 | private String value; | 160 | private String value; |
| 161 | + | ||
| 160 | } | 162 | } |
| 161 | 163 | ||
| 162 | @Schema(description = "审批节点拒绝处理策略") | 164 | @Schema(description = "审批节点拒绝处理策略") |
| @@ -343,6 +345,13 @@ public class BpmSimpleModelNodeVO { | @@ -343,6 +345,13 @@ public class BpmSimpleModelNodeVO { | ||
| 343 | @Valid | 345 | @Valid |
| 344 | private HttpRequestTriggerSetting httpRequestSetting; | 346 | private HttpRequestTriggerSetting httpRequestSetting; |
| 345 | 347 | ||
| 348 | + // TODO @jason:这个要不直接叫 formSetting,更好理解一点哈 | ||
| 349 | + // TODO @jason:如果搞成 List<NormalFormTriggerSetting>,是不是可以做条件组了?微信讨论哈 | ||
| 350 | + /** | ||
| 351 | + * 流程表单触发器设置 | ||
| 352 | + */ | ||
| 353 | + private NormalFormTriggerSetting normalFormSetting; | ||
| 354 | + | ||
| 346 | @Schema(description = "http 请求触发器设置", example = "{}") | 355 | @Schema(description = "http 请求触发器设置", example = "{}") |
| 347 | @Data | 356 | @Data |
| 348 | public static class HttpRequestTriggerSetting { | 357 | public static class HttpRequestTriggerSetting { |
| @@ -359,6 +368,26 @@ public class BpmSimpleModelNodeVO { | @@ -359,6 +368,26 @@ public class BpmSimpleModelNodeVO { | ||
| 359 | @Schema(description = "请求头参数设置", example = "[]") | 368 | @Schema(description = "请求头参数设置", example = "[]") |
| 360 | @Valid | 369 | @Valid |
| 361 | private List<HttpRequestParam> body; | 370 | private List<HttpRequestParam> body; |
| 371 | + | ||
| 372 | + // TODO @json:可能未来看情况,搞个 HttpResponseParam;得看看有没别的业务需要,抽象统一 | ||
| 373 | + /** | ||
| 374 | + * 请求返回处理设置,用于修改流程表单值 | ||
| 375 | + * <p> | ||
| 376 | + * key:表示要修改的流程表单字段名(name) | ||
| 377 | + * value:接口返回的字段名 | ||
| 378 | + */ | ||
| 379 | + @Schema(description = "请求返回处理设置", example = "[]") | ||
| 380 | + private List<KeyValue<String, String>> response; | ||
| 381 | + | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + @Schema(description = "流程表单触发器设置", example = "{}") | ||
| 385 | + @Data | ||
| 386 | + public static class NormalFormTriggerSetting { | ||
| 387 | + | ||
| 388 | + @Schema(description = "修改的表单字段", example = "userName") | ||
| 389 | + private Map<String, Object> updateFormFields; | ||
| 390 | + | ||
| 362 | } | 391 | } |
| 363 | 392 | ||
| 364 | } | 393 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java
| @@ -9,7 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | @@ -9,7 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 9 | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | 9 | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; |
| 10 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc.BpmProcessInstanceCopyRespVO; | 10 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc.BpmProcessInstanceCopyRespVO; |
| 11 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageReqVO; | 11 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageReqVO; |
| 12 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; | ||
| 12 | import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO; | 13 | import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceCopyDO; |
| 14 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | ||
| 15 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; | ||
| 13 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService; | 16 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService; |
| 14 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | 17 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 15 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 18 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -42,6 +45,8 @@ public class BpmProcessInstanceCopyController { | @@ -42,6 +45,8 @@ public class BpmProcessInstanceCopyController { | ||
| 42 | private BpmProcessInstanceCopyService processInstanceCopyService; | 45 | private BpmProcessInstanceCopyService processInstanceCopyService; |
| 43 | @Resource | 46 | @Resource |
| 44 | private BpmProcessInstanceService processInstanceService; | 47 | private BpmProcessInstanceService processInstanceService; |
| 48 | + @Resource | ||
| 49 | + private BpmProcessDefinitionService processDefinitionService; | ||
| 45 | 50 | ||
| 46 | @Resource | 51 | @Resource |
| 47 | private AdminUserApi adminUserApi; | 52 | private AdminUserApi adminUserApi; |
| @@ -62,6 +67,8 @@ public class BpmProcessInstanceCopyController { | @@ -62,6 +67,8 @@ public class BpmProcessInstanceCopyController { | ||
| 62 | convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); | 67 | convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); |
| 63 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), | 68 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), |
| 64 | copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); | 69 | copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); |
| 70 | + Map<String, BpmProcessDefinitionInfoDO> processDefinitionInfoMap = processDefinitionService.getProcessDefinitionInfoMap( | ||
| 71 | + convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessDefinitionId)); | ||
| 65 | return success(convertPage(pageResult, copy -> { | 72 | return success(convertPage(pageResult, copy -> { |
| 66 | BpmProcessInstanceCopyRespVO copyVO = BeanUtils.toBean(copy, BpmProcessInstanceCopyRespVO.class); | 73 | BpmProcessInstanceCopyRespVO copyVO = BeanUtils.toBean(copy, BpmProcessInstanceCopyRespVO.class); |
| 67 | MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), | 74 | MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), |
| @@ -69,7 +76,12 @@ public class BpmProcessInstanceCopyController { | @@ -69,7 +76,12 @@ public class BpmProcessInstanceCopyController { | ||
| 69 | MapUtils.findAndThen(userMap, copy.getStartUserId(), | 76 | MapUtils.findAndThen(userMap, copy.getStartUserId(), |
| 70 | user -> copyVO.setCreateUser(BeanUtils.toBean(user, UserSimpleBaseVO.class))); | 77 | user -> copyVO.setCreateUser(BeanUtils.toBean(user, UserSimpleBaseVO.class))); |
| 71 | MapUtils.findAndThen(processInstanceMap, copyVO.getProcessInstanceId(), | 78 | MapUtils.findAndThen(processInstanceMap, copyVO.getProcessInstanceId(), |
| 72 | - processInstance -> copyVO.setProcessInstanceStartTime(DateUtils.of(processInstance.getStartTime()))); | 79 | + processInstance -> { |
| 80 | + copyVO.setSummary(FlowableUtils.getSummary( | ||
| 81 | + processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | ||
| 82 | + processInstance.getProcessVariables())); | ||
| 83 | + copyVO.setProcessInstanceStartTime(DateUtils.of(processInstance.getStartTime())); | ||
| 84 | + }); | ||
| 73 | return copyVO; | 85 | return copyVO; |
| 74 | })); | 86 | })); |
| 75 | } | 87 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/cc/BpmProcessInstanceCopyRespVO.java
| 1 | package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc; | 1 | package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.cc; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 3 | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; | 4 | import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO; |
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | import lombok.Data; | 6 | import lombok.Data; |
| 6 | 7 | ||
| 7 | import java.time.LocalDateTime; | 8 | import java.time.LocalDateTime; |
| 9 | +import java.util.List; | ||
| 8 | 10 | ||
| 9 | @Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") | 11 | @Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") |
| 10 | @Data | 12 | @Data |
| @@ -40,4 +42,7 @@ public class BpmProcessInstanceCopyRespVO { | @@ -40,4 +42,7 @@ public class BpmProcessInstanceCopyRespVO { | ||
| 40 | @Schema(description = "抄送时间", requiredMode = Schema.RequiredMode.REQUIRED) | 42 | @Schema(description = "抄送时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 41 | private LocalDateTime createTime; | 43 | private LocalDateTime createTime; |
| 42 | 44 | ||
| 45 | + @Schema(description = "流程摘要", example = "[]") | ||
| 46 | + private List<KeyValue<String, String>> summary; | ||
| 47 | + | ||
| 43 | } | 48 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageReqVO.java
| @@ -32,7 +32,14 @@ public class BpmProcessInstancePageReqVO extends PageParam { | @@ -32,7 +32,14 @@ public class BpmProcessInstancePageReqVO extends PageParam { | ||
| 32 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 32 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 33 | private LocalDateTime[] createTime; | 33 | private LocalDateTime[] createTime; |
| 34 | 34 | ||
| 35 | + @Schema(description = "结束时间") | ||
| 36 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 37 | + private LocalDateTime[] endTime; | ||
| 38 | + | ||
| 35 | @Schema(description = "发起用户编号", example = "1024") | 39 | @Schema(description = "发起用户编号", example = "1024") |
| 36 | private Long startUserId; // 注意,只有在【流程实例】菜单,才使用该参数 | 40 | private Long startUserId; // 注意,只有在【流程实例】菜单,才使用该参数 |
| 37 | 41 | ||
| 42 | + @Schema(description = "动态表单字段查询 JSON Str", example = "{}") | ||
| 43 | + private String formFieldsParams; // SpringMVC 在 get 请求下,无法方便的定义 Map 类型的参数,所以通过 String 接收后,逻辑里面转换 | ||
| 44 | + | ||
| 38 | } | 45 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java
| @@ -85,10 +85,6 @@ public class BpmTaskRespVO { | @@ -85,10 +85,6 @@ public class BpmTaskRespVO { | ||
| 85 | @Schema(description = "是否填写审批意见", example = "false") | 85 | @Schema(description = "是否填写审批意见", example = "false") |
| 86 | private Boolean reasonRequire; | 86 | private Boolean reasonRequire; |
| 87 | 87 | ||
| 88 | - // TODO @lesan:要不放到 processInstance 里面?因为摘要是流程实例的,不是流程任务的 | ||
| 89 | - @Schema(description = "流程摘要", example = "[]") | ||
| 90 | - private List<KeyValue<String, String>> summary; // 只有流程表单,才有摘要! | ||
| 91 | - | ||
| 92 | @Data | 88 | @Data |
| 93 | @Schema(description = "流程实例") | 89 | @Schema(description = "流程实例") |
| 94 | public static class ProcessInstance { | 90 | public static class ProcessInstance { |
| @@ -105,6 +101,9 @@ public class BpmTaskRespVO { | @@ -105,6 +101,9 @@ public class BpmTaskRespVO { | ||
| 105 | @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | 101 | @Schema(description = "流程定义的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") |
| 106 | private String processDefinitionId; | 102 | private String processDefinitionId; |
| 107 | 103 | ||
| 104 | + @Schema(description = "流程摘要", example = "[]") | ||
| 105 | + private List<KeyValue<String, String>> summary; // 只有流程表单,才有摘要! | ||
| 106 | + | ||
| 108 | /** | 107 | /** |
| 109 | * 发起人的用户信息 | 108 | * 发起人的用户信息 |
| 110 | */ | 109 | */ |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
| @@ -80,6 +80,8 @@ public interface BpmProcessInstanceConvert { | @@ -80,6 +80,8 @@ public interface BpmProcessInstanceConvert { | ||
| 80 | // 摘要 | 80 | // 摘要 |
| 81 | respVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(respVO.getProcessDefinitionId()), | 81 | respVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(respVO.getProcessDefinitionId()), |
| 82 | pageResult.getList().get(i).getProcessVariables())); | 82 | pageResult.getList().get(i).getProcessVariables())); |
| 83 | + // 表单 | ||
| 84 | + respVO.setFormVariables(pageResult.getList().get(i).getProcessVariables()); | ||
| 83 | } | 85 | } |
| 84 | return vpPageResult; | 86 | return vpPageResult; |
| 85 | } | 87 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
| @@ -54,7 +54,7 @@ public interface BpmTaskConvert { | @@ -54,7 +54,7 @@ public interface BpmTaskConvert { | ||
| 54 | AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); | 54 | AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); |
| 55 | taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); | 55 | taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); |
| 56 | // 摘要 | 56 | // 摘要 |
| 57 | - taskVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | 57 | + taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), |
| 58 | processInstance.getProcessVariables())); | 58 | processInstance.getProcessVariables())); |
| 59 | }); | 59 | }); |
| 60 | } | 60 | } |
| @@ -80,7 +80,7 @@ public interface BpmTaskConvert { | @@ -80,7 +80,7 @@ public interface BpmTaskConvert { | ||
| 80 | taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class)); | 80 | taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class)); |
| 81 | taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); | 81 | taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class)); |
| 82 | // 摘要 | 82 | // 摘要 |
| 83 | - taskVO.setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), | 83 | + taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()), |
| 84 | processInstance.getProcessVariables())); | 84 | processInstance.getProcessVariables())); |
| 85 | } | 85 | } |
| 86 | return taskVO; | 86 | return taskVO; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceCopyDO.java
| @@ -50,6 +50,12 @@ public class BpmProcessInstanceCopyDO extends BaseDO { | @@ -50,6 +50,12 @@ public class BpmProcessInstanceCopyDO extends BaseDO { | ||
| 50 | */ | 50 | */ |
| 51 | private String processInstanceId; | 51 | private String processInstanceId; |
| 52 | /** | 52 | /** |
| 53 | + * 流程实例的流程定义编号 | ||
| 54 | + * | ||
| 55 | + * 关联 ProcessInstance 的 processDefinitionId 属性 | ||
| 56 | + */ | ||
| 57 | + private String processDefinitionId; | ||
| 58 | + /** | ||
| 53 | * 流程分类 | 59 | * 流程分类 |
| 54 | * | 60 | * |
| 55 | * 冗余 ProcessInstance 的 category 字段 | 61 | * 冗余 ProcessInstance 的 category 字段 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
| 1 | package cn.iocoder.yudao.module.bpm.dal.redis; | 1 | package cn.iocoder.yudao.module.bpm.dal.redis; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.date.DateUtil; | 3 | import cn.hutool.core.date.DateUtil; |
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; | 5 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; |
| 5 | import jakarta.annotation.Resource; | 6 | import jakarta.annotation.Resource; |
| 6 | import org.springframework.data.redis.core.StringRedisTemplate; | 7 | import org.springframework.data.redis.core.StringRedisTemplate; |
| @@ -48,7 +49,10 @@ public class BpmProcessIdRedisDAO { | @@ -48,7 +49,10 @@ public class BpmProcessIdRedisDAO { | ||
| 48 | String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix(); | 49 | String noPrefix = processIdRule.getPrefix() + infix + processIdRule.getPostfix(); |
| 49 | String key = RedisKeyConstants.BPM_PROCESS_ID + noPrefix; | 50 | String key = RedisKeyConstants.BPM_PROCESS_ID + noPrefix; |
| 50 | Long no = stringRedisTemplate.opsForValue().increment(key); | 51 | Long no = stringRedisTemplate.opsForValue().increment(key); |
| 51 | - stringRedisTemplate.expire(key, Duration.ofDays(1L)); | 52 | + if (StrUtil.isEmpty(infix)) { |
| 53 | + // 特殊:没有前缀,则不能过期,不能每次都是从 0 开始 | ||
| 54 | + stringRedisTemplate.expire(key, Duration.ofDays(1L)); | ||
| 55 | + } | ||
| 52 | return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no); | 56 | return noPrefix + String.format("%0" + processIdRule.getLength() + "d", no); |
| 53 | } | 57 | } |
| 54 | 58 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| @@ -64,6 +64,13 @@ public class BpmnModelUtils { | @@ -64,6 +64,13 @@ public class BpmnModelUtils { | ||
| 64 | addExtensionElement(element, name, String.valueOf(value)); | 64 | addExtensionElement(element, name, String.valueOf(value)); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | + public static void addExtensionElementJson(FlowElement element, String name, Object value) { | ||
| 68 | + if (value == null) { | ||
| 69 | + return; | ||
| 70 | + } | ||
| 71 | + addExtensionElement(element, name, JsonUtils.toJsonString(value)); | ||
| 72 | + } | ||
| 73 | + | ||
| 67 | public static void addExtensionElement(FlowElement element, String name, Map<String, String> attributes) { | 74 | public static void addExtensionElement(FlowElement element, String name, Map<String, String> attributes) { |
| 68 | if (attributes == null) { | 75 | if (attributes == null) { |
| 69 | return; | 76 | return; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
| @@ -26,6 +26,9 @@ import org.flowable.task.api.TaskInfo; | @@ -26,6 +26,9 @@ import org.flowable.task.api.TaskInfo; | ||
| 26 | 26 | ||
| 27 | import java.util.*; | 27 | import java.util.*; |
| 28 | import java.util.concurrent.Callable; | 28 | import java.util.concurrent.Callable; |
| 29 | +import java.util.stream.Collectors; | ||
| 30 | + | ||
| 31 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 29 | 32 | ||
| 30 | /** | 33 | /** |
| 31 | * Flowable 相关的工具方法 | 34 | * Flowable 相关的工具方法 |
| @@ -193,7 +196,6 @@ public class FlowableUtils { | @@ -193,7 +196,6 @@ public class FlowableUtils { | ||
| 193 | BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES); | 196 | BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES); |
| 194 | } | 197 | } |
| 195 | 198 | ||
| 196 | - // TODO @lesan:如果值是 null 的情况,可能要调研下飞书、钉钉,是不是不返回哈! | ||
| 197 | /** | 199 | /** |
| 198 | * 获得流程实例的摘要 | 200 | * 获得流程实例的摘要 |
| 199 | * | 201 | * |
| @@ -206,53 +208,40 @@ public class FlowableUtils { | @@ -206,53 +208,40 @@ public class FlowableUtils { | ||
| 206 | */ | 208 | */ |
| 207 | public static List<KeyValue<String, String>> getSummary(BpmProcessDefinitionInfoDO processDefinitionInfo, | 209 | public static List<KeyValue<String, String>> getSummary(BpmProcessDefinitionInfoDO processDefinitionInfo, |
| 208 | Map<String, Object> processVariables) { | 210 | Map<String, Object> processVariables) { |
| 209 | - // TODO @lesan:建议 if return,减少 { 层级 | ||
| 210 | - if (ObjectUtil.isNotNull(processDefinitionInfo) | ||
| 211 | - && BpmModelFormTypeEnum.NORMAL.getType().equals(processDefinitionInfo.getFormType())) { | ||
| 212 | - List<KeyValue<String, String>> summaryList = new ArrayList<>(); | ||
| 213 | - // TODO @lesan:可以使用 CollUtils.convertMap 简化工作量哈。 | ||
| 214 | - Map<String, BpmFormFieldVO> formFieldsMap = new HashMap<>(); | ||
| 215 | - processDefinitionInfo.getFormFields().forEach(formFieldStr -> { | ||
| 216 | - BpmFormFieldVO formField = JsonUtils.parseObject(formFieldStr, BpmFormFieldVO.class); | 211 | + // 只有流程表单才会显示摘要! |
| 212 | + if (ObjectUtil.isNull(processDefinitionInfo) | ||
| 213 | + || !BpmModelFormTypeEnum.NORMAL.getType().equals(processDefinitionInfo.getFormType())) { | ||
| 214 | + return null; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + // 解析表单配置 | ||
| 218 | + Map<String, BpmFormFieldVO> formFieldsMap = new HashMap<>(); | ||
| 219 | + processDefinitionInfo.getFormFields().forEach(formFieldStr -> { | ||
| 220 | + BpmFormFieldVO formField = JsonUtils.parseObject(formFieldStr, BpmFormFieldVO.class); | ||
| 221 | + if (formField != null) { | ||
| 222 | + formFieldsMap.put(formField.getField(), formField); | ||
| 223 | + } | ||
| 224 | + }); | ||
| 225 | + | ||
| 226 | + // 情况一:当自定义了摘要 | ||
| 227 | + if (ObjectUtil.isNotNull(processDefinitionInfo.getSummarySetting()) | ||
| 228 | + && Boolean.TRUE.equals(processDefinitionInfo.getSummarySetting().getEnable())) { | ||
| 229 | + return convertList(processDefinitionInfo.getSummarySetting().getSummary(), item -> { | ||
| 230 | + BpmFormFieldVO formField = formFieldsMap.get(item); | ||
| 217 | if (formField != null) { | 231 | if (formField != null) { |
| 218 | - formFieldsMap.put(formField.getField(), formField); | 232 | + return new KeyValue<String, String>(formField.getTitle(), |
| 233 | + processVariables.getOrDefault(item, "").toString()); | ||
| 219 | } | 234 | } |
| 235 | + return null; | ||
| 220 | }); | 236 | }); |
| 221 | - | ||
| 222 | - // TODO @lesan:这里也可以 if return,还是为了减少括号哈。这样,就可以写注释,情况一:;情况二: | ||
| 223 | - if (ObjectUtil.isNotNull(processDefinitionInfo.getSummarySetting()) | ||
| 224 | - && Boolean.TRUE.equals(processDefinitionInfo.getSummarySetting().getEnable())) { | ||
| 225 | - // TODO @lesan:这里,也可以通过 CollUtils.convertList 简化哈。 | ||
| 226 | - for (String item : processDefinitionInfo.getSummarySetting().getSummary()) { | ||
| 227 | - BpmFormFieldVO formField = formFieldsMap.get(item); | ||
| 228 | - if (formField != null) { | ||
| 229 | - summaryList.add(new KeyValue<>(formField.getTitle(), | ||
| 230 | - processVariables.getOrDefault(item, "").toString())); | ||
| 231 | - } | ||
| 232 | - } | ||
| 233 | - } else { | ||
| 234 | - // 默认展示前三个 | ||
| 235 | - /* TODO @lesan:stream 简化 | ||
| 236 | - * summaryList.addAll(formFieldsMap.entrySet().stream() | ||
| 237 | - * .limit(3) | ||
| 238 | - * .map(entry -> new KeyValue<>(entry.getValue().getTitle(), | ||
| 239 | - * processVariables.getOrDefault(entry.getValue().getField(), "").toString())) | ||
| 240 | - * .collect(Collectors.toList())); | ||
| 241 | - */ | ||
| 242 | - int j = 0; | ||
| 243 | - for (Map.Entry<String, BpmFormFieldVO> entry : formFieldsMap.entrySet()) { | ||
| 244 | - BpmFormFieldVO formField = entry.getValue(); | ||
| 245 | - if (j > 2) { | ||
| 246 | - break; | ||
| 247 | - } | ||
| 248 | - summaryList.add(new KeyValue<>(formField.getTitle(), | ||
| 249 | - processVariables.getOrDefault(formField.getField(), "").toString())); | ||
| 250 | - j++; | ||
| 251 | - } | ||
| 252 | - } | ||
| 253 | - return summaryList; | ||
| 254 | } | 237 | } |
| 255 | - return null; | 238 | + |
| 239 | + // 情况二:默认摘要展示前三个表单字段 | ||
| 240 | + return formFieldsMap.entrySet().stream() | ||
| 241 | + .limit(3) | ||
| 242 | + .map(entry -> new KeyValue<>(entry.getValue().getTitle(), | ||
| 243 | + processVariables.getOrDefault(entry.getValue().getField(), "").toString())) | ||
| 244 | + .collect(Collectors.toList()); | ||
| 256 | } | 245 | } |
| 257 | 246 | ||
| 258 | // ========== Task 相关的工具方法 ========== | 247 | // ========== Task 相关的工具方法 ========== |
| @@ -317,9 +306,9 @@ public class FlowableUtils { | @@ -317,9 +306,9 @@ public class FlowableUtils { | ||
| 317 | 306 | ||
| 318 | private static Object getExpressionValue(VariableContainer variableContainer, String expressionString, | 307 | private static Object getExpressionValue(VariableContainer variableContainer, String expressionString, |
| 319 | ProcessEngineConfigurationImpl processEngineConfiguration) { | 308 | ProcessEngineConfigurationImpl processEngineConfiguration) { |
| 320 | - assert processEngineConfiguration!= null; | 309 | + assert processEngineConfiguration != null; |
| 321 | ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager(); | 310 | ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager(); |
| 322 | - assert expressionManager!= null; | 311 | + assert expressionManager != null; |
| 323 | Expression expression = expressionManager.createExpression(expressionString); | 312 | Expression expression = expressionManager.createExpression(expressionString); |
| 324 | return expression.getValue(variableContainer); | 313 | return expression.getValue(variableContainer); |
| 325 | } | 314 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert; | @@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert; | ||
| 5 | import cn.hutool.core.map.MapUtil; | 5 | import cn.hutool.core.map.MapUtil; |
| 6 | import cn.hutool.core.util.*; | 6 | import cn.hutool.core.util.*; |
| 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 8 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 9 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| 10 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; | 9 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; |
| 11 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 10 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| @@ -626,54 +625,50 @@ public class SimpleModelUtils { | @@ -626,54 +625,50 @@ public class SimpleModelUtils { | ||
| 626 | 625 | ||
| 627 | public static SequenceFlow buildSequenceFlow(String sourceId, String targetId, | 626 | public static SequenceFlow buildSequenceFlow(String sourceId, String targetId, |
| 628 | BpmSimpleModelNodeVO node) { | 627 | BpmSimpleModelNodeVO node) { |
| 629 | - String conditionExpression = buildConditionExpression(node); | 628 | + String conditionExpression = buildConditionExpression(node.getConditionSetting()); |
| 630 | return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression); | 629 | return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression); |
| 631 | } | 630 | } |
| 631 | + } | ||
| 632 | 632 | ||
| 633 | - /** | ||
| 634 | - * 构造条件表达式 | ||
| 635 | - * | ||
| 636 | - * @param node 条件节点 | ||
| 637 | - */ | ||
| 638 | - public static String buildConditionExpression(BpmSimpleModelNodeVO node) { | ||
| 639 | - return buildConditionExpression(node.getConditionSetting().getConditionType(), node.getConditionSetting().getConditionExpression(), | ||
| 640 | - node.getConditionSetting().getConditionGroups()); | ||
| 641 | - } | 633 | + /** |
| 634 | + * 构造条件表达式 | ||
| 635 | + */ | ||
| 636 | + public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { | ||
| 637 | + return buildConditionExpression(conditionSetting.getConditionType(), conditionSetting.getConditionExpression(), | ||
| 638 | + conditionSetting.getConditionGroups()); | ||
| 639 | + } | ||
| 642 | 640 | ||
| 643 | - public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting router) { | ||
| 644 | - return buildConditionExpression(router.getConditionType(), router.getConditionExpression(), | ||
| 645 | - router.getConditionGroups()); | ||
| 646 | - } | 641 | + public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting routerSetting) { |
| 642 | + return buildConditionExpression(routerSetting.getConditionType(), routerSetting.getConditionExpression(), | ||
| 643 | + routerSetting.getConditionGroups()); | ||
| 644 | + } | ||
| 647 | 645 | ||
| 648 | - public static String buildConditionExpression(Integer conditionType, String conditionExpression, | ||
| 649 | - ConditionGroups conditionGroups) { | ||
| 650 | - BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType); | ||
| 651 | - if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) { | ||
| 652 | - return conditionExpression; | 646 | + public static String buildConditionExpression(Integer conditionType, String conditionExpression, ConditionGroups conditionGroups) { |
| 647 | + BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType); | ||
| 648 | + if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) { | ||
| 649 | + return conditionExpression; | ||
| 650 | + } | ||
| 651 | + if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) { | ||
| 652 | + if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { | ||
| 653 | + return null; | ||
| 653 | } | 654 | } |
| 654 | - if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) { | ||
| 655 | - if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { | ||
| 656 | - return null; | 655 | + List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { |
| 656 | + if (CollUtil.isEmpty(item.getRules())) { | ||
| 657 | + return ""; | ||
| 657 | } | 658 | } |
| 658 | - List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { | ||
| 659 | - if (CollUtil.isEmpty(item.getRules())) { | ||
| 660 | - return ""; | ||
| 661 | - } | ||
| 662 | - // 构造规则表达式 | ||
| 663 | - List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> { | ||
| 664 | - String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() | ||
| 665 | - : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 | ||
| 666 | - return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); | ||
| 667 | - }); | ||
| 668 | - // 构造条件组的表达式 | ||
| 669 | - Boolean and = item.getAnd(); | ||
| 670 | - return "(" + CollUtil.join(list, and ? " && " : " || ") + ")"; | 659 | + // 构造规则表达式 |
| 660 | + List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> { | ||
| 661 | + String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() | ||
| 662 | + : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 | ||
| 663 | + return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); | ||
| 671 | }); | 664 | }); |
| 672 | - return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || ")); | ||
| 673 | - } | ||
| 674 | - return null; | 665 | + // 构造条件组的表达式 |
| 666 | + Boolean and = item.getAnd(); | ||
| 667 | + return "(" + CollUtil.join(list, and ? " && " : " || ") + ")"; | ||
| 668 | + }); | ||
| 669 | + return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || ")); | ||
| 675 | } | 670 | } |
| 676 | - | 671 | + return null; |
| 677 | } | 672 | } |
| 678 | 673 | ||
| 679 | public static class DelayTimerNodeConvert implements NodeConvert { | 674 | public static class DelayTimerNodeConvert implements NodeConvert { |
| @@ -727,9 +722,10 @@ public class SimpleModelUtils { | @@ -727,9 +722,10 @@ public class SimpleModelUtils { | ||
| 727 | if (node.getTriggerSetting() != null) { | 722 | if (node.getTriggerSetting() != null) { |
| 728 | addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); | 723 | addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); |
| 729 | if (node.getTriggerSetting().getHttpRequestSetting() != null) { | 724 | if (node.getTriggerSetting().getHttpRequestSetting() != null) { |
| 730 | - // TODO @jason:加个 addExtensionElementJson 方法,方便设置 JSON 类型的属性 | ||
| 731 | - addExtensionElement(serviceTask, TRIGGER_PARAM, | ||
| 732 | - JsonUtils.toJsonString(node.getTriggerSetting().getHttpRequestSetting())); | 725 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting()); |
| 726 | + } | ||
| 727 | + if (node.getTriggerSetting().getNormalFormSetting() != null) { | ||
| 728 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getNormalFormSetting()); | ||
| 733 | } | 729 | } |
| 734 | } | 730 | } |
| 735 | return serviceTask; | 731 | return serviceTask; |
| @@ -760,7 +756,7 @@ public class SimpleModelUtils { | @@ -760,7 +756,7 @@ public class SimpleModelUtils { | ||
| 760 | } | 756 | } |
| 761 | 757 | ||
| 762 | public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouterSetting router) { | 758 | public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouterSetting router) { |
| 763 | - String conditionExpression = ConditionNodeConvert.buildConditionExpression(router); | 759 | + String conditionExpression = SimpleModelUtils.buildConditionExpression(router); |
| 764 | return buildBpmnSequenceFlow(nodeId, router.getNodeId(), null, null, conditionExpression); | 760 | return buildBpmnSequenceFlow(nodeId, router.getNodeId(), null, null, conditionExpression); |
| 765 | } | 761 | } |
| 766 | 762 | ||
| @@ -804,7 +800,7 @@ public class SimpleModelUtils { | @@ -804,7 +800,7 @@ public class SimpleModelUtils { | ||
| 804 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 | 800 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 |
| 805 | BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), | 801 | BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), |
| 806 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) | 802 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) |
| 807 | - && evalConditionExpress(variables, conditionNode)); | 803 | + && evalConditionExpress(variables, conditionNode.getConditionSetting())); |
| 808 | if (matchConditionNode == null) { | 804 | if (matchConditionNode == null) { |
| 809 | matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), | 805 | matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), |
| 810 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); | 806 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); |
| @@ -819,7 +815,7 @@ public class SimpleModelUtils { | @@ -819,7 +815,7 @@ public class SimpleModelUtils { | ||
| 819 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 | 815 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 |
| 820 | Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), | 816 | Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), |
| 821 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) | 817 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) |
| 822 | - && evalConditionExpress(variables, conditionNode)); | 818 | + && evalConditionExpress(variables, conditionNode.getConditionSetting())); |
| 823 | if (CollUtil.isEmpty(matchConditionNodes)) { | 819 | if (CollUtil.isEmpty(matchConditionNodes)) { |
| 824 | matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), | 820 | matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), |
| 825 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); | 821 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); |
| @@ -841,16 +837,17 @@ public class SimpleModelUtils { | @@ -841,16 +837,17 @@ public class SimpleModelUtils { | ||
| 841 | simulateNextNode(currentNode.getChildNode(), variables, resultNodes); | 837 | simulateNextNode(currentNode.getChildNode(), variables, resultNodes); |
| 842 | } | 838 | } |
| 843 | 839 | ||
| 844 | - public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO conditionNode) { | ||
| 845 | - return BpmnModelUtils.evalConditionExpress(variables, ConditionNodeConvert.buildConditionExpression(conditionNode)); | 840 | + public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { |
| 841 | + return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); | ||
| 846 | } | 842 | } |
| 847 | 843 | ||
| 848 | // TODO @芋艿:【高】要不要优化下,抽个 HttpUtils | 844 | // TODO @芋艿:【高】要不要优化下,抽个 HttpUtils |
| 845 | + | ||
| 849 | /** | 846 | /** |
| 850 | * 添加 HTTP 请求参数。请求头或者请求体 | 847 | * 添加 HTTP 请求参数。请求头或者请求体 |
| 851 | * | 848 | * |
| 852 | - * @param params HTTP 请求参数 | ||
| 853 | - * @param paramSettings HTTP 请求参数设置 | 849 | + * @param params HTTP 请求参数 |
| 850 | + * @param paramSettings HTTP 请求参数设置 | ||
| 854 | * @param processVariables 流程变量 | 851 | * @param processVariables 流程变量 |
| 855 | */ | 852 | */ |
| 856 | public static void addHttpRequestParam(MultiValueMap<String, String> params, | 853 | public static void addHttpRequestParam(MultiValueMap<String, String> params, |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
| @@ -86,6 +86,7 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -86,6 +86,7 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 86 | if (StrUtil.isNotEmpty(name)) { | 86 | if (StrUtil.isNotEmpty(name)) { |
| 87 | modelQuery.modelNameLike("%" + name + "%"); | 87 | modelQuery.modelNameLike("%" + name + "%"); |
| 88 | } | 88 | } |
| 89 | + modelQuery.modelTenantId(FlowableUtils.getTenantId()); | ||
| 89 | return modelQuery.list(); | 90 | return modelQuery.list(); |
| 90 | } | 91 | } |
| 91 | 92 | ||
| @@ -288,8 +289,7 @@ public class BpmModelServiceImpl implements BpmModelService { | @@ -288,8 +289,7 @@ public class BpmModelServiceImpl implements BpmModelService { | ||
| 288 | // 2.3 清理所有 Task | 289 | // 2.3 清理所有 Task |
| 289 | List<Task> tasks = taskService.createTaskQuery() | 290 | List<Task> tasks = taskService.createTaskQuery() |
| 290 | .processDefinitionKey(model.getKey()).list(); | 291 | .processDefinitionKey(model.getKey()).list(); |
| 291 | - // TODO @lesan:貌似传递一个 reason 会好点! | ||
| 292 | - tasks.forEach(task -> taskService.deleteTask(task.getId())); | 292 | + tasks.forEach(task -> taskService.deleteTask(task.getId(),BpmReasonEnum.CANCEL_BY_PROCESS_CLEAN.getReason())); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | @Override | 295 | @Override |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceCopyServiceImpl.java
| @@ -77,7 +77,8 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy | @@ -77,7 +77,8 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy | ||
| 77 | .setUserId(userId).setReason(reason).setStartUserId(Long.valueOf(processInstance.getStartUserId())) | 77 | .setUserId(userId).setReason(reason).setStartUserId(Long.valueOf(processInstance.getStartUserId())) |
| 78 | .setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName()) | 78 | .setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName()) |
| 79 | .setCategory(processDefinition.getCategory()).setTaskId(taskId) | 79 | .setCategory(processDefinition.getCategory()).setTaskId(taskId) |
| 80 | - .setActivityId(activityId).setActivityName(activityName)); | 80 | + .setActivityId(activityId).setActivityName(activityName) |
| 81 | + .setProcessDefinitionId(processInstance.getProcessDefinitionId())); | ||
| 81 | processInstanceCopyMapper.insertBatch(copyList); | 82 | processInstanceCopyMapper.insertBatch(copyList); |
| 82 | } | 83 | } |
| 83 | 84 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
| @@ -157,4 +157,12 @@ public interface BpmProcessInstanceService { | @@ -157,4 +157,12 @@ public interface BpmProcessInstanceService { | ||
| 157 | */ | 157 | */ |
| 158 | void processProcessInstanceCompleted(ProcessInstance instance); | 158 | void processProcessInstanceCompleted(ProcessInstance instance); |
| 159 | 159 | ||
| 160 | + /** | ||
| 161 | + * 更新 ProcessInstance 的变量 | ||
| 162 | + * | ||
| 163 | + * @param id 流程编号 | ||
| 164 | + * @param variables 流程变量 | ||
| 165 | + */ | ||
| 166 | + void updateProcessInstanceVariables(String id, Map<String, Object> variables); | ||
| 167 | + | ||
| 160 | } | 168 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -133,56 +133,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -133,56 +133,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 133 | 133 | ||
| 134 | @Override | 134 | @Override |
| 135 | public HistoricProcessInstance getHistoricProcessInstance(String id) { | 135 | public HistoricProcessInstance getHistoricProcessInstance(String id) { |
| 136 | - return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult(); | 136 | + return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables() |
| 137 | + .singleResult(); | ||
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | @Override | 140 | @Override |
| 140 | public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { | 141 | public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { |
| 141 | - return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables().list(); | 142 | + return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables() |
| 143 | + .list(); | ||
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | - @Override | ||
| 145 | - public PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId, | ||
| 146 | - BpmProcessInstancePageReqVO pageReqVO) { | ||
| 147 | - // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 | ||
| 148 | - HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery() | ||
| 149 | - .includeProcessVariables() | ||
| 150 | - .processInstanceTenantId(FlowableUtils.getTenantId()) | ||
| 151 | - .orderByProcessInstanceStartTime().desc(); | ||
| 152 | - if (userId != null) { // 【我的流程】菜单时,需要传递该字段 | ||
| 153 | - processInstanceQuery.startedBy(String.valueOf(userId)); | ||
| 154 | - } else if (pageReqVO.getStartUserId() != null) { // 【管理流程】菜单时,才会传递该字段 | ||
| 155 | - processInstanceQuery.startedBy(String.valueOf(pageReqVO.getStartUserId())); | ||
| 156 | - } | ||
| 157 | - if (StrUtil.isNotEmpty(pageReqVO.getName())) { | ||
| 158 | - processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%"); | ||
| 159 | - } | ||
| 160 | - if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionKey())) { | ||
| 161 | - processInstanceQuery.processDefinitionKey(pageReqVO.getProcessDefinitionKey()); | ||
| 162 | - } | ||
| 163 | - if (StrUtil.isNotEmpty(pageReqVO.getCategory())) { | ||
| 164 | - processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory()); | ||
| 165 | - } | ||
| 166 | - if (pageReqVO.getStatus() != null) { | ||
| 167 | - processInstanceQuery.variableValueEquals(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, pageReqVO.getStatus()); | ||
| 168 | - } | ||
| 169 | - if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) { | ||
| 170 | - processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0])); | ||
| 171 | - processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1])); | ||
| 172 | - } | ||
| 173 | - // 查询数量 | ||
| 174 | - long processInstanceCount = processInstanceQuery.count(); | ||
| 175 | - if (processInstanceCount == 0) { | ||
| 176 | - return PageResult.empty(processInstanceCount); | ||
| 177 | - } | ||
| 178 | - // 查询列表 | ||
| 179 | - List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), pageReqVO.getPageSize()); | ||
| 180 | - return new PageResult<>(processInstanceList, processInstanceCount); | ||
| 181 | - } | ||
| 182 | - | ||
| 183 | - | ||
| 184 | private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel, | 146 | private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel, |
| 185 | - String activityId, String taskId) { | 147 | + String activityId, String taskId) { |
| 186 | // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id | 148 | // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id |
| 187 | if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) { | 149 | if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) { |
| 188 | activityId = Optional.ofNullable(taskService.getHistoricTask(taskId)) | 150 | activityId = Optional.ofNullable(taskService.getHistoricTask(taskId)) |
| @@ -215,8 +177,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -215,8 +177,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 215 | } | 177 | } |
| 216 | // 1.3 读取其它相关数据 | 178 | // 1.3 读取其它相关数据 |
| 217 | ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition( | 179 | ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition( |
| 218 | - historicProcessInstance != null ? historicProcessInstance.getProcessDefinitionId() : reqVO.getProcessDefinitionId()); | ||
| 219 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(processDefinition.getId()); | 180 | + historicProcessInstance != null ? historicProcessInstance.getProcessDefinitionId() |
| 181 | + : reqVO.getProcessDefinitionId()); | ||
| 182 | + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService | ||
| 183 | + .getProcessDefinitionInfo(processDefinition.getId()); | ||
| 220 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId()); | 184 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId()); |
| 221 | 185 | ||
| 222 | // 2.1 已结束 + 进行中的活动节点 | 186 | // 2.1 已结束 + 进行中的活动节点 |
| @@ -225,24 +189,29 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -225,24 +189,29 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 225 | List<HistoricActivityInstance> activities = null; // 流程实例列表 | 189 | List<HistoricActivityInstance> activities = null; // 流程实例列表 |
| 226 | if (reqVO.getProcessInstanceId() != null) { | 190 | if (reqVO.getProcessInstanceId() != null) { |
| 227 | activities = taskService.getActivityListByProcessInstanceId(reqVO.getProcessInstanceId()); | 191 | activities = taskService.getActivityListByProcessInstanceId(reqVO.getProcessInstanceId()); |
| 228 | - List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(reqVO.getProcessInstanceId(), true); | 192 | + List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(reqVO.getProcessInstanceId(), |
| 193 | + true); | ||
| 229 | endActivityNodes = getEndActivityNodeList(startUserId, bpmnModel, processDefinitionInfo, | 194 | endActivityNodes = getEndActivityNodeList(startUserId, bpmnModel, processDefinitionInfo, |
| 230 | historicProcessInstance, processInstanceStatus, activities, tasks); | 195 | historicProcessInstance, processInstanceStatus, activities, tasks); |
| 231 | - runActivityNodes = getRunApproveNodeList(startUserId, bpmnModel, processDefinition, processVariables, activities, tasks); | 196 | + runActivityNodes = getRunApproveNodeList(startUserId, bpmnModel, processDefinition, processVariables, |
| 197 | + activities, tasks); | ||
| 232 | } | 198 | } |
| 233 | 199 | ||
| 234 | // 2.2 流程已经结束,直接 return,无需预测 | 200 | // 2.2 流程已经结束,直接 return,无需预测 |
| 235 | if (BpmProcessInstanceStatusEnum.isProcessEndStatus(processInstanceStatus)) { | 201 | if (BpmProcessInstanceStatusEnum.isProcessEndStatus(processInstanceStatus)) { |
| 236 | - return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, historicProcessInstance, | 202 | + return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, |
| 203 | + historicProcessInstance, | ||
| 237 | processInstanceStatus, endActivityNodes, runActivityNodes, null, null); | 204 | processInstanceStatus, endActivityNodes, runActivityNodes, null, null); |
| 238 | } | 205 | } |
| 239 | 206 | ||
| 240 | // 3.1 计算当前登录用户的待办任务 | 207 | // 3.1 计算当前登录用户的待办任务 |
| 241 | - // TODO @jason:有一个极端情况,如果一个用户有 2 个 task A 和 B,A 已经通过,B 需要审核。这个时,通过 A 进来,todo 拿到 B,会不会表单权限不一致哈。 | 208 | + // TODO @jason:有一个极端情况,如果一个用户有 2 个 task A 和 B,A 已经通过,B 需要审核。这个时,通过 A 进来,todo 拿到 |
| 209 | + // B,会不会表单权限不一致哈。 | ||
| 242 | BpmTaskRespVO todoTask = taskService.getFirstTodoTask(loginUserId, reqVO.getProcessInstanceId()); | 210 | BpmTaskRespVO todoTask = taskService.getFirstTodoTask(loginUserId, reqVO.getProcessInstanceId()); |
| 243 | 211 | ||
| 244 | // 3.2 预测未运行节点的审批信息 | 212 | // 3.2 预测未运行节点的审批信息 |
| 245 | - List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel, processDefinitionInfo, | 213 | + List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel, |
| 214 | + processDefinitionInfo, | ||
| 246 | processVariables, activities); | 215 | processVariables, activities); |
| 247 | 216 | ||
| 248 | // 4. 拼接最终数据 | 217 | // 4. 拼接最终数据 |
| @@ -250,34 +219,93 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -250,34 +219,93 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 250 | processInstanceStatus, endActivityNodes, runActivityNodes, simulateActivityNodes, todoTask); | 219 | processInstanceStatus, endActivityNodes, runActivityNodes, simulateActivityNodes, todoTask); |
| 251 | } | 220 | } |
| 252 | 221 | ||
| 222 | + @Override | ||
| 223 | + @SuppressWarnings("unchecked") | ||
| 224 | + public PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId, | ||
| 225 | + BpmProcessInstancePageReqVO pageReqVO) { | ||
| 226 | + // 1. 构建查询条件 | ||
| 227 | + HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery() | ||
| 228 | + .includeProcessVariables() | ||
| 229 | + .processInstanceTenantId(FlowableUtils.getTenantId()) | ||
| 230 | + .orderByProcessInstanceStartTime().desc(); | ||
| 231 | + if (userId != null) { // 【我的流程】菜单时,需要传递该字段 | ||
| 232 | + processInstanceQuery.startedBy(String.valueOf(userId)); | ||
| 233 | + } else if (pageReqVO.getStartUserId() != null) { // 【管理流程】菜单时,才会传递该字段 | ||
| 234 | + processInstanceQuery.startedBy(String.valueOf(pageReqVO.getStartUserId())); | ||
| 235 | + } | ||
| 236 | + if (StrUtil.isNotEmpty(pageReqVO.getName())) { | ||
| 237 | + processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%"); | ||
| 238 | + } | ||
| 239 | + if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionKey())) { | ||
| 240 | + processInstanceQuery.processDefinitionKey(pageReqVO.getProcessDefinitionKey()); | ||
| 241 | + } | ||
| 242 | + if (StrUtil.isNotEmpty(pageReqVO.getCategory())) { | ||
| 243 | + processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory()); | ||
| 244 | + } | ||
| 245 | + if (pageReqVO.getStatus() != null) { | ||
| 246 | + processInstanceQuery.variableValueEquals(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, | ||
| 247 | + pageReqVO.getStatus()); | ||
| 248 | + } | ||
| 249 | + if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) { | ||
| 250 | + processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0])); | ||
| 251 | + processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1])); | ||
| 252 | + } | ||
| 253 | + if (ArrayUtil.isNotEmpty(pageReqVO.getEndTime())) { | ||
| 254 | + processInstanceQuery.finishedAfter(DateUtils.of(pageReqVO.getEndTime()[0])); | ||
| 255 | + processInstanceQuery.finishedBefore(DateUtils.of(pageReqVO.getEndTime()[1])); | ||
| 256 | + } | ||
| 257 | + // 表单字段查询 | ||
| 258 | + Map<String, Object> formFieldsParams = JsonUtils.parseObject(pageReqVO.getFormFieldsParams(), Map.class); | ||
| 259 | + if (CollUtil.isNotEmpty(formFieldsParams)) { | ||
| 260 | + formFieldsParams.forEach((key, value) -> { | ||
| 261 | + if (StrUtil.isEmpty(String.valueOf(value))) { | ||
| 262 | + return; | ||
| 263 | + } | ||
| 264 | + // TODO @lesan:应支持多种类型的查询方式,目前只有字符串全等 | ||
| 265 | + processInstanceQuery.variableValueEquals(key, value); | ||
| 266 | + }); | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + // 2.1 查询数量 | ||
| 270 | + long processInstanceCount = processInstanceQuery.count(); | ||
| 271 | + if (processInstanceCount == 0) { | ||
| 272 | + return PageResult.empty(processInstanceCount); | ||
| 273 | + } | ||
| 274 | + // 2.2 查询列表 | ||
| 275 | + List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), | ||
| 276 | + pageReqVO.getPageSize()); | ||
| 277 | + return new PageResult<>(processInstanceList, processInstanceCount); | ||
| 278 | + } | ||
| 279 | + | ||
| 253 | /** | 280 | /** |
| 254 | * 拼接审批详情的最终数据 | 281 | * 拼接审批详情的最终数据 |
| 255 | * <p> | 282 | * <p> |
| 256 | * 主要是,拼接审批人的用户信息、部门信息 | 283 | * 主要是,拼接审批人的用户信息、部门信息 |
| 257 | */ | 284 | */ |
| 258 | private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO, | 285 | private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO, |
| 259 | - BpmnModel bpmnModel, | ||
| 260 | - ProcessDefinition processDefinition, | ||
| 261 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | ||
| 262 | - HistoricProcessInstance processInstance, | ||
| 263 | - Integer processInstanceStatus, | ||
| 264 | - List<ActivityNode> endApprovalNodeInfos, | ||
| 265 | - List<ActivityNode> runningApprovalNodeInfos, | ||
| 266 | - List<ActivityNode> simulateApprovalNodeInfos, | ||
| 267 | - BpmTaskRespVO todoTask) { | 286 | + BpmnModel bpmnModel, |
| 287 | + ProcessDefinition processDefinition, | ||
| 288 | + BpmProcessDefinitionInfoDO processDefinitionInfo, | ||
| 289 | + HistoricProcessInstance processInstance, | ||
| 290 | + Integer processInstanceStatus, | ||
| 291 | + List<ActivityNode> endApprovalNodeInfos, | ||
| 292 | + List<ActivityNode> runningApprovalNodeInfos, | ||
| 293 | + List<ActivityNode> simulateApprovalNodeInfos, | ||
| 294 | + BpmTaskRespVO todoTask) { | ||
| 268 | // 1. 获取所有需要读取用户信息的 userIds | 295 | // 1. 获取所有需要读取用户信息的 userIds |
| 269 | - List<ActivityNode> approveNodes = newArrayList(asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos)); | 296 | + List<ActivityNode> approveNodes = newArrayList( |
| 297 | + asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos)); | ||
| 270 | Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds(processInstance, approveNodes, todoTask); | 298 | Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds(processInstance, approveNodes, todoTask); |
| 271 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | 299 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| 272 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | 300 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); |
| 273 | 301 | ||
| 274 | - | ||
| 275 | // 2. 表单权限 | 302 | // 2. 表单权限 |
| 276 | String taskId = reqVO.getTaskId() == null && todoTask != null ? todoTask.getId() : reqVO.getTaskId(); | 303 | String taskId = reqVO.getTaskId() == null && todoTask != null ? todoTask.getId() : reqVO.getTaskId(); |
| 277 | Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId); | 304 | Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId); |
| 278 | 305 | ||
| 279 | // 3. 拼接数据 | 306 | // 3. 拼接数据 |
| 280 | - return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition, processDefinitionInfo, processInstance, | 307 | + return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition, |
| 308 | + processDefinitionInfo, processInstance, | ||
| 281 | processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap); | 309 | processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap); |
| 282 | } | 310 | } |
| 283 | 311 | ||
| @@ -285,17 +313,19 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -285,17 +313,19 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 285 | * 获得【已结束】的活动节点们 | 313 | * 获得【已结束】的活动节点们 |
| 286 | */ | 314 | */ |
| 287 | private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel, | 315 | private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel, |
| 288 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | ||
| 289 | - HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus, | ||
| 290 | - List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { | 316 | + BpmProcessDefinitionInfoDO processDefinitionInfo, |
| 317 | + HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus, | ||
| 318 | + List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { | ||
| 291 | // 遍历 tasks 列表,只处理已结束的 UserTask | 319 | // 遍历 tasks 列表,只处理已结束的 UserTask |
| 292 | - // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点 | 320 | + // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities |
| 321 | + // 的话,它无法成为一个节点 | ||
| 293 | List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null); | 322 | List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null); |
| 294 | List<ActivityNode> approvalNodes = convertList(endTasks, task -> { | 323 | List<ActivityNode> approvalNodes = convertList(endTasks, task -> { |
| 295 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); | 324 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); |
| 296 | ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName()) | 325 | ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName()) |
| 297 | - .setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey()) ? | ||
| 298 | - BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() : BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) | 326 | + .setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey()) |
| 327 | + ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() | ||
| 328 | + : BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) | ||
| 299 | .setStatus(FlowableUtils.getTaskStatus(task)) | 329 | .setStatus(FlowableUtils.getTaskStatus(task)) |
| 300 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) | 330 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) |
| 301 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) | 331 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) |
| @@ -320,7 +350,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -320,7 +350,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 320 | .setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName()) | 350 | .setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName()) |
| 321 | .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()) | 351 | .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()) |
| 322 | .setStatus(startTask.getStatus()).setTasks(ListUtil.of(startTask)) | 352 | .setStatus(startTask.getStatus()).setTasks(ListUtil.of(startTask)) |
| 323 | - .setStartTime(DateUtils.of(activity.getStartTime())).setEndTime(DateUtils.of(activity.getEndTime())); | 353 | + .setStartTime(DateUtils.of(activity.getStartTime())) |
| 354 | + .setEndTime(DateUtils.of(activity.getEndTime())); | ||
| 324 | approvalNodes.add(0, startNode); | 355 | approvalNodes.add(0, startNode); |
| 325 | return; | 356 | return; |
| 326 | } | 357 | } |
| @@ -333,7 +364,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -333,7 +364,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 333 | ActivityNode endNode = new ActivityNode().setId(activity.getId()) | 364 | ActivityNode endNode = new ActivityNode().setId(activity.getId()) |
| 334 | .setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName()) | 365 | .setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName()) |
| 335 | .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType()).setStatus(processInstanceStatus) | 366 | .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType()).setStatus(processInstanceStatus) |
| 336 | - .setStartTime(DateUtils.of(activity.getStartTime())).setEndTime(DateUtils.of(activity.getEndTime())); | 367 | + .setStartTime(DateUtils.of(activity.getStartTime())) |
| 368 | + .setEndTime(DateUtils.of(activity.getEndTime())); | ||
| 337 | String reason = FlowableUtils.getProcessInstanceReason(historicProcessInstance); | 369 | String reason = FlowableUtils.getProcessInstanceReason(historicProcessInstance); |
| 338 | if (StrUtil.isNotEmpty(reason)) { | 370 | if (StrUtil.isNotEmpty(reason)) { |
| 339 | endNode.setTasks(singletonList(new ActivityNodeTask().setId(endNode.getId()) | 371 | endNode.setTasks(singletonList(new ActivityNodeTask().setId(endNode.getId()) |
| @@ -349,15 +381,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -349,15 +381,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 349 | * 获得【进行中】的活动节点们 | 381 | * 获得【进行中】的活动节点们 |
| 350 | */ | 382 | */ |
| 351 | private List<ActivityNode> getRunApproveNodeList(Long startUserId, | 383 | private List<ActivityNode> getRunApproveNodeList(Long startUserId, |
| 352 | - BpmnModel bpmnModel, | ||
| 353 | - ProcessDefinition processDefinition, | ||
| 354 | - Map<String, Object> processVariables, | ||
| 355 | - List<HistoricActivityInstance> activities, | ||
| 356 | - List<HistoricTaskInstance> tasks) { | 384 | + BpmnModel bpmnModel, |
| 385 | + ProcessDefinition processDefinition, | ||
| 386 | + Map<String, Object> processVariables, | ||
| 387 | + List<HistoricActivityInstance> activities, | ||
| 388 | + List<HistoricTaskInstance> tasks) { | ||
| 357 | // 构建运行中的任务,基于 activityId 分组 | 389 | // 构建运行中的任务,基于 activityId 分组 |
| 358 | List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null | 390 | List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null |
| 359 | && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER))); | 391 | && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER))); |
| 360 | - Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities, HistoricActivityInstance::getActivityId); | 392 | + Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities, |
| 393 | + HistoricActivityInstance::getActivityId); | ||
| 361 | 394 | ||
| 362 | // 按照 activityId 分组,构建 ApprovalNodeInfo 节点 | 395 | // 按照 activityId 分组,构建 ApprovalNodeInfo 节点 |
| 363 | Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId); | 396 | Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId); |
| @@ -367,8 +400,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -367,8 +400,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 367 | // 构建活动节点 | 400 | // 构建活动节点 |
| 368 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, activityId); | 401 | FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, activityId); |
| 369 | HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同 | 402 | HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同 |
| 370 | - ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId()).setName(firstActivity.getActivityName()) | ||
| 371 | - .setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) | 403 | + ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId()) |
| 404 | + .setName(firstActivity.getActivityName()) | ||
| 405 | + .setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) | ||
| 406 | + .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) | ||
| 372 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) | 407 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) |
| 373 | .setStartTime(DateUtils.of(CollUtil.getFirst(taskActivities).getStartTime())) | 408 | .setStartTime(DateUtils.of(CollUtil.getFirst(taskActivities).getStartTime())) |
| 374 | .setTasks(new ArrayList<>()); | 409 | .setTasks(new ArrayList<>()); |
| @@ -381,7 +416,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -381,7 +416,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 381 | taskService.getAllChildrenTaskListByParentTaskId(activity.getTaskId(), tasks), | 416 | taskService.getAllChildrenTaskListByParentTaskId(activity.getTaskId(), tasks), |
| 382 | childTask -> childTask.getEndTime() == null); | 417 | childTask -> childTask.getEndTime() == null); |
| 383 | if (CollUtil.isNotEmpty(childrenTasks)) { | 418 | if (CollUtil.isNotEmpty(childrenTasks)) { |
| 384 | - activityNode.getTasks().addAll(convertList(childrenTasks, BpmProcessInstanceConvert.INSTANCE::buildApprovalTaskInfo)); | 419 | + activityNode.getTasks().addAll( |
| 420 | + convertList(childrenTasks, BpmProcessInstanceConvert.INSTANCE::buildApprovalTaskInfo)); | ||
| 385 | } | 421 | } |
| 386 | } | 422 | } |
| 387 | // 处理每个任务的 candidateUsers 属性:如果是依次审批,需要预测它的后续审批人。因为 Task 是审批完一个,创建一个新的 Task | 423 | // 处理每个任务的 candidateUsers 属性:如果是依次审批,需要预测它的后续审批人。因为 Task 是审批完一个,创建一个新的 Task |
| @@ -391,8 +427,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -391,8 +427,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 391 | // 截取当前审批人位置后面的候选人,不包含当前审批人 | 427 | // 截取当前审批人位置后面的候选人,不包含当前审批人 |
| 392 | ActivityNodeTask approvalTaskInfo = CollUtil.getFirst(activityNode.getTasks()); | 428 | ActivityNodeTask approvalTaskInfo = CollUtil.getFirst(activityNode.getTasks()); |
| 393 | Assert.notNull(approvalTaskInfo, "任务不能为空"); | 429 | Assert.notNull(approvalTaskInfo, "任务不能为空"); |
| 394 | - int index = CollUtil.indexOf(candidateUserIds, userId -> ObjectUtils.equalsAny(userId, approvalTaskInfo.getOwner(), | ||
| 395 | - approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner | 430 | + int index = CollUtil.indexOf(candidateUserIds, |
| 431 | + userId -> ObjectUtils.equalsAny(userId, approvalTaskInfo.getOwner(), | ||
| 432 | + approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner | ||
| 396 | activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); | 433 | activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); |
| 397 | } | 434 | } |
| 398 | return activityNode; | 435 | return activityNode; |
| @@ -403,10 +440,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -403,10 +440,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 403 | * 获得【预测(未来)】的活动节点们 | 440 | * 获得【预测(未来)】的活动节点们 |
| 404 | */ | 441 | */ |
| 405 | private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel, | 442 | private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel, |
| 406 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | ||
| 407 | - Map<String, Object> processVariables, | ||
| 408 | - List<HistoricActivityInstance> activities) { | ||
| 409 | - // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance 包括了历史的操作,不是只有 startEvent 到当前节点的记录 | 443 | + BpmProcessDefinitionInfoDO processDefinitionInfo, |
| 444 | + Map<String, Object> processVariables, | ||
| 445 | + List<HistoricActivityInstance> activities) { | ||
| 446 | + // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance | ||
| 447 | + // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 | ||
| 410 | Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId); | 448 | Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId); |
| 411 | // 情况一:BPMN 设计器 | 449 | // 情况一:BPMN 设计器 |
| 412 | if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) { | 450 | if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) { |
| @@ -416,7 +454,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -416,7 +454,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 416 | } | 454 | } |
| 417 | // 情况二:SIMPLE 设计器 | 455 | // 情况二:SIMPLE 设计器 |
| 418 | if (Objects.equals(BpmModelTypeEnum.SIMPLE.getType(), processDefinitionInfo.getModelType())) { | 456 | if (Objects.equals(BpmModelTypeEnum.SIMPLE.getType(), processDefinitionInfo.getModelType())) { |
| 419 | - BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), BpmSimpleModelNodeVO.class); | 457 | + BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), |
| 458 | + BpmSimpleModelNodeVO.class); | ||
| 420 | List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables); | 459 | List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables); |
| 421 | return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple(startUserId, bpmnModel, | 460 | return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple(startUserId, bpmnModel, |
| 422 | processDefinitionInfo, processVariables, simpleNode, runActivityIds)); | 461 | processDefinitionInfo, processVariables, simpleNode, runActivityIds)); |
| @@ -425,9 +464,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -425,9 +464,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 425 | } | 464 | } |
| 426 | 465 | ||
| 427 | private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel, | 466 | private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel, |
| 428 | - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | ||
| 429 | - BpmSimpleModelNodeVO node, Set<String> runActivityIds) { | ||
| 430 | - // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance 包括了历史的操作,不是只有 startEvent 到当前节点的记录 | 467 | + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, |
| 468 | + BpmSimpleModelNodeVO node, Set<String> runActivityIds) { | ||
| 469 | + // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance | ||
| 470 | + // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 | ||
| 431 | if (runActivityIds.contains(node.getId())) { | 471 | if (runActivityIds.contains(node.getId())) { |
| 432 | return null; | 472 | return null; |
| 433 | } | 473 | } |
| @@ -460,12 +500,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -460,12 +500,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 460 | } | 500 | } |
| 461 | 501 | ||
| 462 | private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, | 502 | private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, |
| 463 | - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | ||
| 464 | - FlowElement node, Set<String> runActivityIds) { | 503 | + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, |
| 504 | + FlowElement node, Set<String> runActivityIds) { | ||
| 465 | if (runActivityIds.contains(node.getId())) { | 505 | if (runActivityIds.contains(node.getId())) { |
| 466 | return null; | 506 | return null; |
| 467 | } | 507 | } |
| 468 | - ActivityNode activityNode = new ActivityNode().setId(node.getId()).setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | 508 | + ActivityNode activityNode = new ActivityNode().setId(node.getId()) |
| 509 | + .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | ||
| 469 | 510 | ||
| 470 | // 1. 开始节点 | 511 | // 1. 开始节点 |
| 471 | if (node instanceof StartEvent) { | 512 | if (node instanceof StartEvent) { |
| @@ -491,7 +532,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -491,7 +532,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 491 | } | 532 | } |
| 492 | 533 | ||
| 493 | private List<Long> getTaskCandidateUserList(BpmnModel bpmnModel, String activityId, | 534 | private List<Long> getTaskCandidateUserList(BpmnModel bpmnModel, String activityId, |
| 494 | - Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { | 535 | + Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { |
| 495 | Set<Long> userIds = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId, | 536 | Set<Long> userIds = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId, |
| 496 | startUserId, processDefinitionId, processVariables); | 537 | startUserId, processDefinitionId, processVariables); |
| 497 | return new ArrayList<>(userIds); | 538 | return new ArrayList<>(userIds); |
| @@ -505,14 +546,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -505,14 +546,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 505 | return null; | 546 | return null; |
| 506 | } | 547 | } |
| 507 | // 1.2 获得流程定义 | 548 | // 1.2 获得流程定义 |
| 508 | - BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); | 549 | + BpmnModel bpmnModel = processDefinitionService |
| 550 | + .getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()); | ||
| 509 | if (bpmnModel == null) { | 551 | if (bpmnModel == null) { |
| 510 | return null; | 552 | return null; |
| 511 | } | 553 | } |
| 512 | BpmSimpleModelNodeVO simpleModel = null; | 554 | BpmSimpleModelNodeVO simpleModel = null; |
| 513 | BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo( | 555 | BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo( |
| 514 | processInstance.getProcessDefinitionId()); | 556 | processInstance.getProcessDefinitionId()); |
| 515 | - if (processDefinitionInfo != null && BpmModelTypeEnum.SIMPLE.getType().equals(processDefinitionInfo.getModelType())) { | 557 | + if (processDefinitionInfo != null |
| 558 | + && BpmModelTypeEnum.SIMPLE.getType().equals(processDefinitionInfo.getModelType())) { | ||
| 516 | simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), BpmSimpleModelNodeVO.class); | 559 | simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), BpmSimpleModelNodeVO.class); |
| 517 | } | 560 | } |
| 518 | // 1.3 获得流程实例对应的活动实例列表 + 任务列表 | 561 | // 1.3 获得流程实例对应的活动实例列表 + 任务列表 |
| @@ -524,10 +567,12 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -524,10 +567,12 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 524 | activityInstance -> activityInstance.getEndTime() == null); | 567 | activityInstance -> activityInstance.getEndTime() == null); |
| 525 | Set<String> finishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, | 568 | Set<String> finishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, |
| 526 | activityInstance -> activityInstance.getEndTime() != null | 569 | activityInstance -> activityInstance.getEndTime() != null |
| 527 | - && ObjectUtil.notEqual(activityInstance.getActivityType(), BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | 570 | + && ObjectUtil.notEqual(activityInstance.getActivityType(), |
| 571 | + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | ||
| 528 | Set<String> finishedSequenceFlowActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, | 572 | Set<String> finishedSequenceFlowActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, |
| 529 | activityInstance -> activityInstance.getEndTime() != null | 573 | activityInstance -> activityInstance.getEndTime() != null |
| 530 | - && ObjectUtil.equals(activityInstance.getActivityType(), BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | 574 | + && ObjectUtil.equals(activityInstance.getActivityType(), |
| 575 | + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | ||
| 531 | // 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉 | 576 | // 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉 |
| 532 | finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds); | 577 | finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds); |
| 533 | // 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。 | 578 | // 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。 |
| @@ -545,8 +590,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -545,8 +590,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 545 | Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds02(processInstance, tasks); | 590 | Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds02(processInstance, tasks); |
| 546 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | 591 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| 547 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | 592 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); |
| 548 | - return BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceBpmnModelView(processInstance, tasks, bpmnModel, simpleModel, | ||
| 549 | - unfinishedTaskActivityIds, finishedTaskActivityIds, finishedSequenceFlowActivityIds, rejectTaskActivityIds, | 593 | + return BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceBpmnModelView(processInstance, tasks, bpmnModel, |
| 594 | + simpleModel, | ||
| 595 | + unfinishedTaskActivityIds, finishedTaskActivityIds, finishedSequenceFlowActivityIds, | ||
| 596 | + rejectTaskActivityIds, | ||
| 550 | userMap, deptMap); | 597 | userMap, deptMap); |
| 551 | } | 598 | } |
| 552 | 599 | ||
| @@ -556,7 +603,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -556,7 +603,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 556 | @Transactional(rollbackFor = Exception.class) | 603 | @Transactional(rollbackFor = Exception.class) |
| 557 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { | 604 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { |
| 558 | // 获得流程定义 | 605 | // 获得流程定义 |
| 559 | - ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); | 606 | + ProcessDefinition definition = processDefinitionService |
| 607 | + .getProcessDefinition(createReqVO.getProcessDefinitionId()); | ||
| 560 | // 发起流程 | 608 | // 发起流程 |
| 561 | return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, | 609 | return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, |
| 562 | createReqVO.getStartUserSelectAssignees()); | 610 | createReqVO.getStartUserSelectAssignees()); |
| @@ -566,16 +614,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -566,16 +614,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 566 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { | 614 | public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { |
| 567 | return FlowableUtils.executeAuthenticatedUserId(userId, () -> { | 615 | return FlowableUtils.executeAuthenticatedUserId(userId, () -> { |
| 568 | // 获得流程定义 | 616 | // 获得流程定义 |
| 569 | - ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); | 617 | + ProcessDefinition definition = processDefinitionService |
| 618 | + .getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); | ||
| 570 | // 发起流程 | 619 | // 发起流程 |
| 571 | - return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), | 620 | + return createProcessInstance0(userId, definition, createReqDTO.getVariables(), |
| 621 | + createReqDTO.getBusinessKey(), | ||
| 572 | createReqDTO.getStartUserSelectAssignees()); | 622 | createReqDTO.getStartUserSelectAssignees()); |
| 573 | }); | 623 | }); |
| 574 | } | 624 | } |
| 575 | 625 | ||
| 576 | private String createProcessInstance0(Long userId, ProcessDefinition definition, | 626 | private String createProcessInstance0(Long userId, ProcessDefinition definition, |
| 577 | - Map<String, Object> variables, String businessKey, | ||
| 578 | - Map<String, List<Long>> startUserSelectAssignees) { | 627 | + Map<String, Object> variables, String businessKey, |
| 628 | + Map<String, List<Long>> startUserSelectAssignees) { | ||
| 579 | // 1.1 校验流程定义 | 629 | // 1.1 校验流程定义 |
| 580 | if (definition == null) { | 630 | if (definition == null) { |
| 581 | throw exception(PROCESS_DEFINITION_NOT_EXISTS); | 631 | throw exception(PROCESS_DEFINITION_NOT_EXISTS); |
| @@ -583,7 +633,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -583,7 +633,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 583 | if (definition.isSuspended()) { | 633 | if (definition.isSuspended()) { |
| 584 | throw exception(PROCESS_DEFINITION_IS_SUSPENDED); | 634 | throw exception(PROCESS_DEFINITION_IS_SUSPENDED); |
| 585 | } | 635 | } |
| 586 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(definition.getId()); | 636 | + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService |
| 637 | + .getProcessDefinitionInfo(definition.getId()); | ||
| 587 | if (processDefinitionInfo == null) { | 638 | if (processDefinitionInfo == null) { |
| 588 | throw exception(PROCESS_DEFINITION_NOT_EXISTS); | 639 | throw exception(PROCESS_DEFINITION_NOT_EXISTS); |
| 589 | } | 640 | } |
| @@ -602,9 +653,12 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -602,9 +653,12 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 602 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID | 653 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID |
| 603 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 | 654 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 |
| 604 | BpmProcessInstanceStatusEnum.RUNNING.getStatus()); | 655 | BpmProcessInstanceStatusEnum.RUNNING.getStatus()); |
| 605 | - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 true,不影响没配置 skipExpression 的节点 | 656 | + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 |
| 657 | + // true,不影响没配置 | ||
| 658 | + // skipExpression 的节点 | ||
| 606 | if (CollUtil.isNotEmpty(startUserSelectAssignees)) { | 659 | if (CollUtil.isNotEmpty(startUserSelectAssignees)) { |
| 607 | - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees); | 660 | + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, |
| 661 | + startUserSelectAssignees); | ||
| 608 | } | 662 | } |
| 609 | 663 | ||
| 610 | // 3. 创建流程 | 664 | // 3. 创建流程 |
| @@ -634,7 +688,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -634,7 +688,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 634 | return instance.getId(); | 688 | return instance.getId(); |
| 635 | } | 689 | } |
| 636 | 690 | ||
| 637 | - private void validateStartUserSelectAssignees(ProcessDefinition definition, Map<String, List<Long>> startUserSelectAssignees) { | 691 | + private void validateStartUserSelectAssignees(ProcessDefinition definition, |
| 692 | + Map<String, List<Long>> startUserSelectAssignees) { | ||
| 638 | // 1. 获得发起人自选审批人的 UserTask/ServiceTask 列表 | 693 | // 1. 获得发起人自选审批人的 UserTask/ServiceTask 列表 |
| 639 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId()); | 694 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(definition.getId()); |
| 640 | List<Task> tasks = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectTaskList(bpmnModel); | 695 | List<Task> tasks = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectTaskList(bpmnModel); |
| @@ -669,7 +724,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -669,7 +724,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 669 | throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); | 724 | throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); |
| 670 | } | 725 | } |
| 671 | // 1.3 校验允许撤销审批中的申请 | 726 | // 1.3 校验允许撤销审批中的申请 |
| 672 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(instance.getProcessDefinitionId()); | 727 | + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService |
| 728 | + .getProcessDefinitionInfo(instance.getProcessDefinitionId()); | ||
| 673 | Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); | 729 | Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); |
| 674 | if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 | 730 | if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 |
| 675 | && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { | 731 | && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { |
| @@ -707,9 +763,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -707,9 +763,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 707 | 763 | ||
| 708 | @Override | 764 | @Override |
| 709 | public void updateProcessInstanceReject(ProcessInstance processInstance, String reason) { | 765 | public void updateProcessInstanceReject(ProcessInstance processInstance, String reason) { |
| 710 | - runtimeService.setVariable(processInstance.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, | 766 | + runtimeService.setVariable(processInstance.getProcessInstanceId(), |
| 767 | + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, | ||
| 711 | BpmProcessInstanceStatusEnum.REJECT.getStatus()); | 768 | BpmProcessInstanceStatusEnum.REJECT.getStatus()); |
| 712 | - runtimeService.setVariable(processInstance.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, | 769 | + runtimeService.setVariable(processInstance.getProcessInstanceId(), |
| 770 | + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, | ||
| 713 | BpmReasonEnum.REJECT_TASK.format(reason)); | 771 | BpmReasonEnum.REJECT_TASK.format(reason)); |
| 714 | } | 772 | } |
| 715 | 773 | ||
| @@ -720,18 +778,22 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -720,18 +778,22 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 720 | // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 | 778 | // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 |
| 721 | FlowableUtils.execute(instance.getTenantId(), () -> { | 779 | FlowableUtils.execute(instance.getTenantId(), () -> { |
| 722 | // 1.1 获取当前状态 | 780 | // 1.1 获取当前状态 |
| 723 | - Integer status = (Integer) instance.getProcessVariables().get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); | ||
| 724 | - String reason = (String) instance.getProcessVariables().get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); | 781 | + Integer status = (Integer) instance.getProcessVariables() |
| 782 | + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); | ||
| 783 | + String reason = (String) instance.getProcessVariables() | ||
| 784 | + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); | ||
| 725 | // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 | 785 | // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 |
| 726 | // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 | 786 | // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 |
| 727 | if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { | 787 | if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { |
| 728 | status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); | 788 | status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); |
| 729 | - runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, status); | 789 | + runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, |
| 790 | + status); | ||
| 730 | } | 791 | } |
| 731 | 792 | ||
| 732 | // 2. 发送对应的消息通知 | 793 | // 2. 发送对应的消息通知 |
| 733 | if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { | 794 | if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { |
| 734 | - messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); | 795 | + messageService.sendMessageWhenProcessInstanceApprove( |
| 796 | + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); | ||
| 735 | } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { | 797 | } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { |
| 736 | messageService.sendMessageWhenProcessInstanceReject( | 798 | messageService.sendMessageWhenProcessInstanceReject( |
| 737 | BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); | 799 | BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); |
| @@ -743,4 +805,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -743,4 +805,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 743 | }); | 805 | }); |
| 744 | } | 806 | } |
| 745 | 807 | ||
| 808 | + @Override | ||
| 809 | + public void updateProcessInstanceVariables(String id, Map<String, Object> variables) { | ||
| 810 | + runtimeService.setVariables(id, variables); | ||
| 811 | + } | ||
| 812 | + | ||
| 746 | } | 813 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmHttpRequestTrigger.java
| 1 | package cn.iocoder.yudao.module.bpm.service.task.trigger; | 1 | package cn.iocoder.yudao.module.bpm.service.task.trigger; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 3 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 4 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting; | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting; |
| 5 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; | 9 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; |
| 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; | 10 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; |
| 7 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | 11 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 12 | +import com.fasterxml.jackson.core.type.TypeReference; | ||
| 8 | import jakarta.annotation.Resource; | 13 | import jakarta.annotation.Resource; |
| 9 | import lombok.extern.slf4j.Slf4j; | 14 | import lombok.extern.slf4j.Slf4j; |
| 10 | import org.flowable.engine.runtime.ProcessInstance; | 15 | import org.flowable.engine.runtime.ProcessInstance; |
| @@ -17,6 +22,8 @@ import org.springframework.util.MultiValueMap; | @@ -17,6 +22,8 @@ import org.springframework.util.MultiValueMap; | ||
| 17 | import org.springframework.web.client.RestClientException; | 22 | import org.springframework.web.client.RestClientException; |
| 18 | import org.springframework.web.client.RestTemplate; | 23 | import org.springframework.web.client.RestTemplate; |
| 19 | 24 | ||
| 25 | +import java.util.HashMap; | ||
| 26 | +import java.util.List; | ||
| 20 | import java.util.Map; | 27 | import java.util.Map; |
| 21 | 28 | ||
| 22 | import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; | 29 | import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; |
| @@ -63,13 +70,55 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | @@ -63,13 +70,55 @@ public class BpmHttpRequestTrigger implements BpmTrigger { | ||
| 63 | // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢? | 70 | // TODO @芋艿:要不要抽象一个 Http 请求的工具类,方便复用呢? |
| 64 | // 3. 发起请求 | 71 | // 3. 发起请求 |
| 65 | HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); | 72 | HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); |
| 73 | + ResponseEntity<String> responseEntity; | ||
| 66 | try { | 74 | try { |
| 67 | - ResponseEntity<String> responseEntity = restTemplate.exchange(setting.getUrl(), HttpMethod.POST, | 75 | + responseEntity = restTemplate.exchange(setting.getUrl(), HttpMethod.POST, |
| 68 | requestEntity, String.class); | 76 | requestEntity, String.class); |
| 69 | log.info("[execute][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); | 77 | log.info("[execute][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); |
| 70 | } catch (RestClientException e) { | 78 | } catch (RestClientException e) { |
| 71 | log.error("[execute][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); | 79 | log.error("[execute][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); |
| 80 | + return; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + // 4.1 判断是否需要解析返回值 | ||
| 84 | + if (StrUtil.isEmpty(responseEntity.getBody()) | ||
| 85 | + || !responseEntity.getStatusCode().is2xxSuccessful() | ||
| 86 | + || CollUtil.isEmpty(setting.getResponse())) { | ||
| 87 | + return; | ||
| 88 | + } | ||
| 89 | + // 4.2 解析返回值, 返回值必须符合 CommonResult 规范。 | ||
| 90 | + CommonResult<Map<String, Object>> respResult = JsonUtils.parseObjectQuietly( | ||
| 91 | + responseEntity.getBody(), new TypeReference<>() {}); | ||
| 92 | + if (respResult == null || !respResult.isSuccess()){ | ||
| 93 | + return; | ||
| 94 | + } | ||
| 95 | + // 4.3 获取需要更新的流程变量 | ||
| 96 | + Map<String, Object> updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), setting.getResponse()); | ||
| 97 | + // 4.4 更新流程变量 | ||
| 98 | + if (CollUtil.isNotEmpty(updateVariables)) { | ||
| 99 | + processInstanceService.updateProcessInstanceVariables(processInstanceId, updateVariables); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * 从请求返回值获取需要更新的流程变量 | ||
| 105 | + * | ||
| 106 | + * @param result 请求返回结果 | ||
| 107 | + * @param responseSettings 返回设置 | ||
| 108 | + * @return 需要更新的流程变量 | ||
| 109 | + */ | ||
| 110 | + private Map<String, Object> getNeedUpdatedVariablesFromResponse(Map<String,Object> result, | ||
| 111 | + List<KeyValue<String, String>> responseSettings) { | ||
| 112 | + Map<String, Object> updateVariables = new HashMap<>(); | ||
| 113 | + if (CollUtil.isEmpty(result)) { | ||
| 114 | + return updateVariables; | ||
| 72 | } | 115 | } |
| 116 | + responseSettings.forEach(responseSetting -> { | ||
| 117 | + if (StrUtil.isNotEmpty(responseSetting.getKey()) && result.containsKey(responseSetting.getValue())) { | ||
| 118 | + updateVariables.put(responseSetting.getKey(), result.get(responseSetting.getValue())); | ||
| 119 | + } | ||
| 120 | + }); | ||
| 121 | + return updateVariables; | ||
| 73 | } | 122 | } |
| 74 | 123 | ||
| 75 | } | 124 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.NormalFormTriggerSetting; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | ||
| 8 | +import jakarta.annotation.Resource; | ||
| 9 | +import lombok.extern.slf4j.Slf4j; | ||
| 10 | +import org.springframework.stereotype.Component; | ||
| 11 | + | ||
| 12 | +// TODO @jason:改成 BpmFormUpdateTrigger | ||
| 13 | +/** | ||
| 14 | + * BPM 更新流程表单触发器 | ||
| 15 | + * | ||
| 16 | + * @author jason | ||
| 17 | + */ | ||
| 18 | +@Component | ||
| 19 | +@Slf4j | ||
| 20 | +public class BpmUpdateNormalFormTrigger implements BpmTrigger { | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private BpmProcessInstanceService processInstanceService; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public BpmTriggerTypeEnum getType() { | ||
| 27 | + return BpmTriggerTypeEnum.UPDATE_NORMAL_FORM; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public void execute(String processInstanceId, String param) { | ||
| 32 | + // 1. 解析更新流程表单配置 | ||
| 33 | + NormalFormTriggerSetting setting = JsonUtils.parseObject(param, NormalFormTriggerSetting.class); | ||
| 34 | + if (setting == null) { | ||
| 35 | + log.error("[execute][流程({}) 更新流程表单触发器配置为空]", processInstanceId); | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + // 2.更新流程变量 | ||
| 39 | + if (CollUtil.isNotEmpty(setting.getUpdateFormFields())) { | ||
| 40 | + processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields()); | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | +} |