Commit 7967a2a195f93e153e320ac08176dfa2e1298254

Authored by YunaiV
1 parent a1defeb4

BPM:流程实例的 `status` 状态实现,使用 Flowable 的 `variables` 存储,移除 `bpm_process_instance_ext` 表

Showing 17 changed files with 150 additions and 242 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
@@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; @@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
6 /** 6 /**
7 - * 流程实例的状态 7 + * 流程实例 ProcessInstance 的状态
8 * 8 *
9 * @author 芋道源码 9 * @author 芋道源码
10 */ 10 */
@@ -13,7 +13,9 @@ import lombok.Getter; @@ -13,7 +13,9 @@ import lombok.Getter;
13 public enum BpmProcessInstanceStatusEnum { 13 public enum BpmProcessInstanceStatusEnum {
14 14
15 RUNNING(1, "进行中"), 15 RUNNING(1, "进行中"),
16 - FINISH(2, "已完成"); 16 + APPROVE(2, "通过"),
  17 + REJECT(3, "不通过"),
  18 + CANCEL(4, "已取消");
17 19
18 /** 20 /**
19 * 状态 21 * 状态
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusOldEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.enums.task;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 流程实例的状态
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Deprecated
  12 +@Getter
  13 +@AllArgsConstructor
  14 +public enum BpmProcessInstanceStatusOldEnum {
  15 +
  16 + RUNNING(1, "进行中"),
  17 + FINISH(2, "已完成");
  18 +
  19 + /**
  20 + * 状态
  21 + */
  22 + private final Integer status;
  23 + /**
  24 + * 描述
  25 + */
  26 + private final String desc;
  27 +
  28 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/candidate/vo/BpmTaskCandidateRuleVO.java deleted
1 -package cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import jakarta.validation.constraints.NotNull;  
5 -import lombok.Data;  
6 -  
7 -import java.util.Set;  
8 -  
9 -/**  
10 - * 流程任务分配规则 Base VO,提供给添加、修改、详细的子 VO 使用  
11 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成  
12 - */  
13 -@Data  
14 -public class BpmTaskCandidateRuleVO {  
15 -  
16 - @Schema(description = "规则类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "bpm_task_assign_rule_type")  
17 - @NotNull(message = "规则类型不能为空")  
18 - private Integer type;  
19 -  
20 - @Schema(description = "规则值数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")  
21 - @NotNull(message = "规则值数组不能为空")  
22 - private Set<Long> options;  
23 -  
24 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
1 package cn.iocoder.yudao.module.bpm.controller.admin.task; 1 package cn.iocoder.yudao.module.bpm.controller.admin.task;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; 6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  7 +import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
  8 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
6 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 9 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  10 +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
7 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
8 import io.swagger.v3.oas.annotations.Parameter; 12 import io.swagger.v3.oas.annotations.Parameter;
9 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
10 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
11 import jakarta.validation.Valid; 15 import jakarta.validation.Valid;
  16 +import org.flowable.engine.history.HistoricProcessInstance;
  17 +import org.flowable.engine.repository.ProcessDefinition;
  18 +import org.flowable.task.api.Task;
12 import org.springframework.security.access.prepost.PreAuthorize; 19 import org.springframework.security.access.prepost.PreAuthorize;
13 import org.springframework.validation.annotation.Validated; 20 import org.springframework.validation.annotation.Validated;
14 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
15 22
  23 +import java.util.List;
  24 +import java.util.Map;
  25 +
16 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  27 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  28 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
17 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 29 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
18 30
19 @Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请” 31 @Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请”
@@ -24,13 +36,27 @@ public class BpmProcessInstanceController { @@ -24,13 +36,27 @@ public class BpmProcessInstanceController {
24 36
25 @Resource 37 @Resource
26 private BpmProcessInstanceService processInstanceService; 38 private BpmProcessInstanceService processInstanceService;
  39 + @Resource
  40 + private BpmTaskService taskService;
  41 + @Resource
  42 + private BpmProcessDefinitionService processDefinitionService;
27 43
28 @GetMapping("/my-page") 44 @GetMapping("/my-page")
29 @Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用") 45 @Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用")
30 @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')") 46 @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
31 public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage( 47 public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage(
32 @Valid BpmProcessInstanceMyPageReqVO pageReqVO) { 48 @Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
33 - return success(processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO)); 49 + PageResult<HistoricProcessInstance> pageResult = processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO);
  50 + if (CollUtil.isEmpty(pageResult.getList())) {
  51 + return success(PageResult.empty(pageResult.getTotal()));
  52 + }
  53 +
  54 + // 拼接返回
  55 + Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(
  56 + convertList(pageResult.getList(), HistoricProcessInstance::getId));
  57 + Map<String, ProcessDefinition> processDefinitionMap = processDefinitionService.getProcessDefinitionMap(
  58 + convertSet(pageResult.getList(), HistoricProcessInstance::getProcessDefinitionId));
  59 + return success(BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, processDefinitionMap, taskMap));
34 } 60 }
35 61
36 @PostMapping("/create") 62 @PostMapping("/create")
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java
@@ -23,13 +23,10 @@ public class BpmProcessInstancePageItemRespVO { @@ -23,13 +23,10 @@ public class BpmProcessInstancePageItemRespVO {
23 private String category; 23 private String category;
24 24
25 @Schema(description = "流程实例的状态-参见 bpm_process_instance_status", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 25 @Schema(description = "流程实例的状态-参见 bpm_process_instance_status", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
26 - private Integer status;  
27 -  
28 - @Schema(description = "流程实例的结果-参见 bpm_process_instance_result", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")  
29 - private Integer result; 26 + private Integer status; // 参见 BpmProcessInstanceStatusEnum 枚举
30 27
31 @Schema(description = "提交时间", requiredMode = Schema.RequiredMode.REQUIRED) 28 @Schema(description = "提交时间", requiredMode = Schema.RequiredMode.REQUIRED)
32 - private LocalDateTime createTime; 29 + private LocalDateTime startTime;
33 30
34 @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED) 31 @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
35 private LocalDateTime endTime; 32 private LocalDateTime endTime;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java
@@ -20,8 +20,8 @@ public class BpmProcessInstanceRespVO { @@ -20,8 +20,8 @@ public class BpmProcessInstanceRespVO {
20 @Schema(description = "流程分类-参见 bpm_model_category 数据字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 20 @Schema(description = "流程分类-参见 bpm_model_category 数据字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
21 private String category; 21 private String category;
22 22
23 - @Schema(description = "流程实例的状态-参见 bpm_process_instance_status", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
24 - private Integer status; 23 + @Schema(description = "流程实例的状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  24 + private Integer status; // 参见 BpmProcessInstanceStatusEnum 枚举
25 25
26 @Schema(description = "流程实例的结果-参见 bpm_process_instance_result", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") 26 @Schema(description = "流程实例的结果-参见 bpm_process_instance_result", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
27 private Integer result; 27 private Integer result;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
1 package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; 1 package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
2 2
3 -import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 4 import lombok.Data;
6 5
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
1 package cn.iocoder.yudao.module.bpm.convert.task; 1 package cn.iocoder.yudao.module.bpm.convert.task;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
4 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 5 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
5 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 6 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO; 8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; 9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
8 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; 10 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
9 -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;  
10 import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; 11 import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent;
  12 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
11 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; 13 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
12 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; 14 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
13 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 15 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -34,25 +36,26 @@ public interface BpmProcessInstanceConvert { @@ -34,25 +36,26 @@ public interface BpmProcessInstanceConvert {
34 36
35 BpmProcessInstanceConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceConvert.class); 37 BpmProcessInstanceConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceConvert.class);
36 38
37 - default PageResult<BpmProcessInstancePageItemRespVO> convertPage(PageResult<BpmProcessInstanceExtDO> page, 39 + default PageResult<BpmProcessInstancePageItemRespVO> convertPage(PageResult<HistoricProcessInstance> pageResult,
  40 + Map<String, ProcessDefinition> processDefinitionMap,
38 Map<String, List<Task>> taskMap) { 41 Map<String, List<Task>> taskMap) {
39 - List<BpmProcessInstancePageItemRespVO> list = convertList(page.getList());  
40 - list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()))));  
41 - return new PageResult<>(list, page.getTotal()); 42 + PageResult<BpmProcessInstancePageItemRespVO> vpPageResult = BeanUtils.toBean(pageResult, BpmProcessInstancePageItemRespVO.class);
  43 + for (int i = 0; i < pageResult.getList().size(); i++) {
  44 + BpmProcessInstancePageItemRespVO respVO = vpPageResult.getList().get(i);
  45 + respVO.setStatus((Integer) pageResult.getList().get(i).getProcessVariables().get(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS));
  46 + MapUtils.findAndThen(processDefinitionMap, respVO.getProcessDefinitionId(),
  47 + processDefinition -> respVO.setCategory(processDefinition.getCategory()));
  48 + respVO.setTasks(BeanUtils.toBean(taskMap.get(respVO.getId()), BpmProcessInstancePageItemRespVO.Task.class));
  49 + }
  50 + return vpPageResult;
42 } 51 }
43 52
44 - List<BpmProcessInstancePageItemRespVO> convertList(List<BpmProcessInstanceExtDO> list);  
45 -  
46 - @Mapping(source = "processInstanceId", target = "id")  
47 - BpmProcessInstancePageItemRespVO convert(BpmProcessInstanceExtDO bean);  
48 -  
49 - List<BpmProcessInstancePageItemRespVO.Task> convertList2(List<Task> tasks);  
50 -  
51 - default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt, 53 + default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance,
52 ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt, 54 ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt,
53 String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) { 55 String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) {
54 BpmProcessInstanceRespVO respVO = convert2(processInstance); 56 BpmProcessInstanceRespVO respVO = convert2(processInstance);
55 - copyTo(processInstanceExt, respVO); 57 + respVO.setStatus((Integer) processInstance.getProcessVariables().get(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS));
  58 + respVO.setFormVariables(processInstance.getProcessVariables()); // TODO 芋艿:真的这么搞么???formVariable 要不要换个 key 之类的
56 // definition 59 // definition
57 respVO.setProcessDefinition(convert2(processDefinition)); 60 respVO.setProcessDefinition(convert2(processDefinition));
58 copyTo(processDefinitionExt, respVO.getProcessDefinition()); 61 copyTo(processDefinitionExt, respVO.getProcessDefinition());
@@ -69,9 +72,6 @@ public interface BpmProcessInstanceConvert { @@ -69,9 +72,6 @@ public interface BpmProcessInstanceConvert {
69 72
70 BpmProcessInstanceRespVO convert2(HistoricProcessInstance bean); 73 BpmProcessInstanceRespVO convert2(HistoricProcessInstance bean);
71 74
72 - @Mapping(source = "from.id", target = "to.id", ignore = true)  
73 - void copyTo(BpmProcessInstanceExtDO from, @MappingTarget BpmProcessInstanceRespVO to);  
74 -  
75 BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean); 75 BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean);
76 76
77 @Mapping(source = "from.id", target = "to.id", ignore = true) 77 @Mapping(source = "from.id", target = "to.id", ignore = true)
@@ -88,6 +88,7 @@ public interface BpmProcessInstanceConvert { @@ -88,6 +88,7 @@ public interface BpmProcessInstanceConvert {
88 return event; 88 return event;
89 } 89 }
90 90
  91 + // TODO @芋艿:需要改下 key!
91 default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) { 92 default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) {
92 BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source); 93 BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
93 event.setId(instance.getId()); 94 event.setId(instance.getId());
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java deleted
1 -package cn.iocoder.yudao.module.bpm.dal.dataobject.task;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;  
4 -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;  
5 -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;  
6 -import com.baomidou.mybatisplus.annotation.TableField;  
7 -import com.baomidou.mybatisplus.annotation.TableId;  
8 -import com.baomidou.mybatisplus.annotation.TableName;  
9 -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;  
10 -import lombok.Data;  
11 -import lombok.EqualsAndHashCode;  
12 -import lombok.ToString;  
13 -  
14 -import java.time.LocalDateTime;  
15 -import java.util.List;  
16 -import java.util.Map;  
17 -  
18 -/**  
19 - * Bpm 流程实例的拓展表  
20 - * 主要解决 Activiti ProcessInstance 和 HistoricProcessInstance 不支持拓展字段,所以新建拓展表  
21 - *  
22 - * @author 芋道源码  
23 - */  
24 -@TableName(value = "bpm_process_instance_ext", autoResultMap = true)  
25 -@Data  
26 -@EqualsAndHashCode(callSuper = true)  
27 -@ToString(callSuper = true)  
28 -public class BpmProcessInstanceExtDO extends BaseDO {  
29 -  
30 - /**  
31 - * 编号,自增  
32 - */  
33 - @TableId  
34 - private Long id;  
35 - /**  
36 - * 发起流程的用户编号  
37 - *  
38 - * 冗余 HistoricProcessInstance 的 startUserId 属性  
39 - */  
40 - private Long startUserId;  
41 - /**  
42 - * 流程实例的名字  
43 - *  
44 - * 冗余 ProcessInstance 的 name 属性,用于筛选  
45 - */  
46 - private String name;  
47 - /**  
48 - * 流程实例的编号  
49 - *  
50 - * 关联 ProcessInstance 的 id 属性  
51 - */  
52 - private String processInstanceId;  
53 - /**  
54 - * 流程定义的编号  
55 - *  
56 - * 关联 ProcessDefinition 的 id 属性  
57 - */  
58 - private String processDefinitionId;  
59 - /**  
60 - * 流程分类  
61 - *  
62 - * 冗余 ProcessDefinition 的 category 属性  
63 - * 数据字典 bpm_model_category  
64 - */  
65 - private String category;  
66 - /**  
67 - * 流程实例的状态  
68 - *  
69 - * 枚举 {@link BpmProcessInstanceStatusEnum}  
70 - */  
71 - private Integer status;  
72 - /**  
73 - * 流程实例的结果  
74 - *  
75 - * 枚举 {@link BpmProcessInstanceResultEnum}  
76 - */  
77 - private Integer result;  
78 - /**  
79 - * 结束时间  
80 - *  
81 - * 冗余 HistoricProcessInstance 的 endTime 属性  
82 - */  
83 - private LocalDateTime endTime;  
84 -  
85 - /**  
86 - * 提交的表单值  
87 - */  
88 - @TableField(typeHandler = JacksonTypeHandler.class)  
89 - private Map<String, Object> formVariables;  
90 -  
91 - // TODO @hai:assignees 复数  
92 - /**  
93 - * 提前设定好的审批人  
94 - */  
95 - @TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO 芋艿:临时 exist = false,避免 db 报错;  
96 - private Map<String, List<Long>> assignee;  
97 -  
98 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java deleted
1 -package cn.iocoder.yudao.module.bpm.dal.mysql.task;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
5 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
6 -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;  
7 -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;  
8 -import org.apache.ibatis.annotations.Mapper;  
9 -  
10 -@Mapper  
11 -public interface BpmProcessInstanceExtMapper extends BaseMapperX<BpmProcessInstanceExtDO> {  
12 -  
13 - default PageResult<BpmProcessInstanceExtDO> selectPage(Long userId, BpmProcessInstanceMyPageReqVO reqVO) {  
14 - return selectPage(reqVO, new LambdaQueryWrapperX<BpmProcessInstanceExtDO>()  
15 - .eqIfPresent(BpmProcessInstanceExtDO::getStartUserId, userId)  
16 - .likeIfPresent(BpmProcessInstanceExtDO::getName, reqVO.getName())  
17 - .eqIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, reqVO.getProcessDefinitionId())  
18 - .eqIfPresent(BpmProcessInstanceExtDO::getCategory, reqVO.getCategory())  
19 - .eqIfPresent(BpmProcessInstanceExtDO::getStatus, reqVO.getStatus())  
20 - .eqIfPresent(BpmProcessInstanceExtDO::getResult, reqVO.getResult())  
21 - .betweenIfPresent(BpmProcessInstanceExtDO::getCreateTime, reqVO.getCreateTime())  
22 - .orderByDesc(BpmProcessInstanceExtDO::getId));  
23 - }  
24 -  
25 - default BpmProcessInstanceExtDO selectByProcessInstanceId(String processInstanceId) {  
26 - return selectOne(BpmProcessInstanceExtDO::getProcessInstanceId, processInstanceId);  
27 - }  
28 -  
29 - default void updateByProcessInstanceId(BpmProcessInstanceExtDO updateObj) {  
30 - update(updateObj, new LambdaQueryWrapperX<BpmProcessInstanceExtDO>()  
31 - .eq(BpmProcessInstanceExtDO::getProcessInstanceId, updateObj.getProcessInstanceId()));  
32 - }  
33 -  
34 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
  2 +
  3 +import org.flowable.engine.runtime.ProcessInstance;
  4 +
  5 +/**
  6 + * BPM 通用常量
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public class BpmConstants {
  11 +
  12 + /**
  13 + * 流程实例的变量 - 状态
  14 + *
  15 + * @see ProcessInstance#getProcessVariables()
  16 + */
  17 + public static final String PROCESS_INSTANCE_VARIABLE_STATUS = "PROCESS_STATUS";
  18 +
  19 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
2 2
3 /** 3 /**
4 - * 流程常量信息 4 + * BPMN XML 常量信息
  5 + *
  6 + * @author 芋道源码
5 */ 7 */
6 public interface BpmnModelConstants { 8 public interface BpmnModelConstants {
7 9
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
2 2
3 -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;  
4 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 3 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
5 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
  5 +import jakarta.annotation.Resource;
6 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; 6 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
7 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; 7 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
8 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener; 8 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
@@ -11,11 +11,10 @@ import org.flowable.engine.runtime.ProcessInstance; @@ -11,11 +11,10 @@ import org.flowable.engine.runtime.ProcessInstance;
11 import org.springframework.context.annotation.Lazy; 11 import org.springframework.context.annotation.Lazy;
12 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
13 13
14 -import jakarta.annotation.Resource;  
15 import java.util.Set; 14 import java.util.Set;
16 15
17 /** 16 /**
18 - * 监听 {@link ProcessInstance} 的开始与完成,创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录 17 + * 监听 {@link ProcessInstance} 的状态变更,更新其对应的 status 状态
19 * 18 *
20 * @author jason 19 * @author jason
21 */ 20 */
@@ -27,7 +26,6 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @@ -27,7 +26,6 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
27 private BpmProcessInstanceService processInstanceService; 26 private BpmProcessInstanceService processInstanceService;
28 27
29 public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder() 28 public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
30 - .add(FlowableEngineEventType.PROCESS_CREATED)  
31 .add(FlowableEngineEventType.PROCESS_CANCELLED) 29 .add(FlowableEngineEventType.PROCESS_CANCELLED)
32 .add(FlowableEngineEventType.PROCESS_COMPLETED) 30 .add(FlowableEngineEventType.PROCESS_COMPLETED)
33 .build(); 31 .build();
@@ -37,11 +35,6 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @@ -37,11 +35,6 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
37 } 35 }
38 36
39 @Override 37 @Override
40 - protected void processCreated(FlowableEngineEntityEvent event) {  
41 - processInstanceService.createProcessInstanceExt((ProcessInstance)event.getEntity());  
42 - }  
43 -  
44 - @Override  
45 protected void processCancelled(FlowableCancelledEvent event) { 38 protected void processCancelled(FlowableCancelledEvent event) {
46 processInstanceService.updateProcessInstanceExtCancel(event); 39 processInstanceService.updateProcessInstanceExtCancel(event);
47 } 40 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
1 package cn.iocoder.yudao.module.bpm.service.definition; 1 package cn.iocoder.yudao.module.bpm.service.definition;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; 4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
6 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; 5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
7 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; 6 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
8 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; 8 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
10 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; 9 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
  10 +import jakarta.validation.Valid;
11 import org.flowable.bpmn.model.BpmnModel; 11 import org.flowable.bpmn.model.BpmnModel;
12 import org.flowable.engine.repository.Deployment; 12 import org.flowable.engine.repository.Deployment;
13 import org.flowable.engine.repository.ProcessDefinition; 13 import org.flowable.engine.repository.ProcessDefinition;
14 14
15 -import jakarta.validation.Valid;  
16 import java.util.List; 15 import java.util.List;
17 import java.util.Map; 16 import java.util.Map;
18 import java.util.Set; 17 import java.util.Set;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  20 +
19 /** 21 /**
20 * Flowable流程定义接口 22 * Flowable流程定义接口
21 * 23 *
@@ -90,14 +92,16 @@ public interface BpmProcessDefinitionService { @@ -90,14 +92,16 @@ public interface BpmProcessDefinitionService {
90 ProcessDefinition getProcessDefinition(String id); 92 ProcessDefinition getProcessDefinition(String id);
91 93
92 /** 94 /**
93 - * 获得编号对应的 ProcessDefinition  
94 - *  
95 - * 相比 {@link #getProcessDefinition(String)} 方法,category 的取值是正确 95 + * 获得 ids 对应的 ProcessDefinition 数组
96 * 96 *
97 - * @param id 编号  
98 - * @return 流程定义 97 + * @param ids 编号的数组
  98 + * @return 流程定义的数组
99 */ 99 */
100 - ProcessDefinition getProcessDefinition2(String id); 100 + List<ProcessDefinition> getProcessDefinitionList(Set<String> ids);
  101 +
  102 + default Map<String, ProcessDefinition> getProcessDefinitionMap(Set<String> ids) {
  103 + return convertMap(getProcessDefinitionList(ids), ProcessDefinition::getId);
  104 + }
101 105
102 /** 106 /**
103 * 获得 deploymentId 对应的 ProcessDefinition 107 * 获得 deploymentId 对应的 ProcessDefinition
@@ -130,7 +134,7 @@ public interface BpmProcessDefinitionService { @@ -130,7 +134,7 @@ public interface BpmProcessDefinitionService {
130 * @return 流程部署 Map 134 * @return 流程部署 Map
131 */ 135 */
132 default Map<String, Deployment> getDeploymentMap(Set<String> ids) { 136 default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
133 - return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId); 137 + return convertMap(getDeployments(ids), Deployment::getId);
134 } 138 }
135 139
136 /** 140 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -66,8 +66,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -66,8 +66,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
66 } 66 }
67 67
68 @Override 68 @Override
69 - public ProcessDefinition getProcessDefinition2(String id) {  
70 - return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult(); 69 + public List<ProcessDefinition> getProcessDefinitionList(Set<String> ids) {
  70 + return repositoryService.createProcessDefinitionQuery().processDefinitionIds(ids).list();
71 } 71 }
72 72
73 @Override 73 @Override
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
@@ -4,11 +4,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,11 +4,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; 5 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; 6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  7 +import jakarta.validation.Valid;
7 import org.flowable.engine.delegate.event.FlowableCancelledEvent; 8 import org.flowable.engine.delegate.event.FlowableCancelledEvent;
8 import org.flowable.engine.history.HistoricProcessInstance; 9 import org.flowable.engine.history.HistoricProcessInstance;
9 import org.flowable.engine.runtime.ProcessInstance; 10 import org.flowable.engine.runtime.ProcessInstance;
10 11
11 -import jakarta.validation.Valid;  
12 import java.util.List; 12 import java.util.List;
13 import java.util.Map; 13 import java.util.Map;
14 import java.util.Set; 14 import java.util.Set;
@@ -58,14 +58,40 @@ public interface BpmProcessInstanceService { @@ -58,14 +58,40 @@ public interface BpmProcessInstanceService {
58 } 58 }
59 59
60 /** 60 /**
  61 + * 获得历史的流程实例
  62 + *
  63 + * @param id 流程实例的编号
  64 + * @return 历史的流程实例
  65 + */
  66 + HistoricProcessInstance getHistoricProcessInstance(String id);
  67 +
  68 + /**
  69 + * 获得历史的流程实例列表
  70 + *
  71 + * @param ids 流程实例的编号集合
  72 + * @return 历史的流程实例列表
  73 + */
  74 + List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);
  75 +
  76 + /**
  77 + * 获得历史的流程实例 Map
  78 + *
  79 + * @param ids 流程实例的编号集合
  80 + * @return 历史的流程实例列表 Map
  81 + */
  82 + default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
  83 + return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
  84 + }
  85 +
  86 + /**
61 * 获得流程实例的分页 87 * 获得流程实例的分页
62 * 88 *
63 * @param userId 用户编号 89 * @param userId 用户编号
64 * @param pageReqVO 分页请求 90 * @param pageReqVO 分页请求
65 * @return 流程实例的分页 91 * @return 流程实例的分页
66 */ 92 */
67 - PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,  
68 - @Valid BpmProcessInstanceMyPageReqVO pageReqVO); 93 + PageResult<HistoricProcessInstance> getMyProcessInstancePage(Long userId,
  94 + @Valid BpmProcessInstanceMyPageReqVO pageReqVO);
69 95
70 /** 96 /**
71 * 创建流程实例(提供给前端) 97 * 创建流程实例(提供给前端)
@@ -102,39 +128,6 @@ public interface BpmProcessInstanceService { @@ -102,39 +128,6 @@ public interface BpmProcessInstanceService {
102 void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO); 128 void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO);
103 129
104 /** 130 /**
105 - * 获得历史的流程实例  
106 - *  
107 - * @param id 流程实例的编号  
108 - * @return 历史的流程实例  
109 - */  
110 - HistoricProcessInstance getHistoricProcessInstance(String id);  
111 -  
112 - /**  
113 - * 获得历史的流程实例列表  
114 - *  
115 - * @param ids 流程实例的编号集合  
116 - * @return 历史的流程实例列表  
117 - */  
118 - List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);  
119 -  
120 - /**  
121 - * 获得历史的流程实例 Map  
122 - *  
123 - * @param ids 流程实例的编号集合  
124 - * @return 历史的流程实例列表 Map  
125 - */  
126 - default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {  
127 - return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);  
128 - }  
129 -  
130 - /**  
131 - * 创建 ProcessInstance 拓展记录  
132 - *  
133 - * @param instance 流程任务  
134 - */  
135 - void createProcessInstanceExt(ProcessInstance instance);  
136 -  
137 - /**  
138 * 更新 ProcessInstance 拓展记录为取消 131 * 更新 ProcessInstance 拓展记录为取消
139 * 132 *
140 * @param event 流程取消事件 133 * @param event 流程取消事件
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
1 -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * <p> * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * <p> * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * <p> * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables).setAssignee(assignee)); return instance.getId(); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } if (CollUtil.isNotEmpty(instance.getAssignee())) { return instance.getAssignee().get(taskDefinitionKey); } return Collections.emptyList(); } }  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private HistoryService historyService; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private BpmMessageService messageService; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<HistoricProcessInstance> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery().includeProcessVariables() .startedBy(String.valueOf(userId)) .orderByProcessInstanceStartTime().desc(); if (StrUtil.isNotEmpty(pageReqVO.getName())) { processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionId())) { processInstanceQuery.processDefinitionId("%" + pageReqVO.getProcessDefinitionId() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getCategory())) { processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory()); } if (pageReqVO.getStatus() != null) { processInstanceQuery.variableValueEquals(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, pageReqVO.getStatus()); } if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) { processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0])); processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1])); } // 查询数量 long processInstanceCount = processInstanceQuery.count(); if (processInstanceCount == 0) { return PageResult.empty(processInstanceCount); } // 查询列表 List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), pageReqVO.getPageSize()); return new PageResult<>(processInstanceList, processInstanceCount); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 更新流程实例 status runtimeService.setVariable(event.getProcessInstanceId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.CANCEL.getStatus()); // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.CANCEL.getStatus())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 更新拓展表 runtimeService.setVariable(instance.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.APPROVE.getStatus()); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.APPROVE.getStatus())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 更新流程实例 status runtimeService.setVariable(id, BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.REJECT.getStatus()); // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.REJECT.getStatus())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 BpmProcessInstanceStatusEnum.RUNNING.getStatus()); ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); return instance.getId(); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 // TODO @芋艿:指定审批人,这里的存储方案有问题,后续优化下 // BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); // if (instance == null) { // throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); // } // if (CollUtil.isNotEmpty(instance.getAssignee())) { // return instance.getAssignee().get(taskDefinitionKey); // } return Collections.emptyList(); } }
3 \ No newline at end of file 3 \ No newline at end of file