Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
This commit is contained in:
commit
1f2222cf83
|
@ -25,6 +25,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable<Integer> {
|
|||
START_USER_NODE(10, "发起人", "userTask"), // 发起人节点。前端的开始节点,Id 固定
|
||||
APPROVE_NODE(11, "审批人", "userTask"),
|
||||
COPY_NODE(12, "抄送人", "serviceTask"),
|
||||
TRANSACTOR_NODE(13, "办理人", "userTask"),
|
||||
|
||||
DELAY_TIMER_NODE(14, "延迟器", "receiveTask"),
|
||||
TRIGGER_NODE(15, "触发器", "serviceTask"),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmAutoApproveTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
|
@ -27,8 +26,7 @@ import java.util.List;
|
|||
@Data
|
||||
public class BpmModelMetaInfoVO {
|
||||
|
||||
@Schema(description = "流程图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg")
|
||||
@NotEmpty(message = "流程图标不能为空")
|
||||
@Schema(description = "流程图标", example = "https://www.iocoder.cn/yudao.jpg")
|
||||
@URL(message = "流程图标格式不正确")
|
||||
private String icon;
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ public class BpmTaskRespVO {
|
|||
@Schema(description = "是否填写审批意见", example = "false")
|
||||
private Boolean reasonRequire;
|
||||
|
||||
@Schema(description = "节点类型", example = "10")
|
||||
private Integer nodeType; // 参见 BpmSimpleModelNodeTypeEnum 枚举。
|
||||
|
||||
@Data
|
||||
@Schema(description = "流程实例")
|
||||
public static class ProcessInstance {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
|
||||
|
||||
/**
|
||||
* BPMN XML 常量信息
|
||||
*
|
||||
|
@ -129,4 +131,11 @@ public interface BpmnModelConstants {
|
|||
*/
|
||||
String REASON_REQUIRE = "reasonRequire";
|
||||
|
||||
/**
|
||||
* 节点类型
|
||||
*
|
||||
* 目前只有 {@link BpmModelTypeEnum#SIMPLE} 的 UserTask 节点会设置该属性,用于区分是审批节点、还是办理节点
|
||||
*/
|
||||
String NODE_TYPE = "nodeType";
|
||||
|
||||
}
|
||||
|
|
|
@ -410,6 +410,26 @@ public class BpmnModelUtils {
|
|||
return parseExtensionElement(flowElement, TRIGGER_PARAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给节点添加节点类型
|
||||
*
|
||||
* @param nodeType 节点类型
|
||||
* @param flowElement 节点
|
||||
*/
|
||||
public static void addNodeType(Integer nodeType, FlowElement flowElement) {
|
||||
addExtensionElement(flowElement, BpmnModelConstants.NODE_TYPE, nodeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析节点类型
|
||||
*
|
||||
* @param flowElement 节点
|
||||
* @return 节点类型
|
||||
*/
|
||||
public static Integer parseNodeType(FlowElement flowElement) {
|
||||
return NumberUtils.parseInt(parseExtensionElement(flowElement, BpmnModelConstants.NODE_TYPE));
|
||||
}
|
||||
|
||||
// ========== BPM 简单查找相关的方法 ==========
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@ public class SimpleModelUtils {
|
|||
|
||||
static {
|
||||
List<NodeConvert> converts = asList(new StartNodeConvert(), new EndNodeConvert(),
|
||||
new StartUserNodeConvert(), new ApproveNodeConvert(), new CopyNodeConvert(),
|
||||
new StartUserNodeConvert(), new ApproveNodeConvert(), new CopyNodeConvert(), new TransactorNodeConvert(),
|
||||
new DelayTimerNodeConvert(), new TriggerNodeConvert(),
|
||||
new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert(), new RouteBranchNodeConvert());
|
||||
converts.forEach(convert -> NODE_CONVERTS.put(convert.getType(), convert));
|
||||
|
@ -445,6 +445,8 @@ public class SimpleModelUtils {
|
|||
addSignEnable(node.getSignEnable(), userTask);
|
||||
// 审批意见
|
||||
addReasonRequire(node.getReasonRequire(), userTask);
|
||||
// 节点类型
|
||||
addNodeType(node.getType(), userTask);
|
||||
return userTask;
|
||||
}
|
||||
|
||||
|
@ -514,6 +516,15 @@ public class SimpleModelUtils {
|
|||
|
||||
}
|
||||
|
||||
private static class TransactorNodeConvert extends ApproveNodeConvert {
|
||||
|
||||
@Override
|
||||
public BpmSimpleModelNodeTypeEnum getType() {
|
||||
return BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class CopyNodeConvert implements NodeConvert {
|
||||
|
||||
@Override
|
||||
|
@ -785,10 +796,11 @@ public class SimpleModelUtils {
|
|||
BpmSimpleModelNodeTypeEnum nodeType = BpmSimpleModelNodeTypeEnum.valueOf(currentNode.getType());
|
||||
Assert.notNull(nodeType, "模型节点类型不支持");
|
||||
|
||||
// 情况:START_NODE/START_USER_NODE/APPROVE_NODE/COPY_NODE/END_NODE
|
||||
// 情况:START_NODE/START_USER_NODE/APPROVE_NODE/COPY_NODE/END_NODE/TRANSACTOR_NODE
|
||||
if (nodeType == BpmSimpleModelNodeTypeEnum.START_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.START_USER_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.APPROVE_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
|
||||
// 添加元素
|
||||
|
|
|
@ -28,8 +28,7 @@ import java.util.*;
|
|||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.addIfNotNull;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
|
@ -156,16 +155,25 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
|||
|
||||
@Override
|
||||
public void updateProcessDefinitionState(String id, Integer state) {
|
||||
ProcessDefinition processDefinition = repositoryService.getProcessDefinition(id);
|
||||
if (processDefinition == null) {
|
||||
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 激活
|
||||
if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
|
||||
repositoryService.activateProcessDefinitionById(id, false, null);
|
||||
if (processDefinition.isSuspended()) {
|
||||
repositoryService.activateProcessDefinitionById(id, false, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 挂起
|
||||
if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
|
||||
// suspendProcessInstances = false,进行中的任务,不进行挂起。
|
||||
// 原因:只要新的流程不允许发起即可,老流程继续可以执行。
|
||||
repositoryService.suspendProcessDefinitionById(id, false, null);
|
||||
if (!processDefinition.isSuspended()) {
|
||||
repositoryService.suspendProcessDefinitionById(id, false, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
|
||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil;
|
|||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
@ -67,6 +68,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
|||
import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseNodeType;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
|
||||
|
@ -325,7 +327,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName())
|
||||
.setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey())
|
||||
? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
|
||||
: BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
|
||||
: ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
|
||||
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
|
||||
.setStatus(FlowableUtils.getTaskStatus(task))
|
||||
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
|
||||
.setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
|
||||
|
@ -402,7 +405,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同
|
||||
ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId())
|
||||
.setName(firstActivity.getActivityName())
|
||||
.setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
|
||||
.setNodeType(ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
|
||||
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
|
||||
.setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
|
||||
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
|
||||
.setStartTime(DateUtils.of(CollUtil.getFirst(taskActivities).getStartTime()))
|
||||
|
@ -479,7 +483,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
// 1. 开始节点/审批节点
|
||||
if (ObjectUtils.equalsAny(node.getType(),
|
||||
BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType(),
|
||||
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) {
|
||||
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType(),
|
||||
BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE.getType())) {
|
||||
List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
|
||||
startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
|
||||
activityNode.setCandidateUserIds(candidateUserIds);
|
||||
|
|
|
@ -61,6 +61,7 @@ import java.util.stream.Stream;
|
|||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*;
|
||||
|
||||
|
@ -162,6 +163,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
bpmnModel, todoTask.getTaskDefinitionKey());
|
||||
Boolean signEnable = parseSignEnable(bpmnModel, todoTask.getTaskDefinitionKey());
|
||||
Boolean reasonRequire = parseReasonRequire(bpmnModel, todoTask.getTaskDefinitionKey());
|
||||
Integer nodeType = parseNodeType(BpmnModelUtils.getFlowElementById(bpmnModel, todoTask.getTaskDefinitionKey()));
|
||||
|
||||
// 4. 任务表单
|
||||
BpmFormDO taskForm = null;
|
||||
|
@ -170,8 +172,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
}
|
||||
|
||||
return BpmTaskConvert.INSTANCE.buildTodoTask(todoTask, childrenTasks, buttonsSetting, taskForm)
|
||||
.setSignEnable(signEnable)
|
||||
.setReasonRequire(reasonRequire);
|
||||
.setNodeType(nodeType).setSignEnable(signEnable).setReasonRequire(reasonRequire);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,6 +195,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
return PageResult.empty();
|
||||
}
|
||||
List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
|
||||
|
||||
// 特殊:强制移除自动完成的“发起人”节点
|
||||
// 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤
|
||||
tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID));
|
||||
return new PageResult<>(tasks, count);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue