Commit 8a3488f3d1fcf55558fa9ce7ef14d777c917fe17

Authored by 芋道源码
Committed by Gitee
2 parents 2a900380 9734eacf

!62 工作流的流程任务相关

Merge pull request !62 from 芋道源码/feature/activiti
Showing 81 changed files with 3165 additions and 2080 deletions
sql/ruoyi-vue-pro.sql
No preview for this file type
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.http 0 → 100644
  1 +### 请求 /bpm/process-definition/list 接口 => 成功
  2 +GET {{baseUrl}}/bpm/process-definition/list?suspensionState=1
  3 +tenant-id: 1
  4 +Authorization: Bearer {{token}}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; 1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionListReqVO;
3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO;
4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionRespVO;
5 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
6 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 8 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -17,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController; @@ -17,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController;
17 19
18 import javax.annotation.Resource; 20 import javax.annotation.Resource;
19 21
  22 +import java.util.List;
  23 +
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 25
22 @Api(tags = "流程定义") 26 @Api(tags = "流程定义")
@@ -36,14 +40,11 @@ public class BpmProcessDefinitionController { @@ -36,14 +40,11 @@ public class BpmProcessDefinitionController {
36 return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO)); 40 return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO));
37 } 41 }
38 42
39 - // TODO 芋艿:需要重写该方法  
40 - @GetMapping(value = "/getStartForm")  
41 - public CommonResult<String> getStartForm(@RequestParam("processKey") String processKey){  
42 -// final ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().  
43 -// processDefinitionKey(processKey).latestVersion().singleResult();  
44 -// processRuntime.processDefinition(processDefinition.getId()).getFormKey();  
45 - // TODO 这样查似乎有问题??, 暂时写死  
46 - return success("/flow/leave/apply"); 43 + @GetMapping ("/list")
  44 + @ApiOperation(value = "获得流程定义列表")
  45 + public CommonResult<List<BpmProcessDefinitionRespVO>> getProcessDefinitionList(
  46 + BpmProcessDefinitionListReqVO listReqVO) {
  47 + return success(bpmDefinitionService.getProcessDefinitionList(listReqVO));
47 } 48 }
48 49
49 @GetMapping ("/get-bpmn-xml") 50 @GetMapping ("/get-bpmn-xml")
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TodoTaskPageReqVO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/BpmProcessDefinitionListReqVO.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import io.swagger.annotations.ApiModel; 4 import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
5 import lombok.Data; 6 import lombok.Data;
6 import lombok.EqualsAndHashCode; 7 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 8 import lombok.ToString;
8 9
9 -@ApiModel("待办任务申请分页 Request VO")  
10 @Data 10 @Data
11 -@EqualsAndHashCode(callSuper = true)  
12 @ToString(callSuper = true) 11 @ToString(callSuper = true)
13 -public class TodoTaskPageReqVO extends PageParam { 12 +@EqualsAndHashCode(callSuper = true)
  13 +@ApiModel("流程定义列表 Request VO")
  14 +public class BpmProcessDefinitionListReqVO extends PageParam {
  15 +
  16 + @ApiModelProperty(value = "中断状态", example = "1", notes = "参见 SuspensionState 枚举")
  17 + private Integer suspensionState;
14 18
15 - private String assignee;  
16 } 19 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/BpmProcessDefinitionPageItemRespVO.java
@@ -20,5 +20,4 @@ public class BpmProcessDefinitionPageItemRespVO extends BpmProcessDefinitionResp @@ -20,5 +20,4 @@ public class BpmProcessDefinitionPageItemRespVO extends BpmProcessDefinitionResp
20 @ApiModelProperty(value = "部署时间", required = true) 20 @ApiModelProperty(value = "部署时间", required = true)
21 private Date deploymentTime; 21 private Date deploymentTime;
22 22
23 -  
24 } 23 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.http
1 -### 请求 /login 接口 => 成功 1 +### 请求 /bpm/process-instance/create 接口 => 成功
2 POST {{baseUrl}}/bpm/process-instance/create 2 POST {{baseUrl}}/bpm/process-instance/create
3 Content-Type: application/json 3 Content-Type: application/json
4 tenant-id: 1 4 tenant-id: 1
5 Authorization: Bearer {{token}} 5 Authorization: Bearer {{token}}
6 6
7 { 7 {
8 - "processDefinitionId": "leave:7:20ada39c-6c95-11ec-88b1-cacd34981f8e", 8 + "processDefinitionId": "gateway_test:2:00e52d8e-701b-11ec-aca9-a2380e71991a",
9 "variables": { 9 "variables": {
10 "a": 1, 10 "a": 1,
11 "b": "2" 11 "b": "2"
12 } 12 }
13 } 13 }
  14 +
  15 +### 请求 /bpm/process-instance/cancel 接口 => 成功
  16 +DELETE {{baseUrl}}/bpm/process-instance/cancel
  17 +Content-Type: application/json
  18 +tenant-id: 1
  19 +Authorization: Bearer {{token}}
  20 +
  21 +{
  22 + "id": "b9220387-7088-11ec-bcae-a2380e71991a",
  23 + "reason": "我就取消"
  24 +}
  25 +
  26 +### 请求 /bpm/process-instance/my-page 接口 => 成功
  27 +GET {{baseUrl}}/bpm/process-instance/my-page
  28 +tenant-id: 1
  29 +Authorization: Bearer {{token}}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.task; 1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.task;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCancelReqVO;
3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceMyPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstancePageItemRespVO;
4 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 8 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
7 import io.swagger.annotations.ApiOperation; 11 import io.swagger.annotations.ApiOperation;
8 import org.springframework.validation.annotation.Validated; 12 import org.springframework.validation.annotation.Validated;
9 -import org.springframework.web.bind.annotation.PostMapping;  
10 -import org.springframework.web.bind.annotation.RequestBody;  
11 -import org.springframework.web.bind.annotation.RequestMapping;  
12 -import org.springframework.web.bind.annotation.RestController; 13 +import org.springframework.web.bind.annotation.*;
13 14
14 import javax.annotation.Resource; 15 import javax.annotation.Resource;
15 import javax.validation.Valid; 16 import javax.validation.Valid;
@@ -26,10 +27,26 @@ public class BpmProcessInstanceController { @@ -26,10 +27,26 @@ public class BpmProcessInstanceController {
26 @Resource 27 @Resource
27 private BpmProcessInstanceService processInstanceService; 28 private BpmProcessInstanceService processInstanceService;
28 29
  30 + // TODO 芋艿:权限
  31 +
29 @PostMapping("/create") 32 @PostMapping("/create")
30 @ApiOperation("新建流程实例") 33 @ApiOperation("新建流程实例")
31 public CommonResult<String> createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) { 34 public CommonResult<String> createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) {
32 return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO)); 35 return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO));
33 } 36 }
34 37
  38 + @DeleteMapping("/cancel")
  39 + @ApiOperation(value = "取消流程实例", notes = "撤回发起的流程")
  40 + public CommonResult<Boolean> cancelProcessInstance(@Valid @RequestBody BpmProcessInstanceCancelReqVO cancelReqVO) {
  41 + processInstanceService.cancelProcessInstance(getLoginUserId(), cancelReqVO);
  42 + return success(true);
  43 + }
  44 +
  45 + @GetMapping("/my-page")
  46 + @ApiOperation(value = "获得我的实例分页列表", notes = "在【我的流程】菜单中,进行调用")
  47 + public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage(
  48 + @Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
  49 + return success(processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO));
  50 + }
  51 +
35 } 52 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.http 0 → 100644
  1 +### 请求 /bpm/task/todo-page 接口 => 成功
  2 +GET {{baseUrl}}/bpm/task/todo-page
  3 +tenant-id: 1
  4 +Authorization: Bearer {{token}}
  5 +
  6 +### 请求 /bpm/task/done-page 接口 => 成功
  7 +GET {{baseUrl}}/bpm/task/done-page?pageSize=100
  8 +tenant-id: 1
  9 +Authorization: Bearer {{token}}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/TaskController.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.*; 3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*;
4 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; 4 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 7 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
8 import io.swagger.annotations.Api; 8 import io.swagger.annotations.Api;
9 import io.swagger.annotations.ApiOperation; 9 import io.swagger.annotations.ApiOperation;
  10 +import org.springframework.validation.annotation.Validated;
10 import org.springframework.web.bind.annotation.*; 11 import org.springframework.web.bind.annotation.*;
11 12
12 import javax.annotation.Resource; 13 import javax.annotation.Resource;
@@ -16,48 +17,53 @@ import java.io.IOException; @@ -16,48 +17,53 @@ import java.io.IOException;
16 import java.util.List; 17 import java.util.List;
17 18
18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
19 21
20 -// TODO @json:swagger 和 validation 的注解,后续要补全下哈。可以等 workflow 基本写的差不多之后  
21 -@Api(tags = "工作流待办任务") 22 +@Api(tags = "流程任务")
22 @RestController 23 @RestController
23 -@RequestMapping("/workflow/task")  
24 -public class TaskController { 24 +@RequestMapping("/bpm/task")
  25 +@Validated
  26 +public class BpmTaskController {
25 27
26 @Resource 28 @Resource
27 - private BpmTaskService bpmTaskService; 29 + private BpmTaskService taskService;
28 30
29 - @GetMapping("/todo/page")  
30 - @ApiOperation("获取待办任务分页")  
31 - public CommonResult<PageResult<TodoTaskRespVO>> getTodoTaskPage(@Valid TodoTaskPageReqVO pageVO) {  
32 - return success(bpmTaskService.getTodoTaskPage(pageVO));  
33 - } 31 + // TODO 芋艿:权限、validation;
34 32
35 - @GetMapping("/claim")  
36 - @ApiOperation("签收任务")  
37 - public CommonResult<Boolean> claimTask(@RequestParam("id") String taskId) {  
38 - bpmTaskService.claimTask(taskId);  
39 - return success(true); 33 + @GetMapping("todo-page")
  34 + @ApiOperation("获取 Todo 待办任务分页")
  35 + public CommonResult<PageResult<BpmTaskTodoPageItemRespVO>> getTodoTaskPage(@Valid BpmTaskTodoPageReqVO pageVO) {
  36 + return success(taskService.getTodoTaskPage(getLoginUserId(), pageVO));
40 } 37 }
41 38
42 - @PostMapping("/task-steps")  
43 - public CommonResult<TaskHandleVO> getTaskSteps(@RequestBody TaskQueryReqVO taskQuery) {  
44 - return success(bpmTaskService.getTaskSteps(taskQuery)); 39 + @GetMapping("done-page")
  40 + @ApiOperation("获取 Done 已办任务分页")
  41 + public CommonResult<PageResult<BpmTaskDonePageItemRespVO>> getTodoTaskPage(@Valid BpmTaskDonePageReqVO pageVO) {
  42 + return success(taskService.getDoneTaskPage(getLoginUserId(), pageVO));
45 } 43 }
46 44
47 - @PostMapping("/formKey")  
48 - public CommonResult<TodoTaskRespVO> getTaskFormKey(@RequestBody TaskQueryReqVO taskQuery) {  
49 - return success(bpmTaskService.getTaskFormKey(taskQuery)); 45 + @PutMapping("/approve")
  46 + @ApiOperation("通过任务")
  47 + public CommonResult<Boolean> approveTask(@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
  48 + taskService.approveTask(reqVO);
  49 + return success(true);
50 } 50 }
51 51
52 - @PostMapping("/complete")  
53 - public CommonResult<Boolean> complete(@RequestBody TaskReqVO taskReq) {  
54 - bpmTaskService.completeTask(taskReq); 52 + @PutMapping("/reject")
  53 + @ApiOperation("不通过任务")
  54 + public CommonResult<Boolean> rejectTask(@Valid @RequestBody BpmTaskRejectReqVO reqVO) {
  55 + taskService.rejectTask(reqVO);
55 return success(true); 56 return success(true);
56 } 57 }
57 58
  59 + @PostMapping("/task-steps")
  60 + public CommonResult<TaskHandleVO> getTaskSteps(@RequestBody TaskQueryReqVO taskQuery) {
  61 + return success(taskService.getTaskSteps(taskQuery));
  62 + }
  63 +
58 @GetMapping("/process/history-steps") 64 @GetMapping("/process/history-steps")
59 public CommonResult<List<TaskStepVO>> getHistorySteps(@RequestParam("id") String processInstanceId) { 65 public CommonResult<List<TaskStepVO>> getHistorySteps(@RequestParam("id") String processInstanceId) {
60 - return success(bpmTaskService.getHistorySteps(processInstanceId)); 66 + return success(taskService.getHistorySteps(processInstanceId));
61 } 67 }
62 68
63 /** 69 /**
@@ -66,7 +72,7 @@ public class TaskController { @@ -66,7 +72,7 @@ public class TaskController {
66 */ 72 */
67 @GetMapping("/process/highlight-img") 73 @GetMapping("/process/highlight-img")
68 public void getHighlightImg(@RequestParam String processInstanceId, HttpServletResponse response) throws IOException { 74 public void getHighlightImg(@RequestParam String processInstanceId, HttpServletResponse response) throws IOException {
69 - FileResp fileResp = bpmTaskService.getHighlightImg(processInstanceId); 75 + FileResp fileResp = taskService.getHighlightImg(processInstanceId);
70 ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte()); 76 ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte());
71 } 77 }
72 78
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCancelReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +import javax.validation.constraints.NotNull;
  9 +import java.util.Map;
  10 +
  11 +@ApiModel("流程实例的取消 Request VO")
  12 +@Data
  13 +public class BpmProcessInstanceCancelReqVO {
  14 +
  15 + @ApiModelProperty(value = "流程实例的编号", required = true, example = "1024")
  16 + @NotEmpty(message = "流程实例的编号不能为空")
  17 + private String id;
  18 +
  19 + @ApiModelProperty(value = "取消原因", required = true, example = "不请假了!")
  20 + @NotEmpty(message = "取消原因不能为空")
  21 + private String reason;
  22 +
  23 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCreateReqVO.java
@@ -9,8 +9,6 @@ import java.util.Map; @@ -9,8 +9,6 @@ import java.util.Map;
9 9
10 @ApiModel("流程实例的创建 Request VO") 10 @ApiModel("流程实例的创建 Request VO")
11 @Data 11 @Data
12 -//@EqualsAndHashCode(callSuper = true)  
13 -//@ToString(callSuper = true)  
14 public class BpmProcessInstanceCreateReqVO { 12 public class BpmProcessInstanceCreateReqVO {
15 13
16 @ApiModelProperty(value = "流程定义的编号", required = true, example = "1024") 14 @ApiModelProperty(value = "流程定义的编号", required = true, example = "1024")
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceMyPageReqVO.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; 1 package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
4 10
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("流程实例的分页 Item Response VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
5 public class BpmProcessInstanceMyPageReqVO extends PageParam { 19 public class BpmProcessInstanceMyPageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程名称", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "流程定义的编号", example = "2048")
  25 + private String processDefinitionId;
  26 +
  27 + @ApiModelProperty(value = "流程实例的状态", notes = "参见 bpm_process_instance_status", example = "1")
  28 + private Integer status;
  29 +
  30 + @ApiModelProperty(value = "流程实例的结果", notes = "参见 bpm_process_instance_result", example = "2")
  31 + private Integer result;
  32 +
  33 + @ApiModelProperty(value = "流程分类", notes = "参见 bpm_model_category 数据字典", example = "1")
  34 + private String category;
  35 +
  36 + @ApiModelProperty(value = "开始的创建时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + private Date beginCreateTime;
  39 +
  40 + @ApiModelProperty(value = "结束的创建时间")
  41 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  42 + private Date endCreateTime;
  43 +
6 } 44 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstancePageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +
  10 +@ApiModel("流程实例的分页 Item Response VO")
  11 +@Data
  12 +public class BpmProcessInstancePageItemRespVO {
  13 +
  14 + @ApiModelProperty(value = "流程实例的编号", required = true, example = "1024")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "流程名称", required = true, example = "芋道")
  18 + private String name;
  19 +
  20 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
  21 + private String processDefinitionId;
  22 +
  23 + @ApiModelProperty(value = "流程分类", required = true, notes = "参见 bpm_model_category 数据字典", example = "1")
  24 + private String category;
  25 +
  26 + @ApiModelProperty(value = "流程实例的状态", required = true, notes = "参见 bpm_process_instance_status", example = "1")
  27 + private Integer status;
  28 +
  29 + @ApiModelProperty(value = "流程实例的结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
  30 + private Integer result;
  31 +
  32 + @ApiModelProperty(value = "提交时间", required = true)
  33 + private Date createTime;
  34 +
  35 + @ApiModelProperty(value = "结束时间", required = true)
  36 + private Date endTime;
  37 +
  38 + /**
  39 + * 当前任务
  40 + */
  41 + private List<Task> tasks;
  42 +
  43 + @ApiModel("流程任务")
  44 + @Data
  45 + public static class Task {
  46 +
  47 + @ApiModelProperty(value = "流程任务的编号", required = true, example = "1024")
  48 + private String id;
  49 +
  50 + @ApiModelProperty(value = "任务名称", required = true, example = "芋道")
  51 + private String name;
  52 +
  53 + }
  54 +
  55 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskApproveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.Map;
  12 +
  13 +@ApiModel("通过流程任务的 Request VO")
  14 +@Data
  15 +public class BpmTaskApproveReqVO {
  16 +
  17 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  18 + @NotEmpty(message = "任务编号不能为空")
  19 + private String id;
  20 +
  21 + @ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
  22 + @NotEmpty(message = "审批意见不能为空")
  23 + private String comment;
  24 +
  25 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +
  9 +@ApiModel("流程任务的 Done 已完成的分页项 Response VO")
  10 +@Data
  11 +public class BpmTaskDonePageItemRespVO {
  12 +
  13 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  14 + private String id;
  15 +
  16 + @ApiModelProperty(value = "任务名字", required = true, example = "芋道")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "接收时间", required = true)
  20 + private Date claimTime;
  21 +
  22 + @ApiModelProperty(value = "创建时间", required = true)
  23 + private Date createTime;
  24 + @ApiModelProperty(value = "结束时间", required = true)
  25 + private Date endTime;
  26 + @ApiModelProperty(value = "持续时间", required = true, example = "1000")
  27 + private Long durationInMillis;
  28 +
  29 + @ApiModelProperty(value = "任务结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
  30 + private Integer result;
  31 + @ApiModelProperty(value = "审批建议", required = true, example = "不请假了!")
  32 + private String comment;
  33 +
  34 + /**
  35 + * 所属流程实例
  36 + */
  37 + private ProcessInstance processInstance;
  38 +
  39 + @Data
  40 + @ApiModel("流程实例")
  41 + public static class ProcessInstance {
  42 +
  43 + @ApiModelProperty(value = "流程实例编号", required = true, example = "1024")
  44 + private String id;
  45 +
  46 + @ApiModelProperty(value = "流程实例名称", required = true, example = "芋道")
  47 + private String name;
  48 +
  49 + @ApiModelProperty(value = "发起人的用户编号", required = true, example = "1024")
  50 + private Long startUserId;
  51 +
  52 + @ApiModelProperty(value = "发起人的用户昵称", required = true, example = "芋艿")
  53 + private String startUserNickname;
  54 +
  55 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
  56 + private String processDefinitionId;
  57 +
  58 + }
  59 +
  60 +
  61 + // 任务编号、流程名称、任务节点、流程发起人、接收时间、审批时间、耗时【名称、开始时间】「流程记录、撤回」
  62 + // 任务编号、任务名称、所属流程、委托代办人、流程发起人、优先级、审批操作、审批意见、耗时、创建时间【名称、开始时间】「申请详情」
  63 +
  64 + // 任务编号、任务名称、流程名称、流程发起人、接收时间、审批时间、耗时【名称、接收时间】「详情」TODO 撤回
  65 +
  66 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("流程任务的 Done 已办的分页 Request VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class BpmTaskDonePageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程任务名", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "开始的创建收间")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private Date beginCreateTime;
  27 +
  28 + @ApiModelProperty(value = "结束的创建时间")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private Date endCreateTime;
  31 +
  32 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRejectReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotEmpty;
  8 +
  9 +@ApiModel("不通过流程任务的 Request VO")
  10 +@Data
  11 +public class BpmTaskRejectReqVO {
  12 +
  13 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  14 + @NotEmpty(message = "任务编号不能为空")
  15 + private String id;
  16 +
  17 + @ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
  18 + @NotEmpty(message = "审批意见不能为空")
  19 + private String comment;
  20 +
  21 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageItemRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +
  9 +@ApiModel("流程任务的 Running 进行中的分页项 Response VO")
  10 +@Data
  11 +public class BpmTaskTodoPageItemRespVO {
  12 +
  13 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
  14 + private String id;
  15 +
  16 + @ApiModelProperty(value = "任务名字", required = true, example = "芋道")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "接收时间", required = true)
  20 + private Date claimTime;
  21 +
  22 + @ApiModelProperty(value = "创建时间", required = true)
  23 + private Date createTime;
  24 +
  25 + @ApiModelProperty(value = "激活状态", required = true, example = "1", notes = "参见 SuspensionState 枚举")
  26 + private Integer suspensionState;
  27 +
  28 + /**
  29 + * 所属流程实例
  30 + */
  31 + private ProcessInstance processInstance;
  32 +
  33 + @Data
  34 + @ApiModel("流程实例")
  35 + public static class ProcessInstance {
  36 +
  37 + @ApiModelProperty(value = "流程实例编号", required = true, example = "1024")
  38 + private String id;
  39 +
  40 + @ApiModelProperty(value = "流程实例名称", required = true, example = "芋道")
  41 + private String name;
  42 +
  43 + @ApiModelProperty(value = "发起人的用户编号", required = true, example = "1024")
  44 + private Long startUserId;
  45 +
  46 + @ApiModelProperty(value = "发起人的用户昵称", required = true, example = "芋艿")
  47 + private String startUserNickname;
  48 +
  49 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "2048")
  50 + private String processDefinitionId;
  51 +
  52 + }
  53 +
  54 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("流程任务的 TODO 待办的分页 Request VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class BpmTaskTodoPageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "流程任务名", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "开始的创建收间")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private Date beginCreateTime;
  27 +
  28 + @ApiModelProperty(value = "结束的创建时间")
  29 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  30 + private Date endCreateTime;
  31 +
  32 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/FileResp.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/FileResp.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TaskHandleVO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/TaskHandleVO.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import lombok.ToString; 4 import lombok.ToString;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TaskQueryReqVO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/TaskQueryReqVO.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import lombok.ToString; 4 import lombok.ToString;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TaskStepVO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/TaskStepVO.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import lombok.ToString; 4 import lombok.ToString;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TaskReqVO.java deleted
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo;  
2 -  
3 -import lombok.Data;  
4 -import lombok.ToString;  
5 -  
6 -import java.util.Map;  
7 -  
8 -@Data  
9 -@ToString  
10 -public class TaskReqVO {  
11 -  
12 - private String taskId;  
13 -  
14 - private Map<String,Object> variables;  
15 -  
16 - private String comment;  
17 -}  
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/workflow/vo/TodoTaskRespVO.java deleted
1 -package cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo;  
2 -  
3 -import io.swagger.annotations.ApiModel;  
4 -import lombok.Data;  
5 -import lombok.ToString;  
6 -  
7 -@ApiModel("待办任务 Response VO")  
8 -@Data  
9 -@ToString  
10 -public class TodoTaskRespVO {  
11 -  
12 - // TODO @jason:swagger 注解。这样接口文档才完整哈  
13 -  
14 - private String id;  
15 -  
16 -  
17 - private String processInstanceId;  
18 -  
19 - /**  
20 - * 1:未签收  
21 - * 2:已签收  
22 - */  
23 - private Integer status;  
24 -  
25 -  
26 - private String processName;  
27 -  
28 -  
29 - private String processKey;  
30 -  
31 -  
32 - private String businessKey;  
33 -  
34 -  
35 - private String formKey;  
36 -  
37 -}  
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmDefinitionConvert.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; 1 package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition;
2 2
3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO; 3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO;
4 -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionDO; 4 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionRespVO;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
5 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; 6 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@@ -9,10 +10,14 @@ import org.activiti.engine.impl.persistence.entity.SuspensionState; @@ -9,10 +10,14 @@ import org.activiti.engine.impl.persistence.entity.SuspensionState;
9 import org.activiti.engine.repository.Deployment; 10 import org.activiti.engine.repository.Deployment;
10 import org.activiti.engine.repository.ProcessDefinition; 11 import org.activiti.engine.repository.ProcessDefinition;
11 import org.mapstruct.Mapper; 12 import org.mapstruct.Mapper;
  13 +import org.mapstruct.Mapping;
  14 +import org.mapstruct.Mappings;
  15 +import org.mapstruct.Named;
12 import org.mapstruct.factory.Mappers; 16 import org.mapstruct.factory.Mappers;
13 17
14 import java.util.List; 18 import java.util.List;
15 import java.util.Map; 19 import java.util.Map;
  20 +import java.util.function.Function;
16 21
17 /** 22 /**
18 * Bpm 流程定义的 Convert 23 * Bpm 流程定义的 Convert
@@ -25,17 +30,17 @@ public interface BpmDefinitionConvert { @@ -25,17 +30,17 @@ public interface BpmDefinitionConvert {
25 BpmDefinitionConvert INSTANCE = Mappers.getMapper(BpmDefinitionConvert.class); 30 BpmDefinitionConvert INSTANCE = Mappers.getMapper(BpmDefinitionConvert.class);
26 31
27 default List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list, Map<String, Deployment> deploymentMap, 32 default List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list, Map<String, Deployment> deploymentMap,
28 - Map<String, BpmProcessDefinitionDO> processDefinitionDOMap, Map<Long, BpmFormDO> formMap) { 33 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap, Map<Long, BpmFormDO> formMap) {
29 return CollectionUtils.convertList(list, definition -> { 34 return CollectionUtils.convertList(list, definition -> {
30 Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null; 35 Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null;
31 - BpmProcessDefinitionDO definitionDO = processDefinitionDOMap.get(definition.getId()); 36 + BpmProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
32 BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null; 37 BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null;
33 return convert(definition, deployment, definitionDO, form); 38 return convert(definition, deployment, definitionDO, form);
34 }); 39 });
35 } 40 }
36 41
37 default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment, 42 default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
38 - BpmProcessDefinitionDO processDefinitionDO, BpmFormDO form) { 43 + BpmProcessDefinitionExtDO processDefinitionDO, BpmFormDO form) {
39 BpmProcessDefinitionPageItemRespVO respVO = convert(bean); 44 BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
40 respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode()); 45 respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
41 if (deployment != null) { 46 if (deployment != null) {
@@ -53,6 +58,27 @@ public interface BpmDefinitionConvert { @@ -53,6 +58,27 @@ public interface BpmDefinitionConvert {
53 58
54 BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean); 59 BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
55 60
56 - BpmProcessDefinitionDO convert2(BpmDefinitionCreateReqDTO bean); 61 + BpmProcessDefinitionExtDO convert2(BpmDefinitionCreateReqDTO bean);
  62 +
  63 + default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list,
  64 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) {
  65 + return CollectionUtils.convertList(list, processDefinition -> {
  66 + BpmProcessDefinitionRespVO respVO = convert3(processDefinition);
  67 + BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId());
  68 + if (processDefinitionExtDO != null) {
  69 + respVO.setFormId(processDefinitionExtDO.getFormId());
  70 + }
  71 + return respVO;
  72 + });
  73 + }
  74 +
  75 + @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
  76 + BpmProcessDefinitionRespVO convert3(ProcessDefinition bean);
  77 +
  78 + @Named("convertSuspendedToSuspensionState")
  79 + default Integer convertSuspendedToSuspensionState(boolean suspended) {
  80 + return suspended ? SuspensionState.SUSPENDED.getStateCode() :
  81 + SuspensionState.ACTIVE.getStateCode();
  82 + }
57 83
58 } 84 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmProcessInstanceConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.convert.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstancePageItemRespVO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import org.activiti.engine.repository.ProcessDefinition;
  7 +import org.activiti.engine.runtime.ProcessInstance;
  8 +import org.activiti.engine.task.Task;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.Mapping;
  11 +import org.mapstruct.Mappings;
  12 +import org.mapstruct.factory.Mappers;
  13 +
  14 +import java.sql.SQLXML;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +import java.util.function.Consumer;
  18 +
  19 +/**
  20 + * 流程实例 Convert
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Mapper
  25 +public interface BpmProcessInstanceConvert {
  26 +
  27 + BpmProcessInstanceConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceConvert.class);
  28 +
  29 + @Mappings({
  30 + @Mapping(source = "instance.startUserId", target = "startUserId"),
  31 + @Mapping(source = "instance.id", target = "processInstanceId"),
  32 + @Mapping(source = "instance.startTime", target = "createTime"),
  33 + @Mapping(source = "definition.id", target = "processDefinitionId"),
  34 + @Mapping(source = "definition.name", target = "name"),
  35 + @Mapping(source = "definition.category", target = "category")
  36 + })
  37 + BpmProcessInstanceExtDO convert(ProcessInstance instance, ProcessDefinition definition);
  38 +
  39 + default PageResult<BpmProcessInstancePageItemRespVO> convertPage(PageResult<BpmProcessInstanceExtDO> page,
  40 + Map<String, List<Task>> taskMap) {
  41 + List<BpmProcessInstancePageItemRespVO> list = convertList(page.getList());
  42 + list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()))));
  43 + return new PageResult<>(list, page.getTotal());
  44 + }
  45 +
  46 + List<BpmProcessInstancePageItemRespVO> convertList(List<BpmProcessInstanceExtDO> list);
  47 +
  48 + List<BpmProcessInstancePageItemRespVO.Task> convertList2(List<Task> tasks);
  49 +
  50 + @Mapping(source = "processInstanceId", target = "id")
  51 + BpmProcessInstancePageItemRespVO convert(BpmProcessInstanceExtDO bean);
  52 +
  53 + @Mappings({
  54 + @Mapping(source = "id", target = "processInstanceId"),
  55 + @Mapping(source = "startDate", target = "createTime"),
  56 + @Mapping(source = "initiator", target = "startUserId"),
  57 + @Mapping(source = "status", target = "status", ignore = true)
  58 + })
  59 + BpmProcessInstanceExtDO convert(org.activiti.api.process.model.ProcessInstance bean);
  60 +
  61 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.convert.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskDonePageItemRespVO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskTodoPageItemRespVO;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.TaskStepVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  8 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  9 +import org.activiti.engine.history.HistoricActivityInstance;
  10 +import org.activiti.engine.history.HistoricProcessInstance;
  11 +import org.activiti.engine.history.HistoricTaskInstance;
  12 +import org.activiti.engine.impl.persistence.entity.SuspensionState;
  13 +import org.activiti.engine.runtime.ProcessInstance;
  14 +import org.activiti.engine.task.Task;
  15 +import org.mapstruct.Mapper;
  16 +import org.mapstruct.Mapping;
  17 +import org.mapstruct.Mappings;
  18 +import org.mapstruct.Named;
  19 +import org.mapstruct.factory.Mappers;
  20 +
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +
  24 +/**
  25 + * Bpm 任务 Convert
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Mapper
  30 +public interface BpmTaskConvert {
  31 +
  32 + BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
  33 +
  34 + @Mappings(value = {
  35 + @Mapping(source = "activityName", target = "stepName"),
  36 + @Mapping(source = "assignee", target = "assignee")
  37 + })
  38 + TaskStepVO convert(HistoricActivityInstance instance);
  39 +
  40 + default List<BpmTaskTodoPageItemRespVO> convertList(List<Task> tasks, Map<String, ProcessInstance> processInstanceMap,
  41 + Map<Long, SysUserDO> userMap) {
  42 + return CollectionUtils.convertList(tasks, task -> {
  43 + ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
  44 + return convert(task, processInstance, userMap.get(Long.valueOf(processInstance.getStartUserId())));
  45 + });
  46 + }
  47 +
  48 + @Mappings({
  49 + @Mapping(source = "task.id", target = "id"),
  50 + @Mapping(source = "task.name", target = "name"),
  51 + @Mapping(source = "task.claimTime", target = "claimTime"),
  52 + @Mapping(source = "task.createTime", target = "createTime"),
  53 + @Mapping(source = "task.suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState"),
  54 + @Mapping(source = "processInstance.id", target = "processInstance.id"),
  55 + @Mapping(source = "processInstance.name", target = "processInstance.name"),
  56 + @Mapping(source = "processInstance.startUserId", target = "processInstance.startUserId"),
  57 + @Mapping(source = "processInstance.processDefinitionId", target = "processInstance.processDefinitionId"),
  58 + @Mapping(source = "user.nickname", target = "processInstance.startUserNickname")
  59 + })
  60 + BpmTaskTodoPageItemRespVO convert(Task task, ProcessInstance processInstance, SysUserDO user);
  61 +
  62 + @Named("convertSuspendedToSuspensionState")
  63 + default Integer convertSuspendedToSuspensionState(boolean suspended) {
  64 + return suspended ? SuspensionState.SUSPENDED.getStateCode() :
  65 + SuspensionState.ACTIVE.getStateCode();
  66 + }
  67 +
  68 + default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks, Map<String, BpmTaskExtDO> bpmTaskExtDOMap,
  69 + Map<String, HistoricProcessInstance> historicProcessInstanceMap,
  70 + Map<Long, SysUserDO> userMap) {
  71 + return CollectionUtils.convertList(tasks, task -> {
  72 + BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
  73 + HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId());
  74 + SysUserDO userDO = userMap.get(Long.valueOf(processInstance.getStartUserId()));
  75 + return convert(task, taskExtDO, processInstance, userDO);
  76 + });
  77 + }
  78 +
  79 + @Mappings({
  80 + @Mapping(source = "task.id", target = "id"),
  81 + @Mapping(source = "task.name", target = "name"),
  82 + @Mapping(source = "task.claimTime", target = "claimTime"),
  83 + @Mapping(source = "task.createTime", target = "createTime"),
  84 + @Mapping(source = "task.endTime", target = "endTime"),
  85 + @Mapping(source = "task.durationInMillis", target = "durationInMillis"),
  86 + @Mapping(source = "taskExtDO.result", target = "result"),
  87 + @Mapping(source = "taskExtDO.comment", target = "comment"),
  88 + @Mapping(source = "processInstance.id", target = "processInstance.id"),
  89 + @Mapping(source = "processInstance.name", target = "processInstance.name"),
  90 + @Mapping(source = "processInstance.startUserId", target = "processInstance.startUserId"),
  91 + @Mapping(source = "processInstance.processDefinitionId", target = "processInstance.processDefinitionId"),
  92 + @Mapping(source = "user.nickname", target = "processInstance.startUserNickname")
  93 + })
  94 + BpmTaskDonePageItemRespVO convert(HistoricTaskInstance task, BpmTaskExtDO taskExtDO, HistoricProcessInstance processInstance, SysUserDO user);
  95 +
  96 + @Mappings({
  97 + @Mapping(source = "id", target = "taskId"),
  98 + @Mapping(source = "assignee", target = "assigneeUserId"),
  99 + @Mapping(source = "createdDate", target = "createTime")
  100 + })
  101 + BpmTaskExtDO convert(org.activiti.api.task.model.Task bean);
  102 +
  103 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/workflow/TaskConvert.java deleted
1 -package cn.iocoder.yudao.adminserver.modules.bpm.convert.workflow;  
2 -  
3 -import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.TaskStepVO;  
4 -import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.TodoTaskRespVO;  
5 -import org.activiti.api.task.model.Task;  
6 -import org.activiti.engine.history.HistoricActivityInstance;  
7 -import org.activiti.engine.repository.ProcessDefinition;  
8 -import org.mapstruct.Mapper;  
9 -import org.mapstruct.Mapping;  
10 -import org.mapstruct.Mappings;  
11 -import org.mapstruct.Named;  
12 -import org.mapstruct.factory.Mappers;  
13 -  
14 -@Mapper  
15 -public interface TaskConvert {  
16 - TaskConvert INSTANCE = Mappers.getMapper(TaskConvert.class);  
17 -  
18 - @Mappings(value = {  
19 - @Mapping(source = "task.id", target = "id"),  
20 - @Mapping(source = "task.businessKey", target = "businessKey"),  
21 - @Mapping(source = "task.assignee", target = "status",qualifiedByName = "convertAssigneeToStatus"),  
22 - @Mapping(source = "definition.name", target = "processName"),  
23 - @Mapping(source = "definition.key", target = "processKey"),  
24 - @Mapping(source = "definition.id", target = "processInstanceId")  
25 - })  
26 - TodoTaskRespVO convert(Task task, ProcessDefinition definition);  
27 -  
28 - @Mappings(value = {  
29 - @Mapping(source = "assignee", target = "status",qualifiedByName = "convertAssigneeToStatus")  
30 - })  
31 - TodoTaskRespVO convert(Task task);  
32 -  
33 - @Named("convertAssigneeToStatus")  
34 - default Integer convertAssigneeToStatus(String assignee) {  
35 - //TODO 不应该通过 assignee 定义状态 需要定义更多的状态  
36 - return assignee == null ? 1 : 2;  
37 - }  
38 -  
39 - @Mappings(value = {  
40 - @Mapping(source = "activityName", target = "stepName"),  
41 - @Mapping(source = "assignee", target = "assignee")  
42 - })  
43 - TaskStepVO convert(HistoricActivityInstance instance);  
44 -}  
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionDO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java
@@ -9,18 +9,18 @@ import org.activiti.engine.repository.ProcessDefinition; @@ -9,18 +9,18 @@ import org.activiti.engine.repository.ProcessDefinition;
9 9
10 /** 10 /**
11 * Bpm 流程定义的拓展表 11 * Bpm 流程定义的拓展表
12 - * 主要解决 主要进行 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表 12 + * 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表
13 * 13 *
14 * @author 芋道源码 14 * @author 芋道源码
15 */ 15 */
16 -@TableName(value = "bpm_process_definition", autoResultMap = true) 16 +@TableName(value = "bpm_process_definition_ext", autoResultMap = true)
17 @Data 17 @Data
18 @EqualsAndHashCode(callSuper = true) 18 @EqualsAndHashCode(callSuper = true)
19 @ToString(callSuper = true) 19 @ToString(callSuper = true)
20 @Builder 20 @Builder
21 @NoArgsConstructor 21 @NoArgsConstructor
22 @AllArgsConstructor 22 @AllArgsConstructor
23 -public class BpmProcessDefinitionDO extends BaseDO { 23 +public class BpmProcessDefinitionExtDO extends BaseDO {
24 24
25 /** 25 /**
26 * 编号 26 * 编号
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum;
  5 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
  10 +import org.activiti.engine.history.HistoricProcessInstance;
  11 +import org.activiti.engine.repository.ProcessDefinition;
  12 +import org.activiti.engine.runtime.ProcessInstance;
  13 +
  14 +import java.util.Date;
  15 +
  16 +/**
  17 + * Bpm 流程实例的拓展表
  18 + * 主要解决 Activiti {@link ProcessInstance} 和 {@link HistoricProcessInstance} 不支持拓展字段,所以新建拓展表
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@TableName(value = "bpm_process_instance_ext", autoResultMap = true)
  23 +@Data
  24 +@EqualsAndHashCode(callSuper = true)
  25 +@ToString(callSuper = true)
  26 +//@Builder
  27 +//@NoArgsConstructor
  28 +//@AllArgsConstructor
  29 +public class BpmProcessInstanceExtDO extends BaseDO {
  30 +
  31 + /**
  32 + * 发起流程的用户编号
  33 + *
  34 + * 冗余 {@link HistoricProcessInstance#getStartUserId()}
  35 + */
  36 + private Long startUserId;
  37 + /**
  38 + * 流程实例的名字
  39 + *
  40 + * 冗余 {@link ProcessInstance#getName()} 为了筛选
  41 + */
  42 + private String name;
  43 + /**
  44 + * 流程实例的编号
  45 + *
  46 + * 关联 {@link ProcessInstance#getId()}
  47 + */
  48 + private String processInstanceId;
  49 + /**
  50 + * 流程定义的编号
  51 + *
  52 + * 关联 {@link ProcessDefinition#getId()}
  53 + */
  54 + private String processDefinitionId;
  55 + /**
  56 + * 流程分类
  57 + *
  58 + * 冗余 {@link ProcessDefinition#getCategory()}
  59 + * 数据字典 bpm_model_category
  60 + */
  61 + private String category;
  62 + /**
  63 + * 流程实例的状态
  64 + *
  65 + * 枚举 {@link BpmProcessInstanceStatusEnum}
  66 + */
  67 + private Integer status;
  68 + /**
  69 + * 流程实例的结果
  70 + *
  71 + * 枚举 {@link BpmProcessInstanceResultEnum}
  72 + */
  73 + private Integer result;
  74 + /**
  75 + * 结束时间
  76 + *
  77 + * 冗余 {@link HistoricProcessInstance#getEndTime()}
  78 + */
  79 + private Date endTime;
  80 +
  81 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmTaskExtDO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.activiti.engine.history.HistoricTaskInstance;
  10 +import org.activiti.engine.repository.ProcessDefinition;
  11 +import org.activiti.engine.runtime.ProcessInstance;
  12 +import org.activiti.engine.task.Task;
  13 +
  14 +import java.util.Date;
  15 +
  16 +/**
  17 + * Bpm 流程任务的拓展表
  18 + * 主要解决 Activiti {@link Task} 和 {@link HistoricTaskInstance} 不支持拓展字段,所以新建拓展表
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@TableName(value = "bpm_task_ext", autoResultMap = true)
  23 +@Data
  24 +@EqualsAndHashCode(callSuper = true)
  25 +@ToString(callSuper = true)
  26 +//@Builder
  27 +//@NoArgsConstructor
  28 +//@AllArgsConstructor
  29 +public class BpmTaskExtDO extends BaseDO {
  30 +
  31 + /**
  32 + * 任务的审批人
  33 + *
  34 + * 冗余 {@link Task#getAssignee()}
  35 + */
  36 + private Long assigneeUserId;
  37 + /**
  38 + * 任务的名字
  39 + *
  40 + * 冗余 {@link Task#getName()} 为了筛选
  41 + */
  42 + private String name;
  43 + /**
  44 + * 任务的编号
  45 + *
  46 + * 关联 {@link Task#getId()}
  47 + */
  48 + private String taskId;
  49 + /**
  50 + * 任务的结果
  51 + *
  52 + * 枚举 {@link BpmProcessInstanceResultEnum}
  53 + */
  54 + private Integer result;
  55 + /**
  56 + * 审批建议
  57 + */
  58 + private String comment;
  59 + /**
  60 + * 任务的结束时间
  61 + *
  62 + * 冗余 {@link HistoricTaskInstance#getEndTime()}
  63 + */
  64 + private Date endTime;
  65 +
  66 + /**
  67 + * 流程实例的编号
  68 + *
  69 + * 关联 {@link ProcessInstance#getId()}
  70 + */
  71 + private String processInstanceId;
  72 + /**
  73 + * 流程定义的编号
  74 + *
  75 + * 关联 {@link ProcessDefinition#getId()}
  76 + */
  77 + private String processDefinitionId;
  78 +
  79 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/package-info.java deleted
1 -/**  
2 - * TODO 芋艿:工作流创建后的定义  
3 - */  
4 -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task;  
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmProcessDefinitionMapper.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition; 1 package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionDO; 3 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
@@ -9,10 +9,10 @@ import java.util.Collection; @@ -9,10 +9,10 @@ import java.util.Collection;
9 import java.util.List; 9 import java.util.List;
10 10
11 @Mapper 11 @Mapper
12 -public interface BpmProcessDefinitionMapper extends BaseMapper<BpmProcessDefinitionDO> { 12 +public interface BpmProcessDefinitionExtMapper extends BaseMapper<BpmProcessDefinitionExtDO> {
13 13
14 - default List<BpmProcessDefinitionDO> selectListByProcessDefinitionIds(Collection<String> processDefinitionIds) {  
15 - return selectList(new QueryWrapper<BpmProcessDefinitionDO>().in("process_definition_id", processDefinitionIds)); 14 + default List<BpmProcessDefinitionExtDO> selectListByProcessDefinitionIds(Collection<String> processDefinitionIds) {
  15 + return selectList(new QueryWrapper<BpmProcessDefinitionExtDO>().in("process_definition_id", processDefinitionIds));
16 } 16 }
17 17
18 } 18 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceMyPageReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  7 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  8 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +@Mapper
  12 +public interface BpmProcessInstanceExtMapper extends BaseMapperX<BpmProcessInstanceExtDO> {
  13 +
  14 + default PageResult<BpmProcessInstanceExtDO> selectPage(Long userId, BpmProcessInstanceMyPageReqVO reqVO) {
  15 + return selectPage(reqVO, new QueryWrapperX<BpmProcessInstanceExtDO>()
  16 + .eqIfPresent("start_user_id", userId)
  17 + .likeIfPresent("name", reqVO.getName())
  18 + .eqIfPresent("process_definition_id", reqVO.getProcessDefinitionId())
  19 + .eqIfPresent("category", reqVO.getCategory())
  20 + .eqIfPresent("status", reqVO.getStatus())
  21 + .eqIfPresent("result", reqVO.getResult())
  22 + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  23 + .orderByDesc("id"));
  24 + }
  25 +
  26 + default void updateByProcessInstanceId(BpmProcessInstanceExtDO updateObj) {
  27 + update(updateObj, new QueryWrapper<BpmProcessInstanceExtDO>()
  28 + .eq("process_instance_id", updateObj.getProcessInstanceId()));
  29 + }
  30 +
  31 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmTaskExtMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +
  11 +@Mapper
  12 +public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
  13 +
  14 + default void updateByTaskId(BpmTaskExtDO entity) {
  15 + update(entity, new QueryWrapper<BpmTaskExtDO>().eq("task_id", entity.getTaskId()));
  16 + }
  17 +
  18 + default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
  19 + return selectList("task_id", taskIds);
  20 + }
  21 +
  22 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
10 public interface BpmErrorCodeConstants { 10 public interface BpmErrorCodeConstants {
11 11
12 // ========== 通用流程处理 模块 1-009-000-000 ========== 12 // ========== 通用流程处理 模块 1-009-000-000 ==========
13 - ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009000001, "流程实例不存在");  
14 ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常"); 13 ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常");
15 14
16 // ========== OA 流程模块 1-009-001-000 ========== 15 // ========== OA 流程模块 1-009-001-000 ==========
@@ -34,7 +33,12 @@ public interface BpmErrorCodeConstants { @@ -34,7 +33,12 @@ public interface BpmErrorCodeConstants {
34 ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态"); 33 ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态");
35 34
36 // ========== 流程实例 1-009-004-000 ========== 35 // ========== 流程实例 1-009-004-000 ==========
  36 + ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");
  37 + ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1009004001, "流程取消失败,流程不处于运行中");
  38 + ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1009004002, "流程取消失败,该流程不是你发起的");
37 39
  40 + // ========== 流程实例 1-009-005-000 ==========
  41 + ErrorCode TASK_COMPLETE_FAIL_NOT_EXISTS = new ErrorCode(1009004000, "审批任务失败,原因:该任务不处于未审批");
38 42
39 // ========== 动态表单模块 1-009-010-000 ========== 43 // ========== 动态表单模块 1-009-010-000 ==========
40 ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在"); 44 ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.enums.task;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 流程实例的删除原因
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmProcessInstanceDeleteReasonEnum {
  14 +
  15 + REJECT_TASK("驳回任务");
  16 +
  17 + private final String reason;
  18 +
  19 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceResultEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.enums.task;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 流程实例的结果
  8 + *
  9 + * @author jason
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum BpmProcessInstanceResultEnum {
  14 +
  15 + PROCESS(1, "处理中"),
  16 + APPROVE(2, "通过"),
  17 + REJECT(3, "不通过"),
  18 + CANCEL(4, "已取消");
  19 +
  20 + /**
  21 + * 结果
  22 + */
  23 + private final Integer result;
  24 + /**
  25 + * 描述
  26 + */
  27 + private final String desc;
  28 +
  29 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/FlowStatusEnum.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceStatusEnum.java
1 -package cn.iocoder.yudao.adminserver.modules.bpm.enums; 1 +package cn.iocoder.yudao.adminserver.modules.bpm.enums.task;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
6 /** 6 /**
7 - * 流程状态 7 + * 流程实例的状态
  8 + *
  9 + * @author 芋道源码
8 */ 10 */
9 @Getter 11 @Getter
10 @AllArgsConstructor 12 @AllArgsConstructor
11 -public enum FlowStatusEnum { 13 +public enum BpmProcessInstanceStatusEnum {
12 14
13 - HANDLE(1, "处理中"),  
14 -  
15 - PASS(2, "审批通过"),  
16 -  
17 - REJECTED(3, "审批不通过"); 15 + RUNNING(1, "进行中"),
  16 + FINISH(2, "已完成");
18 17
19 /** 18 /**
20 * 状态 19 * 状态
21 */ 20 */
22 private final Integer status; 21 private final Integer status;
23 -  
24 -  
25 /** 22 /**
26 * 描述 23 * 描述
27 */ 24 */
28 private final String desc; 25 private final String desc;
  26 +
29 } 27 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/BpmActivitiConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.listener.BpmTackActivitiEventListener;
  4 +import org.activiti.spring.SpringProcessEngineConfiguration;
  5 +import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +import javax.annotation.Resource;
  9 +import java.util.Collections;
  10 +
  11 +/**
  12 + * BPM 模块的 Activiti 配置类
  13 + */
  14 +@Configuration
  15 +public class BpmActivitiConfiguration implements ProcessEngineConfigurationConfigurer {
  16 +
  17 + @Resource
  18 + private BpmTackActivitiEventListener taskActivitiEventListener;
  19 +
  20 + @Override
  21 + public void configure(SpringProcessEngineConfiguration configuration) {
  22 + // 注册监听器,例如说 BpmActivitiEventListener
  23 + configuration.setEventListeners(Collections.singletonList(taskActivitiEventListener));
  24 + }
  25 +
  26 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/package-info.java 0 → 100644
  1 +/**
  2 + * 属于 bpm 模块的 framework 封装
  3 + *
  4 + * @author 芋道源码
  5 + */
  6 +package cn.iocoder.yudao.adminserver.modules.bpm.framework;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionListReqVO;
3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO;
4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionRespVO;
5 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@@ -31,6 +33,14 @@ public interface BpmProcessDefinitionService { @@ -31,6 +33,14 @@ public interface BpmProcessDefinitionService {
31 PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO); 33 PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
32 34
33 /** 35 /**
  36 + * 获得流程定义列表
  37 + *
  38 + * @param listReqVO 列表入参
  39 + * @return 流程定义列表
  40 + */
  41 + List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
  42 +
  43 + /**
34 * 获得流程定义对应的 BPMN XML 44 * 获得流程定义对应的 BPMN XML
35 * 45 *
36 * @param id 流程定义编号 46 * @param id 流程定义编号
@@ -55,6 +65,16 @@ public interface BpmProcessDefinitionService { @@ -55,6 +65,16 @@ public interface BpmProcessDefinitionService {
55 ProcessDefinition getProcessDefinition(String id); 65 ProcessDefinition getProcessDefinition(String id);
56 66
57 /** 67 /**
  68 + * 获得编号对应的 ProcessDefinition
  69 + *
  70 + * 相比 {@link #getProcessDefinition(String)} 方法,category 的取值是正确
  71 + *
  72 + * @param id 编号
  73 + * @return 流程定义
  74 + */
  75 + ProcessDefinition getProcessDefinition2(String id);
  76 +
  77 + /**
58 * 获得 id 对应的 Deployment 78 * 获得 id 对应的 Deployment
59 * 79 *
60 * @param id 部署编号 80 * @param id 部署编号
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
@@ -2,12 +2,14 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; @@ -2,12 +2,14 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionListReqVO;
5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO; 6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageItemRespVO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionPageReqVO;
  8 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.BpmProcessDefinitionRespVO;
7 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmDefinitionConvert; 9 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmDefinitionConvert;
8 -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionDO; 10 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
9 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO; 11 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.form.BpmFormDO;
10 -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionMapper; 12 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
11 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; 13 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
12 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 14 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;
13 import cn.iocoder.yudao.adminserver.modules.bpm.service.form.BpmFormService; 15 import cn.iocoder.yudao.adminserver.modules.bpm.service.form.BpmFormService;
@@ -56,7 +58,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -56,7 +58,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
56 private BpmFormService bpmFormService; 58 private BpmFormService bpmFormService;
57 59
58 @Resource 60 @Resource
59 - private BpmProcessDefinitionMapper processDefinitionMapper; 61 + private BpmProcessDefinitionExtMapper processDefinitionMapper;
60 62
61 @Override 63 @Override
62 public PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) { 64 public PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) {
@@ -77,14 +79,13 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -77,14 +79,13 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
77 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds); 79 Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
78 80
79 // 获得 BpmProcessDefinitionDO Map 81 // 获得 BpmProcessDefinitionDO Map
80 - List<BpmProcessDefinitionDO> processDefinitionDOs = Collections.emptyList();  
81 - processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( 82 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
82 convertList(processDefinitions, ProcessDefinition::getId)); 83 convertList(processDefinitions, ProcessDefinition::getId));
83 - Map<String, BpmProcessDefinitionDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs,  
84 - BpmProcessDefinitionDO::getProcessDefinitionId); 84 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs,
  85 + BpmProcessDefinitionExtDO::getProcessDefinitionId);
85 86
86 // 获得 Form Map 87 // 获得 Form Map
87 - Set<Long> formIds = CollectionUtils.convertSet(processDefinitionDOs, BpmProcessDefinitionDO::getFormId); 88 + Set<Long> formIds = CollectionUtils.convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
88 Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds); 89 Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds);
89 90
90 // 拼接结果 91 // 拼接结果
@@ -94,6 +95,27 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -94,6 +95,27 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
94 } 95 }
95 96
96 @Override 97 @Override
  98 + public List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO) {
  99 + // 拼接查询条件
  100 + ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
  101 + if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), listReqVO.getSuspensionState())) {
  102 + definitionQuery.suspended();
  103 + } else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), listReqVO.getSuspensionState())) {
  104 + definitionQuery.active();
  105 + }
  106 + // 执行查询
  107 + List<ProcessDefinition> processDefinitions = definitionQuery.list();
  108 +
  109 + // 获得 BpmProcessDefinitionDO Map
  110 + List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
  111 + convertList(processDefinitions, ProcessDefinition::getId));
  112 + Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = CollectionUtils.convertMap(processDefinitionDOs,
  113 + BpmProcessDefinitionExtDO::getProcessDefinitionId);
  114 + // 执行查询,并返回
  115 + return BpmDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap);
  116 + }
  117 +
  118 + @Override
97 public String getProcessDefinitionBpmnXML(String id) { 119 public String getProcessDefinitionBpmnXML(String id) {
98 BpmnModel bpmnModel = repositoryService.getBpmnModel(id); 120 BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
99 if (bpmnModel == null) { 121 if (bpmnModel == null) {
@@ -114,6 +136,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -114,6 +136,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
114 } 136 }
115 137
116 @Override 138 @Override
  139 + public ProcessDefinition getProcessDefinition2(String id) {
  140 + return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
  141 + }
  142 +
  143 + @Override
117 public Deployment getDeployment(String id) { 144 public Deployment getDeployment(String id) {
118 if (StrUtil.isEmpty(id)) { 145 if (StrUtil.isEmpty(id)) {
119 return null; 146 return null;
@@ -169,7 +196,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -169,7 +196,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
169 } 196 }
170 197
171 // 插入拓展表 198 // 插入拓展表
172 - BpmProcessDefinitionDO definitionDO = BpmDefinitionConvert.INSTANCE.convert2(createReqDTO) 199 + BpmProcessDefinitionExtDO definitionDO = BpmDefinitionConvert.INSTANCE.convert2(createReqDTO)
173 .setProcessDefinitionId(definition.getId()); 200 .setProcessDefinitionId(definition.getId());
174 processDefinitionMapper.insert(definitionDO); 201 processDefinitionMapper.insert(definitionDO);
175 return definition.getId(); 202 return definition.getId();
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.oa; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.oa;
2 2
3 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO; 3 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO;
4 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper; 4 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper;
5 -import cn.iocoder.yudao.adminserver.modules.bpm.enums.FlowStatusEnum; 5 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
6 import org.activiti.engine.delegate.DelegateExecution; 6 import org.activiti.engine.delegate.DelegateExecution;
7 import org.activiti.engine.delegate.ExecutionListener; 7 import org.activiti.engine.delegate.ExecutionListener;
8 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
@@ -29,9 +29,9 @@ public class LeaveApplyEndProcessor implements ExecutionListener { @@ -29,9 +29,9 @@ public class LeaveApplyEndProcessor implements ExecutionListener {
29 OALeaveDO updateDo = new OALeaveDO(); 29 OALeaveDO updateDo = new OALeaveDO();
30 updateDo.setId(Long.valueOf(businessKey)); 30 updateDo.setId(Long.valueOf(businessKey));
31 if (Objects.equals(approved, true)) { 31 if (Objects.equals(approved, true)) {
32 - updateDo.setStatus(FlowStatusEnum.PASS.getStatus()); 32 + updateDo.setStatus(BpmProcessInstanceResultEnum.APPROVE.getResult());
33 } else { 33 } else {
34 - updateDo.setStatus(FlowStatusEnum.REJECTED.getStatus()); 34 + updateDo.setStatus(BpmProcessInstanceResultEnum.REJECT.getResult());
35 } 35 }
36 36
37 leaveMapper.updateById(updateDo); 37 leaveMapper.updateById(updateDo);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.*; @@ -6,7 +6,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.*;
6 import cn.iocoder.yudao.adminserver.modules.bpm.convert.oa.OALeaveConvert; 6 import cn.iocoder.yudao.adminserver.modules.bpm.convert.oa.OALeaveConvert;
7 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO;
8 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper; 8 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper;
9 -import cn.iocoder.yudao.adminserver.modules.bpm.enums.FlowStatusEnum; 9 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
10 import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.OALeaveService; 10 import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.OALeaveService;
11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; 11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
12 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysPostMapper; 12 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysPostMapper;
@@ -62,7 +62,7 @@ public class OALeaveServiceImpl implements OALeaveService { @@ -62,7 +62,7 @@ public class OALeaveServiceImpl implements OALeaveService {
62 public Long createLeave(OALeaveCreateReqVO createReqVO) { 62 public Long createLeave(OALeaveCreateReqVO createReqVO) {
63 // 插入 OA 请假单 63 // 插入 OA 请假单
64 OALeaveDO leave = OALeaveConvert.INSTANCE.convert(createReqVO); 64 OALeaveDO leave = OALeaveConvert.INSTANCE.convert(createReqVO);
65 - leave.setStatus(FlowStatusEnum.HANDLE.getStatus()); 65 + leave.setStatus(BpmProcessInstanceResultEnum.PROCESS.getResult());
66 // TODO @jason:应该是存储 userId?? 66 // TODO @jason:应该是存储 userId??
67 leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername()); 67 leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
68 leaveMapper.insert(leave); 68 leaveMapper.insert(leave);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCancelReqVO;
3 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceMyPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstancePageItemRespVO;
  7 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
  8 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
  9 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  10 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  11 +import org.activiti.engine.history.HistoricProcessInstance;
  12 +import org.activiti.engine.runtime.ProcessInstance;
4 13
5 import javax.validation.Valid; 14 import javax.validation.Valid;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +import java.util.Set;
6 18
7 /** 19 /**
8 * 流程实例 Service 接口 20 * 流程实例 Service 接口
@@ -20,4 +32,120 @@ public interface BpmProcessInstanceService { @@ -20,4 +32,120 @@ public interface BpmProcessInstanceService {
20 */ 32 */
21 String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO); 33 String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
22 34
  35 + /**
  36 + * 取消流程实例
  37 + *
  38 + * @param userId 用户编号
  39 + * @param cancelReqVO 取消信息
  40 + */
  41 + void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO);
  42 +
  43 + /**
  44 + * 删除流程实例
  45 + *
  46 + * @param id 流程编号
  47 + * @param reason 删除原因。可选 {@link BpmProcessInstanceDeleteReasonEnum}
  48 + */
  49 + @Deprecated
  50 + void deleteProcessInstance(String id, String reason);
  51 +
  52 + /**
  53 + * 更新流程实例的结果
  54 + * 1. 如果更新为已拒绝时,会进行任务的删除
  55 + *
  56 + * @param id 流程编号
  57 + * @param result 结果,{@link BpmProcessInstanceResultEnum}
  58 + */
  59 + void updateProcessInstanceResult(String id, Integer result);
  60 +
  61 + /**
  62 + * 获得流程实例的分页
  63 + *
  64 + * @param userId 用户编号
  65 + * @param pageReqVO 分页请求
  66 + * @return 流程实例的分页
  67 + */
  68 + PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,
  69 + @Valid BpmProcessInstanceMyPageReqVO pageReqVO);
  70 +
  71 + /**
  72 + * 获得流程实例
  73 + *
  74 + * @param id 流程实例的编号
  75 + * @return 流程实例
  76 + */
  77 + ProcessInstance getProcessInstance(String id);
  78 +
  79 + /**
  80 + * 获得流程实例列表
  81 + *
  82 + * @param ids 流程实例的编号集合
  83 + * @return 流程实例列表
  84 + */
  85 + List<ProcessInstance> getProcessInstances(Set<String> ids);
  86 +
  87 + /**
  88 + * 获得流程实例 Map
  89 + *
  90 + * @param ids 流程实例的编号集合
  91 + * @return 流程实例列表 Map
  92 + */
  93 + default Map<String, ProcessInstance> getProcessInstanceMap(Set<String> ids) {
  94 + return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
  95 + }
  96 +
  97 + /**
  98 + * 获得历史的流程实例
  99 + *
  100 + * @param id 流程实例的编号
  101 + * @return 历史的流程实例
  102 + */
  103 + HistoricProcessInstance getHistoricProcessInstance(String id);
  104 +
  105 + /**
  106 + * 获得历史的流程实例列表
  107 + *
  108 + * @param ids 流程实例的编号集合
  109 + * @return 历史的流程实例列表
  110 + */
  111 + List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);
  112 +
  113 + /**
  114 + * 获得历史的流程实例 Map
  115 + *
  116 + * @param ids 流程实例的编号集合
  117 + * @return 历史的流程实例列表 Map
  118 + */
  119 + default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
  120 + return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
  121 + }
  122 +
  123 + /**
  124 + * 创建 ProcessInstance 拓展记录
  125 + *
  126 + * @param instance 流程任务
  127 + */
  128 + void createProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance);
  129 +
  130 + /**
  131 + * 更新 ProcessInstance 拓展记录
  132 + *
  133 + * @param instance 流程任务
  134 + */
  135 + void updateProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance);
  136 +
  137 + /**
  138 + * 更新 ProcessInstance 拓展记录为取消
  139 + *
  140 + * @param instance 流程任务
  141 + */
  142 + void updateProcessInstanceExtCancel(org.activiti.api.process.model.ProcessInstance instance);
  143 +
  144 + /**
  145 + * 更新 ProcessInstance 拓展记录为完成
  146 + *
  147 + * @param instance 流程任务
  148 + */
  149 + void updateProcessInstanceExtComplete(org.activiti.api.process.model.ProcessInstance instance);
  150 +
23 } 151 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.*; 3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import org.activiti.engine.task.Task;
5 7
  8 +import javax.validation.Valid;
6 import java.util.List; 9 import java.util.List;
  10 +import java.util.Map;
7 11
8 /** 12 /**
9 - * 工作流用户任务服务接口 13 + * 流程任务 Service 接口
  14 + *
  15 + * @author jason
  16 + * @author 芋道源码
10 */ 17 */
11 public interface BpmTaskService { 18 public interface BpmTaskService {
12 19
  20 + /**
  21 + * 获得流程任务列表
  22 + *
  23 + * @param processInstanceId 流程实例的编号
  24 + * @return 流程任务列表
  25 + */
  26 + List<Task> getTasksByProcessInstanceId(String processInstanceId);
  27 +
  28 + /**
  29 + * 获得流程任务列表
  30 + *
  31 + * @param processInstanceIds 流程实例的编号数组
  32 + * @return 流程任务列表
  33 + */
  34 + List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
  35 +
  36 + /**
  37 + * 获得流程任务 Map
  38 + *
  39 + * @param processInstanceIds 流程实例的编号数组
  40 + * @return 流程任务 Map
  41 + */
  42 + default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
  43 + return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
  44 + Task::getProcessInstanceId);
  45 + }
13 46
14 /** 47 /**
15 - * 获取当前用户的待办任务, 分页 48 + * 获得待办的流程任务分页
  49 + *
  50 + * @param userId 用户编号
  51 + * @param pageReqVO 分页请求
  52 + * @return 流程任务分页
16 */ 53 */
17 - PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO); 54 + PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
18 55
19 /** 56 /**
20 - * 签收任务  
21 - * @param taskId 用户任务id 57 + * 获得已办的流程任务分页
  58 + *
  59 + * @param userId 用户编号
  60 + * @param pageReqVO 分页请求
  61 + * @return 流程任务分页
22 */ 62 */
23 - void claimTask(String taskId); 63 + PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
24 64
25 /** 65 /**
26 - * 工作流,完成 userTask, 完成用户任务 一般传入参数 1。是否同意(variables). 2. 评论(comment)  
27 - * variables 变量名 和 评论 由前台传入  
28 - * @param taskReq 任务参数 66 + * 将流程任务分配给指定用户
  67 + *
  68 + * @param id 流程任务编号
  69 + * @param userId 用户编号
29 */ 70 */
30 - void completeTask(TaskReqVO taskReq); 71 + void updateTaskAssign(String id, Long userId);
  72 +
  73 + /**
  74 + * 通过任务
  75 + *
  76 + * @param reqVO 通过请求
  77 + */
  78 + void approveTask(@Valid BpmTaskApproveReqVO reqVO);
  79 +
  80 + /**
  81 + * 不通过任务
  82 + *
  83 + * @param reqVO 不通过请求
  84 + */
  85 + void rejectTask(@Valid BpmTaskRejectReqVO reqVO);
31 86
32 /** 87 /**
33 * 根据任务id, 查询已经完成的用户任务,未完成的用户任务 88 * 根据任务id, 查询已经完成的用户任务,未完成的用户任务
34 * @param taskQuery 查询参数 一般 taskId 89 * @param taskQuery 查询参数 一般 taskId
35 */ 90 */
  91 + @Deprecated
36 TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery); 92 TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery);
37 93
38 /** 94 /**
39 * 根据流程实例id, 查询历史用户任务,包括已完成,未完成 95 * 根据流程实例id, 查询历史用户任务,包括已完成,未完成
40 * @param processInstanceId 流程实例id 96 * @param processInstanceId 流程实例id
41 */ 97 */
  98 + @Deprecated
42 List<TaskStepVO> getHistorySteps(String processInstanceId); 99 List<TaskStepVO> getHistorySteps(String processInstanceId);
43 100
44 /** 101 /**
45 - * 获取用户任务的 formKey, 对应外置表单, 需要根据formKey 对应业务表单  
46 - * @param taskQuery 查询参数 ,一般taskId  
47 - */  
48 - TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery);  
49 -  
50 -  
51 - /**  
52 * 返回高亮的流转进程 102 * 返回高亮的流转进程
53 * @param processInstanceId 实例Id 103 * @param processInstanceId 实例Id
54 * @return {@link FileResp} 返回文件 104 * @return {@link FileResp} 返回文件
55 */ 105 */
56 FileResp getHighlightImg(String processInstanceId); 106 FileResp getHighlightImg(String processInstanceId);
  107 +
  108 + // ========== Task 拓展表相关 ==========
  109 +
  110 + /**
  111 + * 创建 Task 拓展记录
  112 + *
  113 + * @param task 任务实体
  114 + */
  115 + void createTaskExt(org.activiti.api.task.model.Task task);
  116 +
  117 + /**
  118 + * 更新 Task 拓展记录
  119 + *
  120 + * @param task 任务实体
  121 + */
  122 + void updateTaskExt(org.activiti.api.task.model.Task task);
  123 +
  124 + /**
  125 + * 更新 Task 拓展记录为取消
  126 + *
  127 + * @param task 任务实体
  128 + */
  129 + void updateTaskExtCancel(org.activiti.api.task.model.Task task);
  130 +
  131 + /**
  132 + * 更新 Task 拓展记录为完成
  133 + *
  134 + * @param task 任务实体
  135 + */
  136 + void updateTaskExtComplete(org.activiti.api.task.model.Task task);
  137 +
57 } 138 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
2 2
3 -import cn.hutool.core.lang.Assert; 3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCancelReqVO;
4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceMyPageReqVO;
  7 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstancePageItemRespVO;
  8 +import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmProcessInstanceConvert;
  9 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  10 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
  11 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
  12 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
  13 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum;
5 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; 14 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
6 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; 15 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
  16 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
7 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 17 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
8 -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 18 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
10 import org.activiti.engine.HistoryService; 20 import org.activiti.engine.HistoryService;
11 -import org.activiti.engine.RepositoryService;  
12 import org.activiti.engine.RuntimeService; 21 import org.activiti.engine.RuntimeService;
13 -import org.activiti.engine.TaskService;  
14 -import org.activiti.engine.history.HistoricProcessInstanceQuery;  
15 -import org.activiti.engine.impl.identity.Authentication; 22 +import org.activiti.engine.history.HistoricProcessInstance;
16 import org.activiti.engine.repository.ProcessDefinition; 23 import org.activiti.engine.repository.ProcessDefinition;
17 import org.activiti.engine.runtime.ProcessInstance; 24 import org.activiti.engine.runtime.ProcessInstance;
18 import org.activiti.engine.task.Task; 25 import org.activiti.engine.task.Task;
  26 +import org.springframework.context.annotation.Lazy;
19 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
  28 +import org.springframework.transaction.annotation.Transactional;
20 import org.springframework.validation.annotation.Validated; 29 import org.springframework.validation.annotation.Validated;
21 30
22 import javax.annotation.Resource; 31 import javax.annotation.Resource;
23 -import java.util.Map; 32 +import java.util.*;
24 33
25 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_IS_SUSPENDED;  
26 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NOT_EXISTS; 34 +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  36 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
28 37
29 /** 38 /**
30 * 流程实例 Service 实现类 39 * 流程实例 Service 实现类
@@ -44,20 +53,23 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU @@ -44,20 +53,23 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
44 public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { 53 public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
45 54
46 @Resource 55 @Resource
47 - private RepositoryService repositoryService;  
48 - @Resource  
49 private RuntimeService runtimeService; 56 private RuntimeService runtimeService;
50 @Resource 57 @Resource
51 - private TaskService taskService;  
52 - @Resource  
53 private HistoryService historyService; 58 private HistoryService historyService;
54 59
55 @Resource 60 @Resource
56 private SysUserService userService; 61 private SysUserService userService;
57 @Resource 62 @Resource
  63 + @Lazy // 解决循环依赖
  64 + private BpmTaskService taskService;
  65 + @Resource
58 private BpmProcessDefinitionService processDefinitionService; 66 private BpmProcessDefinitionService processDefinitionService;
59 67
  68 + @Resource
  69 + private BpmProcessInstanceExtMapper processInstanceExtMapper;
  70 +
60 @Override 71 @Override
  72 + @Transactional(rollbackFor = Exception.class)
61 public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqVO createReqVO) { 73 public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqVO createReqVO) {
62 // 校验流程定义 74 // 校验流程定义
63 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); 75 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
@@ -68,33 +80,141 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @@ -68,33 +80,141 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
68 throw exception(PROCESS_DEFINITION_IS_SUSPENDED); 80 throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
69 } 81 }
70 82
71 - // 设置流程发起人  
72 - Authentication.setAuthenticatedUserId(String.valueOf(userId));  
73 -  
74 // 创建流程实例 83 // 创建流程实例
75 Map<String, Object> variables = createReqVO.getVariables(); 84 Map<String, Object> variables = createReqVO.getVariables();
76 - variables.put("INITIATOR", userId); // TODO 芋艿:初始化人员  
77 ProcessInstance instance = runtimeService.startProcessInstanceById(createReqVO.getProcessDefinitionId(), variables); 85 ProcessInstance instance = runtimeService.startProcessInstanceById(createReqVO.getProcessDefinitionId(), variables);
  86 + // 设置流程名字
  87 + runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
  88 +
  89 + // TODO 芋艿:临时使用, 保证分配
  90 + List<Task> tasks = taskService.getTasksByProcessInstanceId(instance.getId());
  91 + tasks.forEach(task -> taskService.updateTaskAssign(task.getId(), userId));
78 92
79 // 添加初始的评论 TODO 芋艿:在思考下 93 // 添加初始的评论 TODO 芋艿:在思考下
80 - Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();  
81 - if (task != null) {  
82 - SysUserDO user = userService.getUser(userId);  
83 - Assert.notNull(user, "用户({})不存在", userId);  
84 - String type = "normal";  
85 - taskService.addComment(task.getId(), instance.getProcessInstanceId(), type,  
86 - String.format("%s 发起流程申请", user.getNickname()));  
87 - // TODO 芋艿:应该不用下面两个步骤  
88 -// taskService.setAssignee(task.getId(), String.valueOf(userId));  
89 -// taskService.complete(task.getId(), variables);  
90 - } 94 +// Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
  95 +// if (task != null) {
  96 +// SysUserDO user = userService.getUser(userId);
  97 +// Assert.notNull(user, "用户({})不存在", userId);
  98 +// String type = "normal";
  99 +// taskService.addComment(task.getId(), instance.getProcessInstanceId(), type,
  100 +// String.format("%s 发起流程申请", user.getNickname()));
  101 +// // TODO 芋艿:应该不用下面两个步骤
  102 +//// taskService.setAssignee(task.getId(), String.valueOf(userId));
  103 +//// taskService.complete(task.getId(), variables);
  104 +// }
91 return instance.getId(); 105 return instance.getId();
92 } 106 }
93 107
94 - public void getMyProcessInstancePage(Long userId) {  
95 - HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()  
96 - .startedBy(String.valueOf(userId)) // 发起人是自己  
97 - .orderByProcessInstanceStartTime().desc(); // 按照发起时间倒序 108 + @Override
  109 + @Transactional(rollbackFor = Exception.class)
  110 + public void cancelProcessInstance(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO) {
  111 + // 校验流程实例存在
  112 + ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
  113 + if (instance == null) {
  114 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
  115 + }
  116 + // 只能取消自己的
  117 + if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
  118 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
  119 + }
  120 +
  121 + // 通过删除流程实例,实现流程实例的取消
  122 + runtimeService.deleteProcessInstance(cancelReqVO.getId(), cancelReqVO.getReason());
  123 + }
  124 +
  125 + @Override
  126 + public void deleteProcessInstance(String id, String reason) {
  127 + runtimeService.deleteProcessInstance(id, reason);
  128 + }
  129 +
  130 + @Override
  131 + @Transactional(rollbackFor = Exception.class)
  132 + public void updateProcessInstanceResult(String id, Integer result) {
  133 + // 删除流程实例,以实现驳回任务时,取消整个审批流程
  134 + if (Objects.equals(result, BpmProcessInstanceResultEnum.REJECT.getResult())) {
  135 + deleteProcessInstance(id, BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.getReason());
  136 + }
  137 + // 更新 status + result
  138 + processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(id)
  139 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()).setResult(result));
  140 + }
  141 +
  142 + @Override
  143 + public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,
  144 + BpmProcessInstanceMyPageReqVO pageReqVO) {
  145 + // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
  146 + PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
  147 + if (CollUtil.isEmpty(pageResult.getList())) {
  148 + return new PageResult<>(pageResult.getTotal());
  149 + }
  150 +
  151 + // 获得流程 Task Map
  152 + List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
  153 + Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
  154 + // 转换返回
  155 + return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
  156 + }
  157 +
  158 + @Override
  159 + public List<ProcessInstance> getProcessInstances(Set<String> ids) {
  160 + return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
  161 + }
  162 +
  163 + @Override
  164 + public ProcessInstance getProcessInstance(String id) {
  165 + return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
  166 + }
  167 +
  168 + /**
  169 + * 获得历史的流程实例
  170 + *
  171 + * @param id 流程实例的编号
  172 + * @return 历史的流程实例
  173 + */
  174 + @Override
  175 + public HistoricProcessInstance getHistoricProcessInstance(String id) {
  176 + return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
  177 + }
  178 +
  179 + @Override
  180 + public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
  181 + return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
  182 + }
  183 +
  184 + @Override
  185 + public void createProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance) {
  186 + // 获得流程定义
  187 + ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
  188 + // 插入 BpmProcessInstanceExtDO 对象
  189 + BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
  190 + .setCategory(definition.getCategory())
  191 + .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
  192 + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  193 + processInstanceExtMapper.insert(instanceExtDO);
  194 + }
  195 +
  196 + @Override
  197 + public void updateProcessInstanceExt(org.activiti.api.process.model.ProcessInstance instance) {
  198 + BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance);
  199 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
  200 + }
  201 +
  202 + @Override
  203 + public void updateProcessInstanceExtCancel(org.activiti.api.process.model.ProcessInstance instance) {
  204 + BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
  205 + .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
  206 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
  207 + .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
  208 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
  209 + }
  210 +
  211 + @Override
  212 + public void updateProcessInstanceExtComplete(org.activiti.api.process.model.ProcessInstance instance) {
  213 + BpmProcessInstanceExtDO instanceExtDO = BpmProcessInstanceConvert.INSTANCE.convert(instance)
  214 + .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
  215 + .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
  216 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
  217 + processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
98 } 218 }
99 219
100 } 220 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java
@@ -2,19 +2,20 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; @@ -2,19 +2,20 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.io.IoUtil; 4 import cn.hutool.core.io.IoUtil;
5 -import cn.iocoder.yudao.adminserver.modules.bpm.controller.workflow.vo.*;  
6 -import cn.iocoder.yudao.adminserver.modules.bpm.convert.workflow.TaskConvert; 5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*;
  7 +import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert;
  8 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
  9 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper;
  10 +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
  11 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
7 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; 12 import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
  13 +import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  14 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 15 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 16 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
10 -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 17 +import cn.iocoder.yudao.framework.common.util.object.PageUtils;
11 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
12 -import org.activiti.api.runtime.shared.query.Page;  
13 -import org.activiti.api.runtime.shared.query.Pageable;  
14 -import org.activiti.api.task.model.Task;  
15 -import org.activiti.api.task.model.builders.ClaimTaskPayloadBuilder;  
16 -import org.activiti.api.task.model.builders.TaskPayloadBuilder;  
17 -import org.activiti.api.task.runtime.TaskRuntime;  
18 import org.activiti.bpmn.constants.BpmnXMLConstants; 19 import org.activiti.bpmn.constants.BpmnXMLConstants;
19 import org.activiti.bpmn.model.BpmnModel; 20 import org.activiti.bpmn.model.BpmnModel;
20 import org.activiti.bpmn.model.FlowNode; 21 import org.activiti.bpmn.model.FlowNode;
@@ -22,100 +23,210 @@ import org.activiti.bpmn.model.SequenceFlow; @@ -22,100 +23,210 @@ import org.activiti.bpmn.model.SequenceFlow;
22 import org.activiti.engine.HistoryService; 23 import org.activiti.engine.HistoryService;
23 import org.activiti.engine.RepositoryService; 24 import org.activiti.engine.RepositoryService;
24 import org.activiti.engine.RuntimeService; 25 import org.activiti.engine.RuntimeService;
  26 +import org.activiti.engine.TaskService;
25 import org.activiti.engine.history.HistoricActivityInstance; 27 import org.activiti.engine.history.HistoricActivityInstance;
26 import org.activiti.engine.history.HistoricProcessInstance; 28 import org.activiti.engine.history.HistoricProcessInstance;
  29 +import org.activiti.engine.history.HistoricTaskInstance;
  30 +import org.activiti.engine.history.HistoricTaskInstanceQuery;
27 import org.activiti.engine.repository.ProcessDefinition; 31 import org.activiti.engine.repository.ProcessDefinition;
28 import org.activiti.engine.runtime.ProcessInstance; 32 import org.activiti.engine.runtime.ProcessInstance;
29 import org.activiti.engine.task.Comment; 33 import org.activiti.engine.task.Comment;
  34 +import org.activiti.engine.task.Task;
  35 +import org.activiti.engine.task.TaskQuery;
30 import org.activiti.image.ProcessDiagramGenerator; 36 import org.activiti.image.ProcessDiagramGenerator;
  37 +import org.springframework.context.annotation.Lazy;
31 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
32 import org.springframework.transaction.annotation.Transactional; 39 import org.springframework.transaction.annotation.Transactional;
33 import org.springframework.util.ObjectUtils; 40 import org.springframework.util.ObjectUtils;
34 41
35 import javax.annotation.Resource; 42 import javax.annotation.Resource;
  43 +import javax.validation.Valid;
36 import java.io.IOException; 44 import java.io.IOException;
37 import java.io.InputStream; 45 import java.io.InputStream;
38 -import java.util.ArrayList;  
39 -import java.util.List;  
40 -import java.util.Map;  
41 -import java.util.Optional;  
42 -import java.util.stream.Collectors;  
43 -  
44 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.HIGHLIGHT_IMG_ERROR;  
45 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;  
46 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 46 +import java.util.*;
47 47
  48 +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
  49 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  50 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  51 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  52 +
  53 +/**
  54 + * 流程任务 Service 实现类
  55 + *
  56 + * @author jason
  57 + * @author 芋道源码
  58 + */
48 @Slf4j 59 @Slf4j
49 @Service 60 @Service
50 public class BpmTaskServiceImpl implements BpmTaskService { 61 public class BpmTaskServiceImpl implements BpmTaskService {
51 62
52 @Resource 63 @Resource
53 - private TaskRuntime taskRuntime;  
54 - 64 + private TaskService taskService;
55 @Resource 65 @Resource
56 - private org.activiti.engine.TaskService activitiTaskService;  
57 - 66 + private RuntimeService runtimeService;
58 @Resource 67 @Resource
59 private HistoryService historyService; 68 private HistoryService historyService;
60 -  
61 @Resource 69 @Resource
62 private RepositoryService repositoryService; 70 private RepositoryService repositoryService;
63 71
64 @Resource 72 @Resource
65 - private RuntimeService runtimeService; 73 + private ProcessDiagramGenerator processDiagramGenerator;
66 74
67 @Resource 75 @Resource
68 - private ProcessDiagramGenerator processDiagramGenerator; 76 + private SysUserService userService;
  77 + @Resource
  78 + @Lazy // 解决循环依赖
  79 + private BpmProcessInstanceService processInstanceService;
  80 +
  81 + @Resource
  82 + private BpmTaskExtMapper taskExtMapper;
69 83
70 @Override 84 @Override
71 - public PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO) {  
72 - // TODO @jason:封装一个方法,用于转换成 activiti 的分页对象  
73 - final Pageable pageable = Pageable.of((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), pageReqVO.getPageSize());  
74 - Page<Task> pageTasks = taskRuntime.tasks(pageable);  
75 - int totalItems = pageTasks.getTotalItems();  
76 - List<Task> tasks = pageTasks.getContent();  
77 - final List<TodoTaskRespVO> respVOList = tasks.stream().map(task -> {  
78 - ProcessDefinition definition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());  
79 - return TaskConvert.INSTANCE.convert(task, definition);  
80 - }).collect(Collectors.toList());  
81 - return new PageResult<>(respVOList, (long)totalItems); 85 + public List<Task> getTasksByProcessInstanceId(String processInstanceId) {
  86 + return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
82 } 87 }
83 88
  89 + @Override
  90 + public List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds) {
  91 + if (CollUtil.isEmpty(processInstanceIds)) {
  92 + return Collections.emptyList();
  93 + }
  94 + return taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
  95 + }
84 96
85 @Override 97 @Override
86 - public void claimTask(String taskId) {  
87 - taskRuntime.claim(new ClaimTaskPayloadBuilder()  
88 - .withTaskId(taskId)  
89 - .withAssignee(SecurityFrameworkUtils.getLoginUser().getUsername())  
90 - .build()); 98 + public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
  99 + // 查询待办任务
  100 + TaskQuery taskQuery = taskService.createTaskQuery()
  101 + .taskAssignee(String.valueOf(userId)) // 分配给自己
  102 + .orderByTaskCreateTime().desc(); // 创建时间倒序
  103 + if (StrUtil.isNotBlank(pageVO.getName())) {
  104 + taskQuery.taskNameLike("%" + pageVO.getName() + "%");
  105 + }
  106 + if (pageVO.getBeginCreateTime() != null) {
  107 + taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
  108 + }
  109 + if (pageVO.getEndCreateTime() != null) {
  110 + taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
  111 + }
  112 + // 执行查询
  113 + List<Task> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  114 + if (CollUtil.isEmpty(tasks)) {
  115 + return PageResult.empty(taskQuery.count());
  116 + }
  117 +
  118 + // 获得 ProcessInstance Map
  119 + Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
  120 + convertSet(tasks, Task::getProcessInstanceId));
  121 + // 获得 User Map
  122 + Map<Long, SysUserDO> userMap = userService.getUserMap(
  123 + convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
  124 + // 拼接结果
  125 + return new PageResult<>(BpmTaskConvert.INSTANCE.convertList(tasks, processInstanceMap, userMap),
  126 + taskQuery.count());
91 } 127 }
92 128
  129 + @Override
  130 + public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
  131 + // 查询已办任务
  132 + HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
  133 + .finished() // 已完成
  134 + .taskAssignee(String.valueOf(userId)) // 分配给自己
  135 + .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
  136 + if (StrUtil.isNotBlank(pageVO.getName())) {
  137 + taskQuery.taskNameLike("%" + pageVO.getName() + "%");
  138 + }
  139 + if (pageVO.getBeginCreateTime() != null) {
  140 + taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
  141 + }
  142 + if (pageVO.getEndCreateTime() != null) {
  143 + taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
  144 + }
  145 + // 执行查询
  146 + List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
  147 + if (CollUtil.isEmpty(tasks)) {
  148 + return PageResult.empty(taskQuery.count());
  149 + }
93 150
  151 + // 获得 TaskExtDO Map
  152 + List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
  153 + Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
  154 + // 获得 ProcessInstance Map
  155 + Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
  156 + convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
  157 + // 获得 User Map
  158 + Map<Long, SysUserDO> userMap = userService.getUserMap(
  159 + convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
  160 + // 拼接结果
  161 + return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
  162 + taskQuery.count());
  163 + }
94 164
95 @Override 165 @Override
96 - @Transactional  
97 - public void completeTask(TaskReqVO taskReq) {  
98 - final Task task = taskRuntime.task(taskReq.getTaskId()); 166 + public void updateTaskAssign(String id, Long userId) {
  167 + taskService.setAssignee(id, String.valueOf(userId));
  168 + }
  169 +
  170 + @Override
  171 + @Transactional(rollbackFor = Exception.class)
  172 + public void approveTask(BpmTaskApproveReqVO reqVO) {
  173 + // 校验任务存在
  174 + Task task = getTask(reqVO.getId());
  175 + if (task == null) {
  176 + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
  177 + }
  178 + // 校验流程实例存在
  179 + ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  180 + if (instance == null) {
  181 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  182 + }
99 183
100 - activitiTaskService.addComment(taskReq.getTaskId(), task.getProcessInstanceId(), taskReq.getComment()); 184 + // 完成任务,审批通过
  185 + taskService.complete(task.getId(), instance.getProcessVariables()); // TODO 芋艿:variables 的选择
  186 + // 更新任务拓展表为通过
  187 + taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
  188 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setComment(reqVO.getComment()));
101 189
102 - taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskReq.getTaskId())  
103 - .withVariables(taskReq.getVariables())  
104 - .build()); 190 + // TODO 芋艿:添加评论
  191 +// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
105 } 192 }
106 193
  194 + @Override
  195 + @Transactional(rollbackFor = Exception.class)
  196 + public void rejectTask(@Valid BpmTaskRejectReqVO reqVO) {
  197 + // 校验任务存在
  198 + Task task = getTask(reqVO.getId());
  199 + if (task == null) {
  200 + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
  201 + }
  202 + // 校验流程实例存在
  203 + ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  204 + if (instance == null) {
  205 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  206 + }
  207 +
  208 + // 更新流程实例为不通过
  209 + processInstanceService.updateProcessInstanceResult(instance.getProcessInstanceId(),
  210 + BpmProcessInstanceResultEnum.REJECT.getResult());
107 211
  212 + // 更新任务拓展表为不通过
  213 + taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
  214 + .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
  215 +
  216 + // TODO 芋艿:添加评论
  217 +// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
  218 + }
108 219
109 @Override 220 @Override
110 public TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery) { 221 public TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery) {
111 - TaskHandleVO handleVO = new TaskHandleVO();  
112 - final Task task = taskRuntime.task(taskQuery.getTaskId());  
113 - List<TaskStepVO> steps = getTaskSteps(task.getProcessInstanceId());  
114 - handleVO.setHistoryTask(steps);  
115 - return handleVO; 222 +// TaskHandleVO handleVO = new TaskHandleVO();
  223 +// final Task task = taskRuntime.task(taskQuery.getTaskId());
  224 +// List<TaskStepVO> steps = getTaskSteps(task.getProcessInstanceId());
  225 +// handleVO.setHistoryTask(steps);
  226 +// return handleVO;
  227 + return null;
116 } 228 }
117 229
118 -  
119 private List<TaskStepVO> getTaskSteps(String processInstanceId) { 230 private List<TaskStepVO> getTaskSteps(String processInstanceId) {
120 // 获得已完成的活动 231 // 获得已完成的活动
121 List<HistoricActivityInstance> finished = historyService.createHistoricActivityInstanceQuery() 232 List<HistoricActivityInstance> finished = historyService.createHistoricActivityInstanceQuery()
@@ -126,10 +237,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -126,10 +237,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
126 // 获得对应的步骤 237 // 获得对应的步骤
127 List<TaskStepVO> steps = new ArrayList<>(); 238 List<TaskStepVO> steps = new ArrayList<>();
128 finished.forEach(instance -> { 239 finished.forEach(instance -> {
129 - TaskStepVO stepVO = TaskConvert.INSTANCE.convert(instance); 240 + TaskStepVO stepVO = BpmTaskConvert.INSTANCE.convert(instance);
130 stepVO.setStatus(1); // TODO @jason:1 这个 magic number 要枚举起来。 241 stepVO.setStatus(1); // TODO @jason:1 这个 magic number 要枚举起来。
131 // TODO @jason:可以考虑把 comments 读取后,在统一调用 convert 拼接。另外 Comment 是废弃的类,有没其它可以使用的哈? 242 // TODO @jason:可以考虑把 comments 读取后,在统一调用 convert 拼接。另外 Comment 是废弃的类,有没其它可以使用的哈?
132 - List<Comment> comments = activitiTaskService.getTaskComments(instance.getTaskId()); 243 + List<Comment> comments = taskService.getTaskComments(instance.getTaskId());
133 if (!CollUtil.isEmpty(comments)) { 244 if (!CollUtil.isEmpty(comments)) {
134 stepVO.setComment(Optional.ofNullable(comments.get(0)).map(Comment::getFullMessage).orElse("")); 245 stepVO.setComment(Optional.ofNullable(comments.get(0)).map(Comment::getFullMessage).orElse(""));
135 } 246 }
@@ -144,7 +255,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -144,7 +255,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
144 .unfinished().list(); 255 .unfinished().list();
145 // 获得对应的步骤 256 // 获得对应的步骤
146 for (HistoricActivityInstance instance : unfinished) { 257 for (HistoricActivityInstance instance : unfinished) {
147 - TaskStepVO stepVO = TaskConvert.INSTANCE.convert(instance); 258 + TaskStepVO stepVO = BpmTaskConvert.INSTANCE.convert(instance);
148 stepVO.setComment(""); 259 stepVO.setComment("");
149 stepVO.setStatus(0); 260 stepVO.setStatus(0);
150 steps.add(stepVO); 261 steps.add(stepVO);
@@ -159,12 +270,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -159,12 +270,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
159 } 270 }
160 271
161 @Override 272 @Override
162 - public TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery) {  
163 - final Task task = taskRuntime.task(taskQuery.getTaskId());  
164 - return TaskConvert.INSTANCE.convert(task);  
165 - }  
166 -  
167 - @Override  
168 public FileResp getHighlightImg(String processInstanceId) { 273 public FileResp getHighlightImg(String processInstanceId) {
169 // 查询历史 274 // 查询历史
170 //TODO 云扬四海 貌似流程结束后,点击审批进度会报错 275 //TODO 云扬四海 貌似流程结束后,点击审批进度会报错
@@ -172,7 +277,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -172,7 +277,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
172 HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); 277 HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
173 // 如果不存在实例。 说明数据异常 278 // 如果不存在实例。 说明数据异常
174 if (hpi == null) { 279 if (hpi == null) {
175 - throw exception(PROCESS_INSTANCE_NOT_EXISTS); 280 +// throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  281 + throw new RuntimeException("不存在");
176 } 282 }
177 // 如果有结束时间 返回model的流程图 283 // 如果有结束时间 返回model的流程图
178 if (!ObjectUtils.isEmpty(hpi.getEndTime())) { 284 if (!ObjectUtils.isEmpty(hpi.getEndTime())) {
@@ -285,4 +391,41 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -285,4 +391,41 @@ public class BpmTaskServiceImpl implements BpmTaskService {
285 } 391 }
286 return highLightedFlowIds; 392 return highLightedFlowIds;
287 } 393 }
  394 +
  395 + private Task getTask(String id) {
  396 + return taskService.createTaskQuery().taskId(id).singleResult();
  397 + }
  398 +
  399 + // ========== Task 拓展表相关 ==========
  400 +
  401 + @Override
  402 + public void createTaskExt(org.activiti.api.task.model.Task task) {
  403 + // 插入 BpmTaskExtDO 记录
  404 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task)
  405 + .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
  406 + taskExtMapper.insert(taskExtDO);
  407 + }
  408 +
  409 + @Override
  410 + public void updateTaskExt(org.activiti.api.task.model.Task task) {
  411 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task);
  412 + taskExtMapper.updateByTaskId(taskExtDO);
  413 + }
  414 +
  415 + @Override
  416 + public void updateTaskExtCancel(org.activiti.api.task.model.Task task) {
  417 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task)
  418 + .setEndTime(new Date()) // 由于 Task 里没有办法拿到 endTime,所以这里设置
  419 + .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
  420 + taskExtMapper.updateByTaskId(taskExtDO);
  421 + }
  422 +
  423 + @Override
  424 + public void updateTaskExtComplete(org.activiti.api.task.model.Task task) {
  425 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert(task)
  426 + .setEndTime(task.getCompletedDate())
  427 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
  428 + taskExtMapper.updateByTaskId(taskExtDO);
  429 + }
  430 +
288 } 431 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/listener/BpmProcessInstanceEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.service.task.listener;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
  5 +import org.activiti.api.model.shared.event.RuntimeEvent;
  6 +import org.activiti.api.process.model.ProcessInstance;
  7 +import org.activiti.api.process.model.events.ProcessRuntimeEvent;
  8 +import org.activiti.api.process.runtime.events.listener.ProcessEventListener;
  9 +import org.activiti.api.process.runtime.events.listener.ProcessRuntimeEventListener;
  10 +import org.activiti.api.task.model.events.TaskRuntimeEvent;
  11 +import org.springframework.context.annotation.Lazy;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import javax.annotation.Resource;
  15 +
  16 +/**
  17 + * 监听 {@link ProcessInstance} 的开始与完成,创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@Component
  22 +public class BpmProcessInstanceEventListener<T extends RuntimeEvent<?, ?>>
  23 + implements ProcessRuntimeEventListener<T> {
  24 +
  25 + @Resource
  26 + @Lazy // 解决循环依赖
  27 + private BpmProcessInstanceService processInstanceService;
  28 +
  29 + @Override
  30 + @SuppressWarnings("unchecked")
  31 + public void onEvent(T rawEvent) {
  32 + // 由于 ProcessRuntimeEventListener 无法保证只监听 ProcessRuntimeEvent 事件,所以通过这样的方式
  33 + if (!(rawEvent instanceof ProcessRuntimeEvent)) {
  34 + return;
  35 + }
  36 + ProcessRuntimeEvent<ProcessInstance> event = (ProcessRuntimeEvent<ProcessInstance>) rawEvent;
  37 +
  38 + // 创建时,插入拓展表
  39 + if (event.getEventType() == ProcessRuntimeEvent.ProcessEvents.PROCESS_CREATED) {
  40 + processInstanceService.createProcessInstanceExt(event.getEntity());
  41 + return;
  42 + }
  43 + // 取消时,更新拓展表为取消
  44 + if (event.getEventType() == ProcessRuntimeEvent.ProcessEvents.PROCESS_CANCELLED) {
  45 + processInstanceService.updateProcessInstanceExtCancel(event.getEntity());
  46 + return;
  47 + }
  48 + // 完成时,更新拓展表为已完成
  49 + if (event.getEventType() == ProcessRuntimeEvent.ProcessEvents.PROCESS_COMPLETED) {
  50 + processInstanceService.updateProcessInstanceExtComplete(event.getEntity());
  51 + return;
  52 + }
  53 +
  54 + // 其它事件,进行更新拓展表
  55 + processInstanceService.updateProcessInstanceExt(event.getEntity());
  56 + }
  57 +
  58 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/listener/BpmTackActivitiEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.service.task.listener;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
  5 +import org.activiti.api.process.runtime.events.listener.ProcessRuntimeEventListener;
  6 +import org.activiti.api.task.runtime.events.listener.TaskEventListener;
  7 +import org.activiti.engine.delegate.event.ActivitiEvent;
  8 +import org.activiti.engine.delegate.event.ActivitiEventListener;
  9 +import org.activiti.engine.delegate.event.ActivitiEventType;
  10 +import org.activiti.engine.delegate.event.impl.ActivitiEntityEventImpl;
  11 +import org.activiti.engine.impl.persistence.entity.TaskEntity;
  12 +import org.activiti.engine.repository.ProcessDefinition;
  13 +import org.springframework.context.annotation.Lazy;
  14 +import org.springframework.stereotype.Component;
  15 +
  16 +import javax.annotation.Resource;
  17 +
  18 +/**
  19 + * 监听 {@link TaskEntity} 相关的事件,设置相关属性。
  20 + * 目的:解决 {@link TaskEventListener} 无法解决的场景
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Component
  25 +public class BpmTackActivitiEventListener implements ActivitiEventListener {
  26 +
  27 + @Resource
  28 + @Lazy // 解决循环依赖
  29 + private BpmProcessDefinitionService processDefinitionService;
  30 +
  31 + @Override
  32 + public void onEvent(ActivitiEvent event) {
  33 + // Task 创建时,设置其分类,解决 TaskService 未提供 name 的设置方法
  34 + if (ActivitiEventType.TASK_CREATED == event.getType()) {
  35 + TaskEntity task = ((TaskEntity) ((ActivitiEntityEventImpl) event).getEntity());
  36 + if (StrUtil.isNotEmpty(task.getCategory())) {
  37 + return;
  38 + }
  39 + // 设置 name
  40 + ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition2(task.getProcessDefinitionId());
  41 + if (processDefinition == null) {
  42 + return;
  43 + }
  44 + task.setCategory(processDefinition.getCategory());
  45 + }
  46 + }
  47 +
  48 + @Override
  49 + public boolean isFailOnException() {
  50 + return true;
  51 + }
  52 +
  53 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/listener/BpmTaskEventListener.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.service.task.listener;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
  5 +import org.activiti.api.task.model.Task;
  6 +import org.activiti.api.task.model.events.TaskRuntimeEvent;
  7 +import org.activiti.api.task.runtime.events.listener.TaskEventListener;
  8 +import org.springframework.context.annotation.Lazy;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import javax.annotation.Resource;
  12 +
  13 +/**
  14 + * 监听 {@link Task} 的开始与完成,创建与更新对应的 {@link BpmTaskExtDO} 记录
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@Component
  19 +public class BpmTaskEventListener<T extends TaskRuntimeEvent<? extends Task>>
  20 + implements TaskEventListener<T> {
  21 +
  22 + @Resource
  23 + @Lazy // 解决循环依赖
  24 + private BpmTaskService taskService;
  25 +
  26 + @Override
  27 + public void onEvent(T event) {
  28 + // 创建时,插入拓展表
  29 + if (event.getEventType() == TaskRuntimeEvent.TaskEvents.TASK_CREATED) {
  30 + taskService.createTaskExt(event.getEntity());
  31 + return;
  32 + }
  33 +
  34 + // 取消时,更新拓展表为取消
  35 + if (event.getEventType() == TaskRuntimeEvent.TaskEvents.TASK_CANCELLED) {
  36 + taskService.updateTaskExtCancel(event.getEntity());
  37 + return;
  38 + }
  39 + // 完成时,更新拓展表为已完成。要注意,在调用 delete ProcessInstance 才会触发该逻辑
  40 + if (event.getEventType() == TaskRuntimeEvent.TaskEvents.TASK_COMPLETED) {
  41 + taskService.updateTaskExtComplete(event.getEntity());
  42 + return;
  43 + }
  44 +
  45 + // 其它事件,进行更新拓展表
  46 + taskService.updateTaskExt(event.getEntity());
  47 + }
  48 +
  49 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java
@@ -176,6 +176,9 @@ public class SysUserServiceImpl implements SysUserService { @@ -176,6 +176,9 @@ public class SysUserServiceImpl implements SysUserService {
176 176
177 @Override 177 @Override
178 public List<SysUserDO> getUsers(Collection<Long> ids) { 178 public List<SysUserDO> getUsers(Collection<Long> ids) {
  179 + if (CollUtil.isEmpty(ids)) {
  180 + return Collections.emptyList();
  181 + }
179 return userMapper.selectBatchIds(ids); 182 return userMapper.selectBatchIds(ids);
180 } 183 }
181 184
yudao-admin-ui/package.json
@@ -85,7 +85,7 @@ @@ -85,7 +85,7 @@
85 "@vue/compiler-sfc": "^3.0.1", 85 "@vue/compiler-sfc": "^3.0.1",
86 "@vue/eslint-config-prettier": "^5.0.0", 86 "@vue/eslint-config-prettier": "^5.0.0",
87 "axios": "^0.21.1", 87 "axios": "^0.21.1",
88 - "bpmn-js": "^7.4.0", 88 + "bpmn-js": "^8.8.3",
89 "bpmn-js-properties-panel": "^0.37.2", 89 "bpmn-js-properties-panel": "^0.37.2",
90 "camunda-bpmn-moddle": "^4.4.1", 90 "camunda-bpmn-moddle": "^4.4.1",
91 "compression-webpack-plugin": "^6.1.1", 91 "compression-webpack-plugin": "^6.1.1",
yudao-admin-ui/src/api/bpm/definition.js
@@ -8,6 +8,14 @@ export function getProcessDefinitionPage(query) { @@ -8,6 +8,14 @@ export function getProcessDefinitionPage(query) {
8 }) 8 })
9 } 9 }
10 10
  11 +export function getProcessDefinitionList(query) {
  12 + return request({
  13 + url: '/bpm/process-definition/list',
  14 + method: 'get',
  15 + params: query
  16 + })
  17 +}
  18 +
11 export function getProcessDefinitionBpmnXML(id) { 19 export function getProcessDefinitionBpmnXML(id) {
12 return request({ 20 return request({
13 url: '/bpm/process-definition/get-bpmn-xml?id=' + id, 21 url: '/bpm/process-definition/get-bpmn-xml?id=' + id,
yudao-admin-ui/src/api/bpm/processInstance.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function getMyProcessInstancePage(query) {
  4 + return request({
  5 + url: '/bpm/process-instance/my-page',
  6 + method: 'get',
  7 + params: query
  8 + })
  9 +}
  10 +
  11 +export function createProcessInstance(data) {
  12 + return request({
  13 + url: '/bpm/process-instance/create',
  14 + method: 'POST',
  15 + data: data
  16 + })
  17 +}
  18 +
  19 +export function cancelProcessInstance(id, reason) {
  20 + return request({
  21 + url: '/bpm/process-instance/cancel',
  22 + method: 'DELETE',
  23 + data: {
  24 + id,
  25 + reason
  26 + }
  27 + })
  28 +}
yudao-admin-ui/src/api/bpm/task.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function getTodoTaskPage(query) {
  4 + return request({
  5 + url: '/bpm/task/todo-page',
  6 + method: 'get',
  7 + params: query
  8 + })
  9 +}
  10 +
  11 +export function getDoneTaskPage(query) {
  12 + return request({
  13 + url: '/bpm/task/done-page',
  14 + method: 'get',
  15 + params: query
  16 + })
  17 +}
  18 +
  19 +export function completeTask(data) {
  20 + return request({
  21 + url: '/bpm/task/complete',
  22 + method: 'PUT',
  23 + data: data
  24 + })
  25 +}
  26 +
  27 +export function approveTask(data) {
  28 + return request({
  29 + url: '/bpm/task/approve',
  30 + method: 'PUT',
  31 + data: data
  32 + })
  33 +}
  34 +
  35 +export function rejectTask(data) {
  36 + return request({
  37 + url: '/bpm/task/reject',
  38 + method: 'PUT',
  39 + data: data
  40 + })
  41 +}
yudao-admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js
@@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
14 // paletteProvider: ["type", PaletteProvider] 14 // paletteProvider: ["type", PaletteProvider]
15 // }; 15 // };
16 16
17 -// custom/index.js  
18 import CustomPalette from "./CustomPalette"; 17 import CustomPalette from "./CustomPalette";
19 18
20 export default { 19 export default {
yudao-admin-ui/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
1 <template> 1 <template>
2 <div class="panel-tab__content"> 2 <div class="panel-tab__content">
3 <el-form size="mini" label-width="90px" :model="model" :rules="rules" @submit.native.prevent> 3 <el-form size="mini" label-width="90px" :model="model" :rules="rules" @submit.native.prevent>
4 - <el-form-item label="流程标识" prop="key">  
5 - <el-input v-model="model.key" placeholder="请输入流标标识"  
6 - :disabled="model.id !== undefined && model.id.length > 0" @change="handleKeyUpdate" />  
7 - </el-form-item>  
8 - <el-form-item label="流程名称" prop="name">  
9 - <el-input v-model="model.name" placeholder="请输入流程名称" clearable @change="handleNameUpdate" />  
10 - </el-form-item>  
11 - <el-form-item label="流程分类" prop="category">  
12 - <el-select v-model="model.category" placeholder="请选择流程分类" clearable style="width: 100%">  
13 - <el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>  
14 - </el-select>  
15 - </el-form-item>  
16 - <el-form-item label="流程表单" prop="formId">  
17 - <el-select v-model="model.formId" placeholder="请选择流程表单,非必选哟!" clearable style="width: 100%">  
18 - <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>  
19 - </el-select>  
20 - </el-form-item>  
21 - <el-form-item label="流程描述" prop="description">  
22 - <el-input type="textarea" v-model="model.description" clearable @change="handleDescriptionUpdate" />  
23 - </el-form-item> 4 + <div v-if="elementBaseInfo.$type === 'bpmn:Process'"> <!-- 如果是 Process 信息的时候,使用自定义表单 -->
  5 + <el-form-item label="流程标识" prop="key">
  6 + <el-input v-model="model.key" placeholder="请输入流标标识"
  7 + :disabled="model.id !== undefined && model.id.length > 0" @change="handleKeyUpdate" />
  8 + </el-form-item>
  9 + <el-form-item label="流程名称" prop="name">
  10 + <el-input v-model="model.name" placeholder="请输入流程名称" clearable @change="handleNameUpdate" />
  11 + </el-form-item>
  12 + <el-form-item label="流程分类" prop="category">
  13 + <el-select v-model="model.category" placeholder="请选择流程分类" clearable style="width: 100%">
  14 + <el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
  15 + </el-select>
  16 + </el-form-item>
  17 + <el-form-item label="流程表单" prop="formId">
  18 + <el-select v-model="model.formId" placeholder="请选择流程表单,非必选哟!" clearable style="width: 100%">
  19 + <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>
  20 + </el-select>
  21 + </el-form-item>
  22 + <el-form-item label="流程描述" prop="description">
  23 + <el-input type="textarea" v-model="model.description" clearable @change="handleDescriptionUpdate" />
  24 + </el-form-item>
  25 + </div>
  26 + <div v-else>
  27 + <el-form-item label="ID">
  28 + <el-input v-model="elementBaseInfo.id" clearable @change="updateBaseInfo('id')"/>
  29 + </el-form-item>
  30 + <el-form-item label="名称">
  31 + <el-input v-model="elementBaseInfo.name" clearable @change="updateBaseInfo('name')" />
  32 + </el-form-item>
  33 + </div>
24 </el-form> 34 </el-form>
25 </div> 35 </div>
26 </template> 36 </template>
yudao-admin-ui/src/components/parser/Parser.vue
@@ -173,8 +173,13 @@ export default { @@ -173,8 +173,13 @@ export default {
173 submitForm() { 173 submitForm() {
174 this.$refs[this.formConf.formRef].validate(valid => { 174 this.$refs[this.formConf.formRef].validate(valid => {
175 if (!valid) return false 175 if (!valid) return false
176 - // 触发sumit事件  
177 - this.$emit('submit', this[this.formConf.formModel]) 176 + // 触发 submit 事件
  177 + // update by 芋道源码
  178 + // this.$emit('submit', this[this.formConf.formModel])
  179 + this.$emit('submit', {
  180 + conf: this.formConfCopy,
  181 + values: this[this.formConf.formModel]
  182 + })
178 return true 183 return true
179 }) 184 })
180 } 185 }
yudao-admin-ui/src/router/index.js
@@ -188,6 +188,18 @@ export const constantRoutes = [ @@ -188,6 +188,18 @@ export const constantRoutes = [
188 meta: { title: '流程定义' } 188 meta: { title: '流程定义' }
189 } 189 }
190 ] 190 ]
  191 + }, {
  192 + path: '/bpm',
  193 + component: Layout,
  194 + hidden: true,
  195 + children: [
  196 + {
  197 + path: 'process-instance/create',
  198 + component: (resolve) => require(['@/views/bpm/processInstance/create'], resolve),
  199 + name: '发起流程',
  200 + meta: { title: '发起流程' }
  201 + }
  202 + ]
191 }, 203 },
192 ] 204 ]
193 205
yudao-admin-ui/src/utils/dateUtils.js 0 → 100644
  1 +/**
  2 + * 将毫秒,转换成时间字符串。例如说,xx 分钟
  3 + *
  4 + * @param ms 毫秒
  5 + * @returns {string} 字符串
  6 + */
  7 +export function getDate(ms) {
  8 + const day = Math.floor(ms / (24 * 60 * 60 * 1000));
  9 + const hour = Math.floor((ms / (60 * 60 * 1000) - day * 24));
  10 + const minute = Math.floor(((ms / (60 * 1000)) - day * 24 * 60 - hour * 60));
  11 + const second = Math.floor((ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60));
  12 + if (day > 0) {
  13 + return day + "天" + hour + "小时" + minute + "分钟";
  14 + }
  15 + if (hour > 0) {
  16 + return hour + "小时" + minute + "分钟";
  17 + }
  18 + if (minute > 0) {
  19 + return minute + "分钟";
  20 + }
  21 + if (second > 0) {
  22 + return second + "秒";
  23 + } else {
  24 + return 0 + "秒";
  25 + }
  26 +}
yudao-admin-ui/src/utils/dict.js
@@ -36,6 +36,8 @@ export const DICT_TYPE = { @@ -36,6 +36,8 @@ export const DICT_TYPE = {
36 36
37 // bpm 37 // bpm
38 BPM_MODEL_CATEGORY: 'bpm_model_category', 38 BPM_MODEL_CATEGORY: 'bpm_model_category',
  39 + BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status',
  40 + BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result',
39 OA_LEAVE_STATUS: 'flow_status', 41 OA_LEAVE_STATUS: 'flow_status',
40 OA_LEAVE_TYPE: 'oa_leave_type' 42 OA_LEAVE_TYPE: 'oa_leave_type'
41 } 43 }
yudao-admin-ui/src/views/bpm/definition/index.vue
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 <el-tag size="medium" type="warning" v-else>未部署</el-tag> 29 <el-tag size="medium" type="warning" v-else>未部署</el-tag>
30 </template> 30 </template>
31 </el-table-column> 31 </el-table-column>
32 - <el-table-column label="激活状态" align="center" prop="version" width="80"> 32 + <el-table-column label="状态" align="center" prop="version" width="80">
33 <template slot-scope="scope"> 33 <template slot-scope="scope">
34 <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag> 34 <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
35 <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag> 35 <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
yudao-admin-ui/src/views/bpm/model/modelEditor.vue
@@ -175,17 +175,8 @@ export default { @@ -175,17 +175,8 @@ export default {
175 175
176 .my-process-designer { 176 .my-process-designer {
177 height: calc(100vh - 84px); 177 height: calc(100vh - 84px);
178 - //height: 800px !important; // TODO 芋艿:bjs 容器的高度不对,临时改下  
179 - //z-index: 0 !important;  
180 - //pointer-events: none !important;  
181 } 178 }
182 -.process-panel__container { // TODO 芋艿:右边的位置不对,临时改下  
183 - //margin-top: -800px !important;  
184 - //float: right;  
185 - //margin-left: 800px !important;  
186 - //height: 800px;  
187 - //z-index: 2147483647 !important;  
188 - //cursor:pointer !important; 179 +.process-panel__container {
189 position: absolute; 180 position: absolute;
190 right: 0; 181 right: 0;
191 top: 55px; 182 top: 55px;
yudao-admin-ui/src/views/bpm/processInstance/create.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 + <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
  4 + <div v-if="!selectProcessInstance">
  5 + <el-table v-loading="loading" :data="list">
  6 + <el-table-column label="流程名称" align="center" prop="name" width="200">
  7 + <template slot-scope="scope">
  8 + <el-button type="text" @click="handleBpmnDetail(scope.row)">
  9 + <span>{{ scope.row.name }}</span>
  10 + </el-button>
  11 + </template>
  12 + </el-table-column>
  13 + <el-table-column label="流程分类" align="center" prop="category" width="100">
  14 + <template slot-scope="scope">
  15 + <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>
  16 + </template>
  17 + </el-table-column>
  18 + <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
  19 + <template slot-scope="scope">
  20 + <el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
  21 + </template>
  22 + </el-table-column>
  23 + <el-table-column label="流程描述" align="center" prop="description" width="300" show-overflow-tooltip />
  24 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  25 + <template slot-scope="scope">
  26 + <el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(scope.row)">选择</el-button>
  27 + </template>
  28 + </el-table-column>
  29 + </el-table>
  30 + </div>
  31 + <!-- 第二步,填写表单,进行流程的提交 -->
  32 + <div v-else>
  33 + <el-card class="box-card" >
  34 + <div slot="header" class="clearfix">
  35 + <span class="el-icon-document">{{ selectProcessInstance.name }}</span>
  36 + <el-button style="float: right;" type="primary" @click="selectProcessInstance = undefined">选择其它流程</el-button>
  37 + </div>
  38 + <el-col :span="16" :offset="6">
  39 + <div>
  40 + <parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
  41 + </div>
  42 + </el-col>
  43 + </el-card>
  44 + <el-card class="box-card">
  45 + <div slot="header" class="clearfix">
  46 + <span class="el-icon-picture-outline">流程图</span>
  47 + </div>
  48 + <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
  49 + </el-card>
  50 + </div>
  51 +
  52 + </div>
  53 +</template>
  54 +
  55 +<script>
  56 +import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition";
  57 +import {DICT_TYPE, getDictDatas} from "@/utils/dict";
  58 +import {getForm} from "@/api/bpm/form";
  59 +import {decodeFields} from "@/utils/formGenerator";
  60 +import Parser from '@/components/parser/Parser'
  61 +import {createProcessInstance} from "@/api/bpm/processInstance";
  62 +
  63 +export default {
  64 + name: "processDefinition",
  65 + components: {
  66 + Parser
  67 + },
  68 + data() {
  69 + return {
  70 + // 遮罩层
  71 + loading: true,
  72 + // 总条数
  73 + total: 0,
  74 + // 表格数据
  75 + list: [],
  76 +
  77 + // 流程表单详情
  78 + detailForm: {
  79 + fields: []
  80 + },
  81 +
  82 + // BPMN 数据
  83 + bpmnXML: null,
  84 + bpmnControlForm: {
  85 + prefix: "activiti"
  86 + },
  87 +
  88 + // 流程表单
  89 + selectProcessInstance: undefined, // 选择的流程实例
  90 +
  91 + // 数据字典
  92 + categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
  93 + };
  94 + },
  95 + created() {
  96 + this.getList();
  97 + },
  98 + methods: {
  99 + /** 查询流程定义列表 */
  100 + getList() {
  101 + this.loading = true;
  102 + getProcessDefinitionList({
  103 + suspensionState: 1
  104 + }).then(response => {
  105 + this.list = response.data
  106 + this.loading = false
  107 + }
  108 + );
  109 + },
  110 + /** 处理选择流程的按钮操作 **/
  111 + handleSelect(row) {
  112 + // 如果无表单,则无法发起流程
  113 + if (!row.formId) {
  114 + this.$message.error('该流程未绑定表单,无法发起流程!请重新选择你要发起的流程');
  115 + return;
  116 + }
  117 + // 设置选择的流程
  118 + this.selectProcessInstance = row;
  119 +
  120 + // 加载对应的表单
  121 + getForm(row.formId).then(response => {
  122 + // 设置值
  123 + const data = response.data
  124 + this.detailForm = {
  125 + ...JSON.parse(data.conf),
  126 + fields: decodeFields(data.fields)
  127 + }
  128 + });
  129 +
  130 + // 加载流程图
  131 + getProcessDefinitionBpmnXML(row.id).then(response => {
  132 + this.bpmnXML = response.data
  133 + })
  134 + },
  135 + /** 提交按钮 */
  136 + submitForm(params) {
  137 + if (!params) {
  138 + return;
  139 + }
  140 + // 设置表单禁用
  141 + const conf = params.conf;
  142 + conf.disabled = true; // 表单禁用
  143 + conf.formBtns = false; // 按钮隐藏
  144 +
  145 + // 提交表单,创建流程
  146 + const variables = params.values;
  147 + createProcessInstance({
  148 + processDefinitionId: this.selectProcessInstance.id,
  149 + variables: variables
  150 + }).then(response => {
  151 + this.msgSuccess("发起流程成功");
  152 + // 关闭当前窗口
  153 + this.$store.dispatch("tagsView/delView", this.$route);
  154 + this.$router.go(-1);
  155 + }).catch(() => {
  156 + conf.disabled = false; // 表单开启
  157 + conf.formBtns = true; // 按钮展示
  158 + })
  159 + },
  160 + }
  161 +};
  162 +</script>
  163 +
  164 +<style lang="scss">
  165 +.my-process-designer {
  166 + height: calc(100vh - 200px);
  167 +}
  168 +
  169 +.box-card {
  170 + width: 100%;
  171 + margin-bottom: 20px;
  172 +}
  173 +</style>
yudao-admin-ui/src/views/bpm/processInstance/index.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="流程名" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="所属流程" prop="processDefinitionId">
  10 + <el-input v-model="queryParams.processDefinitionId" placeholder="请输入流程定义的编号" clearable size="small" @keyup.enter.native="handleQuery"/>
  11 + </el-form-item>
  12 + <el-form-item label="流程分类" prop="category">
  13 + <el-select v-model="queryParams.category" placeholder="请选择流程分类" clearable size="small">
  14 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY)"
  15 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  16 + </el-select>
  17 + </el-form-item>
  18 + <el-form-item label="提交时间">
  19 + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  20 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  21 + </el-form-item>
  22 + <el-form-item label="状态" prop="status">
  23 + <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
  24 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
  25 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  26 + </el-select>
  27 + </el-form-item>
  28 + <el-form-item label="结果" prop="result">
  29 + <el-select v-model="queryParams.result" placeholder="请选择流结果" clearable size="small">
  30 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
  31 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  32 + </el-select>
  33 + </el-form-item>
  34 + <el-form-item>
  35 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  36 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  37 + </el-form-item>
  38 + </el-form>
  39 +
  40 + <!-- 操作工具栏 -->
  41 + <el-row :gutter="10" class="mb8">
  42 + <el-col :span="1.5">
  43 + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">发起流程</el-button>
  44 + </el-col>
  45 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  46 + </el-row>
  47 +
  48 + <!-- 列表 -->
  49 + <el-table v-loading="loading" :data="list">
  50 + <el-table-column label="编号" align="center" prop="id" width="320" />
  51 + <el-table-column label="流程名" align="center" prop="name" />
  52 + <el-table-column label="流程分类" align="center" prop="category">
  53 + <template slot-scope="scope">
  54 + <span>{{ getDictDataLabel(DICT_TYPE.BPM_MODEL_CATEGORY, scope.row.category) }}</span>
  55 + </template>
  56 + </el-table-column>
  57 + <el-table-column label="当前审批任务" align="center" prop="tasks">
  58 + <template slot-scope="scope">
  59 + <el-button v-for="task in scope.row.tasks" type="text" @click="handleFormDetail(task.id)">
  60 + <span>{{ task.name }}</span>
  61 + </el-button>
  62 + </template>
  63 + </el-table-column>
  64 + <el-table-column label="状态" align="center" prop="status">
  65 + <template slot-scope="scope">
  66 + <span>
  67 + <el-tag type="primary" v-if="scope.row.status === 1"> <!-- 进行中 -->
  68 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, scope.row.status) }}
  69 + </el-tag>
  70 + <el-tag type="success" v-if="scope.row.status === 2"> <!-- 已结束 -->
  71 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, scope.row.status) }}
  72 + </el-tag>
  73 + </span>
  74 + </template>
  75 + </el-table-column>
  76 + <el-table-column label="结果" align="center" prop="result">
  77 + <template slot-scope="scope">
  78 + <span>
  79 + <el-tag type="primary" v-if="scope.row.result === 1"> <!-- 进行中 -->
  80 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  81 + </el-tag>
  82 + <el-tag type="success" v-if="scope.row.result === 2"> <!-- 通过 -->
  83 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  84 + </el-tag>
  85 + <el-tag type="danger" v-if="scope.row.result === 3"> <!-- 不通过 -->
  86 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  87 + </el-tag>
  88 + <el-tag type="info" v-if="scope.row.result === 4"> <!-- 撤回 -->
  89 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  90 + </el-tag>
  91 + </span>
  92 + </template>
  93 + </el-table-column>
  94 + <el-table-column label="提交时间" align="center" prop="createTime" width="180">
  95 + <template slot-scope="scope">
  96 + <span>{{ parseTime(scope.row.createTime) }}</span>
  97 + </template>
  98 + </el-table-column>
  99 + <el-table-column label="结束时间" align="center" prop="createTime" width="180">
  100 + <template slot-scope="scope">
  101 + <span>{{ parseTime(scope.row.endTime) }}</span>
  102 + </template>
  103 + </el-table-column>
  104 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  105 + <template slot-scope="scope">
  106 + <!-- TODO 芋艿:权限 -->
  107 + <el-button type="text" size="small" icon="el-icon-delete" v-if="scope.row.result === 1"
  108 + @click="handleCancel(scope.row)">取消</el-button>
  109 + </template>
  110 + </el-table-column>
  111 + </el-table>
  112 + <!-- 分页组件 -->
  113 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  114 + @pagination="getList"/>
  115 +
  116 + </div>
  117 +</template>
  118 +
  119 +<script>
  120 +import {
  121 + getMyProcessInstancePage,
  122 + createProcessInstanceExt,
  123 + updateProcessInstanceExt,
  124 + deleteProcessInstanceExt,
  125 + getProcessInstanceExt,
  126 + getProcessInstanceExtPage,
  127 + exportProcessInstanceExtExcel, cancelProcessInstance
  128 +} from "@/api/bpm/processInstance";
  129 +import {deleteErrorCode} from "@/api/system/errorCode";
  130 +
  131 +export default {
  132 + name: "ProcessInstanceExt",
  133 + components: {
  134 + },
  135 + data() {
  136 + return {
  137 + // 遮罩层
  138 + loading: true,
  139 + // 显示搜索条件
  140 + showSearch: true,
  141 + // 总条数
  142 + total: 0,
  143 + // 工作流的流程实例的拓展列表
  144 + list: [],
  145 + // 是否显示弹出层
  146 + dateRangeCreateTime: [],
  147 + // 查询参数
  148 + queryParams: {
  149 + pageNo: 1,
  150 + pageSize: 10,
  151 + name: null,
  152 + processDefinitionId: null,
  153 + category: null,
  154 + status: null,
  155 + result: null,
  156 + }
  157 + };
  158 + },
  159 + created() {
  160 + this.getList();
  161 + },
  162 + methods: {
  163 + /** 查询列表 */
  164 + getList() {
  165 + this.loading = true;
  166 + // 处理查询参数
  167 + let params = {...this.queryParams};
  168 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  169 + // 执行查询
  170 + getMyProcessInstancePage(params).then(response => {
  171 + this.list = response.data.list;
  172 + this.total = response.data.total;
  173 + this.loading = false;
  174 + });
  175 + },
  176 + /** 搜索按钮操作 */
  177 + handleQuery() {
  178 + this.queryParams.pageNo = 1;
  179 + this.getList();
  180 + },
  181 + /** 重置按钮操作 */
  182 + resetQuery() {
  183 + this.dateRangeCreateTime = [];
  184 + this.resetForm("queryForm");
  185 + this.handleQuery();
  186 + },
  187 + /** 新增按钮操作 **/
  188 + handleAdd() {
  189 + this.$router.push({ path: "/bpm/process-instance/create"})
  190 + },
  191 + /** 取消按钮操作 */
  192 + handleCancel(row) {
  193 + const id = row.id;
  194 + this.$prompt('请输出取消原因?', "取消流程", {
  195 + type: 'warning',
  196 + confirmButtonText: "确定",
  197 + cancelButtonText: "取消",
  198 + inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, // 判断非空,且非空格
  199 + inputErrorMessage: "取消原因不能为空",
  200 + }).then(({ value }) => {
  201 + return cancelProcessInstance(id, value);
  202 + }).then(() => {
  203 + this.getList();
  204 + this.msgSuccess("取消成功");
  205 + })
  206 + },
  207 + }
  208 +};
  209 +</script>
yudao-admin-ui/src/views/bpm/task/done.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="流程名" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="创建时间">
  10 + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  11 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  12 + </el-form-item>
  13 + <el-form-item>
  14 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  15 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  16 + </el-form-item>
  17 + </el-form>
  18 +
  19 + <!-- 列表 -->
  20 + <el-table v-loading="loading" :data="list">
  21 + <el-table-column label="任务编号" align="center" prop="id" width="320" fixed />
  22 + <el-table-column label="任务名称" align="center" prop="name" width="200" />
  23 + <el-table-column label="所属流程" align="center" prop="processInstance.name" width="200" />
  24 + <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
  25 + <el-table-column label="结果" align="center" prop="result">
  26 + <template slot-scope="scope">
  27 + <span>
  28 + <el-tag type="primary" v-if="scope.row.result === 1"> <!-- 进行中 -->
  29 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  30 + </el-tag>
  31 + <el-tag type="success" v-if="scope.row.result === 2"> <!-- 通过 -->
  32 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  33 + </el-tag>
  34 + <el-tag type="danger" v-if="scope.row.result === 3"> <!-- 不通过 -->
  35 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  36 + </el-tag>
  37 + <el-tag type="info" v-if="scope.row.result === 4"> <!-- 撤回 -->
  38 + {{ getDictDataLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, scope.row.result) }}
  39 + </el-tag>
  40 + </span>
  41 + </template>
  42 + </el-table-column>
  43 + <el-table-column label="审批意见" align="center" prop="comment" width="200" />
  44 + <el-table-column label="创建时间" align="center" prop="createTime" width="180">
  45 + <template slot-scope="scope">
  46 + <span>{{ parseTime(scope.row.createTime) }}</span>
  47 + </template>
  48 + </el-table-column>
  49 + <el-table-column label="审批时间" align="center" prop="endTime" width="180">
  50 + <template slot-scope="scope">
  51 + <span>{{ parseTime(scope.row.endTime) }}</span>
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column label="耗时" align="center" prop="durationInMillis" width="180">
  55 + <template slot-scope="scope">
  56 + <span>{{ getDateStar(scope.row.durationInMillis) }}</span>
  57 + </template>
  58 + </el-table-column>
  59 + <!-- TODO 耗时 -->
  60 + <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
  61 + <template slot-scope="scope">
  62 + <!-- TODO 权限、颜色 -->
  63 + <el-button size="mini" type="text" icon="el-icon-edit">详情</el-button>
  64 + </template>
  65 + </el-table-column>
  66 + </el-table>
  67 + <!-- 分页组件 -->
  68 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  69 + @pagination="getList"/>
  70 +
  71 + </div>
  72 +</template>
  73 +
  74 +<script>
  75 +import {getDoneTaskPage} from '@/api/bpm/task'
  76 +import {getDate} from "@/utils/dateUtils";
  77 +
  78 +export default {
  79 + name: "Done",
  80 + components: {
  81 + },
  82 + data() {
  83 + return {
  84 + // 遮罩层
  85 + loading: true,
  86 + // 显示搜索条件
  87 + showSearch: true,
  88 + // 总条数
  89 + total: 0,
  90 + // 待办任务列表
  91 + list: [],
  92 + // 查询参数
  93 + dateRangeCreateTime: [],
  94 + queryParams: {
  95 + pageNo: 1,
  96 + pageSize: 10,
  97 + name: null,
  98 + },
  99 + };
  100 + },
  101 + created() {
  102 + this.getList();
  103 + },
  104 + methods: {
  105 + /** 查询列表 */
  106 + getList() {
  107 + this.loading = true;
  108 + // 处理查询参数
  109 + let params = {...this.queryParams};
  110 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  111 + getDoneTaskPage(params).then(response => {
  112 + this.list = response.data.list;
  113 + this.total = response.data.total;
  114 + this.loading = false;
  115 + });
  116 + },
  117 + /** 搜索按钮操作 */
  118 + handleQuery() {
  119 + this.queryParams.pageNo = 1;
  120 + this.getList();
  121 + },
  122 + /** 重置按钮操作 */
  123 + resetQuery() {
  124 + this.dateRangeCreateTime = [];
  125 + this.resetForm("queryForm");
  126 + this.handleQuery();
  127 + },
  128 + getDateStar(ms) {
  129 + return getDate(ms);
  130 + }
  131 + }
  132 +};
  133 +</script>
yudao-admin-ui/src/views/bpm/task/todo.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="流程名" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="创建时间">
  10 + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  11 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  12 + </el-form-item>
  13 + <el-form-item>
  14 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  15 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  16 + </el-form-item>
  17 + </el-form>
  18 +
  19 + <!-- 列表 -->
  20 + <el-table v-loading="loading" :data="list">
  21 + <el-table-column label="任务编号" align="center" prop="id" width="320" />
  22 + <el-table-column label="任务名称" align="center" prop="name" />
  23 + <el-table-column label="所属流程" align="center" prop="processInstance.name" />
  24 + <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
  25 + <el-table-column label="创建时间" align="center" prop="createTime" width="180">
  26 + <template slot-scope="scope">
  27 + <span>{{ parseTime(scope.row.createTime) }}</span>
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column label="状态" align="center" prop="version" width="80">
  31 + <template slot-scope="scope">
  32 + <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
  33 + <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
  34 + </template>
  35 + </el-table-column>
  36 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  37 + <template slot-scope="scope">
  38 + <!-- TODO 权限、颜色 -->
  39 + <el-button size="mini" type="text" icon="el-icon-edit">审批</el-button>
  40 + <el-button size="mini" type="text" icon="el-icon-edit" @click="audit(scope.row, true)">通过</el-button>
  41 + <el-button size="mini" type="text" icon="el-icon-edit" @click="audit(scope.row, false)">不通过</el-button>
  42 + <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.suspensionState === 2">激活</el-button>
  43 + <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.suspensionState === 1">挂起</el-button>
  44 + </template>
  45 + </el-table-column>
  46 + </el-table>
  47 + <!-- 分页组件 -->
  48 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  49 + @pagination="getList"/>
  50 +
  51 + </div>
  52 +</template>
  53 +
  54 +<script>
  55 +import {approveTask, getTodoTaskPage, rejectTask} from '@/api/bpm/task'
  56 +
  57 +export default {
  58 + name: "Todo",
  59 + components: {
  60 + },
  61 + data() {
  62 + return {
  63 + // 遮罩层
  64 + loading: true,
  65 + // 显示搜索条件
  66 + showSearch: true,
  67 + // 总条数
  68 + total: 0,
  69 + // 待办任务列表
  70 + list: [],
  71 + // 查询参数
  72 + dateRangeCreateTime: [],
  73 + queryParams: {
  74 + pageNo: 1,
  75 + pageSize: 10,
  76 + name: null,
  77 + },
  78 + };
  79 + },
  80 + created() {
  81 + this.getList();
  82 + },
  83 + methods: {
  84 + /** 查询列表 */
  85 + getList() {
  86 + this.loading = true;
  87 + // 处理查询参数
  88 + let params = {...this.queryParams};
  89 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  90 + getTodoTaskPage(params).then(response => {
  91 + this.list = response.data.list;
  92 + this.total = response.data.total;
  93 + this.loading = false;
  94 + });
  95 + },
  96 + /** 搜索按钮操作 */
  97 + handleQuery() {
  98 + this.queryParams.pageNo = 1;
  99 + this.getList();
  100 + },
  101 + /** 重置按钮操作 */
  102 + resetQuery() {
  103 + this.dateRangeCreateTime = [];
  104 + this.resetForm("queryForm");
  105 + this.handleQuery();
  106 + },
  107 + audit(row, pass) {
  108 + if (pass) {
  109 + approveTask({
  110 + id: row.id,
  111 + comment: '通过'
  112 + })
  113 + } else {
  114 + rejectTask({
  115 + id: row.id,
  116 + comment: '不通过'
  117 + })
  118 + }
  119 + }
  120 + }
  121 +};
  122 +</script>
yudao-admin-ui/src/views/oa/todo/index.vue deleted
1 -<template>  
2 - <div class="app-container">  
3 -  
4 - <!-- 搜索工作栏 -->  
5 - <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">  
6 - <el-form-item label="状态" prop="status">  
7 - <el-select v-model="queryParams.status" placeholder="请选择状态">  
8 - <el-option  
9 - v-for="dict in leaveStatusData"  
10 - :key="parseInt(dict.value)"  
11 - :label="dict.label"  
12 - :value="parseInt(dict.value)"  
13 - />  
14 - </el-select>  
15 - </el-form-item>  
16 - <el-form-item>  
17 - <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>  
18 - <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>  
19 - </el-form-item>  
20 - </el-form>  
21 -  
22 -  
23 -  
24 - <!-- 列表 -->  
25 - <el-table v-loading="loading" :data="list">  
26 - <el-table-column label="任务Id" align="center" prop="id" />  
27 - <el-table-column label="流程名称" align="center" prop="processName" />  
28 - <el-table-column label="任务状态" align="center" :formatter="statusFormat" prop="status" />  
29 - <el-table-column label="操作" align="center" class-name="small-padding fixed-width">  
30 - <template slot-scope="scope">  
31 - <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.status == 1" @click="handleClaim(scope.row)">签收</el-button>  
32 - <el-button size="mini" type="text" icon="el-icon-edit" v-if="scope.row.status == 2" @click="getTaskFormKey(scope.row)">办理</el-button>  
33 - </template>  
34 - </el-table-column>  
35 - </el-table>  
36 - <!-- 分页组件 -->  
37 - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"  
38 - @pagination="getList"/>  
39 -  
40 - <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>  
41 - <el-tabs tab-position="left" style="height: 500px;">  
42 - <el-tab-pane label="详情">  
43 - <el-form ref="form" :model="handleTask.formObject" label-width="80px">  
44 - <el-form-item label="状态" >  
45 - {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_STATUS, handleTask.formObject.status) }}  
46 - </el-form-item>  
47 - <el-form-item label="申请人id" >{{handleTask.formObject.userId}}</el-form-item>  
48 - <el-form-item label="开始时间" >{{ parseTime(handleTask.formObject.startTime) }}</el-form-item>  
49 - <el-form-item label="结束时间" prop="endTime">{{ parseTime(handleTask.formObject.endTime) }}</el-form-item>  
50 - <el-form-item label="请假类型" prop="leaveType">  
51 - {{ getDictDataLabel(DICT_TYPE.OA_LEAVE_TYPE, handleTask.formObject.leaveType) }}  
52 - </el-form-item>  
53 - <el-form-item label="原因" prop="reason">{{handleTask.formObject.reason}}</el-form-item>  
54 - <el-form-item label="申请时间" prop="applyTime">{{ parseTime(handleTask.formObject.applyTime) }}</el-form-item>  
55 - </el-form>  
56 - </el-tab-pane>  
57 - <el-tab-pane label="任务处理">  
58 - <el-steps :active="handleTask.historyTask.length-1" simple finish-status="success">  
59 - <el-step :title="item.stepName" icon="el-icon-edit" v-for="(item) in handleTask.historyTask" ></el-step>  
60 - </el-steps>  
61 - <br/>  
62 - <el-steps direction="vertical" :active="handleTask.historyTask.length-1" finish-status="success" space="60px">  
63 - <el-step :title="item.stepName" :description="item.comment" v-for="(item) in handleTask.historyTask" ></el-step>  
64 - </el-steps>  
65 - <br/>  
66 - <el-form ref="taskForm" :model="task" label-width="80px" v-show="handleTask.taskVariable !=''">  
67 - <el-form-item label="处理意见" prop="approved">  
68 - <el-select v-model="task.approved" placeholder="处理意见">  
69 - <el-option  
70 - v-for="dict in approvedData"  
71 - :key="parseInt(dict.value)"  
72 - :label="dict.label"  
73 - :value="parseInt(dict.value)"  
74 - />  
75 - </el-select>  
76 - </el-form-item>  
77 - <el-input  
78 - type="textarea"  
79 - :rows="2"  
80 - v-model="task.comment">  
81 - </el-input>  
82 - </el-form>  
83 - <br/>  
84 - <el-button type="primary" @click="submitTask">提交</el-button>  
85 - </el-tab-pane>  
86 - </el-tabs>  
87 - </el-dialog>  
88 - </div>  
89 -</template>  
90 -  
91 -<script>  
92 -import { completeTask, taskSteps, getTaskFormKey,deleteLeave, getLeave, getTodoTaskPage, claimTask } from "@/api/oa/todo";  
93 -import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict'  
94 -export default {  
95 - name: "Todo",  
96 - components: {  
97 - },  
98 - data() {  
99 - return {  
100 - // 遮罩层  
101 - loading: true,  
102 - // 显示搜索条件  
103 - showSearch: true,  
104 - // 总条数  
105 - total: 0,  
106 - // 请假申请列表  
107 - list: [],  
108 - // 弹出层标题  
109 - title: "",  
110 - // 是否显示弹出层  
111 - open: false,  
112 - // 查询参数  
113 - queryParams: {  
114 - pageNo: 1,  
115 - pageSize: 10  
116 - },  
117 - // 表单参数  
118 - form: {},  
119 - handleTask: {  
120 - historyTask:[{  
121 - stepName:"步骤一"  
122 - }  
123 - ],  
124 - taskVariable: "",  
125 - formObject: {}  
126 - },  
127 - steps:[{  
128 - stepName:"步骤一"  
129 - }],  
130 - task: {  
131 - approved : 1,  
132 - variables: {},  
133 - taskId: undefined,  
134 - comment: ""  
135 - },  
136 - rules: {  
137 - },  
138 - leaveTypeDictData: getDictDatas(DICT_TYPE.OA_LEAVE_TYPE),  
139 - leaveStatusData: getDictDatas(DICT_TYPE.OA_LEAVE_STATUS),  
140 - approvedData: [  
141 - {  
142 - value: 1,  
143 - label: '同意'  
144 - },  
145 - {  
146 - value: 0,  
147 - label: '不同意'  
148 - }  
149 - ]  
150 - };  
151 - },  
152 - created() {  
153 - this.getList();  
154 - },  
155 - methods: {  
156 - /** 查询列表 */  
157 - getList() {  
158 - this.loading = true;  
159 - // 处理查询参数  
160 - let params = {...this.queryParams};  
161 - // 执行查询  
162 - getTodoTaskPage(params).then(response => {  
163 - this.list = response.data.list;  
164 - this.total = response.data.total;  
165 - this.loading = false;  
166 - });  
167 - },  
168 - /** 取消按钮 */  
169 - cancel() {  
170 - this.open = false;  
171 - this.reset();  
172 - },  
173 - /** 表单重置 */  
174 - reset() {  
175 - this.form = {  
176 - id: undefined,  
177 - processInstanceId: undefined,  
178 - status: undefined,  
179 - userId: undefined,  
180 - startTime: undefined,  
181 - endTime: undefined,  
182 - leaveType: undefined,  
183 - reason: undefined,  
184 - applyTime: undefined,  
185 - };  
186 - this.resetForm("form");  
187 - },  
188 -  
189 - statusFormat(row, column) {  
190 - return row.status == 1 ? "未签收" : "已签收";  
191 - },  
192 - /** 搜索按钮操作 */  
193 - handleQuery() {  
194 - this.queryParams.pageNo = 1;  
195 - this.getList();  
196 - },  
197 - /** 重置按钮操作 */  
198 - resetQuery() {  
199 - this.dateRangeStartTime = [];  
200 - this.dateRangeEndTime = [];  
201 - this.dateRangeApplyTime = [];  
202 - this.resetForm("queryForm");  
203 - this.handleQuery();  
204 - },  
205 - getTaskFormKey(row) {  
206 - const taskId = row.id;  
207 - const data = {  
208 - taskId : taskId  
209 - }  
210 - getTaskFormKey(data).then(response => {  
211 - const resp = response.data;  
212 - const path = resp.formKey;  
213 - const taskId = resp.id;  
214 - const businessKey = resp.businessKey;  
215 - const route = {  
216 - path: path,  
217 - query: {  
218 - businessKey: businessKey,  
219 - taskId:taskId,  
220 - processInstanceId : resp.processInstanceId  
221 - }  
222 - }  
223 - this.$router.replace(route);  
224 - });  
225 - },  
226 - handleLeaveApprove(row) {  
227 - this.reset();  
228 - const businessKey = row.businessKey;  
229 - const taskId = row.id;  
230 - const processKey = row.processKey;  
231 - const data = {  
232 - taskId : taskId,  
233 - businessKey: businessKey,  
234 - processKey: processKey  
235 - }  
236 - taskSteps(data).then(response => {  
237 - this.form = {};  
238 - this.handleTask = response.data;  
239 - this.task.taskId = taskId;  
240 - this.open = true;  
241 - this.title = "任务办理";  
242 - });  
243 - },  
244 - /** 任务签收操作 */  
245 - handleClaim(row) {  
246 - this.reset();  
247 - const id = row.id;  
248 - claimTask(id).then(() => {  
249 - this.getList();  
250 - this.msgSuccess("签收成功");  
251 - });  
252 - },  
253 - /** 提交任务 */  
254 - submitTask() {  
255 - const taskVariableName = this.handleTask.taskVariable;  
256 - if (taskVariableName != "") {  
257 - if (this.task.approved == 1) {  
258 - this.task.variables[taskVariableName] = true;  
259 - }  
260 - if (this.task.approved == 0) {  
261 - this.task.variables[taskVariableName] = false;  
262 - }  
263 - }  
264 - completeTask(this.task).then(response => {  
265 - this.msgSuccess("执行任务成功");  
266 - this.open = false;  
267 - this.getList();  
268 - })  
269 - },  
270 - /** 删除按钮操作 */  
271 - handleDelete(row) {  
272 - const id = row.id;  
273 - this.$confirm('是否确认删除请假申请编号为"' + id + '"的数据项?', "警告", {  
274 - confirmButtonText: "确定",  
275 - cancelButtonText: "取消",  
276 - type: "warning"  
277 - }).then(function() {  
278 - return deleteLeave(id);  
279 - }).then(() => {  
280 - this.getList();  
281 - this.msgSuccess("删除成功");  
282 - })  
283 - }  
284 - }  
285 -};  
286 -</script>  
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
@@ -25,7 +25,9 @@ public interface WebFilterOrderEnum { @@ -25,7 +25,9 @@ public interface WebFilterOrderEnum {
25 25
26 // Spring Security Filter 默认为 -100,可见 org.springframework.boot.autoconfigure.security.SecurityProperties 配置属性类 26 // Spring Security Filter 默认为 -100,可见 org.springframework.boot.autoconfigure.security.SecurityProperties 配置属性类
27 27
28 - int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后 28 + int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面
  29 +
  30 + int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面
29 31
30 int DEMO_FILTER = Integer.MAX_VALUE; 32 int DEMO_FILTER = Integer.MAX_VALUE;
31 33
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageResult.java
@@ -35,4 +35,8 @@ public final class PageResult&lt;T&gt; implements Serializable { @@ -35,4 +35,8 @@ public final class PageResult&lt;T&gt; implements Serializable {
35 return new PageResult<>(0L); 35 return new PageResult<>(0L);
36 } 36 }
37 37
  38 + public static <T> PageResult<T> empty(Long total) {
  39 + return new PageResult<>(total);
  40 + }
  41 +
38 } 42 }
yudao-framework/yudao-spring-boot-starter-activiti/pom.xml
@@ -37,6 +37,14 @@ @@ -37,6 +37,14 @@
37 <artifactId>yudao-common</artifactId> 37 <artifactId>yudao-common</artifactId>
38 </dependency> 38 </dependency>
39 39
  40 + <!-- Web 相关 -->
  41 + <dependency>
  42 + <groupId>cn.iocoder.boot</groupId>
  43 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  44 + </dependency>
  45 +
  46 +
  47 +
40 <dependency> 48 <dependency>
41 <groupId>org.mybatis</groupId> 49 <groupId>org.mybatis</groupId>
42 <artifactId>mybatis</artifactId> 50 <artifactId>mybatis</artifactId>
@@ -72,6 +80,7 @@ @@ -72,6 +80,7 @@
72 <artifactId>activiti-image-generator</artifactId> 80 <artifactId>activiti-image-generator</artifactId>
73 <version>${activiti.version}</version> 81 <version>${activiti.version}</version>
74 </dependency> 82 </dependency>
  83 +
75 </dependencies> 84 </dependencies>
76 85
77 </project> 86 </project>
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java
1 package cn.iocoder.yudao.framework.activiti.config; 1 package cn.iocoder.yudao.framework.activiti.config;
2 2
  3 +import cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter;
  4 +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
3 import org.activiti.image.ProcessDiagramGenerator; 5 import org.activiti.image.ProcessDiagramGenerator;
4 import org.activiti.image.impl.DefaultProcessDiagramGenerator; 6 import org.activiti.image.impl.DefaultProcessDiagramGenerator;
5 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; 7 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
6 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.apache.ibatis.session.SqlSessionFactory;
  9 +import org.springframework.boot.web.servlet.FilterRegistrationBean;
7 import org.springframework.context.annotation.Bean; 10 import org.springframework.context.annotation.Bean;
8 import org.springframework.context.annotation.Configuration; 11 import org.springframework.context.annotation.Configuration;
9 12
@@ -26,4 +29,12 @@ public class YudaoActivitiConfiguration { @@ -26,4 +29,12 @@ public class YudaoActivitiConfiguration {
26 return springProcessEngineConfiguration -> springProcessEngineConfiguration.setSqlSessionFactory(sqlSessionFactory); 29 return springProcessEngineConfiguration -> springProcessEngineConfiguration.setSqlSessionFactory(sqlSessionFactory);
27 } 30 }
28 31
  32 + @Bean
  33 + public FilterRegistrationBean<ActivitiWebFilter> activitiWebFilter() {
  34 + FilterRegistrationBean<ActivitiWebFilter> registrationBean = new FilterRegistrationBean<>();
  35 + registrationBean.setFilter(new ActivitiWebFilter());
  36 + registrationBean.setOrder(WebFilterOrderEnum.ACTIVITI_FILTER);
  37 + return registrationBean;
  38 + }
  39 +
29 } 40 }
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.activiti.core.util;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import com.alibaba.ttl.TransmittableThreadLocal;
  5 +import org.activiti.engine.history.HistoricProcessInstance;
  6 +import org.activiti.engine.impl.identity.Authentication;
  7 +import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntityImpl;
  8 +import org.activiti.engine.impl.persistence.entity.HistoricScopeInstanceEntityImpl;
  9 +
  10 +/**
  11 + * Activiti 工具类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +public class ActivitiUtils {
  16 +
  17 + static {
  18 + setAuthenticationThreadLocal();
  19 + }
  20 +
  21 + // ========== Authentication 相关 ==========
  22 +
  23 + /**
  24 + * 反射修改 Authentication 的 authenticatedUserIdThreadLocal 静态变量,使用 TTL 线程变量
  25 + * 目的:保证 @Async 等异步执行时,变量丢失的问题
  26 + */
  27 + private static void setAuthenticationThreadLocal() {
  28 + ReflectUtil.setFieldValue(Authentication.class, "authenticatedUserIdThreadLocal",
  29 + new TransmittableThreadLocal<String>());
  30 + }
  31 +
  32 + public static void setAuthenticatedUserId(Long userId) {
  33 + Authentication.setAuthenticatedUserId(String.valueOf(userId));
  34 + }
  35 +
  36 + public static void clearAuthenticatedUserId() {
  37 + Authentication.setAuthenticatedUserId(null);
  38 + }
  39 +
  40 +}
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/web/ActivitiWebFilter.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.activiti.core.web;
  2 +
  3 +import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
  4 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  5 +import org.springframework.web.filter.OncePerRequestFilter;
  6 +
  7 +import javax.servlet.FilterChain;
  8 +import javax.servlet.ServletException;
  9 +import javax.servlet.http.HttpServletRequest;
  10 +import javax.servlet.http.HttpServletResponse;
  11 +import java.io.IOException;
  12 +
  13 +/**
  14 + * Activiti Web 过滤器,将 userId 设置到 {@link org.activiti.engine.impl.identity.Authentication} 中
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +public class ActivitiWebFilter extends OncePerRequestFilter {
  19 +
  20 + @Override
  21 + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
  22 + throws ServletException, IOException {
  23 + try {
  24 + // 设置工作流的用户
  25 + Long userId = SecurityFrameworkUtils.getLoginUserId();
  26 + if (userId != null) {
  27 + ActivitiUtils.setAuthenticatedUserId(userId);
  28 + }
  29 + // 过滤
  30 + chain.doFilter(request, response);
  31 + } finally {
  32 + // 清理
  33 + ActivitiUtils.clearAuthenticatedUserId();
  34 + }
  35 + }
  36 +
  37 +}
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject;
3 import com.baomidou.mybatisplus.annotation.FieldFill; 3 import com.baomidou.mybatisplus.annotation.FieldFill;
4 import com.baomidou.mybatisplus.annotation.TableField; 4 import com.baomidou.mybatisplus.annotation.TableField;
5 import com.baomidou.mybatisplus.annotation.TableLogic; 5 import com.baomidou.mybatisplus.annotation.TableLogic;
  6 +import lombok.Builder;
6 import lombok.Data; 7 import lombok.Data;
7 8
8 import java.io.Serializable; 9 import java.io.Serializable;
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
9 import com.baomidou.mybatisplus.core.metadata.IPage; 9 import com.baomidou.mybatisplus.core.metadata.IPage;
10 import org.apache.ibatis.annotations.Param; 10 import org.apache.ibatis.annotations.Param;
11 11
  12 +import java.util.Collection;
12 import java.util.List; 13 import java.util.List;
13 14
14 /** 15 /**
@@ -44,4 +45,8 @@ public interface BaseMapperX&lt;T&gt; extends BaseMapper&lt;T&gt; { @@ -44,4 +45,8 @@ public interface BaseMapperX&lt;T&gt; extends BaseMapper&lt;T&gt; {
44 return selectList(new QueryWrapper<T>().eq(field, value)); 45 return selectList(new QueryWrapper<T>().eq(field, value));
45 } 46 }
46 47
  48 + default List<T> selectList(String field, Collection<?> values) {
  49 + return selectList(new QueryWrapper<T>().in(field, values));
  50 + }
  51 +
47 } 52 }
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
@@ -98,15 +98,6 @@ public class SecurityFrameworkUtils { @@ -98,15 +98,6 @@ public class SecurityFrameworkUtils {
98 // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 98 // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
99 WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); 99 WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
100 WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); 100 WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
101 -// // TODO @jason:使用 userId 会不会更合适哈?  
102 -// // TODO @芋艿:activiti 需要使用 ttl 上下文  
103 -// // TODO @jason:清理问题  
104 -// if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) {  
105 -// org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());  
106 -// }  
107 -// // TODO @芋道源码 该值被赋值给 user task 中assignee , username 显示更直白一点  
108 -// // TODO @jason:有办法设置 userId,然后 activiti 有地方读取到 username 么?毕竟 username 只是 User 的登陆账号,并不能绝对像 userId 代表一个用户  
109 -// org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());  
110 } 101 }
111 102
112 } 103 }
更新日志.md
@@ -27,7 +27,11 @@ @@ -27,7 +27,11 @@
27 ### ⭐ New Features 27 ### ⭐ New Features
28 28
29 * 【优化】引入 form generator 0.2.0 版本,并重构相关代码 29 * 【优化】引入 form generator 0.2.0 版本,并重构相关代码
30 -* 【新增】新增流程表单,支持动态进行表单的配置 30 +* 【新增】流程表单,支持动态进行表单的配置
  31 +* 【新增】流程模型的管理,支持新增、导入、编辑、删除、发布流程模型
  32 +* 【新增】我的流程的管理,支持发起流程
  33 +* 【新增】待办任务的管理,支持任务的审批通过与不通过
  34 +* 【新增】已办任务的管理,支持详情的查看
31 * 【新增】引入 bpmn-process-designer 0.0.1 版本,提供流程设计器的能力 35 * 【新增】引入 bpmn-process-designer 0.0.1 版本,提供流程设计器的能力
32 36
33 ### 🐞 Bug Fixes 37 ### 🐞 Bug Fixes