Commit 26ff75370115bf7edcbde1a497e9a050a213b22f
1 parent
b37a535d
暂时去除回退功能,边界处理不够正确
Showing
38 changed files
with
15 additions
and
1306 deletions
README.md
| ... | ... | @@ -23,7 +23,7 @@ |
| 23 | 23 | * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统。 |
| 24 | 24 | * 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能。 |
| 25 | 25 | * 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装。 |
| 26 | -* 工作流使用 Activiti + Flowable,支持动态表单、在线设计流程、多种任务分配方式。 | |
| 26 | +* 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式。 | |
| 27 | 27 | * 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验。 |
| 28 | 28 | * 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款。 |
| 29 | 29 | * 集成阿里云、腾讯云、云片等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务。 |
| ... | ... | @@ -167,7 +167,7 @@ ps:核心功能已经实现,正在对接微信小程序中... |
| 167 | 167 | | [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.16 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | |
| 168 | 168 | | [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.5.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | |
| 169 | 169 | | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.2 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | |
| 170 | -| [Activiti](https://github.com/Activiti/Activiti) | 工作流引擎 | 7.1.0.M6 | [文档](TODO) | | |
| 170 | +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.0 | [文档](https://doc.iocoder.cn/bpm/) | | |
| 171 | 171 | | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | |
| 172 | 172 | | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | |
| 173 | 173 | | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | | ... | ... |
yudao-framework/pom.xml
| ... | ... | @@ -25,7 +25,6 @@ |
| 25 | 25 | |
| 26 | 26 | <module>yudao-spring-boot-starter-excel</module> |
| 27 | 27 | <module>yudao-spring-boot-starter-test</module> |
| 28 | - <module>yudao-spring-boot-starter-extension</module> | |
| 29 | 28 | |
| 30 | 29 | <module>yudao-spring-boot-starter-biz-operatelog</module> |
| 31 | 30 | <module>yudao-spring-boot-starter-biz-dict</module> | ... | ... |
yudao-framework/yudao-spring-boot-starter-extension/pom.xml deleted
| 1 | -<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | -<project xmlns="http://maven.apache.org/POM/4.0.0" | |
| 3 | - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 4 | - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| 5 | - <parent> | |
| 6 | - <artifactId>yudao-framework</artifactId> | |
| 7 | - <groupId>cn.iocoder.boot</groupId> | |
| 8 | - <version>${revision}</version> | |
| 9 | - </parent> | |
| 10 | - <modelVersion>4.0.0</modelVersion> | |
| 11 | - | |
| 12 | - <artifactId>yudao-spring-boot-starter-extension</artifactId> | |
| 13 | - <packaging>jar</packaging> | |
| 14 | - | |
| 15 | - <name>${project.artifactId}</name> | |
| 16 | - <description>扩展点组件</description> | |
| 17 | - <url>https://github.com/YunaiV/ruoyi-vue-pro</url> | |
| 18 | - | |
| 19 | - <properties> | |
| 20 | - | |
| 21 | - </properties> | |
| 22 | - | |
| 23 | - <dependencies> | |
| 24 | - <dependency> | |
| 25 | - <groupId>cn.iocoder.boot</groupId> | |
| 26 | - <artifactId>yudao-common</artifactId> | |
| 27 | - </dependency> | |
| 28 | - | |
| 29 | - <!-- Spring 核心 --> | |
| 30 | - <dependency> | |
| 31 | - <groupId>org.springframework</groupId> | |
| 32 | - <artifactId>spring-context</artifactId> | |
| 33 | - <scope>provided</scope> | |
| 34 | - </dependency> | |
| 35 | - | |
| 36 | - <dependency> | |
| 37 | - <groupId>org.springframework</groupId> | |
| 38 | - <artifactId>spring-beans</artifactId> | |
| 39 | - <scope>provided</scope> | |
| 40 | - </dependency> | |
| 41 | - | |
| 42 | - <!-- Spring 核心 --> | |
| 43 | - <dependency> | |
| 44 | - <groupId>org.springframework.boot</groupId> | |
| 45 | - <artifactId>spring-boot-starter-aop</artifactId> | |
| 46 | - </dependency> | |
| 47 | - | |
| 48 | - <!-- 测试包 --> | |
| 49 | - <dependency> | |
| 50 | - <groupId>org.springframework.boot</groupId> | |
| 51 | - <artifactId>spring-boot-starter-test</artifactId> | |
| 52 | - <scope>test</scope> | |
| 53 | - </dependency> | |
| 54 | - | |
| 55 | - <!-- 测试包 --> | |
| 56 | - <dependency> | |
| 57 | - <groupId>junit</groupId> | |
| 58 | - <artifactId>junit</artifactId> | |
| 59 | - <scope>test</scope> | |
| 60 | - </dependency> | |
| 61 | - | |
| 62 | - <!-- 工具类相关 --> | |
| 63 | - <dependency> | |
| 64 | - <groupId>jakarta.validation</groupId> | |
| 65 | - <artifactId>jakarta.validation-api</artifactId> | |
| 66 | - </dependency> | |
| 67 | - </dependencies> | |
| 68 | -</project> | |
| 69 | 0 | \ No newline at end of file |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/config/YudaoExtensionAutoConfiguration.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.config; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.ExtensionBootstrap; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.context.ExtensionContext; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.context.ExtensionContextHolder; | |
| 6 | -import cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor; | |
| 7 | -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory; | |
| 8 | -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory; | |
| 9 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |
| 10 | -import org.springframework.context.annotation.Bean; | |
| 11 | -import org.springframework.context.annotation.Configuration; | |
| 12 | - | |
| 13 | -/** | |
| 14 | - * @description 扩展点组件自动装配 | |
| 15 | - * @author Qingchen | |
| 16 | - * @version 1.0.0 | |
| 17 | - * @date 2021-08-28 21:50 | |
| 18 | - * @class cn.iocoder.yudao.framework.extension.config.YudaoExtensionAutoConfiguration.java | |
| 19 | - */ | |
| 20 | -@Configuration | |
| 21 | -public class YudaoExtensionAutoConfiguration { | |
| 22 | - | |
| 23 | - /** | |
| 24 | - * 组件初始化 | |
| 25 | - * @return | |
| 26 | - */ | |
| 27 | - @Bean(initMethod = "init") | |
| 28 | - @ConditionalOnMissingBean(ExtensionBootstrap.class) | |
| 29 | - public ExtensionBootstrap bootstrap() { | |
| 30 | - return new ExtensionBootstrap(); | |
| 31 | - } | |
| 32 | - | |
| 33 | - /** | |
| 34 | - * 扩展点工厂 | |
| 35 | - * @return | |
| 36 | - */ | |
| 37 | - @Bean | |
| 38 | - @ConditionalOnMissingBean({ExtensionRegisterFactory.class, ExtensionFactory.class}) | |
| 39 | - public ExtensionRegisterFactory registerFactory() { | |
| 40 | - return new ExtensionRegisterFactory(); | |
| 41 | - } | |
| 42 | - | |
| 43 | - /** | |
| 44 | - * 扩展组件上下文对象 | |
| 45 | - * @return | |
| 46 | - */ | |
| 47 | - @Bean | |
| 48 | - @ConditionalOnMissingBean({ExtensionContextHolder.class, ExtensionContext.class}) | |
| 49 | - public ExtensionContextHolder context() { | |
| 50 | - return new ExtensionContextHolder(); | |
| 51 | - } | |
| 52 | - | |
| 53 | - /** | |
| 54 | - * 扩展组件执行器 | |
| 55 | - * @return | |
| 56 | - */ | |
| 57 | - @Bean | |
| 58 | - @ConditionalOnMissingBean(ExtensionExecutor.class) | |
| 59 | - public ExtensionExecutor executor() { | |
| 60 | - return new ExtensionExecutor(); | |
| 61 | - } | |
| 62 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/BusinessScenario.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core; | |
| 2 | - | |
| 3 | -import javax.validation.constraints.NotNull; | |
| 4 | -import java.io.Serializable; | |
| 5 | -import java.util.StringJoiner; | |
| 6 | - | |
| 7 | -/** | |
| 8 | - * @description 业务场景 = businessId + useCase + scenario, 用来标识系统中唯一的一个场景<br/> | |
| 9 | - * @author Qingchen | |
| 10 | - * @version 1.0.0 | |
| 11 | - * @date 2021-08-28 22:19 | |
| 12 | - * @class cn.iocoder.yudao.framework.extension.core.BusinessScenario.java | |
| 13 | - */ | |
| 14 | -public class BusinessScenario implements Serializable { | |
| 15 | - | |
| 16 | - /** | |
| 17 | - * 默认业务id | |
| 18 | - */ | |
| 19 | - public final static String DEFAULT_BUSINESS_ID = "#defaultBusinessId#"; | |
| 20 | - | |
| 21 | - /** | |
| 22 | - * 默认用例 | |
| 23 | - */ | |
| 24 | - public final static String DEFAULT_USECASE = "#defaultUseCase#"; | |
| 25 | - | |
| 26 | - /** | |
| 27 | - * 默认场景 | |
| 28 | - */ | |
| 29 | - public final static String DEFAULT_SCENARIO = "#defaultScenario#"; | |
| 30 | - | |
| 31 | - /** | |
| 32 | - * 分隔符 | |
| 33 | - */ | |
| 34 | - private final static String DOT_SEPARATOR = "."; | |
| 35 | - | |
| 36 | - /** | |
| 37 | - * 业务Id | |
| 38 | - */ | |
| 39 | - private String businessId; | |
| 40 | - | |
| 41 | - /** | |
| 42 | - * 用例 | |
| 43 | - */ | |
| 44 | - private String useCase; | |
| 45 | - | |
| 46 | - /** | |
| 47 | - * 场景 | |
| 48 | - */ | |
| 49 | - private String scenario; | |
| 50 | - | |
| 51 | - public BusinessScenario() { | |
| 52 | - this.businessId = DEFAULT_BUSINESS_ID; | |
| 53 | - this.useCase = DEFAULT_USECASE; | |
| 54 | - this.scenario = DEFAULT_SCENARIO; | |
| 55 | - } | |
| 56 | - | |
| 57 | - public BusinessScenario(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario) { | |
| 58 | - this.businessId = businessId; | |
| 59 | - this.useCase = useCase; | |
| 60 | - this.scenario = scenario; | |
| 61 | - } | |
| 62 | - | |
| 63 | - public BusinessScenario(@NotNull String scenario) { | |
| 64 | - this(); | |
| 65 | - this.scenario = scenario; | |
| 66 | - } | |
| 67 | - | |
| 68 | - public BusinessScenario(@NotNull String useCase, @NotNull String scenario) { | |
| 69 | - this(DEFAULT_BUSINESS_ID, useCase, scenario); | |
| 70 | - } | |
| 71 | - | |
| 72 | - public String getBusinessId() { | |
| 73 | - return businessId; | |
| 74 | - } | |
| 75 | - | |
| 76 | - public void setBusinessId(String businessId) { | |
| 77 | - this.businessId = businessId; | |
| 78 | - } | |
| 79 | - | |
| 80 | - public String getUseCase() { | |
| 81 | - return useCase; | |
| 82 | - } | |
| 83 | - | |
| 84 | - public void setUseCase(String useCase) { | |
| 85 | - this.useCase = useCase; | |
| 86 | - } | |
| 87 | - | |
| 88 | - public String getScenario() { | |
| 89 | - return scenario; | |
| 90 | - } | |
| 91 | - | |
| 92 | - public void setScenario(String scenario) { | |
| 93 | - this.scenario = scenario; | |
| 94 | - } | |
| 95 | - | |
| 96 | - /** | |
| 97 | - * 构建业务场景 | |
| 98 | - * @param businessId | |
| 99 | - * @param useCase | |
| 100 | - * @param scenario | |
| 101 | - * @return | |
| 102 | - */ | |
| 103 | - public static BusinessScenario valueOf(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario) { | |
| 104 | - return new BusinessScenario(businessId, useCase, scenario); | |
| 105 | - } | |
| 106 | - | |
| 107 | - /** | |
| 108 | - * 构建业务场景 | |
| 109 | - * @param useCase | |
| 110 | - * @param scenario | |
| 111 | - * @return | |
| 112 | - */ | |
| 113 | - public static BusinessScenario valueOf(@NotNull String useCase, @NotNull String scenario) { | |
| 114 | - return new BusinessScenario(useCase, scenario); | |
| 115 | - } | |
| 116 | - | |
| 117 | - /** | |
| 118 | - * 构建业务场景 | |
| 119 | - * @param scenario | |
| 120 | - * @return | |
| 121 | - */ | |
| 122 | - public static BusinessScenario valueOf(@NotNull String scenario) { | |
| 123 | - return new BusinessScenario(scenario); | |
| 124 | - } | |
| 125 | - | |
| 126 | - /** | |
| 127 | - * 业务场景唯一标识 | |
| 128 | - * @return | |
| 129 | - */ | |
| 130 | - public String getUniqueIdentity(){ | |
| 131 | - return new StringJoiner(DOT_SEPARATOR).add(businessId).add(useCase).add(scenario).toString(); | |
| 132 | - } | |
| 133 | - | |
| 134 | - @Override | |
| 135 | - public String toString() { | |
| 136 | - return "BusinessScenario{" + | |
| 137 | - "businessId='" + businessId + '\'' + | |
| 138 | - ", useCase='" + useCase + '\'' + | |
| 139 | - ", scenario='" + scenario + '\'' + | |
| 140 | - '}'; | |
| 141 | - } | |
| 142 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/ExtensionBootstrap.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory; | |
| 4 | -import org.springframework.beans.BeansException; | |
| 5 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 6 | -import org.springframework.context.ApplicationContext; | |
| 7 | -import org.springframework.context.ApplicationContextAware; | |
| 8 | - | |
| 9 | -import javax.annotation.PostConstruct; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * @description | |
| 13 | - * @author Qingchen | |
| 14 | - * @version 1.0.0 | |
| 15 | - * @date 2021-08-29 00:18 | |
| 16 | - * @class cn.iocoder.yudao.framework.extension.core.ExtensionBootstrap.java | |
| 17 | - */ | |
| 18 | -public class ExtensionBootstrap implements ApplicationContextAware { | |
| 19 | - | |
| 20 | - /** | |
| 21 | - * spring 容器 | |
| 22 | - */ | |
| 23 | - private ApplicationContext applicationContext; | |
| 24 | - | |
| 25 | - @Autowired | |
| 26 | - private ExtensionRegisterFactory registerFactory; | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * 初始化 | |
| 30 | - */ | |
| 31 | - @PostConstruct | |
| 32 | - public void init() { | |
| 33 | - registerFactory.setApplicationContext(applicationContext); | |
| 34 | - registerFactory.register(null); | |
| 35 | - } | |
| 36 | - | |
| 37 | - @Override | |
| 38 | - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | |
| 39 | - this.applicationContext = applicationContext; | |
| 40 | - } | |
| 41 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/AbstractComponentExecutor.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.context; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | - | |
| 6 | -import java.util.function.Consumer; | |
| 7 | -import java.util.function.Function; | |
| 8 | - | |
| 9 | -/** | |
| 10 | - * @description 执行器通用方法 | |
| 11 | - * @author Qingchen | |
| 12 | - * @version 1.0.0 | |
| 13 | - * @date 2021-08-29 00:38 | |
| 14 | - * @class cn.iocoder.yudao.framework.extension.core.context.AbstractComponentExecutor.java | |
| 15 | - */ | |
| 16 | -public abstract class AbstractComponentExecutor { | |
| 17 | - | |
| 18 | - /** | |
| 19 | - * ("业务" + "用例" + "场景")执行扩展组件,并返回执行结果 | |
| 20 | - * @param targetClazz | |
| 21 | - * @param businessId | |
| 22 | - * @param useCase | |
| 23 | - * @param scenario | |
| 24 | - * @param function | |
| 25 | - * @param <R> | |
| 26 | - * @param <T> | |
| 27 | - * @return | |
| 28 | - */ | |
| 29 | - public <R, T extends ExtensionPoint> R execute(Class<T> targetClazz, String businessId, String useCase, String scenario, Function<T, R> function) { | |
| 30 | - return execute(targetClazz, BusinessScenario.valueOf(businessId, useCase, scenario), function); | |
| 31 | - } | |
| 32 | - | |
| 33 | - | |
| 34 | - /** | |
| 35 | - * ("用例" + "场景")执行扩展组件,并返回执行结果 | |
| 36 | - * @param targetClazz | |
| 37 | - * @param useCase | |
| 38 | - * @param scenario | |
| 39 | - * @param function | |
| 40 | - * @param <R> | |
| 41 | - * @param <T> | |
| 42 | - * @return | |
| 43 | - */ | |
| 44 | - public <R, T extends ExtensionPoint> R execute(Class<T> targetClazz, String useCase, String scenario, Function<T, R> function) { | |
| 45 | - return execute(targetClazz, BusinessScenario.valueOf(useCase, scenario), function); | |
| 46 | - } | |
| 47 | - | |
| 48 | - /** | |
| 49 | - * ("场景")执行扩展组件,并返回执行结果 | |
| 50 | - * @param targetClazz | |
| 51 | - * @param scenario | |
| 52 | - * @param function | |
| 53 | - * @param <R> | |
| 54 | - * @param <T> | |
| 55 | - * @return | |
| 56 | - */ | |
| 57 | - public <R, T extends ExtensionPoint> R execute(Class<T> targetClazz, String scenario, Function<T, R> function) { | |
| 58 | - return execute(targetClazz, BusinessScenario.valueOf(scenario), function); | |
| 59 | - } | |
| 60 | - | |
| 61 | - /** | |
| 62 | - * 执行扩展组件,并返回执行结果 | |
| 63 | - * @param targetClazz | |
| 64 | - * @param businessScenario | |
| 65 | - * @param function | |
| 66 | - * @param <R> Response Type | |
| 67 | - * @param <T> Parameter Type | |
| 68 | - * @return | |
| 69 | - */ | |
| 70 | - public <R, T extends ExtensionPoint> R execute(Class<T> targetClazz, BusinessScenario businessScenario, Function<T, R> function) { | |
| 71 | - T component = locateComponent(targetClazz, businessScenario); | |
| 72 | - return function.apply(component); | |
| 73 | - } | |
| 74 | - | |
| 75 | - /** | |
| 76 | - * ("业务" + "用例" + "场景")执行扩展组件,适用于无返回值的业务 | |
| 77 | - * @param targetClazz | |
| 78 | - * @param businessId | |
| 79 | - * @param useCase | |
| 80 | - * @param scenario | |
| 81 | - * @param consumer | |
| 82 | - * @param <T> | |
| 83 | - */ | |
| 84 | - public <T extends ExtensionPoint> void accept(Class<T> targetClazz, String businessId, String useCase, String scenario, Consumer<T> consumer) { | |
| 85 | - accept(targetClazz, BusinessScenario.valueOf(businessId, useCase, scenario), consumer); | |
| 86 | - } | |
| 87 | - | |
| 88 | - /** | |
| 89 | - * ("场景")执行扩展组件,适用于无返回值的业务 | |
| 90 | - * @param targetClazz | |
| 91 | - * @param useCase | |
| 92 | - * @param scenario | |
| 93 | - * @param consumer | |
| 94 | - * @param <T> | |
| 95 | - */ | |
| 96 | - public <T extends ExtensionPoint> void accept(Class<T> targetClazz, String useCase, String scenario, Consumer<T> consumer) { | |
| 97 | - accept(targetClazz, BusinessScenario.valueOf(useCase, scenario), consumer); | |
| 98 | - } | |
| 99 | - | |
| 100 | - /** | |
| 101 | - * ("场景")执行扩展组件,适用于无返回值的业务 | |
| 102 | - * @param targetClazz | |
| 103 | - * @param scenario | |
| 104 | - * @param consumer | |
| 105 | - * @param <T> | |
| 106 | - */ | |
| 107 | - public <T extends ExtensionPoint> void accept(Class<T> targetClazz, String scenario, Consumer<T> consumer) { | |
| 108 | - accept(targetClazz, BusinessScenario.valueOf(scenario), consumer); | |
| 109 | - } | |
| 110 | - | |
| 111 | - /** | |
| 112 | - * 执行扩展组件,适用于无返回值的业务 | |
| 113 | - * @param targetClazz | |
| 114 | - * @param businessScenario | |
| 115 | - * @param consumer | |
| 116 | - * @param <T> Parameter Type | |
| 117 | - */ | |
| 118 | - public <T extends ExtensionPoint> void accept(Class<T> targetClazz, BusinessScenario businessScenario, Consumer<T> consumer) { | |
| 119 | - T component = locateComponent(targetClazz, businessScenario); | |
| 120 | - consumer.accept(component); | |
| 121 | - } | |
| 122 | - | |
| 123 | - /** | |
| 124 | - * 获取/定位扩展点组件 | |
| 125 | - * @param targetClazz | |
| 126 | - * @param businessScenario | |
| 127 | - * @param <C> | |
| 128 | - * @return | |
| 129 | - */ | |
| 130 | - protected abstract <C extends ExtensionPoint> C locateComponent(Class<C> targetClazz, BusinessScenario businessScenario); | |
| 131 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContext.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.context; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | - | |
| 6 | -/** | |
| 7 | - * @description 上下文,包含各个扩展点的相关操作 | |
| 8 | - * @author Qingchen | |
| 9 | - * @version 1.0.0 | |
| 10 | - * @date 2021-08-28 22:15 | |
| 11 | - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionContext.java | |
| 12 | - */ | |
| 13 | -public interface ExtensionContext { | |
| 14 | - | |
| 15 | - /** | |
| 16 | - * 根据业务场景唯一标识获取扩展点组件实现类 | |
| 17 | - * @param businessId | |
| 18 | - * @param useCase | |
| 19 | - * @param scenario | |
| 20 | - * @param clazz | |
| 21 | - * @param <T> | |
| 22 | - * @return | |
| 23 | - */ | |
| 24 | - <T extends ExtensionPoint> T getPoint(String businessId, String useCase, String scenario, Class<T> clazz); | |
| 25 | - | |
| 26 | - /** | |
| 27 | - * 根据("实例" + "场景")获取扩展点组件实现类,其中:业务id(businessId)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_BUSINESS_ID} | |
| 28 | - * @param useCase | |
| 29 | - * @param scenario | |
| 30 | - * @param clazz | |
| 31 | - * @param <T> | |
| 32 | - * @return | |
| 33 | - */ | |
| 34 | - <T extends ExtensionPoint> T getPoint(String useCase, String scenario, Class<T> clazz); | |
| 35 | - | |
| 36 | - /** | |
| 37 | - * 根据("场景")获取扩展点组件实现类 <br/> | |
| 38 | - * 其中: | |
| 39 | - * 业务id(businessId)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_BUSINESS_ID} | |
| 40 | - * 实例(useCase)= {@linkplain cn.iocoder.yudao.framework.extension.core.BusinessScenario.DEFAULT_USECASE} | |
| 41 | - * @param scenario | |
| 42 | - * @param clazz | |
| 43 | - * @param <T> | |
| 44 | - * @return | |
| 45 | - */ | |
| 46 | - <T extends ExtensionPoint> T getPoint(String scenario, Class<T> clazz); | |
| 47 | - | |
| 48 | - /** | |
| 49 | - * 根据业务场景唯一标识获取扩展点组件实现类 | |
| 50 | - * @param businessScenario | |
| 51 | - * @param clazz | |
| 52 | - * @param <T> | |
| 53 | - * @return | |
| 54 | - */ | |
| 55 | - <T extends ExtensionPoint> T getPoint(BusinessScenario businessScenario, Class<T> clazz); | |
| 56 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionContextHolder.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.context; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 6 | -import lombok.extern.slf4j.Slf4j; | |
| 7 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 8 | -import org.springframework.stereotype.Component; | |
| 9 | - | |
| 10 | -import javax.validation.constraints.NotNull; | |
| 11 | - | |
| 12 | -/** | |
| 13 | - * @description 上下文及扩展点组件工厂的持有类 | |
| 14 | - * @author Qingchen | |
| 15 | - * @version 1.0.0 | |
| 16 | - * @date 2021-08-29 00:29 | |
| 17 | - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionContextHolder.java | |
| 18 | - */ | |
| 19 | -@Component | |
| 20 | -@Slf4j | |
| 21 | -public class ExtensionContextHolder implements ExtensionContext{ | |
| 22 | - | |
| 23 | - @Autowired | |
| 24 | - private ExtensionFactory factory; | |
| 25 | - | |
| 26 | - @Override | |
| 27 | - public <T extends ExtensionPoint> T getPoint(@NotNull String businessId, @NotNull String useCase, @NotNull String scenario, Class<T> clazz) { | |
| 28 | - return getPoint(BusinessScenario.valueOf(businessId, useCase, scenario), clazz); | |
| 29 | - } | |
| 30 | - | |
| 31 | - @Override | |
| 32 | - public <T extends ExtensionPoint> T getPoint(@NotNull String useCase, String scenario, Class<T> clazz) { | |
| 33 | - return getPoint(BusinessScenario.valueOf(useCase, scenario), clazz); | |
| 34 | - } | |
| 35 | - | |
| 36 | - @Override | |
| 37 | - public <T extends ExtensionPoint> T getPoint(@NotNull String scenario, Class<T> clazz) { | |
| 38 | - return getPoint(BusinessScenario.valueOf(scenario), clazz); | |
| 39 | - } | |
| 40 | - | |
| 41 | - @Override | |
| 42 | - public <T extends ExtensionPoint> T getPoint(@NotNull BusinessScenario businessScenario, Class<T> clazz) { | |
| 43 | - return factory.get(businessScenario, clazz); | |
| 44 | - } | |
| 45 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/context/ExtensionExecutor.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.context; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | -import lombok.extern.slf4j.Slf4j; | |
| 6 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 7 | -import org.springframework.stereotype.Component; | |
| 8 | - | |
| 9 | -/** | |
| 10 | - * @description 扩展组件执行器 | |
| 11 | - * @author Qingchen | |
| 12 | - * @version 1.0.0 | |
| 13 | - * @date 2021-08-29 00:32 | |
| 14 | - * @class cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor.java | |
| 15 | - */ | |
| 16 | -@Component | |
| 17 | -@Slf4j | |
| 18 | -public class ExtensionExecutor extends AbstractComponentExecutor{ | |
| 19 | - | |
| 20 | - @Autowired | |
| 21 | - private ExtensionContextHolder contextHolder; | |
| 22 | - | |
| 23 | - | |
| 24 | - @Override | |
| 25 | - protected <C extends ExtensionPoint> C locateComponent(Class<C> targetClazz, BusinessScenario businessScenario) { | |
| 26 | - return contextHolder.getPoint(businessScenario, targetClazz); | |
| 27 | - } | |
| 28 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionDefinition.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.factory; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | -import lombok.Getter; | |
| 6 | -import lombok.Setter; | |
| 7 | - | |
| 8 | -import javax.validation.constraints.NotNull; | |
| 9 | -import java.io.Serializable; | |
| 10 | -import java.util.Objects; | |
| 11 | - | |
| 12 | -/** | |
| 13 | - * @description 扩展定义(扩展坐标),标识唯一一个业务场景实现 | |
| 14 | - * @author Qingchen | |
| 15 | - * @version 1.0.0 | |
| 16 | - * @date 2021-08-28 23:14 | |
| 17 | - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionDefinition.java | |
| 18 | - */ | |
| 19 | -@Setter | |
| 20 | -@Getter | |
| 21 | -public class ExtensionDefinition implements Serializable { | |
| 22 | - | |
| 23 | - /** | |
| 24 | - * 业务场景唯一标识(id) | |
| 25 | - */ | |
| 26 | - private String uniqueIdentify; | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * 扩展点实现类名称 | |
| 30 | - */ | |
| 31 | - private String extensionPointName; | |
| 32 | - | |
| 33 | - /** | |
| 34 | - * 业务场景 | |
| 35 | - */ | |
| 36 | - private BusinessScenario businessScenario; | |
| 37 | - | |
| 38 | - /** | |
| 39 | - * 扩展点实现类 | |
| 40 | - */ | |
| 41 | - private ExtensionPoint extensionPoint; | |
| 42 | - | |
| 43 | - /** | |
| 44 | - * class | |
| 45 | - */ | |
| 46 | - private Class extensionPointClass; | |
| 47 | - | |
| 48 | - public ExtensionDefinition() { | |
| 49 | - } | |
| 50 | - | |
| 51 | - public ExtensionDefinition(@NotNull BusinessScenario businessScenario, @NotNull ExtensionPoint extensionPoint) { | |
| 52 | - this.businessScenario = businessScenario; | |
| 53 | - this.extensionPoint = extensionPoint; | |
| 54 | - this.uniqueIdentify = this.businessScenario.getUniqueIdentity(); | |
| 55 | - this.extensionPointClass = this.extensionPoint.getClass(); | |
| 56 | - } | |
| 57 | - | |
| 58 | - /** | |
| 59 | - * 构建definition | |
| 60 | - * @param businessScenario | |
| 61 | - * @param point | |
| 62 | - * @return | |
| 63 | - */ | |
| 64 | - public static ExtensionDefinition valueOf(@NotNull BusinessScenario businessScenario, @NotNull ExtensionPoint point) { | |
| 65 | - return new ExtensionDefinition(businessScenario, point); | |
| 66 | - } | |
| 67 | - | |
| 68 | - @Override | |
| 69 | - public boolean equals(Object o) { | |
| 70 | - if (this == o) { | |
| 71 | - return true; | |
| 72 | - } | |
| 73 | - if (o == null || getClass() != o.getClass()) { | |
| 74 | - return false; | |
| 75 | - } | |
| 76 | - ExtensionDefinition that = (ExtensionDefinition) o; | |
| 77 | - return Objects.equals(uniqueIdentify, that.uniqueIdentify) && Objects.equals(extensionPointName, that.extensionPointName); | |
| 78 | - } | |
| 79 | - | |
| 80 | - @Override | |
| 81 | - public int hashCode() { | |
| 82 | - final int prime = 31; | |
| 83 | - int result = 1; | |
| 84 | - result = prime * result + ((uniqueIdentify == null) ? 0 : uniqueIdentify.hashCode()); | |
| 85 | - result = prime * result + ((extensionPointName == null) ? 0 : extensionPointName.hashCode()); | |
| 86 | - return result; | |
| 87 | - } | |
| 88 | - | |
| 89 | - @Override | |
| 90 | - public String toString() { | |
| 91 | - return "ExtensionDefinition{" + | |
| 92 | - "uniqueIdentify='" + uniqueIdentify + '\'' + | |
| 93 | - ", extensionPointName='" + extensionPointName + '\'' + | |
| 94 | - '}'; | |
| 95 | - } | |
| 96 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionFactory.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.factory; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | - | |
| 6 | -/** | |
| 7 | - * @description 扩展点工厂 | |
| 8 | - * @author Qingchen | |
| 9 | - * @version 1.0.0 | |
| 10 | - * @date 2021-08-28 23:04 | |
| 11 | - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionFactory.java | |
| 12 | - */ | |
| 13 | -public interface ExtensionFactory { | |
| 14 | - | |
| 15 | - /** | |
| 16 | - * 注册所有扩展点实现类 | |
| 17 | - * @param basePackage | |
| 18 | - */ | |
| 19 | - void register(String basePackage); | |
| 20 | - | |
| 21 | - /** | |
| 22 | - * 根据业务场景获取指定类型的扩展点 | |
| 23 | - * @param businessScenario | |
| 24 | - * @param clazz | |
| 25 | - * @param <T> | |
| 26 | - * @return | |
| 27 | - */ | |
| 28 | - <T extends ExtensionPoint> T get(BusinessScenario businessScenario, Class<T> clazz); | |
| 29 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/factory/ExtensionRegisterFactory.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.factory; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; | |
| 6 | -import lombok.extern.slf4j.Slf4j; | |
| 7 | -import org.springframework.aop.support.AopUtils; | |
| 8 | -import org.springframework.context.ApplicationContext; | |
| 9 | -import org.springframework.core.annotation.AnnotationUtils; | |
| 10 | -import org.springframework.stereotype.Component; | |
| 11 | -import org.springframework.util.ClassUtils; | |
| 12 | - | |
| 13 | -import javax.validation.constraints.NotNull; | |
| 14 | -import java.util.Map; | |
| 15 | -import java.util.concurrent.ConcurrentHashMap; | |
| 16 | - | |
| 17 | -/** | |
| 18 | - * @description 注册工厂 | |
| 19 | - * @author Qingchen | |
| 20 | - * @version 1.0.0 | |
| 21 | - * @date 2021-08-28 23:07 | |
| 22 | - * @class cn.iocoder.yudao.framework.extension.core.factory.ExtensionRegisterFactory.java | |
| 23 | - */ | |
| 24 | -@Component | |
| 25 | -@Slf4j | |
| 26 | -public class ExtensionRegisterFactory implements ExtensionFactory { | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * spring ApplicationContext | |
| 30 | - */ | |
| 31 | - private ApplicationContext applicationContext; | |
| 32 | - | |
| 33 | - /** | |
| 34 | - * 扩展点实现类集合 | |
| 35 | - */ | |
| 36 | - private Map<String, ExtensionDefinition> registerExtensionBeans = new ConcurrentHashMap<>(); | |
| 37 | - | |
| 38 | - @Override | |
| 39 | - public void register(String basePackage) { | |
| 40 | - final Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Extension.class); | |
| 41 | - if(beans == null || beans.isEmpty()) { | |
| 42 | - return; | |
| 43 | - } | |
| 44 | - | |
| 45 | - beans.values().forEach(point -> doRegister((ExtensionPoint) point)); | |
| 46 | - log.info("业务场景相关扩展点注册完成,注册数量: {}", registerExtensionBeans.size()); | |
| 47 | - } | |
| 48 | - | |
| 49 | - @Override | |
| 50 | - public <T extends ExtensionPoint> T get(BusinessScenario businessScenario, Class<T> clazz) { | |
| 51 | - | |
| 52 | - final ExtensionDefinition definition = registerExtensionBeans.get(businessScenario.getUniqueIdentity()); | |
| 53 | - if(definition == null) { | |
| 54 | - log.error("获取业务场景扩展点实现失败,失败原因:尚未定义该业务场景相关扩展点。{}", businessScenario); | |
| 55 | - throw new RuntimeException("尚未定义该业务场景相关扩展点 [" + businessScenario + "]"); | |
| 56 | - } | |
| 57 | - | |
| 58 | - return (T) definition.getExtensionPoint(); | |
| 59 | - } | |
| 60 | - | |
| 61 | - /** | |
| 62 | - * 注册扩展点 | |
| 63 | - * @param point | |
| 64 | - */ | |
| 65 | - private void doRegister(@NotNull ExtensionPoint point) { | |
| 66 | - Class<?> extensionClazz = point.getClass(); | |
| 67 | - | |
| 68 | - if (AopUtils.isAopProxy(point)) { | |
| 69 | - extensionClazz = ClassUtils.getUserClass(point); | |
| 70 | - } | |
| 71 | - | |
| 72 | - Extension extension = AnnotationUtils.findAnnotation(extensionClazz, Extension.class); | |
| 73 | - final BusinessScenario businessScenario = BusinessScenario.valueOf(extension.businessId(), extension.useCase(), extension.scenario()); | |
| 74 | - final ExtensionDefinition definition = ExtensionDefinition.valueOf(businessScenario, point); | |
| 75 | - final ExtensionDefinition exist = registerExtensionBeans.get(businessScenario.getUniqueIdentity()); | |
| 76 | - if(exist != null && !exist.equals(definition)) { | |
| 77 | - throw new RuntimeException("相同的业务场景重复注册了不同类型的扩展点实现 :【" + definition + "】【" + exist + "】"); | |
| 78 | - } | |
| 79 | - | |
| 80 | - registerExtensionBeans.put(businessScenario.getUniqueIdentity(), definition); | |
| 81 | - } | |
| 82 | - | |
| 83 | - public void setApplicationContext(ApplicationContext applicationContext) { | |
| 84 | - this.applicationContext = applicationContext; | |
| 85 | - } | |
| 86 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/package-info.java deleted
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/point/ExtensionPoint.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.point; | |
| 2 | -/** | |
| 3 | - * @description 扩展点 <br/> | |
| 4 | - * 表示一块逻辑在不同的业务有不同的实现,使用扩展点做接口申明,然后用{@linkplain cn.iocoder.yudao.framework.extension.core.stereotype.Extension}(扩展)去实现扩展点。 | |
| 5 | - * @author Qingchen | |
| 6 | - * @version 1.0.0 | |
| 7 | - * @date 2021-08-28 22:06 | |
| 8 | - * @class cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint.java | |
| 9 | - */ | |
| 10 | -public interface ExtensionPoint { | |
| 11 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/core/stereotype/Extension.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.core.stereotype; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 4 | -import org.springframework.stereotype.Component; | |
| 5 | - | |
| 6 | -import java.lang.annotation.*; | |
| 7 | - | |
| 8 | -/** | |
| 9 | - * @description 表示带注释的类是“扩展组件” | |
| 10 | - * @author Qingchen | |
| 11 | - * @version 1.0.0 | |
| 12 | - * @date 2021-08-28 21:59 | |
| 13 | - * @class cn.iocoder.yudao.framework.extension.core.stereotype.Extension.java | |
| 14 | - */ | |
| 15 | -@Inherited | |
| 16 | -@Retention(RetentionPolicy.RUNTIME) | |
| 17 | -@Target({ElementType.TYPE}) | |
| 18 | -@Component | |
| 19 | -public @interface Extension { | |
| 20 | - | |
| 21 | - /** | |
| 22 | - * 业务 <br/> | |
| 23 | - * 一个自负盈亏的财务主体,比如tmall、淘宝和零售通就是三个不同的业务 | |
| 24 | - * @return | |
| 25 | - */ | |
| 26 | - String businessId() default BusinessScenario.DEFAULT_BUSINESS_ID; | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * 用例 <br/> | |
| 30 | - * 描述了用户和系统之间的互动,每个用例提供了一个或多个场景。比如,支付订单就是一个典型的用例。 | |
| 31 | - * @return | |
| 32 | - */ | |
| 33 | - String useCase() default BusinessScenario.DEFAULT_USECASE; | |
| 34 | - | |
| 35 | - /** | |
| 36 | - * 场景 <br/> | |
| 37 | - * 场景也被称为用例的实例(Instance),包括用例所有的可能情况(正常的和异常的)。比如对于"订单支付"这个用例,就有“支付宝支付”、“银行卡支付”、"微信支付"等多个场景 | |
| 38 | - * @return | |
| 39 | - */ | |
| 40 | - String scenario() default BusinessScenario.DEFAULT_SCENARIO; | |
| 41 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/main/java/cn/iocoder/yudao/framework/extension/package-info.java deleted
yudao-framework/yudao-spring-boot-starter-extension/src/main/resources/META-INF/spring.factories deleted
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/Application.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension; | |
| 2 | - | |
| 3 | -import org.springframework.boot.SpringApplication; | |
| 4 | -import org.springframework.boot.autoconfigure.SpringBootApplication; | |
| 5 | - | |
| 6 | -/** | |
| 7 | - * @description Application | |
| 8 | - * @author Qingchen | |
| 9 | - * @version 1.0.0 | |
| 10 | - * @date 2021-08-30 10:32 | |
| 11 | - * @class cn.iocoder.yudao.framework.extension.Application.java | |
| 12 | - */ | |
| 13 | -@SpringBootApplication | |
| 14 | -public class Application { | |
| 15 | - | |
| 16 | - public static void main(String[] args) { | |
| 17 | - SpringApplication.run(Application.class, args); | |
| 18 | - } | |
| 19 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/ExtensionTest.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension; | |
| 2 | - | |
| 3 | -import cn.hutool.core.util.IdUtil; | |
| 4 | -import cn.hutool.json.JSONUtil; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.BusinessScenario; | |
| 6 | -import cn.iocoder.yudao.framework.extension.core.context.ExtensionExecutor; | |
| 7 | -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; | |
| 8 | -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; | |
| 9 | -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; | |
| 10 | -import lombok.extern.slf4j.Slf4j; | |
| 11 | -import org.junit.Assert; | |
| 12 | -import org.junit.Test; | |
| 13 | -import org.junit.runner.RunWith; | |
| 14 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 15 | -import org.springframework.boot.test.context.SpringBootTest; | |
| 16 | -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | |
| 17 | - | |
| 18 | -import java.math.BigDecimal; | |
| 19 | - | |
| 20 | -/** | |
| 21 | - * @description | |
| 22 | - * @author Qingchen | |
| 23 | - * @version 1.0.0 | |
| 24 | - * @date 2021-08-30 10:30 | |
| 25 | - * @class cn.iocoder.yudao.framework.extension.ExtensionTest.java | |
| 26 | - */ | |
| 27 | -@RunWith(SpringJUnit4ClassRunner.class) | |
| 28 | -@SpringBootTest(classes = Application.class) | |
| 29 | -@Slf4j | |
| 30 | -public class ExtensionTest { | |
| 31 | - | |
| 32 | - @Autowired | |
| 33 | - private ExtensionExecutor extensionExecutor; | |
| 34 | - | |
| 35 | - @Test | |
| 36 | - public void unifiedOrder() { | |
| 37 | - final BusinessScenario scenario = BusinessScenario.valueOf("pay", "jsapi", "wechat"); | |
| 38 | - final TransactionsCommand command = new TransactionsCommand(IdUtil.objectId(), new BigDecimal(105), "Image形象店-深圳腾大-QQ公仔", "https://www.weixin.qq.com/wxpay/pay.php"); | |
| 39 | - final TransactionsResult result = extensionExecutor.execute(PayExtensionPoint.class, scenario, extension -> extension.unifiedOrder(command)); | |
| 40 | - log.info("result is: {}", JSONUtil.toJsonStr(result)); | |
| 41 | - Assert.assertSame("wechat", result.getChannel()); | |
| 42 | - } | |
| 43 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/package-info.java deleted
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/PayExtensionPoint.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.pay; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.extension.core.point.ExtensionPoint; | |
| 4 | -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; | |
| 5 | -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; | |
| 6 | - | |
| 7 | -/** | |
| 8 | - * @description 支付操作接口 | |
| 9 | - * @author Qingchen | |
| 10 | - * @version 1.0.0 | |
| 11 | - * @date 2021-08-30 10:35 | |
| 12 | - * @class cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint.java | |
| 13 | - */ | |
| 14 | -public interface PayExtensionPoint extends ExtensionPoint { | |
| 15 | - | |
| 16 | - /** | |
| 17 | - * 统一下单:获取"预支付交易会话标识" | |
| 18 | - * @param command | |
| 19 | - * @return | |
| 20 | - */ | |
| 21 | - TransactionsResult unifiedOrder(TransactionsCommand command); | |
| 22 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/command/TransactionsCommand.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.pay.command; | |
| 2 | - | |
| 3 | -import lombok.AllArgsConstructor; | |
| 4 | -import lombok.Data; | |
| 5 | -import lombok.NoArgsConstructor; | |
| 6 | - | |
| 7 | -import java.io.Serializable; | |
| 8 | -import java.math.BigDecimal; | |
| 9 | - | |
| 10 | -/** | |
| 11 | - * @description 下单请求 | |
| 12 | - * @author Qingchen | |
| 13 | - * @version 1.0.0 | |
| 14 | - * @date 2021-08-30 10:48 | |
| 15 | - * @class cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand.java | |
| 16 | - */ | |
| 17 | -@Data | |
| 18 | -@NoArgsConstructor | |
| 19 | -@AllArgsConstructor | |
| 20 | -public class TransactionsCommand implements Serializable { | |
| 21 | - /** | |
| 22 | - * 订单编号 | |
| 23 | - */ | |
| 24 | - private String orderNo; | |
| 25 | - | |
| 26 | - /** | |
| 27 | - * 支付金额 | |
| 28 | - */ | |
| 29 | - private BigDecimal amount; | |
| 30 | - | |
| 31 | - /** | |
| 32 | - * 商品描述 | |
| 33 | - */ | |
| 34 | - private String productDescription; | |
| 35 | - | |
| 36 | - /** | |
| 37 | - * 通知地址 | |
| 38 | - */ | |
| 39 | - private String notifyUrl; | |
| 40 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/domain/TransactionsResult.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.pay.domain; | |
| 2 | - | |
| 3 | -import lombok.*; | |
| 4 | - | |
| 5 | -import java.io.Serializable; | |
| 6 | - | |
| 7 | -/** | |
| 8 | - * @description 下单: 预支付交易单返回结果 | |
| 9 | - * @author Qingchen | |
| 10 | - * @version 1.0.0 | |
| 11 | - * @date 2021-08-30 10:43 | |
| 12 | - * @class cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult.java | |
| 13 | - */ | |
| 14 | -@Data | |
| 15 | -@AllArgsConstructor | |
| 16 | -public class TransactionsResult implements Serializable { | |
| 17 | - | |
| 18 | - /** | |
| 19 | - * 预支付交易会话标识 | |
| 20 | - */ | |
| 21 | - private String prepayId; | |
| 22 | - | |
| 23 | - /** | |
| 24 | - * 订单编号 | |
| 25 | - */ | |
| 26 | - private String orderNo; | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * 系统内部支付单号 | |
| 30 | - */ | |
| 31 | - private String paymentNo; | |
| 32 | - | |
| 33 | - /** | |
| 34 | - * 支付渠道:微信 or 支付宝 | |
| 35 | - */ | |
| 36 | - private String channel; | |
| 37 | - | |
| 38 | - | |
| 39 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/AlipayService.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.pay.impl; | |
| 2 | - | |
| 3 | -import cn.hutool.core.util.IdUtil; | |
| 4 | -import cn.hutool.json.JSONUtil; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; | |
| 6 | -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; | |
| 7 | -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; | |
| 8 | -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; | |
| 9 | -import lombok.extern.slf4j.Slf4j; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * @description 微信 JSAPI 支付 | |
| 13 | - * @author Qingchen | |
| 14 | - * @version 1.0.0 | |
| 15 | - * @date 2021-08-30 10:38 | |
| 16 | - * @class cn.iocoder.yudao.framework.extension.pay.impl.AlipayService.java | |
| 17 | - */ | |
| 18 | -@Extension(businessId = "pay", useCase = "jsapi", scenario = "alipay") | |
| 19 | -@Slf4j | |
| 20 | -public class AlipayService implements PayExtensionPoint { | |
| 21 | - @Override | |
| 22 | - public TransactionsResult unifiedOrder(TransactionsCommand command) { | |
| 23 | - log.info("微信 JSAPI 支付:{}", JSONUtil.toJsonStr(command)); | |
| 24 | - return new TransactionsResult("alipay26112221580621e9b071c00d9e093b0000", command.getOrderNo(), IdUtil.objectId(), "alipay"); | |
| 25 | - } | |
| 26 | -} |
yudao-framework/yudao-spring-boot-starter-extension/src/test/java/cn/iocoder/yudao/framework/extension/pay/impl/WechatPayService.java deleted
| 1 | -package cn.iocoder.yudao.framework.extension.pay.impl; | |
| 2 | - | |
| 3 | -import cn.hutool.core.util.IdUtil; | |
| 4 | -import cn.hutool.json.JSONUtil; | |
| 5 | -import cn.iocoder.yudao.framework.extension.core.stereotype.Extension; | |
| 6 | -import cn.iocoder.yudao.framework.extension.pay.PayExtensionPoint; | |
| 7 | -import cn.iocoder.yudao.framework.extension.pay.command.TransactionsCommand; | |
| 8 | -import cn.iocoder.yudao.framework.extension.pay.domain.TransactionsResult; | |
| 9 | -import lombok.extern.slf4j.Slf4j; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * @description 微信 JSAPI 支付 | |
| 13 | - * @author Qingchen | |
| 14 | - * @version 1.0.0 | |
| 15 | - * @date 2021-08-30 10:37 | |
| 16 | - * @class cn.iocoder.yudao.framework.extension.pay.impl.WechatPayService.java | |
| 17 | - */ | |
| 18 | -@Extension(businessId = "pay", useCase = "jsapi", scenario = "wechat") | |
| 19 | -@Slf4j | |
| 20 | -public class WechatPayService implements PayExtensionPoint { | |
| 21 | - @Override | |
| 22 | - public TransactionsResult unifiedOrder(TransactionsCommand command) { | |
| 23 | - log.info("微信 JSAPI 支付:{}", JSONUtil.toJsonStr(command)); | |
| 24 | - return new TransactionsResult("wx26112221580621e9b071c00d9e093b0000", command.getOrderNo(), IdUtil.objectId(), "wechat"); | |
| 25 | - } | |
| 26 | -} |
yudao-framework/yudao-spring-boot-starter-extension/《芋道 Spring Boot 扩展点组件》.md deleted
| 1 | -### 作用 | |
| 2 | - | |
| 3 | - 为了解决同一个流程不同业务有不同处理逻辑而产生,减少代码中 if else 逻辑,降低代码的耦合性,通过统一的扩展形式来支撑业务的变化。 | |
| 4 | - | |
| 5 | -### 原理 | |
| 6 | - | |
| 7 | - https://blog.csdn.net/significantfrank/article/details/100074716 | |
| 8 | - | |
| 9 | - | |
| 10 | - | |
| 11 | -### 使用介绍 | |
| 12 | - | |
| 13 | -参考测试代码 `cn.iocoder.yudao.framework.extension.ExtensionTest` | |
| 14 | - | |
| 15 | - | |
| 16 | - | |
| 17 | - | |
| 18 | - | |
| 19 | - |
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 { |
| 75 | 75 | return success(true); |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | - @PutMapping("/back") | |
| 79 | - @ApiOperation(value = "回退") | |
| 80 | - // @PreAuthorize("@ss.hasPermission('bpm:task:back')") | |
| 81 | - public CommonResult<Boolean> backTask(@Valid @RequestBody BpmTaskBackReqVO reqVO) { | |
| 82 | - //先硬编码到 回退到第一个审批节点 | |
| 83 | - // String destinationTaskDefKey = "task01"; | |
| 84 | - return taskService.backTask(reqVO); | |
| 85 | - | |
| 86 | - } | |
| 87 | 78 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | |
| 2 | - | |
| 3 | -import io.swagger.annotations.ApiModelProperty; | |
| 4 | -import lombok.AllArgsConstructor; | |
| 5 | -import lombok.Data; | |
| 6 | -import lombok.NoArgsConstructor; | |
| 7 | - | |
| 8 | -import javax.validation.constraints.NotEmpty; | |
| 9 | -import javax.validation.constraints.NotNull; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * @author kemengkai | |
| 13 | - * @create 2022-05-07 08:05 TODO ke:vo 类,使用 swagger 注解即可 | |
| 14 | - */ | |
| 15 | -@Data | |
| 16 | -@AllArgsConstructor | |
| 17 | -@NoArgsConstructor | |
| 18 | -public class BpmTaskBackReqVO { | |
| 19 | - | |
| 20 | - // TODO ke:userId 应该使用后端的,不能前端传递,不然就越权了 | |
| 21 | - @ApiModelProperty(value = "用户id", required = true, example = "1") | |
| 22 | - @NotEmpty(message = "用户id不能为空") | |
| 23 | - private String userId; | |
| 24 | - | |
| 25 | - // TODO ke:procInstId、taskId、oldTaskDefKey 三个,是不是只要传递一个 taskId?字段不要存在推导关系 | |
| 26 | - @ApiModelProperty(value = "流程编号id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0") | |
| 27 | - @NotEmpty(message = "流程编号id不能为空") | |
| 28 | - private String procInstId; | |
| 29 | - | |
| 30 | - @ApiModelProperty(value = "当前任务id", required = true, example = "730da750-cc4f-11ec-b58e-1e429355e4a0") | |
| 31 | - @NotEmpty(message = "当前任务id不能为空") | |
| 32 | - private String taskId; | |
| 33 | - | |
| 34 | - @ApiModelProperty(value = "当前流程任务id", required = true, example = "Activity_1jlembv") | |
| 35 | - @NotNull(message = "当前流程任务id不能为空") | |
| 36 | - private String oldTaskDefKey; | |
| 37 | - | |
| 38 | - @ApiModelProperty(value = "准备回退的流程任务id", required = true, example = "task01") | |
| 39 | - @NotNull(message = "准备回退流程任务id不能为空") | |
| 40 | - private String newTaskDefKey; | |
| 41 | - | |
| 42 | - @ApiModelProperty(value = "审批结果", required = true, example = "任务驳回") | |
| 43 | - @NotNull(message = "审批结果") | |
| 44 | - private String reason; | |
| 45 | -} |
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; |
| 4 | 4 | import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; |
| 5 | 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 6 | 6 | import org.apache.ibatis.annotations.Mapper; |
| 7 | -import org.apache.ibatis.annotations.Param; | |
| 8 | 7 | |
| 9 | 8 | import java.util.Collection; |
| 10 | 9 | import java.util.List; |
| ... | ... | @@ -24,28 +23,4 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> { |
| 24 | 23 | return selectOne(BpmTaskExtDO::getTaskId, taskId); |
| 25 | 24 | } |
| 26 | 25 | |
| 27 | - default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) { | |
| 28 | - return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId); | |
| 29 | - } | |
| 30 | - | |
| 31 | - // TODO @ke:可以使用类上上面的 default 方法实现。然后,方法的命名上,要保持和 db 一样。因为 mapper 是数据层,不关注业务。例如说,这里,其实复用 updateByTaskId 方法即可 | |
| 32 | - /** | |
| 33 | - * 任务驳回 | |
| 34 | - * | |
| 35 | - * @param taskId 任务列表 | |
| 36 | - * @param reason 驳回理由 | |
| 37 | - * | |
| 38 | - * @return 返回驳回结果,是否成功 | |
| 39 | - */ | |
| 40 | - Boolean backByTaskId(@Param("taskId") String taskId, @Param("reason") String reason); | |
| 41 | - | |
| 42 | - // TODO @ke:tong上哈 | |
| 43 | - /** | |
| 44 | - * 逻辑删除任务 | |
| 45 | - * | |
| 46 | - * @param taskIdList 任务id列表 | |
| 47 | - * | |
| 48 | - * @return 返回是否成功 | |
| 49 | - */ | |
| 50 | - Boolean delByTaskIds(@Param("taskIdList") List<String> taskIdList); | |
| 51 | 26 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| 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. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @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<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> 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<HistoricProcessInstance> getHistoricProcessInstances(Set<String> 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<String, Object> 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); } } | |
| 2 | 1 | \ No newline at end of file |
| 2 | +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. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @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<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> 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<HistoricProcessInstance> getHistoricProcessInstances(Set<String> 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<String, Object> 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(); } } | |
| 3 | 3 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
| ... | ... | @@ -85,13 +85,6 @@ public interface BpmTaskService { |
| 85 | 85 | void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO); |
| 86 | 86 | |
| 87 | 87 | /** |
| 88 | - * 回退任务 | |
| 89 | - * | |
| 90 | - * @param reqVO 回退任务信息 | |
| 91 | - */ | |
| 92 | - CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO); | |
| 93 | - | |
| 94 | - /** | |
| 95 | 88 | * 将流程任务分配给指定用户 |
| 96 | 89 | * |
| 97 | 90 | * @param userId 用户编号 | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 6 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | 6 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 8 | 7 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; |
| 9 | -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | |
| 10 | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| 11 | 9 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; |
| 12 | 10 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; |
| 13 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO; | |
| 14 | 11 | import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; |
| 15 | 12 | import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; |
| 16 | 13 | import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; |
| ... | ... | @@ -24,7 +21,6 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 24 | 21 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 25 | 22 | import lombok.extern.slf4j.Slf4j; |
| 26 | 23 | import org.flowable.engine.HistoryService; |
| 27 | -import org.flowable.engine.RuntimeService; | |
| 28 | 24 | import org.flowable.engine.TaskService; |
| 29 | 25 | import org.flowable.engine.history.HistoricProcessInstance; |
| 30 | 26 | import org.flowable.engine.runtime.ProcessInstance; |
| ... | ... | @@ -40,7 +36,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager |
| 40 | 36 | import javax.annotation.Resource; |
| 41 | 37 | import javax.validation.Valid; |
| 42 | 38 | import java.util.*; |
| 43 | -import java.util.stream.Collectors; | |
| 44 | 39 | |
| 45 | 40 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 46 | 41 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| ... | ... | @@ -60,8 +55,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 60 | 55 | @Resource |
| 61 | 56 | private TaskService taskService; |
| 62 | 57 | @Resource |
| 63 | - private RuntimeService runtimeService; | |
| 64 | - @Resource | |
| 65 | 58 | private HistoryService historyService; |
| 66 | 59 | |
| 67 | 60 | @Resource |
| ... | ... | @@ -227,44 +220,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 227 | 220 | } |
| 228 | 221 | |
| 229 | 222 | @Override |
| 230 | - @Transactional(rollbackFor = Exception.class) | |
| 231 | - @TenantIgnore | |
| 232 | - public CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO) { | |
| 233 | - Long userId = Long.valueOf(reqVO.getUserId()); | |
| 234 | - // 校验任务存在 | |
| 235 | - Task task = checkTask(userId, reqVO.getTaskId()); | |
| 236 | - ArrayList<String> oldTaskDefKeyList = CollUtil.newArrayList(reqVO.getOldTaskDefKey()); | |
| 237 | - | |
| 238 | - // List<HistoricActivityInstance> hisActInstList = | |
| 239 | - // historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list(); | |
| 240 | - // TODO @ke:使用 historyService.createHistoricActivityInstanceQuery().processInstanceId(reqVO.getProcInstId()).list() 读取,会存在啥问题呀? | |
| 241 | - List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(reqVO.getProcInstId()); | |
| 242 | - // List<BpmActivityDO> bpmActivityDOList = BpmTaskConvert.INSTANCE.copyList(hisActInstList, BpmActivityDO.class); | |
| 243 | - // bpmActivityDOList.forEach(bpmActivityDO -> log.info("bpmActivityDO = " + bpmActivityDO)); | |
| 244 | - // TODO @ke:如果 开始->a->b->c->d->结束,从 d 驳回到 b 的话,这样会不会导致 a 也被删除呀?http://blog.wya1.com/article/636697030/details/7296 可以看看这篇文章哈。 | |
| 245 | - List<String> taskIdList = bpmActivityDOList.stream().filter( | |
| 246 | - bpmActivityDO -> bpmActivityDO.getActivityId().equals(reqVO.getOldTaskDefKey()) | |
| 247 | - && !bpmActivityDO.getTaskId().equals(reqVO.getTaskId())).map(BpmActivityDO::getTaskId) | |
| 248 | - .collect(Collectors.toList()); | |
| 249 | - | |
| 250 | - // 使用flowable更改任务节点 | |
| 251 | - runtimeService.createChangeActivityStateBuilder().processInstanceId(reqVO.getProcInstId()) | |
| 252 | - .moveActivityIdsToSingleActivityId(oldTaskDefKeyList, reqVO.getNewTaskDefKey()).changeState(); | |
| 253 | - | |
| 254 | - // 逻辑删除hiActInst表任务 | |
| 255 | - Boolean delHiActInstResult = bpmActivityMapper.delHiActInstByTaskId(taskIdList); | |
| 256 | - // 逻辑删除hiTaskInst表任务 | |
| 257 | - Boolean delHiTaskInstResult = bpmActivityMapper.delHiTaskInstByTaskId(taskIdList); | |
| 258 | - // 更新任务拓展表 | |
| 259 | - Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getReason()); | |
| 260 | - Boolean delTaskResult = taskExtMapper.delByTaskIds(taskIdList); | |
| 261 | - if (!delHiActInstResult && !delHiTaskInstResult && !backResult && !delTaskResult) { | |
| 262 | - throw new RuntimeException("任务驳回失败!!!"); | |
| 263 | - } | |
| 264 | - return CommonResult.success(true); | |
| 265 | - } | |
| 266 | - | |
| 267 | - @Override | |
| 268 | 223 | public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) { |
| 269 | 224 | // 校验任务存在 |
| 270 | 225 | Task task = checkTask(userId, reqVO.getId()); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml deleted
| 1 | -<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | -<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper"> | |
| 4 | - | |
| 5 | - <update id="delHiActInstByTaskId"> | |
| 6 | - UPDATE act_hi_actinst | |
| 7 | - SET delete_reason_ = 'delete task' WHERE task_id_ IN | |
| 8 | - <foreach collection="taskIdList" item="item" open="(" separator="," close=")"> | |
| 9 | - #{item} | |
| 10 | - </foreach> | |
| 11 | - </update> | |
| 12 | - <delete id="delHiTaskInstByTaskId"> | |
| 13 | - UPDATE act_hi_taskinst | |
| 14 | - SET delete_reason_ = 'delete task' WHERE id_ IN | |
| 15 | - <foreach collection="taskIdList" item="item" open="(" separator="," close=")"> | |
| 16 | - #{item} | |
| 17 | - </foreach> | |
| 18 | - </delete> | |
| 19 | - | |
| 20 | - <select id="listAllByProcInstIdAndDelete" | |
| 21 | - resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO"> | |
| 22 | - SELECT id_ AS `id`, | |
| 23 | - rev_ AS `rev`, | |
| 24 | - proc_def_id_ AS `proc_def_id`, | |
| 25 | - proc_inst_id_ AS `process_instance_id`, | |
| 26 | - execution_id_ AS `execution_id`, | |
| 27 | - act_id_ AS `activity_id`, | |
| 28 | - task_id_ AS `task_id`, | |
| 29 | - call_proc_inst_id_ AS `call_proc_inst_id`, | |
| 30 | - act_name_ AS `activity_name`, | |
| 31 | - act_type_ AS `activity_type`, | |
| 32 | - assignee_ AS `assignee`, | |
| 33 | - start_time_ AS `start_time`, | |
| 34 | - end_time_ AS `end_time`, | |
| 35 | - transaction_order_ AS `transaction_order`, | |
| 36 | - duration_ AS `duration`, | |
| 37 | - delete_reason_ AS `delete_reason`, | |
| 38 | - tenant_id_ AS `tenant_id` | |
| 39 | - FROM act_hi_actinst aha | |
| 40 | - WHERE aha.proc_inst_id_ = #{procInstId} | |
| 41 | - AND aha.act_type_ != 'sequenceFlow' | |
| 42 | - LIMIT 500; | |
| 43 | - </select> | |
| 44 | -</mapper> |
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml deleted
| 1 | -<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
| 3 | -<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper"> | |
| 4 | - | |
| 5 | - <update id="backByTaskId"> | |
| 6 | - UPDATE bpm_task_ext | |
| 7 | - SET result=2, | |
| 8 | - `reason`=#{reason} | |
| 9 | - WHERE task_id = #{taskId} | |
| 10 | - </update> | |
| 11 | - <update id="delByTaskIds"> | |
| 12 | - UPDATE bpm_task_ext | |
| 13 | - SET result=1, | |
| 14 | - `deleted`= true | |
| 15 | - WHERE `task_id` IN | |
| 16 | - <foreach collection="taskIdList" item="item" open="(" separator="," close=")"> | |
| 17 | - #{item} | |
| 18 | - </foreach> | |
| 19 | - </update> | |
| 20 | - | |
| 21 | -</mapper> |
yudao-ui-admin/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | <div class="panel-tab__content"> |
| 3 | 3 | <el-form size="mini" label-width="90px" :model="model" :rules="rules" @submit.native.prevent> |
| 4 | 4 | <div v-if="elementBaseInfo.$type === 'bpmn:Process'"> <!-- 如果是 Process 信息的时候,使用自定义表单 --> |
| 5 | + <el-link href="https://doc.iocoder.cn/bpm/#_3-%E4%BC%9A%E7%AD%BE-%E6%88%96%E7%AD%BE" | |
| 6 | + type="danger" target="_blank">如何实现实现会签、或签?</el-link> | |
| 5 | 7 | <el-form-item label="流程标识" prop="key"> |
| 6 | 8 | <el-input v-model="model.key" placeholder="请输入流标标识" |
| 7 | 9 | :disabled="model.id !== undefined && model.id.length > 0" @change="handleKeyUpdate" /> | ... | ... |
yudao-ui-admin/src/views/bpm/processInstance/detail.vue
| ... | ... | @@ -412,15 +412,16 @@ export default { |
| 412 | 412 | }, |
| 413 | 413 | /** 处理审批退回的操作 */ |
| 414 | 414 | handleBack(task) { |
| 415 | - const data = { | |
| 416 | - id: task.id, | |
| 417 | - assigneeUserId: 1 | |
| 418 | - } | |
| 419 | - // this.$modal.msgError("暂不支持【--退回】功能!"); | |
| 420 | - backTask(data).then(response => { | |
| 421 | - this.$modal.msgSuccess("回退成功!"); | |
| 422 | - this.getDetail(); // 获得最新详情 | |
| 423 | - }); | |
| 415 | + this.$modal.msgError("暂不支持【退回】功能!"); | |
| 416 | + // 可参考 http://blog.wya1.com/article/636697030/details/7296 | |
| 417 | + // const data = { | |
| 418 | + // id: task.id, | |
| 419 | + // assigneeUserId: 1 | |
| 420 | + // } | |
| 421 | + // backTask(data).then(response => { | |
| 422 | + // this.$modal.msgSuccess("回退成功!"); | |
| 423 | + // this.getDetail(); // 获得最新详情 | |
| 424 | + // }); | |
| 424 | 425 | } |
| 425 | 426 | } |
| 426 | 427 | }; | ... | ... |