Commit 2607f13abeb65f3ae7c2174ad3b9d8c4c0e362f7

Authored by YunaiV
1 parent bcdc117e

1. 新增流程新建的接口

yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.http 0 → 100644
  1 +### 请求 /login 接口 => 成功
  2 +POST {{baseUrl}}/bpm/process-instance/create
  3 +Content-Type: application/json
  4 +tenant-id: 1
  5 +Authorization: Bearer {{token}}
  6 +
  7 +{
  8 + "processDefinitionId": "leave:7:20ada39c-6c95-11ec-88b1-cacd34981f8e",
  9 + "variables": {
  10 + "a": 1,
  11 + "b": "2"
  12 + }
  13 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
  5 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import io.swagger.annotations.Api;
  7 +import io.swagger.annotations.ApiOperation;
  8 +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 +
  14 +import javax.annotation.Resource;
  15 +import javax.validation.Valid;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  18 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  19 +
  20 +@Api(tags = "流程实例") // 流程实例,通过流程定义创建的一次“申请”
  21 +@RestController
  22 +@RequestMapping("/bpm/process-instance")
  23 +@Validated
  24 +public class BpmProcessInstanceController {
  25 +
  26 + @Resource
  27 + private BpmProcessInstanceService processInstanceService;
  28 +
  29 + @PostMapping("/create")
  30 + @ApiOperation("新建流程实例")
  31 + public CommonResult<String> createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) {
  32 + return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO));
  33 + }
  34 +
  35 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCreateReqVO.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 java.util.Map;
  9 +
  10 +@ApiModel("流程实例的创建 Request VO")
  11 +@Data
  12 +//@EqualsAndHashCode(callSuper = true)
  13 +//@ToString(callSuper = true)
  14 +public class BpmProcessInstanceCreateReqVO {
  15 +
  16 + @ApiModelProperty(value = "流程定义的编号", required = true, example = "1024")
  17 + @NotEmpty(message = "流程定义编号不能为空")
  18 + private String processDefinitionId;
  19 +
  20 + @ApiModelProperty(value = "变量实例")
  21 + private Map<String, Object> variables;
  22 +
  23 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceMyPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +
  5 +public class BpmProcessInstanceMyPageReqVO extends PageParam {
  6 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
... ... @@ -31,9 +31,13 @@ public interface BpmErrorCodeConstants {
31 31 ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
32 32 ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
33 33 ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
  34 + ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态");
34 35  
35   - // ========== 动态表单模块 1-009-004-000 ==========
36   - ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009004000, "动态表单不存在");
37   - ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009004000, "表单项({}) 和 ({}) 使用了相同的字段名({})");
  36 + // ========== 流程实例 1-009-004-000 ==========
  37 +
  38 +
  39 + // ========== 动态表单模块 1-009-010-000 ==========
  40 + ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");
  41 + ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009010000, "表单项({}) 和 ({}) 使用了相同的字段名({})");
38 42  
39 43 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  4 +
  5 +import javax.validation.Valid;
  6 +
  7 +/**
  8 + * 流程实例 Service 接口
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public interface BpmProcessInstanceService {
  13 +
  14 + /**
  15 + * 创建流程实例
  16 + *
  17 + * @param userId 用户编号
  18 + * @param createReqVO 创建信息
  19 + * @return 实例的编号
  20 + */
  21 + String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
  22 +
  23 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
  6 +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
  7 +import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  8 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.activiti.engine.HistoryService;
  11 +import org.activiti.engine.RepositoryService;
  12 +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;
  16 +import org.activiti.engine.repository.ProcessDefinition;
  17 +import org.activiti.engine.runtime.ProcessInstance;
  18 +import org.activiti.engine.task.Task;
  19 +import org.springframework.stereotype.Service;
  20 +import org.springframework.validation.annotation.Validated;
  21 +
  22 +import javax.annotation.Resource;
  23 +import java.util.Map;
  24 +
  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;
  27 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  28 +
  29 +/**
  30 + * 流程实例 Service 实现类
  31 + *
  32 + * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
  33 + * 1. https://blog.csdn.net/bobozai86/article/details/105210414
  34 + *
  35 + * HistoricProcessInstance & ProcessInstance 的关系:
  36 + * 1.https://my.oschina.net/843294669/blog/719024
  37 + * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
  38 + *
  39 + * @author 芋道源码
  40 + */
  41 +@Service
  42 +@Validated
  43 +@Slf4j
  44 +public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
  45 +
  46 + @Resource
  47 + private RepositoryService repositoryService;
  48 + @Resource
  49 + private RuntimeService runtimeService;
  50 + @Resource
  51 + private TaskService taskService;
  52 + @Resource
  53 + private HistoryService historyService;
  54 +
  55 + @Resource
  56 + private SysUserService userService;
  57 + @Resource
  58 + private BpmProcessDefinitionService processDefinitionService;
  59 +
  60 + @Override
  61 + public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqVO createReqVO) {
  62 + // 校验流程定义
  63 + ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
  64 + if (definition == null) {
  65 + throw exception(PROCESS_DEFINITION_NOT_EXISTS);
  66 + }
  67 + if (definition.isSuspended()) {
  68 + throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
  69 + }
  70 +
  71 + // 设置流程发起人
  72 + Authentication.setAuthenticatedUserId(String.valueOf(userId));
  73 +
  74 + // 创建流程实例
  75 + Map<String, Object> variables = createReqVO.getVariables();
  76 + variables.put("INITIATOR", userId); // TODO 芋艿:初始化人员
  77 + ProcessInstance instance = runtimeService.startProcessInstanceById(createReqVO.getProcessDefinitionId(), variables);
  78 +
  79 + // 添加初始的评论 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 + }
  91 + return instance.getId();
  92 + }
  93 +
  94 + public void getMyProcessInstancePage(Long userId) {
  95 + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
  96 + .startedBy(String.valueOf(userId)) // 发起人是自己
  97 + .orderByProcessInstanceStartTime().desc(); // 按照发起时间倒序
  98 + }
  99 +
  100 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java
... ... @@ -108,6 +108,14 @@ public interface SysUserService {
108 108 PageResult<SysUserDO> getUserPage(SysUserPageReqVO reqVO);
109 109  
110 110 /**
  111 + * 获得用户
  112 + *
  113 + * @param id 用户编号
  114 + * @return 用户
  115 + */
  116 + SysUserDO getUser(Long id);
  117 +
  118 + /**
111 119 * 获得用户列表
112 120 *
113 121 * @param reqVO 列表请求
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java
... ... @@ -165,6 +165,11 @@ public class SysUserServiceImpl implements SysUserService {
165 165 }
166 166  
167 167 @Override
  168 + public SysUserDO getUser(Long id) {
  169 + return userMapper.selectById(id);
  170 + }
  171 +
  172 + @Override
168 173 public List<SysUserDO> getUsers(SysUserExportReqVO reqVO) {
169 174 return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
170 175 }
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
1 1 package cn.iocoder.yudao.framework.security.core.util;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 3 import cn.iocoder.yudao.framework.security.core.LoginUser;
5 4 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
6 5 import org.springframework.lang.Nullable;
... ... @@ -12,7 +11,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
12 11 import org.springframework.util.StringUtils;
13 12  
14 13 import javax.servlet.http.HttpServletRequest;
15   -import java.util.Objects;
16 14 import java.util.Set;
17 15  
18 16 /**
... ... @@ -100,15 +98,15 @@ public class SecurityFrameworkUtils {
100 98 // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
101 99 WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
102 100 WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
103   - // TODO @jason:使用 userId 会不会更合适哈?
104   - // TODO @芋艿:activiti 需要使用 ttl 上下文
105   - // TODO @jason:清理问题
106   - if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) {
107   - org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
108   - }
109   - // TODO @芋道源码 该值被赋值给 user task 中assignee , username 显示更直白一点
110   - // TODO @jason:有办法设置 userId,然后 activiti 有地方读取到 username 么?毕竟 username 只是 User 的登陆账号,并不能绝对像 userId 代表一个用户
111   - org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
  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());
112 110 }
113 111  
114 112 }
... ...