Merge remote-tracking branch 'origin/master' into feature/countersign_ext

# Conflicts:
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java
#	workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/TestController.java
This commit is contained in:
wangli 2025-10-23 09:56:09 +08:00
commit c7bff3bf34
77 changed files with 1903 additions and 677 deletions

View File

@ -32,6 +32,7 @@
<easy-es.version>2.0.0</easy-es.version>
<xxl-job.version>2.5.0</xxl-job.version>
<workflow-engine-common.version>0.0.1-SNAPSHOT</workflow-engine-common.version>
<adapter.version>2.0.1-SNAPSHOT</adapter.version>
</properties>
<dependencyManagement>
@ -179,6 +180,11 @@
<artifactId>doc-api</artifactId>
<version>${axzo-dependencies.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>adapter</artifactId>
<version>${adapter.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -3,16 +3,17 @@ package cn.axzo.workflow.client.feign.manage;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FromDataSearchDTO;
import cn.axzo.workflow.common.model.request.form.model.WpsFileConfigVariableDTO;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormDataVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -69,4 +70,14 @@ public interface FormAdminApi {
@PostMapping("/api/form/admin/instance/form/data")
@InvokeMode(SYNC)
CommonResponse<List<FormDataVO>> getFormData(@Validated @RequestBody FromDataSearchDTO dto);
/**
* 获取 WPS 文档中所有可配置的流程相关变量
*
* @param dto
* @return
*/
@PostMapping("/api/form/admin/wps/file/config/variables")
@InvokeMode(SYNC)
CommonResponse<List<PrintFieldDTO>> getWpsFileConfigVariables(@Validated @RequestBody WpsFileConfigVariableDTO dto);
}

View File

@ -0,0 +1,50 @@
package cn.axzo.workflow.client.feign.manage;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.enums.AdminDataSource;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
/**
* 一些功能性 API
*
* @author wangli
* @since 2025-09-02 14:40
*/
@WorkflowEngineFeignClient
public interface FunctionApi {
@Operation(summary = "获取指定枚举类型的枚举值信息")
@GetMapping("/api/function/enum/admin-data-source/get")
@Manageable
@InvokeMode(SYNC)
CommonResponse<AdminDataSource> getAdminDataSourceEnum(@RequestParam String enumValue);
@Operation(summary = "获取指定枚举类型的枚举值信息")
@GetMapping("/api/function/enum/process-instance-result/get")
@Manageable
@InvokeMode(SYNC)
CommonResponse<BpmnProcessInstanceResultEnum> getFileTypeEnum(@RequestParam String enumValue);
/**
* 用于 Starter 检测必接事件的告警
*
* @param dto
* @return
*/
@Operation(summary = "发送钉钉消息")
@PostMapping("/api/function/dingtalk/alter")
@InvokeMode(SYNC)
CommonResponse<Boolean> sendDingtalk(@Validated @RequestBody DingTalkStarterAlterDTO dto);
}

View File

@ -72,5 +72,6 @@ public interface PrintAdminApi {
@GetMapping("/api/print/admin/field/variables")
@Manageable
@InvokeMode(SYNC)
CommonResponse<Map<String, Object>> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);
CommonResponse<Map<String, Object>> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId,
@RequestParam(required = false, defaultValue = "true") Boolean throwException);
}

View File

@ -1,11 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum AdminDataSource {
SYSTEM_ENTRY("systemEntry", "系统录入"),
USER_ENTRY("userEntry", "用户手动录入");
USER_ENTRY("userEntry", "用户手动录入"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知"),
;
private final String type;
private final String desc;
@ -14,4 +21,15 @@ public enum AdminDataSource {
this.type = type;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AdminDataSource fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(AdminDataSource.values())
.filter(v -> v.getType().equalsIgnoreCase(value) || v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,13 +1,19 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum AdminRoleType {
ORGANIZATION_ADMIN("organizationAdmin", "单位超管"),
ORG_WORKSPACE_ADMIN("organizationWorkspaceAdmin", "项目内单位负责人"),
WORKSPACE_ADMIN("workspaceAdmin", "项目超管"),
OTHER("other", "其他用户");
OTHER("other", "其他用户"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知");
private final String type;
private final String desc;
@ -16,4 +22,15 @@ public enum AdminRoleType {
this.type = type;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AdminRoleType fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(AdminRoleType.values())
.filter(v -> v.getType().equalsIgnoreCase(value) || v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,14 +1,21 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 审批管理员类型
*/
@Getter
public enum AdminTypeEnum {
SUPER_ADMIN("super_admin", "超级管理员"),
COMMON_ADMIN("common_admin", "普通管理员");
COMMON_ADMIN("common_admin", "普通管理员"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知"),
;
private final String type;
private final String desc;
@ -17,4 +24,15 @@ public enum AdminTypeEnum {
this.type = type;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AdminTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(AdminTypeEnum.values())
.filter(v -> v.getType().equalsIgnoreCase(value) || v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 审批方式枚举
@ -9,6 +12,7 @@ import java.util.Objects;
* @author wangli
* @since 2023/11/16 10:10
*/
@Getter
public enum ApprovalMethodEnum {
human("human", "人工审批", ""),
@ -19,12 +23,12 @@ public enum ApprovalMethodEnum {
nobody("nobody", "不设置审批人", "[仅业务节点可能有该值]"),
bizSpecify("bizSpecify", "业务指定审批人", "[仅业务节点可能有该值]"),
transferToAdmin("transferToAdmin", "转办给管理员", "该枚举仅日志处理使用"),
unknown("unknown", "未知", "兜底")
;
@JsonEnumDefaultValue
unknown("unknown", "未知", "兜底");
private String type;
private String desc;
private String remark;
private final String type;
private final String desc;
private final String remark;
ApprovalMethodEnum(String type, String desc, String remark) {
this.type = type;
@ -32,34 +36,18 @@ public enum ApprovalMethodEnum {
this.remark = remark;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApprovalMethodEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
public static ApprovalMethodEnum valueOfType(String type) {
return Arrays.stream(ApprovalMethodEnum.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
return fromValue(type);
}
}

View File

@ -1,17 +1,26 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 审批人为空时的处理方式枚举
*
* @author wangli
* @since 2023/11/16 10:22
*/
@Getter
public enum ApproverEmptyHandleTypeEnum {
autoPassed("autoPassed", "自动通过"),
autoRejection("autoRejection", "自动驳回"),
autoSkipped("autoSkipped", "自动跳过"),
transferToAdmin("transferToAdmin", "转交给管理员"),
specifyAssignee("specifyAssignee", "指定审批人"),
@JsonEnumDefaultValue
unknown("unknown", "未知"),
;
private String type;
private String desc;
@ -21,19 +30,15 @@ public enum ApproverEmptyHandleTypeEnum {
this.desc = desc;
}
public String getType() {
return type;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApproverEmptyHandleTypeEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@ -1,5 +1,9 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
@ -9,12 +13,15 @@ import java.util.Objects;
* @author wangli
* @since 2023/11/16 10:14
*/
@Getter
public enum ApproverScopeEnum {
entWorkspace("entWorkspace", "企业工作台", "entWorkspaceProcessor"),
govWorkspace("govWorkspace", "政务工作台", "govWorkspaceProcessor"),
projectWorkspace("projectWorkspace", "项目工作台","projectWorkspaceProcessor"),
preTaskUser("preTaskUser", "上节点审批人所在单位","preTaskUserProcessor"),
preTaskSpecified("preTaskSpecified", "上节点审批人指定","preTaskUserProcessor"),
projectWorkspace("projectWorkspace", "项目工作台", "projectWorkspaceProcessor"),
preTaskUser("preTaskUser", "上节点审批人所在单位", "preTaskUserProcessor"),
preTaskSpecified("preTaskSpecified", "上节点审批人指定", "preTaskUserProcessor"),
@JsonEnumDefaultValue
unknown("unknown", "未知", "unknownProcessor"),
;
private final String type;
private final String desc;
@ -26,20 +33,15 @@ public enum ApproverScopeEnum {
this.processor = processor;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public String getProcessor() {
return processor;
}
public boolean selectWorkspace() {
return this == ApproverScopeEnum.projectWorkspace;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApprovalMethodEnum fromValue(String value) {
if (value == null) {
return ApprovalMethodEnum.unknown;
}
return Arrays.stream(ApprovalMethodEnum.values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(ApprovalMethodEnum.unknown);
}
public static ApproverScopeEnum valueOfProcessor(String processor) {

View File

@ -1,11 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 审批人指定枚举
*
* @author wangli
* @since 2023/11/16 10:16
*/
@Getter
public enum ApproverSpecifyEnum {
position("position", "指定岗位", 1),
@ -28,11 +35,13 @@ public enum ApproverSpecifyEnum {
initiatorLeader_v2("initiatorLeader_v2", "发起人主管", 2),
fixedPerson_v2("fixedPerson_v2", "固定人员", 2),
preAllNodeApprover_v2("preAllNodeApprover_v2", "所有前序节点审批人", 2),
@JsonEnumDefaultValue
unknown("unknown", "未知", 1),
;
private String type;
private String desc;
private Integer version;
private final String type;
private final String desc;
private final Integer version;
ApproverSpecifyEnum(String type, String desc, Integer version) {
this.type = type;
@ -40,27 +49,14 @@ public enum ApproverSpecifyEnum {
this.version = version;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApproverSpecifyEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,11 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 审批人指定的二次范围限定枚举
*
* @author wangli
* @since 2025-08-13 14:32
*/
@Getter
public enum ApproverSpecifyRangeEnum {
within_the_project("within_the_project", "项目内岗位"),
@ -13,29 +20,26 @@ public enum ApproverSpecifyRangeEnum {
specified_org("specified_org", "审批单指定的末级组织"),
initiator("initiator", "审批单发起人"),
pre_node_approver("pre_node_approver", "上节点审批人"),
@JsonEnumDefaultValue
unknown("unknown", "未知"),
;
private String type;
private String desc;
private final String type;
private final String desc;
ApproverSpecifyRangeEnum(String type, String desc) {
this.type = type;
this.desc = desc;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApproverSpecifyRangeEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,11 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 审批人指定的范围单位枚举
*
* @author wangli
* @since 2025-08-13 15:05
*/
@Getter
public enum ApproverSpecifyRangeUnitEnum {
in_project("in_project", "项目内", null),
in_ent("in_ent", "企业内", null),
@ -14,8 +21,8 @@ public enum ApproverSpecifyRangeUnitEnum {
in_group_lv_3("in_group_lv_3", "集团岗位,上三级", 3),
in_group_lv_4("in_group_lv_4", "集团岗位,上四级", 4),
in_group_lv_top("in_group_lv_top", "集团岗位,总公司", Integer.MAX_VALUE),
UNKNOWN("UNKNOWN", "未知范围", null)
;
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知范围", null);
private final String type;
private final String desc;
private final Integer value;
@ -26,15 +33,14 @@ public enum ApproverSpecifyRangeUnitEnum {
this.value = value;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public Integer getValue() {
return value;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ApproverSpecifyRangeUnitEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,39 +1,43 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 附件类型枚举
*
* @author wangli
* @since 2023/11/22 23:19
*/
@Getter
public enum AttachmentTypeEnum {
image("image", "图片"),
file("file", "文件"),
signature("signature", "签名"),
@JsonEnumDefaultValue
unknown("unknown", "未知"),
;
private String type;
private String desc;
private final String type;
private final String desc;
AttachmentTypeEnum(String type, String desc) {
this.type = type;
this.desc = desc;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AttachmentTypeEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import org.springframework.util.StringUtils;
import java.util.Arrays;
/**
* 自动过审参数
@ -11,7 +14,10 @@ import org.springframework.util.StringUtils;
public enum AutoApprovalTypeEnum {
NO_AUTO_APPROVAL("noAutoApproval", "不自动过审"),
CONTINUOUS_NODES_AUTO_APPROVAL("continuousNodesAutoApproval", "连续节点自动过审");
CONTINUOUS_NODES_AUTO_APPROVAL("continuousNodesAutoApproval", "连续节点自动过审"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知"),
;
private final String type;
private final String desc;
@ -22,14 +28,17 @@ public enum AutoApprovalTypeEnum {
}
public static AutoApprovalTypeEnum fromType(String type) {
if (!StringUtils.hasText(type)) {
return null;
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static AutoApprovalTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
for (AutoApprovalTypeEnum typeEnum : AutoApprovalTypeEnum.values()) {
if (typeEnum.type.equals(type)) {
return typeEnum;
}
}
return null;
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,8 +1,12 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import com.google.common.collect.Lists;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import static cn.axzo.workflow.common.enums.BusinessTypeEnum.APPROVAL;
@ -14,6 +18,7 @@ import static cn.axzo.workflow.common.enums.BusinessTypeEnum.SIGN;
* @author wangli
* @since 2023/9/4 10:38
*/
@Getter
public enum BpmnButtonEnum {
/**
* 同意按钮
@ -66,24 +71,13 @@ public enum BpmnButtonEnum {
/**
* 管理员转交按钮
*/
BPMN_ADMIN_TRANSFER(90, "BPMN_ADMIN_TRANSFER", "管理员转交", Lists.newArrayList());
public int getOrder() {
return order;
}
public String getBtnKey() {
return btnKey;
}
public String getBtnName() {
return btnName;
}
public List<BusinessTypeEnum> getSupportBizType() {
return supportBizType;
}
BPMN_ADMIN_TRANSFER(90, "BPMN_ADMIN_TRANSFER", "管理员转交", Lists.newArrayList()),
/**
* 兜底
*/
@JsonEnumDefaultValue
UNKNOWN(99, "UNKNOWN", "未知", Lists.newArrayList()),
;
private final int order;
private final String btnKey;
@ -98,4 +92,15 @@ public enum BpmnButtonEnum {
this.supportBizType = supportBizType;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnButtonEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getBtnKey().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,12 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
/**
* 加签类型
*
* @author zuoqinbo
*/
@Getter
public enum BpmnCountersignTypeEnum {
/**
* 向前加签
@ -20,6 +26,11 @@ public enum BpmnCountersignTypeEnum {
* 共享加签
*/
SHARE_COUNTERSIGN("SHARE_COUNTERSIGN", "共享加签"),
/**
* 兜底
*/
@JsonEnumDefaultValue
UNKNOW("UNKNOW", "未知"),
;
private final String type;
@ -30,14 +41,6 @@ public enum BpmnCountersignTypeEnum {
this.desc = desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public static BpmnCountersignTypeEnum valueOfType(String countersignType) {
if (StringUtils.isBlank(countersignType)) {
return null;
@ -50,4 +53,15 @@ public enum BpmnCountersignTypeEnum {
}
return null;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnCountersignTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOW;
}
return Arrays.stream(values())
.filter(v -> v.getType().equalsIgnoreCase(value) || v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOW);
}
}

View File

@ -1,49 +1,43 @@
package cn.axzo.workflow.common.enums;
import java.util.Arrays;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum BpmnFlowNodeMode {
GENERAL("GENERAL", "普通节点"),
OR("OR", "或签节点"),
AND("AND", "会签节点"),
SEQUENCE("SEQUENCE", "顺序节点"),
EXCEPTIONAL("EXCEPTIONAL", "异常"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
private String type;
private String desc;
private final String type;
private final String desc;
BpmnFlowNodeMode(String type, String desc) {
this.type = type;
this.desc = desc;
}
public boolean isEqual(String type) {
return this.type.equals(type);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static BpmnFlowNodeMode valueOfType(String type) {
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnFlowNodeMode fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(BpmnFlowNodeMode.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,11 +1,14 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.Objects;
@Getter
public enum BpmnFlowNodeType {
//0 发起人 1审批 2抄送 3条件 4路由
@ -25,53 +28,33 @@ public enum BpmnFlowNodeType {
NODE_ALTER("NODE_ALTER", "告警节点"),
NODE_CANCEL("NODE_CANCEL", "撤回节点"),
NODE_EMPTY("NODE_EMPTY", "空节点"),
;
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知");
private String type;
private String desc;
private final String type;
private final String desc;
BpmnFlowNodeType(String type, String desc) {
this.type = type;
this.desc = desc;
}
public boolean isEqual(String type) {
return this.type.equals(type);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static BpmnFlowNodeType getByType(String type) {
if (!StringUtils.hasText(type)) {
return null;
}
BpmnFlowNodeType[] values = BpmnFlowNodeType.values();
for (BpmnFlowNodeType value : values) {
if (value.getType().equals(type)) {
return value;
}
}
return null;
return fromValue(type);
}
public static BpmnFlowNodeType valueOfType(String type) {
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnFlowNodeType fromValue(String value) {
if (!StringUtils.hasText(value)) {
return UNKNOWN;
}
return Arrays.stream(BpmnFlowNodeType.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,5 +1,11 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MESSAGE_CONFIG;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAGE_ID;
@ -10,11 +16,14 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAG
* @author wangli
* @since 2023/11/22 11:02
*/
@Getter
public enum BpmnNoticeEnum {
notice("notice", TEMPLATE_NOTICE_MESSAGE_CONFIG, "通知模板"),
pending("pending", TEMPLATE_PENDING_MESSAGE_ID, "待办模板"),
sms("sms", TEMPLATE_SMS_MESSAGE_ID, "短信模板"),
@JsonEnumDefaultValue
unknown("unknown", "unknown", "未知类型"),
;
private final String key;
private final String configName;
@ -26,15 +35,14 @@ public enum BpmnNoticeEnum {
this.desc = desc;
}
public String getKey() {
return key;
}
public String getConfigName() {
return configName;
}
public String getDesc() {
return desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnNoticeEnum fromValue(String key) {
if (key == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getKey().equalsIgnoreCase(key) || e.name().equalsIgnoreCase(key))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,7 +1,12 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum BpmnProcessInstanceResultEnum {
PROCESSING("PROCESSING", "审批中"),
APPROVED("APPROVED", "已通过"),
@ -14,6 +19,8 @@ public enum BpmnProcessInstanceResultEnum {
UPGRADED("UPGRADED", "已提级"),
COMMENTED("COMMENTED", "已评论"),
DELETED("DELETED", "已删除"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
/**
* 结果
@ -29,25 +36,8 @@ public enum BpmnProcessInstanceResultEnum {
this.desc = desc;
}
public String getStatus() {
return status;
}
public String getDesc() {
return desc;
}
/**
* 判断该结果是否已经处于 End 最终结果
* <p>
* 主要用于一些结果更新的逻辑如果已经是最终结果就不再进行更新
*
* @param result 结果
* @return 是否
*/
public static boolean isEndResult(String result) {
return Arrays.asList(PROCESSING.getStatus(), APPROVED.getStatus(), REJECTED.getStatus(),
CANCELLED.getStatus()).contains(result);
public static BpmnProcessInstanceResultEnum valueOfDesc(String desc) {
return Arrays.stream(values()).filter(it -> it.getDesc().equals(desc)).findFirst().orElse(DELETED);
}
public static BpmnProcessInstanceResultEnum valueOfStatus(String status) {
@ -55,8 +45,15 @@ public enum BpmnProcessInstanceResultEnum {
.orElse(DELETED);
}
public static BpmnProcessInstanceResultEnum valueOfDesc(String desc) {
return Arrays.stream(values()).filter(it -> it.getDesc().equals(desc)).findFirst()
.orElse(DELETED);
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnProcessInstanceResultEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(BpmnProcessInstanceResultEnum.values())
.filter(e -> e.getStatus().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,7 +1,11 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum BpmnProcessTaskResultEnum {
PENDING("PENDING", "待处理"),
@ -11,6 +15,8 @@ public enum BpmnProcessTaskResultEnum {
CANCELED("CANCELED", "已撤销"),
TRANSFERRED("TRANSFERRED", "已转交"),
NONE("NONE", "没有执行动作,例如 抄送"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
/**
* 结果
@ -26,4 +32,14 @@ public enum BpmnProcessTaskResultEnum {
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnProcessTaskResultEnum fromValue(String status) {
if (status == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getStatus().equalsIgnoreCase(status) || e.name().equalsIgnoreCase(status))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,10 +1,17 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 加签类型
*
* @author zuoqinbo
*/
@Getter
public enum BpmnReminderType {
/**
* 短信
@ -13,7 +20,10 @@ public enum BpmnReminderType {
/**
* 站内信
*/
INBOX_MESSAGE("INBOX_MESSAGE", "站内信");
INBOX_MESSAGE("INBOX_MESSAGE", "站内信"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
private String type;
private String desc;
@ -23,24 +33,15 @@ public enum BpmnReminderType {
this.desc = desc;
}
public boolean isEqual(String type) {
return this.type.equals(type);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnReminderType fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 签署方式
@ -9,10 +12,13 @@ import java.util.Objects;
* @author wangli
* @since 2025-03-25 17:00
*/
@Getter
public enum BpmnSignType {
SINGLE("SINGLE", "指定人群,所有人共同签署一份文件"),
MULTI("MULTI", "指定人群,每人签署一份文件"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
private final String type;
@ -23,20 +29,19 @@ public enum BpmnSignType {
this.desc = desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public static BpmnSignType valueOfType(String type) {
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BpmnSignType fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(BpmnSignType.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,18 +1,35 @@
package cn.axzo.workflow.common.enums;
import lombok.AllArgsConstructor;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
import java.util.Arrays;
@Getter
public enum BusinessTypeEnum {
SIGN("sign", "签署业务"),
APPROVAL("approval", "审批业务"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知");
APPROVAL("approval", "审批业务");
private final String type;
private final String desc;
private String type;
private String desc;
BusinessTypeEnum(String type, String desc) {
this.type = type;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static BusinessTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(v -> v.getType().equalsIgnoreCase(value) || v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,14 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum ButtonVisibleScopeEnum {
INITIATOR("INITIATOR", "发起人"),
EXECUTOR("EXECUTOR", "当前操作人"),
;
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知");
/**
* 结果
@ -23,4 +27,15 @@ public enum ButtonVisibleScopeEnum {
this.status = status;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ButtonVisibleScopeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getStatus().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 抄送对象类型枚举
@ -9,6 +12,7 @@ import java.util.Objects;
* @author wangli
* @since 12/03/2024 09:33
*/
@Getter
public enum CarbonCopyObjectType {
// 单位下
ent_role("ent_role", "role", "单位内指定角色", "entWorkspaceProcessor"),
@ -33,12 +37,14 @@ public enum CarbonCopyObjectType {
approver("approver", "approver", "审批人", "common"),
ent_initiator_leader("ent_initiator_leader", "initiatorLeader", "单位内发起人主管", "entWorkspaceProcessor"),
project_initiator_leader("project_initiator_leader", "initiatorLeader", "项目部内发起人主管", "projectWorkspaceProcessor"),
;
private String type;
private String simpleType;
private String desc;
private String processor;
@JsonEnumDefaultValue
unknown("unknown", "unknown", "未知", "unknownProcessor");
private final String type;
private final String simpleType;
private final String desc;
private final String processor;
CarbonCopyObjectType(String type, String simpleType, String desc, String processor) {
this.type = type;
@ -47,43 +53,19 @@ public enum CarbonCopyObjectType {
this.processor = processor;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSimpleType() {
return simpleType;
}
public void setSimpleType(String simpleType) {
this.simpleType = simpleType;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getProcessor() {
return processor;
}
public void setProcessor(String processor) {
this.processor = processor;
}
public static CarbonCopyObjectType valueOfType(String type) {
return Arrays.stream(CarbonCopyObjectType.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static CarbonCopyObjectType fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,5 +1,11 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 参建单位类型枚举
* <p>
@ -8,6 +14,7 @@ package cn.axzo.workflow.common.enums;
* @author wangli
* @since 2025-08-13 14:51
*/
@Getter
public enum CooperateShipTypeEnum {
PROJ_PRIMARY_CONTRACTING_UNIT(1, "施工总承包"),
PROJ_CONSTRUCTION_UNIT(2, "建设单位"),
@ -22,7 +29,9 @@ public enum CooperateShipTypeEnum {
PROJ_GROUP(11, "项目内小组"),
SURVEY_UNIT(12, "地勘单位"),
DESIGN_UNIT(13, "设计单位"),
OTHER(30, "其他");
OTHER(30, "其他"),
@JsonEnumDefaultValue
UNKNOWN(99, "未知");
private final Integer code;
private final String desc;
@ -32,12 +41,15 @@ public enum CooperateShipTypeEnum {
this.desc = desc;
}
public Integer getCode() {
return code;
}
public String getDesc() {
return desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static CooperateShipTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(v -> v.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,11 +1,34 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 模型扩展表的状态枚举
*
* @author wangli
* @since 2025-01-15 09:46
*/
@Getter
public enum ExtModelStateFieldEnum {
status, printStatus
status,
printStatus,
@JsonEnumDefaultValue
unknown,
;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ExtModelStateFieldEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(ExtModelStateFieldEnum.values())
.filter(e -> e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 文档类型枚举
@ -9,11 +12,14 @@ import java.util.Objects;
* @author wangli
* @since 2025-03-27 09:55
*/
@Getter
public enum FileTypeEnum {
WORD("word", "文本", ".docx"),
EXCEL("excel", "表格", ".xlsx"),
HIPRINT("hiprint", "智能文档", ""),
PDF("pdf", "PDF", ".pdf"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知", ""),
;
private final String type;
private final String desc;
@ -25,22 +31,19 @@ public enum FileTypeEnum {
this.suffix = suffix;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public String getSuffix() {
return suffix;
}
public static FileTypeEnum valueOfType(String type) {
return Arrays.stream(FileTypeEnum.values())
.filter(i -> Objects.equals(i.getType().toUpperCase(), type.toUpperCase()))
.findAny()
.orElse(null);
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static FileTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(FileTypeEnum.values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,16 +1,25 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 新版配置下的发起人自选的范围限定枚举
*
* @author wangli
* @since 2025-08-13 15:13
*/
@Getter
public enum InitiatorSpecifiedRangeEnum {
self_and_children_in_project("self_and_children_in_project", "项目内本组织及其下属组织所有成员"),
self_in_project("self_in_project", "项目内本组织所有成员"),
in_project("in_project", "项目内所有成员"),
in_ent("in_ent", "企业内所有成员"),
@JsonEnumDefaultValue
unknown("unknown", "未知"),
;
private final String type;
private final String desc;
@ -20,11 +29,14 @@ public enum InitiatorSpecifiedRangeEnum {
this.desc = desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static InitiatorSpecifiedRangeEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 模型业务类型枚举
@ -9,10 +12,13 @@ import java.util.Objects;
* @author wangli
* @since 2025-03-26 11:49
*/
@Getter
public enum ModelBizTypeEnum {
SIGN("SIGN", "签署业务"),
FLOWABLE("FLOWABLE", "审批业务"),
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知"),
;
private final String type;
private final String desc;
@ -22,18 +28,18 @@ public enum ModelBizTypeEnum {
this.desc = desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public static ModelBizTypeEnum valueOfType(String type) {
return Arrays.stream(ModelBizTypeEnum.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static ModelBizTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,12 +1,32 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 顺序操作枚举
*
* @author wangli
* @since 2025-03-31 16:35
*/
@Getter
public enum OrderEnum {
UP, DOWN
UP, DOWN,
@JsonEnumDefaultValue
UNKNOWN;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static OrderEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,11 +1,18 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 打印字段的类型枚举
*
* @author wangli
* @since 2025-01-16 18:19
*/
@Getter
public enum PrintFieldCategoryEnum {
// 表单变量
@ -15,5 +22,21 @@ public enum PrintFieldCategoryEnum {
// 电子签名变量
signature,
// 签署业务自定义变量
sign
sign,
// 审批业务的变量
biz_variable,
@JsonEnumDefaultValue
unknown,
;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static PrintFieldCategoryEnum fromValue(String value) {
if (value == null) {
return unknown;
}
return Arrays.stream(values())
.filter(e -> e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(unknown);
}
}

View File

@ -1,7 +1,10 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 签署确认节点的审批人层级范围限制
@ -9,6 +12,7 @@ import java.util.Objects;
* @author wangli
* @since 2025-03-26 14:30
*/
@Getter
public enum SignApproverOrgLimitEnum {
LV_0("LV_0", "当前组织", 0),
LV_1("LV_1", "上1级组织", 1),
@ -18,13 +22,11 @@ public enum SignApproverOrgLimitEnum {
LV_5("LV_5", "上5级组织", 5),
LV_ALL("LV_ALL", "所有组织", -1),
LV_TOP("LV_TOP", "顶层组织", Integer.MAX_VALUE),
UNKNOWN("UNKNOWN", "未知层级", null)
;
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知层级", null);
private final String type;
private final String desc;
private final Integer code;
SignApproverOrgLimitEnum(String type, String desc, Integer code) {
@ -33,22 +35,18 @@ public enum SignApproverOrgLimitEnum {
this.code = code;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public Integer getCode() {
return code;
}
public static SignApproverOrgLimitEnum valueOfType(String type) {
return Arrays.stream(SignApproverOrgLimitEnum.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
return fromValue(type);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static SignApproverOrgLimitEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,5 +1,9 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
@ -9,12 +13,13 @@ import java.util.Objects;
* @author wangli
* @since 2025-03-26 14:30
*/
@Getter
public enum SignApproverRoleLimitEnum {
LEADER("LEADER", "负责人"),
;
@JsonEnumDefaultValue
UNKNOWN("UNKNOWN", "未知");
private final String type;
private final String desc;
SignApproverRoleLimitEnum(String type, String desc) {
@ -22,18 +27,21 @@ public enum SignApproverRoleLimitEnum {
this.desc = desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public static SignApproverRoleLimitEnum valueOfType(String type) {
return Arrays.stream(SignApproverRoleLimitEnum.values())
.filter(i -> Objects.equals(i.getType(), type))
.findAny()
.orElse(null);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static SignApproverRoleLimitEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,5 +1,11 @@
package cn.axzo.workflow.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
/**
* 时间查询方向
* <p>
@ -9,8 +15,22 @@ package cn.axzo.workflow.common.enums;
* @author wangli
* @since 2024-09-29 09:56
*/
@Getter
public enum TimeQueryDirection {
BEFORE,
AFTER,
@JsonEnumDefaultValue
UNKNOWN,
;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static TimeQueryDirection fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,21 +1,39 @@
package cn.axzo.workflow.common.enums;
import lombok.AllArgsConstructor;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Arrays;
/**
* 模版上变量字段类型
*/
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum VarTypeEnum {
TEXT("text", "文本"),
PICTURE("picture", "图片"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "未知"),
;
PICTURE("picture", "图片");
private final String type;
private final String desc;
private String type;
private String desc;
VarTypeEnum(String type, String desc) {
this.type = type;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static VarTypeEnum fromValue(String value) {
if (value == null) {
return UNKNOWN;
}
return Arrays.stream(values())
.filter(e -> e.getType().equalsIgnoreCase(value) || e.name().equalsIgnoreCase(value))
.findFirst()
.orElse(UNKNOWN);
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.workflow.common.enums;
import lombok.AllArgsConstructor;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import lombok.Getter;
import java.util.Arrays;
@ -10,7 +11,6 @@ import java.util.Arrays;
* @date 2023/11/21
*/
@Getter
@AllArgsConstructor
public enum WorkspaceType {
/**
@ -21,15 +21,30 @@ public enum WorkspaceType {
PROJECT(2, "项目"),
GOVERNMENT(3, "政务监管平台"),
OMS(6, "oms工作台"),
@JsonEnumDefaultValue
UN_KNOW(0, "未知"),
;
private final Integer code;
private final String desc;
WorkspaceType(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static WorkspaceType getType(Integer code) {
return Arrays.stream(values()).filter(it -> it.getCode().equals(code))
return fromValue(String.valueOf(code));
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static WorkspaceType fromValue(String value) {
if (value == null) {
return UN_KNOW;
}
return Arrays.stream(values())
.filter(e -> e.getCode().toString().equalsIgnoreCase(value))
.findFirst()
.orElse(null);
.orElse(UN_KNOW);
}
}

View File

@ -21,7 +21,9 @@ import java.io.Serializable;
@Builder
public class TermNodeAddTimerJobDTO implements Serializable {
private String processInstanceId;
private String processDefinitionId;
private String activityId;
private String activityName;
private Integer delayTime;
private String timeUnit;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.workflow.common.model.request.feature;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 钉钉告警内容对象
*
* @author wangli
* @since 2025-09-02 15:24
*/
@ApiModel("钉钉告警内容对象")
@Data
public class DingTalkStarterAlterDTO {
@NotBlank(message = "环境信息不能为空")
private String profile;
@NotBlank(message = "应用名称不能为空")
private String applicationName;
@NotBlank(message = "告警内容不能为空")
private String alterContent;
}

View File

@ -0,0 +1,29 @@
package cn.axzo.workflow.common.model.request.feature;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 枚举查询对象
*
* @author wangli
* @since 2025-09-02 15:17
*/
@ApiModel("枚举查询对象")
@Data
public class EnumQueryDTO {
/**
* 枚举类全路径
*/
@NotBlank(message = "枚举类全路径不能为空")
private String enumClz;
/**
* 枚举值
*/
@NotBlank(message = "枚举值不能为空")
private String enumValue;
}

View File

@ -0,0 +1,39 @@
package cn.axzo.workflow.common.model.request.form.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 查询用于 WPS 左侧变量列表的集合
*
* @author wangli
* @since 2025-09-15 10:07
*/
@ApiModel("查询用于 WPS 左侧变量列表的集合")
@Data
@Builder
public class WpsFileConfigVariableDTO {
/**
* 模板定义 KEY
*/
@ApiModelProperty(value = "流程模板 KEY")
@NotBlank(message = "流程模板 KEY 不能为空")
private String processDefinitionKey;
/**
* 租户 ID
*/
@ApiModelProperty(value = "租户 ID")
private String tenantId;
/**
* 是否抛出内部异常
*/
@ApiModelProperty(value = "是否报错内部异常")
@Builder.Default
private Boolean throwException = true;
}

View File

@ -0,0 +1,49 @@
package cn.axzo.workflow.common.model.response.mq;
import cn.axzo.workflow.common.enums.DocChangeEventEnum;
import cn.axzo.workflow.common.model.dto.BizDocDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 用于 MQ 传输数据
*
* @author wangli
* @since 2025-09-29 11:03
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DocChangeDTO implements Serializable {
/**
* 业务 ID
*/
private String key;
/**
* 工作台 ID
*/
private Long workspaceId;
/**
* 修改后的文档
*/
private List<BizDocDTO> newSettings;
/**
* 修改前的文档
*/
private List<BizDocDTO> oldSettings;
/**
* 模型配置 MQ 事件的数据类型
*/
private DocChangeEventEnum type;
}

View File

@ -20,7 +20,6 @@ import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncRemindTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncResetApproversUserTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler;
import cn.axzo.workflow.core.engine.job.NextActivityConfigCheckJobHandler;
import cn.axzo.workflow.core.engine.job.exception.handle.CustomAsyncJobLogClearTraceExceptionHandler;
@ -116,7 +115,7 @@ public class FlowableConfiguration {
configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
// configuration.addCustomJobHandler(new AsyncTermNodeAlterJobHandler(refreshProperties));
configuration.addCustomJobHandler(new AsyncActivityLeaveJobHandler(bpmnProcessActivityService));
configuration.addCustomJobHandler(new AsyncActivityCallbackJobHandler());
configuration.addCustomJobHandler(new AsyncApproveTaskWithFormJobHandler());

View File

@ -41,6 +41,16 @@ public class SupportRefreshProperties {
@Value(value = "${workflow.alter.enable:false}")
private Boolean alterEnable;
/**
* 是否全量业务 ID 都开启告警功能
*/
@Value(value = "${workflow.alter.allDefinitionKey:false}")
private Boolean alterAllDefinitionKey;
/**
* 需要开启告警功能的业务 ID 列表
*/
@Value(value = "${workflow.alter.definitionKeys:}")
private List<String> alterDefinitionKeys;
/**
* 节点卡住多久才告警单位分钟
*/
@ -92,4 +102,10 @@ public class SupportRefreshProperties {
@Value("${workflow.imTemplateCode:}")
private String imTemplateCode;
/**
* 忽略 MQ 必接事件的告警服务名
*/
@Value("${workflow.ignoreMqAlterApplicationNames:}")
private List<String> ignoreMqAlterApplicationNames;
}

View File

@ -0,0 +1,13 @@
package cn.axzo.workflow.core.deletage.approverscope;
import org.springframework.stereotype.Component;
/**
* 兜底的处理器
*
* @author wangli
* @since 2025-08-28 16:45
*/
@Component
public class UnknownProcessor implements ApproverScopeProcessor {
}

View File

@ -1,16 +1,13 @@
package cn.axzo.workflow.core.engine.cmd;
import cn.axzo.workflow.common.model.dto.TermNodeAddTimerJobDTO;
import cn.axzo.workflow.core.engine.job.AsyncTermNodeAlterJobHandler;
import cn.axzo.workflow.core.common.utils.SpringContextUtils;
import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.ManagementService;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.job.service.TimerJobService;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import java.io.Serializable;
import java.util.Date;
@ -37,14 +34,11 @@ public class CustomAddTimerJobCmd extends AbstractCommand<Void> implements Seria
@Override
public Void executeInternal(CommandContext commandContext) {
log.info("CustomAddTimerJobCmd start. instanceId: {}, activityId: {}, delayTime: {}, timeUnit: {}", dto.getProcessInstanceId(), dto.getActivityId(), dto.getDelayTime(), dto.getTimeUnit());
ProcessEngineConfigurationImpl processEngineConfiguration =
CommandContextUtil.getProcessEngineConfiguration(commandContext);
ManagementService managementService = processEngineConfiguration.getManagementService();
Date alterTime;
switch (dto.getTimeUnit()) {
case "M":
alterTime = DateUtil.offsetDay(new Date(), dto.getDelayTime());
alterTime = DateUtil.offsetMinute(new Date(), dto.getDelayTime());
break;
case "H":
alterTime = DateUtil.offsetHour(new Date(), dto.getDelayTime());
@ -54,20 +48,15 @@ public class CustomAddTimerJobCmd extends AbstractCommand<Void> implements Seria
break;
}
managementService.executeCommand(context -> {
TimerJobService timerJobService = CommandContextUtil.getTimerJobService();
TimerJobEntity timerJobEntity = timerJobService.createTimerJob();
timerJobEntity.setJobType("timer");
timerJobEntity.setJobHandlerType(AsyncTermNodeAlterJobHandler.TYPE); // 这里填写你自定义的 JobHandler 类型
timerJobEntity.setProcessInstanceId(dto.getProcessInstanceId());
timerJobEntity.setExecutionId(null);
timerJobEntity.setDuedate(alterTime); // 立即执行
timerJobEntity.setRepeat(null); // 不重复
timerJobEntity.setRetries(1);
timerJobEntity.setJobHandlerConfiguration(dto.getActivityId()); // 可选传递参数
timerJobService.scheduleTimerJob(timerJobEntity);
return null;
});
ExtAxNodeAlterJobService service = SpringContextUtils.getBean(ExtAxNodeAlterJobService.class);
ExtAxNodeAlterJob job = new ExtAxNodeAlterJob();
job.setProcessInstanceId(dto.getProcessInstanceId());
job.setProcessDefinitionId(dto.getProcessDefinitionId());
job.setActivityId(dto.getActivityId());
job.setActivityName(dto.getActivityName());
job.setAlterTime(alterTime);
job.setException("");
service.save(job);
return null;
}

View File

@ -89,12 +89,13 @@ public class CustomBizSpecifyAssigneeToTaskCmd extends AbstractCommand<Boolean>
* @param assigners
*/
public static void validate(RuntimeService runtimeService, String executionId, Task task, List<BpmnTaskDelegateAssigner> assigners) {
validTask(task, executionId);
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(task.getProcessDefinitionId());
boolean present = assigners.stream().anyMatch(assigner -> !StringUtils.hasText(assigner.getNodeId()));
if (present && getCategoryVersion(bpmnModel.getMainProcess()).orElse(0) > 0) {
throw new WorkflowEngineException(ASSIGNEE_NODE_ID_NOT_EXISTS, "审批人");
}
validTask(task, executionId);
//校验审批人数量是否超过限制
validTaskAssignerCount(runtimeService, (TaskEntity) task, assigners);
}

View File

@ -6,6 +6,7 @@ import java.util.List;
/**
* 模型关联的文档变更事件对象
* 该事件目前仅用于考勤业务王庆
*
* @author wangli
* @since 2025-04-07 16:51

View File

@ -11,6 +11,7 @@ import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.impl.cfg.TransactionState;
@ -60,11 +61,16 @@ public class InternalBpmnActivityEventListener_lo_Listener extends AbstractBpmnE
if (!Boolean.TRUE.equals(refreshProperties.getAlterEnable())) {
return;
}
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
if (!refreshProperties.getAlterAllDefinitionKey()) {
if (!ListUtils.emptyIfNull(refreshProperties.getAlterDefinitionKeys()).contains(bpmnModel.getMainProcess().getId())) {
return;
}
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
TermNodePausingDTO dto = new TermNodePausingDTO(execution.getProcessInstanceId(), execution.getCurrentActivityId(), 0);
runtimeService.setVariable(execution.getProcessInstanceId(), BIZ_NODE_ALTER + execution.getCurrentActivityId(), dto);
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
FlowElement flowElement = bpmnModel.getFlowElement(execution.getCurrentActivityId());
BpmnMetaParserHelper.getNodeType(flowElement).ifPresent(e -> {
if (Objects.equals(BpmnFlowNodeType.NODE_BUSINESS, e)) {
@ -89,7 +95,9 @@ public class InternalBpmnActivityEventListener_lo_Listener extends AbstractBpmnE
TermNodeAddTimerJobDTO addTimerJobDTO = new TermNodeAddTimerJobDTO();
addTimerJobDTO.setProcessInstanceId(execution.getProcessInstanceId());
addTimerJobDTO.setProcessDefinitionId(execution.getProcessDefinitionId());
addTimerJobDTO.setActivityId(execution.getCurrentActivityId());
addTimerJobDTO.setActivityName(flowElement.getName());
addTimerJobDTO.setDelayTime(refreshProperties.getAlterInterval());
addTimerJobDTO.setTimeUnit(timeUnit);

View File

@ -0,0 +1,48 @@
package cn.axzo.workflow.core.repository.entity;
import cn.axzo.framework.data.mybatisplus.model.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* 业务节点告警任务表
*
* @author wangli
* @since 2025-09-05 13:43
*/
@EqualsAndHashCode(callSuper = true)
@TableName(value = "ext_ax_node_alter_job", autoResultMap = true)
@Data
@ToString(callSuper = true)
public class ExtAxNodeAlterJob extends BaseEntity<ExtAxNodeAlterJob> {
private static final long serialVersionUID = 461756492937079852L;
/**
* 流程实例 ID
*/
private String processInstanceId;
/**
* 流程定义 ID
*/
private String processDefinitionId;
/**
* 活动节点 ID
*/
private String activityId;
/**
* 活动节点名称
*/
private String activityName;
/**
* 告警事件
*/
private Date alterTime;
/**
* 异常信息
*/
private String exception;
}

View File

@ -0,0 +1,22 @@
package cn.axzo.workflow.core.repository.mapper;
import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ExtAxNodeAlterJobMapper extends BaseMapperX<ExtAxNodeAlterJob> {
@Delete({
"<script>",
"DELETE FROM ext_ax_node_alter_job WHERE id IN ",
"<foreach item='id' collection='ids' open='(' separator=',' close=')'>",
"#{id}",
"</foreach>",
"</script>"
})
int physicsDeleteBatchIds(@Param("ids") List<Long> ids);
}

View File

@ -0,0 +1,17 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 业务节点告警表操作服务
*
* @author wangli
* @since 2024/4/3 10:40
*/
public interface ExtAxNodeAlterJobService extends IService<ExtAxNodeAlterJob> {
boolean deleteByIds(List<Long> ids);
}

View File

@ -0,0 +1,31 @@
package cn.axzo.workflow.core.service.impl;
import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
import cn.axzo.workflow.core.repository.mapper.ExtAxNodeAlterJobMapper;
import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
/**
* 业务节点告警表操作服务实现类
*
* @author wangli
* @since 2025-09-05 13:50
*/
@Service
@Slf4j
public class ExtAxNodeAlterJobServiceImpl extends ServiceImpl<ExtAxNodeAlterJobMapper, ExtAxNodeAlterJob> implements ExtAxNodeAlterJobService {
@Resource
private ExtAxNodeAlterJobMapper extAxNodeAlterJobMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteByIds(List<Long> ids) {
return extAxNodeAlterJobMapper.physicsDeleteBatchIds(ids) > 0;
}
}

View File

@ -2,6 +2,7 @@ package cn.axzo.workflow.core.util;
import cn.axzo.workflow.common.model.NextNodePreCheckAlterDTO;
import cn.axzo.workflow.common.model.dto.AlterDTO;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
@ -203,4 +204,21 @@ public class DingTalkUtils {
request.setMarkdown(markdown);
sendDingTalk(request);
}
public static void sendDingTalkForStarter(DingTalkStarterAlterDTO dto, List<String> alterMobiles) {
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("markdown");
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle("Notice 应用必接广播 MQ 事件告警, Env: " + dto.getProfile());
markdown.setText("#### [" + dto.getProfile() + "]应用必接广播 MQ 事件告警\n" +
"> 应用名称:" + dto.getApplicationName() + "\n\n" +
"> 检测信息:" + dto.getAlterContent() + "\n\n" +
mobiles(alterMobiles));
request.setMarkdown(markdown);
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(alterMobiles);
at.setIsAtAll(false);
request.setAt(at);
sendDingTalk(request);
}
}

View File

@ -154,6 +154,10 @@
<groupId>cn.axzo.nanopart</groupId>
<artifactId>doc-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.infra</groupId>
<artifactId>adapter</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -7,6 +7,7 @@ import cn.axzo.riven.client.model.SampleMarkdown;
import cn.axzo.riven.client.req.DingDingSendRebootGroupMsgReq;
import cn.axzo.workflow.common.model.NextNodePreCheckAlterDTO;
import cn.axzo.workflow.common.model.dto.AlterDTO;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
import cn.axzo.workflow.core.listener.Alter;
import cn.axzo.workflow.core.util.DingTalkUtils;
@ -41,23 +42,55 @@ public class DingTalkAlter implements Alter {
@Override
public void invoke(Object obj) {
if (!Boolean.TRUE.equals(refreshProperties.getAlterSendDingTalk())) {
log.info("ignore send alter");
return;
}
log.info("send biz node alter : {}", JSON.toJSONString(obj));
if (obj instanceof AlterDTO) {
AlterDTO alterDTO = (AlterDTO) obj;
if (Objects.equals(profile, "master")) {
rivenDingtalk(alterDTO);
} else {
DingTalkUtils.sendDingTalkForBizNodeAlter(profile, alterDTO, refreshProperties.getAlterMobiles());
} else {
rivenDingtalk(alterDTO);
}
}
if (obj instanceof NextNodePreCheckAlterDTO) {
NextNodePreCheckAlterDTO alterDTO = (NextNodePreCheckAlterDTO) obj;
if (Objects.equals(profile, "master")) {
rivenDingtalkForNodePreCheck(alterDTO);
} else {
DingTalkUtils.sendDingTalkForNodePreCheck(profile, alterDTO, refreshProperties.getAlterMobiles());
} else {
rivenDingtalkForNodePreCheck(alterDTO);
}
}
if (obj instanceof DingTalkStarterAlterDTO) {
DingTalkStarterAlterDTO starterAlterDTO = (DingTalkStarterAlterDTO) obj;
if (refreshProperties.getIgnoreMqAlterApplicationNames().contains(starterAlterDTO.getApplicationName())) {
// 忽略必接事件的应用
return;
}
DingTalkUtils.sendDingTalkForStarter(starterAlterDTO, refreshProperties.getAlterMobiles());
}
}
private void rivenDingtalkForStarter(DingTalkStarterAlterDTO alterDTO) {
DingDingSendRebootGroupMsgReq req = new DingDingSendRebootGroupMsgReq();
req.setDingDingScene("WORKFLOW_ENGINE_BIZNODE_ALTER");
String title = "Notice 应用必接事件告警, Env: " + profile;
String text = "#### [" + profile + "]应用必接事件告警\n" +
"> 应用名称:" + alterDTO.getApplicationName() + "\n\n" +
"> 检测信息:" + alterDTO.getAlterContent() + "\n\n" +
mobiles(refreshProperties.getAlterMobiles());
SampleMarkdown markdown = new SampleMarkdown(title, text);
JSONObject markdownJson = JSONObject.parseObject(markdown.toJson());
JSONObject atMobiles = new JSONObject();
atMobiles.put("atMobiles", refreshProperties.getAlterMobiles());
markdownJson.put("at", atMobiles);
markdownJson.put("isAtAll", false);
req.setDingDingJson(markdownJson.toJSONString());
req.setMsgType(DingTalkMsgTypeEnum.sampleMarkdown);
dingDingMsgApi.sendRebootGroupMsg(req);
}
private void rivenDingtalkForNodePreCheck(NextNodePreCheckAlterDTO alterDTO) {

View File

@ -3,10 +3,9 @@ package cn.axzo.workflow.server.controller.listener.doc;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.workflow.common.enums.DocChangeEventEnum;
import cn.axzo.workflow.common.model.response.mq.DocChangeDTO;
import cn.axzo.workflow.core.conf.CustomEventManager;
import cn.axzo.workflow.core.engine.event.DocChangeEvent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
@ -48,7 +47,13 @@ public class DocChangeListener {
.eventCode(DocChangeEventEnum.DOC_CHANGE.getEventCode())
.targetId(event.getKey())
.targetType(event.getKey())
.data(JSON.toJSONString(event, SerializerFeature.WriteMapNullValue))
.data(DocChangeDTO.builder()
.key(event.getKey())
.workspaceId(event.getWorkspaceId())
.newSettings(event.getNewSettings())
.oldSettings(event.getOldSettings())
.type(DocChangeEventEnum.DOC_CHANGE)
.build())
.build());
}
}

View File

@ -0,0 +1,28 @@
package cn.axzo.workflow.server.controller.web;
import com.alibaba.fastjson.JSONObject;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.handler.IJobHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yanglin
*/
@RestController
public class JobHttpHandler {
@PostMapping("/jobs/{jobName}")
ReturnT<String> exec(@PathVariable String jobName,
@RequestBody(required = false) JSONObject paramObj) throws Exception {
IJobHandler jobHandler = XxlJobExecutor.loadJobHandler(jobName);
if (jobHandler == null)
return new ReturnT<>(ReturnT.FAIL_CODE, String.format("找不到job: %s", jobName));
jobHandler.execute();
return ReturnT.SUCCESS;
}
}

View File

@ -12,6 +12,7 @@ import cn.axzo.workflow.common.model.request.form.definition.FormContentSearchDT
import cn.axzo.workflow.common.model.request.form.instance.FormInstanceSearchDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
import cn.axzo.workflow.core.engine.cmd.CustomGetProcessInstanceVariablesToObjectCmd;
import cn.axzo.workflow.core.repository.entity.ExtAxBpmnFormRelation;
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;

View File

@ -8,6 +8,7 @@ import cn.axzo.workflow.common.model.response.es.ProcessInstanceDocumentVO;
import cn.axzo.workflow.common.model.response.es.ProcessTaskDocumentVO;
import cn.axzo.workflow.es.service.aggregation.AggregateProcessInstanceService;
import cn.axzo.workflow.es.service.aggregation.AggregateProcessTaskService;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
@ -30,6 +31,7 @@ import java.util.List;
@Slf4j
@RequestMapping({"/web/v1/api/es", "/api/es"})
@RestController
@ErrorReporter
@Validated
public class ElasticSearchController implements EsProcessInstanceApi {
@Resource

View File

@ -1,20 +1,30 @@
package cn.axzo.workflow.server.controller.web.form;
import cn.axzo.workflow.client.feign.manage.FormAdminApi;
import cn.axzo.workflow.common.enums.PrintFieldCategoryEnum;
import cn.axzo.workflow.common.model.dto.BpmnFormRelationSearchDTO;
import cn.axzo.workflow.common.model.dto.print.FieldAttributeDTO;
import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO;
import cn.axzo.workflow.common.model.request.category.CategoryGroupVarSearchDto;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FromDataSearchDTO;
import cn.axzo.workflow.common.model.request.form.model.WpsFileConfigVariableDTO;
import cn.axzo.workflow.common.model.response.category.CategoryGroupVarItemVo;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormDataVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import cn.axzo.workflow.core.service.CategoryGroupService;
import cn.axzo.workflow.core.service.FormCoreService;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.axzo.workflow.server.controller.web.manage.PrintAdminController;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -22,6 +32,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import static cn.azxo.framework.common.model.CommonResponse.success;
@ -41,6 +52,10 @@ public class FormAdminController implements FormAdminApi {
@Resource
private FormCoreService formCoreService;
@Resource
private PrintAdminController printAdminController;
@Resource
private CategoryGroupService categoryGroupService;
@Operation(summary = "表单列表")
@PostMapping("/form/page")
@ -68,4 +83,48 @@ public class FormAdminController implements FormAdminApi {
public CommonResponse<List<FormDataVO>> getFormData(@Validated @RequestBody FromDataSearchDTO dto) {
return success(formCoreService.getFormData(dto));
}
/**
* 获取 WPS 文档中所有可配置的流程相关变量
*
* @param dto
* @return
*/
@PostMapping("/wps/file/config/variables")
@Override
public CommonResponse<List<PrintFieldDTO>> getWpsFileConfigVariables(@Validated @RequestBody WpsFileConfigVariableDTO dto) {
CommonResponse<List<PrintFieldDTO>> printFieldResponse = printAdminController.getPrintFields(PrintFieldQueryDTO.builder()
.processDefinitionKey(dto.getProcessDefinitionKey())
.tenantId(dto.getTenantId())
.throwException(dto.getThrowException())
.build());
List<PrintFieldDTO> result = printFieldResponse.getData();
List<CategoryGroupVarItemVo> categoryGroupVarItemVos = categoryGroupService.searchGroupAndVarList(CategoryGroupVarSearchDto.builder()
.category(dto.getProcessDefinitionKey())
.build());
if (CollectionUtils.isEmpty(categoryGroupVarItemVos)) {
return printFieldResponse;
}
categoryGroupVarItemVos.forEach(i -> {
PrintFieldDTO field = new PrintFieldDTO();
field.setName(i.getGroupName());
field.setFieldCategoryType(PrintFieldCategoryEnum.biz_variable);
field.setCode("");
field.setFieldFormType("");
List<FieldAttributeDTO> attributes = new ArrayList<>();
i.getVars().forEach(e -> {
FieldAttributeDTO attribute = new FieldAttributeDTO();
attribute.setCode(e.getCode());
attribute.setName(e.getName());
attribute.setFieldFormType(e.getType().getType());
attributes.add(attribute);
});
field.setAttributes(attributes);
result.add(field);
});
return success(result);
}
}

View File

@ -0,0 +1,63 @@
package cn.axzo.workflow.server.controller.web.manage;
import cn.axzo.workflow.client.feign.manage.FunctionApi;
import cn.axzo.workflow.common.enums.AdminDataSource;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.axzo.workflow.server.alter.DingTalkAlter;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 功能性 API 控制器
*
* @author wangli
* @since 2025-09-02 14:44
*/
@Slf4j
@RequestMapping({"/web/v1/api/function", "/api/function"})
@RestController
@ErrorReporter
@Validated
public class FunctionController implements FunctionApi {
@Resource
private DingTalkAlter dingTalkAlter;
/**
* 获取指定枚举类型的枚举值信息
*
* @param enumValue
* @return
*/
@Operation(summary = "获取指定枚举类型的枚举值信息")
@Override
@GetMapping("/enum/admin-data-source/get")
public CommonResponse<AdminDataSource> getAdminDataSourceEnum(String enumValue) {
return CommonResponse.success(AdminDataSource.fromValue(enumValue));
}
@Operation(summary = "获取指定枚举类型的枚举值信息")
@Override
@GetMapping("/enum/process-instance-result/get")
public CommonResponse<BpmnProcessInstanceResultEnum> getFileTypeEnum(String enumValue) {
return CommonResponse.success(BpmnProcessInstanceResultEnum.fromValue(enumValue));
}
@Operation(summary = "发送钉钉消息")
@PostMapping("/dingtalk/alter")
@Override
public CommonResponse<Boolean> sendDingtalk(@Validated @RequestBody DingTalkStarterAlterDTO dto) {
dingTalkAlter.invoke(dto);
return CommonResponse.success(true);
}
}

View File

@ -339,10 +339,11 @@ public class PrintAdminController implements PrintAdminApi {
@Operation(summary = "获取指定流程下用于替换打印的相关变量")
@GetMapping("/field/variables")
@Override
public CommonResponse<Map<String, Object>> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId) {
public CommonResponse<Map<String, Object>> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId,
@RequestParam(required = false, defaultValue = "true") Boolean throwException) {
Map<String, Object> result = new HashMap<>();
CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
byte[] formInstanceValue = commandExecutor.execute(new CustomGetFormInstanceLatestValuesCmd(processInstanceId));
byte[] formInstanceValue = commandExecutor.execute(new CustomGetFormInstanceLatestValuesCmd(processInstanceId, throwException));
if (!ObjectUtils.isEmpty(formInstanceValue)) {
JSONObject treeNode = JSON.parseObject(new String(formInstanceValue));
result.putAll(treeNode.getJSONObject("values").getInnerMap());

View File

@ -0,0 +1,132 @@
package cn.axzo.workflow.server.xxljob;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.framework.jackson.utility.JSON;
import cn.axzo.infra.xxl220to250.IJobHandler;
import cn.axzo.workflow.common.model.dto.AlterDTO;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import cn.axzo.workflow.core.common.utils.SpringContextUtils;
import cn.axzo.workflow.core.conf.SupportRefreshProperties;
import cn.axzo.workflow.core.listener.Alter;
import cn.axzo.workflow.core.repository.entity.ExtAxNodeAlterJob;
import cn.axzo.workflow.core.service.CategoryService;
import cn.axzo.workflow.core.service.ExtAxNodeAlterJobService;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.constant.BpmnConstants.BPM_MODEL_CATEGORY;
/**
* 调度业务节点告警定时任务
*
* @author wangli
* @since 2025-09-05 11:19
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class NodeAlterJobHandler extends IJobHandler {
private final ExtAxNodeAlterJobService extAxNodeAlterJobService;
private final CategoryService categoryService;
private final SpringProcessEngineConfiguration processEngineConfiguration;
private final SupportRefreshProperties refreshProperties;
@XxlJob("nodeAlterJobHandler")
@Override
public ReturnT<String> execute(String param) throws Exception {
List<ExtAxNodeAlterJob> jobs = extAxNodeAlterJobService.list(new LambdaQueryWrapper<ExtAxNodeAlterJob>()
.le(ExtAxNodeAlterJob::getAlterTime, new Date()));
if (CollectionUtils.isEmpty(jobs)) {
XxlJobHelper.log("没有需要处理的业务节点告警任务");
return ReturnT.SUCCESS;
}
List<ExtAxNodeAlterJob> executedJobs = new ArrayList<>();
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
TaskService taskService = processEngineConfiguration.getTaskService();
jobs.forEach(e -> {
XxlJobHelper.log("start execution of job: {}", JSON.toJSONString(e));
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(e.getProcessInstanceId()).singleResult();
if (Objects.isNull(processInstance)) {
executedJobs.add(e);
return;
}
if (!refreshProperties.getAlterAllDefinitionKey()) {
if (!ListUtils.emptyIfNull(refreshProperties.getAlterDefinitionKeys()).contains(processInstance.getProcessDefinitionKey())) {
XxlJobHelper.log("skip alter by config");
return;
}
}
List<Task> tasks = taskService.createTaskQuery()
.processInstanceId(e.getProcessInstanceId())
.taskDefinitionKey(e.getActivityId())
.active().list();
StringBuilder sb = new StringBuilder();
tasks.forEach(t -> {
sb.append("id").append(e.getId()).append(", assignee: ").append(t.getAssignee());
});
XxlJobHelper.log("tasks size:{}, info: {}", tasks.size(), com.alibaba.fastjson.JSON.toJSONString(sb));
if (CollectionUtils.isEmpty(tasks) || tasks.size() > 1 || hasAssignee(tasks.get(0).getAssignee())) {
executedJobs.add(e);
return;
}
Optional<CategoryItemVO> category = categoryService.get(BPM_MODEL_CATEGORY, processInstance.getProcessDefinitionKey());
sendAlter(processInstance, category, e, tasks.get(0));
executedJobs.add(e);
XxlJobHelper.log("end execution of job: {}", JSON.toJSONString(e));
});
extAxNodeAlterJobService.deleteByIds(executedJobs.stream().map(ExtAxNodeAlterJob::getId).collect(Collectors.toList()));
return ReturnT.SUCCESS;
}
private void sendAlter(ProcessInstance processInstance, Optional<CategoryItemVO> category, ExtAxNodeAlterJob job, Task task) {
// 发送告警对象
Alter alter = SpringContextUtils.getBean(Alter.class);
AlterDTO alterDTO = new AlterDTO();
alterDTO.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
alterDTO.setProcessDefinitionName(category.orElse(new CategoryItemVO()).getLabel());
alterDTO.setProcessInstanceId(job.getProcessInstanceId());
alterDTO.setActivityId(job.getActivityId());
alterDTO.setTaskId(task.getId());
alterDTO.setStartTime(task.getCreateTime());
alterDTO.setPrettyStartTime(DateUtil.formatDateTime(task.getCreateTime()));
if (Boolean.TRUE.equals(refreshProperties.getAlterSendDingTalk())) {
alter.invoke(alterDTO);
}
}
private Boolean hasAssignee(String assignee) {
if (!StringUtils.hasText(assignee)) {
return false;
}
String[] split = assignee.split("\\|");
return split.length == 2 && NumberUtil.isPositiveNumber(Long.valueOf(split[1]));
}
}

View File

@ -30,4 +30,5 @@ public class StarterFeignClientConfiguration {
public static class WorkflowManageServiceClient {
}
}

View File

@ -1,7 +1,9 @@
package cn.axzo.workflow.starter;
import cn.axzo.workflow.starter.api.WorkflowCoreService;
import cn.axzo.workflow.starter.common.enums.FailHandleTypeEnum;
import cn.axzo.workflow.starter.common.exception.WorkflowUnsupportedException;
import cn.axzo.workflow.starter.handler.DocEventHandler;
import cn.axzo.workflow.starter.handler.MessageNotificationEventHandler;
import cn.axzo.workflow.starter.handler.ProcessActivityEventHandler;
import cn.axzo.workflow.starter.handler.ProcessInstanceEventHandler;
@ -12,6 +14,7 @@ import cn.axzo.workflow.starter.handler.execute.interceptor.ExecutorInvoker;
import cn.axzo.workflow.starter.handler.execute.interceptor.FailFastInterceptor;
import cn.axzo.workflow.starter.handler.execute.interceptor.FailOverInterceptor;
import cn.axzo.workflow.starter.handler.execute.interceptor.LogInterceptor;
import cn.axzo.workflow.starter.handler.filter.DocEventFilter;
import cn.axzo.workflow.starter.handler.filter.MessageNotificationEventFilter;
import cn.axzo.workflow.starter.handler.filter.ProcessActivityEventFilter;
import cn.axzo.workflow.starter.handler.filter.ProcessInstanceEventFilter;
@ -19,10 +22,12 @@ import cn.axzo.workflow.starter.handler.filter.ProcessTaskEventFilter;
import cn.axzo.workflow.starter.handler.monitor.BroadcastDLQReporter;
import cn.axzo.workflow.starter.handler.monitor.RpcDLQReporter;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerActivityEventListener;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerDocEventListener;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerInstanceEventListener;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerNotificationEventListener;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerTaskEventListener;
import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerWorkflowListener;
import cn.axzo.workflow.starter.mq.check.ImplementationReadyChecker;
import cn.axzo.workflow.starter.mq.monitor.WorkflowEngineStarterDefaultMQMonitor;
import cn.axzo.workflow.starter.mq.monitor.console.WorkflowEngineStarterMQMonitorController;
import cn.axzo.workflow.starter.selector.MetaFeignClientEnableSelector;
@ -101,6 +106,13 @@ public class WorkflowEngineStarterAutoConfiguration {
return new InnerNotificationEventListener(executor, handlerProvider, filterProvider);
}
@Bean
public InnerDocEventListener innerDocEventListener(ListenerExecutor executor,
ObjectProvider<List<DocEventHandler>> handlerProvider,
ObjectProvider<List<DocEventFilter>> filterProvider) {
return new InnerDocEventListener(executor, handlerProvider, filterProvider);
}
private ExecuteInterceptor getFailInterceptor(WorkflowEngineStarterProperties starterProperties) {
BroadcastListenerProperties listenerRetry = starterProperties.getBroadcast();
FailHandleTypeEnum failHandleType = listenerRetry.getFailHandleType();
@ -155,9 +167,9 @@ public class WorkflowEngineStarterAutoConfiguration {
return new WorkflowEngineStarterDefaultMQMonitor(mqAdminExtObjectProvider, broadcastDLQProcessorObjectProvider, rpcDLQProcessorObjectProvider, workflowEngineStarterProperties, environment);
}
// @Bean
// public ImplementationReadyChecker implementationReadyChecker() {
// return new ImplementationReadyChecker();
// }
@Bean
public ImplementationReadyChecker implementationReadyChecker(WorkflowCoreService workflowCoreService) {
return new ImplementationReadyChecker(workflowCoreService);
}
}

View File

@ -1,87 +1,66 @@
package cn.axzo.workflow.starter.api;
import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import cn.axzo.workflow.common.util.ThreadUtil;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.constraints.NotBlank;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import java.util.List;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.log.LogApproveSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigUpsertDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BeforeProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceBatchQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ExtProcessLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.util.Map;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditWithFormDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
import javax.validation.constraints.NotEmpty;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import cn.axzo.workflow.common.util.ThreadUtil;
import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
/**
* Workflow Engine Starter Core Service
@ -94,14 +73,26 @@ import javax.validation.constraints.NotEmpty;
public interface WorkflowCoreService {
/**
* 业务节点唤醒, 该节点废弃请换成 {@link ProcessActivityApi#trigger(cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO)} 接口
* <p>
* 当模型中使用了业务节点且设置了不设置审批人模式则当业务监听到 PROCESS_ACTIVITY_START 事件时可通过该接口推动流程继续运行
* 查询指定审批流程是否能打印打印开关是否开启是否存在打印模板
*
* @param processInstanceId
* @return
*/
@Deprecated
@GetMapping("/api/process/activity/trigger")
@Operation(summary = "查询指定审批流程是否能打印,打印开关是否开启,是否存在打印模板")
@GetMapping("/api/print/admin/template/exists")
@InvokeMode(SYNC)
Boolean trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId);
Boolean hasPrintTemplate(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);
/**
* 打印模板配置内容更新保存
*
* @param dto
* @return
*/
@Operation(summary = "打印模板配置内容更新保存")
@PostMapping("/api/print/admin/template/upsert")
@InvokeMode(SYNC)
Void printTemplateConfig(@Validated @RequestBody PrintTemplateConfigUpsertDTO dto);
/**
* 业务节点唤醒
@ -148,6 +139,17 @@ public interface WorkflowCoreService {
@InvokeMode(SYNC)
Boolean setTimeoutCallback(@Validated @RequestBody BpmnActivityTimeoutCallbackDTO dto);
/**
* 用于 Starter 检测必接事件的告警
*
* @param dto
* @return
*/
@Operation(summary = "发送钉钉消息")
@PostMapping("/api/function/dingtalk/alter")
@InvokeMode(SYNC)
Boolean sendDingtalk(@Validated @RequestBody DingTalkStarterAlterDTO dto);
/**
* 获取指定审批业务的流程表单设置
* @param dto
@ -236,6 +238,17 @@ public interface WorkflowCoreService {
@InvokeMode(ASYNC)
BatchOperationResultVO batchAbortProcessInstance(@Validated @RequestBody List<BpmnProcessInstanceAbortDTO> dtos);
/**
* 抄送流程实例未实现
*
* @param dto
* @return
*/
@Operation(summary = "抄送流程实例")
@PostMapping("/api/process/instance/carbon-copy")
@Deprecated
Boolean carbonCopyProcessInstance(@Validated @RequestBody BpmnProcessInstanceCarbonCopyDTO dto);
/**
* 获得流程实例
*
@ -247,6 +260,17 @@ public interface WorkflowCoreService {
@InvokeMode(SYNC)
BpmnProcessInstanceVO getProcessInstanceVO(@Validated @RequestBody BpmnProcessInstanceQueryDTO dto);
/**
* 批量获得流程实例
*
* @param dto
* @return
*/
@Operation(summary = "批量获得流程实例")
@PostMapping("/api/process/instance/batch/get")
@InvokeMode(SYNC)
List<BpmnProcessInstanceVO> getBatchProcessInstanceVO(@Validated @RequestBody BpmnProcessInstanceBatchQueryDTO dto);
/**
* 获取指定流程实例的流程变量
*

View File

@ -1,74 +1,17 @@
package cn.axzo.workflow.starter.api;
import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import cn.axzo.workflow.common.util.ThreadUtil;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.enums.AdminDataSource;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminCreateDTO;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminDeleteDTO;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminQueryDTO;
import cn.axzo.workflow.common.model.response.admin.ProcessAdminVo;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import cn.axzo.workflow.common.model.request.es.InstanceSearchReqDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.es.ProcessInstanceDocumentVO;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.log.LogApproveSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BeforeProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ExtProcessLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import cn.axzo.workflow.common.model.request.category.*;
import cn.axzo.workflow.common.model.response.category.CategoryConfigItemVO;
import cn.axzo.workflow.common.model.response.category.CategoryGroupVarItemVo;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import org.springframework.web.bind.annotation.*;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.*;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
import cn.axzo.workflow.common.model.request.bpmn.RestBpmnProcessVariable;
import cn.axzo.workflow.common.model.request.bpmn.definition.BpmnProcessDefinitionUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.log.LogApproveSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelUpdateDTO;
@ -81,38 +24,69 @@ import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocTenantQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigUpsertDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.RestPrintTemplateConfigDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.request.category.CategoryConfigCreateDTO;
import cn.axzo.workflow.common.model.request.category.CategoryConfigSearchDTO;
import cn.axzo.workflow.common.model.request.category.CategoryCreateDTO;
import cn.axzo.workflow.common.model.request.category.CategoryGroupVarSearchDto;
import cn.axzo.workflow.common.model.request.category.CategoryGroupVarUpsertDto;
import cn.axzo.workflow.common.model.request.category.CategorySearchDTO;
import cn.axzo.workflow.common.model.request.category.CategoryUpdateDTO;
import cn.axzo.workflow.common.model.request.es.InstanceSearchReqDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.admin.ProcessAdminVo;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelExtVO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.common.model.response.print.PrintModelDTO;
import cn.axzo.workflow.common.model.request.bpmn.RestBpmnProcessVariable;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditWithFormDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ExtProcessLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
import cn.axzo.workflow.common.model.response.category.CategoryConfigItemVO;
import cn.axzo.workflow.common.model.response.category.CategoryGroupVarItemVo;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import cn.axzo.workflow.common.model.response.es.ProcessInstanceDocumentVO;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.print.PrintModelDTO;
import cn.axzo.workflow.common.util.ThreadUtil;
import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import cn.axzo.workflow.common.model.request.bpmn.definition.BpmnProcessDefinitionUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;
/**
* Workflow Engine Starter Management Service
@ -124,18 +98,27 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;
@org.springframework.cloud.openfeign.FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = WorkflowEngineStarterFeignConfiguration.class)
public interface WorkflowManageService {
@Operation(summary = "查询指定审批流程是否能打印,打印开关是否开启,是否存在打印模板")
@GetMapping("/api/print/admin/template/exists")
@InvokeMode(SYNC)
Boolean hasPrintTemplate(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);
/**
* 获取打印模板中可打印的字段
*
* @param dto
* @return
*/
@Operation(summary = "获取打印模板中可打印的字段")
@PostMapping("/api/print/admin/fields")
@Manageable
@InvokeMode(SYNC)
List<PrintFieldDTO> getPrintFields(@Validated @RequestBody PrintFieldQueryDTO dto);
/**
* 获取指定流程下用于替换打印的相关变量
*
* @param processInstanceId
* @return
*/
@Operation(summary = "获取指定流程下用于替换打印的相关变量")
@GetMapping("/api/print/admin/field/variables")
@Manageable
@InvokeMode(SYNC)
Map<String, Object> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);
@ -202,6 +185,29 @@ public interface WorkflowManageService {
@InvokeMode(SYNC)
Integer batchDeleteProcessAdmin(@RequestBody List<Long> ids);
/**
* 业务节点唤醒, 该节点废弃请换成 {@link ProcessActivityApi#trigger(cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO)} 接口
* <p>
* 当模型中使用了业务节点且设置了不设置审批人模式则当业务监听到 PROCESS_ACTIVITY_START 事件时可通过该接口推动流程继续运行
*/
@Deprecated
@GetMapping("/api/process/activity/trigger")
@Manageable
@InvokeMode(SYNC)
Boolean trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId);
@Operation(summary = "获取指定枚举类型的枚举值信息")
@GetMapping("/api/function/enum/admin-data-source/get")
@Manageable
@InvokeMode(SYNC)
AdminDataSource getAdminDataSourceEnum(@RequestParam String enumValue);
@Operation(summary = "获取指定枚举类型的枚举值信息")
@GetMapping("/api/function/enum/process-instance-result/get")
@Manageable
@InvokeMode(SYNC)
BpmnProcessInstanceResultEnum getFileTypeEnum(@RequestParam String enumValue);
@PostMapping("/api/form/admin/form/page")
@InvokeMode(SYNC)
@Manageable
@ -221,18 +227,6 @@ public interface WorkflowManageService {
@Manageable
Boolean superCancelProcessInstance(@Validated @RequestBody SuperBpmnProcessInstanceCancelDTO dto);
/**
* 抄送流程实例未实现
*
* @param dto
* @return
*/
@Operation(summary = "抄送流程实例")
@PostMapping("/api/process/instance/carbon-copy")
@Deprecated
@Manageable
Boolean carbonCopyProcessInstance(@Validated @RequestBody BpmnProcessInstanceCarbonCopyDTO dto);
/**
* 查询所有的审批流
*
@ -675,17 +669,6 @@ public interface WorkflowManageService {
@InvokeMode(SYNC)
List<String> getModelTenantIds();
/**
* 打印模板配置内容更新保存
*
* @param dto
* @return
*/
@Operation(summary = "打印模板配置内容更新保存")
@PostMapping("/api/process/model/print/template/upsert")
@InvokeMode(SYNC)
Void printTemplateConfig(@Validated @RequestBody PrintTemplateConfigUpsertDTO dto);
/**
* 获取打印模板配置内容
*

View File

@ -0,0 +1,35 @@
package cn.axzo.workflow.starter.handler;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.model.response.mq.DocChangeDTO;
import org.springframework.core.Ordered;
/**
* 流程模板关联的文档配置变更事件
*
* @author wangli
* @since 2025-09-29 11:00
*/
public interface DocEventHandler extends Ordered {
/**
* 针对当前接口的实现进行过滤, true 往下执行下面的方法
*
* @param dto
* @param event
* @param context
* @return
*/
default boolean accept(DocChangeDTO dto, Event event, EventConsumer.Context context) {
return true;
}
/**
* 文档配置变更
*
* @param dto
*/
default void changed(DocChangeDTO dto) {
}
}

View File

@ -0,0 +1,21 @@
package cn.axzo.workflow.starter.handler.filter;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.model.response.mq.DocChangeDTO;
import cn.axzo.workflow.common.model.response.mq.ProcessActivityDTO;
import cn.axzo.workflow.starter.mq.broadcast.filter.BasicMessageQueueFilter;
/**
* DocChangeEvent 的自定义过滤接口
*
* <p>
* 该接口的实现是会全局过滤比如当应用需要监听多个流程模型时全局过滤会不精确所以我们还提供了针对 {@link cn.axzo.workflow.starter.handler.DocEventHandler#accept(ProcessActivityDTO, Event, EventConsumer.Context)} 实例的专属过滤
* <p>
* 注意Order 的顺序遵循值越小越优先取值范围Integer. MIN_VALUE - Integer. MAX_VALUE
*
* @author wangli
* @since 2025-09-29 11:09
*/
public interface DocEventFilter extends BasicMessageQueueFilter<DocChangeDTO> {
}

View File

@ -1,5 +1,7 @@
package cn.axzo.workflow.starter.handler.filter;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.model.response.mq.MessagePushDTO;
import cn.axzo.workflow.starter.handler.MessageNotificationEventHandler;
import cn.axzo.workflow.starter.mq.broadcast.filter.BasicMessageQueueFilter;
@ -7,7 +9,7 @@ import cn.axzo.workflow.starter.mq.broadcast.filter.BasicMessageQueueFilter;
/**
* MessageNotificationEvent 的自定义过滤接口
* <p>
* 该接口的实现是会全局过滤比如当应用需要监听多个流程模型时全局过滤会不精确所以我们还提供了针对 {@link MessageNotificationEventHandler#filter(MessagePushDTO)} 实例的专属过滤
* 该接口的实现是会全局过滤比如当应用需要监听多个流程模型时全局过滤会不精确所以我们还提供了针对 {@link MessageNotificationEventHandler#accept(MessagePushDTO, Event, EventConsumer.Context)} 实例的专属过滤
* <p>
* 注意Order 的顺序遵循值越小越优先取值范围Integer. MIN_VALUE - Integer. MAX_VALUE
*

View File

@ -1,5 +1,7 @@
package cn.axzo.workflow.starter.handler.filter;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.model.response.mq.ProcessActivityDTO;
import cn.axzo.workflow.starter.handler.ProcessActivityEventHandler;
import cn.axzo.workflow.starter.mq.broadcast.filter.BasicMessageQueueFilter;
@ -7,7 +9,7 @@ import cn.axzo.workflow.starter.mq.broadcast.filter.BasicMessageQueueFilter;
/**
* ProcessActivityEvent 自定义的过滤接口
* <p>
* 该接口的实现是会全局过滤比如当应用需要监听多个流程模型时全局过滤会不精确所以我们还提供了针对 {@link ProcessActivityEventHandler#filter(ProcessActivityDTO)} 实例的专属过滤
* 该接口的实现是会全局过滤比如当应用需要监听多个流程模型时全局过滤会不精确所以我们还提供了针对 {@link ProcessActivityEventHandler#accept(ProcessActivityDTO, Event, EventConsumer.Context)} 实例的专属过滤
* <p>
* 注意Order 的顺序遵循值越小越优先取值范围Integer. MIN_VALUE - Integer. MAX_VALUE
*

View File

@ -0,0 +1,66 @@
package cn.axzo.workflow.starter.mq.broadcast.consumer;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.enums.DocChangeEventEnum;
import cn.axzo.workflow.common.model.response.mq.DocChangeDTO;
import cn.axzo.workflow.starter.handler.DocEventHandler;
import cn.axzo.workflow.starter.handler.execute.ListenerExecutor;
import cn.axzo.workflow.starter.handler.filter.DocEventFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author wangli
* @since 2025-09-29 10:57
*/
public class InnerDocEventListener extends AbstractInnerWorkflowListener<DocEventHandler, DocEventFilter, DocChangeDTO> {
private final Logger log = LoggerFactory.getLogger(InnerDocEventListener.class);
public final static Supplier<List<Event.EventCode>> SUPPORTED_EVENT_CODES_SUPPLIER = () ->
Arrays.stream(DocChangeEventEnum.values()).map(DocChangeEventEnum::getEventCode)
.collect(Collectors.toList());
public InnerDocEventListener(ListenerExecutor listenerExecutor,
ObjectProvider<List<DocEventHandler>> handlerProvider,
ObjectProvider<List<DocEventFilter>> filterProvider) {
super(listenerExecutor, handlerProvider, filterProvider);
}
@Override
protected DocChangeDTO convert(Event event) {
return event.normalizedData(DocChangeDTO.class);
}
@Override
protected void onEvent(DocChangeDTO dto, Event event, EventConsumer.Context context) {
log.debug("【{}】new message begin processing, messageId: {}",
this.getClass().getSimpleName(), context.getMsgId());
DocChangeEventEnum type = dto.getType();
for (DocEventHandler activityListener : businessListeners) {
Consumer<DocChangeDTO> consumer = null;
switch (type) {
case DOC_CHANGE:
consumer = activityListener::changed;
break;
default:
log.warn("unknown process activity event type: {}", type);
}
if (activityListener.accept(dto, event, context)) {
listenerExecutor.execute(consumer, context, dto);
}
}
}
@Override
protected List<Event.EventCode> getSupportEventCodes() {
return SUPPORTED_EVENT_CODES_SUPPLIER.get();
}
}

View File

@ -26,7 +26,9 @@ public class WorkflowEngineBroadcastEventListener implements EventHandler, Initi
private final List<InnerWorkflowListener> workflowListeners;
public WorkflowEngineBroadcastEventListener(EventConsumer eventConsumer, WorkflowEngineStarterProperties workflowEngineStarterProperties, List<InnerWorkflowListener> workflowListeners) {
public WorkflowEngineBroadcastEventListener(EventConsumer eventConsumer,
WorkflowEngineStarterProperties workflowEngineStarterProperties,
List<InnerWorkflowListener> workflowListeners) {
this.eventConsumer = eventConsumer;
this.starterProperties = workflowEngineStarterProperties;
this.workflowListeners = workflowListeners;
@ -64,6 +66,7 @@ public class WorkflowEngineBroadcastEventListener implements EventHandler, Initi
eventConsumer.registerHandlers(InnerInstanceEventListener.SUPPORTED_EVENT_CODES_SUPPLIER.get(), this);
eventConsumer.registerHandlers(InnerNotificationEventListener.SUPPORTED_EVENT_CODES_SUPPLIER.get(), this);
eventConsumer.registerHandlers(InnerTaskEventListener.SUPPORTED_EVENT_CODES_SUPPLIER.get(), this);
eventConsumer.registerHandlers(InnerDocEventListener.SUPPORTED_EVENT_CODES_SUPPLIER.get(), this);
}
}

View File

@ -1,12 +1,23 @@
package cn.axzo.workflow.starter.mq.check;
import cn.axzo.framework.rocketmq.DefaultEventConsumer;
import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandler;
import cn.axzo.framework.rocketmq.EventHandlerRepository;
import cn.axzo.workflow.common.enums.ProcessInstanceEventEnum;
import cn.axzo.workflow.common.model.request.feature.DingTalkStarterAlterDTO;
import cn.axzo.workflow.common.model.response.mq.ProcessInstanceDTO;
import cn.axzo.workflow.starter.api.WorkflowCoreService;
import cn.axzo.workflow.starter.handler.ProcessInstanceEventHandler;
import com.google.common.collect.ListMultimap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@ -31,19 +42,82 @@ public class ImplementationReadyChecker implements ApplicationListener<Applicati
"onAborted"
);
private static final List<Event.EventCode> EVENT_CODES = Arrays.asList(
ProcessInstanceEventEnum.PROCESS_INSTANCE_COMPLETED.getEventCode(),
ProcessInstanceEventEnum.PROCESS_INSTANCE_CANCELLED.getEventCode(),
ProcessInstanceEventEnum.PROCESS_INSTANCE_REJECTED.getEventCode(),
ProcessInstanceEventEnum.PROCESS_INSTANCE_ABORTED.getEventCode()
);
private final WorkflowCoreService workflowCoreService;
public ImplementationReadyChecker(WorkflowCoreService workflowCoreService) {
this.workflowCoreService = workflowCoreService;
}
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
ApplicationContext context = event.getApplicationContext();
// 获取所有实现了目标接口的Bean
Map<String, ProcessInstanceEventHandler> handlers = context.getBeansOfType(TARGET_INTERFACE);
if (handlers.isEmpty()) {
log.warn("未找到实现 {} 接口的Bean, 请确保至少有一个实现类被正确扫描和注册。", TARGET_INTERFACE.getName());
boolean[] methodImplemented = checkUnImplementedMethodsWithInterface(context);
if (getBinaryResult(methodImplemented) == 15) {
log.info("Congratulations, passed the verification");
log.info("祝贺,已通过必接事件的校验!但仍然请确保您的实现类逻辑正确无误,不允许出现空实现,否则生产问题自行负责!");
return;
}
log.warn("将继续通过 EventConsumer 进行检查...");
boolean[] methodImplemented2 = checkUnImplementedMethodsWithEventConsumer(context);
if (getBinaryResult(methodImplemented2) == 15) {
log.info("Congratulations, passed the verification");
log.info("祝贺,已通过必接事件的校验!但仍然请确保您的实现类逻辑正确无误,不允许出现空实现,否则生产问题自行负责!");
} else {
int finalResult = getBinaryResult(methodImplemented) | getBinaryResult(methodImplemented2);
boolean[] booleansAdaptive = toBooleansAdaptive(finalResult);
log.warn("----------------------------------------");
log.warn("最终事件实现情况:(二进制:{})(十进制:{})", String.format("%4s", Integer.toBinaryString(finalResult)).replace(' ', '0'), finalResult);
log.warn("警告:未通过必接事件的校验!未实现的方法:{},请确保实现了 {} 接口的Bean被Spring扫描或者在EventConsumer注册了 ProcessInstanceEventEnum 的 EventCode。", String.join(", ", getUnImplementedMethods(booleansAdaptive)), TARGET_INTERFACE.getName());
log.warn("----------------------------------------");
sendAlter(context, getUnImplementedMethods(booleansAdaptive));
}
}
public static boolean[] toBooleansAdaptive(int value) {
if (value < 0) throw new IllegalArgumentException("adaptive mode only for non-negative");
if (value == 0) return new boolean[]{false};
int bits = 32 - Integer.numberOfLeadingZeros(value);
return toBooleans(value, bits);
}
// 高位在前index=0 是最高位
public static boolean[] toBooleans(int value, int bits) {
if (bits <= 0 || bits > 32) throw new IllegalArgumentException("bits must be 1~32");
boolean[] arr = new boolean[bits];
for (int i = 0; i < bits; i++) {
int shift = bits - 1 - i;
arr[i] = ((value >>> shift) & 1) == 1;
}
return arr;
}
private void sendAlter(ApplicationContext context, List<String> unImplementedMethods) {
Environment environment = context.getEnvironment();
DingTalkStarterAlterDTO dto = new DingTalkStarterAlterDTO();
dto.setApplicationName(environment.getProperty("spring.application.name"));
dto.setProfile(environment.getProperty("spring.profiles.active"));
dto.setAlterContent("必接事件实现类检查未通过,未实现的方法: " + String.join(", ", unImplementedMethods) + "。请确保至少有一个实现类覆盖这些方法以处理相应的事件。");
workflowCoreService.sendDingtalk(dto);
}
private static boolean[] checkUnImplementedMethodsWithInterface(ApplicationContext context) {
// 记录每个方法是否被实现
boolean[] methodImplemented = new boolean[4];
Arrays.fill(methodImplemented, false);
// 获取所有实现了目标接口的Bean
Map<String, ProcessInstanceEventHandler> handlers = context.getBeansOfType(TARGET_INTERFACE);
if (handlers.isEmpty()) {
log.warn("未找到实现 {} 接口的Bean ", TARGET_INTERFACE.getName());
return methodImplemented;
}
// 检查每个实现类
for (ProcessInstanceEventHandler handler : handlers.values()) {
@ -63,7 +137,60 @@ public class ImplementationReadyChecker implements ApplicationListener<Applicati
}
}
}
int binaryResult = getBinaryResult(methodImplemented);
List<String> unimplementedMethods = getUnImplementedMethods(methodImplemented);
log.info("实现 {} 接口的Bean数量: {}", TARGET_INTERFACE.getName(), handlers.size());
log.warn("基于接口事件实现情况:(二进制:{})(十进制:{})", String.format("%4s", Integer.toBinaryString(binaryResult)).replace(' ', '0'), binaryResult);
if (!unimplementedMethods.isEmpty()) {
log.info("未通过 Starter 提供的 {} 接口实现中找到以下方法的实现: {}。请确保至少有一个实现类覆盖这些方法以处理相应的事件。", TARGET_INTERFACE.getName(), String.join(", ", unimplementedMethods));
}
return methodImplemented;
}
private static boolean[] checkUnImplementedMethodsWithEventConsumer(ApplicationContext context) {
// 记录每个方法是否被实现
boolean[] methodImplemented = new boolean[4];
Arrays.fill(methodImplemented, false);
Map<String, EventConsumer> beansOfType = context.getBeansOfType(EventConsumer.class);
beansOfType.forEach((name, c) -> {
if (c instanceof DefaultEventConsumer) {
try {
Field repoField = DefaultEventConsumer.class.getDeclaredField("handlerRepository");
repoField.setAccessible(true);
EventHandlerRepository repo = (EventHandlerRepository) repoField.get(c);
Field handlersField = EventHandlerRepository.class.getDeclaredField("handlers");
handlersField.setAccessible(true);
@SuppressWarnings("unchecked")
ListMultimap<Event.EventCode, EventHandler> eventHandlers =
(ListMultimap<Event.EventCode, EventHandler>) handlersField.get(repo);
for (int i = 0; i < EVENT_CODES.size(); i++) {
methodImplemented[i] = eventHandlers.keySet().contains(EVENT_CODES.get(i));
}
} catch (Exception e) {
log.warn("通过 EventConsumer 检测必接事件异常:{}", e.getMessage(), e);
}
}
});
int binaryResult = getBinaryResult(methodImplemented);
log.warn("基于EventConsumer事件实现情况(二进制:{})(十进制:{})", String.format("%4s", Integer.toBinaryString(binaryResult)).replace(' ', '0'), binaryResult);
return methodImplemented;
}
private static List<String> getUnImplementedMethods(boolean[] methodImplemented) {
// 收集未实现的方法
List<String> unimplementedMethods = new ArrayList<>();
for (int i = 0; i < methodImplemented.length; i++) {
if (!methodImplemented[i]) {
unimplementedMethods.add(METHOD_NAMES.get(i));
}
}
return unimplementedMethods;
}
private static int getBinaryResult(boolean[] methodImplemented) {
// 生成4位二进制数
int binaryResult = 0;
for (int i = 0; i < methodImplemented.length; i++) {
@ -73,22 +200,6 @@ public class ImplementationReadyChecker implements ApplicationListener<Applicati
binaryResult += weight;
}
}
// 收集未实现的方法
List<String> unimplementedMethods = new ArrayList<>();
for (int i = 0; i < methodImplemented.length; i++) {
if (!methodImplemented[i]) {
unimplementedMethods.add(METHOD_NAMES.get(i));
}
}
log.warn("实现 {} 接口的Bean数量: {}", TARGET_INTERFACE.getName(), handlers.size());
log.warn("方法实现情况:(二进制:{})(十进制:{})", String.format("%4s", Integer.toBinaryString(binaryResult)).replace(' ', '0'), binaryResult);
if (!unimplementedMethods.isEmpty()) {
log.error("以下方法未被任何实现类覆盖: {}。请确保至少有一个实现类覆盖这些方法以处理相应的事件。", String.join(", ", unimplementedMethods));
} else {
log.warn("Congratulations, passed the verification");
log.warn("祝贺,已通过必接事件的校验!但仍然请确保您的实现类逻辑正确无误,不允许出现空实现,否则生产问题自行负责!");
}
return binaryResult;
}
}