diff --git a/README.md b/README.md index b0277fd54..eee2a451c 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统。 * 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能。 * 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装。 -* 工作流使用 Activiti + Flowable,支持动态表单、在线设计流程、多种任务分配方式。 +* 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式。 * 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验。 * 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款。 * 集成阿里云、腾讯云、云片等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务。 @@ -167,7 +167,7 @@ ps:核心功能已经实现,正在对接微信小程序中... | [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.16 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | | [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.5.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.2 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | -| [Activiti](https://github.com/Activiti/Activiti) | 工作流引擎 | 7.1.0.M6 | [文档](TODO) | +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.0 | [文档](https://doc.iocoder.cn/bpm/) | | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index 02e4ff6fe..35880d110 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -25,7 +25,6 @@ yudao-spring-boot-starter-excel yudao-spring-boot-starter-test - yudao-spring-boot-starter-extension yudao-spring-boot-starter-biz-operatelog yudao-spring-boot-starter-biz-dict diff --git a/yudao-framework/yudao-spring-boot-starter-extension/pom.xml b/yudao-framework/yudao-spring-boot-starter-extension/pom.xml deleted file mode 100644 index 3da9572c4..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - yudao-framework - cn.iocoder.boot - ${revision} - - 4.0.0 - - yudao-spring-boot-starter-extension - jar - - ${project.artifactId} - 扩展点组件 - https://github.com/YunaiV/ruoyi-vue-pro - - - - - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework - spring-context - provided - - - - org.springframework - spring-beans - provided - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - junit - junit - test - - - - - jakarta.validation - jakarta.validation-api - - - \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/config/YudaoExtensionAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/config/YudaoExtensionAutoConfiguration.java deleted file mode 100644 index 8b047ae1b..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/config/YudaoExtensionAutoConfiguration.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.iocoder.yudao.framework.extension.config; - -import cn.iocoder.yudao.framework.extension.core.ExtensionBootstrap; -import cn.iocoder.yudao.framework.extension.core.context.ExtensionContext; -import cn.iocoder.yudao.framework.extension.core.context.ExtensionContextHolder; -import cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor; -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory; -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @description 扩展点组件自动装配 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 21:50 - * @class cn.iocoder.yudao.framework.extension.config.YudaoExtensionAutoConfiguration.java - */ -@Configuration -public class YudaoExtensionAutoConfiguration { - - /** - * 组件初始化 - * @return - */ - @Bean(initMethod = "init") - @ConditionalOnMissingBean(ExtensionBootstrap.class) - public ExtensionBootstrap bootstrap() { - return new ExtensionBootstrap(); - } - - /** - * 扩展点工厂 - * @return - */ - @Bean - @ConditionalOnMissingBean({ExtensionRegisterFactory.class, ExtensionFactory.class}) - public ExtensionRegisterFactory registerFactory() { - return new ExtensionRegisterFactory(); - } - - /** - * 扩展组件上下文对象 - * @return - */ - @Bean - @ConditionalOnMissingBean({ExtensionContextHolder.class, ExtensionContext.class}) - public ExtensionContextHolder context() { - return new ExtensionContextHolder(); - } - - /** - * 扩展组件执行器 - * @return - */ - @Bean - @ConditionalOnMissingBean(ExtensionExecutor.class) - public ExtensionExecutor executor() { - return new ExtensionExecutor(); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/BusinessScenario.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/BusinessScenario.java deleted file mode 100644 index 732350c67..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/BusinessScenario.java +++ /dev/null @@ -1,142 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core; - -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.StringJoiner; - -/** - * @description 业务场景 = businessId + useCase + scenario, 用来标识系统中唯一的一个场景
- * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 22:19 - * @class cn.iocoder.yudao.framework.extension.core.BusinessScenario.java - */ -public class BusinessScenario implements Serializable { - - /** - * 默认业务id - */ - public final static String DEFAULT_BUSINESS_ID = "#defaultBusinessId#"; - - /** - * 默认用例 - */ - public final static String DEFAULT_USECASE = "#defaultUseCase#"; - - /** - * 默认场景 - */ - public final static String DEFAULT_SCENARIO = "#defaultScenario#"; - - /** - * 分隔符 - */ - private final static String DOT_SEPARATOR = "."; - - /** - * 业务Id - */ - private String businessId; - - /** - * 用例 - */ - private String useCase; - - /** - * 场景 - */ - private String scenario; - - public BusinessScenario() { - this.businessId = DEFAULT_BUSINESS_ID; - this.useCase = DEFAULT_USECASE; - this.scenario = DEFAULT_SCENARIO; - } - - public BusinessScenario(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario) { - this.businessId = businessId; - this.useCase = useCase; - this.scenario = scenario; - } - - public BusinessScenario(@NotNull String scenario) { - this(); - this.scenario = scenario; - } - - public BusinessScenario(@NotNull String useCase, @NotNull String scenario) { - this(DEFAULT_BUSINESS_ID, useCase, scenario); - } - - public String getBusinessId() { - return businessId; - } - - public void setBusinessId(String businessId) { - this.businessId = businessId; - } - - public String getUseCase() { - return useCase; - } - - public void setUseCase(String useCase) { - this.useCase = useCase; - } - - public String getScenario() { - return scenario; - } - - public void setScenario(String scenario) { - this.scenario = scenario; - } - - /** - * 构建业务场景 - * @param businessId - * @param useCase - * @param scenario - * @return - */ - public static BusinessScenario valueOf(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario) { - return new BusinessScenario(businessId, useCase, scenario); - } - - /** - * 构建业务场景 - * @param useCase - * @param scenario - * @return - */ - public static BusinessScenario valueOf(@NotNull String useCase, @NotNull String scenario) { - return new BusinessScenario(useCase, scenario); - } - - /** - * 构建业务场景 - * @param scenario - * @return - */ - public static BusinessScenario valueOf(@NotNull String scenario) { - return new BusinessScenario(scenario); - } - - /** - * 业务场景唯一标识 - * @return - */ - public String getUniqueIdentity(){ - return new StringJoiner(DOT_SEPARATOR).add(businessId).add(useCase).add(scenario).toString(); - } - - @Override - public String toString() { - return "BusinessScenario{" + - "businessId='" + businessId + '\'' + - ", useCase='" + useCase + '\'' + - ", scenario='" + scenario + '\'' + - '}'; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/ExtensionBootstrap.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/ExtensionBootstrap.java deleted file mode 100644 index 800c431be..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/ExtensionBootstrap.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core; - -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -import javax.annotation.PostConstruct; - -/** - * @description - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-29 00:18 - * @class cn.iocoder.yudao.framework.extension.core.ExtensionBootstrap.java - */ -public class ExtensionBootstrap implements ApplicationContextAware { - - /** - * spring 容器 - */ - private ApplicationContext applicationContext; - - @Autowired - private ExtensionRegisterFactory registerFactory; - - /** - * 初始化 - */ - @PostConstruct - public void init() { - registerFactory.setApplicationContext(applicationContext); - registerFactory.register(null); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/AbstractComponentExecutor.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/AbstractComponentExecutor.java deleted file mode 100644 index f46d05d90..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/AbstractComponentExecutor.java +++ /dev/null @@ -1,131 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.context; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * @description 执行器通用方法 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-29 00:38 - * @class cn.iocoder.yudao.framework.extension.core.context.AbstractComponentExecutor.java - */ -public abstract class AbstractComponentExecutor { - - /** - * ("业务" + "用例" + "场景")执行扩展组件,并返回执行结果 - * @param targetClazz - * @param businessId - * @param useCase - * @param scenario - * @param function - * @param - * @param - * @return - */ - public R execute(Class targetClazz, String businessId, String useCase, String scenario, Function function) { - return execute(targetClazz, BusinessScenario.valueOf(businessId, useCase, scenario), function); - } - - - /** - * ("用例" + "场景")执行扩展组件,并返回执行结果 - * @param targetClazz - * @param useCase - * @param scenario - * @param function - * @param - * @param - * @return - */ - public R execute(Class targetClazz, String useCase, String scenario, Function function) { - return execute(targetClazz, BusinessScenario.valueOf(useCase, scenario), function); - } - - /** - * ("场景")执行扩展组件,并返回执行结果 - * @param targetClazz - * @param scenario - * @param function - * @param - * @param - * @return - */ - public R execute(Class targetClazz, String scenario, Function function) { - return execute(targetClazz, BusinessScenario.valueOf(scenario), function); - } - - /** - * 执行扩展组件,并返回执行结果 - * @param targetClazz - * @param businessScenario - * @param function - * @param Response Type - * @param Parameter Type - * @return - */ - public R execute(Class targetClazz, BusinessScenario businessScenario, Function function) { - T component = locateComponent(targetClazz, businessScenario); - return function.apply(component); - } - - /** - * ("业务" + "用例" + "场景")执行扩展组件,适用于无返回值的业务 - * @param targetClazz - * @param businessId - * @param useCase - * @param scenario - * @param consumer - * @param - */ - public void accept(Class targetClazz, String businessId, String useCase, String scenario, Consumer consumer) { - accept(targetClazz, BusinessScenario.valueOf(businessId, useCase, scenario), consumer); - } - - /** - * ("场景")执行扩展组件,适用于无返回值的业务 - * @param targetClazz - * @param useCase - * @param scenario - * @param consumer - * @param - */ - public void accept(Class targetClazz, String useCase, String scenario, Consumer consumer) { - accept(targetClazz, BusinessScenario.valueOf(useCase, scenario), consumer); - } - - /** - * ("场景")执行扩展组件,适用于无返回值的业务 - * @param targetClazz - * @param scenario - * @param consumer - * @param - */ - public void accept(Class targetClazz, String scenario, Consumer consumer) { - accept(targetClazz, BusinessScenario.valueOf(scenario), consumer); - } - - /** - * 执行扩展组件,适用于无返回值的业务 - * @param targetClazz - * @param businessScenario - * @param consumer - * @param Parameter Type - */ - public void accept(Class targetClazz, BusinessScenario businessScenario, Consumer consumer) { - T component = locateComponent(targetClazz, businessScenario); - consumer.accept(component); - } - - /** - * 获取/定位扩展点组件 - * @param targetClazz - * @param businessScenario - * @param - * @return - */ - protected abstract C locateComponent(Class targetClazz, BusinessScenario businessScenario); -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContext.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContext.java deleted file mode 100644 index 5704cc49f..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContext.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.context; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; - -/** - * @description 上下文,包含各个扩展点的相关操作 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 22:15 - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionContext.java - */ -public interface ExtensionContext { - - /** - * 根据业务场景唯一标识获取扩展点组件实现类 - * @param businessId - * @param useCase - * @param scenario - * @param clazz - * @param - * @return - */ - T getPoint(String businessId, String useCase, String scenario, Class clazz); - - /** - * 根据("实例" + "场景")获取扩展点组件实现类,其中:业务id(businessId)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_BUSINESS_ID} - * @param useCase - * @param scenario - * @param clazz - * @param - * @return - */ - T getPoint(String useCase, String scenario, Class clazz); - - /** - * 根据("场景")获取扩展点组件实现类
- * 其中: - * 业务id(businessId)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_BUSINESS_ID} - * 实例(useCase)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_USECASE} - * @param scenario - * @param clazz - * @param - * @return - */ - T getPoint(String scenario, Class clazz); - - /** - * 根据业务场景唯一标识获取扩展点组件实现类 - * @param businessScenario - * @param clazz - * @param - * @return - */ - T getPoint(BusinessScenario businessScenario, Class clazz); -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContextHolder.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContextHolder.java deleted file mode 100644 index 6e121b70d..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContextHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.context; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.validation.constraints.NotNull; - -/** - * @description 上下文及扩展点组件工厂的持有类 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-29 00:29 - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionContextHolder.java - */ -@Component -@Slf4j -public class ExtensionContextHolder implements ExtensionContext{ - - @Autowired - private ExtensionFactory factory; - - @Override - public T getPoint(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario, Class clazz) { - return getPoint(BusinessScenario.valueOf(businessId, useCase, scenario), clazz); - } - - @Override - public T getPoint(@NotNull String useCase, String scenario, Class clazz) { - return getPoint(BusinessScenario.valueOf(useCase, scenario), clazz); - } - - @Override - public T getPoint(@NotNull String scenario, Class clazz) { - return getPoint(BusinessScenario.valueOf(scenario), clazz); - } - - @Override - public T getPoint(@NotNull BusinessScenario businessScenario, Class clazz) { - return factory.get(businessScenario, clazz); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionExecutor.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionExecutor.java deleted file mode 100644 index 5f48652e5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionExecutor.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.context; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * @description 扩展组件执行器 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-29 00:32 - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor.java - */ -@Component -@Slf4j -public class ExtensionExecutor extends AbstractComponentExecutor{ - - @Autowired - private ExtensionContextHolder contextHolder; - - - @Override - protected C locateComponent(Class targetClazz, BusinessScenario businessScenario) { - return contextHolder.getPoint(businessScenario, targetClazz); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionDefinition.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionDefinition.java deleted file mode 100644 index 5feed6660..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionDefinition.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.factory; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; -import lombok.Getter; -import lombok.Setter; - -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Objects; - -/** - * @description 扩展定义(扩展坐标),标识唯一一个业务场景实现 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 23:14 - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionDefinition.java - */ -@Setter -@Getter -public class ExtensionDefinition implements Serializable { - - /** - * 业务场景唯一标识(id) - */ - private String uniqueIdentify; - - /** - * 扩展点实现类名称 - */ - private String extensionPointName; - - /** - * 业务场景 - */ - private BusinessScenario businessScenario; - - /** - * 扩展点实现类 - */ - private ExtensionPoint extensionPoint; - - /** - * class - */ - private Class extensionPointClass; - - public ExtensionDefinition() { - } - - public ExtensionDefinition(@NotNull BusinessScenario businessScenario, @NotNull ExtensionPoint extensionPoint) { - this.businessScenario = businessScenario; - this.extensionPoint = extensionPoint; - this.uniqueIdentify = this.businessScenario.getUniqueIdentity(); - this.extensionPointClass = this.extensionPoint.getClass(); - } - - /** - * 构建definition - * @param businessScenario - * @param point - * @return - */ - public static ExtensionDefinition valueOf(@NotNull BusinessScenario businessScenario, @NotNull ExtensionPoint point) { - return new ExtensionDefinition(businessScenario, point); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ExtensionDefinition that = (ExtensionDefinition) o; - return Objects.equals(uniqueIdentify, that.uniqueIdentify) && Objects.equals(extensionPointName, that.extensionPointName); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((uniqueIdentify == null) ? 0 : uniqueIdentify.hashCode()); - result = prime * result + ((extensionPointName == null) ? 0 : extensionPointName.hashCode()); - return result; - } - - @Override - public String toString() { - return "ExtensionDefinition{" + - "uniqueIdentify='" + uniqueIdentify + '\'' + - ", extensionPointName='" + extensionPointName + '\'' + - '}'; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionFactory.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionFactory.java deleted file mode 100644 index c03175c13..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.factory; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; - -/** - * @description 扩展点工厂 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 23:04 - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory.java - */ -public interface ExtensionFactory { - - /** - * 注册所有扩展点实现类 - * @param basePackage - */ - void register(String basePackage); - - /** - * 根据业务场景获取指定类型的扩展点 - * @param businessScenario - * @param clazz - * @param - * @return - */ - T get(BusinessScenario businessScenario, Class clazz); -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionRegisterFactory.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionRegisterFactory.java deleted file mode 100644 index 15b802436..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionRegisterFactory.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.factory; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; -import lombok.extern.slf4j.Slf4j; -import org.springframework.aop.support.AopUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.stereotype.Component; -import org.springframework.util.ClassUtils; - -import javax.validation.constraints.NotNull; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @description 注册工厂 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 23:07 - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory.java - */ -@Component -@Slf4j -public class ExtensionRegisterFactory implements ExtensionFactory { - - /** - * spring ApplicationContext - */ - private ApplicationContext applicationContext; - - /** - * 扩展点实现类集合 - */ - private Map registerExtensionBeans = new ConcurrentHashMap<>(); - - @Override - public void register(String basePackage) { - final Map beans = applicationContext.getBeansWithAnnotation(Extension.class); - if(beans == null || beans.isEmpty()) { - return; - } - - beans.values().forEach(point -> doRegister((ExtensionPoint) point)); - log.info("业务场景相关扩展点注册完成,注册数量: {}", registerExtensionBeans.size()); - } - - @Override - public T get(BusinessScenario businessScenario, Class clazz) { - - final ExtensionDefinition definition = registerExtensionBeans.get(businessScenario.getUniqueIdentity()); - if(definition == null) { - log.error("获取业务场景扩展点实现失败,失败原因:尚未定义该业务场景相关扩展点。{}", businessScenario); - throw new RuntimeException("尚未定义该业务场景相关扩展点 [" + businessScenario + "]"); - } - - return (T) definition.getExtensionPoint(); - } - - /** - * 注册扩展点 - * @param point - */ - private void doRegister(@NotNull ExtensionPoint point) { - Class extensionClazz = point.getClass(); - - if (AopUtils.isAopProxy(point)) { - extensionClazz = ClassUtils.getUserClass(point); - } - - Extension extension = AnnotationUtils.findAnnotation(extensionClazz, Extension.class); - final BusinessScenario businessScenario = BusinessScenario.valueOf(extension.businessId(), extension.useCase(), extension.scenario()); - final ExtensionDefinition definition = ExtensionDefinition.valueOf(businessScenario, point); - final ExtensionDefinition exist = registerExtensionBeans.get(businessScenario.getUniqueIdentity()); - if(exist != null && !exist.equals(definition)) { - throw new RuntimeException("相同的业务场景重复注册了不同类型的扩展点实现 :【" + definition + "】【" + exist + "】"); - } - - registerExtensionBeans.put(businessScenario.getUniqueIdentity(), definition); - } - - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/package-info.java deleted file mode 100644 index 636491eca..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @description core 核心 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 21:54 - * @class cn.iocoder.yudao.framework.extension.core.package-info.java - */ -package cn.iocoder.yudao.framework.extension.core; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/point/ExtensionPoint.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/point/ExtensionPoint.java deleted file mode 100644 index e1a86d791..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/point/ExtensionPoint.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.point; -/** - * @description 扩展点
- * 表示一块逻辑在不同的业务有不同的实现,使用扩展点做接口申明,然后用{@linkplain cn.iocoder.yudao.framework.extension.core.stereotype.Extension}(扩展)去实现扩展点。 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 22:06 - * @class cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint.java - */ -public interface ExtensionPoint { -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/stereotype/Extension.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/stereotype/Extension.java deleted file mode 100644 index eaa9f99f8..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/stereotype/Extension.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.framework.extension.core.stereotype; - -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import org.springframework.stereotype.Component; - -import java.lang.annotation.*; - -/** - * @description 表示带注释的类是“扩展组件” - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 21:59 - * @class cn.iocoder.yudao.framework.extension.core.stereotype.Extension.java - */ -@Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@Component -public @interface Extension { - - /** - * 业务
- * 一个自负盈亏的财务主体,比如tmall、淘宝和零售通就是三个不同的业务 - * @return - */ - String businessId() default BusinessScenario.DEFAULT_BUSINESS_ID; - - /** - * 用例
- * 描述了用户和系统之间的互动,每个用例提供了一个或多个场景。比如,支付订单就是一个典型的用例。 - * @return - */ - String useCase() default BusinessScenario.DEFAULT_USECASE; - - /** - * 场景
- * 场景也被称为用例的实例(Instance),包括用例所有的可能情况(正常的和异常的)。比如对于"订单支付"这个用例,就有“支付宝支付”、“银行卡支付”、"微信支付"等多个场景 - * @return - */ - String scenario() default BusinessScenario.DEFAULT_SCENARIO; -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/package-info.java b/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/package-info.java deleted file mode 100644 index 1c4ae94ae..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @description 扩展点组件 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-28 14:35 - * @class cn.iocoder.yudao.framework.extension.package-info.java - */ -package cn.iocoder.yudao.framework.extension; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-extension/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 82d14b8b0..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.extension.config.YudaoExtensionAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/Application.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/Application.java deleted file mode 100644 index a589affd3..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/Application.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.extension; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @description Application - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:32 - * @class cn.iocoder.yudao.framework.extension.Application.java - */ -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/ExtensionTest.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/ExtensionTest.java deleted file mode 100644 index aa3b900c3..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/ExtensionTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.framework.extension; - -import cn.hutool.core.util.IdUtil; -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; -import cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor; -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; -import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import java.math.BigDecimal; - -/** - * @description - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:30 - * @class cn.iocoder.yudao.framework.extension.ExtensionTest.java - */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = Application.class) -@Slf4j -public class ExtensionTest { - - @Autowired - private ExtensionExecutor extensionExecutor; - - @Test - public void unifiedOrder() { - final BusinessScenario scenario = BusinessScenario.valueOf("pay", "jsapi", "wechat"); - final TransactionsCommand command = new TransactionsCommand(IdUtil.objectId(), new BigDecimal(105), "Image形象店-深圳腾大-QQ公仔", "https://www.weixin.qq.com/wxpay/pay.php"); - final TransactionsResult result = extensionExecutor.execute(PayExtensionPoint.class, scenario, extension -> extension.unifiedOrder(command)); - log.info("result is: {}", JSONUtil.toJsonStr(result)); - Assert.assertSame("wechat", result.getChannel()); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/package-info.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/package-info.java deleted file mode 100644 index d0bc63e1c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @description - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:25 - * @class cn.iocoder.yudao.framework.extension.package-info.java - */ -package cn.iocoder.yudao.framework.extension; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/PayExtensionPoint.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/PayExtensionPoint.java deleted file mode 100644 index 9adc56b4c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/PayExtensionPoint.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.framework.extension.pay; - -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; - -/** - * @description 支付操作接口 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:35 - * @class cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint.java - */ -public interface PayExtensionPoint extends ExtensionPoint { - - /** - * 统一下单:获取"预支付交易会话标识" - * @param command - * @return - */ - TransactionsResult unifiedOrder(TransactionsCommand command); -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/command/TransactionsCommand.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/command/TransactionsCommand.java deleted file mode 100644 index 0ac1908dd..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/command/TransactionsCommand.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.framework.extension.pay.command; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.math.BigDecimal; - -/** - * @description 下单请求 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:48 - * @class cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand.java - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class TransactionsCommand implements Serializable { - /** - * 订单编号 - */ - private String orderNo; - - /** - * 支付金额 - */ - private BigDecimal amount; - - /** - * 商品描述 - */ - private String productDescription; - - /** - * 通知地址 - */ - private String notifyUrl; -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/domain/TransactionsResult.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/domain/TransactionsResult.java deleted file mode 100644 index 35861bbd0..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/domain/TransactionsResult.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.framework.extension.pay.domain; - -import lombok.*; - -import java.io.Serializable; - -/** - * @description 下单: 预支付交易单返回结果 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:43 - * @class cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult.java - */ -@Data -@AllArgsConstructor -public class TransactionsResult implements Serializable { - - /** - * 预支付交易会话标识 - */ - private String prepayId; - - /** - * 订单编号 - */ - private String orderNo; - - /** - * 系统内部支付单号 - */ - private String paymentNo; - - /** - * 支付渠道:微信 or 支付宝 - */ - private String channel; - - -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/AlipayService.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/AlipayService.java deleted file mode 100644 index 2daac2ff6..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/AlipayService.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.framework.extension.pay.impl; - -import cn.hutool.core.util.IdUtil; -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; -import lombok.extern.slf4j.Slf4j; - -/** - * @description 微信 JSAPI 支付 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:38 - * @class cn.iocoder.yudao.framework.extension.pay.impl.AlipayService.java - */ -@Extension(businessId = "pay", useCase = "jsapi", scenario = "alipay") -@Slf4j -public class AlipayService implements PayExtensionPoint { - @Override - public TransactionsResult unifiedOrder(TransactionsCommand command) { - log.info("微信 JSAPI 支付:{}", JSONUtil.toJsonStr(command)); - return new TransactionsResult("alipay26112221580621e9b071c00d9e093b0000", command.getOrderNo(), IdUtil.objectId(), "alipay"); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/WechatPayService.java b/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/WechatPayService.java deleted file mode 100644 index cae294092..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/WechatPayService.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.framework.extension.pay.impl; - -import cn.hutool.core.util.IdUtil; -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; -import lombok.extern.slf4j.Slf4j; - -/** - * @description 微信 JSAPI 支付 - * @author Qingchen - * @version 1.0.0 - * @date 2021-08-30 10:37 - * @class cn.iocoder.yudao.framework.extension.pay.impl.WechatPayService.java - */ -@Extension(businessId = "pay", useCase = "jsapi", scenario = "wechat") -@Slf4j -public class WechatPayService implements PayExtensionPoint { - @Override - public TransactionsResult unifiedOrder(TransactionsCommand command) { - log.info("微信 JSAPI 支付:{}", JSONUtil.toJsonStr(command)); - return new TransactionsResult("wx26112221580621e9b071c00d9e093b0000", command.getOrderNo(), IdUtil.objectId(), "wechat"); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-extension/《芋道 Spring Boot 扩展点组件》.md b/yudao-framework/yudao-spring-boot-starter-extension/《芋道 Spring Boot 扩展点组件》.md deleted file mode 100644 index 59ff2dcb3..000000000 --- a/yudao-framework/yudao-spring-boot-starter-extension/《芋道 Spring Boot 扩展点组件》.md +++ /dev/null @@ -1,19 +0,0 @@ -### 作用 - -​ 为了解决同一个流程不同业务有不同处理逻辑而产生,减少代码中 if else 逻辑,降低代码的耦合性,通过统一的扩展形式来支撑业务的变化。 - -### 原理 - -​ https://blog.csdn.net/significantfrank/article/details/100074716 - - - -### 使用介绍 - -参考测试代码 `cn.iocoder.yudao.framework.extension.ExtensionTest` - - - - - - diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java index 9d96dead9..eaa991f55 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java @@ -75,13 +75,4 @@ public class BpmTaskController { return success(true); } - @PutMapping("/back") - @ApiOperation(value = "回退") - // @PreAuthorize("@ss.hasPermission('bpm:task:back')") - public CommonResult backTask(@Valid @RequestBody BpmTaskBackReqVO reqVO) { - //先硬编码到 回退到第一个审批节点 - // String destinationTaskDefKey = "task01"; - return taskService.backTask(reqVO); - - } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java deleted file mode 100644 index f618781f2..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; - -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * @author kemengkai - * @create 2022-05-07 08:05 TODO ke:vo 类,使用 swagger 注解即可 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class BpmTaskBackReqVO { - - // TODO ke:userId 应该使用后端的,不能前端传递,不然就越权了 - @ApiModelProperty(value = "用户id", required = true, example = "1") - @NotEmpty(message = "用户id不能为空") - private String userId; - - // TODO ke:procInstId、taskId、oldTaskDefKey 三个,是不是只要传递一个 taskId?字段不要存在推导关系 - @ApiModelProperty(value = "流程编号id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0") - @NotEmpty(message = "流程编号id不能为空") - private String procInstId; - - @ApiModelProperty(value = "当前任务id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0") - @NotEmpty(message = "当前任务id不能为空") - private String taskId; - - @ApiModelProperty(value = "当前流程任务id", required = true, example = "Activity_1jlembv") - @NotNull(message = "当前流程任务id不能为空") - private String oldTaskDefKey; - - @ApiModelProperty(value = "准备回退的流程任务id", required = true, example = "task01") - @NotNull(message = "准备回退流程任务id不能为空") - private String newTaskDefKey; - - @ApiModelProperty(value = "审批结果", required = true, example = "任务驳回") - @NotNull(message = "审批结果") - private String reason; -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java index d855f6066..6683b536d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; @@ -24,28 +23,4 @@ public interface BpmTaskExtMapper extends BaseMapperX { return selectOne(BpmTaskExtDO::getTaskId, taskId); } - default List selectListByProcessInstanceId(String processInstanceId) { - return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId); - } - - // TODO @ke:可以使用类上上面的 default 方法实现。然后,方法的命名上,要保持和 db 一样。因为 mapper 是数据层,不关注业务。例如说,这里,其实复用 updateByTaskId 方法即可 - /** - * 任务驳回 - * - * @param taskId 任务列表 - * @param reason 驳回理由 - * - * @return 返回驳回结果,是否成功 - */ - Boolean backByTaskId(@Param("taskId") String taskId, @Param("reason") String reason); - - // TODO @ke:tong上哈 - /** - * 逻辑删除任务 - * - * @param taskIdList 任务id列表 - * - * @return 返回是否成功 - */ - Boolean delByTaskIds(@Param("taskIdList") List taskIdList); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java index cdbb0861c..b5c91ebad 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java @@ -5,7 +5,6 @@ import org.flowable.engine.delegate.DelegateExecution; import java.util.Set; -// TODO @芋艿:迁移到 bpm 的 core 下 /** * Bpm 任务分配的自定义 Script 脚本 * 使用场景: diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index def430100..13443282f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables)); BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables); asyncUpdateProcesInstance(bpmProcessInstanceExtDO); return instance.getId(); } @Async public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){ log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock"); processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO); } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 6c9048e6f..fc45887b7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -84,13 +84,6 @@ public interface BpmTaskService { */ void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO); - /** - * 回退任务 - * - * @param reqVO 回退任务信息 - */ - CommonResult backTask(BpmTaskBackReqVO reqVO); - /** * 将流程任务分配给指定用户 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index e35a6626d..72863b82f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -2,15 +2,12 @@ package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; @@ -24,7 +21,6 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; -import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ProcessInstance; @@ -40,7 +36,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; @@ -60,8 +55,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @Resource private TaskService taskService; @Resource - private RuntimeService runtimeService; - @Resource private HistoryService historyService; @Resource @@ -226,44 +219,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { .setReason(reqVO.getReason())); } - @Override - @Transactional(rollbackFor = Exception.class) - @TenantIgnore - public CommonResult backTask(BpmTaskBackReqVO reqVO) { - Long userId = Long.valueOf(reqVO.getUserId()); - // 校验任务存在 - Task task = checkTask(userId, reqVO.getTaskId()); - ArrayList oldTaskDefKeyList = CollUtil.newArrayList(reqVO.getOldTaskDefKey()); - - // List hisActInstList = - // historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list(); - // TODO @ke:使用 historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list() 读取,会存在啥问题呀? - List bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(reqVO.getProcInstId()); - // List bpmActivityDOList = BpmTaskConvert.INSTANCE.copyList(hisActInstList, BpmActivityDO.class); - // bpmActivityDOList.forEach(bpmActivityDO -> log.info("bpmActivityDO = " + bpmActivityDO)); - // TODO @ke:如果 开始->a->b->c->d->结束,从 d 驳回到 b 的话,这样会不会导致 a 也被删除呀?http://blog.wya1.com/article/636697030/details/7296 可以看看这篇文章哈。 - List taskIdList = bpmActivityDOList.stream().filter( - bpmActivityDO -> bpmActivityDO.getActivityId().equals(reqVO.getOldTaskDefKey()) - && !bpmActivityDO.getTaskId().equals(reqVO.getTaskId())).map(BpmActivityDO::getTaskId) - .collect(Collectors.toList()); - - // 使用flowable更改任务节点 - runtimeService.createChangeActivityStateBuilder().processInstanceId(reqVO.getProcInstId()) - .moveActivityIdsToSingleActivityId(oldTaskDefKeyList, reqVO.getNewTaskDefKey()).changeState(); - - // 逻辑删除hiActInst表任务 - Boolean delHiActInstResult = bpmActivityMapper.delHiActInstByTaskId(taskIdList); - // 逻辑删除hiTaskInst表任务 - Boolean delHiTaskInstResult = bpmActivityMapper.delHiTaskInstByTaskId(taskIdList); - // 更新任务拓展表 - Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getReason()); - Boolean delTaskResult = taskExtMapper.delByTaskIds(taskIdList); - if (!delHiActInstResult && !delHiTaskInstResult && !backResult && !delTaskResult) { - throw new RuntimeException("任务驳回失败!!!"); - } - return CommonResult.success(true); - } - @Override public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) { // 校验任务存在 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml deleted file mode 100644 index f17c04750..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - UPDATE act_hi_actinst - SET delete_reason_ = 'delete task' WHERE task_id_ IN - - #{item} - - - - UPDATE act_hi_taskinst - SET delete_reason_ = 'delete task' WHERE id_ IN - - #{item} - - - - - diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml deleted file mode 100644 index 934a358f5..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - UPDATE bpm_task_ext - SET result=2, - `reason`=#{reason} - WHERE task_id = #{taskId} - - - UPDATE bpm_task_ext - SET result=1, - `deleted`= true - WHERE `task_id` IN - - #{item} - - - - diff --git a/yudao-ui-admin/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/yudao-ui-admin/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue index 6c5edb88c..f80e0c8a8 100644 --- a/yudao-ui-admin/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue +++ b/yudao-ui-admin/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue @@ -2,6 +2,8 @@
+ 如何实现实现会签、或签? diff --git a/yudao-ui-admin/src/views/bpm/processInstance/detail.vue b/yudao-ui-admin/src/views/bpm/processInstance/detail.vue index bb1ffadf0..5a5459a7a 100644 --- a/yudao-ui-admin/src/views/bpm/processInstance/detail.vue +++ b/yudao-ui-admin/src/views/bpm/processInstance/detail.vue @@ -412,15 +412,16 @@ export default { }, /** 处理审批退回的操作 */ handleBack(task) { - const data = { - id: task.id, - assigneeUserId: 1 - } - // this.$modal.msgError("暂不支持【--退回】功能!"); - backTask(data).then(response => { - this.$modal.msgSuccess("回退成功!"); - this.getDetail(); // 获得最新详情 - }); + this.$modal.msgError("暂不支持【退回】功能!"); + // 可参考 http://blog.wya1.com/article/636697030/details/7296 + // const data = { + // id: task.id, + // assigneeUserId: 1 + // } + // backTask(data).then(response => { + // this.$modal.msgSuccess("回退成功!"); + // this.getDetail(); // 获得最新详情 + // }); } } };