) sessionManager.getSessionList(userType);
}
if (CollUtil.isEmpty(sessions)) {
- log.info("[send][sessionId({}) userType({}) userId({}) messageType({}) messageContent({}) 未匹配到会话]",
- sessionId, userType, userId, messageType, messageContent);
+ if (log.isDebugEnabled()) {
+ log.debug("[send][sessionId({}) userType({}) userId({}) messageType({}) messageContent({}) 未匹配到会话]",
+ sessionId, userType, userId, messageType, messageContent);
+ }
}
// 2. 执行发送
doSend(sessions, messageType, messageContent);
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java
index 7abb3e1dbc..c00638694a 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java
@@ -7,7 +7,4 @@ package cn.iocoder.yudao.module.bpm.enums;
*/
public interface DictTypeConstants {
- String TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型
- String TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本
-
}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
index ec167719cc..6c7a7ce92e 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -23,6 +23,7 @@ public interface ErrorCodeConstants {
"原因:用户任务({})未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置");
ErrorCode MODEL_DEPLOY_FAIL_BPMN_START_EVENT_NOT_EXISTS = new ErrorCode(1_009_002_005, "部署流程失败,原因:BPMN 流程图中,没有开始事件");
ErrorCode MODEL_DEPLOY_FAIL_BPMN_USER_TASK_NAME_NOT_EXISTS = new ErrorCode(1_009_002_006, "部署流程失败,原因:BPMN 流程图中,用户任务({})的名字不存在");
+ ErrorCode MODEL_UPDATE_FAIL_NOT_MANAGER = new ErrorCode(1_009_002_007, "操作流程失败,原因:你不是该流程({})的管理员");
// ========== 流程定义 1-009-003-000 ==========
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1_009_003_000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
@@ -34,15 +35,16 @@ public interface ErrorCodeConstants {
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1_009_004_000, "流程实例不存在");
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1_009_004_001, "流程取消失败,流程不处于运行中");
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1_009_004_002, "流程取消失败,该流程不是你发起的");
- ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_003, "审批任务({})的审批人未配置");
- ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "审批任务({})的审批人({})不存在");
+ ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_003, "任务({})的候选人未配置");
+ ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在");
+ ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
// ========== 流程任务 1-009-005-000 ==========
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1_009_005_002, "流程任务不存在");
ErrorCode TASK_IS_PENDING = new ErrorCode(1_009_005_003, "当前任务处于挂起状态,不能操作");
ErrorCode TASK_TARGET_NODE_NOT_EXISTS = new ErrorCode(1_009_005_004, " 目标节点不存在");
- ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
+ ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "退回任务失败,目标节点是在并行网关上或非同一路线上,不可跳转");
ErrorCode TASK_DELEGATE_FAIL_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人");
ErrorCode TASK_DELEGATE_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在");
ErrorCode TASK_SIGN_CREATE_USER_NOT_EXIST = new ErrorCode(1_009_005_009, "任务加签:选择的用户不存在");
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventType.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventType.java
new file mode 100644
index 0000000000..537e03e03c
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventType.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * BPM 边界事件 (boundary event) 自定义类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmBoundaryEventType {
+
+ USER_TASK_TIMEOUT(1,"用户任务超时");
+
+ private final Integer type;
+ private final String name;
+
+ public static BpmBoundaryEventType typeOf(Integer type) {
+ return ArrayUtil.firstMatch(eventType -> eventType.getType().equals(type), values());
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmFieldPermissionEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmFieldPermissionEnum.java
new file mode 100644
index 0000000000..5a9b4b26af
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmFieldPermissionEnum.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * BPM 表单权限的枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmFieldPermissionEnum {
+
+ READ(1, "只读"),
+ WRITE(2, "可编辑"),
+ NONE(3, "隐藏");
+
+ /**
+ * 权限
+ */
+ private final Integer permission;
+ /**
+ * 名字
+ */
+ private final String name;
+
+ public static BpmFieldPermissionEnum valueOf(Integer permission) {
+ return ArrayUtil.firstMatch(item -> item.getPermission().equals(permission), values());
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelTypeEnum.java
new file mode 100644
index 0000000000..9863a44e87
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelTypeEnum.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 模型的类型的枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmModelTypeEnum implements IntArrayValuable {
+
+ BPMN(10, "BPMN 设计器"), // https://bpmn.io/toolkit/bpmn-js/
+ SIMPLE(20, "SIMPLE 设计器"); // 参考钉钉、飞书工作流的设计器
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmModelTypeEnum::getType).toArray();
+
+ private final Integer type;
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java
new file mode 100644
index 0000000000..234ec7e47b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionType.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 仿钉钉的流程器设计器条件节点的条件类型
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmSimpleModeConditionType implements IntArrayValuable {
+
+ EXPRESSION(1, "条件表达式"),
+ RULE(2, "条件规则");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModeConditionType::getType).toArray();
+
+ private final Integer type;
+
+ private final String name;
+
+ public static BpmSimpleModeConditionType valueOf(Integer type) {
+ return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values());
+ }
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
new file mode 100644
index 0000000000..4a2e1d50f8
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * 仿钉钉的流程器设计器的模型节点类型
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmSimpleModelNodeType implements IntArrayValuable {
+
+ // 0 ~ 1 开始和结束
+ START_NODE(0, "开始", "startEvent"),
+ END_NODE(1, "结束", "endEvent"),
+
+ // 10 ~ 49 各种节点
+ START_USER_NODE(10, "发起人", "userTask"), // 发起人节点。前端的开始节点,Id 固定
+ APPROVE_NODE(11, "审批人", "userTask"),
+ COPY_NODE(12, "抄送人", "serviceTask"),
+
+ // 50 ~ 条件分支
+ CONDITION_NODE(50, "条件", "sequenceFlow"), // 用于构建流转条件的表达式
+ CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"),
+ PARALLEL_BRANCH_NODE(52, "并行分支", "parallelGateway"),
+ INCLUSIVE_BRANCH_NODE(53, "包容分支", "inclusiveGateway"),
+ ;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
+
+ private final Integer type;
+ private final String name;
+ private final String bpmnType;
+
+ /**
+ * 判断是否为分支节点
+ *
+ * @param type 节点类型
+ */
+ public static boolean isBranchNode(Integer type) {
+ return Objects.equals(CONDITION_BRANCH_NODE.getType(), type)
+ || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type)
+ || Objects.equals(INCLUSIVE_BRANCH_NODE.getType(), type);
+ }
+
+ public static BpmSimpleModelNodeType valueOf(Integer type) {
+ return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values());
+ }
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
new file mode 100644
index 0000000000..1089f181d3
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 多人审批方式的枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskApproveMethodEnum implements IntArrayValuable {
+
+ RANDOM(1, "随机挑选一人审批", null),
+ RATIO(2, "多人会签(按通过比例)", "${ nrOfCompletedInstances/nrOfInstances >= %s}"), // 会签(按通过比例)
+ ANY(3, "多人或签(一人通过或拒绝)", "${ nrOfCompletedInstances > 0 }"), // 或签(通过只需一人,拒绝只需一人)
+ SEQUENTIAL(4, "依次审批", "${ nrOfCompletedInstances >= nrOfInstances }"); // 依次审批
+
+ /**
+ * 审批方式
+ */
+ private final Integer method;
+ /**
+ * 名字
+ */
+ private final String name;
+ /**
+ * 完成表达式
+ */
+ private final String completionCondition;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskApproveMethodEnum::getMethod).toArray();
+
+ public static BpmUserTaskApproveMethodEnum valueOf(Integer method) {
+ return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values());
+ }
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java
new file mode 100644
index 0000000000..fa6dba665a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 用户任务的审批类型枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskApproveTypeEnum implements IntArrayValuable {
+
+ USER(1), // 人工审批
+ AUTO_APPROVE(2), // 自动通过
+ AUTO_REJECT(3); // 自动拒绝
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskApproveTypeEnum::getType).toArray();
+
+ private final Integer type;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
new file mode 100644
index 0000000000..7a7242a494
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务的审批人为空时,处理类型枚举
+ *
+ * @author 芋道源码
+ */
+@RequiredArgsConstructor
+@Getter
+public enum BpmUserTaskAssignEmptyHandlerTypeEnum implements IntArrayValuable {
+
+ APPROVE(1), // 自动通过
+ REJECT(2), // 自动拒绝
+ ASSIGN_USER(3), // 指定人员审批
+ ASSIGN_ADMIN(4), // 转交给流程管理员
+ ;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskAssignEmptyHandlerTypeEnum::getType).toArray();
+
+ private final Integer type;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
new file mode 100644
index 0000000000..5012815027
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务的审批人与发起人相同时,处理类型枚举
+ *
+ * @author 芋道源码
+ */
+@RequiredArgsConstructor
+@Getter
+public enum BpmUserTaskAssignStartUserHandlerTypeEnum implements IntArrayValuable {
+
+ START_USER_AUDIT(1), // 由发起人对自己审批
+ SKIP(2), // 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过
+ TRANSFER_DEPT_LEADER(3); // 转交给部门负责人审批【参考飞书】:若部门负责人为空,则自动通过
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskAssignStartUserHandlerTypeEnum::getType).toArray();
+
+ private final Integer type;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerType.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerType.java
new file mode 100644
index 0000000000..f2d48f7d9a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerType.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务拒绝处理类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskRejectHandlerType implements IntArrayValuable {
+
+ FINISH_PROCESS_INSTANCE(1, "终止流程"),
+ RETURN_USER_TASK(2, "驳回到指定任务节点");
+
+ private final Integer type;
+ private final String name;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskRejectHandlerType::getType).toArray();
+
+ public static BpmUserTaskRejectHandlerType typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java
new file mode 100644
index 0000000000..0d56c9b379
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.bpm.enums.definition;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 用户任务超时处理类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskTimeoutHandlerTypeEnum implements IntArrayValuable {
+
+ REMINDER(1,"自动提醒"),
+ APPROVE(2, "自动同意"),
+ REJECT(3, "自动拒绝");
+
+ private final Integer type;
+ private final String name;
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskTimeoutHandlerTypeEnum::getType).toArray();
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java
index 79001fccd3..abec70276e 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java
@@ -14,7 +14,8 @@ public enum BpmMessageEnum {
PROCESS_INSTANCE_APPROVE("bpm_process_instance_approve"), // 流程任务被审批通过时,发送给申请人
PROCESS_INSTANCE_REJECT("bpm_process_instance_reject"), // 流程任务被审批不通过时,发送给申请人
- TASK_ASSIGNED("bpm_task_assigned"); // 任务被分配时,发送给审批人
+ TASK_ASSIGNED("bpm_task_assigned"), // 任务被分配时,发送给审批人
+ TASK_TIMEOUT("bpm_task_timeout"); // 任务审批超时时,发送给审批人
/**
* 短信模板的标识
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
index 82a4119b57..29cc1280e2 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.enums.task;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -15,6 +16,7 @@ import java.util.Arrays;
@AllArgsConstructor
public enum BpmProcessInstanceStatusEnum implements IntArrayValuable {
+ NOT_START(-1, "未开始"),
RUNNING(1, "审批中"),
APPROVE(2, "审批通过"),
REJECT(3, "审批不通过"),
@@ -33,7 +35,16 @@ public enum BpmProcessInstanceStatusEnum implements IntArrayValuable {
@Override
public int[] array() {
- return new int[0];
+ return ARRAYS;
+ }
+
+ public static boolean isRejectStatus(Integer status) {
+ return REJECT.getStatus().equals(status);
+ }
+
+ public static boolean isProcessEndStatus(Integer status) {
+ return ObjectUtils.equalsAny(status,
+ APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
}
}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
new file mode 100644
index 0000000000..5ea8c41871
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.bpm.enums.task;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 流程实例/任务的的处理原因枚举
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmReasonEnum {
+
+ // ========== 流程实例的独有原因 ==========
+
+ REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法
+ CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程
+ CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程
+
+ // ========== 流程任务的独有原因 ==========
+
+ CANCEL_BY_SYSTEM("系统自动取消"), // 场景:非常多,比如说:1)多任务审批已经满足条件,无需审批该任务;2)流程实例被取消,无需审批该任务;等等
+ TIMEOUT_APPROVE("审批超时,系统自动通过"),
+ TIMEOUT_REJECT("审批超时,系统自动不通过"),
+ ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"),
+ ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"),
+ ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND("审批人与提交人为同一人时,找不到部门负责人,自动通过"),
+ ASSIGN_START_USER_TRANSFER_DEPT_LEADER("审批人与提交人为同一人时,转交给部门负责人审批"),
+ ASSIGN_EMPTY_APPROVE("审批人为空,自动通过"),
+ ASSIGN_EMPTY_REJECT("审批人为空,自动不通过"),
+ APPROVE_TYPE_AUTO_APPROVE("非人工审核,自动通过"),
+ APPROVE_TYPE_AUTO_REJECT("非人工审核,自动不通过"),
+ ;
+
+ private final String reason;
+
+ /**
+ * 格式化理由
+ *
+ * @param args 参数
+ * @return 理由
+ */
+ public String format(Object... args) {
+ return StrUtil.format(reason, args);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
index 40a385a582..a19f122bd8 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
+++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.enums.task;
+import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -13,13 +14,13 @@ import lombok.Getter;
@AllArgsConstructor
public enum BpmTaskStatusEnum {
+ NOT_START(-1, "未开始"),
RUNNING(1, "审批中"),
APPROVE(2, "审批通过"),
REJECT(3, "审批不通过"),
CANCEL(4, "已取消"),
RETURN(5, "已退回"),
- DELEGATE(6, "委派中"),
/**
* 使用场景:
@@ -44,6 +45,10 @@ public enum BpmTaskStatusEnum {
*/
private final String name;
+ public static boolean isRejectStatus(Integer status) {
+ return REJECT.getStatus().equals(status);
+ }
+
/**
* 判断该状态是否已经处于 End 最终状态
*
@@ -58,4 +63,8 @@ public enum BpmTaskStatusEnum {
RETURN.getStatus(), APPROVING.getStatus());
}
+ public static boolean isCancelStatus(Integer status) {
+ return ObjUtil.equal(status, CANCEL.getStatus());
+ }
+
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/package-info.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/package-info.java
new file mode 100644
index 0000000000..41ce65081f
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 基础包,放一些通用的 VO 类
+ */
+package cn.iocoder.yudao.module.bpm.controller.admin.base;
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java
new file mode 100644
index 0000000000..b2fb016231
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.base.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "用户精简信息 VO")
+@Data
+public class UserSimpleBaseVO {
+
+ @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long id;
+ @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+ private String nickname;
+ @Schema(description = "用户头像", example = "https://www.iocoder.cn/1.png")
+ private String avatar;
+
+ @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long deptId;
+ @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
+ private String deptName;
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java
index a787905541..43cafaf7fc 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java
@@ -48,6 +48,15 @@ public class BpmCategoryController {
return success(true);
}
+ @PutMapping("/update-sort-batch")
+ @Operation(summary = "批量更新流程分类的排序")
+ @Parameter(name = "ids", description = "分类编号列表", required = true, example = "1,2,3")
+ @PreAuthorize("@ss.hasPermission('bpm:category:update')")
+ public CommonResult updateCategorySortBatch(@RequestParam("ids") List ids) {
+ categoryService.updateCategorySortBatch(ids);
+ return success(true);
+ }
+
@DeleteMapping("/delete")
@Operation(summary = "删除流程分类")
@Parameter(name = "id", description = "编号", required = true)
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
index 4095450233..42eab67d53 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
@@ -2,12 +2,9 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.common.util.io.IoUtils;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelUpdateReqVO;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
@@ -15,7 +12,8 @@ import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -28,15 +26,15 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
-import java.io.IOException;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 流程模型")
@RestController
@@ -53,32 +51,42 @@ public class BpmModelController {
@Resource
private BpmProcessDefinitionService processDefinitionService;
- @GetMapping("/page")
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @GetMapping("/list")
@Operation(summary = "获得模型分页")
- public CommonResult> getModelPage(BpmModelPageReqVO pageVO) {
- PageResult pageResult = modelService.getModelPage(pageVO);
- if (CollUtil.isEmpty(pageResult.getList())) {
- return success(PageResult.empty(pageResult.getTotal()));
+ @Parameter(name = "name", description = "模型名称", example = "芋艿")
+ public CommonResult> getModelPage(@RequestParam(value = "name", required = false) String name) {
+ List list = modelService.getModelList(name);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
}
- // 拼接数据
// 获得 Form 表单
- Set formIds = convertSet(pageResult.getList(), model -> {
- BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+ Set formIds = convertSet(list, model -> {
+ BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model);
return metaInfo != null ? metaInfo.getFormId() : null;
});
Map formMap = formService.getFormMap(formIds);
// 获得 Category Map
Map categoryMap = categoryService.getCategoryMap(
- convertSet(pageResult.getList(), Model::getCategory));
+ convertSet(list, Model::getCategory));
// 获得 Deployment Map
- Set deploymentIds = new HashSet<>();
- pageResult.getList().forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId()));
- Map deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds);
+ Map deploymentMap = processDefinitionService.getDeploymentMap(
+ convertSet(list, Model::getDeploymentId));
// 获得 ProcessDefinition Map
- List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds);
+ List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(
+ deploymentMap.keySet());
Map processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId);
- return success(BpmModelConvert.INSTANCE.buildModelPage(pageResult, formMap, categoryMap, deploymentMap, processDefinitionMap));
+ // 获得 User Map
+ Set userIds = convertSetByFlatMap(list, model -> {
+ BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model);
+ return metaInfo != null ? metaInfo.getStartUserIds().stream() : Stream.empty();
+ });
+ Map userMap = adminUserApi.getUserMap(userIds);
+ return success(BpmModelConvert.INSTANCE.buildModelList(list,
+ formMap, categoryMap, deploymentMap, processDefinitionMap, userMap));
}
@GetMapping("/get")
@@ -97,26 +105,25 @@ public class BpmModelController {
@PostMapping("/create")
@Operation(summary = "新建模型")
@PreAuthorize("@ss.hasPermission('bpm:model:create')")
- public CommonResult createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) {
- return success(modelService.createModel(createRetVO, null));
+ public CommonResult createModel(@Valid @RequestBody BpmModelSaveReqVO createRetVO) {
+ return success(modelService.createModel(createRetVO));
}
+
@PutMapping("/update")
@Operation(summary = "修改模型")
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
- public CommonResult updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) {
- modelService.updateModel(modelVO);
+ public CommonResult updateModel(@Valid @RequestBody BpmModelSaveReqVO modelVO) {
+ modelService.updateModel(getLoginUserId(), modelVO);
return success(true);
}
- @PostMapping("/import")
- @Operation(summary = "导入模型")
- @PreAuthorize("@ss.hasPermission('bpm:model:import')")
- public CommonResult importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException {
- BpmModelCreateReqVO createReqVO = BeanUtils.toBean(importReqVO, BpmModelCreateReqVO.class);
- // 读取文件
- String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
- return success(modelService.createModel(createReqVO, bpmnXml));
+ @PutMapping("/update-sort-batch")
+ @Operation(summary = "批量修改模型排序")
+ @Parameter(name = "ids", description = "编号数组", required = true, example = "1,2,3")
+ public CommonResult updateModelSortBatch(@RequestParam("ids") List ids) {
+ modelService.updateModelSortBatch(getLoginUserId(), ids);
+ return success(true);
}
@PostMapping("/deploy")
@@ -124,7 +131,7 @@ public class BpmModelController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
public CommonResult deployModel(@RequestParam("id") String id) {
- modelService.deployModel(id);
+ modelService.deployModel(getLoginUserId(), id);
return success(true);
}
@@ -132,7 +139,15 @@ public class BpmModelController {
@Operation(summary = "修改模型的状态", description = "实际更新的部署的流程定义的状态")
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
public CommonResult updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
- modelService.updateModelState(reqVO.getId(), reqVO.getState());
+ modelService.updateModelState(getLoginUserId(), reqVO.getId(), reqVO.getState());
+ return success(true);
+ }
+
+ @PutMapping("/update-bpmn")
+ @Operation(summary = "修改模型的 BPMN")
+ @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+ public CommonResult updateModelBpmn(@Valid @RequestBody BpmModeUpdateBpmnReqVO reqVO) {
+ modelService.updateModelBpmnXml(reqVO.getId(), reqVO.getBpmnXml());
return success(true);
}
@@ -141,8 +156,25 @@ public class BpmModelController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('bpm:model:delete')")
public CommonResult deleteModel(@RequestParam("id") String id) {
- modelService.deleteModel(id);
+ modelService.deleteModel(getLoginUserId(), id);
return success(true);
}
+ // ========== 仿钉钉/飞书的精简模型 =========
+
+ @GetMapping("/simple/get")
+ @Operation(summary = "获得仿钉钉流程设计模型")
+ @Parameter(name = "modelId", description = "流程模型编号", required = true, example = "a2c5eee0-eb6c-11ee-abf4-0c37967c420a")
+ public CommonResult getSimpleModel(@RequestParam("id") String modelId){
+ return success(modelService.getSimpleModel(modelId));
+ }
+
+ @PostMapping("/simple/update")
+ @Operation(summary = "保存仿钉钉流程设计模型")
+ @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+ public CommonResult updateSimpleModel(@Valid @RequestBody BpmSimpleModelUpdateReqVO reqVO) {
+ modelService.updateSimpleModel(getLoginUserId(), reqVO);
+ return success(Boolean.TRUE);
+ }
+
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
index ee23c63e8f..0dc55eb0a5 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConver
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.BpmTaskCandidateStartUserSelectStrategy;
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
@@ -17,7 +16,6 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.flowable.bpmn.model.BpmnModel;
-import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -34,6 +32,7 @@ import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 流程定义")
@RestController
@@ -77,17 +76,25 @@ public class BpmProcessDefinitionController {
@GetMapping ("/list")
@Operation(summary = "获得流程定义列表")
@Parameter(name = "suspensionState", description = "挂起状态", required = true, example = "1") // 参见 Flowable SuspensionState 枚举
- @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
public CommonResult> getProcessDefinitionList(
@RequestParam("suspensionState") Integer suspensionState) {
+ // 1.1 获得开启的流程定义
List list = processDefinitionService.getProcessDefinitionListBySuspensionState(suspensionState);
if (CollUtil.isEmpty(list)) {
return success(Collections.emptyList());
}
-
- // 获得 BpmProcessDefinitionInfoDO Map
+ // 1.2 移除不可见的流程定义
Map processDefinitionMap = processDefinitionService.getProcessDefinitionInfoMap(
convertSet(list, ProcessDefinition::getId));
+ Long userId = getLoginUserId();
+ list.removeIf(processDefinition -> {
+ BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionMap.get(processDefinition.getId());
+ return processDefinitionInfo == null // 不存在
+ || Boolean.FALSE.equals(processDefinitionInfo.getVisible()) // visible 不可见
+ || !processDefinitionService.canUserStartProcessDefinition(processDefinitionInfo, userId); // 无权限发起
+ });
+
+ // 2. 拼接 VO 返回
return success(BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinitionList(
list, null, processDefinitionMap, null, null));
}
@@ -96,7 +103,6 @@ public class BpmProcessDefinitionController {
@Operation(summary = "获得流程定义")
@Parameter(name = "id", description = "流程编号", required = true, example = "1024")
@Parameter(name = "key", description = "流程定义标识", required = true, example = "1024")
- @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
public CommonResult getProcessDefinition(
@RequestParam(value = "id", required = false) String id,
@RequestParam(value = "key", required = false) String key) {
@@ -105,10 +111,10 @@ public class BpmProcessDefinitionController {
if (processDefinition == null) {
return success(null);
}
+ BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(processDefinition.getId());
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
- List userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
return success(BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinition(
- processDefinition, null, null, null, null, bpmnModel, userTaskList));
+ processDefinition, null, processDefinitionInfo, null, null, bpmnModel));
}
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java
new file mode 100644
index 0000000000..053583d4f0
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+
+@Schema(description = "管理后台 - 流程模型的更新 BPMN XML Request VO")
+@Data
+public class BpmModeUpdateBpmnReqVO {
+
+ @Schema(description = "流程编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotEmpty(message = "流程编号不能为空")
+ private String id;
+
+ @Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "BPMN XML 不能为空")
+ private String bpmnXml;
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
new file mode 100644
index 0000000000..4f5e75a8e5
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.hibernate.validator.constraints.URL;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * BPM 流程 MetaInfo Response DTO
+ * 主要用于 { Model#setMetaInfo(String)} 的存储
+ *
+ * 最终,它的字段和
+ * {@link cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO}
+ * 是一致的
+ *
+ * @author 芋道源码
+ */
+@Data
+public class BpmModelMetaInfoVO {
+
+ @Schema(description = "流程图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg")
+ @NotEmpty(message = "流程图标不能为空")
+ @URL(message = "流程图标格式不正确")
+ private String icon;
+
+ @Schema(description = "流程描述", example = "我是描述")
+ private String description;
+
+ @Schema(description = "流程类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+ @InEnum(BpmModelTypeEnum.class)
+ @NotNull(message = "流程类型不能为空")
+ private Integer type;
+
+ @Schema(description = "表单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
+ @InEnum(BpmModelFormTypeEnum.class)
+ @NotNull(message = "表单类型不能为空")
+ private Integer formType;
+ @Schema(description = "表单编号", example = "1024")
+ private Long formId; // formType 为 NORMAL 使用,必须非空
+ @Schema(description = "自定义表单的提交路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/create")
+ private String formCustomCreatePath; // 表单类型为 CUSTOM 时,必须非空
+ @Schema(description = "自定义表单的查看路径,使用 Vue 的路由地址", example = "/bpm/oa/leave/view")
+ private String formCustomViewPath; // 表单类型为 CUSTOM 时,必须非空
+
+ @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+ @NotNull(message = "是否可见不能为空")
+ private Boolean visible;
+
+ @Schema(description = "可发起用户编号数组", example = "[1,2,3]")
+ private List startUserIds;
+
+ @Schema(description = "可管理用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2,4,6]")
+ @NotEmpty(message = "可管理用户编号数组不能为空")
+ private List managerUserIds;
+
+ @Schema(description = "排序", example = "1")
+ private Long sort; // 创建时,后端自动生成
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
index aad2015c7e..c828b64638 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
@@ -1,14 +1,16 @@
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
+import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
+import java.util.List;
@Schema(description = "管理后台 - 流程模型 Response VO")
@Data
-public class BpmModelRespVO {
+public class BpmModelRespVO extends BpmModelMetaInfoVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String id;
@@ -22,33 +24,23 @@ public class BpmModelRespVO {
@Schema(description = "流程图标", example = "https://www.iocoder.cn/yudao.jpg")
private String icon;
- @Schema(description = "流程描述", example = "我是描述")
- private String description;
-
@Schema(description = "流程分类编码", example = "1")
private String category;
@Schema(description = "流程分类名字", example = "请假")
private String categoryName;
- @Schema(description = "表单类型-参见 bpm_model_form_type 数据字典", example = "1")
- private Integer formType;
-
- @Schema(description = "表单编号", example = "1024")
- private Long formId; // 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空
@Schema(description = "表单名字", example = "请假表单")
private String formName;
- @Schema(description = "自定义表单的提交路径", example = "/bpm/oa/leave/create")
- private String formCustomCreatePath; // 使用 Vue 的路由地址-在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空
- @Schema(description = "自定义表单的查看路径", example = "/bpm/oa/leave/view")
- private String formCustomViewPath; // ,使用 Vue 的路由地址-在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM} 时,必须非空
-
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED)
private String bpmnXml;
+ @Schema(description = "可发起的用户数组")
+ private List startUsers;
+
/**
* 最新部署的流程定义
*/
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java
new file mode 100644
index 0000000000..6f91f158f2
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+
+@Schema(description = "管理后台 - 流程模型的保存 Request VO")
+@Data
+public class BpmModelSaveReqVO extends BpmModelMetaInfoVO {
+
+ @Schema(description = "编号", example = "1024")
+ private String id;
+
+ @Schema(description = "流程标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "process_yudao")
+ @NotEmpty(message = "流程标识不能为空")
+ private String key;
+
+ @Schema(description = "流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ @NotEmpty(message = "流程名称不能为空")
+ private String name;
+
+ @Schema(description = "流程分类", example = "1")
+ private String category;
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
new file mode 100644
index 0000000000..b94fa9622f
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
@@ -0,0 +1,212 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.bpm.enums.definition.*;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+import java.util.Map;
+
+@Schema(description = "管理后台 - 仿钉钉流程设计模型节点 VO")
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class BpmSimpleModelNodeVO {
+
+ @Schema(description = "模型节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "StartEvent_1")
+ @NotEmpty(message = "模型节点编号不能为空")
+ private String id;
+
+ @Schema(description = "模型节点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "模型节点类型不能为空")
+ @InEnum(BpmSimpleModelNodeType.class)
+ private Integer type;
+
+ @Schema(description = "模型节点名称", example = "领导审批")
+ private String name;
+
+ @Schema(description = "节点展示内容", example = "指定成员: 芋道源码")
+ private String showText;
+
+ @Schema(description = "子节点")
+ private BpmSimpleModelNodeVO childNode; // 补充说明:在该模型下,子节点有且仅有一个,不会有多个
+
+ @Schema(description = "条件节点")
+ private List conditionNodes; // 补充说明:有且仅有条件、并行、包容等分支会使用
+
+ @Schema(description = "条件类型", example = "1")
+ @InEnum(BpmSimpleModeConditionType.class)
+ private Integer conditionType; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
+
+ @Schema(description = "条件表达式", example = "${day>3}")
+ private String conditionExpression; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
+
+ @Schema(description = "是否默认条件", example = "true")
+ private Boolean defaultFlow; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
+ /**
+ * 条件组
+ */
+ private ConditionGroups conditionGroups; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
+
+ @Schema(description = "候选人策略", example = "30")
+ @InEnum(BpmTaskCandidateStrategyEnum.class)
+ private Integer candidateStrategy; // 用于审批,抄送节点
+
+ @Schema(description = "候选人参数")
+ private String candidateParam; // 用于审批,抄送节点
+
+ @Schema(description = "审批节点类型", example = "1")
+ @InEnum(BpmUserTaskApproveTypeEnum.class)
+ private Integer approveType; // 用于审批节点
+
+ @Schema(description = "多人审批方式", example = "1")
+ @InEnum(BpmUserTaskApproveMethodEnum.class)
+ private Integer approveMethod; // 用于审批节点
+
+ @Schema(description = "通过比例", example = "100")
+ private Integer approveRatio; // 通过比例,当多人审批方式为:多人会签(按通过比例) 需要设置
+
+ @Schema(description = "表单权限", example = "[]")
+ private List