Commit 2607f13abeb65f3ae7c2174ad3b9d8c4c0e362f7
1 parent
bcdc117e
1. 新增流程新建的接口
Showing
10 changed files
with
229 additions
and
14 deletions
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
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 | } | ... | ... |