1. 新增流程新建的接口

This commit is contained in:
YunaiV 2022-01-04 08:27:22 +08:00
parent bcdc117e59
commit 2607f13abe
10 changed files with 229 additions and 14 deletions

View File

@ -0,0 +1,13 @@
### 请求 /login 接口 => 成功
POST {{baseUrl}}/bpm/process-instance/create
Content-Type: application/json
tenant-id: 1
Authorization: Bearer {{token}}
{
"processDefinitionId": "leave:7:20ada39c-6c95-11ec-88b1-cacd34981f8e",
"variables": {
"a": 1,
"b": "2"
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.adminserver.modules.bpm.controller.task;
import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Api(tags = "流程实例") // 流程实例通过流程定义创建的一次申请
@RestController
@RequestMapping("/bpm/process-instance")
@Validated
public class BpmProcessInstanceController {
@Resource
private BpmProcessInstanceService processInstanceService;
@PostMapping("/create")
@ApiOperation("新建流程实例")
public CommonResult<String> createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) {
return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO));
}
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.Map;
@ApiModel("流程实例的创建 Request VO")
@Data
//@EqualsAndHashCode(callSuper = true)
//@ToString(callSuper = true)
public class BpmProcessInstanceCreateReqVO {
@ApiModelProperty(value = "流程定义的编号", required = true, example = "1024")
@NotEmpty(message = "流程定义编号不能为空")
private String processDefinitionId;
@ApiModelProperty(value = "变量实例")
private Map<String, Object> variables;
}

View File

@ -0,0 +1,6 @@
package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
public class BpmProcessInstanceMyPageReqVO extends PageParam {
}

View File

@ -31,9 +31,13 @@ public interface BpmErrorCodeConstants {
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图"); ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图"); ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在"); ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态");
// ========== 动态表单模块 1-009-004-000 ========== // ========== 流程实例 1-009-004-000 ==========
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009004000, "动态表单不存在");
ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009004000, "表单项({}) 和 ({}) 使用了相同的字段名({})");
// ========== 动态表单模块 1-009-010-000 ==========
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1009010000, "动态表单不存在");
ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1009010000, "表单项({}) 和 ({}) 使用了相同的字段名({})");
} }

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
import javax.validation.Valid;
/**
* 流程实例 Service 接口
*
* @author 芋道源码
*/
public interface BpmProcessInstanceService {
/**
* 创建流程实例
*
* @param userId 用户编号
* @param createReqVO 创建信息
* @return 实例的编号
*/
String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
}

View File

@ -0,0 +1,100 @@
package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Map;
import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_IS_SUSPENDED;
import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 流程实例 Service 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系
* 1. https://blog.csdn.net/bobozai86/article/details/105210414
*
* HistoricProcessInstance & ProcessInstance 的关系
* 1.https://my.oschina.net/843294669/blog/719024
* 简单来说前者 = 历史 + 运行中的流程实例后者仅是运行中的流程实例
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Resource
private SysUserService userService;
@Resource
private BpmProcessDefinitionService processDefinitionService;
@Override
public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqVO createReqVO) {
// 校验流程定义
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 设置流程发起人
Authentication.setAuthenticatedUserId(String.valueOf(userId));
// 创建流程实例
Map<String, Object> variables = createReqVO.getVariables();
variables.put("INITIATOR", userId); // TODO 芋艿初始化人员
ProcessInstance instance = runtimeService.startProcessInstanceById(createReqVO.getProcessDefinitionId(), variables);
// 添加初始的评论 TODO 芋艿在思考下
Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
if (task != null) {
SysUserDO user = userService.getUser(userId);
Assert.notNull(user, "用户({})不存在", userId);
String type = "normal";
taskService.addComment(task.getId(), instance.getProcessInstanceId(), type,
String.format("%s 发起流程申请", user.getNickname()));
// TODO 芋艿应该不用下面两个步骤
// taskService.setAssignee(task.getId(), String.valueOf(userId));
// taskService.complete(task.getId(), variables);
}
return instance.getId();
}
public void getMyProcessInstancePage(Long userId) {
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
.startedBy(String.valueOf(userId)) // 发起人是自己
.orderByProcessInstanceStartTime().desc(); // 按照发起时间倒序
}
}

View File

@ -107,6 +107,14 @@ public interface SysUserService {
*/ */
PageResult<SysUserDO> getUserPage(SysUserPageReqVO reqVO); PageResult<SysUserDO> getUserPage(SysUserPageReqVO reqVO);
/**
* 获得用户
*
* @param id 用户编号
* @return 用户
*/
SysUserDO getUser(Long id);
/** /**
* 获得用户列表 * 获得用户列表
* *

View File

@ -164,6 +164,11 @@ public class SysUserServiceImpl implements SysUserService {
return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId())); return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
} }
@Override
public SysUserDO getUser(Long id) {
return userMapper.selectById(id);
}
@Override @Override
public List<SysUserDO> getUsers(SysUserExportReqVO reqVO) { public List<SysUserDO> getUsers(SysUserExportReqVO reqVO) {
return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.security.core.util; package cn.iocoder.yudao.framework.security.core.util;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -12,7 +11,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Set; import java.util.Set;
/** /**
@ -100,15 +98,15 @@ public class SecurityFrameworkUtils {
// 原因是Spring Security Filter ApiAccessLogFilter 后面在它记录访问日志时线上上下文已经没有用户编号等信息 // 原因是Spring Security Filter ApiAccessLogFilter 后面在它记录访问日志时线上上下文已经没有用户编号等信息
WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
// TODO @jason使用 userId 会不会更合适哈 // // TODO @jason使用 userId 会不会更合适哈
// TODO @芋艿activiti 需要使用 ttl 上下文 // // TODO @芋艿activiti 需要使用 ttl 上下文
// TODO @jason清理问题 // // TODO @jason清理问题
if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) { // if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) {
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername()); // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
} // }
// TODO @芋道源码 该值被赋值给 user task 中assignee username 显示更直白一点 // // TODO @芋道源码 该值被赋值给 user task 中assignee username 显示更直白一点
// TODO @jason有办法设置 userId然后 activiti 有地方读取到 username 毕竟 username 只是 User 的登陆账号并不能绝对像 userId 代表一个用户 // // TODO @jason有办法设置 userId然后 activiti 有地方读取到 username 毕竟 username 只是 User 的登陆账号并不能绝对像 userId 代表一个用户
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername()); // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername());
} }
} }