mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 18:46:36 +08:00
commit:支持activiti
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package com.flow.demo.common.flow.base.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.flow.constant.FlowApprovalType;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.model.FlowTaskComment;
|
||||
import com.flow.demo.common.flow.service.FlowApiService;
|
||||
import com.flow.demo.common.flow.service.FlowWorkOrderService;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public abstract class BaseFlowService<M, K extends Serializable> extends BaseService<M, K> {
|
||||
|
||||
@Autowired
|
||||
private FlowApiService flowApiService;
|
||||
@Autowired
|
||||
private FlowWorkOrderService flowWorkOrderService;
|
||||
|
||||
public void startAndTakeFirst(
|
||||
String processDefinitionId, K dataId, FlowTaskComment comment, JSONObject variables) {
|
||||
ProcessInstance instance = flowApiService.startAndTakeFirst(
|
||||
processDefinitionId, dataId, comment, variables);
|
||||
flowWorkOrderService.saveNew(instance, dataId, null);
|
||||
}
|
||||
|
||||
public void takeFirstTask(
|
||||
String processInstanceId, String taskId, K dataId, FlowTaskComment comment, JSONObject variables) {
|
||||
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
|
||||
flowApiService.setBusinessKeyForProcessInstance(processInstanceId, dataId);
|
||||
flowApiService.completeTask(task, comment, variables);
|
||||
ProcessInstance instance = flowApiService.getProcessInstance(processInstanceId);
|
||||
flowWorkOrderService.saveNew(instance, dataId, null);
|
||||
}
|
||||
|
||||
public void takeTask(Task task, K dataId, FlowTaskComment comment, JSONObject variables) {
|
||||
int flowStatus = FlowTaskStatus.APPROVING;
|
||||
if (comment.getApprovalType().equals(FlowApprovalType.REFUSE)) {
|
||||
flowStatus = FlowTaskStatus.REFUSED;
|
||||
}
|
||||
flowWorkOrderService.updateFlowStatusByBusinessKey(dataId.toString(), flowStatus);
|
||||
flowApiService.completeTask(task, comment, variables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.flow.demo.common.flow.command;
|
||||
|
||||
import com.flow.demo.common.core.exception.MyRuntimeException;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import org.activiti.bpmn.model.Activity;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics;
|
||||
import org.activiti.bpmn.model.UserTask;
|
||||
import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
|
||||
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
|
||||
import org.activiti.engine.impl.history.HistoryManager;
|
||||
import org.activiti.engine.impl.interceptor.Command;
|
||||
import org.activiti.engine.impl.interceptor.CommandContext;
|
||||
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
|
||||
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||
import org.activiti.engine.impl.persistence.entity.TaskEntity;
|
||||
import org.activiti.engine.impl.persistence.entity.TaskEntityManager;
|
||||
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 多实例加签命令对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public class AddMultiInstanceExecutionCmd implements Command<Void>, Serializable {
|
||||
|
||||
protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
|
||||
protected final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
|
||||
protected String collectionElementIndexVariable = "loopCounter";
|
||||
private String startTaskId;
|
||||
private String taskId;
|
||||
private String assignee;
|
||||
|
||||
public AddMultiInstanceExecutionCmd(String startTaskId, String taskId, String assignee) {
|
||||
this.startTaskId = startTaskId;
|
||||
this.taskId = taskId;
|
||||
this.assignee = assignee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void execute(CommandContext commandContext) {
|
||||
TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
|
||||
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
|
||||
//根据任务id获取任务实例
|
||||
TaskEntity taskEntity = taskEntityManager.findById(taskId);
|
||||
//根据执行实例ID获取当前执行实例
|
||||
ExecutionEntity multiExecutionEntity = executionEntityManager.findById(taskEntity.getExecutionId());
|
||||
// 获取流程执行实例(即当前执行实例的父实例)
|
||||
ExecutionEntity parentExecutionEntity = multiExecutionEntity.getParent();
|
||||
//判断当前执行实例的节点是否是多实例节点
|
||||
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(multiExecutionEntity.getProcessDefinitionId());
|
||||
Activity miActivityElement = (Activity) bpmnModel.getFlowElement(multiExecutionEntity.getCurrentActivityId());
|
||||
MultiInstanceLoopCharacteristics loopCharacteristics = miActivityElement.getLoopCharacteristics();
|
||||
if (loopCharacteristics == null) {
|
||||
throw new MyRuntimeException("此节点不是多实例节点!");
|
||||
}
|
||||
//判断是否是并行多实例
|
||||
if (loopCharacteristics.isSequential()) {
|
||||
throw new MyRuntimeException("此节点为串行多实例节点!");
|
||||
}
|
||||
//创建新的子实例
|
||||
ExecutionEntity childExecution = executionEntityManager.createChildExecution(parentExecutionEntity);
|
||||
//获取并为新的执行实例设置当前活动节点
|
||||
UserTask currentFlowElement = (UserTask) multiExecutionEntity.getCurrentFlowElement();
|
||||
//设置处理人
|
||||
childExecution.setCurrentFlowElement(currentFlowElement);
|
||||
childExecution.setVariableLocal("assignee", assignee);
|
||||
childExecution.setVariableLocal(FlowConstant.MULTI_SIGN_START_TASK_VAR, startTaskId);
|
||||
//获取设置变量
|
||||
Integer nrOfInstances = (Integer) parentExecutionEntity.getVariableLocal(FlowConstant.NUMBER_OF_INSTANCES_VAR);
|
||||
Integer nrOfActiveInstances = (Integer) parentExecutionEntity.getVariableLocal(NUMBER_OF_ACTIVE_INSTANCES);
|
||||
parentExecutionEntity.setVariableLocal(FlowConstant.NUMBER_OF_INSTANCES_VAR, nrOfInstances + 1);
|
||||
parentExecutionEntity.setVariableLocal(NUMBER_OF_ACTIVE_INSTANCES, nrOfActiveInstances + 1);
|
||||
//通知活动开始
|
||||
HistoryManager historyManager = commandContext.getHistoryManager();
|
||||
historyManager.recordActivityStart(childExecution);
|
||||
//获取处理行为类
|
||||
ParallelMultiInstanceBehavior prallelMultiInstanceBehavior =
|
||||
(ParallelMultiInstanceBehavior) miActivityElement.getBehavior();
|
||||
AbstractBpmnActivityBehavior innerActivityBehavior = prallelMultiInstanceBehavior.getInnerActivityBehavior();
|
||||
//执行
|
||||
innerActivityBehavior.execute(childExecution);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.flow.demo.common.flow.config;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* common-flow模块的自动配置引导类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@EnableConfigurationProperties({FlowProperties.class})
|
||||
public class FlowAutoConfig {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.flow.demo.common.flow.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 工作流的配置对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "common-flow")
|
||||
public class FlowProperties {
|
||||
|
||||
/**
|
||||
* 工作落工单操作接口的URL前缀。
|
||||
*/
|
||||
private String urlPrefix;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.flow.demo.common.flow.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流任务触发BUTTON。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowApprovalType {
|
||||
|
||||
/**
|
||||
* 保存。
|
||||
*/
|
||||
public static final String SAVE = "save";
|
||||
/**
|
||||
* 同意。
|
||||
*/
|
||||
public static final String AGREE = "agree";
|
||||
/**
|
||||
* 拒绝。
|
||||
*/
|
||||
public static final String REFUSE = "refuse";
|
||||
/**
|
||||
* 指派。
|
||||
*/
|
||||
public static final String TRANSFER = "transfer";
|
||||
/**
|
||||
* 多实例会签。
|
||||
*/
|
||||
public static final String MULTI_SIGN = "multi_sign";
|
||||
/**
|
||||
* 会签同意。
|
||||
*/
|
||||
public static final String MULTI_AGREE = "multi_agree";
|
||||
/**
|
||||
* 会签拒绝。
|
||||
*/
|
||||
public static final String MULTI_REFUSE = "multi_refuse";
|
||||
/**
|
||||
* 会签弃权。
|
||||
*/
|
||||
public static final String MULTI_ABSTAIN = "multi_abstain";
|
||||
/**
|
||||
* 多实例加签。
|
||||
*/
|
||||
public static final String MULTI_CONSIGN = "multi_consign";
|
||||
/**
|
||||
* 中止。
|
||||
*/
|
||||
public static final String STOP = "stop";
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(SAVE, "保存");
|
||||
DICT_MAP.put(AGREE, "同意");
|
||||
DICT_MAP.put(REFUSE, "拒绝");
|
||||
DICT_MAP.put(TRANSFER, "指派");
|
||||
DICT_MAP.put(MULTI_SIGN, "多实例会签");
|
||||
DICT_MAP.put(MULTI_AGREE, "会签同意");
|
||||
DICT_MAP.put(MULTI_REFUSE, "会签拒绝");
|
||||
DICT_MAP.put(MULTI_ABSTAIN, "会签弃权");
|
||||
DICT_MAP.put(MULTI_CONSIGN, "多实例加签");
|
||||
DICT_MAP.put(STOP, "中止");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowApprovalType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.flow.demo.common.flow.constant;
|
||||
|
||||
/**
|
||||
* 工作流中的常量数据。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public class FlowConstant {
|
||||
|
||||
/**
|
||||
* 标识流程实例启动用户的变量名。
|
||||
*/
|
||||
public final static String START_USER_NAME_VAR = "${startUserName}";
|
||||
|
||||
/**
|
||||
* 流程实例发起人变量名。
|
||||
*/
|
||||
public final static String PROC_INSTANCE_INITIATOR_VAR = "initiator";
|
||||
|
||||
/**
|
||||
* 流程实例中发起人用户的变量名。
|
||||
*/
|
||||
public final static String PROC_INSTANCE_START_USER_NAME_VAR = "startUserName";
|
||||
|
||||
/**
|
||||
* 操作类型变量。
|
||||
*/
|
||||
public final static String OPERATION_TYPE_VAR = "operationType";
|
||||
|
||||
/**
|
||||
* 多任务拒绝数量变量。
|
||||
*/
|
||||
public final static String MULTI_REFUSE_COUNT_VAR = "multiRefuseCount";
|
||||
|
||||
/**
|
||||
* 多任务同意数量变量。
|
||||
*/
|
||||
public final static String MULTI_AGREE_COUNT_VAR = "multiAgreeCount";
|
||||
|
||||
/**
|
||||
* 多任务弃权数量变量。
|
||||
*/
|
||||
public final static String MULTI_ABSTAIN_COUNT_VAR = "multiAbstainCount";
|
||||
|
||||
/**
|
||||
* 会签发起任务。
|
||||
*/
|
||||
public final static String MULTI_SIGN_START_TASK_VAR = "multiSignStartTask";
|
||||
|
||||
/**
|
||||
* 会签任务总数量。
|
||||
*/
|
||||
public final static String MULTI_SIGN_NUM_OF_INSTANCES_VAR = "multiNumOfInstances";
|
||||
|
||||
/**
|
||||
* 多实例实例数量变量。
|
||||
*/
|
||||
public final static String NUMBER_OF_INSTANCES_VAR = "nrOfInstances";
|
||||
|
||||
/**
|
||||
* 多任务指派人列表变量。
|
||||
*/
|
||||
public final static String MULTI_ASSIGNEE_LIST_VAR = "assigneeList";
|
||||
|
||||
/**
|
||||
* 上级部门领导审批变量
|
||||
*/
|
||||
public final static String GROUP_TYPE_UP_DEPT_POST_LEADER_VAR = "upDeptPostLeader";
|
||||
|
||||
/**
|
||||
* 上级部门领导审批变量
|
||||
*/
|
||||
public final static String GROUP_TYPE_DEPT_POST_LEADER_VAR = "deptPostLeader";
|
||||
|
||||
/**
|
||||
* 上级部门领导审批
|
||||
*/
|
||||
public final static String GROUP_TYPE_UP_DEPT_POST_LEADER = "UP_DEPT_POST_LEADER";
|
||||
|
||||
/**
|
||||
* 本部门岗位领导审批
|
||||
*/
|
||||
public final static String GROUP_TYPE_DEPT_POST_LEADER = "DEPT_POST_LEADER";
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.flow.demo.common.flow.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流任务类型。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowTaskStatus {
|
||||
|
||||
/**
|
||||
* 已提交。
|
||||
*/
|
||||
public static final int SUBMITTED = 0;
|
||||
/**
|
||||
* 审批中。
|
||||
*/
|
||||
public static final int APPROVING = 1;
|
||||
/**
|
||||
* 被拒绝。
|
||||
*/
|
||||
public static final int REFUSED = 2;
|
||||
/**
|
||||
* 已结束。
|
||||
*/
|
||||
public static final int FINISHED = 3;
|
||||
/**
|
||||
* 提前停止。
|
||||
*/
|
||||
public static final Integer STOPPED = 4;
|
||||
/**
|
||||
* 已取消。
|
||||
*/
|
||||
public static final Integer CANCELLED = 5;
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(SUBMITTED, "已提交");
|
||||
DICT_MAP.put(APPROVING, "审批中");
|
||||
DICT_MAP.put(REFUSED, "被拒绝");
|
||||
DICT_MAP.put(FINISHED, "已结束");
|
||||
DICT_MAP.put(STOPPED, "提前停止");
|
||||
DICT_MAP.put(CANCELLED, "已取消");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowTaskStatus() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.flow.demo.common.flow.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流任务类型。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowTaskType {
|
||||
|
||||
/**
|
||||
* 其他类型任务。
|
||||
*/
|
||||
public static final int OTHER_TYPE = 0;
|
||||
/**
|
||||
* 用户任务。
|
||||
*/
|
||||
public static final int USER_TYPE = 1;
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(OTHER_TYPE, "其他任务类型");
|
||||
DICT_MAP.put(USER_TYPE, "用户任务类型");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowTaskType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package com.flow.demo.common.flow.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jimmyshi.beanquery.BeanQuery;
|
||||
import com.github.pagehelper.page.PageMethod;
|
||||
import com.flow.demo.common.core.annotation.MyRequestBody;
|
||||
import com.flow.demo.common.core.constant.ErrorCodeEnum;
|
||||
import com.flow.demo.common.core.object.*;
|
||||
import com.flow.demo.common.core.util.MyCommonUtil;
|
||||
import com.flow.demo.common.core.util.MyModelUtil;
|
||||
import com.flow.demo.common.core.util.MyPageUtil;
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import com.flow.demo.common.flow.dto.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.model.constant.FlowEntryStatus;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.vo.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.groups.Default;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流分类操作控制器类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("${common-flow.urlPrefix}/flowCategory")
|
||||
public class FlowCategoryController {
|
||||
|
||||
@Autowired
|
||||
private FlowCategoryService flowCategoryService;
|
||||
@Autowired
|
||||
private FlowEntryService flowEntryService;
|
||||
|
||||
/**
|
||||
* 新增FlowCategory数据。
|
||||
*
|
||||
* @param flowCategoryDto 新增对象。
|
||||
* @return 应答结果对象,包含新增对象主键Id。
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseResult<Long> add(@MyRequestBody FlowCategoryDto flowCategoryDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowCategoryDto);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class);
|
||||
flowCategory = flowCategoryService.saveNew(flowCategory);
|
||||
return ResponseResult.success(flowCategory.getCategoryId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新FlowCategory数据。
|
||||
*
|
||||
* @param flowCategoryDto 更新对象。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public ResponseResult<Void> update(@MyRequestBody FlowCategoryDto flowCategoryDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowCategoryDto, Default.class, UpdateGroup.class);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class);
|
||||
FlowCategory originalFlowCategory = flowCategoryService.getById(flowCategory.getCategoryId());
|
||||
if (originalFlowCategory == null) {
|
||||
errorMessage = "数据验证失败,当前流程分类并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!StrUtil.equals(flowCategory.getCode(), originalFlowCategory.getCode())) {
|
||||
FlowEntry filter = new FlowEntry();
|
||||
filter.setCategoryId(flowCategory.getCategoryId());
|
||||
filter.setStatus(FlowEntryStatus.PUBLISHED);
|
||||
List<FlowEntry> flowEntryList = flowEntryService.getListByFilter(filter);
|
||||
if (CollUtil.isNotEmpty(flowEntryList)) {
|
||||
errorMessage = "数据验证失败,当前流程分类存在已经发布的流程数据,因此分类标识不能修改!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
if (!flowCategoryService.update(flowCategory, originalFlowCategory)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除FlowCategory数据。
|
||||
*
|
||||
* @param categoryId 删除对象主键Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public ResponseResult<Void> delete(@MyRequestBody Long categoryId) {
|
||||
String errorMessage;
|
||||
if (MyCommonUtil.existBlankArgument(categoryId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
FlowCategory originalFlowCategory = flowCategoryService.getById(categoryId);
|
||||
if (originalFlowCategory == null) {
|
||||
errorMessage = "数据验证失败,当前流程分类并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
FlowEntry filter = new FlowEntry();
|
||||
filter.setCategoryId(categoryId);
|
||||
List<FlowEntry> flowEntryList = flowEntryService.getListByFilter(filter);
|
||||
if (CollUtil.isNotEmpty(flowEntryList)) {
|
||||
errorMessage = "数据验证失败,请先删除当前流程分类关联的流程数据!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!flowCategoryService.remove(categoryId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出符合过滤条件的FlowCategory列表。
|
||||
*
|
||||
* @param flowCategoryDtoFilter 过滤对象。
|
||||
* @param orderParam 排序参数。
|
||||
* @param pageParam 分页参数。
|
||||
* @return 应答结果对象,包含查询结果集。
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public ResponseResult<MyPageData<FlowCategoryVo>> list(
|
||||
@MyRequestBody FlowCategoryDto flowCategoryDtoFilter,
|
||||
@MyRequestBody MyOrderParam orderParam,
|
||||
@MyRequestBody MyPageParam pageParam) {
|
||||
if (pageParam != null) {
|
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
|
||||
}
|
||||
FlowCategory flowCategoryFilter = MyModelUtil.copyTo(flowCategoryDtoFilter, FlowCategory.class);
|
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowCategory.class);
|
||||
List<FlowCategory> flowCategoryList = flowCategoryService.getFlowCategoryListWithRelation(flowCategoryFilter, orderBy);
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowCategoryList, FlowCategory.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看指定FlowCategory对象详情。
|
||||
*
|
||||
* @param categoryId 指定对象主键Id。
|
||||
* @return 应答结果对象,包含对象详情。
|
||||
*/
|
||||
@GetMapping("/view")
|
||||
public ResponseResult<FlowCategoryVo> view(@RequestParam Long categoryId) {
|
||||
if (MyCommonUtil.existBlankArgument(categoryId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
FlowCategory flowCategory = flowCategoryService.getByIdWithRelation(categoryId, MyRelationParam.full());
|
||||
if (flowCategory == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
FlowCategoryVo flowCategoryVo = FlowCategory.INSTANCE.fromModel(flowCategory);
|
||||
return ResponseResult.success(flowCategoryVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以字典形式返回全部FlowCategory数据集合。字典的键值为[categoryId, name]。
|
||||
* 白名单接口,登录用户均可访问。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @return 应答结果对象,包含的数据为 List<Map<String, String>>,map中包含两条记录,key的值分别是id和name,value对应具体数据。
|
||||
*/
|
||||
@GetMapping("/listDict")
|
||||
public ResponseResult<List<Map<String, Object>>> listDict(FlowCategory filter) {
|
||||
List<FlowCategory> resultList = flowCategoryService.getListByFilter(filter);
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"categoryId as id", "name as name").executeFrom(resultList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典Id集合,获取查询后的字典数据。
|
||||
*
|
||||
* @param dictIds 字典Id集合。
|
||||
* @return 应答结果对象,包含字典形式的数据集合。
|
||||
*/
|
||||
@PostMapping("/listDictByIds")
|
||||
public ResponseResult<List<Map<String, Object>>> listDictByIds(
|
||||
@MyRequestBody(elementType = Long.class) List<Long> dictIds) {
|
||||
List<FlowCategory> resultList = flowCategoryService.getInList(new HashSet<>(dictIds));
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"categoryId as id", "name as name").executeFrom(resultList));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,537 @@
|
||||
package com.flow.demo.common.flow.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jimmyshi.beanquery.BeanQuery;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.pagehelper.page.PageMethod;
|
||||
import com.flow.demo.common.core.annotation.MyRequestBody;
|
||||
import com.flow.demo.common.core.constant.ErrorCodeEnum;
|
||||
import com.flow.demo.common.core.object.*;
|
||||
import com.flow.demo.common.core.util.MyCommonUtil;
|
||||
import com.flow.demo.common.core.util.MyModelUtil;
|
||||
import com.flow.demo.common.core.util.MyPageUtil;
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskType;
|
||||
import com.flow.demo.common.flow.dto.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.model.constant.FlowEntryStatus;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.vo.*;
|
||||
import lombok.Cleanup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.groups.Default;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 工作流操作控制器类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("${common-flow.urlPrefix}/flowEntry")
|
||||
public class FlowEntryController {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryService flowEntryService;
|
||||
@Autowired
|
||||
private FlowCategoryService flowCategoryService;
|
||||
@Autowired
|
||||
private FlowEntryVariableService flowEntryVariableService;
|
||||
|
||||
/**
|
||||
* 新增工作流对象数据。
|
||||
*
|
||||
* @param flowEntryDto 新增对象。
|
||||
* @return 应答结果对象,包含新增对象主键Id。
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseResult<Long> add(@MyRequestBody FlowEntryDto flowEntryDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryDto);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowEntry flowEntry = MyModelUtil.copyTo(flowEntryDto, FlowEntry.class);
|
||||
if (flowEntryService.existOne("processDefinitionKey", flowEntry.getProcessDefinitionKey())) {
|
||||
errorMessage = "数据验证失败,该流程定义标识已存在!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
CallResult callResult = flowEntryService.verifyRelatedData(flowEntry, null);
|
||||
if (!callResult.isSuccess()) {
|
||||
errorMessage = callResult.getErrorMessage();
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
flowEntry = flowEntryService.saveNew(flowEntry);
|
||||
return ResponseResult.success(flowEntry.getEntryId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新工作流对象数据。
|
||||
*
|
||||
* @param flowEntryDto 更新对象。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public ResponseResult<Void> update(@MyRequestBody FlowEntryDto flowEntryDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryDto, Default.class, UpdateGroup.class);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowEntry flowEntry = MyModelUtil.copyTo(flowEntryDto, FlowEntry.class);
|
||||
FlowEntry originalFlowEntry = flowEntryService.getById(flowEntry.getEntryId());
|
||||
if (originalFlowEntry == null) {
|
||||
errorMessage = "数据验证失败,当前流程并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (ObjectUtil.notEqual(flowEntry.getProcessDefinitionKey(), originalFlowEntry.getProcessDefinitionKey())) {
|
||||
if (originalFlowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) {
|
||||
errorMessage = "数据验证失败,当前流程为发布状态,流程标识不能修改!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (flowEntryService.existOne("processDefinitionKey", flowEntry.getProcessDefinitionKey())) {
|
||||
errorMessage = "数据验证失败,该流程定义标识已存在!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
if (ObjectUtil.notEqual(flowEntry.getCategoryId(), originalFlowEntry.getCategoryId())) {
|
||||
if (originalFlowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) {
|
||||
errorMessage = "数据验证失败,当前流程为发布状态,流程分类不能修改!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
CallResult callResult = flowEntryService.verifyRelatedData(flowEntry, originalFlowEntry);
|
||||
if (!callResult.isSuccess()) {
|
||||
errorMessage = callResult.getErrorMessage();
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!flowEntryService.update(flowEntry, originalFlowEntry)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除工作流对象数据。
|
||||
*
|
||||
* @param entryId 删除对象主键Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public ResponseResult<Void> delete(@MyRequestBody Long entryId) {
|
||||
String errorMessage;
|
||||
if (MyCommonUtil.existBlankArgument(entryId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
FlowEntry originalFlowEntry = flowEntryService.getById(entryId);
|
||||
if (originalFlowEntry == null) {
|
||||
errorMessage = "数据验证失败,当前流程并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (originalFlowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) {
|
||||
errorMessage = "数据验证失败,当前流程为发布状态,不能删除!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!flowEntryService.remove(entryId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布工作流。
|
||||
*
|
||||
* @param entryId 流程主键Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/publish")
|
||||
public ResponseResult<Void> publish(@MyRequestBody(required = true) Long entryId) throws XMLStreamException {
|
||||
String errorMessage;
|
||||
FlowEntry flowEntry = flowEntryService.getById(entryId);
|
||||
if (flowEntry == null) {
|
||||
errorMessage = "数据验证失败,该流程并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (StrUtil.isBlank(flowEntry.getBpmnXml())) {
|
||||
errorMessage = "数据验证失败,该流程没有流程图不能被发布!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
ResponseResult<TaskInfoVo> taskInfoResult = this.verifyAndGetInitialTaskInfo(flowEntry);
|
||||
if (!taskInfoResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(taskInfoResult);
|
||||
}
|
||||
List<FlowTaskExt> flowTaskExtList = this.buildTaskExtList(flowEntry);
|
||||
String taskInfo = taskInfoResult.getData() == null ? null : JSON.toJSONString(taskInfoResult.getData());
|
||||
flowEntryService.publish(flowEntry, taskInfo, flowTaskExtList);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出符合过滤条件的工作流列表。
|
||||
*
|
||||
* @param flowEntryDtoFilter 过滤对象。
|
||||
* @param orderParam 排序参数。
|
||||
* @param pageParam 分页参数。
|
||||
* @return 应答结果对象,包含查询结果集。
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public ResponseResult<MyPageData<FlowEntryVo>> list(
|
||||
@MyRequestBody FlowEntryDto flowEntryDtoFilter,
|
||||
@MyRequestBody MyOrderParam orderParam,
|
||||
@MyRequestBody MyPageParam pageParam) {
|
||||
if (pageParam != null) {
|
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
|
||||
}
|
||||
FlowEntry flowEntryFilter = MyModelUtil.copyTo(flowEntryDtoFilter, FlowEntry.class);
|
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowEntry.class);
|
||||
List<FlowEntry> flowEntryList = flowEntryService.getFlowEntryListWithRelation(flowEntryFilter, orderBy);
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowEntryList, FlowEntry.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看指定工作流对象详情。
|
||||
*
|
||||
* @param entryId 指定对象主键Id。
|
||||
* @return 应答结果对象,包含对象详情。
|
||||
*/
|
||||
@GetMapping("/view")
|
||||
public ResponseResult<FlowEntryVo> view(@RequestParam Long entryId) {
|
||||
if (MyCommonUtil.existBlankArgument(entryId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
FlowEntry flowEntry = flowEntryService.getByIdWithRelation(entryId, MyRelationParam.full());
|
||||
if (flowEntry == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
FlowEntryVo flowEntryVo = FlowEntry.INSTANCE.fromModel(flowEntry);
|
||||
return ResponseResult.success(flowEntryVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出指定流程的发布版本列表。
|
||||
*
|
||||
* @param entryId 流程主键Id。
|
||||
* @return 应答结果对象,包含流程发布列表数据。
|
||||
*/
|
||||
@GetMapping("/listFlowEntryPublish")
|
||||
public ResponseResult<List<FlowEntryPublishVo>> listFlowEntryPublish(@RequestParam Long entryId) {
|
||||
List<FlowEntryPublish> flowEntryPublishList = flowEntryService.getFlowEntryPublishList(entryId);
|
||||
return ResponseResult.success(MyModelUtil.copyCollectionTo(flowEntryPublishList, FlowEntryPublishVo.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 以字典形式返回全部FlowEntry数据集合。字典的键值为[entryId, procDefinitionName]。
|
||||
* 白名单接口,登录用户均可访问。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @return 应答结果对象,包含的数据为 List<Map<String, String>>,map中包含两条记录,key的值分别是id和name,value对应具体数据。
|
||||
*/
|
||||
@GetMapping("/listDict")
|
||||
public ResponseResult<List<Map<String, Object>>> listDict(FlowEntry filter) {
|
||||
List<FlowEntry> resultList = flowEntryService.getListByFilter(filter);
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"entryId as id", "processDefinitionName as name").executeFrom(resultList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 白名单接口,根据流程Id,获取流程引擎需要的流程标识和流程名称。
|
||||
*
|
||||
* @param entryId 流程Id。
|
||||
* @return 流程的部分数据。
|
||||
*/
|
||||
@GetMapping("/viewDict")
|
||||
public ResponseResult<Map<String, Object>> viewDict(@RequestParam Long entryId) {
|
||||
FlowEntry flowEntry = flowEntryService.getById(entryId);
|
||||
if (flowEntry == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
Map<String, Object> resultMap = new HashMap<>(2);
|
||||
resultMap.put("processDefinitionKey", flowEntry.getProcessDefinitionKey());
|
||||
resultMap.put("processDefinitionName", flowEntry.getProcessDefinitionName());
|
||||
return ResponseResult.success(resultMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换指定工作的发布主版本。
|
||||
*
|
||||
* @param entryId 工作流主键Id。
|
||||
* @param newEntryPublishId 新的工作流发布主版本对象的主键Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/updateMainVersion")
|
||||
public ResponseResult<Void> updateMainVersion(
|
||||
@MyRequestBody(required = true) Long entryId,
|
||||
@MyRequestBody(required = true) Long newEntryPublishId) {
|
||||
String errorMessage;
|
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishById(newEntryPublishId);
|
||||
if (flowEntryPublish == null) {
|
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (ObjectUtil.notEqual(entryId, flowEntryPublish.getEntryId())) {
|
||||
errorMessage = "数据验证失败,当前工作流并不包含该工作流发布版本数据,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (flowEntryPublish.getMainVersion()) {
|
||||
errorMessage = "数据验证失败,该版本已经为当前工作流的发布主版本,不能重复设置!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
flowEntryService.updateFlowEntryMainVersion(flowEntryService.getById(entryId), flowEntryPublish);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起工作流的指定发布版本。
|
||||
*
|
||||
* @param entryPublishId 工作发布Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/suspendFlowEntryPublish")
|
||||
public ResponseResult<Void> suspendFlowEntryPublish(@MyRequestBody(required = true) Long entryPublishId) {
|
||||
String errorMessage;
|
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishById(entryPublishId);
|
||||
if (flowEntryPublish == null) {
|
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!flowEntryPublish.getActiveStatus()) {
|
||||
errorMessage = "数据验证失败,当前流程发布版本已处于挂起状态!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
flowEntryService.suspendFlowEntryPublish(flowEntryPublish);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活工作流的指定发布版本。
|
||||
*
|
||||
* @param entryPublishId 工作发布Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/activateFlowEntryPublish")
|
||||
public ResponseResult<Void> activateFlowEntryPublish(@MyRequestBody(required = true) Long entryPublishId) {
|
||||
String errorMessage;
|
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishById(entryPublishId);
|
||||
if (flowEntryPublish == null) {
|
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (flowEntryPublish.getActiveStatus()) {
|
||||
errorMessage = "数据验证失败,当前流程发布版本已处于激活状态!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
flowEntryService.activateFlowEntryPublish(flowEntryPublish);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
private FlowTaskExt buildTaskExt(UserTask userTask) {
|
||||
FlowTaskExt flowTaskExt = new FlowTaskExt();
|
||||
flowTaskExt.setTaskId(userTask.getId());
|
||||
String formKey = userTask.getFormKey();
|
||||
if (StrUtil.isNotBlank(formKey)) {
|
||||
TaskInfoVo taskInfoVo = JSON.parseObject(formKey, TaskInfoVo.class);
|
||||
flowTaskExt.setGroupType(taskInfoVo.getGroupType());
|
||||
}
|
||||
Map<String, List<ExtensionElement>> extensionMap = userTask.getExtensionElements();
|
||||
if (MapUtil.isNotEmpty(extensionMap)) {
|
||||
List<JSONObject> operationList = this.buildUserTaskOperationListExtensionElement(extensionMap);
|
||||
if (CollUtil.isNotEmpty(operationList)) {
|
||||
flowTaskExt.setOperationListJson(JSON.toJSONString(operationList));
|
||||
}
|
||||
List<JSONObject> variableList = this.buildUserTaskVariableListExtensionElement(extensionMap);
|
||||
if (CollUtil.isNotEmpty(variableList)) {
|
||||
flowTaskExt.setVariableListJson(JSON.toJSONString(variableList));
|
||||
}
|
||||
JSONObject assigneeListObject = this.buildUserTaskAssigneeListExtensionElement(extensionMap);
|
||||
if (assigneeListObject != null) {
|
||||
flowTaskExt.setAssigneeListJson(JSON.toJSONString(assigneeListObject));
|
||||
}
|
||||
}
|
||||
return flowTaskExt;
|
||||
}
|
||||
|
||||
private List<FlowTaskExt> buildTaskExtList(FlowEntry flowEntry) throws XMLStreamException {
|
||||
List<FlowTaskExt> flowTaskExtList = new LinkedList<>();
|
||||
BpmnModel bpmnModel = this.convertToBpmnModel(flowEntry.getBpmnXml());
|
||||
List<Process> processList = bpmnModel.getProcesses();
|
||||
for (Process process : processList) {
|
||||
for (FlowElement element : process.getFlowElements()) {
|
||||
if (element instanceof UserTask) {
|
||||
FlowTaskExt flowTaskExt = this.buildTaskExt((UserTask) element);
|
||||
flowTaskExtList.add(flowTaskExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flowTaskExtList;
|
||||
}
|
||||
|
||||
private ResponseResult<TaskInfoVo> verifyAndGetInitialTaskInfo(FlowEntry flowEntry) throws XMLStreamException {
|
||||
String errorMessage;
|
||||
BpmnModel bpmnModel = this.convertToBpmnModel(flowEntry.getBpmnXml());
|
||||
Process process = bpmnModel.getMainProcess();
|
||||
if (process == null) {
|
||||
errorMessage = "数据验证失败,当前流程标识 [" + flowEntry.getProcessDefinitionKey() + "] 关联的流程模型并不存在!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
Collection<FlowElement> elementList = process.getFlowElements();
|
||||
FlowElement startEvent = null;
|
||||
FlowElement firstTask = null;
|
||||
// 这里我们只定位流程模型中的第二个节点。
|
||||
for (FlowElement flowElement : elementList) {
|
||||
if (flowElement instanceof StartEvent) {
|
||||
startEvent = flowElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startEvent == null) {
|
||||
errorMessage = "数据验证失败,当前流程图没有包含 [开始事件] 节点,请修改流程图!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
for (FlowElement flowElement : elementList) {
|
||||
if (flowElement instanceof SequenceFlow) {
|
||||
SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
|
||||
if (sequenceFlow.getSourceFlowElement().equals(startEvent)) {
|
||||
firstTask = sequenceFlow.getTargetFlowElement();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstTask == null) {
|
||||
errorMessage = "数据验证失败,当前流程图没有包含 [开始事件] 节点没有任何连线,请修改流程图!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
TaskInfoVo taskInfoVo;
|
||||
if (firstTask instanceof UserTask) {
|
||||
UserTask userTask = (UserTask) firstTask;
|
||||
String formKey = userTask.getFormKey();
|
||||
if (StrUtil.isNotBlank(formKey)) {
|
||||
taskInfoVo = JSON.parseObject(formKey, TaskInfoVo.class);
|
||||
} else {
|
||||
taskInfoVo = new TaskInfoVo();
|
||||
}
|
||||
taskInfoVo.setAssignee(userTask.getAssignee());
|
||||
taskInfoVo.setTaskKey(userTask.getId());
|
||||
taskInfoVo.setTaskType(FlowTaskType.USER_TYPE);
|
||||
Map<String, List<ExtensionElement>> extensionMap = userTask.getExtensionElements();
|
||||
if (MapUtil.isNotEmpty(extensionMap)) {
|
||||
taskInfoVo.setOperationList(this.buildUserTaskOperationListExtensionElement(extensionMap));
|
||||
taskInfoVo.setVariableList(this.buildUserTaskVariableListExtensionElement(extensionMap));
|
||||
}
|
||||
} else {
|
||||
taskInfoVo = new TaskInfoVo();
|
||||
taskInfoVo.setTaskType(FlowTaskType.OTHER_TYPE);
|
||||
}
|
||||
return ResponseResult.success(taskInfoVo);
|
||||
}
|
||||
|
||||
private JSONObject buildUserTaskAssigneeListExtensionElement(
|
||||
Map<String, List<ExtensionElement>> extensionMap) {
|
||||
JSONObject jsonData = null;
|
||||
List<ExtensionElement> elementAssigneeList = extensionMap.get("assigneeList");
|
||||
if (CollUtil.isEmpty(elementAssigneeList)) {
|
||||
return jsonData;
|
||||
}
|
||||
ExtensionElement ee = elementAssigneeList.get(0);
|
||||
Map<String, List<ExtensionElement>> childExtensionMap = ee.getChildElements();
|
||||
if (MapUtil.isEmpty(childExtensionMap)) {
|
||||
return jsonData;
|
||||
}
|
||||
List<ExtensionElement> assigneeElements = childExtensionMap.get("assignee");
|
||||
if (CollUtil.isEmpty(assigneeElements)) {
|
||||
return jsonData;
|
||||
}
|
||||
JSONArray assigneeIdArray = new JSONArray();
|
||||
for (ExtensionElement e : assigneeElements) {
|
||||
assigneeIdArray.add(e.getAttributeValue(null, "id"));
|
||||
}
|
||||
jsonData = new JSONObject();
|
||||
String assigneeType = ee.getAttributeValue(null, "type");
|
||||
jsonData.put("assigneeType", assigneeType);
|
||||
jsonData.put("assigneeList", assigneeIdArray);
|
||||
return jsonData;
|
||||
}
|
||||
|
||||
private List<JSONObject> buildUserTaskOperationListExtensionElement(
|
||||
Map<String, List<ExtensionElement>> extensionMap) {
|
||||
List<JSONObject> resultList = null;
|
||||
List<ExtensionElement> elementOperationList = extensionMap.get("operationList");
|
||||
if (CollUtil.isEmpty(elementOperationList)) {
|
||||
return resultList;
|
||||
}
|
||||
ExtensionElement ee = elementOperationList.get(0);
|
||||
Map<String, List<ExtensionElement>> childExtensionMap = ee.getChildElements();
|
||||
if (MapUtil.isEmpty(childExtensionMap)) {
|
||||
return resultList;
|
||||
}
|
||||
List<ExtensionElement> formOperationElements = childExtensionMap.get("formOperation");
|
||||
if (CollUtil.isEmpty(formOperationElements)) {
|
||||
return resultList;
|
||||
}
|
||||
resultList = new LinkedList<>();
|
||||
for (ExtensionElement e : formOperationElements) {
|
||||
JSONObject operationJsonData = new JSONObject();
|
||||
operationJsonData.put("id", e.getAttributeValue(null, "id"));
|
||||
operationJsonData.put("label", e.getAttributeValue(null, "label"));
|
||||
operationJsonData.put("type", e.getAttributeValue(null, "type"));
|
||||
operationJsonData.put("showOrder", e.getAttributeValue(null, "showOrder"));
|
||||
resultList.add(operationJsonData);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private List<JSONObject> buildUserTaskVariableListExtensionElement(
|
||||
Map<String, List<ExtensionElement>> extensionMap) {
|
||||
List<ExtensionElement> elementVariableList = extensionMap.get("variableList");
|
||||
if (CollUtil.isEmpty(elementVariableList)) {
|
||||
return null;
|
||||
}
|
||||
ExtensionElement ee = elementVariableList.get(0);
|
||||
Map<String, List<ExtensionElement>> childExtensionMap = ee.getChildElements();
|
||||
if (MapUtil.isEmpty(childExtensionMap)) {
|
||||
return null;
|
||||
}
|
||||
List<ExtensionElement> formVariableElements = childExtensionMap.get("formVariable");
|
||||
if (CollUtil.isEmpty(formVariableElements)) {
|
||||
return null;
|
||||
}
|
||||
Set<Long> variableIdSet = new HashSet<>();
|
||||
for (ExtensionElement e : formVariableElements) {
|
||||
String id = e.getAttributeValue(null, "id");
|
||||
variableIdSet.add(Long.parseLong(id));
|
||||
}
|
||||
List<FlowEntryVariable> variableList = flowEntryVariableService.getInList(variableIdSet);
|
||||
List<JSONObject> resultList = new LinkedList<>();
|
||||
for (FlowEntryVariable variable : variableList) {
|
||||
resultList.add((JSONObject) JSON.toJSON(variable));
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
private BpmnModel convertToBpmnModel(String bpmnXml) throws XMLStreamException {
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
InputStream in = new ByteArrayInputStream(bpmnXml.getBytes(StandardCharsets.UTF_8));
|
||||
@Cleanup XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(in);
|
||||
return converter.convertToBpmnModel(reader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.flow.demo.common.flow.controller;
|
||||
|
||||
import com.github.pagehelper.page.PageMethod;
|
||||
import com.flow.demo.common.flow.vo.*;
|
||||
import com.flow.demo.common.flow.dto.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.core.object.*;
|
||||
import com.flow.demo.common.core.util.*;
|
||||
import com.flow.demo.common.core.constant.*;
|
||||
import com.flow.demo.common.core.annotation.MyRequestBody;
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.groups.Default;
|
||||
|
||||
/**
|
||||
* 流程变量操作控制器类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("${common-flow.urlPrefix}/flowEntryVariable")
|
||||
public class FlowEntryVariableController {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryVariableService flowEntryVariableService;
|
||||
|
||||
/**
|
||||
* 新增流程变量数据。
|
||||
*
|
||||
* @param flowEntryVariableDto 新增对象。
|
||||
* @return 应答结果对象,包含新增对象主键Id。
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public ResponseResult<Long> add(@MyRequestBody FlowEntryVariableDto flowEntryVariableDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryVariableDto);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowEntryVariable flowEntryVariable = MyModelUtil.copyTo(flowEntryVariableDto, FlowEntryVariable.class);
|
||||
flowEntryVariable = flowEntryVariableService.saveNew(flowEntryVariable);
|
||||
return ResponseResult.success(flowEntryVariable.getVariableId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新流程变量数据。
|
||||
*
|
||||
* @param flowEntryVariableDto 更新对象。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public ResponseResult<Void> update(@MyRequestBody FlowEntryVariableDto flowEntryVariableDto) {
|
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryVariableDto, Default.class, UpdateGroup.class);
|
||||
if (errorMessage != null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowEntryVariable flowEntryVariable = MyModelUtil.copyTo(flowEntryVariableDto, FlowEntryVariable.class);
|
||||
FlowEntryVariable originalFlowEntryVariable = flowEntryVariableService.getById(flowEntryVariable.getVariableId());
|
||||
if (originalFlowEntryVariable == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!flowEntryVariableService.update(flowEntryVariable, originalFlowEntryVariable)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程变量数据。
|
||||
*
|
||||
* @param variableId 删除对象主键Id。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public ResponseResult<Void> delete(@MyRequestBody Long variableId) {
|
||||
String errorMessage;
|
||||
if (MyCommonUtil.existBlankArgument(variableId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
FlowEntryVariable originalFlowEntryVariable = flowEntryVariableService.getById(variableId);
|
||||
if (originalFlowEntryVariable == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!flowEntryVariableService.remove(variableId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出符合过滤条件的流程变量列表。
|
||||
*
|
||||
* @param flowEntryVariableDtoFilter 过滤对象。
|
||||
* @param orderParam 排序参数。
|
||||
* @param pageParam 分页参数。
|
||||
* @return 应答结果对象,包含查询结果集。
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public ResponseResult<MyPageData<FlowEntryVariableVo>> list(
|
||||
@MyRequestBody FlowEntryVariableDto flowEntryVariableDtoFilter,
|
||||
@MyRequestBody MyOrderParam orderParam,
|
||||
@MyRequestBody MyPageParam pageParam) {
|
||||
if (pageParam != null) {
|
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
|
||||
}
|
||||
FlowEntryVariable flowEntryVariableFilter = MyModelUtil.copyTo(flowEntryVariableDtoFilter, FlowEntryVariable.class);
|
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowEntryVariable.class);
|
||||
List<FlowEntryVariable> flowEntryVariableList =
|
||||
flowEntryVariableService.getFlowEntryVariableListWithRelation(flowEntryVariableFilter, orderBy);
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowEntryVariableList, FlowEntryVariable.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看指定流程变量对象详情。
|
||||
*
|
||||
* @param variableId 指定对象主键Id。
|
||||
* @return 应答结果对象,包含对象详情。
|
||||
*/
|
||||
@GetMapping("/view")
|
||||
public ResponseResult<FlowEntryVariableVo> view(@RequestParam Long variableId) {
|
||||
if (MyCommonUtil.existBlankArgument(variableId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
FlowEntryVariable flowEntryVariable = flowEntryVariableService.getByIdWithRelation(variableId, MyRelationParam.full());
|
||||
if (flowEntryVariable == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
FlowEntryVariableVo flowEntryVariableVo = FlowEntryVariable.INSTANCE.fromModel(flowEntryVariable);
|
||||
return ResponseResult.success(flowEntryVariableVo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
package com.flow.demo.common.flow.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.flow.demo.common.core.annotation.MyRequestBody;
|
||||
import com.flow.demo.common.core.constant.ErrorCodeEnum;
|
||||
import com.flow.demo.common.core.object.*;
|
||||
import com.flow.demo.common.core.util.MyPageUtil;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.util.FlowOperationHelper;
|
||||
import com.flow.demo.common.flow.vo.FlowTaskCommentVo;
|
||||
import com.flow.demo.common.flow.vo.FlowTaskVo;
|
||||
import com.flow.demo.common.flow.vo.TaskInfoVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.FlowElement;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.bpmn.model.SequenceFlow;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 流程操作接口类
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("${common-flow.urlPrefix}/flowOperation")
|
||||
public class FlowOperationController {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryService flowEntryService;
|
||||
@Autowired
|
||||
private FlowTaskCommentService flowTaskCommentService;
|
||||
@Autowired
|
||||
private FlowTaskExtService flowTaskExtService;
|
||||
@Autowired
|
||||
private FlowApiService flowApiService;
|
||||
@Autowired
|
||||
private FlowWorkOrderService flowWorkOrderService;
|
||||
@Autowired
|
||||
private FlowOperationHelper flowOperationHelper;
|
||||
|
||||
/**
|
||||
* 根据指定流程的主版本,发起一个流程实例。
|
||||
*
|
||||
* @param processDefinitionKey 流程标识。
|
||||
* @return 应答结果对象。
|
||||
*/
|
||||
@PostMapping("/startOnly")
|
||||
public ResponseResult<Void> startOnly(@MyRequestBody(required = true) String processDefinitionKey) {
|
||||
// 1. 验证流程数据的合法性。
|
||||
ResponseResult<FlowEntry> flowEntryResult = flowOperationHelper.verifyAndGetFlowEntry(processDefinitionKey);
|
||||
if (!flowEntryResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(flowEntryResult);
|
||||
}
|
||||
// 2. 验证流程一个用户任务的合法性。
|
||||
FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
|
||||
ResponseResult<TaskInfoVo> taskInfoResult =
|
||||
flowOperationHelper.verifyAndGetInitialTaskInfo(flowEntryPublish, false);
|
||||
if (!taskInfoResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(taskInfoResult);
|
||||
}
|
||||
flowApiService.start(flowEntryPublish.getProcessDefinitionId());
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开始节点之后的第一个任务节点的数据。
|
||||
*
|
||||
* @param processDefinitionKey 流程标识。
|
||||
* @return 任务节点的自定义对象数据。
|
||||
*/
|
||||
@GetMapping("/viewInitialTaskInfo")
|
||||
public ResponseResult<TaskInfoVo> viewInitialTaskInfo(@RequestParam String processDefinitionKey) {
|
||||
ResponseResult<FlowEntry> flowEntryResult = flowOperationHelper.verifyAndGetFlowEntry(processDefinitionKey);
|
||||
if (!flowEntryResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(flowEntryResult);
|
||||
}
|
||||
FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
|
||||
String initTaskInfo = flowEntryPublish.getInitTaskInfo();
|
||||
TaskInfoVo taskInfo = StrUtil.isBlank(initTaskInfo)
|
||||
? null : JSON.parseObject(initTaskInfo, TaskInfoVo.class);
|
||||
if (taskInfo != null) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
taskInfo.setAssignedMe(StrUtil.equalsAny(
|
||||
taskInfo.getAssignee(), loginName, FlowConstant.START_USER_NAME_VAR));
|
||||
}
|
||||
return ResponseResult.success(taskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程运行时指定任务的信息。
|
||||
*
|
||||
* @param processDefinitionId 流程引擎的定义Id。
|
||||
* @param processInstanceId 流程引擎的实例Id。
|
||||
* @param taskId 流程引擎的任务Id。
|
||||
* @return 任务节点的自定义对象数据。
|
||||
*/
|
||||
@GetMapping("/viewRuntimeTaskInfo")
|
||||
public ResponseResult<TaskInfoVo> viewRuntimeTaskInfo(
|
||||
@RequestParam String processDefinitionId,
|
||||
@RequestParam String processInstanceId,
|
||||
@RequestParam String taskId) {
|
||||
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
|
||||
ResponseResult<TaskInfoVo> taskInfoResult = flowOperationHelper.verifyAndGetRuntimeTaskInfo(task);
|
||||
if (!taskInfoResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(taskInfoResult);
|
||||
}
|
||||
TaskInfoVo taskInfoVo = taskInfoResult.getData();
|
||||
FlowTaskExt flowTaskExt =
|
||||
flowTaskExtService.getByProcessDefinitionIdAndTaskId(processDefinitionId, taskInfoVo.getTaskKey());
|
||||
if (flowTaskExt != null) {
|
||||
if (StrUtil.isNotBlank(flowTaskExt.getOperationListJson())) {
|
||||
taskInfoVo.setOperationList(JSON.parseArray(flowTaskExt.getOperationListJson(), JSONObject.class));
|
||||
}
|
||||
if (StrUtil.isNotBlank(flowTaskExt.getVariableListJson())) {
|
||||
taskInfoVo.setVariableList(JSON.parseArray(flowTaskExt.getVariableListJson(), JSONObject.class));
|
||||
}
|
||||
}
|
||||
return ResponseResult.success(taskInfoVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程运行时指定任务的信息。
|
||||
*
|
||||
* @param processDefinitionId 流程引擎的定义Id。
|
||||
* @param processInstanceId 流程引擎的实例Id。
|
||||
* @param taskId 流程引擎的任务Id。
|
||||
* @return 任务节点的自定义对象数据。
|
||||
*/
|
||||
@GetMapping("/viewHistoricTaskInfo")
|
||||
public ResponseResult<TaskInfoVo> viewHistoricTaskInfo(
|
||||
@RequestParam String processDefinitionId,
|
||||
@RequestParam String processInstanceId,
|
||||
@RequestParam String taskId) {
|
||||
String errorMessage;
|
||||
HistoricTaskInstance taskInstance = flowApiService.getHistoricTaskInstance(processInstanceId, taskId);
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
if (!StrUtil.equals(taskInstance.getAssignee(), loginName)) {
|
||||
errorMessage = "数据验证失败,当前用户不是指派人!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
TaskInfoVo taskInfoVo = JSON.parseObject(taskInstance.getFormKey(), TaskInfoVo.class);
|
||||
FlowTaskExt flowTaskExt =
|
||||
flowTaskExtService.getByProcessDefinitionIdAndTaskId(processDefinitionId, taskInstance.getTaskDefinitionKey());
|
||||
if (flowTaskExt != null) {
|
||||
if (StrUtil.isNotBlank(flowTaskExt.getOperationListJson())) {
|
||||
taskInfoVo.setOperationList(JSON.parseArray(flowTaskExt.getOperationListJson(), JSONObject.class));
|
||||
}
|
||||
if (StrUtil.isNotBlank(flowTaskExt.getVariableListJson())) {
|
||||
taskInfoVo.setVariableList(JSON.parseArray(flowTaskExt.getVariableListJson(), JSONObject.class));
|
||||
}
|
||||
}
|
||||
return ResponseResult.success(taskInfoVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第一个提交表单数据的任务信息。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 任务节点的自定义对象数据。
|
||||
*/
|
||||
@GetMapping("/viewInitialHistoricTaskInfo")
|
||||
public ResponseResult<TaskInfoVo> viewInitialHistoricTaskInfo(@RequestParam String processInstanceId) {
|
||||
String errorMessage;
|
||||
List<FlowTaskComment> taskCommentList =
|
||||
flowTaskCommentService.getFlowTaskCommentList(processInstanceId);
|
||||
if (CollUtil.isEmpty(taskCommentList)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
FlowTaskComment taskComment = taskCommentList.get(0);
|
||||
if (ObjectUtil.notEqual(taskComment.getCreateUserId(), TokenData.takeFromRequest().getUserId())) {
|
||||
errorMessage = "数据验证失败,当前流程发起人与当前用户不匹配!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
HistoricTaskInstance task = flowApiService.getHistoricTaskInstance(processInstanceId, taskComment.getTaskId());
|
||||
if (StrUtil.isBlank(task.getFormKey())) {
|
||||
errorMessage = "数据验证失败,指定任务的formKey属性不存在,请重新修改流程图!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
TaskInfoVo taskInfo = JSON.parseObject(task.getFormKey(), TaskInfoVo.class);
|
||||
taskInfo.setTaskKey(task.getTaskDefinitionKey());
|
||||
return ResponseResult.success(taskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交多实例加签。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 多实例任务的上一级任务Id。
|
||||
* @param newAssignees 新的加签人列表,多个指派人之间逗号分隔。
|
||||
* @return 应答结果。
|
||||
*/
|
||||
@PostMapping("/submitConsign")
|
||||
public ResponseResult<Void> submitConsign(
|
||||
@MyRequestBody(required = true) String processInstanceId,
|
||||
@MyRequestBody(required = true) String taskId,
|
||||
@MyRequestBody(required = true) String newAssignees) {
|
||||
String errorMessage;
|
||||
if (!flowApiService.existActiveProcessInstance(processInstanceId)) {
|
||||
errorMessage = "数据验证失败,当前流程实例已经结束,不能执行加签!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
HistoricTaskInstance taskInstance = flowApiService.getHistoricTaskInstance(processInstanceId, taskId);
|
||||
if (taskInstance == null) {
|
||||
errorMessage = "数据验证失败,当前任务不存在!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!StrUtil.equals(taskInstance.getAssignee(), TokenData.takeFromRequest().getLoginName())) {
|
||||
errorMessage = "数据验证失败,任务指派人与当前用户不匹配!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
List<Task> activeTaskList = flowApiService.getProcessInstanceActiveTaskList(processInstanceId);
|
||||
Task activeMultiInstanceTask = null;
|
||||
for (Task activeTask : activeTaskList) {
|
||||
Object startTaskId = flowApiService.getTaskVariable(
|
||||
activeTask.getId(), FlowConstant.MULTI_SIGN_START_TASK_VAR);
|
||||
if (startTaskId != null && startTaskId.toString().equals(taskId)) {
|
||||
activeMultiInstanceTask = activeTask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (activeMultiInstanceTask == null) {
|
||||
errorMessage = "数据验证失败,指定加签任务不存在或已审批完毕!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
flowApiService.submitConsign(taskInstance, activeMultiInstanceTask, newAssignees);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前用户待办的任务列表。
|
||||
*
|
||||
* @param processDefinitionKey 流程标识。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 返回当前用户待办的任务列表。如果指定流程标识,则仅返回该流程的待办任务列表。
|
||||
*/
|
||||
@PostMapping("/listRuntimeTask")
|
||||
public ResponseResult<MyPageData<FlowTaskVo>> listRuntimeTask(
|
||||
@MyRequestBody String processDefinitionKey,
|
||||
@MyRequestBody(required = true) MyPageParam pageParam) {
|
||||
String username = TokenData.takeFromRequest().getLoginName();
|
||||
MyPageData<Task> pageData = flowApiService.getTaskListByUserName(username, processDefinitionKey, pageParam);
|
||||
List<FlowTaskVo> flowTaskVoList = flowApiService.convertToFlowTaskList(pageData.getDataList());
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowTaskVoList, pageData.getTotalCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前用户待办的任务数量。
|
||||
*
|
||||
* @return 返回当前用户待办的任务数量。
|
||||
*/
|
||||
@PostMapping("/countRuntimeTask")
|
||||
public ResponseResult<Long> countRuntimeTask() {
|
||||
String username = TokenData.takeFromRequest().getLoginName();
|
||||
long totalCount = flowApiService.getTaskCountByUserName(username);
|
||||
return ResponseResult.success(totalCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前流程任务的审批列表。
|
||||
*
|
||||
* @param processInstanceId 当前运行时的流程实例Id。
|
||||
* @return 当前流程实例的详情数据。
|
||||
*/
|
||||
@GetMapping("/listFlowTaskComment")
|
||||
public ResponseResult<List<FlowTaskCommentVo>> listFlowTaskComment(@RequestParam String processInstanceId) {
|
||||
List<FlowTaskComment> flowTaskCommentList =
|
||||
flowTaskCommentService.getFlowTaskCommentList(processInstanceId);
|
||||
List<FlowTaskCommentVo> resultList = FlowTaskComment.INSTANCE.fromModelList(flowTaskCommentList);
|
||||
return ResponseResult.success(resultList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定流程定义的流程图。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @return 流程图。
|
||||
*/
|
||||
@GetMapping("/viewProcessBpmn")
|
||||
public ResponseResult<String> viewProcessBpmn(@RequestParam String processDefinitionId) throws IOException {
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
BpmnModel bpmnModel = flowApiService.getBpmnModelByDefinitionId(processDefinitionId);
|
||||
byte[] xmlBytes = converter.convertToXML(bpmnModel);
|
||||
InputStream in = new ByteArrayInputStream(xmlBytes);
|
||||
return ResponseResult.success(StreamUtils.copyToString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流程图高亮数据。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 流程图高亮数据。
|
||||
*/
|
||||
@GetMapping("/viewHighlightFlowData")
|
||||
public ResponseResult<JSONObject> viewHighlightFlowData(@RequestParam String processInstanceId) {
|
||||
HistoricProcessInstance hpi = flowApiService.getHistoricProcessInstance(processInstanceId);
|
||||
BpmnModel bpmnModel = flowApiService.getBpmnModelByDefinitionId(hpi.getProcessDefinitionId());
|
||||
List<Process> processList = bpmnModel.getProcesses();
|
||||
List<FlowElement> flowElementList = new LinkedList<>();
|
||||
processList.forEach(p -> flowElementList.addAll(p.getFlowElements()));
|
||||
Map<String, String> allSequenceFlowMap = new HashMap<>(16);
|
||||
for (FlowElement flowElement : flowElementList) {
|
||||
if (flowElement instanceof SequenceFlow) {
|
||||
SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
|
||||
String ref = sequenceFlow.getSourceRef();
|
||||
String targetRef = sequenceFlow.getTargetRef();
|
||||
allSequenceFlowMap.put(ref + targetRef, sequenceFlow.getId());
|
||||
}
|
||||
}
|
||||
Set<String> finishedTaskSet = new LinkedHashSet<>();
|
||||
//获取流程实例的历史节点(全部执行过的节点,被拒绝的任务节点将会出现多次)
|
||||
List<HistoricActivityInstance> activityInstanceList =
|
||||
flowApiService.getHistoricActivityInstanceList(processInstanceId);
|
||||
Set<String> finishedTaskSequenceSet = new LinkedHashSet<>();
|
||||
for (int i = 0; i < activityInstanceList.size(); i++) {
|
||||
HistoricActivityInstance current = activityInstanceList.get(i);
|
||||
if (i != activityInstanceList.size() - 1) {
|
||||
HistoricActivityInstance next = activityInstanceList.get(i + 1);
|
||||
finishedTaskSequenceSet.add(current.getActivityId() + next.getActivityId());
|
||||
}
|
||||
finishedTaskSet.add(current.getActivityId());
|
||||
}
|
||||
Set<String> finishedSequenceFlowSet = new HashSet<>();
|
||||
finishedTaskSequenceSet.forEach(s -> finishedSequenceFlowSet.add(allSequenceFlowMap.get(s)));
|
||||
//获取流程实例当前正在待办的节点
|
||||
List<HistoricActivityInstance> unfinishedInstanceList =
|
||||
flowApiService.getHistoricUnfinishedInstanceList(processInstanceId);
|
||||
Set<String> unfinishedTaskSet = new LinkedHashSet<>();
|
||||
for (HistoricActivityInstance unfinishedActivity : unfinishedInstanceList) {
|
||||
unfinishedTaskSet.add(unfinishedActivity.getActivityId());
|
||||
}
|
||||
JSONObject jsonData = new JSONObject();
|
||||
jsonData.put("finishedTaskSet", finishedTaskSet);
|
||||
jsonData.put("finishedSequenceFlowSet", finishedSequenceFlowSet);
|
||||
jsonData.put("unfinishedTaskSet", unfinishedTaskSet);
|
||||
return ResponseResult.success(jsonData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的已办理的审批任务列表。
|
||||
*
|
||||
* @param processDefinitionName 流程名。
|
||||
* @param beginDate 流程发起开始时间。
|
||||
* @param endDate 流程发起结束时间。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 查询结果应答。
|
||||
*/
|
||||
@PostMapping("/listHistoricTask")
|
||||
public ResponseResult<MyPageData<Map<String, Object>>> listHistoricTask(
|
||||
@MyRequestBody String processDefinitionName,
|
||||
@MyRequestBody String beginDate,
|
||||
@MyRequestBody String endDate,
|
||||
@MyRequestBody(required = true) MyPageParam pageParam) throws ParseException {
|
||||
MyPageData<HistoricTaskInstance> pageData =
|
||||
flowApiService.getHistoricTaskInstanceFinishedList(processDefinitionName, beginDate, endDate, pageParam);
|
||||
List<Map<String, Object>> resultList = new LinkedList<>();
|
||||
pageData.getDataList().forEach(instance -> resultList.add(BeanUtil.beanToMap(instance)));
|
||||
List<HistoricTaskInstance> taskInstanceList = pageData.getDataList();
|
||||
if (CollUtil.isNotEmpty(taskInstanceList)) {
|
||||
Set<String> instanceIdSet = taskInstanceList.stream()
|
||||
.map(HistoricTaskInstance::getProcessInstanceId).collect(Collectors.toSet());
|
||||
List<HistoricProcessInstance> instanceList = flowApiService.getHistoricProcessInstanceList(instanceIdSet);
|
||||
Map<String, HistoricProcessInstance> instanceMap =
|
||||
instanceList.stream().collect(Collectors.toMap(HistoricProcessInstance::getId, c -> c));
|
||||
resultList.forEach(result -> {
|
||||
HistoricProcessInstance instance = instanceMap.get(result.get("processInstanceId").toString());
|
||||
result.put("processDefinitionKey", instance.getProcessDefinitionKey());
|
||||
result.put("processDefinitionName", instance.getProcessDefinitionName());
|
||||
result.put("startUser", instance.getStartUserId());
|
||||
});
|
||||
}
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, pageData.getTotalCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据输入参数查询,当前用户的历史流程数据。
|
||||
*
|
||||
* @param processDefinitionName 流程名。
|
||||
* @param beginDate 流程发起开始时间。
|
||||
* @param endDate 流程发起结束时间。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 查询结果应答。
|
||||
*/
|
||||
@PostMapping("/listHistoricProcessInstance")
|
||||
public ResponseResult<MyPageData<Map<String, Object>>> listHistoricProcessInstance(
|
||||
@MyRequestBody String processDefinitionName,
|
||||
@MyRequestBody String beginDate,
|
||||
@MyRequestBody String endDate,
|
||||
@MyRequestBody(required = true) MyPageParam pageParam) throws ParseException {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
MyPageData<HistoricProcessInstance> pageData = flowApiService.getHistoricProcessInstanceList(
|
||||
null, processDefinitionName, loginName, beginDate, endDate, pageParam, true);
|
||||
List<Map<String, Object>> resultList = new LinkedList<>();
|
||||
pageData.getDataList().forEach(instance -> resultList.add(BeanUtil.beanToMap(instance)));
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, pageData.getTotalCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据输入参数查询,所有历史流程数据。
|
||||
*
|
||||
* @param processDefinitionName 流程名。
|
||||
* @param startUser 流程发起用户。
|
||||
* @param beginDate 流程发起开始时间。
|
||||
* @param endDate 流程发起结束时间。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 查询结果。
|
||||
*/
|
||||
@PostMapping("/listAllHistoricProcessInstance")
|
||||
public ResponseResult<MyPageData<Map<String, Object>>> listAllHistoricProcessInstance(
|
||||
@MyRequestBody String processDefinitionName,
|
||||
@MyRequestBody String startUser,
|
||||
@MyRequestBody String beginDate,
|
||||
@MyRequestBody String endDate,
|
||||
@MyRequestBody(required = true) MyPageParam pageParam) throws ParseException {
|
||||
MyPageData<HistoricProcessInstance> pageData = flowApiService.getHistoricProcessInstanceList(
|
||||
null, processDefinitionName, startUser, beginDate, endDate, pageParam, false);
|
||||
List<Map<String, Object>> resultList = new LinkedList<>();
|
||||
pageData.getDataList().forEach(instance -> resultList.add(BeanUtil.beanToMap(instance)));
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, pageData.getTotalCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消工作流工单,仅当没有进入任何审批流程之前,才可以取消工单。
|
||||
*
|
||||
* @param workOrderId 工单Id。
|
||||
* @param cancelReason 取消原因。
|
||||
* @return 应答结果。
|
||||
*/
|
||||
@PostMapping("/cancelWorkOrder")
|
||||
public ResponseResult<Void> cancelWorkOrder(
|
||||
@MyRequestBody(required = true) Long workOrderId,
|
||||
@MyRequestBody(required = true) String cancelReason) {
|
||||
FlowWorkOrder flowWorkOrder = flowWorkOrderService.getById(workOrderId);
|
||||
if (flowWorkOrder == null) {
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
|
||||
}
|
||||
String errorMessage;
|
||||
if (!flowWorkOrder.getFlowStatus().equals(FlowTaskStatus.SUBMITTED)) {
|
||||
errorMessage = "数据验证失败,当前流程已经进入审批状态,不能撤销工单!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!flowWorkOrder.getCreateUserId().equals(TokenData.takeFromRequest().getUserId())) {
|
||||
errorMessage = "数据验证失败,当前用户不是工单所有者,不能撤销工单!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
CallResult result = flowApiService.stopProcessInstance(
|
||||
flowWorkOrder.getProcessInstanceId(), cancelReason, true);
|
||||
if (!result.isSuccess()) {
|
||||
return ResponseResult.errorFrom(result);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止流程实例,将任务从当前节点直接流转到主流程的结束事件。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param stopReason 停止原因。
|
||||
* @return 执行结果应答。
|
||||
*/
|
||||
@PostMapping("/stopProcessInstance")
|
||||
public ResponseResult<Void> stopProcessInstance(
|
||||
@MyRequestBody(required = true) String processInstanceId,
|
||||
@MyRequestBody(required = true) String stopReason) {
|
||||
CallResult result = flowApiService.stopProcessInstance(processInstanceId, stopReason, false);
|
||||
if (!result.isSuccess()) {
|
||||
return ResponseResult.errorFrom(result);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流程实例。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 执行结果应答。
|
||||
*/
|
||||
@PostMapping("/deleteProcessInstance")
|
||||
public ResponseResult<Void> deleteProcessInstance(@MyRequestBody(required = true) String processInstanceId) {
|
||||
flowApiService.deleteProcessInstance(processInstanceId);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.flow.demo.common.flow.custom;
|
||||
|
||||
import org.activiti.api.runtime.shared.identity.UserGroupManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CustomUserGroupManager implements UserGroupManager {
|
||||
|
||||
@Override
|
||||
public List<String> getUserGroups(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUserRoles(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUsers() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowCategory;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FlowCategory数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowCategoryMapper extends BaseDaoMapper<FlowCategory> {
|
||||
|
||||
/**
|
||||
* 获取过滤后的对象列表。
|
||||
*
|
||||
* @param flowCategoryFilter 主表过滤对象。
|
||||
* @param orderBy 排序字符串,order by从句的参数。
|
||||
* @return 对象列表。
|
||||
*/
|
||||
List<FlowCategory> getFlowCategoryList(
|
||||
@Param("flowCategoryFilter") FlowCategory flowCategoryFilter, @Param("orderBy") String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowEntry;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FlowEntry数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryMapper extends BaseDaoMapper<FlowEntry> {
|
||||
|
||||
/**
|
||||
* 获取过滤后的对象列表。
|
||||
*
|
||||
* @param flowEntryFilter 主表过滤对象。
|
||||
* @param orderBy 排序字符串,order by从句的参数。
|
||||
* @return 对象列表。
|
||||
*/
|
||||
List<FlowEntry> getFlowEntryList(
|
||||
@Param("flowEntryFilter") FlowEntry flowEntryFilter, @Param("orderBy") String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowEntryPublish;
|
||||
|
||||
/**
|
||||
* 数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryPublishMapper extends BaseDaoMapper<FlowEntryPublish> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowEntryPublishVariable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryPublishVariableMapper extends BaseDaoMapper<FlowEntryPublishVariable> {
|
||||
|
||||
/**
|
||||
* 批量插入流程发布的变量列表。
|
||||
*
|
||||
* @param entryPublishVariableList 流程发布的变量列表。
|
||||
*/
|
||||
void insertList(List<FlowEntryPublishVariable> entryPublishVariableList);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowEntryVariable;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程变量数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryVariableMapper extends BaseDaoMapper<FlowEntryVariable> {
|
||||
|
||||
/**
|
||||
* 获取过滤后的对象列表。
|
||||
*
|
||||
* @param flowEntryVariableFilter 主表过滤对象。
|
||||
* @param orderBy 排序字符串,order by从句的参数。
|
||||
* @return 对象列表。
|
||||
*/
|
||||
List<FlowEntryVariable> getFlowEntryVariableList(
|
||||
@Param("flowEntryVariableFilter") FlowEntryVariable flowEntryVariableFilter,
|
||||
@Param("orderBy") String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowTaskComment;
|
||||
|
||||
/**
|
||||
* 流程任务批注数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowTaskCommentMapper extends BaseDaoMapper<FlowTaskComment> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowTaskExt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程任务扩展数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowTaskExtMapper extends BaseDaoMapper<FlowTaskExt> {
|
||||
|
||||
/**
|
||||
* 批量插入流程任务扩展信息列表。
|
||||
*
|
||||
* @param flowTaskExtList 流程任务扩展信息列表。
|
||||
*/
|
||||
void insertList(List<FlowTaskExt> flowTaskExtList);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.flow.demo.common.flow.dao;
|
||||
|
||||
import com.flow.demo.common.core.annotation.EnableDataPerm;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.flow.model.FlowWorkOrder;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 工作流工单表数据操作访问接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@EnableDataPerm
|
||||
public interface FlowWorkOrderMapper extends BaseDaoMapper<FlowWorkOrder> {
|
||||
|
||||
/**
|
||||
* 获取过滤后的对象列表。
|
||||
*
|
||||
* @param flowWorkOrderFilter 主表过滤对象。
|
||||
* @param orderBy 排序字符串,order by从句的参数。
|
||||
* @return 对象列表。
|
||||
*/
|
||||
List<FlowWorkOrder> getFlowWorkOrderList(
|
||||
@Param("flowWorkOrderFilter") FlowWorkOrder flowWorkOrderFilter, @Param("orderBy") String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowCategoryMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowCategory">
|
||||
<id column="category_id" jdbcType="BIGINT" property="categoryId"/>
|
||||
<result column="name" jdbcType="VARCHAR" property="name"/>
|
||||
<result column="code" jdbcType="VARCHAR" property="code"/>
|
||||
<result column="show_order" jdbcType="INTEGER" property="showOrder"/>
|
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
|
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
|
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="getFlowCategoryList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.flow.model.FlowCategory">
|
||||
SELECT * FROM zz_flow_category
|
||||
<if test="orderBy != null and orderBy != ''">
|
||||
ORDER BY ${orderBy}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowEntryMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowEntry">
|
||||
<id column="entry_id" jdbcType="BIGINT" property="entryId"/>
|
||||
<result column="process_definition_name" jdbcType="VARCHAR" property="processDefinitionName"/>
|
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/>
|
||||
<result column="category_id" jdbcType="BIGINT" property="categoryId"/>
|
||||
<result column="main_entry_publish_id" jdbcType="BIGINT" property="mainEntryPublishId"/>
|
||||
<result column="lastest_publish_time" jdbcType="TIMESTAMP" property="lastestPublishTime"/>
|
||||
<result column="status" jdbcType="INTEGER" property="status"/>
|
||||
<result column="bpmn_xml" jdbcType="LONGVARCHAR" property="bpmnXml"/>
|
||||
<result column="bind_form_type" jdbcType="INTEGER" property="bindFormType"/>
|
||||
<result column="page_id" jdbcType="BIGINT" property="pageId"/>
|
||||
<result column="default_form_id" jdbcType="BIGINT" property="defaultFormId"/>
|
||||
<result column="default_router_name" jdbcType="VARCHAR" property="defaultRouterName"/>
|
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
|
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
|
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
|
||||
<sql id="filterRef">
|
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
|
||||
<include refid="com.flow.demo.common.flow.dao.FlowEntryMapper.inputFilterRef"/>
|
||||
</sql>
|
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
|
||||
<sql id="inputFilterRef">
|
||||
<if test="flowEntryFilter != null">
|
||||
<if test="flowEntryFilter.processDefinitionName != null and flowEntryFilter.processDefinitionName != ''">
|
||||
AND zz_flow_entry.process_definition_name = #{flowEntryFilter.processDefinitionName}
|
||||
</if>
|
||||
<if test="flowEntryFilter.processDefinitionKey != null and flowEntryFilter.processDefinitionKey != ''">
|
||||
AND zz_flow_entry.process_definition_key = #{flowEntryFilter.processDefinitionKey}
|
||||
</if>
|
||||
<if test="flowEntryFilter.categoryId != null">
|
||||
AND zz_flow_entry.category_id = #{flowEntryFilter.categoryId}
|
||||
</if>
|
||||
<if test="flowEntryFilter.status != null">
|
||||
AND zz_flow_entry.status = #{flowEntryFilter.status}
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="getFlowEntryList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.flow.model.FlowEntry">
|
||||
SELECT
|
||||
entry_id,
|
||||
process_definition_name,
|
||||
process_definition_key,
|
||||
category_id,
|
||||
main_entry_publish_id,
|
||||
lastest_publish_time,
|
||||
status,
|
||||
bind_form_type,
|
||||
page_id,
|
||||
default_form_id,
|
||||
default_router_name,
|
||||
update_time,
|
||||
update_user_id,
|
||||
create_time,
|
||||
create_user_id
|
||||
FROM
|
||||
zz_flow_entry
|
||||
<where>
|
||||
<include refid="filterRef"/>
|
||||
</where>
|
||||
<if test="orderBy != null and orderBy != ''">
|
||||
ORDER BY ${orderBy}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowEntryPublishMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowEntryPublish">
|
||||
<id column="entry_publish_id" jdbcType="BIGINT" property="entryPublishId"/>
|
||||
<result column="entry_id" jdbcType="BIGINT" property="entryId"/>
|
||||
<result column="deploy_id" jdbcType="VARCHAR" property="deployId"/>
|
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/>
|
||||
<result column="publish_version" jdbcType="INTEGER" property="publishVersion"/>
|
||||
<result column="active_status" jdbcType="BIT" property="activeStatus"/>
|
||||
<result column="main_version" jdbcType="BIT" property="mainVersion"/>
|
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
|
||||
<result column="publish_time" jdbcType="TIMESTAMP" property="publishTime"/>
|
||||
<result column="init_task_info" jdbcType="VARCHAR" property="initTaskInfo"/>
|
||||
</resultMap>
|
||||
</mapper>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowEntryPublishVariableMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowEntryPublishVariable">
|
||||
<id column="variable_id" jdbcType="BIGINT" property="variableId"/>
|
||||
<result column="entry_publish_id" jdbcType="BIGINT" property="entryPublishId"/>
|
||||
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/>
|
||||
<result column="show_name" jdbcType="VARCHAR" property="showName"/>
|
||||
<result column="variable_type" jdbcType="INTEGER" property="variableType"/>
|
||||
<result column="bind_datasource_id" jdbcType="BIGINT" property="bindDatasourceId"/>
|
||||
<result column="bind_relation_id" jdbcType="BIGINT" property="bindRelationId"/>
|
||||
<result column="bind_column_id" jdbcType="BIGINT" property="bindColumnId"/>
|
||||
<result column="builtin" jdbcType="BIT" property="builtin"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertList">
|
||||
INSERT INTO zz_flow_entry_publish_variable VALUES
|
||||
<foreach collection="list" index="index" item="item" separator="," >
|
||||
(#{item.variableId},
|
||||
#{item.entryPublishId},
|
||||
#{item.variableName},
|
||||
#{item.showName},
|
||||
#{item.variableType},
|
||||
#{item.bindDatasourceId},
|
||||
#{item.bindRelationId},
|
||||
#{item.bindColumnId},
|
||||
#{item.builtin})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowEntryVariableMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowEntryVariable">
|
||||
<id column="variable_id" jdbcType="BIGINT" property="variableId"/>
|
||||
<result column="entry_id" jdbcType="BIGINT" property="entryId"/>
|
||||
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/>
|
||||
<result column="show_name" jdbcType="VARCHAR" property="showName"/>
|
||||
<result column="variable_type" jdbcType="INTEGER" property="variableType"/>
|
||||
<result column="bind_datasource_id" jdbcType="BIGINT" property="bindDatasourceId"/>
|
||||
<result column="bind_relation_id" jdbcType="BIGINT" property="bindRelationId"/>
|
||||
<result column="bind_column_id" jdbcType="BIGINT" property="bindColumnId"/>
|
||||
<result column="builtin" jdbcType="BIT" property="builtin"/>
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
|
||||
<sql id="filterRef">
|
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
|
||||
<include refid="com.flow.demo.common.flow.dao.FlowEntryVariableMapper.inputFilterRef"/>
|
||||
</sql>
|
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
|
||||
<sql id="inputFilterRef">
|
||||
<if test="flowEntryVariableFilter != null">
|
||||
<if test="flowEntryVariableFilter.entryId != null">
|
||||
AND zz_flow_entry_variable.entry_id = #{flowEntryVariableFilter.entryId}
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="getFlowEntryVariableList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.flow.model.FlowEntryVariable">
|
||||
SELECT * FROM zz_flow_entry_variable
|
||||
<where>
|
||||
<include refid="filterRef"/>
|
||||
</where>
|
||||
<if test="orderBy != null and orderBy != ''">
|
||||
ORDER BY ${orderBy}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowTaskCommentMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowTaskComment">
|
||||
<id column="id" jdbcType="BIGINT" property="id"/>
|
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/>
|
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/>
|
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/>
|
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName"/>
|
||||
<result column="approval_type" jdbcType="VARCHAR" property="approvalType"/>
|
||||
<result column="delegate_assignee" jdbcType="VARCHAR" property="delegateAssginee"/>
|
||||
<result column="comment" jdbcType="VARCHAR" property="comment"/>
|
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
|
||||
<result column="create_username" jdbcType="VARCHAR" property="createUsername"/>
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
|
||||
</resultMap>
|
||||
</mapper>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowTaskExtMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowTaskExt">
|
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/>
|
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/>
|
||||
<result column="operation_list_json" jdbcType="LONGVARCHAR" property="operationListJson"/>
|
||||
<result column="variable_list_json" jdbcType="LONGVARCHAR" property="variableListJson"/>
|
||||
<result column="assignee_list_json" jdbcType="LONGVARCHAR" property="assigneeListJson"/>
|
||||
<result column="group_type" jdbcType="VARCHAR" property="groupType"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertList">
|
||||
INSERT INTO zz_flow_task_ext VALUES
|
||||
<foreach collection="list" index="index" item="item" separator="," >
|
||||
(#{item.processDefinitionId},
|
||||
#{item.taskId},
|
||||
#{item.operationListJson},
|
||||
#{item.variableListJson},
|
||||
#{item.assigneeListJson},
|
||||
#{item.groupType})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.flow.demo.common.flow.dao.FlowWorkOrderMapper">
|
||||
<resultMap id="BaseResultMap" type="com.flow.demo.common.flow.model.FlowWorkOrder">
|
||||
<id column="work_order_id" jdbcType="BIGINT" property="workOrderId"/>
|
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/>
|
||||
<result column="process_definition_name" jdbcType="VARCHAR" property="processDefinitionName"/>
|
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/>
|
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/>
|
||||
<result column="online_table_id" jdbcType="BIGINT" property="onlineTableId"/>
|
||||
<result column="business_key" jdbcType="VARCHAR" property="businessKey"/>
|
||||
<result column="flow_status" jdbcType="INTEGER" property="flowStatus"/>
|
||||
<result column="submit_username" jdbcType="VARCHAR" property="submitUsername"/>
|
||||
<result column="dept_id" jdbcType="BIGINT" property="deptId"/>
|
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
|
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
|
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
|
||||
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
|
||||
<sql id="filterRef">
|
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
|
||||
<include refid="inputFilterRef"/>
|
||||
AND zz_flow_work_order.deleted_flag = ${@com.flow.demo.common.core.constant.GlobalDeletedFlag@NORMAL}
|
||||
</sql>
|
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
|
||||
<sql id="inputFilterRef">
|
||||
<if test="flowWorkOrderFilter != null">
|
||||
<if test="flowWorkOrderFilter.processDefinitionKey != null and flowWorkOrderFilter.processDefinitionKey != ''">
|
||||
AND zz_flow_work_order.process_definition_key = #{flowWorkOrderFilter.processDefinitionKey}
|
||||
</if>
|
||||
<if test="flowWorkOrderFilter.flowStatus != null">
|
||||
AND zz_flow_work_order.flow_status = #{flowWorkOrderFilter.flowStatus}
|
||||
</if>
|
||||
<if test="flowWorkOrderFilter.createTimeStart != null and flowWorkOrderFilter.createTimeStart != ''">
|
||||
AND zz_flow_work_order.create_time >= #{flowWorkOrderFilter.createTimeStart}
|
||||
</if>
|
||||
<if test="flowWorkOrderFilter.createTimeEnd != null and flowWorkOrderFilter.createTimeEnd != ''">
|
||||
AND zz_flow_work_order.create_time <= #{flowWorkOrderFilter.createTimeEnd}
|
||||
</if>
|
||||
<if test="flowWorkOrderFilter.createUserId != null">
|
||||
AND zz_flow_work_order.create_user_id = #{flowWorkOrderFilter.createUserId}
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="getFlowWorkOrderList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.flow.model.FlowWorkOrder">
|
||||
SELECT * FROM zz_flow_work_order
|
||||
<where>
|
||||
<include refid="filterRef"/>
|
||||
</where>
|
||||
<if test="orderBy != null and orderBy != ''">
|
||||
ORDER BY ${orderBy}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.flow.demo.common.flow.dto;
|
||||
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 流程分类的Dto对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowCategoryDto {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class})
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 显示名称。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,显示名称不能为空!")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 分类编码。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,分类编码不能为空!")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 实现顺序。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,实现顺序不能为空!")
|
||||
private Integer showOrder;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.flow.demo.common.flow.dto;
|
||||
|
||||
import com.flow.demo.common.core.validator.ConstDictRef;
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import com.flow.demo.common.flow.model.constant.FlowBindFormType;
|
||||
import com.flow.demo.common.flow.model.constant.FlowEntryStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 流程的Dto对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowEntryDto {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,主键不能为空!", groups = {UpdateGroup.class})
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 流程名称。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,流程名称不能为空!")
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程标识Key。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,流程标识Key不能为空!")
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程分类。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,流程分类不能为空!")
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 流程状态。
|
||||
*/
|
||||
@ConstDictRef(constDictClass = FlowEntryStatus.class, message = "数据验证失败,工作流状态为无效值!")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 流程定义的xml。
|
||||
*/
|
||||
private String bpmnXml;
|
||||
|
||||
/**
|
||||
* 绑定表单类型。
|
||||
*/
|
||||
@ConstDictRef(constDictClass = FlowBindFormType.class, message = "数据验证失败,工作流绑定表单类型为无效值!")
|
||||
@NotNull(message = "数据验证失败,工作流绑定表单类型不能为空!")
|
||||
private Integer bindFormType;
|
||||
|
||||
/**
|
||||
* 在线表单的页面Id。
|
||||
*/
|
||||
private Long pageId;
|
||||
|
||||
/**
|
||||
* 在线表单Id。
|
||||
*/
|
||||
private Long defaultFormId;
|
||||
|
||||
/**
|
||||
* 在线表单的缺省路由名称。
|
||||
*/
|
||||
private String defaultRouterName;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.flow.demo.common.flow.dto;
|
||||
|
||||
import com.flow.demo.common.core.validator.ConstDictRef;
|
||||
import com.flow.demo.common.core.validator.UpdateGroup;
|
||||
import com.flow.demo.common.flow.model.constant.FlowVariableType;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* 流程变量Dto对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowEntryVariableDto {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class})
|
||||
private Long variableId;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,流程Id不能为空!")
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 变量名。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,变量名不能为空!")
|
||||
private String variableName;
|
||||
|
||||
/**
|
||||
* 显示名。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,显示名不能为空!")
|
||||
private String showName;
|
||||
|
||||
/**
|
||||
* 流程变量类型。
|
||||
*/
|
||||
@ConstDictRef(constDictClass = FlowVariableType.class, message = "数据验证失败,流程变量类型为无效值!")
|
||||
@NotNull(message = "数据验证失败,流程变量类型不能为空!")
|
||||
private Integer variableType;
|
||||
|
||||
/**
|
||||
* 绑定数据源Id。
|
||||
*/
|
||||
private Long bindDatasourceId;
|
||||
|
||||
/**
|
||||
* 绑定数据源关联Id。
|
||||
*/
|
||||
private Long bindRelationId;
|
||||
|
||||
/**
|
||||
* 绑定字段Id。
|
||||
*/
|
||||
private Long bindColumnId;
|
||||
|
||||
/**
|
||||
* 是否内置。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,是否内置不能为空!")
|
||||
private Boolean builtin;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.flow.demo.common.flow.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 流程任务的批注。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowTaskCommentDto {
|
||||
|
||||
/**
|
||||
* 流程任务触发按钮类型,内置值可参考FlowTaskButton。
|
||||
*/
|
||||
@NotNull(message = "数据验证失败,任务的审批类型不能为空!")
|
||||
private String approvalType;
|
||||
|
||||
/**
|
||||
* 流程任务的批注内容。
|
||||
*/
|
||||
@NotBlank(message = "数据验证失败,任务审批内容不能为空!")
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 委托指定人,比如加签、转办等。
|
||||
*/
|
||||
private String delegateAssginee;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.flow.demo.common.flow.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 工作流工单Dto对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowWorkOrderDto {
|
||||
|
||||
/**
|
||||
* 流程状态。参考FlowTaskStatus常量值对象。
|
||||
*/
|
||||
private Integer flowStatus;
|
||||
|
||||
/**
|
||||
* createTime 范围过滤起始值(>=)。
|
||||
*/
|
||||
private String createTimeStart;
|
||||
|
||||
/**
|
||||
* createTime 范围过滤结束值(<=)。
|
||||
*/
|
||||
private String createTimeEnd;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.flow.demo.common.flow.exception;
|
||||
|
||||
/**
|
||||
* 流程操作异常。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public class FlowOperationException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
*/
|
||||
public FlowOperationException() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
*
|
||||
* @param throwable 引发异常对象。
|
||||
*/
|
||||
public FlowOperationException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
*
|
||||
* @param msg 错误信息。
|
||||
*/
|
||||
public FlowOperationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.flow.demo.common.flow.listener;
|
||||
|
||||
import com.flow.demo.common.core.util.ApplicationContextHolder;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.service.FlowApiService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.delegate.DelegateTask;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 当用户任务的候选组为本部门领导岗位时,该监听器会在任务创建时,获取当前流程实例发起人的部门领导。
|
||||
* 并将其指派为当前任务的候选组。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
public class DeptPostLeaderListener implements TaskListener {
|
||||
|
||||
private final FlowApiService flowApiService = ApplicationContextHolder.getBean(FlowApiService.class);
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
HistoricProcessInstance instance =
|
||||
flowApiService.getHistoricProcessInstance(delegateTask.getProcessInstanceId());
|
||||
Map<String, Object> variables = delegateTask.getVariables();
|
||||
if (variables.get(FlowConstant.GROUP_TYPE_DEPT_POST_LEADER_VAR) == null) {
|
||||
delegateTask.setAssignee(variables.get(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.flow.demo.common.flow.listener;
|
||||
|
||||
import com.flow.demo.common.core.util.ApplicationContextHolder;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.service.FlowApiService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.delegate.DelegateTask;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 当用户任务的候选组为上级部门领导岗位时,该监听器会在任务创建时,获取当前流程实例发起人的部门领导。
|
||||
* 并将其指派为当前任务的候选组。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
public class UpDeptPostLeaderListener implements TaskListener {
|
||||
|
||||
private final FlowApiService flowApiService = ApplicationContextHolder.getBean(FlowApiService.class);
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
HistoricProcessInstance instance =
|
||||
flowApiService.getHistoricProcessInstance(delegateTask.getProcessInstanceId());
|
||||
Map<String, Object> variables = delegateTask.getVariables();
|
||||
if (variables.get(FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER_VAR) == null) {
|
||||
delegateTask.setAssignee(variables.get(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.flow.demo.common.flow.listener;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.flow.demo.common.core.util.ApplicationContextHolder;
|
||||
import com.flow.demo.common.flow.service.FlowWorkOrderService;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.delegate.DelegateExecution;
|
||||
import org.activiti.engine.delegate.ExecutionListener;
|
||||
|
||||
/**
|
||||
* 流程实例监听器,在流程实例结束的时候更新流程工单表的审批状态字段。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
public class UpdateFlowStatusListener implements ExecutionListener {
|
||||
|
||||
private final FlowWorkOrderService flowWorkOrderService =
|
||||
ApplicationContextHolder.getBean(FlowWorkOrderService.class);
|
||||
|
||||
@Override
|
||||
public void notify(DelegateExecution execution) {
|
||||
if (!StrUtil.equals("end", execution.getEventName())) {
|
||||
return;
|
||||
}
|
||||
String processInstanceId = execution.getProcessInstanceId();
|
||||
flowWorkOrderService.updateFlowStatusByProcessInstanceId(processInstanceId, FlowTaskStatus.FINISHED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
|
||||
import com.flow.demo.common.flow.vo.FlowCategoryVo;
|
||||
import lombok.Data;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程分类的实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_category")
|
||||
public class FlowCategory {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "category_id")
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 显示名称。
|
||||
*/
|
||||
@TableField(value = "name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 分类编码。
|
||||
*/
|
||||
@TableField(value = "code")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 实现顺序。
|
||||
*/
|
||||
@TableField(value = "show_order")
|
||||
private Integer showOrder;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
@TableField(value = "update_user_id")
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
@TableField(value = "create_user_id")
|
||||
private Long createUserId;
|
||||
|
||||
@Mapper
|
||||
public interface FlowCategoryModelMapper extends BaseModelMapper<FlowCategoryVo, FlowCategory> {
|
||||
}
|
||||
public static final FlowCategoryModelMapper INSTANCE = Mappers.getMapper(FlowCategoryModelMapper.class);
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.flow.demo.common.core.annotation.RelationOneToOne;
|
||||
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
|
||||
import com.flow.demo.common.flow.vo.FlowEntryVo;
|
||||
import lombok.Data;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程的实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_entry")
|
||||
public class FlowEntry {
|
||||
|
||||
/**
|
||||
* 主键。
|
||||
*/
|
||||
@TableId(value = "entry_id")
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 流程名称。
|
||||
*/
|
||||
@TableField(value = "process_definition_name")
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程标识Key。
|
||||
*/
|
||||
@TableField(value = "process_definition_key")
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程分类。
|
||||
*/
|
||||
@TableField(value = "category_id")
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 工作流部署的发布主版本Id。
|
||||
*/
|
||||
@TableField(value = "main_entry_publish_id")
|
||||
private Long mainEntryPublishId;
|
||||
|
||||
/**
|
||||
* 最新发布时间。
|
||||
*/
|
||||
@TableField(value = "lastest_publish_time")
|
||||
private Date lastestPublishTime;
|
||||
|
||||
/**
|
||||
* 流程状态。
|
||||
*/
|
||||
@TableField(value = "status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 流程定义的xml。
|
||||
*/
|
||||
@TableField(value = "bpmn_xml")
|
||||
private String bpmnXml;
|
||||
|
||||
/**
|
||||
* 绑定表单类型。
|
||||
*/
|
||||
@TableField(value = "bind_form_type")
|
||||
private Integer bindFormType;
|
||||
|
||||
/**
|
||||
* 在线表单的页面Id。
|
||||
*/
|
||||
@TableField(value = "page_id")
|
||||
private Long pageId;
|
||||
|
||||
/**
|
||||
* 在线表单Id。
|
||||
*/
|
||||
@TableField(value = "default_form_id")
|
||||
private Long defaultFormId;
|
||||
|
||||
/**
|
||||
* 静态表单的缺省路由名称。
|
||||
*/
|
||||
@TableField(value = "default_router_name")
|
||||
private String defaultRouterName;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
@TableField(value = "update_user_id")
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
@TableField(value = "create_user_id")
|
||||
private Long createUserId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private FlowEntryPublish mainFlowEntryPublish;
|
||||
|
||||
@RelationOneToOne(
|
||||
masterIdField = "categoryId",
|
||||
slaveServiceName = "flowCategoryService",
|
||||
slaveModelClass = FlowCategory.class,
|
||||
slaveIdField = "categoryId")
|
||||
@TableField(exist = false)
|
||||
private FlowCategory flowCategory;
|
||||
|
||||
@Mapper
|
||||
public interface FlowEntryModelMapper extends BaseModelMapper<FlowEntryVo, FlowEntry> {
|
||||
/**
|
||||
* 转换Vo对象到实体对象。
|
||||
*
|
||||
* @param flowEntryVo 域对象。
|
||||
* @return 实体对象。
|
||||
*/
|
||||
@Mapping(target = "mainFlowEntryPublish", expression = "java(mapToBean(flowEntryVo.getMainFlowEntryPublish(), com.flow.demo.common.flow.model.FlowEntryPublish.class))")
|
||||
@Mapping(target = "flowCategory", expression = "java(mapToBean(flowEntryVo.getFlowCategory(), com.flow.demo.common.flow.model.FlowCategory.class))")
|
||||
@Override
|
||||
FlowEntry toModel(FlowEntryVo flowEntryVo);
|
||||
/**
|
||||
* 转换实体对象到VO对象。
|
||||
*
|
||||
* @param flowEntry 实体对象。
|
||||
* @return 域对象。
|
||||
*/
|
||||
@Mapping(target = "mainFlowEntryPublish", expression = "java(beanToMap(flowEntry.getMainFlowEntryPublish(), false))")
|
||||
@Mapping(target = "flowCategory", expression = "java(beanToMap(flowEntry.getFlowCategory(), false))")
|
||||
@Override
|
||||
FlowEntryVo fromModel(FlowEntry flowEntry);
|
||||
}
|
||||
public static final FlowEntryModelMapper INSTANCE = Mappers.getMapper(FlowEntryModelMapper.class);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程发布数据的实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_entry_publish")
|
||||
public class FlowEntryPublish {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "entry_publish_id")
|
||||
private Long entryPublishId;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
@TableField(value = "entry_id")
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 流程引擎的部署Id。
|
||||
*/
|
||||
@TableField(value = "deploy_id")
|
||||
private String deployId;
|
||||
|
||||
/**
|
||||
* 流程引擎中的流程定义Id。
|
||||
*/
|
||||
@TableField(value = "process_definition_id")
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 发布版本。
|
||||
*/
|
||||
@TableField(value = "publish_version")
|
||||
private Integer publishVersion;
|
||||
|
||||
/**
|
||||
* 激活状态。
|
||||
*/
|
||||
@TableField(value = "active_status")
|
||||
private Boolean activeStatus;
|
||||
|
||||
/**
|
||||
* 是否为主版本。
|
||||
*/
|
||||
@TableField(value = "main_version")
|
||||
private Boolean mainVersion;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
@TableField(value = "create_user_id")
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 发布时间。
|
||||
*/
|
||||
@TableField(value = "publish_time")
|
||||
private Date publishTime;
|
||||
|
||||
/**
|
||||
* 第一个非开始节点任务的附加信息。
|
||||
*/
|
||||
@TableField(value = "init_task_info")
|
||||
private String initTaskInfo;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* FlowEntryPublishVariable实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_entry_publish_variable")
|
||||
public class FlowEntryPublishVariable {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "variable_id")
|
||||
private Long variableId;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
@TableField(value = "entry_publish_id")
|
||||
private Long entryPublishId;
|
||||
|
||||
/**
|
||||
* 变量名。
|
||||
*/
|
||||
@TableField(value = "variable_name")
|
||||
private String variableName;
|
||||
|
||||
/**
|
||||
* 显示名。
|
||||
*/
|
||||
@TableField(value = "show_name")
|
||||
private String showName;
|
||||
|
||||
/**
|
||||
* 变量类型。
|
||||
*/
|
||||
@TableField(value = "variable_type")
|
||||
private Integer variableType;
|
||||
|
||||
/**
|
||||
* 绑定数据源Id。
|
||||
*/
|
||||
@TableField(value = "bind_datasource_id")
|
||||
private Long bindDatasourceId;
|
||||
|
||||
/**
|
||||
* 绑定数据源关联Id。
|
||||
*/
|
||||
@TableField(value = "bind_relation_id")
|
||||
private Long bindRelationId;
|
||||
|
||||
/**
|
||||
* 绑定字段Id。
|
||||
*/
|
||||
@TableField(value = "bind_column_id")
|
||||
private Long bindColumnId;
|
||||
|
||||
/**
|
||||
* 是否内置。
|
||||
*/
|
||||
@TableField(value = "builtin")
|
||||
private Boolean builtin;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
|
||||
import com.flow.demo.common.flow.vo.FlowEntryVariableVo;
|
||||
import lombok.Data;
|
||||
import org.mapstruct.*;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程变量实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_entry_variable")
|
||||
public class FlowEntryVariable {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "variable_id")
|
||||
private Long variableId;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
@TableField(value = "entry_id")
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 变量名。
|
||||
*/
|
||||
@TableField(value = "variable_name")
|
||||
private String variableName;
|
||||
|
||||
/**
|
||||
* 显示名。
|
||||
*/
|
||||
@TableField(value = "show_name")
|
||||
private String showName;
|
||||
|
||||
/**
|
||||
* 流程变量类型。
|
||||
*/
|
||||
@TableField(value = "variable_type")
|
||||
private Integer variableType;
|
||||
|
||||
/**
|
||||
* 绑定数据源Id。
|
||||
*/
|
||||
@TableField(value = "bind_datasource_id")
|
||||
private Long bindDatasourceId;
|
||||
|
||||
/**
|
||||
* 绑定数据源关联Id。
|
||||
*/
|
||||
@TableField(value = "bind_relation_id")
|
||||
private Long bindRelationId;
|
||||
|
||||
/**
|
||||
* 绑定字段Id。
|
||||
*/
|
||||
@TableField(value = "bind_column_id")
|
||||
private Long bindColumnId;
|
||||
|
||||
/**
|
||||
* 是否内置。
|
||||
*/
|
||||
@TableField(value = "builtin")
|
||||
private Boolean builtin;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
@Mapper
|
||||
public interface FlowEntryVariableModelMapper extends BaseModelMapper<FlowEntryVariableVo, FlowEntryVariable> {
|
||||
}
|
||||
public static final FlowEntryVariableModelMapper INSTANCE = Mappers.getMapper(FlowEntryVariableModelMapper.class);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
|
||||
import com.flow.demo.common.flow.vo.FlowTaskCommentVo;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.activiti.engine.task.TaskInfo;
|
||||
import org.mapstruct.*;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* FlowTaskComment实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "zz_flow_task_comment")
|
||||
public class FlowTaskComment {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 流程实例Id。
|
||||
*/
|
||||
@TableField(value = "process_instance_id")
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 任务Id。
|
||||
*/
|
||||
@TableField(value = "task_id")
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 任务标识。
|
||||
*/
|
||||
@TableField(value = "task_key")
|
||||
private String taskKey;
|
||||
|
||||
/**
|
||||
* 任务名称。
|
||||
*/
|
||||
@TableField(value = "task_name")
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 审批类型。
|
||||
*/
|
||||
@TableField(value = "approval_type")
|
||||
private String approvalType;
|
||||
|
||||
/**
|
||||
* 批注内容。
|
||||
*/
|
||||
@TableField(value = "comment")
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 委托指定人,比如加签、转办等。
|
||||
*/
|
||||
@TableField(value = "delegate_assignee")
|
||||
private String delegateAssginee;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
@TableField(value = "create_user_id")
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 创建者显示名。
|
||||
*/
|
||||
@TableField(value = "create_username")
|
||||
private String createUsername;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
public FlowTaskComment(TaskInfo task) {
|
||||
this.fillWith(task);
|
||||
}
|
||||
|
||||
public void fillWith(TaskInfo task) {
|
||||
this.taskId = task.getId();
|
||||
this.taskKey = task.getTaskDefinitionKey();
|
||||
this.taskName = task.getName();
|
||||
this.processInstanceId = task.getProcessInstanceId();
|
||||
}
|
||||
|
||||
@Mapper
|
||||
public interface FlowTaskCommentModelMapper extends BaseModelMapper<FlowTaskCommentVo, FlowTaskComment> {
|
||||
}
|
||||
public static final FlowTaskCommentModelMapper INSTANCE = Mappers.getMapper(FlowTaskCommentModelMapper.class);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 流程任务扩展实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_task_ext")
|
||||
public class FlowTaskExt {
|
||||
|
||||
/**
|
||||
* 流程引擎的定义Id。
|
||||
*/
|
||||
@TableField(value = "process_definition_id")
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程引擎任务Id。
|
||||
*/
|
||||
@TableField(value = "task_id")
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 操作列表JSON。
|
||||
*/
|
||||
@TableField(value = "operation_list_json")
|
||||
private String operationListJson;
|
||||
|
||||
/**
|
||||
* 变量列表JSON。
|
||||
*/
|
||||
@TableField(value = "variable_list_json")
|
||||
private String variableListJson;
|
||||
|
||||
/**
|
||||
* 存储多实例的assigneeList的JSON。
|
||||
*/
|
||||
@TableField(value = "assignee_list_json")
|
||||
private String assigneeListJson;
|
||||
|
||||
/**
|
||||
* 分组类型。
|
||||
*/
|
||||
@TableField(value = "group_type")
|
||||
private String groupType;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.flow.demo.common.flow.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.flow.demo.common.core.annotation.DeptFilterColumn;
|
||||
import com.flow.demo.common.core.annotation.RelationConstDict;
|
||||
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.vo.FlowWorkOrderVo;
|
||||
import lombok.Data;
|
||||
import org.mapstruct.*;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流工单实体对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "zz_flow_work_order")
|
||||
public class FlowWorkOrder {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
@TableId(value = "work_order_id")
|
||||
private Long workOrderId;
|
||||
|
||||
/**
|
||||
* 流程定义标识。
|
||||
*/
|
||||
@TableField(value = "process_definition_key")
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程名称。
|
||||
*/
|
||||
@TableField(value = "process_definition_name")
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程引擎的定义Id。
|
||||
*/
|
||||
@TableField(value = "process_definition_id")
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程实例Id。
|
||||
*/
|
||||
@TableField(value = "process_instance_id")
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 在线表单的主表Id。
|
||||
*/
|
||||
@TableField(value = "online_table_id")
|
||||
private Long onlineTableId;
|
||||
|
||||
/**
|
||||
* 业务主键值。
|
||||
*/
|
||||
@TableField(value = "business_key")
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 流程状态。参考FlowTaskStatus常量值对象。
|
||||
*/
|
||||
@TableField(value = "flow_status")
|
||||
private Integer flowStatus;
|
||||
|
||||
/**
|
||||
* 提交用户登录名称。
|
||||
*/
|
||||
@TableField(value = "submit_username")
|
||||
private String submitUsername;
|
||||
|
||||
/**
|
||||
* 提交用户所在部门Id。
|
||||
*/
|
||||
@DeptFilterColumn
|
||||
@TableField(value = "dept_id")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
@TableField(value = "update_time")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
@TableField(value = "update_user_id")
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
@TableField(value = "create_user_id")
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 逻辑删除标记字段(1: 正常 -1: 已删除)。
|
||||
*/
|
||||
@TableLogic
|
||||
@TableField(value = "deleted_flag")
|
||||
private Integer deletedFlag;
|
||||
|
||||
/**
|
||||
* createTime 范围过滤起始值(>=)。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String createTimeStart;
|
||||
|
||||
/**
|
||||
* createTime 范围过滤结束值(<=)。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String createTimeEnd;
|
||||
|
||||
@RelationConstDict(
|
||||
masterIdField = "flowStatus",
|
||||
constantDictClass = FlowTaskStatus.class)
|
||||
@TableField(exist = false)
|
||||
private Map<String, Object> flowStatusDictMap;
|
||||
|
||||
@Mapper
|
||||
public interface FlowWorkOrderModelMapper extends BaseModelMapper<FlowWorkOrderVo, FlowWorkOrder> {
|
||||
}
|
||||
public static final FlowWorkOrderModelMapper INSTANCE = Mappers.getMapper(FlowWorkOrderModelMapper.class);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.flow.demo.common.flow.model.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流绑定表单类型。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowBindFormType {
|
||||
|
||||
/**
|
||||
* 在线表单。
|
||||
*/
|
||||
public static final int ONLINE_FORM = 0;
|
||||
/**
|
||||
* 路由表单。
|
||||
*/
|
||||
public static final int ROUTER_FORM = 1;
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(ONLINE_FORM, "在线表单");
|
||||
DICT_MAP.put(ROUTER_FORM, "路由表单");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowBindFormType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.flow.demo.common.flow.model.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流状态。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowEntryStatus {
|
||||
|
||||
/**
|
||||
* 未发布。
|
||||
*/
|
||||
public static final int UNPUBLISHED = 0;
|
||||
/**
|
||||
* 已发布。
|
||||
*/
|
||||
public static final int PUBLISHED = 1;
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(UNPUBLISHED, "未发布");
|
||||
DICT_MAP.put(PUBLISHED, "已发布");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowEntryStatus() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.flow.demo.common.flow.model.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程变量类型。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public final class FlowVariableType {
|
||||
|
||||
/**
|
||||
* 流程实例变量。
|
||||
*/
|
||||
public static final int INSTANCE = 0;
|
||||
/**
|
||||
* 任务变量。
|
||||
*/
|
||||
public static final int TASK = 1;
|
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
|
||||
static {
|
||||
DICT_MAP.put(INSTANCE, "流程实例变量");
|
||||
DICT_MAP.put(TASK, "任务变量");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为当前常量字典的合法值。
|
||||
*
|
||||
* @param value 待验证的参数值。
|
||||
* @return 合法返回true,否则false。
|
||||
*/
|
||||
public static boolean isValid(Integer value) {
|
||||
return value != null && DICT_MAP.containsKey(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私有构造函数,明确标识该常量类的作用。
|
||||
*/
|
||||
private FlowVariableType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.flow.demo.common.flow.object;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 流程任务扩展属性中,表示多实例任务的扩展对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowTaskExtMultiInstance {
|
||||
|
||||
public static final String ASSIGNEE_TYPE_ASSIGNEE = "assignee";
|
||||
public static final String ASSIGNEE_TYPE_GROUPID = "groupId";
|
||||
|
||||
/**
|
||||
* 指派人类型。目前支持 assignee、groupId。
|
||||
*/
|
||||
private String assigneeType;
|
||||
|
||||
/**
|
||||
* 指派人登录名列表。
|
||||
*/
|
||||
private List<String> assigneeList;
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.flow.demo.common.core.object.CallResult;
|
||||
import com.flow.demo.common.core.object.MyPageData;
|
||||
import com.flow.demo.common.core.object.MyPageParam;
|
||||
import com.flow.demo.common.flow.model.FlowTaskComment;
|
||||
import com.flow.demo.common.flow.vo.FlowTaskVo;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.UserTask;
|
||||
import org.activiti.engine.delegate.ExecutionListener;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.activiti.engine.task.TaskInfo;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 流程引擎API的接口封装服务。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowApiService {
|
||||
|
||||
/**
|
||||
* 启动流程实例。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
*/
|
||||
void start(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 启动流程实例,如果当前登录用户为第一个用户任务的指派者,或者Assginee为流程启动人变量时,
|
||||
* 则自动完成第一个用户任务。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @param dataId 当前流程主表的主键数据。
|
||||
* @param flowTaskComment 审批对象。
|
||||
* @param taskVariableData 流程任务的变量数据。
|
||||
* @return 新启动的流程实例。
|
||||
*/
|
||||
ProcessInstance startAndTakeFirst(
|
||||
String processDefinitionId, Object dataId, FlowTaskComment flowTaskComment, JSONObject taskVariableData);
|
||||
|
||||
/**
|
||||
* 多实例加签。
|
||||
*
|
||||
* @param startTaskInstance 会签对象的发起任务实例。
|
||||
* @param multiInstanceActiveTask 正在执行的多实例任务对象。
|
||||
* @param newAssignees 新指派人,多个指派人之间逗号分隔。
|
||||
*/
|
||||
void submitConsign(HistoricTaskInstance startTaskInstance, Task multiInstanceActiveTask, String newAssignees);
|
||||
|
||||
/**
|
||||
* 完成任务,同时提交审批数据。
|
||||
*
|
||||
* @param task 工作流任务对象。
|
||||
* @param flowTaskComment 审批对象。
|
||||
* @param taskVariableData 流程任务的变量数据。
|
||||
*/
|
||||
void completeTask(Task task, FlowTaskComment flowTaskComment, JSONObject taskVariableData);
|
||||
|
||||
/**
|
||||
* 判断当前登录用户是否为流程实例中的用户任务的指派人。或是候选人之一,如果是候选人则拾取该任务并成为指派人。
|
||||
* 如果都不是,就会返回具体的错误信息。
|
||||
*
|
||||
* @param task 流程实例中的用户任务。
|
||||
* @return 调用结果。
|
||||
*/
|
||||
CallResult verifyAssigneeOrCandidateAndClaim(Task task);
|
||||
|
||||
/**
|
||||
* 初始化并返回流程实例的变量Map。
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @return 初始化后的流程实例变量Map。
|
||||
*/
|
||||
Map<String, Object> initAndGetProcessInstanceVariables(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 判断当前登录用户是否为流程实例中的用户任务的指派人。或是候选人之一。
|
||||
*
|
||||
* @param task 流程实例中的用户任务。
|
||||
* @return 是返回true,否则false。
|
||||
*/
|
||||
boolean isAssigneeOrCandidate(TaskInfo task);
|
||||
|
||||
/**
|
||||
* 判断当前登录用户是否为流程实例的发起人。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 是返回true,否则false。
|
||||
*/
|
||||
boolean isProcessInstanceStarter(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 为流程实例设置BusinessKey。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param dataId 通常为主表的主键Id。
|
||||
*/
|
||||
void setBusinessKeyForProcessInstance(String processInstanceId, Object dataId);
|
||||
|
||||
/**
|
||||
* 判断指定的流程实例Id是否存在。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 存在返回true,否则false。
|
||||
*/
|
||||
boolean existActiveProcessInstance(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取指定的流程实例对象。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 流程实例对象。
|
||||
*/
|
||||
ProcessInstance getProcessInstance(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取流程实例的列表。
|
||||
*
|
||||
* @param processInstanceIdSet 流程实例Id集合。
|
||||
* @return 流程实例列表。
|
||||
*/
|
||||
List<ProcessInstance> getProcessInstanceList(Set<String> processInstanceIdSet);
|
||||
|
||||
/**
|
||||
* 根据流程部署Id查询流程定义对象。
|
||||
*
|
||||
* @param deployId 流程部署Id。
|
||||
* @return 流程定义对象。
|
||||
*/
|
||||
ProcessDefinition getProcessDefinitionByDeployId(String deployId);
|
||||
|
||||
/**
|
||||
* 获取流程定义的列表。
|
||||
*
|
||||
* @param processDefinitionIdSet 流程定义Id集合。
|
||||
* @return 流程定义列表。
|
||||
*/
|
||||
List<ProcessDefinition> getProcessDefinitionList(Set<String> processDefinitionIdSet);
|
||||
|
||||
/**
|
||||
* 挂起流程定义对象。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
*/
|
||||
void suspendProcessDefinition(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 激活流程定义对象。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
*/
|
||||
void activateProcessDefinition(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 获取指定流程定义的BpmnModel。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @return 关联的BpmnModel。
|
||||
*/
|
||||
BpmnModel getBpmnModelByDefinitionId(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 获取流程实例的变量。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param variableName 变量名。
|
||||
* @return 变量值。
|
||||
*/
|
||||
Object getProcessInstanceVariable(String processInstanceId, String variableName);
|
||||
|
||||
/**
|
||||
* 获取指定流程实例和任务Id的当前活动任务。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 流程任务Id。
|
||||
* @return 当前流程实例的活动任务。
|
||||
*/
|
||||
Task getProcessInstanceActiveTask(String processInstanceId, String taskId);
|
||||
|
||||
/**
|
||||
* 获取指定流程实例的当前活动任务列表。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 当前流程实例的活动任务。
|
||||
*/
|
||||
List<Task> getProcessInstanceActiveTaskList(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取用户的任务列表。这其中包括当前用户作为指派人和候选人。
|
||||
*
|
||||
* @param username 指派人。
|
||||
* @param definitionKey 流程定义的标识。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 用户的任务列表。
|
||||
*/
|
||||
MyPageData<Task> getTaskListByUserName(String username, String definitionKey, MyPageParam pageParam);
|
||||
|
||||
/**
|
||||
* 获取用户的任务数量。这其中包括当前用户作为指派人和候选人。
|
||||
*
|
||||
* @param username 指派人。
|
||||
* @return 用户的任务数量。
|
||||
*/
|
||||
long getTaskCountByUserName(String username);
|
||||
|
||||
/**
|
||||
* 获取流程实例Id集合的运行时任务列表。
|
||||
*
|
||||
* @param processInstanceIdSet 流程实例Id集合。
|
||||
* @return 运行时任务列表。
|
||||
*/
|
||||
List<Task> getTaskListByProcessInstanceIds(List<String> processInstanceIdSet);
|
||||
|
||||
/**
|
||||
* 将流程任务列表数据,转换为前端可以显示的流程对象。
|
||||
*
|
||||
* @param taskList 流程引擎中的任务列表。
|
||||
* @return 前端可以显示的流程任务列表。
|
||||
*/
|
||||
List<FlowTaskVo> convertToFlowTaskList(List<Task> taskList);
|
||||
|
||||
/**
|
||||
* 添加流程实例结束的监听器。
|
||||
*
|
||||
* @param bpmnModel 流程模型。
|
||||
* @param listenerClazz 流程监听器的Class对象。
|
||||
*/
|
||||
void addProcessInstanceEndListener(BpmnModel bpmnModel, Class<? extends ExecutionListener> listenerClazz);
|
||||
|
||||
/**
|
||||
* 添加流程任务创建的任务监听器。
|
||||
*
|
||||
* @param userTask 用户任务。
|
||||
* @param listenerClazz 任务监听器。
|
||||
*/
|
||||
void addTaskCreateListener(UserTask userTask, Class<? extends TaskListener> listenerClazz);
|
||||
|
||||
/**
|
||||
* 获取流程实例的历史流程实例。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 历史流程实例。
|
||||
*/
|
||||
HistoricProcessInstance getHistoricProcessInstance(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取流程实例的历史流程实例列表。
|
||||
*
|
||||
* @param processInstanceIdSet 流程实例Id集合。
|
||||
* @return 历史流程实例列表。
|
||||
*/
|
||||
List<HistoricProcessInstance> getHistoricProcessInstanceList(Set<String> processInstanceIdSet);
|
||||
|
||||
/**
|
||||
* 查询历史流程实例的列表。
|
||||
*
|
||||
* @param processDefinitionKey 流程标识名。
|
||||
* @param processDefinitionName 流程名。
|
||||
* @param startUser 流程发起用户。
|
||||
* @param beginDate 流程发起开始时间。
|
||||
* @param endDate 流程发起结束时间。
|
||||
* @param pageParam 分页对象。
|
||||
* @param finishedOnly 仅仅返回已经结束的流程。
|
||||
* @return 分页后的查询列表对象。
|
||||
* @throws ParseException 日期参数解析失败。
|
||||
*/
|
||||
MyPageData<HistoricProcessInstance> getHistoricProcessInstanceList(
|
||||
String processDefinitionKey,
|
||||
String processDefinitionName,
|
||||
String startUser,
|
||||
String beginDate,
|
||||
String endDate,
|
||||
MyPageParam pageParam,
|
||||
boolean finishedOnly) throws ParseException;
|
||||
|
||||
/**
|
||||
* 获取流程实例的已完成历史任务列表。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 流程实例已完成的历史任务列表。
|
||||
*/
|
||||
List<HistoricActivityInstance> getHistoricActivityInstanceList(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取当前用户的历史已办理任务列表。
|
||||
*
|
||||
* @param processDefinitionName 流程名。
|
||||
* @param beginDate 流程发起开始时间。
|
||||
* @param endDate 流程发起结束时间。
|
||||
* @param pageParam 分页对象。
|
||||
* @return 分页后的查询列表对象。
|
||||
* @throws ParseException 日期参数解析失败。
|
||||
*/
|
||||
MyPageData<HistoricTaskInstance> getHistoricTaskInstanceFinishedList(
|
||||
String processDefinitionName,
|
||||
String beginDate,
|
||||
String endDate,
|
||||
MyPageParam pageParam) throws ParseException;
|
||||
|
||||
/**
|
||||
* 获取指定的历史任务实例。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 任务Id。
|
||||
* @return 历史任务实例。
|
||||
*/
|
||||
HistoricTaskInstance getHistoricTaskInstance(String processInstanceId, String taskId);
|
||||
|
||||
/**
|
||||
* 获取流程实例的待完成任务列表。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 流程实例待完成的任务列表。
|
||||
*/
|
||||
List<HistoricActivityInstance> getHistoricUnfinishedInstanceList(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 终止流程实例,将任务从当前节点直接流转到主流程的结束事件。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param stopReason 停止原因。
|
||||
* @param forCancel 是否由取消工单触发。
|
||||
* @return 执行结果。
|
||||
*/
|
||||
CallResult stopProcessInstance(String processInstanceId, String stopReason, boolean forCancel);
|
||||
|
||||
/**
|
||||
* 删除流程实例。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
*/
|
||||
void deleteProcessInstance(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取任务的指定本地变量。
|
||||
*
|
||||
* @param taskId 任务Id。
|
||||
* @param variableName 变量名。
|
||||
* @return 变量值。
|
||||
*/
|
||||
Object getTaskVariable(String taskId, String variableName);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FlowCategory数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowCategoryService extends IBaseService<FlowCategory, Long> {
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowCategory 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
FlowCategory saveNew(FlowCategory flowCategory);
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowCategory 更新的对象。
|
||||
* @param originalFlowCategory 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean update(FlowCategory flowCategory, FlowCategory originalFlowCategory);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param categoryId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean remove(Long categoryId);
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowCategoryListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowCategory> getFlowCategoryList(FlowCategory filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowCategoryList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowCategory> getFlowCategoryListWithRelation(FlowCategory filter, String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
import com.flow.demo.common.core.object.CallResult;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* FlowEntry数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryService extends IBaseService<FlowEntry, Long> {
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowEntry 新增工作流对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
FlowEntry saveNew(FlowEntry flowEntry);
|
||||
|
||||
/**
|
||||
* 发布指定流程。
|
||||
*
|
||||
* @param flowEntry 待发布的流程对象。
|
||||
* @param initTaskInfo 第一个非开始节点任务的附加信息。
|
||||
* @param flowTaskExtList 所有用户任务的自定义扩展数据列表。
|
||||
* @throws XMLStreamException 解析bpmn.xml的异常。
|
||||
*/
|
||||
void publish(FlowEntry flowEntry, String initTaskInfo, List<FlowTaskExt> flowTaskExtList) throws XMLStreamException;
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowEntry 更新的对象。
|
||||
* @param originalFlowEntry 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean update(FlowEntry flowEntry, FlowEntry originalFlowEntry);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param entryId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean remove(Long entryId);
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowEntryListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowEntry> getFlowEntryList(FlowEntry filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowEntryList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowEntry> getFlowEntryListWithRelation(FlowEntry filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 根据流程定义标识获取流程对象。
|
||||
*
|
||||
* @param processDefinitionKey 流程定义标识。
|
||||
* @return 流程对象。
|
||||
*/
|
||||
FlowEntry getFlowEntryByProcessDefinitionKey(String processDefinitionKey);
|
||||
|
||||
/**
|
||||
* 根据流程Id获取流程发布列表数据。
|
||||
*
|
||||
* @param entryId 流程Id。
|
||||
* @return 流程关联的发布列表数据。
|
||||
*/
|
||||
List<FlowEntryPublish> getFlowEntryPublishList(Long entryId);
|
||||
|
||||
/**
|
||||
* 根据流程引擎中的流程定义Id集合,查询流程发布对象。
|
||||
*
|
||||
* @param processDefinitionIdSet 流程引擎中的流程定义Id集合。
|
||||
* @return 查询结果。
|
||||
*/
|
||||
List<FlowEntryPublish> getFlowEntryPublishList(Set<String> processDefinitionIdSet);
|
||||
|
||||
/**
|
||||
* 获取指定工作流发布版本对象。
|
||||
*
|
||||
* @param entryPublishId 工作流发布对象Id。
|
||||
* @return 查询后的对象。
|
||||
*/
|
||||
FlowEntryPublish getFlowEntryPublishById(Long entryPublishId);
|
||||
|
||||
/**
|
||||
* 获取指定流程定义Id对应的流程发布对象。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @return 流程发布对象。
|
||||
*/
|
||||
FlowEntryPublish getFlowEntryPublishByDefinitionId(String processDefinitionId);
|
||||
|
||||
/**
|
||||
* 为指定工作流更新发布的主版本。
|
||||
*
|
||||
* @param flowEntry 工作流对象。
|
||||
* @param newMainFlowEntryPublish 工作流新的发布主版本对象。
|
||||
*/
|
||||
void updateFlowEntryMainVersion(FlowEntry flowEntry, FlowEntryPublish newMainFlowEntryPublish);
|
||||
|
||||
/**
|
||||
* 挂起指定的工作流发布对象。
|
||||
*
|
||||
* @param flowEntryPublish 待挂起的工作流发布对象。
|
||||
*/
|
||||
void suspendFlowEntryPublish(FlowEntryPublish flowEntryPublish);
|
||||
|
||||
/**
|
||||
* 激活指定的工作流发布对象。
|
||||
*
|
||||
* @param flowEntryPublish 待恢复的工作流发布对象。
|
||||
*/
|
||||
void activateFlowEntryPublish(FlowEntryPublish flowEntryPublish);
|
||||
|
||||
/**
|
||||
* 主表的关联数据验证。
|
||||
*
|
||||
* @param flowEntry 最新数据对象。
|
||||
* @param originalFlowEntry 原有数据对象。
|
||||
* @return 数据全部正确返回true,否则false。
|
||||
*/
|
||||
CallResult verifyRelatedData(FlowEntry flowEntry, FlowEntry originalFlowEntry);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程变量数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowEntryVariableService extends IBaseService<FlowEntryVariable, Long> {
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowEntryVariable 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
FlowEntryVariable saveNew(FlowEntryVariable flowEntryVariable);
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowEntryVariable 更新的对象。
|
||||
* @param originalFlowEntryVariable 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean update(FlowEntryVariable flowEntryVariable, FlowEntryVariable originalFlowEntryVariable);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param variableId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean remove(Long variableId);
|
||||
|
||||
/**
|
||||
* 删除指定流程Id的所有变量。
|
||||
*
|
||||
* @param entryId 流程Id。
|
||||
*/
|
||||
void removeByEntryId(Long entryId);
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowEntryVariableListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowEntryVariable> getFlowEntryVariableList(FlowEntryVariable filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowEntryVariableList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowEntryVariable> getFlowEntryVariableListWithRelation(FlowEntryVariable filter, String orderBy);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程任务批注数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowTaskCommentService extends IBaseService<FlowTaskComment, Long> {
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowTaskComment 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
FlowTaskComment saveNew(FlowTaskComment flowTaskComment);
|
||||
|
||||
/**
|
||||
* 查询指定流程实例Id下的所有审批任务的批注。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowTaskComment> getFlowTaskCommentList(String processInstanceId);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程任务扩展数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowTaskExtService extends IBaseService<FlowTaskExt, String> {
|
||||
|
||||
/**
|
||||
* 批量插入流程任务扩展信息列表。
|
||||
*
|
||||
* @param flowTaskExtList 流程任务扩展信息列表。
|
||||
*/
|
||||
void saveBatch(List<FlowTaskExt> flowTaskExtList);
|
||||
|
||||
/**
|
||||
* 查询指定的流程任务扩展对象。
|
||||
* @param processDefinitionId 流程引擎的定义Id。
|
||||
* @param taskId 流程引擎的任务Id。
|
||||
* @return 查询结果。
|
||||
*/
|
||||
FlowTaskExt getByProcessDefinitionIdAndTaskId(String processDefinitionId, String taskId);
|
||||
|
||||
/**
|
||||
* 查询指定的流程定义的任务扩展对象。
|
||||
*
|
||||
* @param processDefinitionId 流程引擎的定义Id。
|
||||
* @return 查询结果。
|
||||
*/
|
||||
List<FlowTaskExt> getByProcessDefinitionId(String processDefinitionId);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.flow.demo.common.flow.service;
|
||||
|
||||
import com.flow.demo.common.core.base.service.IBaseService;
|
||||
import com.flow.demo.common.flow.model.FlowWorkOrder;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 工作流工单表数据操作服务接口。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface FlowWorkOrderService extends IBaseService<FlowWorkOrder, Long> {
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param instance 流程实例对象。
|
||||
* @param dataId 流程实例的BusinessKey。
|
||||
* @param onlineTableId 在线数据表的主键Id。
|
||||
* @return 新增的工作流工单对象。
|
||||
*/
|
||||
FlowWorkOrder saveNew(ProcessInstance instance, Object dataId, Long onlineTableId);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param workOrderId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean remove(Long workOrderId);
|
||||
|
||||
/**
|
||||
* 删除指定流程实例Id的关联工单。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
*/
|
||||
void removeByProcessInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获取工作流工单单表查询结果。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowWorkOrder> getFlowWorkOrderList(FlowWorkOrder filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 获取工作流工单列表及其关联字典数据。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
List<FlowWorkOrder> getFlowWorkOrderListWithRelation(FlowWorkOrder filter, String orderBy);
|
||||
|
||||
/**
|
||||
* 根据流程实例Id,查询关联的工单对象。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 工作流工单对象。
|
||||
*/
|
||||
FlowWorkOrder getFlowWorkOrderByProcessInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 根据业务主键,查询是否存在指定的工单。
|
||||
*
|
||||
* @param businessKey 业务数据主键Id。
|
||||
* @param unfinished 是否为没有结束工单。
|
||||
* @return 存在返回true,否则false。
|
||||
*/
|
||||
boolean existByBusinessKey(Object businessKey, boolean unfinished);
|
||||
|
||||
/**
|
||||
* 根据业务数据的主键Id,更新流程状态。
|
||||
* @param businessKey 业务数据主键Id。
|
||||
* @param flowStatus 新的流程状态值。
|
||||
*/
|
||||
void updateFlowStatusByBusinessKey(String businessKey, int flowStatus);
|
||||
|
||||
/**
|
||||
* 根据流程实例Id,更新流程状态。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param flowStatus 新的流程状态值。
|
||||
*/
|
||||
void updateFlowStatusByProcessInstanceId(String processInstanceId, int flowStatus);
|
||||
}
|
||||
@@ -0,0 +1,618 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.flow.demo.common.core.object.CallResult;
|
||||
import com.flow.demo.common.core.object.MyPageData;
|
||||
import com.flow.demo.common.core.object.MyPageParam;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.flow.command.AddMultiInstanceExecutionCmd;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.constant.FlowApprovalType;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.model.FlowEntryPublish;
|
||||
import com.flow.demo.common.flow.model.FlowTaskComment;
|
||||
import com.flow.demo.common.flow.model.FlowTaskExt;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.util.BaseFlowDeptPostExtHelper;
|
||||
import com.flow.demo.common.flow.util.FlowCustomExtFactory;
|
||||
import com.flow.demo.common.flow.vo.FlowTaskVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.engine.*;
|
||||
import org.activiti.engine.delegate.ExecutionListener;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
import org.activiti.engine.history.*;
|
||||
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.activiti.engine.task.TaskInfo;
|
||||
import org.activiti.engine.task.TaskQuery;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service("flowApiService")
|
||||
public class FlowApiServiceImpl implements FlowApiService {
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private ManagementService managementService;
|
||||
@Autowired
|
||||
private FlowEntryService flowEntryService;
|
||||
@Autowired
|
||||
private FlowTaskCommentService flowTaskCommentService;
|
||||
@Autowired
|
||||
private FlowTaskExtService flowTaskExtService;
|
||||
@Autowired
|
||||
private FlowWorkOrderService flowWorkOrderService;
|
||||
@Autowired
|
||||
private FlowCustomExtFactory flowCustomExtFactory;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void start(String processDefinitionId) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
Map<String, Object> variableMap = new HashMap<>(4);
|
||||
variableMap.put(FlowConstant.PROC_INSTANCE_INITIATOR_VAR, loginName);
|
||||
variableMap.put(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR, loginName);
|
||||
Authentication.setAuthenticatedUserId(loginName);
|
||||
runtimeService.startProcessInstanceById(processDefinitionId, null, variableMap);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public ProcessInstance startAndTakeFirst(
|
||||
String processDefinitionId, Object dataId, FlowTaskComment flowTaskComment, JSONObject taskVariableData) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
Authentication.setAuthenticatedUserId(loginName);
|
||||
// 设置流程变量。
|
||||
Map<String, Object> variableMap = this.initAndGetProcessInstanceVariables(processDefinitionId);
|
||||
// 根据当前流程的主版本,启动一个流程实例,同时将businessKey参数设置为主表主键值。
|
||||
ProcessInstance instance = runtimeService.startProcessInstanceById(
|
||||
processDefinitionId, dataId.toString(), variableMap);
|
||||
// 获取流程启动后的第一个任务。
|
||||
Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).active().singleResult();
|
||||
if (StrUtil.equalsAny(task.getAssignee(), loginName, FlowConstant.START_USER_NAME_VAR)) {
|
||||
// 按照规则,调用该方法的用户,就是第一个任务的assignee,因此默认会自动执行complete。
|
||||
flowTaskComment.fillWith(task);
|
||||
this.completeTask(task, flowTaskComment, taskVariableData);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void submitConsign(HistoricTaskInstance startTaskInstance, Task multiInstanceActiveTask, String newAssignees) {
|
||||
JSONArray assigneeArray = JSON.parseArray(newAssignees);
|
||||
for (int i = 0; i < assigneeArray.size(); i++) {
|
||||
managementService.executeCommand(new AddMultiInstanceExecutionCmd(
|
||||
startTaskInstance.getId(), multiInstanceActiveTask.getId(), assigneeArray.getString(i)));
|
||||
}
|
||||
FlowTaskComment flowTaskComment = new FlowTaskComment();
|
||||
flowTaskComment.fillWith(startTaskInstance);
|
||||
flowTaskComment.setApprovalType(FlowApprovalType.MULTI_CONSIGN);
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
String comment = String.format("用户 [%s] 加签 [%s]。", loginName, newAssignees);
|
||||
flowTaskComment.setComment(comment);
|
||||
flowTaskCommentService.saveNew(flowTaskComment);
|
||||
return;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void completeTask(Task task, FlowTaskComment flowTaskComment, JSONObject taskVariableData) {
|
||||
if (flowTaskComment != null) {
|
||||
// 这里处理多实例会签逻辑。
|
||||
if (flowTaskComment.getApprovalType().equals(FlowApprovalType.MULTI_SIGN)) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
String assigneeList = taskVariableData.getString(FlowConstant.MULTI_ASSIGNEE_LIST_VAR);
|
||||
Assert.notNull(taskVariableData);
|
||||
Assert.notNull(assigneeList);
|
||||
taskVariableData.put(FlowConstant.MULTI_AGREE_COUNT_VAR, 0);
|
||||
taskVariableData.put(FlowConstant.MULTI_REFUSE_COUNT_VAR, 0);
|
||||
taskVariableData.put(FlowConstant.MULTI_ABSTAIN_COUNT_VAR, 0);
|
||||
taskVariableData.put(FlowConstant.MULTI_SIGN_NUM_OF_INSTANCES_VAR, 0);
|
||||
taskVariableData.put(FlowConstant.MULTI_SIGN_START_TASK_VAR, task.getId());
|
||||
String comment = String.format("用户 [%s] 会签 [%s]。", loginName, assigneeList);
|
||||
flowTaskComment.setComment(comment);
|
||||
}
|
||||
// 处理转办。
|
||||
if (FlowApprovalType.TRANSFER.equals(flowTaskComment.getApprovalType())) {
|
||||
taskService.setAssignee(task.getId(), flowTaskComment.getDelegateAssginee());
|
||||
flowTaskComment.fillWith(task);
|
||||
flowTaskCommentService.saveNew(flowTaskComment);
|
||||
return;
|
||||
}
|
||||
if (taskVariableData == null) {
|
||||
taskVariableData = new JSONObject();
|
||||
}
|
||||
this.handleMultiInstanceApprovalType(
|
||||
task.getExecutionId(), flowTaskComment.getApprovalType(), taskVariableData);
|
||||
taskVariableData.put(FlowConstant.OPERATION_TYPE_VAR, flowTaskComment.getApprovalType());
|
||||
taskService.complete(task.getId(), taskVariableData, true);
|
||||
flowTaskComment.fillWith(task);
|
||||
flowTaskCommentService.saveNew(flowTaskComment);
|
||||
} else {
|
||||
taskService.complete(task.getId(), taskVariableData, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public CallResult verifyAssigneeOrCandidateAndClaim(Task task) {
|
||||
String errorMessage;
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
// 这里必须先执行拾取操作,如果当前用户是候选人,特别是对于分布式场景,更是要先完成候选人的拾取。
|
||||
if (task.getAssignee() == null) {
|
||||
// 没有指派人
|
||||
if (!this.isAssigneeOrCandidate(task)) {
|
||||
errorMessage = "数据验证失败,当前用户不是该待办任务的候选人,请刷新后重试!";
|
||||
return CallResult.error(errorMessage);
|
||||
}
|
||||
// 作为候选人主动拾取任务。
|
||||
taskService.claim(task.getId(), loginName);
|
||||
} else {
|
||||
if (!task.getAssignee().equals(loginName)) {
|
||||
errorMessage = "数据验证失败,当前用户不是该待办任务的指派人,请刷新后重试!";
|
||||
return CallResult.error(errorMessage);
|
||||
}
|
||||
}
|
||||
return CallResult.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> initAndGetProcessInstanceVariables(String processDefinitionId) {
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
String loginName = tokenData.getLoginName();
|
||||
// 设置流程变量。
|
||||
Map<String, Object> variableMap = new HashMap<>(4);
|
||||
variableMap.put(FlowConstant.PROC_INSTANCE_INITIATOR_VAR, loginName);
|
||||
variableMap.put(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR, loginName);
|
||||
List<FlowTaskExt> flowTaskExtList = flowTaskExtService.getByProcessDefinitionId(processDefinitionId);
|
||||
boolean hasDeptPostLeader = false;
|
||||
boolean hasUpDeptPostLeader = false;
|
||||
for (FlowTaskExt flowTaskExt : flowTaskExtList) {
|
||||
if (StrUtil.equals(flowTaskExt.getGroupType(), FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER)) {
|
||||
hasUpDeptPostLeader = true;
|
||||
} else if (StrUtil.equals(flowTaskExt.getGroupType(), FlowConstant.GROUP_TYPE_DEPT_POST_LEADER)) {
|
||||
hasDeptPostLeader = true;
|
||||
}
|
||||
}
|
||||
// 如果流程图的配置中包含部门岗位相关的变量(如:部门领导和上级领导审批),flowDeptPostExtHelper就不能为null。
|
||||
// 这个需要子类去实现 BaseFlowDeptPostExtHelper 接口,并注册到FlowCustomExtFactory的工厂中。
|
||||
BaseFlowDeptPostExtHelper flowDeptPostExtHelper = flowCustomExtFactory.getFlowDeptPostExtHelper();
|
||||
if (hasUpDeptPostLeader) {
|
||||
Assert.notNull(flowDeptPostExtHelper);
|
||||
Object upLeaderDeptPostId = flowDeptPostExtHelper.getUpLeaderDeptPostId(tokenData.getDeptId());
|
||||
if (upLeaderDeptPostId != null) {
|
||||
variableMap.put(FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER_VAR, upLeaderDeptPostId.toString());
|
||||
}
|
||||
}
|
||||
if (hasDeptPostLeader) {
|
||||
Assert.notNull(flowDeptPostExtHelper);
|
||||
Object leaderDeptPostId = flowDeptPostExtHelper.getLeaderDeptPostId(tokenData.getDeptId());
|
||||
if (leaderDeptPostId != null) {
|
||||
variableMap.put(FlowConstant.GROUP_TYPE_DEPT_POST_LEADER_VAR, leaderDeptPostId.toString());
|
||||
}
|
||||
}
|
||||
return variableMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssigneeOrCandidate(TaskInfo task) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
if (StrUtil.isNotBlank(task.getAssignee())) {
|
||||
return StrUtil.equals(loginName, task.getAssignee());
|
||||
}
|
||||
TaskQuery query = taskService.createTaskQuery();
|
||||
this.buildCandidateCondition(query, loginName);
|
||||
return query.active().count() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProcessInstanceStarter(String processInstanceId) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
return historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId).startedBy(loginName).count() != 0;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void setBusinessKeyForProcessInstance(String processInstanceId, Object dataId) {
|
||||
runtimeService.updateBusinessKey(processInstanceId, dataId.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existActiveProcessInstance(String processInstanceId) {
|
||||
return runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId).active().count() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessInstance getProcessInstance(String processInstanceId) {
|
||||
return runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task getProcessInstanceActiveTask(String processInstanceId, String taskId) {
|
||||
TaskQuery query = taskService.createTaskQuery().processInstanceId(processInstanceId);
|
||||
if (StrUtil.isNotBlank(taskId)) {
|
||||
query.taskId(taskId);
|
||||
}
|
||||
return query.active().singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> getProcessInstanceActiveTaskList(String processInstanceId) {
|
||||
return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyPageData<Task> getTaskListByUserName(String username, String definitionKey, MyPageParam pageParam) {
|
||||
TaskQuery query = taskService.createTaskQuery().active();
|
||||
if (StrUtil.isNotBlank(definitionKey)) {
|
||||
query.processDefinitionKey(definitionKey);
|
||||
}
|
||||
this.buildCandidateCondition(query, username);
|
||||
query.orderByTaskCreateTime().desc();
|
||||
long totalCount = query.count();
|
||||
int firstResult = (pageParam.getPageNum() - 1) * pageParam.getPageSize();
|
||||
List<Task> taskList = query.listPage(firstResult, pageParam.getPageSize());
|
||||
return new MyPageData<>(taskList, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTaskCountByUserName(String username) {
|
||||
return taskService.createTaskQuery().taskCandidateOrAssigned(username).active().count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> getTaskListByProcessInstanceIds(List<String> processInstanceIdSet) {
|
||||
return taskService.createTaskQuery().processInstanceIdIn(processInstanceIdSet).active().list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProcessInstance> getProcessInstanceList(Set<String> processInstanceIdSet) {
|
||||
return runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdSet).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProcessDefinition> getProcessDefinitionList(Set<String> processDefinitionIdSet) {
|
||||
return repositoryService.createProcessDefinitionQuery().processDefinitionIds(processDefinitionIdSet).list();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void suspendProcessDefinition(String processDefinitionId) {
|
||||
repositoryService.suspendProcessDefinitionById(processDefinitionId);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void activateProcessDefinition(String processDefinitionId) {
|
||||
repositoryService.activateProcessDefinitionById(processDefinitionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmnModel getBpmnModelByDefinitionId(String processDefinitionId) {
|
||||
return repositoryService.getBpmnModel(processDefinitionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getProcessDefinitionByDeployId(String deployId) {
|
||||
return repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProcessInstanceVariable(String processInstanceId, String variableName) {
|
||||
return runtimeService.getVariable(processInstanceId, variableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowTaskVo> convertToFlowTaskList(List<Task> taskList) {
|
||||
List<FlowTaskVo> flowTaskVoList = new LinkedList<>();
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
return flowTaskVoList;
|
||||
}
|
||||
Set<String> processDefinitionIdSet = taskList.stream()
|
||||
.map(Task::getProcessDefinitionId).collect(Collectors.toSet());
|
||||
Set<String> procInstanceIdSet = taskList.stream()
|
||||
.map(Task::getProcessInstanceId).collect(Collectors.toSet());
|
||||
List<FlowEntryPublish> flowEntryPublishList =
|
||||
flowEntryService.getFlowEntryPublishList(processDefinitionIdSet);
|
||||
Map<String, FlowEntryPublish> flowEntryPublishMap =
|
||||
flowEntryPublishList.stream().collect(Collectors.toMap(FlowEntryPublish::getProcessDefinitionId, c -> c));
|
||||
List<ProcessInstance> instanceList = this.getProcessInstanceList(procInstanceIdSet);
|
||||
Map<String, ProcessInstance> instanceMap =
|
||||
instanceList.stream().collect(Collectors.toMap(ProcessInstance::getId, c -> c));
|
||||
List<ProcessDefinition> definitionList = this.getProcessDefinitionList(processDefinitionIdSet);
|
||||
Map<String, ProcessDefinition> definitionMap =
|
||||
definitionList.stream().collect(Collectors.toMap(ProcessDefinition::getId, c -> c));
|
||||
for (Task task : taskList) {
|
||||
FlowTaskVo flowTaskVo = new FlowTaskVo();
|
||||
flowTaskVo.setTaskId(task.getId());
|
||||
flowTaskVo.setTaskName(task.getName());
|
||||
flowTaskVo.setTaskKey(task.getTaskDefinitionKey());
|
||||
flowTaskVo.setTaskFormKey(task.getFormKey());
|
||||
flowTaskVo.setEntryId(flowEntryPublishMap.get(task.getProcessDefinitionId()).getEntryId());
|
||||
ProcessDefinition processDefinition = definitionMap.get(task.getProcessDefinitionId());
|
||||
flowTaskVo.setProcessDefinitionId(processDefinition.getId());
|
||||
flowTaskVo.setProcessDefinitionName(processDefinition.getName());
|
||||
flowTaskVo.setProcessDefinitionKey(processDefinition.getKey());
|
||||
flowTaskVo.setProcessDefinitionVersion(processDefinition.getVersion());
|
||||
ProcessInstance processInstance = instanceMap.get(task.getProcessInstanceId());
|
||||
flowTaskVo.setProcessInstanceId(processInstance.getId());
|
||||
Object initiator = this.getProcessInstanceVariable(
|
||||
processInstance.getId(), FlowConstant.PROC_INSTANCE_INITIATOR_VAR);
|
||||
flowTaskVo.setProcessInstanceInitiator(initiator.toString());
|
||||
flowTaskVo.setProcessInstanceStartTime(processInstance.getStartTime());
|
||||
flowTaskVoList.add(flowTaskVo);
|
||||
}
|
||||
return flowTaskVoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProcessInstanceEndListener(BpmnModel bpmnModel, Class<? extends ExecutionListener> listenerClazz) {
|
||||
Assert.notNull(listenerClazz);
|
||||
Process process = bpmnModel.getMainProcess();
|
||||
ActivitiListener activitiListener = new ActivitiListener();
|
||||
activitiListener.setEvent("end");
|
||||
activitiListener.setImplementationType("class");
|
||||
activitiListener.setImplementation(listenerClazz.getName());
|
||||
process.getExecutionListeners().add(activitiListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTaskCreateListener(UserTask userTask, Class<? extends TaskListener> listenerClazz) {
|
||||
Assert.notNull(listenerClazz);
|
||||
ActivitiListener activitiListener = new ActivitiListener();
|
||||
activitiListener.setEvent("create");
|
||||
activitiListener.setImplementationType("class");
|
||||
activitiListener.setImplementation(listenerClazz.getName());
|
||||
userTask.getTaskListeners().add(activitiListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoricProcessInstance getHistoricProcessInstance(String processInstanceId) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricProcessInstance> getHistoricProcessInstanceList(Set<String> processInstanceIdSet) {
|
||||
return historyService.createHistoricProcessInstanceQuery().processInstanceIds(processInstanceIdSet).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyPageData<HistoricProcessInstance> getHistoricProcessInstanceList(
|
||||
String processDefinitionKey,
|
||||
String processDefinitionName,
|
||||
String startUser,
|
||||
String beginDate,
|
||||
String endDate,
|
||||
MyPageParam pageParam,
|
||||
boolean finishedOnly) throws ParseException {
|
||||
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
|
||||
if (StrUtil.isNotBlank(processDefinitionKey)) {
|
||||
query.processDefinitionKey(processDefinitionKey);
|
||||
}
|
||||
if (StrUtil.isNotBlank(processDefinitionName)) {
|
||||
query.processDefinitionName(processDefinitionName);
|
||||
}
|
||||
if (StrUtil.isNotBlank(startUser)) {
|
||||
query.startedBy(startUser);
|
||||
}
|
||||
if (StrUtil.isNotBlank(beginDate)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
query.startedAfter(sdf.parse(beginDate));
|
||||
}
|
||||
if (StrUtil.isNotBlank(endDate)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
query.startedBefore(sdf.parse(endDate));
|
||||
}
|
||||
if (finishedOnly) {
|
||||
query.finished();
|
||||
}
|
||||
query.orderByProcessInstanceStartTime().desc();
|
||||
long totalCount = query.count();
|
||||
int firstResult = (pageParam.getPageNum() - 1) * pageParam.getPageSize();
|
||||
List<HistoricProcessInstance> instanceList = query.listPage(firstResult, pageParam.getPageSize());
|
||||
return new MyPageData<>(instanceList, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyPageData<HistoricTaskInstance> getHistoricTaskInstanceFinishedList(
|
||||
String processDefinitionName,
|
||||
String beginDate,
|
||||
String endDate,
|
||||
MyPageParam pageParam) throws ParseException {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
|
||||
.taskAssignee(loginName)
|
||||
.finished();
|
||||
if (StrUtil.isNotBlank(processDefinitionName)) {
|
||||
query.processDefinitionName(processDefinitionName);
|
||||
}
|
||||
if (StrUtil.isNotBlank(beginDate)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
query.taskCompletedAfter(sdf.parse(beginDate));
|
||||
}
|
||||
if (StrUtil.isNotBlank(endDate)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
query.taskCompletedBefore(sdf.parse(endDate));
|
||||
}
|
||||
query.orderByHistoricTaskInstanceEndTime().desc();
|
||||
long totalCount = query.count();
|
||||
int firstResult = (pageParam.getPageNum() - 1) * pageParam.getPageSize();
|
||||
List<HistoricTaskInstance> instanceList = query.listPage(firstResult, pageParam.getPageSize());
|
||||
return new MyPageData<>(instanceList, totalCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricActivityInstance> getHistoricActivityInstanceList(String processInstanceId) {
|
||||
return historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoricTaskInstance getHistoricTaskInstance(String processInstanceId, String taskId) {
|
||||
return historyService.createHistoricTaskInstanceQuery()
|
||||
.processInstanceId(processInstanceId).taskId(taskId).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HistoricActivityInstance> getHistoricUnfinishedInstanceList(String processInstanceId) {
|
||||
return historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(processInstanceId).unfinished().list();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public CallResult stopProcessInstance(String processInstanceId, String stopReason, boolean forCancel) {
|
||||
List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).active().list();
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
return CallResult.error("数据验证失败,当前流程尚未开始或已经结束!");
|
||||
}
|
||||
for (Task task : taskList) {
|
||||
String currActivityId = task.getTaskDefinitionKey();
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
|
||||
FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);
|
||||
if (currFlow == null) {
|
||||
List<SubProcess> subProcessList =
|
||||
bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class);
|
||||
for (SubProcess subProcess : subProcessList) {
|
||||
FlowElement flowElement = subProcess.getFlowElement(currActivityId);
|
||||
if (flowElement != null) {
|
||||
currFlow = (FlowNode) flowElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EndEvent endEvent =
|
||||
bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class, false).get(0);
|
||||
if (!(currFlow.getParentContainer().equals(endEvent.getParentContainer()))) {
|
||||
return CallResult.error("数据验证失败,不能从子流程直接中止!");
|
||||
}
|
||||
// 保存原有的输出方向。
|
||||
List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
|
||||
oriSequenceFlows.addAll(currFlow.getOutgoingFlows());
|
||||
// 清空原有方向。
|
||||
currFlow.getOutgoingFlows().clear();
|
||||
// 建立新方向。
|
||||
SequenceFlow newSequenceFlow = new SequenceFlow();
|
||||
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||
newSequenceFlow.setId(uuid);
|
||||
newSequenceFlow.setSourceFlowElement(currFlow);
|
||||
newSequenceFlow.setTargetFlowElement(endEvent);
|
||||
currFlow.setOutgoingFlows(CollUtil.newArrayList(newSequenceFlow));
|
||||
// 完成任务并跳转到新方向。
|
||||
taskService.complete(task.getId());
|
||||
FlowTaskComment taskComment = new FlowTaskComment(task);
|
||||
taskComment.setApprovalType(FlowApprovalType.STOP);
|
||||
taskComment.setComment(stopReason);
|
||||
flowTaskCommentService.saveNew(taskComment);
|
||||
// 回复原有输出方向。
|
||||
currFlow.setOutgoingFlows(oriSequenceFlows);
|
||||
}
|
||||
int status = FlowTaskStatus.STOPPED;
|
||||
if (forCancel) {
|
||||
status = FlowTaskStatus.CANCELLED;
|
||||
}
|
||||
flowWorkOrderService.updateFlowStatusByProcessInstanceId(processInstanceId, status);
|
||||
return CallResult.ok();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void deleteProcessInstance(String processInstanceId) {
|
||||
historyService.deleteHistoricProcessInstance(processInstanceId);
|
||||
flowWorkOrderService.removeByProcessInstanceId(processInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTaskVariable(String taskId, String variableName) {
|
||||
return taskService.getVariable(taskId, variableName);
|
||||
}
|
||||
|
||||
private void handleMultiInstanceApprovalType(String executionId, String approvalType, JSONObject taskVariableData) {
|
||||
if (StrUtil.isBlank(approvalType)) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.equalsAny(approvalType,
|
||||
FlowApprovalType.MULTI_AGREE,
|
||||
FlowApprovalType.MULTI_REFUSE,
|
||||
FlowApprovalType.MULTI_ABSTAIN)) {
|
||||
Map<String, Object> variables = runtimeService.getVariables(executionId);
|
||||
Integer agreeCount = (Integer) variables.get(FlowConstant.MULTI_AGREE_COUNT_VAR);
|
||||
Integer refuseCount = (Integer) variables.get(FlowConstant.MULTI_REFUSE_COUNT_VAR);
|
||||
Integer abstainCount = (Integer) variables.get(FlowConstant.MULTI_ABSTAIN_COUNT_VAR);
|
||||
Integer nrOfInstances = (Integer) variables.get(FlowConstant.NUMBER_OF_INSTANCES_VAR);
|
||||
taskVariableData.put(FlowConstant.MULTI_AGREE_COUNT_VAR, agreeCount);
|
||||
taskVariableData.put(FlowConstant.MULTI_REFUSE_COUNT_VAR, refuseCount);
|
||||
taskVariableData.put(FlowConstant.MULTI_ABSTAIN_COUNT_VAR, abstainCount);
|
||||
taskVariableData.put(FlowConstant.MULTI_SIGN_NUM_OF_INSTANCES_VAR, nrOfInstances);
|
||||
switch (approvalType) {
|
||||
case FlowApprovalType.MULTI_AGREE:
|
||||
if (agreeCount == null) {
|
||||
agreeCount = 0;
|
||||
}
|
||||
taskVariableData.put(FlowConstant.MULTI_AGREE_COUNT_VAR, agreeCount + 1);
|
||||
break;
|
||||
case FlowApprovalType.MULTI_REFUSE:
|
||||
if (refuseCount == null) {
|
||||
refuseCount = 0;
|
||||
}
|
||||
taskVariableData.put(FlowConstant.MULTI_REFUSE_COUNT_VAR, refuseCount + 1);
|
||||
break;
|
||||
case FlowApprovalType.MULTI_ABSTAIN:
|
||||
if (abstainCount == null) {
|
||||
abstainCount = 0;
|
||||
}
|
||||
taskVariableData.put(FlowConstant.MULTI_ABSTAIN_COUNT_VAR, abstainCount + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildCandidateCondition(TaskQuery query, String loginName) {
|
||||
Set<String> groupIdSet = new HashSet<>();
|
||||
// NOTE: 目前已经支持部门和岗位,如果今后需要支持角色,可将角色Id也加到groupIdSet中即可。
|
||||
// 需要注意的是,部门Id、部门岗位Id,或者其他类型的分组Id,他们之间一定不能重复。
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
Object deptId = tokenData.getDeptId();
|
||||
if (deptId != null) {
|
||||
groupIdSet.add(deptId.toString());
|
||||
}
|
||||
String deptPostIds = tokenData.getDeptPostIds();
|
||||
if (StrUtil.isNotBlank(deptPostIds)) {
|
||||
groupIdSet.addAll(Arrays.asList(StrUtil.split(deptPostIds, ",")));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(groupIdSet)) {
|
||||
List<String> groupIdList = new LinkedList<>(groupIdSet);
|
||||
query.or().taskCandidateGroupIn(groupIdList).taskCandidateOrAssigned(loginName).endOr();
|
||||
} else {
|
||||
query.taskCandidateOrAssigned(loginName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.core.object.MyRelationParam;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
|
||||
import com.flow.demo.common.flow.dao.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FlowCategory数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowCategoryService")
|
||||
public class FlowCategoryServiceImpl extends BaseService<FlowCategory, Long> implements FlowCategoryService {
|
||||
|
||||
@Autowired
|
||||
private FlowCategoryMapper flowCategoryMapper;
|
||||
@Autowired
|
||||
private IdGeneratorWrapper idGenerator;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowCategory> mapper() {
|
||||
return flowCategoryMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowCategory 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public FlowCategory saveNew(FlowCategory flowCategory) {
|
||||
flowCategory.setCategoryId(idGenerator.nextLongId());
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
flowCategory.setUpdateUserId(tokenData.getUserId());
|
||||
flowCategory.setCreateUserId(tokenData.getUserId());
|
||||
Date now = new Date();
|
||||
flowCategory.setUpdateTime(now);
|
||||
flowCategory.setCreateTime(now);
|
||||
flowCategoryMapper.insert(flowCategory);
|
||||
return flowCategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowCategory 更新的对象。
|
||||
* @param originalFlowCategory 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean update(FlowCategory flowCategory, FlowCategory originalFlowCategory) {
|
||||
flowCategory.setUpdateUserId(TokenData.takeFromRequest().getUserId());
|
||||
flowCategory.setCreateUserId(originalFlowCategory.getCreateUserId());
|
||||
flowCategory.setUpdateTime(new Date());
|
||||
flowCategory.setCreateTime(originalFlowCategory.getCreateTime());
|
||||
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
|
||||
UpdateWrapper<FlowCategory> uw =
|
||||
this.createUpdateQueryForNullValue(flowCategory, flowCategory.getCategoryId());
|
||||
return flowCategoryMapper.update(flowCategory, uw) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param categoryId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean remove(Long categoryId) {
|
||||
return flowCategoryMapper.deleteById(categoryId) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowCategoryListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowCategory> getFlowCategoryList(FlowCategory filter, String orderBy) {
|
||||
return flowCategoryMapper.getFlowCategoryList(filter, orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowCategoryList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowCategory> getFlowCategoryListWithRelation(FlowCategory filter, String orderBy) {
|
||||
List<FlowCategory> resultList = flowCategoryMapper.getFlowCategoryList(filter, orderBy);
|
||||
// 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
|
||||
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
|
||||
int batchSize = resultList instanceof Page ? 0 : 1000;
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.core.object.CallResult;
|
||||
import com.flow.demo.common.core.object.MyRelationParam;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.core.util.MyModelUtil;
|
||||
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
|
||||
import com.flow.demo.common.flow.util.BaseFlowDeptPostExtHelper;
|
||||
import com.flow.demo.common.flow.util.FlowCustomExtFactory;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.dao.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.model.constant.FlowEntryStatus;
|
||||
import com.flow.demo.common.flow.model.constant.FlowVariableType;
|
||||
import com.flow.demo.common.flow.listener.UpdateFlowStatusListener;
|
||||
import lombok.Cleanup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.FlowElement;
|
||||
import org.activiti.bpmn.model.UserTask;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* FlowEntry数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowEntryService")
|
||||
public class FlowEntryServiceImpl extends BaseService<FlowEntry, Long> implements FlowEntryService {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryMapper flowEntryMapper;
|
||||
@Autowired
|
||||
private FlowEntryPublishMapper flowEntryPublishMapper;
|
||||
@Autowired
|
||||
private FlowEntryPublishVariableMapper flowEntryPublishVariableMapper;
|
||||
@Autowired
|
||||
private FlowEntryVariableService flowEntryVariableService;
|
||||
@Autowired
|
||||
private FlowCategoryService flowCategoryService;
|
||||
@Autowired
|
||||
private FlowTaskExtService flowTaskExtService;
|
||||
@Autowired
|
||||
private FlowApiService flowApiService;
|
||||
@Autowired
|
||||
private FlowCustomExtFactory flowCustomExtFactory;
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private IdGeneratorWrapper idGenerator;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowEntry> mapper() {
|
||||
return flowEntryMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowEntry 新增工作流对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public FlowEntry saveNew(FlowEntry flowEntry) {
|
||||
flowEntry.setEntryId(idGenerator.nextLongId());
|
||||
flowEntry.setStatus(FlowEntryStatus.UNPUBLISHED);
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
flowEntry.setUpdateUserId(tokenData.getUserId());
|
||||
flowEntry.setCreateUserId(tokenData.getUserId());
|
||||
Date now = new Date();
|
||||
flowEntry.setUpdateTime(now);
|
||||
flowEntry.setCreateTime(now);
|
||||
flowEntryMapper.insert(flowEntry);
|
||||
this.insertBuiltinEntryVariables(flowEntry.getEntryId());
|
||||
return flowEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布指定流程。
|
||||
*
|
||||
* @param flowEntry 待发布的流程对象。
|
||||
* @param initTaskInfo 第一个非开始节点任务的附加信息。
|
||||
* @param flowTaskExtList 所有用户任务的自定义扩展数据列表。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void publish(FlowEntry flowEntry, String initTaskInfo, List<FlowTaskExt> flowTaskExtList) throws XMLStreamException {
|
||||
FlowCategory flowCategory = flowCategoryService.getById(flowEntry.getCategoryId());
|
||||
InputStream xmlStream = new ByteArrayInputStream(
|
||||
flowEntry.getBpmnXml().getBytes(StandardCharsets.UTF_8));
|
||||
@Cleanup XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(xmlStream);
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
BpmnModel bpmnModel = converter.convertToBpmnModel(reader);
|
||||
flowApiService.addProcessInstanceEndListener(bpmnModel, UpdateFlowStatusListener.class);
|
||||
Collection<FlowElement> elementList = bpmnModel.getMainProcess().getFlowElements();
|
||||
Map<String, FlowElement> elementMap =
|
||||
elementList.stream().filter(e -> e instanceof UserTask).collect(Collectors.toMap(FlowElement::getId, c -> c));
|
||||
if (CollUtil.isNotEmpty(flowTaskExtList)) {
|
||||
BaseFlowDeptPostExtHelper flowDeptPostExtHelper = flowCustomExtFactory.getFlowDeptPostExtHelper();
|
||||
for (FlowTaskExt t : flowTaskExtList) {
|
||||
UserTask userTask = (UserTask) elementMap.get(t.getTaskId());
|
||||
// 如果流程图中包含部门领导审批和上级部门领导审批的选项,就需要注册 FlowCustomExtFactory 工厂中的
|
||||
// BaseFlowDeptPostExtHelper 对象,该注册操作需要业务模块中实现。
|
||||
if (StrUtil.equals(t.getGroupType(), FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER)) {
|
||||
userTask.setCandidateGroups(
|
||||
CollUtil.newArrayList("${" + FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER_VAR + "}"));
|
||||
Assert.notNull(flowDeptPostExtHelper);
|
||||
flowApiService.addTaskCreateListener(userTask, flowDeptPostExtHelper.getUpDeptPostLeaderListener());
|
||||
} else if (StrUtil.equals(t.getGroupType(), FlowConstant.GROUP_TYPE_DEPT_POST_LEADER)) {
|
||||
userTask.setCandidateGroups(
|
||||
CollUtil.newArrayList("${" + FlowConstant.GROUP_TYPE_DEPT_POST_LEADER_VAR + "}"));
|
||||
Assert.notNull(flowDeptPostExtHelper);
|
||||
flowApiService.addTaskCreateListener(userTask, flowDeptPostExtHelper.getDeptPostLeaderListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.addBpmnModel(flowEntry.getProcessDefinitionKey() + ".bpmn", bpmnModel)
|
||||
.name(flowEntry.getProcessDefinitionName())
|
||||
.key(flowEntry.getProcessDefinitionKey())
|
||||
.category(flowCategory.getCode())
|
||||
.deploy();
|
||||
ProcessDefinition processDefinition = flowApiService.getProcessDefinitionByDeployId(deploy.getId());
|
||||
FlowEntryPublish flowEntryPublish = new FlowEntryPublish();
|
||||
flowEntryPublish.setEntryPublishId(idGenerator.nextLongId());
|
||||
flowEntryPublish.setEntryId(flowEntry.getEntryId());
|
||||
flowEntryPublish.setProcessDefinitionId(processDefinition.getId());
|
||||
flowEntryPublish.setDeployId(processDefinition.getDeploymentId());
|
||||
flowEntryPublish.setPublishVersion(processDefinition.getVersion());
|
||||
flowEntryPublish.setActiveStatus(true);
|
||||
flowEntryPublish.setMainVersion(flowEntry.getStatus().equals(FlowEntryStatus.UNPUBLISHED));
|
||||
flowEntryPublish.setCreateUserId(TokenData.takeFromRequest().getUserId());
|
||||
flowEntryPublish.setPublishTime(new Date());
|
||||
flowEntryPublish.setInitTaskInfo(initTaskInfo);
|
||||
flowEntryPublishMapper.insert(flowEntryPublish);
|
||||
FlowEntry updatedFlowEntry = new FlowEntry();
|
||||
updatedFlowEntry.setEntryId(flowEntry.getEntryId());
|
||||
updatedFlowEntry.setStatus(FlowEntryStatus.PUBLISHED);
|
||||
updatedFlowEntry.setLastestPublishTime(new Date());
|
||||
// 对于从未发布过的工作,第一次发布的时候会将本地发布置位主版本。
|
||||
if (flowEntry.getStatus().equals(FlowEntryStatus.UNPUBLISHED)) {
|
||||
updatedFlowEntry.setMainEntryPublishId(flowEntryPublish.getEntryPublishId());
|
||||
}
|
||||
flowEntryMapper.updateById(updatedFlowEntry);
|
||||
FlowEntryVariable flowEntryVariableFilter = new FlowEntryVariable();
|
||||
flowEntryVariableFilter.setEntryId(flowEntry.getEntryId());
|
||||
List<FlowEntryVariable> flowEntryVariableList =
|
||||
flowEntryVariableService.getFlowEntryVariableList(flowEntryVariableFilter, null);
|
||||
if (CollUtil.isNotEmpty(flowTaskExtList)) {
|
||||
flowTaskExtList.forEach(t -> t.setProcessDefinitionId(processDefinition.getId()));
|
||||
flowTaskExtService.saveBatch(flowTaskExtList);
|
||||
}
|
||||
this.insertEntryPublishVariables(flowEntryVariableList, flowEntryPublish.getEntryPublishId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowEntry 更新的对象。
|
||||
* @param originalFlowEntry 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean update(FlowEntry flowEntry, FlowEntry originalFlowEntry) {
|
||||
flowEntry.setUpdateUserId(TokenData.takeFromRequest().getUserId());
|
||||
flowEntry.setCreateUserId(originalFlowEntry.getCreateUserId());
|
||||
flowEntry.setUpdateTime(new Date());
|
||||
flowEntry.setCreateTime(originalFlowEntry.getCreateTime());
|
||||
flowEntry.setPageId(originalFlowEntry.getPageId());
|
||||
return flowEntryMapper.updateById(flowEntry) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param entryId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean remove(Long entryId) {
|
||||
if (flowEntryMapper.deleteById(entryId) != 1) {
|
||||
return false;
|
||||
}
|
||||
flowEntryVariableService.removeByEntryId(entryId);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowEntryListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntry> getFlowEntryList(FlowEntry filter, String orderBy) {
|
||||
return flowEntryMapper.getFlowEntryList(filter, orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowEntryList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntry> getFlowEntryListWithRelation(FlowEntry filter, String orderBy) {
|
||||
List<FlowEntry> resultList = flowEntryMapper.getFlowEntryList(filter, orderBy);
|
||||
// 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
|
||||
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
|
||||
int batchSize = resultList instanceof Page ? 0 : 1000;
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
|
||||
Set<Long> mainEntryPublishIdSet = resultList.stream().filter(e -> e.getMainEntryPublishId() != null)
|
||||
.map(FlowEntry::getMainEntryPublishId).collect(Collectors.toSet());
|
||||
if (CollUtil.isNotEmpty(mainEntryPublishIdSet)) {
|
||||
List<FlowEntryPublish> mainEntryPublishList =
|
||||
flowEntryPublishMapper.selectBatchIds(mainEntryPublishIdSet);
|
||||
MyModelUtil.makeOneToOneRelation(FlowEntry.class, resultList, FlowEntry::getMainEntryPublishId,
|
||||
mainEntryPublishList, FlowEntryPublish::getEntryPublishId, "mainFlowEntryPublish");
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowEntry getFlowEntryByProcessDefinitionKey(String processDefinitionKey) {
|
||||
FlowEntry filter = new FlowEntry();
|
||||
filter.setProcessDefinitionKey(processDefinitionKey);
|
||||
return flowEntryMapper.selectOne(new LambdaQueryWrapper<>(filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程Id获取流程发布列表数据。
|
||||
*
|
||||
* @param entryId 流程Id。
|
||||
* @return 流程关联的发布列表数据。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntryPublish> getFlowEntryPublishList(Long entryId) {
|
||||
FlowEntryPublish filter = new FlowEntryPublish();
|
||||
filter.setEntryId(entryId);
|
||||
LambdaQueryWrapper<FlowEntryPublish> queryWrapper = new LambdaQueryWrapper<>(filter);
|
||||
queryWrapper.orderByDesc(FlowEntryPublish::getEntryPublishId);
|
||||
return flowEntryPublishMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程引擎中的流程定义Id集合,查询流程发布对象。
|
||||
*
|
||||
* @param processDefinitionIdSet 流程引擎中的流程定义Id集合。
|
||||
* @return 查询结果。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntryPublish> getFlowEntryPublishList(Set<String> processDefinitionIdSet) {
|
||||
LambdaQueryWrapper<FlowEntryPublish> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(FlowEntryPublish::getProcessDefinitionId, processDefinitionIdSet);
|
||||
return flowEntryPublishMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定工作流发布版本对象。同时同步修改工作流对象中冗余状态字段。
|
||||
*
|
||||
* @param entryPublishId 工作流发布对象Id。
|
||||
* @return 查询后的对象。
|
||||
*/
|
||||
@Override
|
||||
public FlowEntryPublish getFlowEntryPublishById(Long entryPublishId) {
|
||||
return flowEntryPublishMapper.selectById(entryPublishId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定流程定义Id对应的流程发布对象。
|
||||
*
|
||||
* @param processDefinitionId 流程定义Id。
|
||||
* @return 流程发布对象。
|
||||
*/
|
||||
@Override
|
||||
public FlowEntryPublish getFlowEntryPublishByDefinitionId(String processDefinitionId) {
|
||||
LambdaQueryWrapper<FlowEntryPublish> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(FlowEntryPublish::getProcessDefinitionId, processDefinitionId);
|
||||
return flowEntryPublishMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为指定工作流切换发布的主版本。
|
||||
*
|
||||
* @param flowEntry 工作流对象。
|
||||
* @param newMainFlowEntryPublish 工作流新的发布主版本对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateFlowEntryMainVersion(FlowEntry flowEntry, FlowEntryPublish newMainFlowEntryPublish) {
|
||||
FlowEntryPublish oldMainFlowEntryPublish =
|
||||
flowEntryPublishMapper.selectById(flowEntry.getMainEntryPublishId());
|
||||
oldMainFlowEntryPublish.setMainVersion(false);
|
||||
flowEntryPublishMapper.updateById(oldMainFlowEntryPublish);
|
||||
newMainFlowEntryPublish.setMainVersion(true);
|
||||
flowEntryPublishMapper.updateById(newMainFlowEntryPublish);
|
||||
FlowEntry updatedEntry = new FlowEntry();
|
||||
updatedEntry.setEntryId(flowEntry.getEntryId());
|
||||
updatedEntry.setMainEntryPublishId(newMainFlowEntryPublish.getEntryPublishId());
|
||||
flowEntryMapper.updateById(updatedEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起指定的工作流发布对象。同时同步修改工作流对象中冗余状态字段。
|
||||
*
|
||||
* @param flowEntryPublish 待挂起的工作流发布对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void suspendFlowEntryPublish(FlowEntryPublish flowEntryPublish) {
|
||||
FlowEntryPublish updatedEntryPublish = new FlowEntryPublish();
|
||||
updatedEntryPublish.setEntryPublishId(flowEntryPublish.getEntryPublishId());
|
||||
updatedEntryPublish.setActiveStatus(false);
|
||||
flowEntryPublishMapper.updateById(updatedEntryPublish);
|
||||
flowApiService.suspendProcessDefinition(flowEntryPublish.getProcessDefinitionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活指定的工作流发布对象。
|
||||
*
|
||||
* @param flowEntryPublish 待恢复的工作流发布对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void activateFlowEntryPublish(FlowEntryPublish flowEntryPublish) {
|
||||
FlowEntryPublish updatedEntryPublish = new FlowEntryPublish();
|
||||
updatedEntryPublish.setEntryPublishId(flowEntryPublish.getEntryPublishId());
|
||||
updatedEntryPublish.setActiveStatus(true);
|
||||
flowEntryPublishMapper.updateById(updatedEntryPublish);
|
||||
flowApiService.activateProcessDefinition(flowEntryPublish.getProcessDefinitionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 主表的关联数据验证。
|
||||
*
|
||||
* @param flowEntry 最新数据对象。
|
||||
* @param originalFlowEntry 原有数据对象。
|
||||
* @return 数据全部正确返回true,否则false。
|
||||
*/
|
||||
@Override
|
||||
public CallResult verifyRelatedData(FlowEntry flowEntry, FlowEntry originalFlowEntry) {
|
||||
String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!";
|
||||
if (this.needToVerify(flowEntry, originalFlowEntry, FlowEntry::getCategoryId)
|
||||
&& !flowCategoryService.existId(flowEntry.getCategoryId())) {
|
||||
return CallResult.error(String.format(errorMessageFormat, "流程类别Id"));
|
||||
}
|
||||
return CallResult.ok();
|
||||
}
|
||||
|
||||
private void insertBuiltinEntryVariables(Long entryId) {
|
||||
Date now = new Date();
|
||||
FlowEntryVariable operationTypeVariable = new FlowEntryVariable();
|
||||
operationTypeVariable.setVariableId(idGenerator.nextLongId());
|
||||
operationTypeVariable.setEntryId(entryId);
|
||||
operationTypeVariable.setVariableName(FlowConstant.OPERATION_TYPE_VAR);
|
||||
operationTypeVariable.setShowName("审批类型");
|
||||
operationTypeVariable.setVariableType(FlowVariableType.TASK);
|
||||
operationTypeVariable.setBuiltin(true);
|
||||
operationTypeVariable.setCreateTime(now);
|
||||
flowEntryVariableService.saveNew(operationTypeVariable);
|
||||
FlowEntryVariable startUserNameVariable = new FlowEntryVariable();
|
||||
startUserNameVariable.setVariableId(idGenerator.nextLongId());
|
||||
startUserNameVariable.setEntryId(entryId);
|
||||
startUserNameVariable.setVariableName("startUserName");
|
||||
startUserNameVariable.setShowName("流程启动用户");
|
||||
startUserNameVariable.setVariableType(FlowVariableType.INSTANCE);
|
||||
startUserNameVariable.setBuiltin(true);
|
||||
startUserNameVariable.setCreateTime(now);
|
||||
flowEntryVariableService.saveNew(startUserNameVariable);
|
||||
}
|
||||
|
||||
private void insertEntryPublishVariables(List<FlowEntryVariable> entryVariableList, Long entryPublishId) {
|
||||
if (CollUtil.isEmpty(entryVariableList)) {
|
||||
return;
|
||||
}
|
||||
List<FlowEntryPublishVariable> entryPublishVariableList =
|
||||
MyModelUtil.copyCollectionTo(entryVariableList, FlowEntryPublishVariable.class);
|
||||
for (FlowEntryPublishVariable variable : entryPublishVariableList) {
|
||||
variable.setVariableId(idGenerator.nextLongId());
|
||||
variable.setEntryPublishId(entryPublishId);
|
||||
}
|
||||
flowEntryPublishVariableMapper.insertList(entryPublishVariableList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.dao.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.object.MyRelationParam;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
|
||||
import com.github.pagehelper.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程变量数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowEntryVariableService")
|
||||
public class FlowEntryVariableServiceImpl extends BaseService<FlowEntryVariable, Long> implements FlowEntryVariableService {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryVariableMapper flowEntryVariableMapper;
|
||||
@Autowired
|
||||
private IdGeneratorWrapper idGenerator;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowEntryVariable> mapper() {
|
||||
return flowEntryVariableMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowEntryVariable 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public FlowEntryVariable saveNew(FlowEntryVariable flowEntryVariable) {
|
||||
flowEntryVariable.setVariableId(idGenerator.nextLongId());
|
||||
flowEntryVariable.setCreateTime(new Date());
|
||||
flowEntryVariableMapper.insert(flowEntryVariable);
|
||||
return flowEntryVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据对象。
|
||||
*
|
||||
* @param flowEntryVariable 更新的对象。
|
||||
* @param originalFlowEntryVariable 原有数据对象。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean update(FlowEntryVariable flowEntryVariable, FlowEntryVariable originalFlowEntryVariable) {
|
||||
flowEntryVariable.setCreateTime(originalFlowEntryVariable.getCreateTime());
|
||||
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
|
||||
UpdateWrapper<FlowEntryVariable> uw = this.createUpdateQueryForNullValue(flowEntryVariable, flowEntryVariable.getVariableId());
|
||||
return flowEntryVariableMapper.update(flowEntryVariable, uw) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param variableId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean remove(Long variableId) {
|
||||
return flowEntryVariableMapper.deleteById(variableId) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定流程Id的所有变量。
|
||||
*
|
||||
* @param entryId 流程Id。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void removeByEntryId(Long entryId) {
|
||||
flowEntryVariableMapper.delete(
|
||||
new LambdaQueryWrapper<FlowEntryVariable>().eq(FlowEntryVariable::getEntryId, entryId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
|
||||
* 如果需要同时获取关联数据,请移步(getFlowEntryVariableListWithRelation)方法。
|
||||
*
|
||||
* @param filter 过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntryVariable> getFlowEntryVariableList(FlowEntryVariable filter, String orderBy) {
|
||||
return flowEntryVariableMapper.getFlowEntryVariableList(filter, orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
|
||||
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
|
||||
* 如果仅仅需要获取主表数据,请移步(getFlowEntryVariableList),以便获取更好的查询性能。
|
||||
*
|
||||
* @param filter 主表过滤对象。
|
||||
* @param orderBy 排序参数。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowEntryVariable> getFlowEntryVariableListWithRelation(FlowEntryVariable filter, String orderBy) {
|
||||
List<FlowEntryVariable> resultList = flowEntryVariableMapper.getFlowEntryVariableList(filter, orderBy);
|
||||
// 在缺省生成的代码中,如果查询结果resultList不是Page对象,说明没有分页,那么就很可能是数据导出接口调用了当前方法。
|
||||
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
|
||||
int batchSize = resultList instanceof Page ? 0 : 1000;
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.dao.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 流程任务批注数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowTaskCommentService")
|
||||
public class FlowTaskCommentServiceImpl extends BaseService<FlowTaskComment, Long> implements FlowTaskCommentService {
|
||||
|
||||
@Autowired
|
||||
private FlowTaskCommentMapper flowTaskCommentMapper;
|
||||
@Autowired
|
||||
private IdGeneratorWrapper idGenerator;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowTaskComment> mapper() {
|
||||
return flowTaskCommentMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param flowTaskComment 新增对象。
|
||||
* @return 返回新增对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public FlowTaskComment saveNew(FlowTaskComment flowTaskComment) {
|
||||
flowTaskComment.setId(idGenerator.nextLongId());
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
flowTaskComment.setCreateUserId(tokenData.getUserId());
|
||||
flowTaskComment.setCreateUsername(tokenData.getShowName());
|
||||
flowTaskComment.setCreateTime(new Date());
|
||||
flowTaskCommentMapper.insert(flowTaskComment);
|
||||
return flowTaskComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定流程实例Id下的所有审批任务的批注。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @return 查询结果集。
|
||||
*/
|
||||
@Override
|
||||
public List<FlowTaskComment> getFlowTaskCommentList(String processInstanceId) {
|
||||
LambdaQueryWrapper<FlowTaskComment> queryWrapper =
|
||||
new LambdaQueryWrapper<FlowTaskComment>().eq(FlowTaskComment::getProcessInstanceId, processInstanceId);
|
||||
queryWrapper.orderByAsc(FlowTaskComment::getId);
|
||||
return flowTaskCommentMapper.selectList(queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.flow.demo.common.flow.service.*;
|
||||
import com.flow.demo.common.flow.dao.*;
|
||||
import com.flow.demo.common.flow.model.*;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程任务扩展数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowTaskExtService")
|
||||
public class FlowTaskExtServiceImpl extends BaseService<FlowTaskExt, String> implements FlowTaskExtService {
|
||||
|
||||
@Autowired
|
||||
private FlowTaskExtMapper flowTaskExtMapper;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowTaskExt> mapper() {
|
||||
return flowTaskExtMapper;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void saveBatch(List<FlowTaskExt> flowTaskExtList) {
|
||||
if (CollUtil.isNotEmpty(flowTaskExtList)) {
|
||||
flowTaskExtMapper.insertList(flowTaskExtList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowTaskExt getByProcessDefinitionIdAndTaskId(String processDefinitionId, String taskId) {
|
||||
FlowTaskExt filter = new FlowTaskExt();
|
||||
filter.setProcessDefinitionId(processDefinitionId);
|
||||
filter.setTaskId(taskId);
|
||||
return flowTaskExtMapper.selectOne(new QueryWrapper<>(filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowTaskExt> getByProcessDefinitionId(String processDefinitionId) {
|
||||
FlowTaskExt filter = new FlowTaskExt();
|
||||
filter.setProcessDefinitionId(processDefinitionId);
|
||||
return flowTaskExtMapper.selectList(new QueryWrapper<>(filter));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.flow.demo.common.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
|
||||
import com.flow.demo.common.core.constant.GlobalDeletedFlag;
|
||||
import com.flow.demo.common.core.object.MyRelationParam;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.core.base.service.BaseService;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.dao.FlowWorkOrderMapper;
|
||||
import com.flow.demo.common.flow.model.FlowWorkOrder;
|
||||
import com.flow.demo.common.flow.service.FlowWorkOrderService;
|
||||
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 工作流工单表数据操作服务类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("flowWorkOrderService")
|
||||
public class FlowWorkOrderServiceImpl extends BaseService<FlowWorkOrder, Long> implements FlowWorkOrderService {
|
||||
|
||||
@Autowired
|
||||
private FlowWorkOrderMapper flowWorkOrderMapper;
|
||||
@Autowired
|
||||
private IdGeneratorWrapper idGenerator;
|
||||
|
||||
/**
|
||||
* 返回当前Service的主表Mapper对象。
|
||||
*
|
||||
* @return 主表Mapper对象。
|
||||
*/
|
||||
@Override
|
||||
protected BaseDaoMapper<FlowWorkOrder> mapper() {
|
||||
return flowWorkOrderMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新增对象。
|
||||
*
|
||||
* @param instance 流程实例对象。
|
||||
* @param dataId 流程实例的BusinessKey。
|
||||
* @param onlineTableId 在线数据表的主键Id。
|
||||
* @return 新增的工作流工单对象。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public FlowWorkOrder saveNew(ProcessInstance instance, Object dataId, Long onlineTableId) {
|
||||
TokenData tokenData = TokenData.takeFromRequest();
|
||||
Date now = new Date();
|
||||
FlowWorkOrder flowWorkOrder = new FlowWorkOrder();
|
||||
flowWorkOrder.setWorkOrderId(idGenerator.nextLongId());
|
||||
flowWorkOrder.setProcessDefinitionKey(instance.getProcessDefinitionKey());
|
||||
flowWorkOrder.setProcessDefinitionName(instance.getProcessDefinitionName());
|
||||
flowWorkOrder.setProcessDefinitionId(instance.getProcessDefinitionId());
|
||||
flowWorkOrder.setProcessInstanceId(instance.getId());
|
||||
flowWorkOrder.setBusinessKey(dataId.toString());
|
||||
flowWorkOrder.setOnlineTableId(onlineTableId);
|
||||
flowWorkOrder.setFlowStatus(FlowTaskStatus.SUBMITTED);
|
||||
flowWorkOrder.setSubmitUsername(tokenData.getLoginName());
|
||||
flowWorkOrder.setDeptId(tokenData.getDeptId());
|
||||
flowWorkOrder.setCreateUserId(tokenData.getUserId());
|
||||
flowWorkOrder.setUpdateUserId(tokenData.getUserId());
|
||||
flowWorkOrder.setCreateTime(now);
|
||||
flowWorkOrder.setUpdateTime(now);
|
||||
flowWorkOrder.setDeletedFlag(GlobalDeletedFlag.NORMAL);
|
||||
flowWorkOrderMapper.insert(flowWorkOrder);
|
||||
return flowWorkOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
* @param workOrderId 主键Id。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean remove(Long workOrderId) {
|
||||
return flowWorkOrderMapper.deleteById(workOrderId) == 1;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void removeByProcessInstanceId(String processInstanceId) {
|
||||
FlowWorkOrder filter = new FlowWorkOrder();
|
||||
filter.setProcessInstanceId(processInstanceId);
|
||||
super.removeBy(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowWorkOrder> getFlowWorkOrderList(FlowWorkOrder filter, String orderBy) {
|
||||
return flowWorkOrderMapper.getFlowWorkOrderList(filter, orderBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FlowWorkOrder> getFlowWorkOrderListWithRelation(FlowWorkOrder filter, String orderBy) {
|
||||
List<FlowWorkOrder> resultList = flowWorkOrderMapper.getFlowWorkOrderList(filter, orderBy);
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowWorkOrder getFlowWorkOrderByProcessInstanceId(String processInstanceId) {
|
||||
FlowWorkOrder filter = new FlowWorkOrder();
|
||||
filter.setProcessInstanceId(processInstanceId);
|
||||
return flowWorkOrderMapper.selectOne(new QueryWrapper<>(filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existByBusinessKey(Object businessKey, boolean unfinished) {
|
||||
LambdaQueryWrapper<FlowWorkOrder> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(FlowWorkOrder::getBusinessKey, businessKey.toString());
|
||||
if (unfinished) {
|
||||
queryWrapper.notIn(FlowWorkOrder::getFlowStatus,
|
||||
FlowTaskStatus.FINISHED, FlowTaskStatus.CANCELLED, FlowTaskStatus.STOPPED);
|
||||
}
|
||||
return flowWorkOrderMapper.selectCount(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateFlowStatusByBusinessKey(String businessKey, int flowStatus) {
|
||||
FlowWorkOrder flowWorkOrder = new FlowWorkOrder();
|
||||
flowWorkOrder.setFlowStatus(flowStatus);
|
||||
if (FlowTaskStatus.FINISHED != flowStatus) {
|
||||
flowWorkOrder.setUpdateTime(new Date());
|
||||
flowWorkOrder.setUpdateUserId(TokenData.takeFromRequest().getUserId());
|
||||
}
|
||||
LambdaQueryWrapper<FlowWorkOrder> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(FlowWorkOrder::getBusinessKey, businessKey);
|
||||
flowWorkOrderMapper.update(flowWorkOrder, queryWrapper);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateFlowStatusByProcessInstanceId(String processInstanceId, int flowStatus) {
|
||||
FlowWorkOrder flowWorkOrder = new FlowWorkOrder();
|
||||
flowWorkOrder.setFlowStatus(flowStatus);
|
||||
if (FlowTaskStatus.FINISHED != flowStatus) {
|
||||
flowWorkOrder.setUpdateTime(new Date());
|
||||
flowWorkOrder.setUpdateUserId(TokenData.takeFromRequest().getUserId());
|
||||
}
|
||||
LambdaQueryWrapper<FlowWorkOrder> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(FlowWorkOrder::getProcessInstanceId, processInstanceId);
|
||||
flowWorkOrderMapper.update(flowWorkOrder, queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.flow.demo.common.flow.util;
|
||||
|
||||
import com.flow.demo.common.flow.listener.DeptPostLeaderListener;
|
||||
import com.flow.demo.common.flow.listener.UpDeptPostLeaderListener;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
|
||||
/**
|
||||
* 工作流与部门岗位相关的自定义扩展接口,需要业务模块自行实现该接口。也可以根据实际需求扩展该接口的方法。
|
||||
* 目前支持的主键类型为字符型和长整型,所以这里提供了两套实现接口。可根据实际情况实现其中一套即可。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
public interface BaseFlowDeptPostExtHelper {
|
||||
|
||||
/**
|
||||
* 根据(字符型)部门Id,获取当前用户部门领导所有的部门岗位Id。
|
||||
*
|
||||
* @param deptId 用户所在部门Id。
|
||||
* @return 当前用户部门领导所有的部门岗位Id。
|
||||
*/
|
||||
default String getLeaderDeptPostId(String deptId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据(字符型)部门Id,获取当前用户上级部门领导所有的部门岗位Id。
|
||||
*
|
||||
* @param deptId 用户所在部门Id。
|
||||
* @return 当前用户上级部门领导所有的部门岗位Id。
|
||||
*/
|
||||
default String getUpLeaderDeptPostId(String deptId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据(长整型)部门Id,获取当前用户部门领导所有的部门岗位Id。
|
||||
*
|
||||
* @param deptId 用户所在部门Id。
|
||||
* @return 当前用户部门领导所有的部门岗位Id。
|
||||
*/
|
||||
default Long getLeaderDeptPostId(Long deptId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据(长整型)部门Id,获取当前用户上级部门领导所有的部门岗位Id。
|
||||
*
|
||||
* @param deptId 用户所在部门Id。
|
||||
* @return 当前用户上级部门领导所有的部门岗位Id。
|
||||
*/
|
||||
default Long getUpLeaderDeptPostId(Long deptId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务执行人是当前部门领导岗位的任务监听器。
|
||||
* 通常会在没有找到领导部门岗位Id的时候,为当前任务指定其他的指派人、候选人或候选组。
|
||||
*
|
||||
* @return 任务监听器。
|
||||
*/
|
||||
default Class<? extends TaskListener> getDeptPostLeaderListener() {
|
||||
return DeptPostLeaderListener.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务执行人是上级部门领导岗位的任务监听器。
|
||||
* 通常会在没有找到领导部门岗位Id的时候,为当前任务指定其他的指派人、候选人或候选组。
|
||||
*
|
||||
* @return 任务监听器。
|
||||
*/
|
||||
default Class<? extends TaskListener> getUpDeptPostLeaderListener() {
|
||||
return UpDeptPostLeaderListener.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.flow.demo.common.flow.util;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 工作流自定义扩展工厂类。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Component
|
||||
public class FlowCustomExtFactory {
|
||||
|
||||
private BaseFlowDeptPostExtHelper flowDeptPostExtHelper;
|
||||
|
||||
/**
|
||||
* 获取业务模块自行实现的部门岗位扩展帮助实现类。
|
||||
*
|
||||
* @return 业务模块自行实现的部门岗位扩展帮助实现类。
|
||||
*/
|
||||
public BaseFlowDeptPostExtHelper getFlowDeptPostExtHelper() {
|
||||
return flowDeptPostExtHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册业务模块自行实现的部门岗位扩展帮助实现类。
|
||||
*
|
||||
* @param helper 业务模块自行实现的部门岗位扩展帮助实现类。
|
||||
*/
|
||||
public void registerFlowDeptPostExtHelper(BaseFlowDeptPostExtHelper helper) {
|
||||
this.flowDeptPostExtHelper = helper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
package com.flow.demo.common.flow.util;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.flow.demo.common.core.constant.ErrorCodeEnum;
|
||||
import com.flow.demo.common.core.object.CallResult;
|
||||
import com.flow.demo.common.core.object.ResponseResult;
|
||||
import com.flow.demo.common.core.object.TokenData;
|
||||
import com.flow.demo.common.core.util.MyModelUtil;
|
||||
import com.flow.demo.common.flow.constant.FlowApprovalType;
|
||||
import com.flow.demo.common.flow.constant.FlowConstant;
|
||||
import com.flow.demo.common.flow.constant.FlowTaskStatus;
|
||||
import com.flow.demo.common.flow.dto.FlowTaskCommentDto;
|
||||
import com.flow.demo.common.flow.dto.FlowWorkOrderDto;
|
||||
import com.flow.demo.common.flow.model.FlowEntry;
|
||||
import com.flow.demo.common.flow.model.FlowEntryPublish;
|
||||
import com.flow.demo.common.flow.model.FlowWorkOrder;
|
||||
import com.flow.demo.common.flow.model.constant.FlowEntryStatus;
|
||||
import com.flow.demo.common.flow.service.FlowApiService;
|
||||
import com.flow.demo.common.flow.service.FlowEntryService;
|
||||
import com.flow.demo.common.flow.vo.FlowWorkOrderVo;
|
||||
import com.flow.demo.common.flow.vo.TaskInfoVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.activiti.engine.task.TaskInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 工作流操作的通用帮助对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FlowOperationHelper {
|
||||
|
||||
@Autowired
|
||||
private FlowEntryService flowEntryService;
|
||||
@Autowired
|
||||
private FlowApiService flowApiService;
|
||||
|
||||
/**
|
||||
* 验证并获取流程对象。
|
||||
*
|
||||
* @param processDefinitionKey 流程引擎的流程定义标识。
|
||||
* @return 流程对象。
|
||||
*/
|
||||
public ResponseResult<FlowEntry> verifyAndGetFlowEntry(String processDefinitionKey) {
|
||||
String errorMessage;
|
||||
FlowEntry flowEntry = flowEntryService.getFlowEntryByProcessDefinitionKey(processDefinitionKey);
|
||||
if (flowEntry == null) {
|
||||
errorMessage = "数据验证失败,该流程并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!flowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) {
|
||||
errorMessage = "数据验证失败,该流程尚未发布,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
FlowEntryPublish flowEntryPublish =
|
||||
flowEntryService.getFlowEntryPublishById(flowEntry.getMainEntryPublishId());
|
||||
flowEntry.setMainFlowEntryPublish(flowEntryPublish);
|
||||
return ResponseResult.success(flowEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作流静态表单的参数验证工具方法。根据流程定义标识,获取关联的流程并对其进行合法性验证。
|
||||
*
|
||||
* @param processDefinitionKey 流程定义标识。
|
||||
* @return 返回流程对象。
|
||||
*/
|
||||
public ResponseResult<FlowEntry> verifyFullAndGetFlowEntry(String processDefinitionKey) {
|
||||
String errorMessage;
|
||||
// 验证流程管理数据状态的合法性。
|
||||
ResponseResult<FlowEntry> flowEntryResult = this.verifyAndGetFlowEntry(processDefinitionKey);
|
||||
if (!flowEntryResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(flowEntryResult);
|
||||
}
|
||||
// 验证流程一个用户任务的合法性。
|
||||
FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
|
||||
if (!flowEntryPublish.getActiveStatus()) {
|
||||
errorMessage = "数据验证失败,当前流程发布对象已被挂起,不能启动新流程!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
ResponseResult<TaskInfoVo> taskInfoResult =
|
||||
this.verifyAndGetInitialTaskInfo(flowEntryPublish, true);
|
||||
if (!taskInfoResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(taskInfoResult);
|
||||
}
|
||||
return flowEntryResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作流静态表单的参数验证工具方法。根据参数验证并获取指定的流程任务对象。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 流程任务Id。
|
||||
* @param flowTaskComment 流程审批对象。
|
||||
* @return 验证后的流程任务对象。
|
||||
*/
|
||||
public ResponseResult<Task> verifySubmitAndGetTask(
|
||||
String processInstanceId, String taskId, FlowTaskCommentDto flowTaskComment) {
|
||||
// 验证流程任务的合法性。
|
||||
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
|
||||
ResponseResult<TaskInfoVo> taskInfoResult = this.verifyAndGetRuntimeTaskInfo(task);
|
||||
if (!taskInfoResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(taskInfoResult);
|
||||
}
|
||||
CallResult assigneeVerifyResult = flowApiService.verifyAssigneeOrCandidateAndClaim(task);
|
||||
if (!assigneeVerifyResult.isSuccess()) {
|
||||
return ResponseResult.errorFrom(assigneeVerifyResult);
|
||||
}
|
||||
if (StrUtil.isBlank(task.getBusinessKey())) {
|
||||
return ResponseResult.success(task);
|
||||
}
|
||||
String errorMessage;
|
||||
if (StrUtil.equals(flowTaskComment.getApprovalType(), FlowApprovalType.TRANSFER)) {
|
||||
if (StrUtil.isBlank(flowTaskComment.getDelegateAssginee())) {
|
||||
errorMessage = "数据验证失败,加签或转办任务指派人不能为空!!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
return ResponseResult.success(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作流静态表单的参数验证工具方法。根据参数验证并获取指定的历史流程实例对象。
|
||||
* 仅当登录用户为任务的分配人时,才能通过验证。
|
||||
*
|
||||
* @param processInstanceId 历史流程实例Id。
|
||||
* @param taskId 历史流程任务Id。
|
||||
* @return 验证后并返回的历史流程实例对象。
|
||||
*/
|
||||
public ResponseResult<HistoricProcessInstance> verifyAndHistoricProcessInstance(String processInstanceId, String taskId) {
|
||||
String errorMessage;
|
||||
// 验证流程实例的合法性。
|
||||
HistoricProcessInstance instance = flowApiService.getHistoricProcessInstance(processInstanceId);
|
||||
if (instance == null) {
|
||||
errorMessage = "数据验证失败,指定的流程实例Id并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
if (StrUtil.isBlank(taskId)) {
|
||||
if (!StrUtil.equals(loginName, instance.getStartUserId())) {
|
||||
errorMessage = "数据验证失败,指定历史流程的发起人与当前用户不匹配!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
} else {
|
||||
HistoricTaskInstance taskInstance = flowApiService.getHistoricTaskInstance(processInstanceId, taskId);
|
||||
if (taskInstance == null) {
|
||||
errorMessage = "数据验证失败,指定的任务Id并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!StrUtil.equals(loginName, taskInstance.getAssignee())) {
|
||||
errorMessage = "数据验证失败,历史任务的指派人与当前用户不匹配!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
return ResponseResult.success(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证并获取流程的实时任务信息。
|
||||
*
|
||||
* @param task 流程引擎的任务对象。
|
||||
* @return 任务信息对象。
|
||||
*/
|
||||
public ResponseResult<TaskInfoVo> verifyAndGetRuntimeTaskInfo(Task task) {
|
||||
String errorMessage;
|
||||
if (task == null) {
|
||||
errorMessage = "数据验证失败,指定的任务Id,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (!flowApiService.isAssigneeOrCandidate(task)) {
|
||||
errorMessage = "数据验证失败,当前用户不是指派人也不是候选人之一!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
if (StrUtil.isBlank(task.getFormKey())) {
|
||||
errorMessage = "数据验证失败,指定任务的formKey属性不存在,请重新修改流程图!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
TaskInfoVo taskInfo = JSON.parseObject(task.getFormKey(), TaskInfoVo.class);
|
||||
taskInfo.setTaskKey(task.getTaskDefinitionKey());
|
||||
return ResponseResult.success(taskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证并获取启动任务的对象信息。
|
||||
*
|
||||
* @param flowEntryPublish 流程发布对象。
|
||||
* @param checkStarter 是否检查发起用户。
|
||||
* @return 第一个可执行的任务信息。
|
||||
*/
|
||||
public ResponseResult<TaskInfoVo> verifyAndGetInitialTaskInfo(
|
||||
FlowEntryPublish flowEntryPublish, boolean checkStarter) {
|
||||
String errorMessage;
|
||||
if (StrUtil.isBlank(flowEntryPublish.getInitTaskInfo())) {
|
||||
errorMessage = "数据验证失败,当前流程发布的数据中,没有包含初始任务信息!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
TaskInfoVo taskInfo = JSON.parseObject(flowEntryPublish.getInitTaskInfo(), TaskInfoVo.class);
|
||||
if (checkStarter) {
|
||||
String loginName = TokenData.takeFromRequest().getLoginName();
|
||||
if (!StrUtil.equalsAny(taskInfo.getAssignee(), loginName, FlowConstant.START_USER_NAME_VAR)) {
|
||||
errorMessage = "数据验证失败,该工作流第一个用户任务的指派人并非当前用户,不能执行该操作!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
}
|
||||
return ResponseResult.success(taskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前用户是否有当前流程实例的数据上传或下载权限。
|
||||
* 如果taskId为空,则验证当前用户是否为当前流程实例的发起人,否则判断是否为当前任务的指派人或候选人。
|
||||
*
|
||||
* @param processInstanceId 流程实例Id。
|
||||
* @param taskId 流程任务Id。
|
||||
* @return 验证结果。
|
||||
*/
|
||||
public ResponseResult<Void> verifyUploadOrDownloadPermission(String processInstanceId, String taskId) {
|
||||
String errorMessage;
|
||||
if (StrUtil.isBlank(taskId)) {
|
||||
if (!flowApiService.isProcessInstanceStarter(processInstanceId)) {
|
||||
errorMessage = "数据验证失败,当前用户并非指派人或候选人,因此没有权限下载!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
} else {
|
||||
TaskInfo task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId);
|
||||
if (task == null) {
|
||||
task = flowApiService.getHistoricTaskInstance(processInstanceId, taskId);
|
||||
if (task == null) {
|
||||
errorMessage = "数据验证失败,指定任务Id不存在!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
}
|
||||
if (!flowApiService.isAssigneeOrCandidate(task)) {
|
||||
errorMessage = "数据验证失败,当前用户并非指派人或候选人,因此没有权限下载!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据已有的过滤对象,补充添加缺省过滤条件。如流程标识、创建用户等。
|
||||
*
|
||||
* @param filterDto 工单过滤对象。
|
||||
* @param processDefinitionKey 流程标识。
|
||||
* @return 创建并转换后的流程工单过滤对象。
|
||||
*/
|
||||
public FlowWorkOrder makeWorkOrderFilter(FlowWorkOrderDto filterDto, String processDefinitionKey) {
|
||||
FlowWorkOrder filter = MyModelUtil.copyTo(filterDto, FlowWorkOrder.class);
|
||||
if (filter == null) {
|
||||
filter = new FlowWorkOrder();
|
||||
}
|
||||
filter.setProcessDefinitionKey(processDefinitionKey);
|
||||
filter.setCreateUserId(TokenData.takeFromRequest().getUserId());
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装工作流工单列表中的流程任务数据。
|
||||
*
|
||||
* @param flowWorkOrderVoList 工作流工单列表。
|
||||
*/
|
||||
public void buildWorkOrderTaskInfo(List<FlowWorkOrderVo> flowWorkOrderVoList) {
|
||||
if (CollUtil.isEmpty(flowWorkOrderVoList)) {
|
||||
return;
|
||||
}
|
||||
Set<String> definitionIdSet =
|
||||
flowWorkOrderVoList.stream().map(FlowWorkOrderVo::getProcessDefinitionId).collect(Collectors.toSet());
|
||||
List<FlowEntryPublish> flowEntryPublishList = flowEntryService.getFlowEntryPublishList(definitionIdSet);
|
||||
Map<String, FlowEntryPublish> flowEntryPublishMap =
|
||||
flowEntryPublishList.stream().collect(Collectors.toMap(FlowEntryPublish::getProcessDefinitionId, c -> c));
|
||||
for (FlowWorkOrderVo flowWorkOrderVo : flowWorkOrderVoList) {
|
||||
FlowEntryPublish flowEntryPublish = flowEntryPublishMap.get(flowWorkOrderVo.getProcessDefinitionId());
|
||||
flowWorkOrderVo.setInitTaskInfo(flowEntryPublish.getInitTaskInfo());
|
||||
}
|
||||
List<String> unfinishedProcessInstanceIds = flowWorkOrderVoList.stream()
|
||||
.filter(c -> !c.getFlowStatus().equals(FlowTaskStatus.FINISHED))
|
||||
.map(FlowWorkOrderVo::getProcessInstanceId)
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(unfinishedProcessInstanceIds)) {
|
||||
return;
|
||||
}
|
||||
List<Task> taskList = flowApiService.getTaskListByProcessInstanceIds(unfinishedProcessInstanceIds);
|
||||
Map<String, List<Task>> taskMap =
|
||||
taskList.stream().collect(Collectors.groupingBy(Task::getProcessInstanceId));
|
||||
for (FlowWorkOrderVo flowWorkOrderVo : flowWorkOrderVoList) {
|
||||
List<Task> instanceTaskList = taskMap.get(flowWorkOrderVo.getProcessInstanceId());
|
||||
if (instanceTaskList == null) {
|
||||
continue;
|
||||
}
|
||||
JSONArray taskArray = new JSONArray();
|
||||
for (Task task : instanceTaskList) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("taskId", task.getId());
|
||||
jsonObject.put("taskName", task.getName());
|
||||
jsonObject.put("taskKey", task.getTaskDefinitionKey());
|
||||
jsonObject.put("assignee", task.getAssignee());
|
||||
taskArray.add(jsonObject);
|
||||
}
|
||||
flowWorkOrderVo.setRuntimeTaskInfoList(taskArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装工作流工单中的业务数据。
|
||||
*
|
||||
* @param workOrderVoList 工单列表。
|
||||
* @param dataList 业务数据列表。
|
||||
* @param idGetter 获取业务对象主键字段的返回方法。
|
||||
* @param <T> 业务主对象类型。
|
||||
* @param <K> 业务主对象的主键字段类型。
|
||||
*/
|
||||
public <T, K> void buildWorkOrderBusinessData(
|
||||
List<FlowWorkOrderVo> workOrderVoList, List<T> dataList, Function<T, K> idGetter) {
|
||||
if (CollUtil.isEmpty(dataList)) {
|
||||
return;
|
||||
}
|
||||
Map<Object, T> dataMap = dataList.stream().collect(Collectors.toMap(idGetter, c -> c));
|
||||
K id = idGetter.apply(dataList.get(0));
|
||||
for (FlowWorkOrderVo flowWorkOrderVo : workOrderVoList) {
|
||||
Object dataId = flowWorkOrderVo.getBusinessKey();
|
||||
if (id instanceof Long) {
|
||||
dataId = Long.valueOf(flowWorkOrderVo.getBusinessKey());
|
||||
} else if (id instanceof Integer) {
|
||||
dataId = Integer.valueOf(flowWorkOrderVo.getBusinessKey());
|
||||
}
|
||||
T data = dataMap.get(dataId);
|
||||
if (data != null) {
|
||||
flowWorkOrderVo.setMasterData(BeanUtil.beanToMap(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程分类的Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowCategoryVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 显示名称。
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 分类编码。
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 实现顺序。
|
||||
*/
|
||||
private Integer showOrder;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
private Long createUserId;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程发布信息的Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowEntryPublishVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long entryPublishId;
|
||||
|
||||
/**
|
||||
* 发布版本。
|
||||
*/
|
||||
private Integer publishVersion;
|
||||
|
||||
/**
|
||||
* 流程引擎中的流程定义Id。
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 激活状态。
|
||||
*/
|
||||
private Boolean activeStatus;
|
||||
|
||||
/**
|
||||
* 是否为主版本。
|
||||
*/
|
||||
private Boolean mainVersion;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 发布时间。
|
||||
*/
|
||||
private Date publishTime;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程变量Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowEntryVariableVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long variableId;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 变量名。
|
||||
*/
|
||||
private String variableName;
|
||||
|
||||
/**
|
||||
* 显示名。
|
||||
*/
|
||||
private String showName;
|
||||
|
||||
/**
|
||||
* 变量类型。
|
||||
*/
|
||||
private Integer variableType;
|
||||
|
||||
/**
|
||||
* 绑定数据源Id。
|
||||
*/
|
||||
private Long bindDatasourceId;
|
||||
|
||||
/**
|
||||
* 绑定数据源关联Id。
|
||||
*/
|
||||
private Long bindRelationId;
|
||||
|
||||
/**
|
||||
* 绑定字段Id。
|
||||
*/
|
||||
private Long bindColumnId;
|
||||
|
||||
/**
|
||||
* 是否内置。
|
||||
*/
|
||||
private Boolean builtin;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程的Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowEntryVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 流程名称。
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程标识Key。
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程分类。
|
||||
*/
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 工作流部署的发布主版本Id。
|
||||
*/
|
||||
private Long mainEntryPublishId;
|
||||
|
||||
/**
|
||||
* 最新发布时间。
|
||||
*/
|
||||
private Date lastestPublishTime;
|
||||
|
||||
/**
|
||||
* 流程状态。
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 流程定义的xml。
|
||||
*/
|
||||
private String bpmnXml;
|
||||
|
||||
/**
|
||||
* 绑定表单类型。
|
||||
*/
|
||||
private Integer bindFormType;
|
||||
|
||||
/**
|
||||
* 在线表单的页面Id。
|
||||
*/
|
||||
private Long pageId;
|
||||
|
||||
/**
|
||||
* 在线表单Id。
|
||||
*/
|
||||
private Long defaultFormId;
|
||||
|
||||
/**
|
||||
* 在线表单的缺省路由名称。
|
||||
*/
|
||||
private String defaultRouterName;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* categoryId 的一对一关联数据对象,数据对应类型为FlowCategoryVo。
|
||||
*/
|
||||
private Map<String, Object> flowCategory;
|
||||
|
||||
/**
|
||||
* mainEntryPublishId 的一对一关联数据对象,数据对应类型为FlowEntryPublishVo。
|
||||
*/
|
||||
private Map<String, Object> mainFlowEntryPublish;
|
||||
|
||||
/**
|
||||
* 关联的在线表单列表。
|
||||
*/
|
||||
private List<Map<String, Object>> formList;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* FlowTaskCommentVO对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowTaskCommentVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 流程实例Id。
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 任务Id。
|
||||
*/
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 任务标识。
|
||||
*/
|
||||
private String taskKey;
|
||||
|
||||
/**
|
||||
* 任务名称。
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 审批类型。
|
||||
*/
|
||||
private String approvalType;
|
||||
|
||||
/**
|
||||
* 批注内容。
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 委托指定人,比如加签、转办等。
|
||||
*/
|
||||
private String delegateAssginee;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 创建者显示名。
|
||||
*/
|
||||
private String createUsername;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程任务Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowTaskVo {
|
||||
|
||||
/**
|
||||
* 流程任务Id。
|
||||
*/
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 流程任务名称。
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 流程任务标识。
|
||||
*/
|
||||
private String taskKey;
|
||||
|
||||
/**
|
||||
* 任务的表单信息。
|
||||
*/
|
||||
private String taskFormKey;
|
||||
|
||||
/**
|
||||
* 流程Id。
|
||||
*/
|
||||
private Long entryId;
|
||||
|
||||
/**
|
||||
* 流程定义Id。
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程定义名称。
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程定义标识。
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程定义版本。
|
||||
*/
|
||||
private Integer processDefinitionVersion;
|
||||
|
||||
/**
|
||||
* 流程实例Id。
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 流程实例发起人。
|
||||
*/
|
||||
private String processInstanceInitiator;
|
||||
|
||||
/**
|
||||
* 流程实例创建时间。
|
||||
*/
|
||||
private Date processInstanceStartTime;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流工单VO对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class FlowWorkOrderVo {
|
||||
|
||||
/**
|
||||
* 主键Id。
|
||||
*/
|
||||
private Long workOrderId;
|
||||
|
||||
/**
|
||||
* 流程定义标识。
|
||||
*/
|
||||
private String processDefinitionKey;
|
||||
|
||||
/**
|
||||
* 流程名称。
|
||||
*/
|
||||
private String processDefinitionName;
|
||||
|
||||
/**
|
||||
* 流程引擎的定义Id。
|
||||
*/
|
||||
private String processDefinitionId;
|
||||
|
||||
/**
|
||||
* 流程实例Id。
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 在线表单的主表Id。
|
||||
*/
|
||||
private Long onlineTableId;
|
||||
|
||||
/**
|
||||
* 业务主键值。
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 流程状态。参考FlowTaskStatus常量值对象。
|
||||
*/
|
||||
private Integer flowStatus;
|
||||
|
||||
/**
|
||||
* 提交用户登录名称。
|
||||
*/
|
||||
private String submitUsername;
|
||||
|
||||
/**
|
||||
* 提交用户所在部门Id。
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 更新时间。
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 更新者Id。
|
||||
*/
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 创建时间。
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者Id。
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* flowStatus 常量字典关联数据。
|
||||
*/
|
||||
private Map<String, Object> flowStatusDictMap;
|
||||
|
||||
/**
|
||||
* FlowEntryPublish对象中的同名字段。
|
||||
*/
|
||||
private String initTaskInfo;
|
||||
|
||||
/**
|
||||
* 当前实例的运行时任务列表。
|
||||
* 正常情况下只有一个,在并行网关下可能存在多个。
|
||||
*/
|
||||
private JSONArray runtimeTaskInfoList;
|
||||
|
||||
/**
|
||||
* 业务主表数据。
|
||||
*/
|
||||
private Map<String, Object> masterData;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.flow.demo.common.flow.vo;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程任务信息Vo对象。
|
||||
*
|
||||
* @author Jerry
|
||||
* @date 2021-06-06
|
||||
*/
|
||||
@Data
|
||||
public class TaskInfoVo {
|
||||
|
||||
/**
|
||||
* 流程节点任务类型。具体值可参考FlowTaskType常量值。
|
||||
*/
|
||||
private Integer taskType;
|
||||
|
||||
/**
|
||||
* 指定人。
|
||||
*/
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 任务标识。
|
||||
*/
|
||||
private String taskKey;
|
||||
|
||||
/**
|
||||
* 是否分配给当前登录用户的标记。
|
||||
* 当该值为true时,登录用户启动流程时,就自动完成了第一个用户任务。
|
||||
*/
|
||||
private Boolean assignedMe;
|
||||
|
||||
/**
|
||||
* 动态表单Id。
|
||||
*/
|
||||
private Long formId;
|
||||
|
||||
/**
|
||||
* 静态表单路由。
|
||||
*/
|
||||
private String routerName;
|
||||
|
||||
/**
|
||||
* 候选组类型。
|
||||
*/
|
||||
private String groupType;
|
||||
|
||||
/**
|
||||
* 只读标记。
|
||||
*/
|
||||
private Boolean readOnly;
|
||||
|
||||
/**
|
||||
* 前端所需的操作列表。
|
||||
*/
|
||||
List<JSONObject> operationList;
|
||||
|
||||
/**
|
||||
* 任务节点的自定义变量列表。
|
||||
*/
|
||||
List<JSONObject> variableList;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.flow.demo.common.flow.config.FlowAutoConfig
|
||||
Reference in New Issue
Block a user