> summary;
+
+ @Schema(description = "发起人的用户信息")
+ private UserSimpleDTO startUser;
+ }
+
+ @Data
+ @Schema(description = "操作按钮设置")
+ public static class OperationButtonSettingDTO {
+
+ @Schema(description = "显示名称", example = "审批")
+ private String displayName;
+
+ @Schema(description = "是否启用", example = "true")
+ private Boolean enable;
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/UserSimpleDTO.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/UserSimpleDTO.java
new file mode 100644
index 0000000..ddb00d6
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/api/task/dto/UserSimpleDTO.java
@@ -0,0 +1,25 @@
+package com.zt.plat.module.bpm.api.task.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "RPC 服务 - 用户精简信息 DTO")
+@Data
+public class UserSimpleDTO {
+
+ @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/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ApiConstants.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ApiConstants.java
new file mode 100644
index 0000000..3c4bac9
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ApiConstants.java
@@ -0,0 +1,23 @@
+package com.zt.plat.module.bpm.enums;
+
+import com.zt.plat.framework.common.enums.RpcConstants;
+
+/**
+ * API 相关的枚举
+ *
+ * @author ZT
+ */
+public class ApiConstants {
+
+ /**
+ * 服务名
+ *
+ * 注意,需要保证和 spring.application.name 保持一致
+ */
+ public static final String NAME = "bpm-server";
+
+ public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/bpm";
+
+ public static final String VERSION = "1.0.0";
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/DictTypeConstants.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/DictTypeConstants.java
new file mode 100644
index 0000000..13dcf72
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/DictTypeConstants.java
@@ -0,0 +1,10 @@
+package com.zt.plat.module.bpm.enums;
+
+/**
+ * BPM 字典类型的枚举类
+ *
+ * @author ZT
+ */
+public interface DictTypeConstants {
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ErrorCodeConstants.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ErrorCodeConstants.java
new file mode 100644
index 0000000..b9db1ed
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/ErrorCodeConstants.java
@@ -0,0 +1,87 @@
+package com.zt.plat.module.bpm.enums;
+
+import com.zt.plat.framework.common.exception.ErrorCode;
+
+/**
+ * Bpm 错误码枚举类
+ *
+ * bpm 系统,使用 1-009-000-000 段
+ */
+public interface ErrorCodeConstants {
+
+ // ========== 通用流程处理 模块 1-009-000-000 ==========
+
+ // ========== OA 流程模块 1-009-001-000 ==========
+ ErrorCode OA_LEAVE_NOT_EXISTS = new ErrorCode(1_009_001_001, "请假申请不存在");
+
+ // ========== 流程模型 1-009-002-000 ==========
+ ErrorCode MODEL_KEY_EXISTS = new ErrorCode(1_009_002_000, "已经存在流程标识为【{}】的流程");
+ ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在");
+ ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
+ ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
+ ErrorCode MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
+ "原因:用户任务({})未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置");
+ 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, "操作流程失败,原因:你不是该流程({})的管理员");
+ ErrorCode MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR = new ErrorCode(1_009_002_008, "部署流程失败,原因:首个任务({})的审批人不能是【审批人自选】");
+
+ // ========== 流程定义 1-009-003-000 ==========
+ ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1_009_003_000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
+ ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1_009_003_001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
+ ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_009_003_002, "流程定义不存在");
+ ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1_009_003_003, "流程定义处于挂起状态");
+
+ // ========== 流程实例 1-009-004-000 ==========
+ 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_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
+ ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消");
+ ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败");
+ ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置");
+ ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消");
+
+ // ========== 流程任务 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_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, "任务加签:选择的用户不存在");
+ ErrorCode TASK_SIGN_CREATE_TYPE_ERROR = new ErrorCode(1_009_005_010, "任务加签:当前任务已经{},不能{}");
+ ErrorCode TASK_SIGN_CREATE_USER_REPEAT = new ErrorCode(1_009_005_011, "任务加签失败,加签人与现有审批人[{}]重复");
+ ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
+ ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
+ ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
+ ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
+ ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
+ ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");
+
+ // ========== 动态表单模块 1-009-010-000 ==========
+ ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
+ ErrorCode FORM_FIELD_REPEAT = new ErrorCode(1_009_010_001, "表单项({}) 和 ({}) 使用了相同的字段名({})");
+
+ // ========== 用户组模块 1-009-011-000 ==========
+ ErrorCode USER_GROUP_NOT_EXISTS = new ErrorCode(1_009_011_000, "用户分组不存在");
+ ErrorCode USER_GROUP_IS_DISABLE = new ErrorCode(1_009_011_001, "名字为【{}】的用户分组已被禁用");
+
+ // ========== 用户组模块 1-009-012-000 ==========
+ ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_009_012_000, "流程分类不存在");
+ ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(1_009_012_001, "流程分类名字【{}】重复");
+ ErrorCode CATEGORY_CODE_DUPLICATE = new ErrorCode(1_009_012_002, "流程分类编码【{}】重复");
+
+ // ========== BPM 流程监听器 1-009-013-000 ==========
+ ErrorCode PROCESS_LISTENER_NOT_EXISTS = new ErrorCode(1_009_013_000, "流程监听器不存在");
+ ErrorCode PROCESS_LISTENER_CLASS_NOT_FOUND = new ErrorCode(1_009_013_001, "流程监听器类({})不存在");
+ ErrorCode PROCESS_LISTENER_CLASS_IMPLEMENTS_ERROR = new ErrorCode(1_009_013_002, "流程监听器类({})没有实现接口({})");
+ ErrorCode PROCESS_LISTENER_EXPRESSION_INVALID = new ErrorCode(1_009_013_003, "流程监听器表达式({})不合法");
+
+ // ========== BPM 流程表达式 1-009-014-000 ==========
+ ErrorCode PROCESS_EXPRESSION_NOT_EXISTS = new ErrorCode(1_009_014_000, "流程表达式不存在");
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmAutoApproveTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmAutoApproveTypeEnum.java
new file mode 100644
index 0000000..2611d38
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmAutoApproveTypeEnum.java
@@ -0,0 +1,32 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 自动去重的类型的枚举
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmAutoApproveTypeEnum implements ArrayValuable {
+
+ NONE(0, "不自动通过"),
+ APPROVE_ALL(1, "仅审批一次,后续重复的审批节点均自动通过"),
+ APPROVE_SEQUENT(2, "仅针对连续审批的节点自动通过");
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmAutoApproveTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+ private final String name;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java
new file mode 100644
index 0000000..d168f66
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java
@@ -0,0 +1,27 @@
+package com.zt.plat.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 BpmBoundaryEventTypeEnum {
+
+ USER_TASK_TIMEOUT(1, "用户任务超时"),
+ DELAY_TIMER_TIMEOUT(2, "延迟器超时"),
+ CHILD_PROCESS_TIMEOUT(3, "子流程超时");
+
+ private final Integer type;
+ private final String name;
+
+ public static BpmBoundaryEventTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(eventType -> eventType.getType().equals(type), values());
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java
new file mode 100644
index 0000000..68574cb
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java
@@ -0,0 +1,37 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 子流程多实例来源类型枚举
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmChildProcessMultiInstanceSourceTypeEnum implements ArrayValuable {
+
+ FIXED_QUANTITY(1, "固定数量"),
+ NUMBER_FORM(2, "数字表单"),
+ MULTIPLE_FORM(3, "多选表单");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessMultiInstanceSourceTypeEnum::getType).toArray(Integer[]::new);
+
+ public static BpmChildProcessMultiInstanceSourceTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java
new file mode 100644
index 0000000..5b13462
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java
@@ -0,0 +1,36 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 当子流程发起人为空时类型枚举
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmChildProcessStartUserEmptyTypeEnum implements ArrayValuable {
+
+ MAIN_PROCESS_START_USER(1, "同主流程发起人"),
+ CHILD_PROCESS_ADMIN(2, "子流程管理员"),
+ MAIN_PROCESS_ADMIN(3, "主流程管理员");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserEmptyTypeEnum::getType).toArray(Integer[]::new);
+
+ public static BpmChildProcessStartUserEmptyTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java
new file mode 100644
index 0000000..8470a72
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java
@@ -0,0 +1,35 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 子流程发起人类型枚举
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmChildProcessStartUserTypeEnum implements ArrayValuable {
+
+ MAIN_PROCESS_START_USER(1, "同主流程发起人"),
+ FROM_FORM(2, "表单");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmChildProcessStartUserTypeEnum::getType).toArray(Integer[]::new);
+
+ public static BpmChildProcessStartUserTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmDelayTimerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmDelayTimerTypeEnum.java
new file mode 100644
index 0000000..aabaef0
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmDelayTimerTypeEnum.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 延迟器类型枚举
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmDelayTimerTypeEnum implements ArrayValuable {
+
+ FIXED_TIME_DURATION(1, "固定时长"),
+ FIXED_DATE_TIME(2, "固定日期");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmDelayTimerTypeEnum::getType).toArray(Integer[]::new);
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmFieldPermissionEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmFieldPermissionEnum.java
new file mode 100644
index 0000000..8571f90
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmFieldPermissionEnum.java
@@ -0,0 +1,33 @@
+package com.zt.plat.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/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmHttpRequestParamTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmHttpRequestParamTypeEnum.java
new file mode 100644
index 0000000..dd1fc50
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmHttpRequestParamTypeEnum.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM HTTP 请求参数设置类型。用于 Simple 设计器任务监听器和触发器配置。
+ *
+ * @author Lesan
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmHttpRequestParamTypeEnum implements ArrayValuable {
+
+ FIXED_VALUE(1, "固定值"),
+ FROM_FORM(2, "表单");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmHttpRequestParamTypeEnum::getType).toArray(Integer[]::new);
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelFormTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelFormTypeEnum.java
new file mode 100644
index 0000000..f28b1ed
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelFormTypeEnum.java
@@ -0,0 +1,32 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 模型的表单类型的枚举
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmModelFormTypeEnum implements ArrayValuable {
+
+ NORMAL(10, "流程表单"), // 对应 BpmFormDO
+ CUSTOM(20, "业务表单") // 业务自己定义的表单,自己进行数据的存储
+ ;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmModelFormTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+ private final String name;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelTypeEnum.java
new file mode 100644
index 0000000..259b365
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmModelTypeEnum.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 模型的类型的枚举
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmModelTypeEnum implements ArrayValuable {
+
+ BPMN(10, "BPMN 设计器"), // https://bpmn.io/toolkit/bpmn-js/
+ SIMPLE(20, "SIMPLE 设计器"); // 参考钉钉、飞书工作流的设计器
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmModelTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+ private final String name;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerTypeEnum.java
new file mode 100644
index 0000000..b1ecfe4
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerTypeEnum.java
@@ -0,0 +1,21 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * BPM 流程监听器的类型
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmProcessListenerTypeEnum {
+
+ EXECUTION("execution", "执行监听器"),
+ TASK("task", "任务执行器");
+
+ private final String type;
+ private final String name;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerValueTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerValueTypeEnum.java
new file mode 100644
index 0000000..7ff961b
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmProcessListenerValueTypeEnum.java
@@ -0,0 +1,22 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * BPM 流程监听器的值类型
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmProcessListenerValueTypeEnum {
+
+ CLASS("class", "Java 类"),
+ DELEGATE_EXPRESSION("delegateExpression", "代理表达式"),
+ EXPRESSION("expression", "表达式");
+
+ private final String type;
+ private final String name;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModeConditionTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModeConditionTypeEnum.java
new file mode 100644
index 0000000..b8c8ee2
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModeConditionTypeEnum.java
@@ -0,0 +1,36 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 仿钉钉的流程器设计器条件节点的条件类型
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmSimpleModeConditionTypeEnum implements ArrayValuable {
+
+ EXPRESSION(1, "条件表达式"),
+ RULE(2, "条件规则");
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmSimpleModeConditionTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+
+ private final String name;
+
+ public static BpmSimpleModeConditionTypeEnum valueOf(Integer type) {
+ return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java
new file mode 100644
index 0000000..6590a4c
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java
@@ -0,0 +1,70 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * 仿钉钉的流程器设计器的模型节点类型
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable {
+
+ // 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"),
+ TRANSACTOR_NODE(13, "办理人", "userTask"),
+
+ DELAY_TIMER_NODE(14, "延迟器", "receiveTask"),
+ TRIGGER_NODE(15, "触发器", "serviceTask"),
+
+ CHILD_PROCESS(20, "子流程", "callActivity"),
+
+ // 50 ~ 条件分支
+ CONDITION_NODE(50, "条件", "sequenceFlow"), // 用于构建流转条件的表达式
+ CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"),
+ PARALLEL_BRANCH_NODE(52, "并行分支", "parallelGateway"),
+ INCLUSIVE_BRANCH_NODE(53, "包容分支", "inclusiveGateway"),
+ ROUTER_BRANCH_NODE(54, "路由分支", "exclusiveGateway")
+ ;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmSimpleModelNodeTypeEnum::getType).toArray(Integer[]::new);
+
+ 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)
+ || Objects.equals(ROUTER_BRANCH_NODE.getType(), type);
+ }
+
+ public static BpmSimpleModelNodeTypeEnum valueOf(Integer type) {
+ return ArrayUtil.firstMatch(nodeType -> nodeType.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmTriggerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmTriggerTypeEnum.java
new file mode 100644
index 0000000..72c3c39
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmTriggerTypeEnum.java
@@ -0,0 +1,46 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM Simple 触发器类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmTriggerTypeEnum implements ArrayValuable {
+
+ HTTP_REQUEST(1, "发起 HTTP 请求"), // BPM => 业务,流程继续执行,无需等待业务
+ HTTP_CALLBACK(2, "接收 HTTP 回调"), // BPM => 业务 => BPM,流程卡主,等待业务回调
+
+ FORM_UPDATE(10, "更新流程表单数据"),
+ FORM_DELETE(11, "删除流程表单数据"),
+ ;
+
+ /**
+ * 触发器执行动作类型
+ */
+ private final Integer type;
+
+ /**
+ * 触发器执行动作描述
+ */
+ private final String desc;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmTriggerTypeEnum::getType).toArray(Integer[]::new);
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+ public static BpmTriggerTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
new file mode 100644
index 0000000..065035d
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
@@ -0,0 +1,47 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 多人审批方式的枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskApproveMethodEnum implements ArrayValuable {
+
+ 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 Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskApproveMethodEnum::getMethod).toArray(Integer[]::new);
+
+ public static BpmUserTaskApproveMethodEnum valueOf(Integer method) {
+ return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java
new file mode 100644
index 0000000..df40e18
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 用户任务的审批类型枚举
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskApproveTypeEnum implements ArrayValuable {
+
+ USER(1), // 人工审批
+ AUTO_APPROVE(2), // 自动通过
+ AUTO_REJECT(3); // 自动拒绝
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskApproveTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
new file mode 100644
index 0000000..237ef8e
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
@@ -0,0 +1,33 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务的审批人为空时,处理类型枚举
+ *
+ * @author ZT
+ */
+@RequiredArgsConstructor
+@Getter
+public enum BpmUserTaskAssignEmptyHandlerTypeEnum implements ArrayValuable {
+
+ APPROVE(1), // 自动通过
+ REJECT(2), // 自动拒绝
+ ASSIGN_USER(3), // 指定人员审批
+ ASSIGN_ADMIN(4), // 转交给流程管理员
+ ;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskAssignEmptyHandlerTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
new file mode 100644
index 0000000..ffed389
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务的审批人与发起人相同时,处理类型枚举
+ *
+ * @author ZT
+ */
+@RequiredArgsConstructor
+@Getter
+public enum BpmUserTaskAssignStartUserHandlerTypeEnum implements ArrayValuable {
+
+ START_USER_AUDIT(1), // 由发起人对自己审批
+ SKIP(2), // 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过
+ TRANSFER_DEPT_LEADER(3); // 转交给部门负责人审批【参考飞书】:若部门负责人为空,则自动通过
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskAssignStartUserHandlerTypeEnum::getType).toArray(Integer[]::new);
+
+ private final Integer type;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskRejectHandlerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskRejectHandlerTypeEnum.java
new file mode 100644
index 0000000..f251971
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskRejectHandlerTypeEnum.java
@@ -0,0 +1,35 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * BPM 用户任务拒绝处理类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskRejectHandlerTypeEnum implements ArrayValuable {
+
+ FINISH_PROCESS_INSTANCE(1, "终止流程"),
+ RETURN_USER_TASK(2, "驳回到指定任务节点");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskRejectHandlerTypeEnum::getType).toArray(Integer[]::new);
+
+ public static BpmUserTaskRejectHandlerTypeEnum typeOf(Integer type) {
+ return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
+ }
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java
new file mode 100644
index 0000000..8f9460e
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java
@@ -0,0 +1,32 @@
+package com.zt.plat.module.bpm.enums.definition;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * 用户任务超时处理类型枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmUserTaskTimeoutHandlerTypeEnum implements ArrayValuable {
+
+ REMINDER(1,"自动提醒"),
+ APPROVE(2, "自动同意"),
+ REJECT(3, "自动拒绝");
+
+ private final Integer type;
+ private final String name;
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmUserTaskTimeoutHandlerTypeEnum::getType).toArray(Integer[]::new);
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/message/BpmMessageEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/message/BpmMessageEnum.java
new file mode 100644
index 0000000..d8db9ae
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/message/BpmMessageEnum.java
@@ -0,0 +1,27 @@
+package com.zt.plat.module.bpm.enums.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Bpm 消息的枚举
+ *
+ * @author ZT
+ */
+@AllArgsConstructor
+@Getter
+public enum BpmMessageEnum {
+
+ PROCESS_INSTANCE_APPROVE("bpm_process_instance_approve"), // 流程任务被审批通过时,发送给申请人
+ PROCESS_INSTANCE_REJECT("bpm_process_instance_reject"), // 流程任务被审批不通过时,发送给申请人
+ TASK_ASSIGNED("bpm_task_assigned"), // 任务被分配时,发送给审批人
+ TASK_TIMEOUT("bpm_task_timeout"); // 任务审批超时时,发送给审批人
+
+ /**
+ * 短信模板的标识
+ *
+ * 关联 SmsTemplateDO 的 code 属性
+ */
+ private final String smsTemplateCode;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmCommentTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmCommentTypeEnum.java
new file mode 100644
index 0000000..51a5ffa
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmCommentTypeEnum.java
@@ -0,0 +1,46 @@
+package com.zt.plat.module.bpm.enums.task;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 流程任务的 Comment 评论类型枚举
+ *
+ * @author kehaiyou
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmCommentTypeEnum {
+
+ APPROVE("1", "审批通过", "审批通过,原因是:{}"),
+ REJECT("2", "不通过", "审批不通过:原因是:{}"),
+ CANCEL("3", "已取消", "系统自动取消,原因是:{}"),
+ RETURN("4", "退回", "任务被退回,原因是:{}"),
+ DELEGATE_START("5", "委派发起", "[{}]将任务委派给[{}],委派理由为:{}"),
+ DELEGATE_END("6", "委派完成", "[{}]完成委派任务,任务重新回到[{}]手中,审批建议为:{}"),
+ TRANSFER("7", "转派", "[{}]将任务转派给[{}],转派理由为:{}"),
+ ADD_SIGN("8", "加签", "[{}]{}给了[{}],理由为:{}"),
+ SUB_SIGN("9", "减签", "[{}]操作了【减签】,审批人[{}]的任务被取消"),
+ ;
+
+ /**
+ * 操作类型
+ *
+ * 由于 BPM Comment 类型为 String,所以这里就不使用 Integer
+ */
+ private final String type;
+ /**
+ * 操作名字
+ */
+ private final String name;
+ /**
+ * 操作描述
+ */
+ private final String comment;
+
+ public String formatComment(Object... params) {
+ return StrUtil.format(comment, params);
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
new file mode 100644
index 0000000..0e61d22
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
@@ -0,0 +1,80 @@
+package com.zt.plat.module.bpm.enums.task;
+
+import com.zt.plat.framework.common.core.ArrayValuable;
+import com.zt.plat.framework.common.util.object.ObjectUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+
+/**
+ * 流程实例 ProcessInstance 的状态
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmProcessInstanceStatusEnum implements ArrayValuable {
+
+ NOT_START(-1, "未开始"),
+ RUNNING(1, "审批中"),
+ APPROVE(2, "审批通过"),
+ REJECT(3, "审批不通过"),
+ CANCEL(4, "已取消");
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(BpmProcessInstanceStatusEnum::getStatus).toArray(Integer[]::new);
+
+ /**
+ * 状态
+ */
+ private final Integer status;
+ /**
+ * 描述
+ */
+ private final String desc;
+
+ @Override
+ public Integer[] array() {
+ 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());
+ }
+
+ /**
+ * 通过流程的状态返回对应的枚举
+ * @param status 流程状态
+ * @return
+ */
+ public static BpmProcessInstanceStatusEnum getEnumByStatus(Integer status){
+ for (BpmProcessInstanceStatusEnum e : BpmProcessInstanceStatusEnum.values()) {
+ if (e.getStatus().equals(status)) {
+ return e;
+ }
+ }
+ return NOT_START;
+ }
+
+ /**
+ * 通过枚举描述返回对应的枚举
+ * @param desc 描述
+ * @return
+ */
+ public static BpmProcessInstanceStatusEnum getEnumByDesc(String desc){
+ if (StringUtils.isEmpty(desc)) return NOT_START;
+ for (BpmProcessInstanceStatusEnum e : BpmProcessInstanceStatusEnum.values()) {
+ if (desc.equals(e.getDesc())) {
+ return e;
+ }
+ }
+ return NOT_START;
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmReasonEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmReasonEnum.java
new file mode 100644
index 0000000..8bf768f
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmReasonEnum.java
@@ -0,0 +1,52 @@
+package com.zt.plat.module.bpm.enums.task;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 流程实例/任务的的处理原因枚举
+ *
+ * @author ZT
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmReasonEnum {
+
+ // ========== 流程实例的独有原因 ==========
+
+ REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法
+ CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程
+ CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程
+ CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:主流程已取消"),
+
+ // ========== 流程任务的独有原因 ==========
+
+ CANCEL_BY_SYSTEM("系统自动取消"), // 场景:非常多,比如说:1)多任务审批已经满足条件,无需审批该任务;2)流程实例被取消,无需审批该任务;等等
+ TIMEOUT_APPROVE("审批超时,系统自动通过"),
+ TIMEOUT_REJECT("审批超时,系统自动不通过"),
+ ASSIGN_START_USER_APPROVE("审批人与提交人为同一人时,自动通过"),
+ ASSIGN_START_USER_APPROVE_WHEN_SKIP("审批人与提交人为同一人时,自动通过"),
+ ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE("发起人节点首次自动通过"), // 目前仅“子流程”使用
+ 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("非人工审核,自动不通过"),
+ CANCEL_BY_PROCESS_CLEAN("进程清理自动取消"),
+ ;
+
+ private final String reason;
+
+ /**
+ * 格式化理由
+ *
+ * @param args 参数
+ * @return 理由
+ */
+ public String format(Object... args) {
+ return StrUtil.format(reason, args);
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskSignTypeEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskSignTypeEnum.java
new file mode 100644
index 0000000..40aa2b1
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskSignTypeEnum.java
@@ -0,0 +1,47 @@
+package com.zt.plat.module.bpm.enums.task;
+
+import cn.hutool.core.util.ArrayUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 流程任务的加签类型枚举
+ *
+ * @author kehaiyou
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmTaskSignTypeEnum {
+
+ /**
+ * 向前加签,需要前置任务审批完成,才回到原审批人
+ */
+ BEFORE("before", "向前加签"),
+ /**
+ * 向后加签,需要后置任务全部审批完,才会通过原审批人节点
+ */
+ AFTER("after", "向后加签");
+
+ /**
+ * 类型
+ */
+ private final String type;
+ /**
+ * 名字
+ */
+ private final String name;
+
+ public static String nameOfType(String type) {
+ for (BpmTaskSignTypeEnum value : values()) {
+ if (value.type.equals(type)) {
+ return value.name;
+ }
+ }
+ return null;
+ }
+
+ public static BpmTaskSignTypeEnum of(String type) {
+ return ArrayUtil.firstMatch(value -> value.getType().equals(type), values());
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskStatusEnum.java b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskStatusEnum.java
new file mode 100644
index 0000000..42ac7df
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-api/src/main/java/com/zt/plat/module/bpm/enums/task/BpmTaskStatusEnum.java
@@ -0,0 +1,100 @@
+package com.zt.plat.module.bpm.enums.task;
+
+import cn.hutool.core.util.ObjUtil;
+import com.zt.plat.framework.common.util.object.ObjectUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 流程任务 Task 的状态枚举
+ *
+ * @author jason
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmTaskStatusEnum {
+
+ NOT_START(-1, "未开始"),
+ RUNNING(1, "审批中"),
+ APPROVE(2, "审批通过"),
+ REJECT(3, "审批不通过"),
+ CANCEL(4, "已取消"),
+
+ RETURN(5, "已退回"),
+
+ /**
+ * 使用场景:
+ * 1. 任务被向后【加签】时,它在审批通过后,会变成 APPROVING 这个状态,然后等到【加签】出来的任务都被审批后,才会变成 APPROVE 审批通过
+ */
+ APPROVING(7, "审批通过中"),
+ /**
+ * 使用场景:
+ * 1. 任务被向前【加签】时,它会变成 WAIT 状态,需要等待【加签】出来的任务被审批后,它才能继续变为 RUNNING 继续审批
+ * 2. 任务被向后【加签】时,【加签】出来的任务处于 WAIT 状态,它们需要等待该任务被审批后,它们才能继续变为 RUNNING 继续审批
+ */
+ WAIT(0, "待审批");
+
+ /**
+ * 状态
+ *
+ * 如果新增时,注意 {@link #isEndStatus(Integer)} 是否需要变更
+ */
+ private final Integer status;
+ /**
+ * 名字
+ */
+ private final String name;
+
+ public static boolean isRejectStatus(Integer status) {
+ return REJECT.getStatus().equals(status);
+ }
+
+ /**
+ * 判断该状态是否已经处于 End 最终状态
+ *
+ * 主要用于一些状态更新的逻辑,如果已经是最终状态,就不再进行更新
+ *
+ * @param status 状态
+ * @return 是否
+ */
+ public static boolean isEndStatus(Integer status) {
+ return ObjectUtils.equalsAny(status,
+ APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus(),
+ RETURN.getStatus(), APPROVING.getStatus());
+ }
+
+ public static boolean isCancelStatus(Integer status) {
+ return ObjUtil.equal(status, CANCEL.getStatus());
+ }
+
+
+ /**
+ * 通过流程的状态返回对应的枚举
+ * @param status 流程状态
+ * @return
+ */
+ public static BpmTaskStatusEnum getEnumByStatus(Integer status){
+ for (BpmTaskStatusEnum e : BpmTaskStatusEnum.values()) {
+ if (e.getStatus().equals(status)) {
+ return e;
+ }
+ }
+ return NOT_START;
+ }
+
+ /**
+ * 通过枚举描述返回对应的枚举
+ * @param name 描述
+ * @return
+ */
+ public static BpmTaskStatusEnum getEnumByName(String name){
+ if (StringUtils.isEmpty(name)) return NOT_START;
+ for (BpmTaskStatusEnum e : BpmTaskStatusEnum.values()) {
+ if (name.equals(e.getName())) {
+ return e;
+ }
+ }
+ return NOT_START;
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/Dockerfile b/zt-module-bpm/zt-module-bpm-server/Dockerfile
new file mode 100644
index 0000000..230aa5c
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/Dockerfile
@@ -0,0 +1,19 @@
+## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
+
+FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
+
+## 创建目录,并使用它作为工作目录
+RUN mkdir -p /zt-module-bpm-server
+WORKDIR /zt-module-bpm-server
+## 将后端项目的 Jar 文件,复制到镜像中
+COPY ./target/zt-module-bpm-server.jar app.jar
+
+## 设置 TZ 时区
+## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
+ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m"
+
+## 暴露后端项目的 48080 端口
+EXPOSE 48083
+
+## 启动后端项目
+CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar
diff --git a/zt-module-bpm/zt-module-bpm-server/pom.xml b/zt-module-bpm/zt-module-bpm-server/pom.xml
new file mode 100644
index 0000000..06a5ac4
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/pom.xml
@@ -0,0 +1,142 @@
+
+
+
+ com.zt.plat
+ zt-module-bpm
+ ${revision}
+
+ 4.0.0
+ zt-module-bpm-server
+
+ ${project.artifactId}
+
+ bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 Flowable 6 版本实现。
+ 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-env
+
+
+
+
+ com.zt.plat
+ zt-module-bpm-api
+ ${revision}
+
+
+ com.zt.plat
+ zt-module-system-api
+ ${revision}
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-biz-data-permission
+
+
+ com.zt.plat
+ zt-spring-boot-starter-biz-tenant
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-security
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-mybatis
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-redis
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-rpc
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+
+
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-test
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-monitor
+
+
+
+
+ com.zt.plat
+ zt-spring-boot-starter-excel
+
+
+
+
+ org.flowable
+ flowable-spring-boot-starter-process
+
+
+ org.flowable
+ flowable-spring-boot-starter-actuator
+
+
+ com.zt.plat
+ zt-spring-boot-starter-biz-business
+ ${revision}
+ compile
+
+
+
+
+
+ ${project.artifactId}
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java
new file mode 100644
index 0000000..1c86d9e
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java
@@ -0,0 +1,781 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package com.alibaba.druid.pool;
+
+import com.alibaba.cloud.commons.lang.StringUtils;
+import com.alibaba.druid.VERSION;
+import com.alibaba.druid.support.logging.Log;
+import com.alibaba.druid.support.logging.LogFactory;
+import com.alibaba.druid.util.JdbcUtils;
+import com.alibaba.druid.util.MySqlUtils;
+import java.net.SocketTimeoutException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DruidPooledStatement extends PoolableWrapper implements Statement {
+ private static final Log LOG = LogFactory.getLog(DruidPooledStatement.class);
+ private final Statement stmt;
+ protected DruidPooledConnection conn;
+ protected List resultSetTrace;
+ protected boolean closed;
+ protected int fetchRowPeak = -1;
+ protected int exceptionCount;
+
+ public DruidPooledStatement(DruidPooledConnection conn, Statement stmt) {
+ super(stmt);
+ this.conn = conn;
+ this.stmt = stmt;
+ }
+
+ protected void addResultSetTrace(ResultSet resultSet) {
+ if (this.resultSetTrace == null) {
+ this.resultSetTrace = new ArrayList(1);
+ } else if (this.resultSetTrace.size() > 0) {
+ int lastIndex = this.resultSetTrace.size() - 1;
+ ResultSet lastResultSet = (ResultSet)this.resultSetTrace.get(lastIndex);
+
+ try {
+ if (lastResultSet.isClosed()) {
+ this.resultSetTrace.set(lastIndex, resultSet);
+ return;
+ }
+ } catch (SQLException var5) {
+ }
+ }
+
+ this.resultSetTrace.add(resultSet);
+ }
+
+ protected void recordFetchRowCount(int fetchRowCount) {
+ if (this.fetchRowPeak < fetchRowCount) {
+ this.fetchRowPeak = fetchRowCount;
+ }
+
+ }
+
+ public int getFetchRowPeak() {
+ return this.fetchRowPeak;
+ }
+
+ protected SQLException checkException(Throwable error) throws SQLException {
+ String sql = null;
+ if (this instanceof DruidPooledPreparedStatement) {
+ sql = ((DruidPooledPreparedStatement)this).getSql();
+ }
+
+ this.handleSocketTimeout(error);
+ ++this.exceptionCount;
+ return this.conn.handleException(error, sql);
+ }
+
+ protected SQLException checkException(Throwable error, String sql) throws SQLException {
+ this.handleSocketTimeout(error);
+ ++this.exceptionCount;
+ return this.conn.handleException(error, sql);
+ }
+
+ protected void handleSocketTimeout(Throwable error) throws SQLException {
+ if (this.conn != null && this.conn.transactionInfo == null && this.conn.holder != null) {
+ DruidDataSource dataSource = null;
+ DruidConnectionHolder holder = this.conn.holder;
+ if (holder.dataSource instanceof DruidDataSource) {
+ dataSource = (DruidDataSource)holder.dataSource;
+ }
+
+ if (dataSource != null) {
+ if (dataSource.killWhenSocketReadTimeout) {
+ SQLException sqlException = null;
+ if (error instanceof SQLException) {
+ sqlException = (SQLException)error;
+ }
+
+ if (sqlException != null) {
+ Throwable cause = error.getCause();
+ boolean socketReadTimeout = cause instanceof SocketTimeoutException && "Read timed out".equals(cause.getMessage());
+ if (socketReadTimeout) {
+ if (JdbcUtils.isMysqlDbType(dataSource.dbTypeName)) {
+ String killQuery = MySqlUtils.buildKillQuerySql(this.conn.getConnection(), (SQLException)error);
+ if (killQuery != null) {
+ DruidPooledConnection killQueryConn = null;
+ Statement killQueryStmt = null;
+
+ try {
+ killQueryConn = dataSource.getConnection(1000L);
+ if (killQueryConn != null) {
+ killQueryStmt = killQueryConn.createStatement();
+ killQueryStmt.execute(killQuery);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(killQuery + " success.");
+ }
+
+ return;
+ }
+ } catch (Exception ex) {
+ LOG.warn(killQuery + " error.", ex);
+ return;
+ } finally {
+ JdbcUtils.close(killQueryStmt);
+ JdbcUtils.close(killQueryConn);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public DruidPooledConnection getPoolableConnection() {
+ return this.conn;
+ }
+
+ public Statement getStatement() {
+ return this.stmt;
+ }
+
+ protected void checkOpen() throws SQLException {
+ if (this.closed) {
+ Throwable disableError = null;
+ if (this.conn != null) {
+ disableError = this.conn.getDisableError();
+ }
+
+ if (disableError != null) {
+ throw new SQLException("statement is closed", disableError);
+ } else {
+ throw new SQLException("statement is closed");
+ }
+ }
+ }
+
+ protected void clearResultSet() {
+ if (this.resultSetTrace != null) {
+ for(ResultSet rs : this.resultSetTrace) {
+ try {
+ if (!rs.isClosed()) {
+ rs.close();
+ }
+ } catch (SQLException ex) {
+ LOG.error("clearResultSet error", ex);
+ }
+ }
+
+ this.resultSetTrace.clear();
+ }
+ }
+
+ public void incrementExecuteCount() {
+ DruidPooledConnection conn = this.getPoolableConnection();
+ if (conn != null) {
+ DruidConnectionHolder holder = conn.getConnectionHolder();
+ if (holder != null) {
+ DruidAbstractDataSource dataSource = holder.getDataSource();
+ if (dataSource != null) {
+ dataSource.incrementExecuteCount();
+ }
+ }
+ }
+ }
+
+ public void incrementExecuteBatchCount() {
+ DruidPooledConnection conn = this.getPoolableConnection();
+ if (conn != null) {
+ DruidConnectionHolder holder = conn.getConnectionHolder();
+ if (holder != null) {
+ if (holder.getDataSource() != null) {
+ DruidAbstractDataSource dataSource = holder.getDataSource();
+ if (dataSource != null) {
+ dataSource.incrementExecuteBatchCount();
+ }
+ }
+ }
+ }
+ }
+
+ public void incrementExecuteUpdateCount() {
+ DruidPooledConnection conn = this.getPoolableConnection();
+ if (conn != null) {
+ DruidConnectionHolder holder = conn.getConnectionHolder();
+ if (holder != null) {
+ DruidAbstractDataSource dataSource = holder.getDataSource();
+ if (dataSource != null) {
+ dataSource.incrementExecuteUpdateCount();
+ }
+ }
+ }
+ }
+
+ public void incrementExecuteQueryCount() {
+ DruidPooledConnection conn = this.conn;
+ if (conn != null) {
+ DruidConnectionHolder holder = conn.holder;
+ if (holder != null) {
+ DruidAbstractDataSource dataSource = holder.dataSource;
+ if (dataSource != null) {
+ ++dataSource.executeQueryCount;
+ }
+ }
+ }
+ }
+
+ protected void transactionRecord(String sql) throws SQLException {
+ this.conn.transactionRecord(sql);
+ }
+
+ public final ResultSet executeQuery(String sql) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteQueryCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ ResultSet var3;
+ try {
+ ResultSet rs = this.stmt.executeQuery(sql);
+ if (rs != null) {
+ DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);
+ this.addResultSetTrace(poolableResultSet);
+ DruidPooledResultSet var4 = poolableResultSet;
+ return var4;
+ }
+
+ var3 = rs;
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final int executeUpdate(String sql) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteUpdateCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ int var2;
+ try {
+ var2 = this.stmt.executeUpdate(sql);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var2;
+ }
+
+ protected final void errorCheck(Throwable t) {
+ String errorClassName = t.getClass().getName();
+ if (errorClassName.endsWith(".CommunicationsException") && this.conn.holder != null && this.conn.holder.dataSource.testWhileIdle) {
+ DruidConnectionHolder holder = this.conn.holder;
+ DruidAbstractDataSource dataSource = holder.dataSource;
+ long currentTimeMillis = System.currentTimeMillis();
+ long lastActiveTimeMillis = holder.lastActiveTimeMillis;
+ if (lastActiveTimeMillis < holder.lastKeepTimeMillis) {
+ lastActiveTimeMillis = holder.lastKeepTimeMillis;
+ }
+
+ long idleMillis = currentTimeMillis - lastActiveTimeMillis;
+ long lastValidIdleMillis = currentTimeMillis - holder.lastActiveTimeMillis;
+ String errorMsg = "CommunicationsException, druid version " + VERSION.getVersionNumber() + ", jdbcUrl : " + dataSource.jdbcUrl + ", testWhileIdle " + dataSource.testWhileIdle + ", idle millis " + idleMillis + ", minIdle " + dataSource.minIdle + ", poolingCount " + dataSource.getPoolingCount() + ", timeBetweenEvictionRunsMillis " + dataSource.timeBetweenEvictionRunsMillis + ", lastValidIdleMillis " + lastValidIdleMillis + ", driver " + dataSource.driver.getClass().getName();
+ if (dataSource.exceptionSorter != null) {
+ errorMsg = errorMsg + ", exceptionSorter " + dataSource.exceptionSorter.getClass().getName();
+ }
+
+ LOG.error(errorMsg);
+ }
+
+ }
+
+ public final int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteUpdateCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ int var3;
+ try {
+ var3 = this.stmt.executeUpdate(sql, autoGeneratedKeys);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteUpdateCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ int var3;
+ try {
+ var3 = this.stmt.executeUpdate(sql, columnIndexes);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final int executeUpdate(String sql, String[] columnNames) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteUpdateCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ int var3;
+ try {
+ var3 = this.stmt.executeUpdate(sql, columnNames);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ boolean var3;
+ try {
+ var3 = this.stmt.execute(sql, autoGeneratedKeys);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final boolean execute(String sql, int[] columnIndexes) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ boolean var3;
+ try {
+ var3 = this.stmt.execute(sql, columnIndexes);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+ public final boolean execute(String sql, String[] columnNames) throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteCount();
+ this.transactionRecord(sql);
+ this.conn.beforeExecute();
+
+ boolean var3;
+ try {
+ var3 = this.stmt.execute(sql, columnNames);
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t, sql);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var3;
+ }
+
+
+ public int getMaxFieldSize() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getMaxFieldSize();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public void close() throws SQLException {
+ if (!this.closed) {
+ this.clearResultSet();
+ if (this.stmt != null) {
+ this.stmt.close();
+ }
+
+ this.closed = true;
+ DruidConnectionHolder connHolder = this.conn.getConnectionHolder();
+ if (connHolder != null) {
+ connHolder.removeTrace(this);
+ }
+
+ }
+ }
+
+ public void setMaxFieldSize(int max) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setMaxFieldSize(max);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getMaxRows() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getMaxRows();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public void setMaxRows(int max) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setMaxRows(max);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final void setEscapeProcessing(boolean enable) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setEscapeProcessing(enable);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getQueryTimeout() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getQueryTimeout();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public void setQueryTimeout(int seconds) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setQueryTimeout(seconds);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final void cancel() throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.cancel();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final SQLWarning getWarnings() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getWarnings();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final void clearWarnings() throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.clearWarnings();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final void setCursorName(String name) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setCursorName(name);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ @Override
+ public final boolean execute(String sql) throws SQLException {
+ checkOpen();
+
+ incrementExecuteCount();
+ transactionRecord(sql);
+
+ try {
+ if (StringUtils.isNotEmpty(sql)){
+ sql = sql.replace("TRUE", "1");
+ sql = sql.replace("FALSE", "0");
+ }
+ return stmt.execute(sql);
+ } catch (Throwable t) {
+ errorCheck(t);
+ throw checkException(t, sql);
+ }
+ }
+
+ public final ResultSet getResultSet() throws SQLException {
+ this.checkOpen();
+
+ try {
+ ResultSet rs = this.stmt.getResultSet();
+ if (rs == null) {
+ return null;
+ } else {
+ DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);
+ this.addResultSetTrace(poolableResultSet);
+ return poolableResultSet;
+ }
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getUpdateCount() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getUpdateCount();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final boolean getMoreResults() throws SQLException {
+ this.checkOpen();
+
+ try {
+ boolean moreResults = this.stmt.getMoreResults();
+ if (this.resultSetTrace != null && this.resultSetTrace.size() > 0) {
+ ResultSet lastResultSet = (ResultSet)this.resultSetTrace.get(this.resultSetTrace.size() - 1);
+ if (lastResultSet instanceof DruidPooledResultSet) {
+ DruidPooledResultSet pooledResultSet = (DruidPooledResultSet)lastResultSet;
+ pooledResultSet.closed = true;
+ }
+ }
+
+ return moreResults;
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setFetchDirection(direction);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getFetchDirection() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getFetchDirection();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public void setFetchSize(int rows) throws SQLException {
+ this.checkOpen();
+
+ try {
+ this.stmt.setFetchSize(rows);
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getFetchSize() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getFetchSize();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getResultSetConcurrency() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getResultSetConcurrency();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getResultSetType() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getResultSetType();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final void addBatch(String sql) throws SQLException {
+ this.checkOpen();
+ this.transactionRecord(sql);
+
+ try {
+ this.stmt.addBatch(sql);
+ } catch (Throwable t) {
+ throw this.checkException(t, sql);
+ }
+ }
+
+ public final void clearBatch() throws SQLException {
+ if (!this.closed) {
+ try {
+ this.stmt.clearBatch();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+ }
+
+ public int[] executeBatch() throws SQLException {
+ this.checkOpen();
+ this.incrementExecuteBatchCount();
+ this.conn.beforeExecute();
+
+ int[] var1;
+ try {
+ var1 = this.stmt.executeBatch();
+ } catch (Throwable t) {
+ this.errorCheck(t);
+ throw this.checkException(t);
+ } finally {
+ this.conn.afterExecute();
+ }
+
+ return var1;
+ }
+
+ public final Connection getConnection() throws SQLException {
+ this.checkOpen();
+ return this.conn;
+ }
+
+ public final boolean getMoreResults(int current) throws SQLException {
+ this.checkOpen();
+
+ try {
+ boolean results = this.stmt.getMoreResults(current);
+ if (this.resultSetTrace != null && this.resultSetTrace.size() > 0) {
+ ResultSet lastResultSet = (ResultSet)this.resultSetTrace.get(this.resultSetTrace.size() - 1);
+ if (lastResultSet instanceof DruidPooledResultSet) {
+ DruidPooledResultSet pooledResultSet = (DruidPooledResultSet)lastResultSet;
+ pooledResultSet.closed = true;
+ }
+ }
+
+ return results;
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final ResultSet getGeneratedKeys() throws SQLException {
+ this.checkOpen();
+
+ try {
+ ResultSet rs = this.stmt.getGeneratedKeys();
+ DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);
+ this.addResultSetTrace(poolableResultSet);
+ return poolableResultSet;
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final int getResultSetHoldability() throws SQLException {
+ this.checkOpen();
+
+ try {
+ return this.stmt.getResultSetHoldability();
+ } catch (Throwable t) {
+ throw this.checkException(t);
+ }
+ }
+
+ public final boolean isClosed() throws SQLException {
+ return this.closed;
+ }
+
+ public final void setPoolable(boolean poolable) throws SQLException {
+ if (!poolable) {
+ throw new SQLException("not support");
+ }
+ }
+
+ public final boolean isPoolable() throws SQLException {
+ return false;
+ }
+
+ public String toString() {
+ return this.stmt.toString();
+ }
+
+ public void closeOnCompletion() throws SQLException {
+ this.stmt.closeOnCompletion();
+ }
+
+ public boolean isCloseOnCompletion() throws SQLException {
+ return this.stmt.isCloseOnCompletion();
+ }
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/BpmServerApplication.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/BpmServerApplication.java
new file mode 100644
index 0000000..f9ce039
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/BpmServerApplication.java
@@ -0,0 +1,30 @@
+package com.zt.plat.module.bpm;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * 项目的启动类
+ *
+ * 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ * 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ * 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ *
+ * @author ZT
+ */
+@SpringBootApplication
+public class BpmServerApplication {
+
+ public static void main(String[] args) {
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+
+ SpringApplication.run(BpmServerApplication.class, args);
+
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ // 如果你碰到启动的问题,请认真阅读 http://172.16.46.63:30888/quick-start/ 文章
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmCategoryApiImpl.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmCategoryApiImpl.java
new file mode 100644
index 0000000..7f161dd
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmCategoryApiImpl.java
@@ -0,0 +1,79 @@
+package com.zt.plat.module.bpm.api.definition;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.api.definition.dto.BpmCategoryPageReqDTO;
+import com.zt.plat.module.bpm.api.definition.dto.BpmCategoryRespDTO;
+import com.zt.plat.module.bpm.api.definition.dto.BpmCategorySaveReqDTO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.category.BpmCategoryPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
+import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+/**
+ * BPM 流程分类 Api 实现类
+ *
+ * @author ZT
+ */
+@RestController
+@Validated
+public class BpmCategoryApiImpl implements BpmCategoryApi {
+
+ @Resource
+ private BpmCategoryService categoryService;
+
+ @Override
+ public CommonResult createCategory(@Valid BpmCategorySaveReqDTO createReqDTO) {
+ BpmCategorySaveReqVO createReqVO = BeanUtils.toBean(createReqDTO, BpmCategorySaveReqVO.class);
+ return success(categoryService.createCategory(createReqVO));
+ }
+
+ @Override
+ public CommonResult updateCategory(@Valid BpmCategorySaveReqDTO updateReqDTO) {
+ BpmCategorySaveReqVO updateReqVO = BeanUtils.toBean(updateReqDTO, BpmCategorySaveReqVO.class);
+ categoryService.updateCategory(updateReqVO);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult updateCategorySortBatch(List ids) {
+ categoryService.updateCategorySortBatch(ids);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult deleteCategory(Long id) {
+ categoryService.deleteCategory(id);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult getCategory(Long id) {
+ BpmCategoryDO category = categoryService.getCategory(id);
+ return success(BeanUtils.toBean(category, BpmCategoryRespDTO.class));
+ }
+
+ @Override
+ public CommonResult> getCategoryPage(@Valid BpmCategoryPageReqDTO pageReqDTO) {
+ BpmCategoryPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BpmCategoryPageReqVO.class);
+ PageResult pageResult = categoryService.getCategoryPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, BpmCategoryRespDTO.class));
+ }
+
+ @Override
+ public CommonResult> getCategorySimpleList() {
+ List list = categoryService.getCategoryListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ return success(BeanUtils.toBean(list, BpmCategoryRespDTO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmFormApiImpl.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmFormApiImpl.java
new file mode 100644
index 0000000..faceb1e
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmFormApiImpl.java
@@ -0,0 +1,76 @@
+package com.zt.plat.module.bpm.api.definition;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.api.definition.dto.BpmFormPageReqDTO;
+import com.zt.plat.module.bpm.api.definition.dto.BpmFormRespDTO;
+import com.zt.plat.module.bpm.api.definition.dto.BpmFormSaveReqDTO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.form.BpmFormSaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmFormDO;
+import com.zt.plat.module.bpm.service.definition.BpmFormService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+/**
+ * 动态表单 Api 实现类
+ *
+ * @author ZT
+ */
+@RestController
+@Validated
+public class BpmFormApiImpl implements BpmFormApi {
+
+ @Resource
+ private BpmFormService formService;
+
+ @Override
+ public CommonResult createForm(@Valid BpmFormSaveReqDTO createReqDTO) {
+ BpmFormSaveReqVO createReqVO = BeanUtils.toBean(createReqDTO, BpmFormSaveReqVO.class);
+ return success(formService.createForm(createReqVO));
+ }
+
+ @Override
+ public CommonResult updateForm(@Valid BpmFormSaveReqDTO updateReqDTO) {
+ BpmFormSaveReqVO updateReqVO = BeanUtils.toBean(updateReqDTO, BpmFormSaveReqVO.class);
+ formService.updateForm(updateReqVO);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult deleteForm(Long id) {
+ formService.deleteForm(id);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult getForm(Long id) {
+ BpmFormDO form = formService.getForm(id);
+ return success(BeanUtils.toBean(form, BpmFormRespDTO.class));
+ }
+
+ @Override
+ public CommonResult> getFormPage(BpmFormPageReqDTO pageReqDTO) {
+ BpmFormPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BpmFormPageReqVO.class);
+ PageResult pageResult = formService.getFormPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, BpmFormRespDTO.class));
+ }
+
+ @Override
+ public CommonResult> getFormSimpleList() {
+ List list = formService.getFormList();
+ // 只返回 id、name 字段
+ List dtoList = list.stream()
+ .map(formDO -> new BpmFormRespDTO().setId(formDO.getId()).setName(formDO.getName()))
+ .collect(java.util.stream.Collectors.toList());
+ return success(dtoList);
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmUserGroupApiImpl.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmUserGroupApiImpl.java
new file mode 100644
index 0000000..502b9d6
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/definition/BpmUserGroupApiImpl.java
@@ -0,0 +1,41 @@
+package com.zt.plat.module.bpm.api.definition;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.api.definition.dto.BpmUserGroupRespDTO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
+import com.zt.plat.module.bpm.service.definition.BpmUserGroupService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.annotation.Resource;
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+/**
+ * 用户组 Api 实现类
+ *
+ * @author ZT
+ */
+@RestController
+@Validated
+public class BpmUserGroupApiImpl implements BpmUserGroupApi {
+
+ @Resource
+ private BpmUserGroupService userGroupService;
+
+ @Override
+ public CommonResult getUserGroup(Long id) {
+ BpmUserGroupDO userGroup = userGroupService.getUserGroup(id);
+ return success(BeanUtils.toBean(userGroup, BpmUserGroupRespDTO.class));
+ }
+
+ @Override
+ public CommonResult> getUserGroupSimpleList() {
+ List list = userGroupService.getUserGroupListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ return success(BeanUtils.toBean(list, BpmUserGroupRespDTO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/package-info.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/package-info.java
new file mode 100644
index 0000000..7c3b4c4
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * bpm API 实现类,定义暴露给其它模块的 API
+ */
+package com.zt.plat.module.bpm.api;
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java
new file mode 100644
index 0000000..b3d1e79
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java
@@ -0,0 +1,150 @@
+package com.zt.plat.module.bpm.api.task;
+
+import cn.hutool.core.util.StrUtil;
+import com.zt.plat.framework.business.core.util.DeptUtil;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.util.json.JsonUtils;
+import com.zt.plat.framework.common.util.number.NumberUtils;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.api.task.dto.*;
+import com.zt.plat.module.bpm.controller.admin.task.vo.instance.*;
+import com.zt.plat.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
+import com.zt.plat.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO;
+import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceConvert;
+import com.zt.plat.module.bpm.convert.task.BpmProcessInstanceDTOConvert;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
+import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
+import com.zt.plat.module.bpm.service.task.BpmProcessInstanceService;
+import com.zt.plat.module.bpm.service.task.BpmTaskService;
+import com.zt.plat.module.system.api.dept.DeptApi;
+import com.zt.plat.module.system.api.dept.dto.DeptRespDTO;
+import com.zt.plat.module.system.api.user.AdminUserApi;
+import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
+
+/**
+ * Flowable 流程实例 Api 实现类
+ *
+ * @author ZT
+ * @author jason
+ */
+@RestController
+@Valid
+public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
+
+ @Resource
+ private BpmProcessInstanceService processInstanceService;
+
+ @Resource
+ private BpmTaskService taskService;
+
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public CommonResult createProcessInstance(Long userId, @Valid @RequestBody BpmProcessInstanceCreateReqDTO reqDTO) {
+ return success(processInstanceService.createProcessInstance(userId, reqDTO));
+ }
+
+
+ @Override
+ public CommonResult getProcessInstance(String id) {
+ HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(id);
+ if (processInstance == null) {
+ return success(null);
+ }
+
+ // 拼接返回
+ ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(
+ processInstance.getProcessDefinitionId());
+ BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
+ processInstance.getProcessDefinitionId());
+ AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())).getCheckedData();
+ DeptRespDTO dept = null;
+ if (startUser != null) {
+ Long deptId = DeptUtil.getDeptId(startUser);
+ if (deptId > 0) {
+ dept = deptApi.getDept(deptId).getCheckedData();
+ }
+ }
+ BpmProcessInstanceRespVO vo = BpmProcessInstanceConvert.INSTANCE.buildProcessInstance(processInstance,
+ processDefinition, processDefinitionInfo, startUser, dept);
+ return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(vo));
+ }
+
+ @Override
+ public CommonResult cancelProcessInstanceByStartUser(
+ Long userId, @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO) {
+ BpmProcessInstanceCancelReqVO cancelReqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(cancelReqDTO);
+ processInstanceService.cancelProcessInstanceByStartUser(userId, cancelReqVO);
+ return success(true);
+ }
+
+ @Override
+ public CommonResult cancelProcessInstanceByAdmin(
+ Long userId, @Valid @RequestBody BpmProcessInstanceCancelReqDTO cancelReqDTO) {
+ BpmProcessInstanceCancelReqVO cancelReqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(cancelReqDTO);
+ processInstanceService.cancelProcessInstanceByAdmin(userId, cancelReqVO);
+ return success(true);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public CommonResult getApprovalDetail(Long userId,
+ @Valid @RequestBody BpmApprovalDetailReqDTO reqDTO) {
+ BpmApprovalDetailReqVO reqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(reqDTO);
+ if (StrUtil.isNotEmpty(reqDTO.getProcessVariablesStr())) {
+ reqVO.setProcessVariables(JsonUtils.parseObject(reqDTO.getProcessVariablesStr(), Map.class));
+ }
+ BpmApprovalDetailRespVO respVO = processInstanceService.getApprovalDetail(userId, reqVO);
+ return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(respVO));
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public CommonResult> getNextApprovalNodes(Long userId,
+ @Valid @RequestBody BpmApprovalDetailReqDTO reqDTO) {
+ BpmApprovalDetailReqVO reqVO = BpmProcessInstanceDTOConvert.INSTANCE.convertVO(reqDTO);
+ if (StrUtil.isNotEmpty(reqDTO.getProcessVariablesStr())) {
+ reqVO.setProcessVariables(JsonUtils.parseObject(reqDTO.getProcessVariablesStr(), Map.class));
+ }
+ List nodes = processInstanceService.getNextApprovalNodes(userId, reqVO);
+ return success(BpmProcessInstanceDTOConvert.INSTANCE.convertActivityNodes(nodes));
+ }
+
+ @Override
+ public CommonResult getProcessInstanceBpmnModelView(String id) {
+ BpmProcessInstanceBpmnModelViewRespVO respVO = processInstanceService.getProcessInstanceBpmnModelView(id);
+ return success(BpmProcessInstanceDTOConvert.INSTANCE.convert(respVO));
+ }
+
+ @Override
+ public CommonResult approveTask(BpmTaskApproveReqDTO reqVO) {
+ taskService.approveTask(getLoginUserId(), BeanUtils.toBean(reqVO, BpmTaskApproveReqVO.class));
+ return success(true);
+ }
+
+ @Override
+ public CommonResult rejectTask(BpmTaskRejectReqDTO reqVO) {
+ taskService.rejectTask(getLoginUserId(), BeanUtils.toBean(reqVO, BpmTaskRejectReqVO.class));
+ return success(true);
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmTaskApiImpl.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmTaskApiImpl.java
new file mode 100644
index 0000000..4d70c6a
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmTaskApiImpl.java
@@ -0,0 +1,203 @@
+package com.zt.plat.module.bpm.api.task;
+
+import cn.hutool.core.collection.CollUtil;
+import com.zt.plat.framework.business.core.util.DeptUtil;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.number.NumberUtils;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
+import com.zt.plat.module.bpm.api.task.dto.BpmTaskPageReqDTO;
+import com.zt.plat.module.bpm.api.task.dto.BpmTaskRespDTO;
+import com.zt.plat.module.bpm.controller.admin.task.vo.task.BpmTaskPageReqVO;
+import com.zt.plat.module.bpm.convert.task.BpmTaskConvert;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmFormDO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
+import com.zt.plat.module.bpm.service.definition.BpmFormService;
+import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
+import com.zt.plat.module.bpm.service.task.BpmProcessInstanceService;
+import com.zt.plat.module.bpm.service.task.BpmTaskService;
+import com.zt.plat.module.system.api.dept.DeptApi;
+import com.zt.plat.module.system.api.dept.dto.DeptRespDTO;
+import com.zt.plat.module.system.api.user.AdminUserApi;
+import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.flowable.task.api.history.HistoricTaskInstance;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.*;
+import java.util.stream.Stream;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertSet;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
+
+/**
+ * BPM 任务 API 实现类
+ *
+ * @author ZT
+ */
+@RestController
+@Validated
+public class BpmTaskApiImpl implements BpmTaskApi {
+
+ @Resource
+ private BpmTaskService taskService;
+ @Resource
+ private BpmProcessInstanceService processInstanceService;
+ @Resource
+ private BpmFormService formService;
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public CommonResult> getTaskTodoPage(@Valid BpmTaskPageReqDTO pageReqDTO) {
+ // 转换请求参数
+ BpmTaskPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BpmTaskPageReqVO.class);
+
+ // 调用 Service 层方法
+ PageResult pageResult = taskService.getTaskTodoPage(SecurityFrameworkUtils.getLoginUserId(), pageReqVO);
+ if (CollUtil.isEmpty(pageResult.getList())) {
+ return success(new ArrayList<>());
+ }
+
+ // 拼接数据 - 参考 Controller 逻辑
+ Map processInstanceMap = processInstanceService.getProcessInstanceMap(convertSet(pageResult.getList(), Task::getProcessInstanceId));
+ Map userMap = adminUserApi.getUserMap(convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+ Map processDefinitionInfoMap = processDefinitionService.getProcessDefinitionInfoMap(convertSet(pageResult.getList(), Task::getProcessDefinitionId));
+
+ // 使用转换器构建完整的 VO 结果,然后转换为 DTO
+ var voPageResult = BpmTaskConvert.INSTANCE.buildTodoTaskPage(pageResult, processInstanceMap, userMap, processDefinitionInfoMap);
+ List result = BpmTaskConvert.INSTANCE.buildTaskRespDTOList(voPageResult.getList());
+
+ return success(result);
+ }
+
+ @Override
+ public CommonResult> getTaskDonePage(@Valid BpmTaskPageReqDTO pageReqDTO) {
+ // 转换请求参数
+ BpmTaskPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BpmTaskPageReqVO.class);
+
+ // 调用 Service 层方法
+ PageResult pageResult = taskService.getTaskDonePage(SecurityFrameworkUtils.getLoginUserId(), pageReqVO);
+ if (CollUtil.isEmpty(pageResult.getList())) {
+ return success(new ArrayList<>());
+ }
+
+ // 拼接数据 - 参考 Controller 逻辑
+ Map processInstanceMap = processInstanceService.getHistoricProcessInstanceMap(convertSet(pageResult.getList(), HistoricTaskInstance::getProcessInstanceId));
+ Map userMap = adminUserApi.getUserMap(convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+ Map processDefinitionInfoMap = processDefinitionService.getProcessDefinitionInfoMap(convertSet(pageResult.getList(), HistoricTaskInstance::getProcessDefinitionId));
+
+ // 使用转换器构建完整的 VO 结果,然后转换为 DTO
+ var voPageResult = BpmTaskConvert.INSTANCE.buildTaskPage(pageResult, processInstanceMap, userMap, null, processDefinitionInfoMap);
+ List result = BpmTaskConvert.INSTANCE.buildTaskRespDTOList(voPageResult.getList());
+
+ return success(result);
+ }
+
+ @Override
+ public CommonResult> getTaskManagerPage(@Valid BpmTaskPageReqDTO pageReqDTO) {
+ // 转换请求参数
+ BpmTaskPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BpmTaskPageReqVO.class);
+
+ // 调用 Service 层方法
+ PageResult pageResult = taskService.getTaskPage(SecurityFrameworkUtils.getLoginUserId(), pageReqVO);
+ if (CollUtil.isEmpty(pageResult.getList())) {
+ return success(new ArrayList<>());
+ }
+
+ // 拼接数据 - 参考 Controller 逻辑
+ Map processInstanceMap = processInstanceService.getHistoricProcessInstanceMap(convertSet(pageResult.getList(), HistoricTaskInstance::getProcessInstanceId));
+ // 获得 User 和 Dept Map
+ Set userIds = convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()));
+ userIds.addAll(convertSet(pageResult.getList(), task -> NumberUtils.parseLong(task.getAssignee())));
+ Map userMap = adminUserApi.getUserMap(userIds);
+ Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), DeptUtil::getDeptId));
+ Map processDefinitionInfoMap = processDefinitionService.getProcessDefinitionInfoMap(convertSet(pageResult.getList(), HistoricTaskInstance::getProcessDefinitionId));
+
+ // 使用转换器构建完整的 VO 结果,然后转换为 DTO
+ var voPageResult = BpmTaskConvert.INSTANCE.buildTaskPage(pageResult, processInstanceMap, userMap, deptMap, processDefinitionInfoMap);
+ List result = BpmTaskConvert.INSTANCE.buildTaskRespDTOList(voPageResult.getList());
+
+ return success(result);
+ }
+
+ @Override
+ public CommonResult> getTaskListByProcessInstanceId(String processInstanceId) {
+ // 调用 Service 层方法
+ List taskList = taskService.getTaskListByProcessInstanceId(processInstanceId, true);
+ if (CollUtil.isEmpty(taskList)) {
+ return success(Collections.emptyList());
+ }
+
+ // 拼接数据 - 参考 Controller 逻辑
+ Set userIds = convertSetByFlatMap(taskList, task -> Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner())));
+ Map userMap = adminUserApi.getUserMap(userIds);
+ Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), DeptUtil::getDeptId));
+ // 获得 Form Map
+ Map formMap = formService.getFormMap(convertSet(taskList, task -> {
+ String formKey = task.getFormKey();
+ if (formKey == null || formKey.isBlank()) {
+ return 0L;
+ }
+ try {
+ return Long.parseLong(formKey);
+ } catch (NumberFormatException e) {
+ // 如果 formKey 不是数字(比如是URL),返回0L
+ return 0L;
+ }
+ }));
+
+ // 使用转换器构建完整的 VO 结果,然后转换为 DTO
+ var voList = BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, formMap, userMap, deptMap);
+ List result = BpmTaskConvert.INSTANCE.buildTaskRespDTOList(voList);
+
+ return success(result);
+ }
+
+ @Override
+ public CommonResult> getTaskListByReturn(String id) {
+ // 调用 Service 层方法
+ var userTaskList = taskService.getUserTaskListByReturn(id);
+
+ // 转换返回结果 - 只返回 id 和 name(对应 taskDefinitionKey 和 name)
+ List result = userTaskList.stream().map(userTask -> {
+ BpmTaskRespDTO dto = new BpmTaskRespDTO();
+ dto.setName(userTask.getName());
+ dto.setTaskDefinitionKey(userTask.getId());
+ return dto;
+ }).toList();
+
+ return success(result);
+ }
+
+ @Override
+ public CommonResult> getTaskListByParentTaskId(String parentTaskId) {
+ // 调用 Service 层方法
+ List taskList = taskService.getTaskListByParentTaskId(parentTaskId);
+ if (CollUtil.isEmpty(taskList)) {
+ return success(Collections.emptyList());
+ }
+
+ // 拼接数据 - 参考 Controller 逻辑
+ Map userMap = adminUserApi.getUserMap(convertSetByFlatMap(taskList, user -> Stream.of(NumberUtils.parseLong(user.getAssignee()), NumberUtils.parseLong(user.getOwner()))));
+ Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), DeptUtil::getDeptId));
+
+ // 使用转换器构建完整的 VO 结果,然后转换为 DTO
+ var voList = BpmTaskConvert.INSTANCE.buildTaskListByParentTaskId(taskList, userMap, deptMap);
+ List result = BpmTaskConvert.INSTANCE.buildTaskRespDTOList(voList);
+
+ return success(result);
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java
new file mode 100644
index 0000000..b0c466b
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java
@@ -0,0 +1,15 @@
+package com.zt.plat.module.bpm.controller.admin.base.dept;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "部门精简信息 VO")
+@Data
+public class DeptSimpleBaseVO {
+
+ @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long id;
+ @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术部")
+ private String name;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/package-info.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/package-info.java
new file mode 100644
index 0000000..141c17f
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 基础包,放一些通用的 VO 类
+ */
+package com.zt.plat.module.bpm.controller.admin.base;
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java
new file mode 100644
index 0000000..6fcbb96
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java
@@ -0,0 +1,22 @@
+package com.zt.plat.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/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmCategoryController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmCategoryController.java
new file mode 100644
index 0000000..b318b4b
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmCategoryController.java
@@ -0,0 +1,95 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.category.BpmCategoryPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.category.BpmCategoryRespVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
+import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Comparator;
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - BPM 流程分类")
+@RestController
+@RequestMapping("/bpm/category")
+@Validated
+public class BpmCategoryController {
+
+ @Resource
+ private BpmCategoryService categoryService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建流程分类")
+ @PreAuthorize("@ss.hasPermission('bpm:category:create')")
+ public CommonResult createCategory(@Valid @RequestBody BpmCategorySaveReqVO createReqVO) {
+ return success(categoryService.createCategory(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新流程分类")
+ @PreAuthorize("@ss.hasPermission('bpm:category:update')")
+ public CommonResult updateCategory(@Valid @RequestBody BpmCategorySaveReqVO updateReqVO) {
+ categoryService.updateCategory(updateReqVO);
+ 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)
+ @PreAuthorize("@ss.hasPermission('bpm:category:delete')")
+ public CommonResult deleteCategory(@RequestParam("id") Long id) {
+ categoryService.deleteCategory(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得流程分类")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:category:query')")
+ public CommonResult getCategory(@RequestParam("id") Long id) {
+ BpmCategoryDO category = categoryService.getCategory(id);
+ return success(BeanUtils.toBean(category, BpmCategoryRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得流程分类分页")
+ @PreAuthorize("@ss.hasPermission('bpm:category:query')")
+ public CommonResult> getCategoryPage(@Valid BpmCategoryPageReqVO pageReqVO) {
+ PageResult pageResult = categoryService.getCategoryPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, BpmCategoryRespVO.class));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获取流程分类的精简信息列表", description = "只包含被开启的分类,主要用于前端的下拉选项")
+ public CommonResult> getCategorySimpleList() {
+ List list = categoryService.getCategoryListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ list.sort(Comparator.comparingInt(BpmCategoryDO::getSort));
+ return success(convertList(list, category -> new BpmCategoryRespVO().setId(category.getId())
+ .setName(category.getName()).setCode(category.getCode())));
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmFormController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmFormController.java
new file mode 100644
index 0000000..fa47346
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmFormController.java
@@ -0,0 +1,83 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.form.BpmFormRespVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.form.BpmFormSaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmFormDO;
+import com.zt.plat.module.bpm.service.definition.BpmFormService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - 动态表单")
+@RestController
+@RequestMapping("/bpm/form")
+@Validated
+public class BpmFormController {
+
+ @Resource
+ private BpmFormService formService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建动态表单")
+ @PreAuthorize("@ss.hasPermission('bpm:form:create')")
+ public CommonResult createForm(@Valid @RequestBody BpmFormSaveReqVO createReqVO) {
+ return success(formService.createForm(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新动态表单")
+ @PreAuthorize("@ss.hasPermission('bpm:form:update')")
+ public CommonResult updateForm(@Valid @RequestBody BpmFormSaveReqVO updateReqVO) {
+ formService.updateForm(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除动态表单")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('bpm:form:delete')")
+ public CommonResult deleteForm(@RequestParam("id") Long id) {
+ formService.deleteForm(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得动态表单")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:form:query')")
+ public CommonResult getForm(@RequestParam("id") Long id) {
+ BpmFormDO form = formService.getForm(id);
+ return success(BeanUtils.toBean(form, BpmFormRespVO.class));
+ }
+
+ @GetMapping({"/list-all-simple", "/simple-list"})
+ @Operation(summary = "获得动态表单的精简列表", description = "用于表单下拉框")
+ public CommonResult> getFormSimpleList() {
+ List list = formService.getFormList();
+ return success(convertList(list, formDO -> // 只返回 id、name 字段
+ new BpmFormRespVO().setId(formDO.getId()).setName(formDO.getName())));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得动态表单分页")
+ @PreAuthorize("@ss.hasPermission('bpm:form:query')")
+ public CommonResult> getFormPage(@Valid BpmFormPageReqVO pageVO) {
+ PageResult pageResult = formService.getFormPage(pageVO);
+ return success(BeanUtils.toBean(pageResult, BpmFormRespVO.class));
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmModelController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmModelController.java
new file mode 100644
index 0000000..f787066
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmModelController.java
@@ -0,0 +1,200 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.*;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelUpdateReqVO;
+import com.zt.plat.module.bpm.convert.definition.BpmModelConvert;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmFormDO;
+import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
+import com.zt.plat.module.bpm.service.definition.BpmFormService;
+import com.zt.plat.module.bpm.service.definition.BpmModelService;
+import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
+import com.zt.plat.module.system.api.dept.DeptApi;
+import com.zt.plat.module.system.api.dept.dto.DeptRespDTO;
+import com.zt.plat.module.system.api.user.AdminUserApi;
+import com.zt.plat.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;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.Model;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.*;
+import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "管理后台 - 流程模型")
+@RestController
+@RequestMapping("/bpm/model")
+@Validated
+public class BpmModelController {
+
+ @Resource
+ private BpmModelService modelService;
+ @Resource
+ private BpmFormService formService;
+ @Resource
+ private BpmCategoryService categoryService;
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+
+ @GetMapping("/list")
+ @Operation(summary = "获得模型分页")
+ @Parameter(name = "name", description = "模型名称", example = "芋艿")
+ public CommonResult> getModelList(@RequestParam(value = "name", required = false) String name) {
+ List list = modelService.getModelList(name);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
+ }
+
+ // 获得 Form 表单
+ 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(list, Model::getCategory));
+ // 获得 Deployment Map
+ Map deploymentMap = processDefinitionService.getDeploymentMap(
+ convertSet(list, Model::getDeploymentId));
+ // 获得 ProcessDefinition Map
+ List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(
+ deploymentMap.keySet());
+ Map processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId);
+ // 获得 User Map、Dept 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);
+ Set deptIds = convertSetByFlatMap(list, model -> {
+ BpmModelMetaInfoVO metaInfo = BpmModelConvert.INSTANCE.parseMetaInfo(model);
+ return metaInfo != null && metaInfo.getStartDeptIds() != null ? metaInfo.getStartDeptIds().stream() : Stream.empty();
+ });
+ Map deptMap = deptApi.getDeptMap(deptIds);
+ return success(BpmModelConvert.INSTANCE.buildModelList(list,
+ formMap, categoryMap, deploymentMap, processDefinitionMap, userMap, deptMap));
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得模型")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:model:query')")
+ public CommonResult getModel(@RequestParam("id") String id) {
+ Model model = modelService.getModel(id);
+ if (model == null) {
+ return null;
+ }
+ byte[] bpmnBytes = modelService.getModelBpmnXML(id);
+ BpmSimpleModelNodeVO simpleModel = modelService.getSimpleModel(id);
+ return success(BpmModelConvert.INSTANCE.buildModel(model, bpmnBytes, simpleModel));
+ }
+
+ @PostMapping("/create")
+ @Operation(summary = "新建模型")
+ @PreAuthorize("@ss.hasPermission('bpm:model:create')")
+ 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 BpmModelSaveReqVO modelVO) {
+ modelService.updateModel(getLoginUserId(), modelVO);
+ return success(true);
+ }
+
+ @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")
+ @Operation(summary = "部署模型")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
+ public CommonResult deployModel(@RequestParam("id") String id) {
+ modelService.deployModel(getLoginUserId(), id);
+ return success(true);
+ }
+
+ @PutMapping("/update-state")
+ @Operation(summary = "修改模型的状态", description = "实际更新的部署的流程定义的状态")
+ @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+ public CommonResult updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
+ modelService.updateModelState(getLoginUserId(), reqVO.getId(), reqVO.getState());
+ return success(true);
+ }
+
+ @Deprecated
+ @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);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除模型")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:model:delete')")
+ public CommonResult deleteModel(@RequestParam("id") String id) {
+ modelService.deleteModel(getLoginUserId(), id);
+ return success(true);
+ }
+
+ @DeleteMapping("/clean")
+ @Operation(summary = "清理模型")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:model:clean')")
+ public CommonResult cleanModel(@RequestParam("id") String id) {
+ modelService.cleanModel(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));
+ }
+
+ @Deprecated
+ @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/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
new file mode 100644
index 0000000..e5ee29a
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
@@ -0,0 +1,133 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
+import com.zt.plat.module.bpm.convert.definition.BpmProcessDefinitionConvert;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmCategoryDO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmFormDO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
+import com.zt.plat.module.bpm.service.definition.BpmCategoryService;
+import com.zt.plat.module.bpm.service.definition.BpmFormService;
+import com.zt.plat.module.bpm.service.definition.BpmProcessDefinitionService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertSet;
+import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "管理后台 - 流程定义")
+@RestController
+@RequestMapping("/bpm/process-definition")
+@Validated
+public class BpmProcessDefinitionController {
+
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+ @Resource
+ private BpmFormService formService;
+ @Resource
+ private BpmCategoryService categoryService;
+
+ @GetMapping("/page")
+ @Operation(summary = "获得流程定义分页")
+ @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+ public CommonResult> getProcessDefinitionPage(
+ BpmProcessDefinitionPageReqVO pageReqVO) {
+ PageResult pageResult = processDefinitionService.getProcessDefinitionPage(pageReqVO);
+ if (CollUtil.isEmpty(pageResult.getList())) {
+ return success(PageResult.empty(pageResult.getTotal()));
+ }
+
+ // 获得 Category Map
+ Map categoryMap = categoryService.getCategoryMap(
+ convertSet(pageResult.getList(), ProcessDefinition::getCategory));
+ // 获得 Deployment Map
+ Map deploymentMap = processDefinitionService.getDeploymentMap(
+ convertSet(pageResult.getList(), ProcessDefinition::getDeploymentId));
+ // 获得 BpmProcessDefinitionInfoDO Map
+ Map processDefinitionMap = processDefinitionService.getProcessDefinitionInfoMap(
+ convertSet(pageResult.getList(), ProcessDefinition::getId));
+ // 获得 Form Map
+ Map formMap = formService.getFormMap(
+ convertSet(processDefinitionMap.values(), BpmProcessDefinitionInfoDO::getFormId));
+ return success(BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinitionPage(
+ pageResult, deploymentMap, processDefinitionMap, formMap, categoryMap));
+ }
+
+ @GetMapping ("/list")
+ @Operation(summary = "获得流程定义列表")
+ @Parameter(name = "suspensionState", description = "挂起状态", required = true, example = "1") // 参见 Flowable SuspensionState 枚举
+ public CommonResult> getProcessDefinitionList(
+ @RequestParam("suspensionState") Integer suspensionState) {
+ // 1.1 获得开启的流程定义
+ List list = processDefinitionService.getProcessDefinitionListBySuspensionState(suspensionState);
+ if (CollUtil.isEmpty(list)) {
+ return success(Collections.emptyList());
+ }
+ // 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));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获得流程定义精简列表", description = "只包含未挂起的流程,主要用于前端的下拉选项")
+ public CommonResult> getSimpleProcessDefinitionList() {
+ // 只查询未挂起的流程
+ List list = processDefinitionService.getProcessDefinitionListBySuspensionState(
+ SuspensionState.ACTIVE.getStateCode());
+ // 拼接 VO 返回,只返回 id、name、key
+ return success(convertList(list, definition -> new BpmProcessDefinitionRespVO()
+ .setId(definition.getId()).setName(definition.getName()).setKey(definition.getKey())));
+ }
+
+ @GetMapping ("/get")
+ @Operation(summary = "获得流程定义")
+ @Parameter(name = "id", description = "流程编号", required = true, example = "1024")
+ @Parameter(name = "key", description = "流程定义标识", required = true, example = "1024")
+ public CommonResult getProcessDefinition(
+ @RequestParam(value = "id", required = false) String id,
+ @RequestParam(value = "key", required = false) String key) {
+ ProcessDefinition processDefinition = id != null ? processDefinitionService.getProcessDefinition(id)
+ : processDefinitionService.getActiveProcessDefinition(key);
+ if (processDefinition == null) {
+ return success(null);
+ }
+ BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(processDefinition.getId());
+ BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
+ return success(BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinition(
+ processDefinition, null, processDefinitionInfo, null, null, bpmnModel));
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessExpressionController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessExpressionController.java
new file mode 100644
index 0000000..08fcb42
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessExpressionController.java
@@ -0,0 +1,73 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.expression.BpmProcessExpressionPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.expression.BpmProcessExpressionRespVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.expression.BpmProcessExpressionSaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessExpressionDO;
+import com.zt.plat.module.bpm.service.definition.BpmProcessExpressionService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - BPM 流程表达式")
+@RestController
+@RequestMapping("/bpm/process-expression")
+@Validated
+public class BpmProcessExpressionController {
+
+ @Resource
+ private BpmProcessExpressionService processExpressionService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建流程表达式")
+ @PreAuthorize("@ss.hasPermission('bpm:process-expression:create')")
+ public CommonResult createProcessExpression(@Valid @RequestBody BpmProcessExpressionSaveReqVO createReqVO) {
+ return success(processExpressionService.createProcessExpression(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新流程表达式")
+ @PreAuthorize("@ss.hasPermission('bpm:process-expression:update')")
+ public CommonResult updateProcessExpression(@Valid @RequestBody BpmProcessExpressionSaveReqVO updateReqVO) {
+ processExpressionService.updateProcessExpression(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除流程表达式")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('bpm:process-expression:delete')")
+ public CommonResult deleteProcessExpression(@RequestParam("id") Long id) {
+ processExpressionService.deleteProcessExpression(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得流程表达式")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:process-expression:query')")
+ public CommonResult getProcessExpression(@RequestParam("id") Long id) {
+ BpmProcessExpressionDO processExpression = processExpressionService.getProcessExpression(id);
+ return success(BeanUtils.toBean(processExpression, BpmProcessExpressionRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得流程表达式分页")
+ @PreAuthorize("@ss.hasPermission('bpm:process-expression:query')")
+ public CommonResult> getProcessExpressionPage(
+ @Valid BpmProcessExpressionPageReqVO pageReqVO) {
+ PageResult pageResult = processExpressionService.getProcessExpressionPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, BpmProcessExpressionRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessListenerController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessListenerController.java
new file mode 100644
index 0000000..3077a91
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmProcessListenerController.java
@@ -0,0 +1,73 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.listener.BpmProcessListenerPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.listener.BpmProcessListenerRespVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.listener.BpmProcessListenerSaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessListenerDO;
+import com.zt.plat.module.bpm.service.definition.BpmProcessListenerService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - BPM 流程监听器")
+@RestController
+@RequestMapping("/bpm/process-listener")
+@Validated
+public class BpmProcessListenerController {
+
+ @Resource
+ private BpmProcessListenerService processListenerService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建流程监听器")
+ @PreAuthorize("@ss.hasPermission('bpm:process-listener:create')")
+ public CommonResult createProcessListener(@Valid @RequestBody BpmProcessListenerSaveReqVO createReqVO) {
+ return success(processListenerService.createProcessListener(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新流程监听器")
+ @PreAuthorize("@ss.hasPermission('bpm:process-listener:update')")
+ public CommonResult updateProcessListener(@Valid @RequestBody BpmProcessListenerSaveReqVO updateReqVO) {
+ processListenerService.updateProcessListener(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除流程监听器")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('bpm:process-listener:delete')")
+ public CommonResult deleteProcessListener(@RequestParam("id") Long id) {
+ processListenerService.deleteProcessListener(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得流程监听器")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:process-listener:query')")
+ public CommonResult getProcessListener(@RequestParam("id") Long id) {
+ BpmProcessListenerDO processListener = processListenerService.getProcessListener(id);
+ return success(BeanUtils.toBean(processListener, BpmProcessListenerRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得流程监听器分页")
+ @PreAuthorize("@ss.hasPermission('bpm:process-listener:query')")
+ public CommonResult> getProcessListenerPage(
+ @Valid BpmProcessListenerPageReqVO pageReqVO) {
+ PageResult pageResult = processListenerService.getProcessListenerPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, BpmProcessListenerRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmUserGroupController.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmUserGroupController.java
new file mode 100644
index 0000000..226e5da
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/BpmUserGroupController.java
@@ -0,0 +1,83 @@
+package com.zt.plat.module.bpm.controller.admin.definition;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.group.BpmUserGroupSaveReqVO;
+import com.zt.plat.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
+import com.zt.plat.module.bpm.service.definition.BpmUserGroupService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
+
+@Tag(name = "管理后台 - 用户组")
+@RestController
+@RequestMapping("/bpm/user-group")
+@Validated
+public class BpmUserGroupController {
+
+ @Resource
+ private BpmUserGroupService userGroupService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建用户组")
+ @PreAuthorize("@ss.hasPermission('bpm:user-group:create')")
+ public CommonResult createUserGroup(@Valid @RequestBody BpmUserGroupSaveReqVO createReqVO) {
+ return success(userGroupService.createUserGroup(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新用户组")
+ @PreAuthorize("@ss.hasPermission('bpm:user-group:update')")
+ public CommonResult updateUserGroup(@Valid @RequestBody BpmUserGroupSaveReqVO updateReqVO) {
+ userGroupService.updateUserGroup(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除用户组")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('bpm:user-group:delete')")
+ public CommonResult deleteUserGroup(@RequestParam("id") Long id) {
+ userGroupService.deleteUserGroup(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得用户组")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('bpm:user-group:query')")
+ public CommonResult getUserGroup(@RequestParam("id") Long id) {
+ BpmUserGroupDO userGroup = userGroupService.getUserGroup(id);
+ return success(BeanUtils.toBean(userGroup, BpmUserGroupRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得用户组分页")
+ @PreAuthorize("@ss.hasPermission('bpm:user-group:query')")
+ public CommonResult> getUserGroupPage(@Valid BpmUserGroupPageReqVO pageVO) {
+ PageResult pageResult = userGroupService.getUserGroupPage(pageVO);
+ return success(BeanUtils.toBean(pageResult, BpmUserGroupRespVO.class));
+ }
+
+ @GetMapping("/simple-list")
+ @Operation(summary = "获取用户组精简信息列表", description = "只包含被开启的用户组,主要用于前端的下拉选项")
+ public CommonResult> getUserGroupSimpleList() {
+ List list = userGroupService.getUserGroupListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ return success(convertList(list, group -> new BpmUserGroupRespVO().setId(group.getId()).setName(group.getName())));
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryPageReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryPageReqVO.java
new file mode 100644
index 0000000..5de14e2
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryPageReqVO.java
@@ -0,0 +1,32 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.category;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.PageParam;
+import com.zt.plat.framework.common.validation.InEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - BPM 流程分类分页 Request VO")
+@Data
+public class BpmCategoryPageReqVO extends PageParam {
+
+ @Schema(description = "分类名", example = "王五")
+ private String name;
+
+ @Schema(description = "分类标志", example = "OA")
+ private String code;
+
+ @Schema(description = "分类状态", example = "1")
+ @InEnum(CommonStatusEnum.class)
+ private Integer status;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryRespVO.java
new file mode 100644
index 0000000..5f3db13
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategoryRespVO.java
@@ -0,0 +1,33 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.category;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - BPM 流程分类 Response VO")
+@Data
+public class BpmCategoryRespVO {
+
+ @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
+ private Long id;
+
+ @Schema(description = "分类名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+ private String name;
+
+ @Schema(description = "分类标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "OA")
+ private String code;
+
+ @Schema(description = "分类描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
+ private String description;
+
+ @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer status;
+
+ @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Integer sort;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategorySaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategorySaveReqVO.java
new file mode 100644
index 0000000..0203453
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/category/BpmCategorySaveReqVO.java
@@ -0,0 +1,37 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.category;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.validation.InEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - BPM 流程分类新增/修改 Request VO")
+@Data
+public class BpmCategorySaveReqVO {
+
+ @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
+ private Long id;
+
+ @Schema(description = "分类名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+ @NotEmpty(message = "分类名不能为空")
+ private String name;
+
+ @Schema(description = "分类描述", example = "你猜")
+ private String description;
+
+ @Schema(description = "分类标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "OA")
+ @NotEmpty(message = "分类标志不能为空")
+ private String code;
+
+ @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "分类状态不能为空")
+ @InEnum(CommonStatusEnum.class)
+ private Integer status;
+
+ @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "分类排序不能为空")
+ private Integer sort;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionPageReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionPageReqVO.java
new file mode 100644
index 0000000..1d3bbed
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionPageReqVO.java
@@ -0,0 +1,33 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.expression;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.PageParam;
+import com.zt.plat.framework.common.validation.InEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - BPM 流程表达式分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BpmProcessExpressionPageReqVO extends PageParam {
+
+ @Schema(description = "表达式名字", example = "李四")
+ private String name;
+
+ @Schema(description = "表达式状态", example = "1")
+ @InEnum(CommonStatusEnum.class)
+ private Integer status;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java
new file mode 100644
index 0000000..2bb959b
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java
@@ -0,0 +1,30 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.expression;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - BPM 流程表达式 Response VO")
+@Data
+public class BpmProcessExpressionRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3870")
+ @ExcelProperty("编号")
+ private Long id;
+
+ @Schema(description = "表达式名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+ @ExcelProperty("表达式名字")
+ private String name;
+
+ @Schema(description = "表达式状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer status;
+
+ @Schema(description = "表达式", requiredMode = Schema.RequiredMode.REQUIRED)
+ private String expression;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionSaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionSaveReqVO.java
new file mode 100644
index 0000000..a5771d1
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionSaveReqVO.java
@@ -0,0 +1,27 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.expression;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - BPM 流程表达式新增/修改 Request VO")
+@Data
+public class BpmProcessExpressionSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3870")
+ private Long id;
+
+ @Schema(description = "表达式名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+ @NotEmpty(message = "表达式名字不能为空")
+ private String name;
+
+ @Schema(description = "表达式状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "表达式状态不能为空")
+ private Integer status;
+
+ @Schema(description = "表达式", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "表达式不能为空")
+ private String expression;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormFieldVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormFieldVO.java
new file mode 100644
index 0000000..53af985
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormFieldVO.java
@@ -0,0 +1,24 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.form;
+
+import lombok.Data;
+
+/**
+ * 流程表单字段 VO
+ */
+@Data
+public class BpmFormFieldVO {
+
+ /**
+ * 字段类型
+ */
+ private String type;
+ /**
+ * 字段标识
+ */
+ private String field;
+ /**
+ * 字段标题
+ */
+ private String title;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java
new file mode 100644
index 0000000..437f67c
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java
@@ -0,0 +1,14 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.form;
+
+import com.zt.plat.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 动态表单分页 Request VO")
+@Data
+public class BpmFormPageReqVO extends PageParam {
+
+ @Schema(description = "表单名称", example = "芋道")
+ private String name;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java
new file mode 100644
index 0000000..42295df
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java
@@ -0,0 +1,39 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 动态表单 Response VO")
+@Data
+public class BpmFormRespVO {
+
+ @Schema(description = "表单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "表单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ @NotNull(message = "表单名称不能为空")
+ private String name;
+
+ @Schema(description = "表单的配置-JSON 字符串", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "表单的配置不能为空")
+ private String conf;
+
+ @Schema(description = "表单项的数组-JSON 字符串的数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "表单项的数组不能为空")
+ private List fields;
+
+ @Schema(description = "表单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "表单状态不能为空")
+ private Integer status; // 参见 CommonStatusEnum 枚举
+
+ @Schema(description = "备注", example = "我是备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormSaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormSaveReqVO.java
new file mode 100644
index 0000000..faa420b
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/form/BpmFormSaveReqVO.java
@@ -0,0 +1,35 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 动态表单创建/更新 Request VO")
+@Data
+public class BpmFormSaveReqVO {
+
+ @Schema(description = "表单编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "表单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ @NotNull(message = "表单名称不能为空")
+ private String name;
+
+ @Schema(description = "表单的配置-JSON 字符串", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "表单的配置不能为空")
+ private String conf;
+
+ @Schema(description = "表单项的数组-JSON 字符串的数组", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "表单项的数组不能为空")
+ private List fields;
+
+ @Schema(description = "表单状态-参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "表单状态不能为空")
+ private Integer status;
+
+ @Schema(description = "备注", example = "我是备注")
+ private String remark;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java
new file mode 100644
index 0000000..a146e35
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java
@@ -0,0 +1,28 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.group;
+
+import com.zt.plat.framework.common.pojo.PageParam;
+import com.zt.plat.framework.common.util.date.DateUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 用户组分页 Request VO")
+@Data
+public class BpmUserGroupPageReqVO extends PageParam {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "组名", example = "芋道")
+ private String name;
+
+ @Schema(description = "状态", example = "1")
+ private Integer status;
+
+ @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ @Schema(description = "创建时间")
+ private LocalDateTime[] createTime;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java
new file mode 100644
index 0000000..b356351
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.group;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Set;
+
+@Schema(description = "管理后台 - 用户组 Response VO")
+@Data
+public class BpmUserGroupRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
+
+ @Schema(description = "组名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ private String name;
+
+ @Schema(description = "描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
+ private String description;
+
+ @Schema(description = "成员编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
+ private Set userIds;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer status;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSaveReqVO.java
new file mode 100644
index 0000000..ce2c7d9
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSaveReqVO.java
@@ -0,0 +1,31 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.group;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.Set;
+
+@Schema(description = "管理后台 - 用户组创建/修改 Request VO")
+@Data
+public class BpmUserGroupSaveReqVO {
+
+ @Schema(description = "编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "组名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ @NotNull(message = "组名不能为空")
+ private String name;
+
+ @Schema(description = "描述", example = "芋道源码")
+ private String description;
+
+ @Schema(description = "成员编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
+ @NotNull(message = "成员编号数组不能为空")
+ private Set userIds;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerPageReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerPageReqVO.java
new file mode 100644
index 0000000..13b8a73
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerPageReqVO.java
@@ -0,0 +1,30 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.listener;
+
+import com.zt.plat.framework.common.enums.CommonStatusEnum;
+import com.zt.plat.framework.common.pojo.PageParam;
+import com.zt.plat.framework.common.validation.InEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - BPM 流程监听器分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BpmProcessListenerPageReqVO extends PageParam {
+
+ @Schema(description = "监听器名字", example = "赵六")
+ private String name;
+
+ @Schema(description = "监听器类型", example = "execution")
+ private String type;
+
+ @Schema(description = "监听事件", example = "start")
+ private String event;
+
+ @Schema(description = "状态", example = "1")
+ @InEnum(CommonStatusEnum.class)
+ private Integer status;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerRespVO.java
new file mode 100644
index 0000000..7bfdde8
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerRespVO.java
@@ -0,0 +1,36 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.listener;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - BPM 流程监听器 Response VO")
+@Data
+public class BpmProcessListenerRespVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13089")
+ private Long id;
+
+ @Schema(description = "监听器名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+ private String name;
+
+ @Schema(description = "监听器类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "execution")
+ private String type;
+
+ @Schema(description = "监听器状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer status;
+
+ @Schema(description = "监听事件", requiredMode = Schema.RequiredMode.REQUIRED, example = "start")
+ private String event;
+
+ @Schema(description = "监听器值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "class")
+ private String valueType;
+
+ @Schema(description = "监听器值", requiredMode = Schema.RequiredMode.REQUIRED)
+ private String value;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerSaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerSaveReqVO.java
new file mode 100644
index 0000000..908caa9
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerSaveReqVO.java
@@ -0,0 +1,39 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.listener;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - BPM 流程监听器新增/修改 Request VO")
+@Data
+public class BpmProcessListenerSaveReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13089")
+ private Long id;
+
+ @Schema(description = "监听器名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+ @NotEmpty(message = "监听器名字不能为空")
+ private String name;
+
+ @Schema(description = "监听器类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "execution")
+ @NotEmpty(message = "监听器类型不能为空")
+ private String type;
+
+ @Schema(description = "监听器状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "监听器状态不能为空")
+ private Integer status;
+
+ @Schema(description = "监听事件", requiredMode = Schema.RequiredMode.REQUIRED, example = "start")
+ @NotEmpty(message = "监听事件不能为空")
+ private String event;
+
+ @Schema(description = "监听器值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "class")
+ @NotEmpty(message = "监听器值类型不能为空")
+ private String valueType;
+
+ @Schema(description = "监听器值", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "监听器值不能为空")
+ private String value;
+
+}
\ No newline at end of file
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java
new file mode 100644
index 0000000..03e0e5f
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java
@@ -0,0 +1,19 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+
+@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/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
new file mode 100644
index 0000000..cabc1fd
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
@@ -0,0 +1,180 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model;
+
+import com.zt.plat.framework.common.core.KeyValue;
+import com.zt.plat.framework.common.validation.InEnum;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
+import com.zt.plat.module.bpm.enums.definition.BpmAutoApproveTypeEnum;
+import com.zt.plat.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import com.zt.plat.module.bpm.enums.definition.BpmModelTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.URL;
+
+import java.util.List;
+
+/**
+ * BPM 流程 MetaInfo Response DTO
+ * 主要用于 { Model#setMetaInfo(String)} 的存储
+ *
+ * 最终,它的字段和
+ * {@link com.zt.plat.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO}
+ * 是一致的
+ *
+ * @author ZT
+ */
+@Data
+public class BpmModelMetaInfoVO {
+
+ @Schema(description = "流程图标", example = "https://www.iocoder.cn/zt.jpg")
+ @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 = "可发起部门编号数组", example = "[2,4,6]")
+ private List startDeptIds;
+
+ @Schema(description = "可管理用户编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2,4,6]")
+ @NotEmpty(message = "可管理用户编号数组不能为空")
+ private List managerUserIds;
+
+ @Schema(description = "排序", example = "1")
+ private Long sort; // 创建时,后端自动生成
+
+ @Schema(description = "允许撤销审批中的申请", example = "true")
+ private Boolean allowCancelRunningProcess;
+
+ @Schema(description = "流程 ID 规则", example = "{}")
+ private ProcessIdRule processIdRule;
+
+ @Schema(description = "自动去重类型", example = "1")
+ @InEnum(BpmAutoApproveTypeEnum.class)
+ private Integer autoApprovalType;
+
+ @Schema(description = "标题设置", example = "{}")
+ private TitleSetting titleSetting;
+
+ @Schema(description = "摘要设置", example = "{}")
+ private SummarySetting summarySetting;
+
+ @Schema(description = "流程前置通知设置", example = "{}")
+ private HttpRequestSetting processBeforeTriggerSetting;
+
+ @Schema(description = "流程后置通知设置", example = "{}")
+ private HttpRequestSetting processAfterTriggerSetting;
+
+ @Schema(description = "任务前置通知设置", example = "{}")
+ private HttpRequestSetting taskBeforeTriggerSetting;
+
+ @Schema(description = "任务后置通知设置", example = "{}")
+ private HttpRequestSetting taskAfterTriggerSetting;
+
+ @Schema(description = "流程 ID 规则")
+ @Data
+ @Valid
+ public static class ProcessIdRule {
+
+ @Schema(description = "是否启用", example = "false")
+ @NotNull(message = "是否启用不能为空")
+ private Boolean enable;
+
+ @Schema(description = "前缀", example = "XX")
+ private String prefix;
+
+ @Schema(description = "中缀", example = "20250120")
+ private String infix; // 精确到日、精确到时、精确到分、精确到秒
+
+ @Schema(description = "后缀", example = "YY")
+ private String postfix;
+
+ @Schema(description = "序列长度", example = "5")
+ @NotNull(message = "序列长度不能为空")
+ private Integer length;
+
+ }
+
+ @Schema(description = "标题设置")
+ @Data
+ @Valid
+ public static class TitleSetting {
+
+ @Schema(description = "是否自定义", example = "false")
+ @NotNull(message = "是否自定义不能为空")
+ private Boolean enable;
+
+ @Schema(description = "标题", example = "流程标题")
+ private String title;
+
+ }
+
+ @Schema(description = "摘要设置")
+ @Data
+ @Valid
+ public static class SummarySetting {
+
+ @Schema(description = "是否自定义", example = "false")
+ @NotNull(message = "是否自定义不能为空")
+ private Boolean enable;
+
+ @Schema(description = "摘要字段数组", example = "[]")
+ private List summary;
+
+ }
+
+ @Schema(description = "http 请求通知设置", example = "{}")
+ @Data
+ public static class HttpRequestSetting {
+
+ @Schema(description = "请求路径", example = "http://127.0.0.1")
+ @NotEmpty(message = "请求 URL 不能为空")
+ @URL(message = "请求 URL 格式不正确")
+ private String url;
+
+ @Schema(description = "请求头参数设置", example = "[]")
+ @Valid
+ private List header;
+
+ @Schema(description = "请求头参数设置", example = "[]")
+ @Valid
+ private List body;
+
+ /**
+ * 请求返回处理设置,用于修改流程表单值
+ *
+ * key:表示要修改的流程表单字段名(name)
+ * value:接口返回的字段名
+ */
+ @Schema(description = "请求返回处理设置", example = "[]")
+ private List> response;
+
+ }
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
new file mode 100644
index 0000000..12d6ac1
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
@@ -0,0 +1,57 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model;
+
+import com.zt.plat.module.bpm.controller.admin.base.dept.DeptSimpleBaseVO;
+import com.zt.plat.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
+import com.zt.plat.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 extends BpmModelMetaInfoVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private String id;
+
+ @Schema(description = "流程标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "process_zt")
+ private String key;
+
+ @Schema(description = "流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ private String name;
+
+ @Schema(description = "流程图标", example = "https://www.iocoder.cn/zt.jpg")
+ private String icon;
+
+ @Schema(description = "流程分类编号", example = "1")
+ private String category;
+ @Schema(description = "流程分类名字", example = "请假")
+ private String categoryName;
+
+ @Schema(description = "表单名字", example = "请假表单")
+ private String formName;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime createTime;
+
+ @Schema(description = "可发起的用户数组")
+ private List startUsers;
+
+ @Schema(description = "可发起的部门数组")
+ private List startDepts;
+
+ @Schema(description = "BPMN XML")
+ private String bpmnXml;
+
+ @Schema(description = "仿钉钉流程设计模型对象")
+ private BpmSimpleModelNodeVO simpleModel;
+
+ /**
+ * 最新部署的流程定义
+ */
+ private BpmProcessDefinitionRespVO processDefinition;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java
new file mode 100644
index 0000000..279519c
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java
@@ -0,0 +1,34 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model;
+
+import com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+
+@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_zt")
+ @NotEmpty(message = "流程标识不能为空")
+ private String key;
+
+ @Schema(description = "流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
+ @NotEmpty(message = "流程名称不能为空")
+ private String name;
+
+ @Schema(description = "流程分类", example = "1")
+ private String category;
+
+ @Schema(description = "BPMN XML")
+ private String bpmnXml;
+
+ @Schema(description = "仿钉钉流程设计模型对象")
+ @Valid
+ private BpmSimpleModelNodeVO simpleModel;
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java
new file mode 100644
index 0000000..cd7fea1
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java
@@ -0,0 +1,19 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 流程模型更新状态 Request VO")
+@Data
+public class BpmModelUpdateStateReqVO {
+
+ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "编号不能为空")
+ private String id;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "状态不能为空")
+ private Integer state; // 参见 Flowable SuspensionState 枚举
+
+}
diff --git a/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
new file mode 100644
index 0000000..8dc222c
--- /dev/null
+++ b/zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
@@ -0,0 +1,526 @@
+package com.zt.plat.module.bpm.controller.admin.definition.vo.model.simple;
+
+import com.zt.plat.framework.common.core.KeyValue;
+import com.zt.plat.framework.common.validation.InEnum;
+import com.zt.plat.module.bpm.enums.definition.*;
+import com.zt.plat.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.flowable.bpmn.model.IOParameter;
+import org.hibernate.validator.constraints.URL;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@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(BpmSimpleModelNodeTypeEnum.class)
+ private Integer type;
+
+ @Schema(description = "模型节点名称", example = "领导审批")
+ private String name;
+
+ @Schema(description = "节点展示内容", example = "指定成员: 芋道源码")
+ private String showText;
+
+ @Schema(description = "子节点")
+ private BpmSimpleModelNodeVO childNode; // 补充说明:在该模型下,子节点有且仅有一个,不会有多个
+
+ @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