初始代码
This commit is contained in:
101
.gitignore
vendored
Normal file
101
.gitignore
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#======================================================================================================================
|
||||||
|
#========================================= gitignore的基础用法 =========================================
|
||||||
|
#======================================================================================================================
|
||||||
|
# 一.基础语法
|
||||||
|
# .gitignore配置文件的一些通用技巧 [参考:https://git-scm.com/docs/gitignore]
|
||||||
|
# 1.空白行不匹配任何文件,所以可以作为可读性的分隔符,同时两端的空格将会被忽略.
|
||||||
|
# 2.使用[#]开头,将会注释掉整行,使其不进行匹配操作,如果需要匹配#开头,可以使用转义字符[\].
|
||||||
|
# 3.1匹配模式以[/]结尾,表示想要匹配一个目录及其子文件.(比如[foo/]会匹配foo目录及其下面的路径.)
|
||||||
|
# 3.2匹配模式不包含[/],将会全局匹配该文件.
|
||||||
|
# 4.通配符
|
||||||
|
# [*]: 匹配除[/]以外的任何内容,也就意味着[*]不能跨目录.
|
||||||
|
# [?]: 匹配除[/]和[[]以及[]]以外的任何一个字符.
|
||||||
|
# [**]: 匹配所有的内容,或者说匹配任意目录下的内容.
|
||||||
|
# 示例:
|
||||||
|
# 1.[**/foo/bar] 将会匹配所有直接在foo目录下的bar,无论foo处在何处.
|
||||||
|
# 2.[foo/**]则表示匹配foo目录下的所有文件和目录.
|
||||||
|
# 3.[a/**/b]则可以匹配a/b, a/c/b, a/c/d/b,即此处的[**]可以表示0个或多个.
|
||||||
|
# !!! 需要注意的是,除上面示例的用法外,剩余的[**]都是无效的..
|
||||||
|
# 5.可以通过前缀[!]来表示不忽略某些文件,比如可以通过[!a]来确保文件a不会被忽略,即时前面已经声明了忽略其父目录,该模式优先级高于普通忽略模式.
|
||||||
|
# 二.常用命令
|
||||||
|
# 1.git -rm [https://git-scm.com/docs/git-rm]
|
||||||
|
# 删除文件索引,或者同时删除文件索引和物理文件.可以使用通配符.
|
||||||
|
# 2.git-check-ignore [https://git-scm.com/docs/git-check-ignore]
|
||||||
|
# 调试.gitignore文件
|
||||||
|
# 三.注意事项
|
||||||
|
# 1.如果文件已经被git管理,那么后续添加的忽略模式将不会生效,具体解决方法,参考<<二.常用命令>>.
|
||||||
|
|
||||||
|
#=======================================================================================================================
|
||||||
|
#============================== java忽略文件 =====================================
|
||||||
|
#===================== https://github.com/github/gitignore/blob/master/Java.gitignore ==================
|
||||||
|
#=======================================================================================================================
|
||||||
|
# 编译后的class文件,忽略所有以[.class]结尾的文件
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# 日志文件,忽略所有以[.log]结尾的文件.
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ 文件,忽略所有以[.ctxt]结尾的文件.
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME),忽略[.mtj.tmp/]目录及其子文件.
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# 打包文件,忽略所有以[.jar]或[.war]或[.nar]或[.ear]或[.zip]或[.tar.gz]或[rar]结尾的文件.
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# 虚拟机崩溃日志,忽略所有以[hs_err_pid]开头的文件.[see http://www.java.com/en/download/help/error_hotspot.xml]
|
||||||
|
hs_err_pid*
|
||||||
|
#=======================================================================================================================
|
||||||
|
#============================== maven忽略文件 ===================================
|
||||||
|
#===================== https://github.com/github/gitignore/blob/master/Maven.gitignore ==================
|
||||||
|
#=======================================================================================================================
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
|
||||||
|
!/.mvn/wrapper/maven-wrapper.jar
|
||||||
|
#=======================================================================================================================
|
||||||
|
#============================== IDE环境忽略文件 ==================================
|
||||||
|
#===================== https://github.com/github/gitignore/blob/master/Maven.gitignore ==================
|
||||||
|
#=======================================================================================================================
|
||||||
|
#----------------IDEA-------------
|
||||||
|
.idea/*
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/encodings.xml
|
||||||
|
.idea/modules.xml
|
||||||
|
*.iml
|
||||||
|
#=======================================================================================================================
|
||||||
|
#============================== other环境忽略文件 ================================
|
||||||
|
#===================== https://github.com/github/gitignore/blob/master/Maven.gitignore ==================
|
||||||
|
#=======================================================================================================================
|
||||||
|
*.sw?
|
||||||
|
.#*
|
||||||
|
*#
|
||||||
|
*~
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
bin
|
||||||
|
build
|
||||||
|
target
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
*.sublime-*
|
||||||
|
/scratch
|
||||||
|
.gradle
|
||||||
|
Guardfile
|
||||||
|
README.html
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
45
README.md
Normal file
45
README.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
> 特别说明:源码、JDK、数据库、Redis等安装或存放路径禁止包含中文、空格、特殊字符等
|
||||||
|
|
||||||
|
## 一 环境要求
|
||||||
|
|
||||||
|
| 类目 | 版本说明或建议 |
|
||||||
|
| --- |--------------------------------------------------|
|
||||||
|
| 硬件 | 开发电脑建议使用I3及以上CPU,16G及以上内存 |
|
||||||
|
| 操作系统 | Windows 10/11,MacOS |
|
||||||
|
| JDK | 默认使用JDK 21,如需要切换JDK 8/11/17版本请参考文档调整代码,推荐使用 `OpenJDK`,如 `Liberica JDK`、`Eclipse Temurin`、`Alibaba Dragonwell`、`BiSheng`等发行版;|
|
||||||
|
| Maven | 依赖管理工具,推荐使用 `3.6.3` 及以上版本 |
|
||||||
|
| IDE | 代码集成开发环境,推荐使用 `IDEA2024` 及以上版本,兼容 `Eclipse`、 `Spring Tool Suite` 等IDE工具 |
|
||||||
|
|
||||||
|
## 二 关联项目
|
||||||
|
> 为以下项目提供基础依赖
|
||||||
|
|
||||||
|
| 项目 | 分支 | 说明 |
|
||||||
|
|---------------|---------------|------------|
|
||||||
|
| yunzhupaas-workflow | v1.0.0-stable | 流程引擎后端项目源码 |
|
||||||
|
|
||||||
|
## 三 选择是否加密
|
||||||
|
|
||||||
|
> 是否加密将会影响 `yunzhupaas-workflow` 项目的启动方式
|
||||||
|
> 如果此项目选择加密 `yunzhupaas-workflow` 项目也需要选择加密
|
||||||
|
|
||||||
|
### 3.1 不使用加密
|
||||||
|
|
||||||
|
在IDEA中, 展开右侧 `Maven` 中 `Profiles` 去除勾选 `encrypted` 选项, 再点击Maven `刷新` 图标刷新Maven
|
||||||
|
|
||||||
|
### 3.2 使用加密
|
||||||
|
|
||||||
|
在IDEA中, 展开右侧 `Maven` 中 `Profiles` 勾选 `encrypted` 选项, 再点击Maven `刷新` 图标刷新Maven
|
||||||
|
|
||||||
|
#### 3.2.1 安装加密插件
|
||||||
|
|
||||||
|
在IDEA中,双击右侧 `Maven` 中 `yunzhupaas-workflow-core` > `clean` 将会自动安装加密打包插件
|
||||||
|
|
||||||
|
## 四 使用方式
|
||||||
|
|
||||||
|
### 4.1 本地安装
|
||||||
|
|
||||||
|
在IDEA中,双击右侧 `Maven` 中 `yunzhupaas-workflow-core` > `Lifecycle` > `install`,将`yunzhupaas-workflow-core`包安装至本地
|
||||||
|
|
||||||
|
### 4.2 发布到私服
|
||||||
|
|
||||||
|
在IDEA中,双击右侧 `Maven` 中 `yunzhupaas-workflow-core` > `Lifecycle` > `deploy` 发布至私服。
|
||||||
31
allatori/allatori.xml
Normal file
31
allatori/allatori.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<config>
|
||||||
|
<input>
|
||||||
|
<jar in="${project.build.finalName}.jar" out="${project.build.finalName}.jar"/>
|
||||||
|
</input>
|
||||||
|
|
||||||
|
<keep-names>
|
||||||
|
<class access="protected+">
|
||||||
|
<field access="protected+"/>
|
||||||
|
<method access="protected+"/>
|
||||||
|
</class>
|
||||||
|
</keep-names>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 混淆设置 -->
|
||||||
|
<!--随机类名保持小写-->
|
||||||
|
<property name="classes-naming" value="abc"/>
|
||||||
|
<!-- 接口形参名保持不变 -->
|
||||||
|
<property name="local-variables-naming" value="keep-parameters"/>
|
||||||
|
<!-- 字符串加密 -->
|
||||||
|
<property name="string-encryption" value="maximum"/>
|
||||||
|
<property name="string-encryption-type" value="strong"/>
|
||||||
|
<property name="string-encryption-version" value="v4"/>
|
||||||
|
<!-- 行数混淆 -->
|
||||||
|
<property name="line-numbers" value="obfuscate"/>
|
||||||
|
<!-- 成员重新排序 -->
|
||||||
|
<property name="member-reorder" value="enable"/>
|
||||||
|
<!-- 数据jar压缩等级 -->
|
||||||
|
<property name="output-jar-compression-level" value="9"/>
|
||||||
|
|
||||||
|
<property name="log-file" value="log.xml"/>
|
||||||
|
</config>
|
||||||
37
allatori/class-winter-maven-plugin-pom.xml
Normal file
37
allatori/class-winter-maven-plugin-pom.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.idea-aedi</groupId>
|
||||||
|
<artifactId>class-winter-core</artifactId>
|
||||||
|
<version>enhance-2.9.4</version>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.idea-aedi</groupId>
|
||||||
|
<artifactId>class-winter-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-plugin-api</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugin-tools</groupId>
|
||||||
|
<artifactId>maven-plugin-annotations</artifactId>
|
||||||
|
<version>3.6.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-project</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
196
pom.xml
Normal file
196
pom.xml
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-core</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>1.0.0-RELEASE</version>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>yunzhupaas-workflow-common</module>
|
||||||
|
<module>yunzhupaas-workflow-flowable</module>
|
||||||
|
<!-- <module>yunzhupaas-workflow-activiti</module>-->
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
|
||||||
|
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
|
||||||
|
<maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
|
||||||
|
<maven-install-plugin.version>2.5.2</maven-install-plugin.version>
|
||||||
|
<maven-dependency-plugin.version>3.5.0</maven-dependency-plugin.version>
|
||||||
|
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
|
||||||
|
<exec-maven-plugin.version>1.2.1</exec-maven-plugin.version>
|
||||||
|
<class-winter-maven-plugin.version>enhance-2.9.4</class-winter-maven-plugin.version>
|
||||||
|
|
||||||
|
<hutool.version>5.8.27</hutool.version>
|
||||||
|
<springdoc.openapi.version>2.3.0</springdoc.openapi.version>
|
||||||
|
<activiti.version>7.1.0.M4</activiti.version>
|
||||||
|
<!-- swagger -->
|
||||||
|
<knife4j.version>4.5.0</knife4j.version>
|
||||||
|
<!--flowable 脚本引擎-->
|
||||||
|
<liqui.version>4.27.0</liqui.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- SpringBoot 依赖配置 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--flowable 脚本引擎-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.liquibase</groupId>
|
||||||
|
<artifactId>liquibase-core</artifactId>
|
||||||
|
<version>${liqui.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>${maven-deploy-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-install-plugin</artifactId>
|
||||||
|
<version>${maven-install-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>${maven-dependency-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>${maven-resources-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>${exec-maven-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.idea-aedi</groupId>
|
||||||
|
<artifactId>class-winter-maven-plugin</artifactId>
|
||||||
|
<version>${class-winter-maven-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<parameters>true</parameters>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>boot3</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[17,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<!--这里修改JDK版本号, 1.8, 11, 17-->
|
||||||
|
<java.version>21</java.version>
|
||||||
|
<!--最高版本语言特性-->
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<!--最低运行JDK版本-->
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<!-- spring依赖 -->
|
||||||
|
<spring-boot.version>3.3.2</spring-boot.version>
|
||||||
|
|
||||||
|
<!-- 流程引擎 -->
|
||||||
|
<flowable.version>7.0.1</flowable.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>boot2</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>(,17)</jdk>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<!--这里修改JDK版本号, 1.8, 11, 17-->
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<!--最高版本语言特性-->
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<!--最低运行JDK版本-->
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<!-- spring依赖 -->
|
||||||
|
<spring-boot.version>2.7.18</spring-boot.version>
|
||||||
|
|
||||||
|
<!-- 流程引擎 -->
|
||||||
|
<flowable.version>6.8.1</flowable.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<!--私服仓库配置-->
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>maven-releases</id>
|
||||||
|
<name>maven-releases</name>
|
||||||
|
<url>https://xadev.szlecheng.cn/nexus/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
</project>
|
||||||
32
yunzhupaas-workflow-activiti/pom.xml
Normal file
32
yunzhupaas-workflow-activiti/pom.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-core</artifactId>
|
||||||
|
<version>1.0.0-RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>yunzhupaas-workflow-activiti</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.activiti</groupId>
|
||||||
|
<artifactId>activiti-spring-boot-starter</artifactId>
|
||||||
|
<version>${activiti.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package com.yunzhupaas.workflow.activiti.cmd;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import org.activiti.bpmn.model.BpmnModel;
|
||||||
|
import org.activiti.bpmn.model.UserTask;
|
||||||
|
import org.activiti.engine.RuntimeService;
|
||||||
|
import org.activiti.engine.history.HistoricActivityInstance;
|
||||||
|
import org.activiti.engine.history.HistoricTaskInstance;
|
||||||
|
import org.activiti.engine.impl.HistoricActivityInstanceQueryImpl;
|
||||||
|
import org.activiti.engine.impl.HistoricTaskInstanceQueryImpl;
|
||||||
|
import org.activiti.engine.impl.Page;
|
||||||
|
import org.activiti.engine.impl.interceptor.Command;
|
||||||
|
import org.activiti.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.activiti.engine.impl.persistence.entity.*;
|
||||||
|
import org.activiti.engine.runtime.Execution;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转命令类
|
||||||
|
*
|
||||||
|
* @author yanghuixing
|
||||||
|
* @author YMPaaS CloudYUNZHUPAAS开发组
|
||||||
|
* @version 0.2.0
|
||||||
|
* @since 2023/8/22 17:56
|
||||||
|
*/
|
||||||
|
public class JumpCmd implements Command<Void> {
|
||||||
|
private final String processInstanceId;
|
||||||
|
|
||||||
|
private List<String> sourceTaskDefIdList;
|
||||||
|
private List<String> targetFlowNodeIdList;
|
||||||
|
|
||||||
|
private String deleteReason;
|
||||||
|
|
||||||
|
private final BpmnModel bpmnModel;
|
||||||
|
private final RuntimeService runtimeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存撤回节点的变量map
|
||||||
|
*/
|
||||||
|
private Map<String, List<VariableInstanceEntity>> varMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public JumpCmd(String processInstanceId, List<String> sourceTaskDefIdList, List<String> targetFlowNodeIdList,
|
||||||
|
String deleteReason, BpmnModel bpmnModel, RuntimeService runtimeService) {
|
||||||
|
this.processInstanceId = processInstanceId;
|
||||||
|
this.sourceTaskDefIdList = sourceTaskDefIdList;
|
||||||
|
this.deleteReason = deleteReason;
|
||||||
|
this.targetFlowNodeIdList = targetFlowNodeIdList;
|
||||||
|
this.bpmnModel = bpmnModel;
|
||||||
|
this.runtimeService = runtimeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(CommandContext commandContext) {
|
||||||
|
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
|
||||||
|
// 处理act_ru_execution
|
||||||
|
handleExecution(commandContext);
|
||||||
|
// 处理act_hi_actinst
|
||||||
|
handleActInst(commandContext);
|
||||||
|
|
||||||
|
targetFlowNodeIdList.forEach(targetId -> {
|
||||||
|
UserTask userTask = (UserTask) bpmnModel.getFlowElement(targetId);
|
||||||
|
// 创建子执行流,开启任务
|
||||||
|
ExecutionEntity processExecution = executionEntityManager.findById(processInstanceId);
|
||||||
|
ExecutionEntity childExecution = executionEntityManager.createChildExecution(processExecution);
|
||||||
|
childExecution.setCurrentFlowElement(userTask);
|
||||||
|
|
||||||
|
// 设置执行变量
|
||||||
|
VariableInstanceEntityManager variableManage = commandContext.getVariableInstanceEntityManager();
|
||||||
|
List<VariableInstanceEntity> variableInstanceEntities = varMap.get(userTask.getId());
|
||||||
|
if (CollectionUtil.isNotEmpty(variableInstanceEntities)) {
|
||||||
|
variableInstanceEntities.forEach(var -> {
|
||||||
|
var.setExecutionId(childExecution.getId());
|
||||||
|
variableManage.insert(var);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
executionEntityManager.insert(childExecution);
|
||||||
|
// 交给引擎流转
|
||||||
|
commandContext.getAgenda().planContinueProcessOperation(childExecution);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleActInst(CommandContext commandContext) {
|
||||||
|
for (String str : sourceTaskDefIdList) {
|
||||||
|
HistoricActivityInstanceQueryImpl query = new HistoricActivityInstanceQueryImpl().activityId(str)
|
||||||
|
.processInstanceId(processInstanceId).unfinished();
|
||||||
|
List<HistoricActivityInstance> activityInstances = commandContext.getHistoricActivityInstanceEntityManager()
|
||||||
|
.findHistoricActivityInstancesByQueryCriteria(query, new Page(0, Integer.MAX_VALUE));
|
||||||
|
for (HistoricActivityInstance activity : activityInstances) {
|
||||||
|
HistoricActivityInstanceEntity activityEntity = (HistoricActivityInstanceEntity) activity;
|
||||||
|
// 修改act_hi_actinst表
|
||||||
|
activityEntity.setDeleted(true);
|
||||||
|
activityEntity.setDeleteReason(deleteReason);
|
||||||
|
commandContext.getHistoricActivityInstanceEntityManager().update(activityEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleExecution(CommandContext commandContext) {
|
||||||
|
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
|
||||||
|
HistoricTaskInstanceEntityManager historicTaskManager = commandContext.getHistoricTaskInstanceEntityManager();
|
||||||
|
VariableInstanceEntityManager variableManager = commandContext.getVariableInstanceEntityManager();
|
||||||
|
for (String str : sourceTaskDefIdList) {
|
||||||
|
List<Execution> executionEntities = runtimeService.createExecutionQuery()
|
||||||
|
.processInstanceId(processInstanceId).activityId(str).list();
|
||||||
|
for (Execution parentExecution : executionEntities) {
|
||||||
|
// 关闭未完成的任务执行流
|
||||||
|
// 获取子级Executions,如子流程节点等需要处理
|
||||||
|
List<ExecutionEntity> childExecutions = executionEntityManager
|
||||||
|
.findChildExecutionsByParentExecutionId(parentExecution.getId());
|
||||||
|
for (ExecutionEntity childExecution : childExecutions) {
|
||||||
|
// 因为外键约束,首先要删除variable表中的execution相关数据
|
||||||
|
List<VariableInstanceEntity> variableInstances = variableManager
|
||||||
|
.findVariableInstancesByExecutionId(childExecution.getId());
|
||||||
|
varMap.put(parentExecution.getActivityId(), variableInstances);
|
||||||
|
variableInstances.forEach(variableManager::delete);
|
||||||
|
executionEntityManager.deleteExecutionAndRelatedData(childExecution, deleteReason, false);
|
||||||
|
// 修改历史实例
|
||||||
|
HistoricTaskInstanceQueryImpl query = new HistoricTaskInstanceQueryImpl()
|
||||||
|
.executionId(childExecution.getId()).processInstanceId(processInstanceId);
|
||||||
|
List<HistoricTaskInstance> HistoricTaskInstances = historicTaskManager
|
||||||
|
.findHistoricTaskInstancesByQueryCriteria(query);
|
||||||
|
if (CollectionUtil.isNotEmpty(HistoricTaskInstances)) {
|
||||||
|
for (HistoricTaskInstance HistoricTaskInstance : HistoricTaskInstances) {
|
||||||
|
HistoricTaskInstanceEntity entity = (HistoricTaskInstanceEntity) HistoricTaskInstance;
|
||||||
|
entity.setDeleteReason(deleteReason);
|
||||||
|
commandContext.getHistoricTaskInstanceEntityManager().update(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 父执行流关闭
|
||||||
|
List<VariableInstanceEntity> variableInstances = variableManager
|
||||||
|
.findVariableInstancesByExecutionId(parentExecution.getId());
|
||||||
|
varMap.put(parentExecution.getActivityId(), variableInstances);
|
||||||
|
variableInstances.forEach(variableManager::delete);
|
||||||
|
ExecutionEntity parentExecution1 = (ExecutionEntity) parentExecution;
|
||||||
|
executionEntityManager.deleteExecutionAndRelatedData(parentExecution1, deleteReason, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
package com.yunzhupaas.workflow.activiti.util;
|
||||||
|
|
||||||
|
import org.activiti.bpmn.model.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activiti工具类
|
||||||
|
*
|
||||||
|
* @author yanghuixing
|
||||||
|
* @author YMPaaS CloudYUNZHUPAAS开发组
|
||||||
|
* @version 0.2.0
|
||||||
|
* @since 2023/8/22 14:12
|
||||||
|
*/
|
||||||
|
public class ActivitiUtil {
|
||||||
|
/**
|
||||||
|
* 获取全部节点元素
|
||||||
|
*
|
||||||
|
* @param flowElements {@link Collection<FlowElement>}
|
||||||
|
* @param allElements {@link Collection<FlowElement>}
|
||||||
|
* @return {@link Collection<FlowElement>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:08
|
||||||
|
**/
|
||||||
|
public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements,
|
||||||
|
Collection<FlowElement> allElements) {
|
||||||
|
allElements = allElements == null ? new ArrayList<>() : allElements;
|
||||||
|
for (FlowElement flowElement : flowElements) {
|
||||||
|
allElements.add(flowElement);
|
||||||
|
if (flowElement instanceof SubProcess) {
|
||||||
|
// 获取子流程元素
|
||||||
|
allElements = getAllElements(((SubProcess) flowElement).getFlowElements(), allElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的入口连线
|
||||||
|
*
|
||||||
|
* @param element {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:09
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getElementIncomingFlows(FlowElement element) {
|
||||||
|
List<SequenceFlow> sequenceFlows = null;
|
||||||
|
if (element instanceof FlowNode) {
|
||||||
|
sequenceFlows = ((FlowNode) element).getIncomingFlows();
|
||||||
|
}
|
||||||
|
return sequenceFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的入口连线
|
||||||
|
*
|
||||||
|
* @param element {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:10
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement element) {
|
||||||
|
List<SequenceFlow> sequenceFlows = null;
|
||||||
|
if (element instanceof FlowNode) {
|
||||||
|
sequenceFlows = ((FlowNode) element).getOutgoingFlows();
|
||||||
|
}
|
||||||
|
return sequenceFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可回退的节点(用户任务、子流程)
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param passActs {@link List<Activity>}
|
||||||
|
* @return {@link List<Activity>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:11
|
||||||
|
**/
|
||||||
|
public static List<Activity> getPassActs(FlowElement source, Set<String> passFlows, List<Activity> passActs) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
passActs = passActs == null ? new ArrayList<>() : passActs;
|
||||||
|
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && sequenceFlows.size() > 0) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加经过的用户任务、子流程
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||||
|
passActs.add((UserTask) sequenceFlow.getSourceFlowElement());
|
||||||
|
}
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
|
||||||
|
passActs.add((SubProcess) sequenceFlow.getSourceFlowElement());
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getPassActs(sequenceFlow.getSourceFlowElement(), passFlows, passActs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passActs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上一级节点(用户任务、子流程)
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param parentActs {@link List<Activity>}
|
||||||
|
* @return {@link List<Activity>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:13
|
||||||
|
**/
|
||||||
|
public static List<Activity> getParentActs(FlowElement source, Set<String> passFlows, List<Activity> parentActs) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
parentActs = parentActs == null ? new ArrayList<>() : parentActs;
|
||||||
|
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && sequenceFlows.size() > 0) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加用户任务、子流程
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||||
|
parentActs.add((UserTask) sequenceFlow.getSourceFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof SubProcess) {
|
||||||
|
parentActs.add((SubProcess) sequenceFlow.getSourceFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getParentActs(sequenceFlow.getSourceFlowElement(), passFlows, parentActs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parentActs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要撤回的节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param runTaskKeyList {@link List<String>}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param userTasks {@link List<UserTask>}
|
||||||
|
* @return {@link List<UserTask>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:13
|
||||||
|
**/
|
||||||
|
public static List<UserTask> getChildUserTasks(FlowElement source, List<String> runTaskKeyList,
|
||||||
|
Set<String> passFlows, List<UserTask> userTasks) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
userTasks = userTasks == null ? new ArrayList<>() : userTasks;
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows && sequenceFlows.size() > 0) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 用户任务
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof UserTask
|
||||||
|
&& runTaskKeyList.contains(sequenceFlow.getTargetFlowElement().getId())) {
|
||||||
|
userTasks.add((UserTask) sequenceFlow.getTargetFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 子流程,从第一个节点开始获取
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
|
||||||
|
FlowElement flowElement = (FlowElement) ((SubProcess) sequenceFlow.getTargetFlowElement())
|
||||||
|
.getFlowElements().toArray()[0];
|
||||||
|
List<UserTask> tasks = getChildUserTasks(flowElement, runTaskKeyList, passFlows, null);
|
||||||
|
// 找到用户任务,不继续向下找
|
||||||
|
if (tasks.size() > 0) {
|
||||||
|
userTasks.addAll(tasks);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, passFlows, userTasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下一级的用户任务
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param hasSequenceFlow {@link Set<String>}
|
||||||
|
* @param userTaskList {@link List<UserTask>}
|
||||||
|
* @return {@link List<UserTask>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:15
|
||||||
|
**/
|
||||||
|
public static List<UserTask> getNextUserTasks(FlowElement source, Set<String> hasSequenceFlow,
|
||||||
|
List<UserTask> userTaskList) {
|
||||||
|
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
|
||||||
|
userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof UserTask) {
|
||||||
|
// 若节点为用户任务,加入到结果列表中
|
||||||
|
userTaskList.add((UserTask) targetFlowElement);
|
||||||
|
} else {
|
||||||
|
// 若节点非用户任务,继续递归查找下一个节点
|
||||||
|
getNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断某个节点的出口是否是网关,获取网关的出口连线
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:15
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getOutFlowsOfGateway(FlowElement source) {
|
||||||
|
List<SequenceFlow> flows = new ArrayList<>();
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof Gateway) {
|
||||||
|
List<SequenceFlow> outgoingFlows = ((Gateway) targetFlowElement).getOutgoingFlows();
|
||||||
|
flows.addAll(outgoingFlows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flows;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取之前的节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param keys {@link List<String>}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @author yanghuixing
|
||||||
|
* @since 2023/8/22 16:16
|
||||||
|
**/
|
||||||
|
public static List<String> getBefore(FlowElement source, Set<String> passFlows, List<String> keys) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
keys = keys == null ? new ArrayList<>() : keys;
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && sequenceFlows.size() > 0) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加节点Key
|
||||||
|
keys.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getBefore(sequenceFlow.getSourceFlowElement(), passFlows, keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
yunzhupaas-workflow-common/pom.xml
Normal file
65
yunzhupaas-workflow-common/pom.xml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>yunzhupaas-workflow-common</artifactId>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-core</artifactId>
|
||||||
|
<version>1.0.0-RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- lombok 工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- hutool 工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>${springdoc.openapi.version}</version>
|
||||||
|
</dependency>-->
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>boot3</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[17,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>boot2</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>(,17)</jdk>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<!--引入Knife4j的官方start包,该指南选择Spring Boot版本<3.0,开发者需要注意-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.exception;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务异常类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 15:31
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class BizException extends RuntimeException {
|
||||||
|
public ResultCode resultCode;
|
||||||
|
|
||||||
|
public BizException(ResultCode errorCode) {
|
||||||
|
super(errorCode.getMsg());
|
||||||
|
this.resultCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BizException(String message) {
|
||||||
|
super(message);
|
||||||
|
this.resultCode = ResultCode.SYSTEM_EXECUTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BizException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
this.resultCode = ResultCode.SYSTEM_EXECUTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BizException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
this.resultCode = ResultCode.SYSTEM_EXECUTION_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.exception;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一返回结果枚举类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 15:08
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum ResultCode implements Serializable {
|
||||||
|
|
||||||
|
SUCCESS("200", "请求成功"),
|
||||||
|
FAILURE("999", "请求失败"),
|
||||||
|
|
||||||
|
DELETE_SUCCESS("1101", "删除成功"),
|
||||||
|
DELETE_FAILURE("1102", "删除失败"),
|
||||||
|
DEPLOY_FAILURE("1103", "部署失败"),
|
||||||
|
START_FAILURE("1104", "启动失败"),
|
||||||
|
COMPLETE_SUCCESS("1105", "任务完成成功"),
|
||||||
|
COMPLETE_FAILURE("1106", "任务完成失败"),
|
||||||
|
RETRACT_SUCCESS("1107", "撤回成功"),
|
||||||
|
RETRACT_FAILURE("1108", "撤回失败"),
|
||||||
|
JUMP_SUCCESS("1109", "跳转成功"),
|
||||||
|
JUMP_FAILURE("1110", "跳转失败"),
|
||||||
|
|
||||||
|
DEPLOY_ERROR("9001", "部署错误,请检查XML格式、内容等是否有误"),
|
||||||
|
DEFINITION_NOT_EXIST("9002", "找不到流程模板,请重新发布该流程"),
|
||||||
|
INSTANCE_NOT_EXIST("9003", "实例不存在"),
|
||||||
|
TASK_NOT_EXIST("9004", "任务不存在"),
|
||||||
|
TASK_COMPLETE_ERROR("9005", "任务完成错误"),
|
||||||
|
TASK_JUMP_ERROR("9006", "节点跳转错误"),
|
||||||
|
|
||||||
|
SYSTEM_EXECUTION_ERROR("9901", "系统执行出错"),
|
||||||
|
REQUEST_PARAM_IS_NULL("9701", "请求必填参数为空");
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/6/4 11:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CompensateFo {
|
||||||
|
/**
|
||||||
|
* 实例主键
|
||||||
|
*/
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 原先的节点
|
||||||
|
*/
|
||||||
|
private List<String> source;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义删除参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 11:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DefinitionDeleteFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 引擎部署ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "引擎部署ID不能为空")
|
||||||
|
@Schema(name = "deploymentId", description = "引擎部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 是否级联删除流程定义下的流程实例等
|
||||||
|
*/
|
||||||
|
@Schema(name = "cascade", description = "是否级联删除流程定义下的流程实例等")
|
||||||
|
private Boolean cascade;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义部署参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 11:45
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DefinitionDeployFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* bpmn xml字符串
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "bpmn xml字符串不能为空")
|
||||||
|
@Schema(name = "bpmnXml", description = "bpmn xml字符串")
|
||||||
|
private String bpmnXml;
|
||||||
|
/**
|
||||||
|
* 业务名称
|
||||||
|
*/
|
||||||
|
@Schema(name = "name", description = "业务名称")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 业务Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "key", description = "业务Key")
|
||||||
|
private String key;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接线目标任务
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/4/17 17:36
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FlowTargetTaskFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 线的Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "flowKey", description = "线的Key")
|
||||||
|
private String flowKey;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/9/30 15:09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InfoModel implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 节点Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "key", description = "节点Key")
|
||||||
|
private String key;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例删除参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 15:55
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InstanceDeleteFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "实例ID不能为空")
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 删除原因
|
||||||
|
*/
|
||||||
|
@Schema(name = "deleteReason", description = "删除原因")
|
||||||
|
private String deleteReason;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例启动参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 15:14
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InstanceStartFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "部署ID不能为空")
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 变量
|
||||||
|
*/
|
||||||
|
@Schema(name = "variables", description = "变量")
|
||||||
|
private Map<String, Object> variables;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/10 11:18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class JumpFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "实例ID不能为空")
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 源节点集合
|
||||||
|
*/
|
||||||
|
@Schema(name = "source", description = "源节点集合")
|
||||||
|
private List<String> source;
|
||||||
|
/**
|
||||||
|
* 目标节点集合
|
||||||
|
*/
|
||||||
|
@Schema(name = "target", description = "目标节点集合")
|
||||||
|
private List<String> target;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多节点跳转单节点参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/9 14:23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MoveMultiToSingleFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "实例ID不能为空")
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 当前节点集合
|
||||||
|
*/
|
||||||
|
@NotNull(message = "当前节点集合不能为空")
|
||||||
|
@Schema(name = "sourceKeys", description = "当前节点集合")
|
||||||
|
private List<String> sourceKeys;
|
||||||
|
/**
|
||||||
|
* 目标节点
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "目标节点不能为空")
|
||||||
|
@Schema(name = "targetKey", description = "目标节点")
|
||||||
|
private String targetKey;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单节点跳转多节点参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 16:36
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MoveSingleToMultiFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "实例ID不能为空")
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 当前节点
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "当前节点不能为空")
|
||||||
|
@Schema(name = "sourceKey", description = "当前节点")
|
||||||
|
private String sourceKey;
|
||||||
|
/**
|
||||||
|
* 目标节点集合
|
||||||
|
*/
|
||||||
|
@NotNull(message = "目标节点集合不能为空")
|
||||||
|
@Schema(name = "targetKeys", description = "目标节点集合")
|
||||||
|
private List<String> targetKeys;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/5/8 20:03
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskAfterFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 节点Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskKeys", description = "节点Key")
|
||||||
|
private List<String> taskKeys = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务退回参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 16:05
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskBackFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "任务ID不能为空")
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 目标节点ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "targetKey", description = "目标节点ID")
|
||||||
|
private String targetKey;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务完成参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 13:57
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskCompleteFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "任务ID不能为空")
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 变量
|
||||||
|
*/
|
||||||
|
@Schema(name = "variables", description = "变量")
|
||||||
|
private Map<String, Object> variables;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一级任务参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 17:03
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskNextFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 节点Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskKey", description = "节点Key")
|
||||||
|
private String taskKey;
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/9 9:53
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskOutgoingFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 节点Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskKey", description = "节点Key")
|
||||||
|
private String taskKey;
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.fo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上一级任务参数类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/4/23 10:38
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskPrevFo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
private String deploymentId;
|
||||||
|
/**
|
||||||
|
* 节点Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskKey", description = "节点Key")
|
||||||
|
private String taskKey;
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义VO
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 14:26
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DefinitionVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 定义ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "id", description = "定义ID")
|
||||||
|
String definitionId;
|
||||||
|
/**
|
||||||
|
* 定义名称
|
||||||
|
*/
|
||||||
|
@Schema(name = "name", description = "定义名称")
|
||||||
|
String definitionName;
|
||||||
|
/**
|
||||||
|
* 定义Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "key", description = "定义Key")
|
||||||
|
String definitionKey;
|
||||||
|
/**
|
||||||
|
* 定义版本
|
||||||
|
*/
|
||||||
|
@Schema(name = "version", description = "定义版本")
|
||||||
|
Integer definitionVersion;
|
||||||
|
/**
|
||||||
|
* 定义部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "定义部署ID")
|
||||||
|
String deploymentId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义部署Vo
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 9:35
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeploymentVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 部署ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "deploymentId", description = "部署ID")
|
||||||
|
String deploymentId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/6/11 10:33
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FlowElementVo {
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 线的源
|
||||||
|
*/
|
||||||
|
private String sourceRef;
|
||||||
|
/**
|
||||||
|
* 线的目标
|
||||||
|
*/
|
||||||
|
private String targetRef;
|
||||||
|
/**
|
||||||
|
* 节点进线
|
||||||
|
*/
|
||||||
|
private List<String> incomingList;
|
||||||
|
/**
|
||||||
|
* 节点出线
|
||||||
|
*/
|
||||||
|
private List<String> outgoingList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/8/13 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FlowVo {
|
||||||
|
private String key;
|
||||||
|
private List<FlowVo> children = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 历史流程实例Vo
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 17:04
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class HistoricInstanceVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(name = "startTime", description = "开始时间")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
/**
|
||||||
|
* 结束时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(name = "endTime", description = "结束时间")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
/**
|
||||||
|
* 耗时
|
||||||
|
*/
|
||||||
|
@Schema(name = "durationInMillis", description = "耗时")
|
||||||
|
private Long durationInMillis;
|
||||||
|
/**
|
||||||
|
* 删除原因
|
||||||
|
*/
|
||||||
|
@Schema(name = "deleteReason", description = "删除原因")
|
||||||
|
private String deleteReason;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类的描述
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAASYUNZHUPAAS开发组
|
||||||
|
* @version 5.0.x
|
||||||
|
* @since 2024/6/17 16:06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class HistoricNodeVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 节点编码
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
private Long startTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例Vo
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 14:42
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InstanceVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 元素Vo
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 17:48
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NodeElementVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 元素ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "id", description = "元素ID")
|
||||||
|
private String id;
|
||||||
|
/**
|
||||||
|
* 元素名称
|
||||||
|
*/
|
||||||
|
@Schema(name = "name", description = "元素名称")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 进线ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "incoming", description = "进线ID")
|
||||||
|
private List<String> incomingList;
|
||||||
|
/**
|
||||||
|
* 出线ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "outgoingList", description = "出线ID")
|
||||||
|
private List<String> outgoingList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.model.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程任务VO
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 11:22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TaskVo implements Serializable {
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskId", description = "任务ID")
|
||||||
|
private String taskId;
|
||||||
|
/**
|
||||||
|
* 任务名称
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskName", description = "任务名称")
|
||||||
|
private String taskName;
|
||||||
|
/**
|
||||||
|
* 任务Key
|
||||||
|
*/
|
||||||
|
@Schema(name = "taskKey", description = "任务Key")
|
||||||
|
private String taskKey;
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
@Schema(name = "instanceId", description = "实例ID")
|
||||||
|
private String instanceId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.service;
|
||||||
|
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeleteFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeployFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.DefinitionVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.DeploymentVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.FlowElementVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义服务接口
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 11:36
|
||||||
|
*/
|
||||||
|
public interface IDefinitionService {
|
||||||
|
/**
|
||||||
|
* 部署流程定义
|
||||||
|
*
|
||||||
|
* @param fo {@link DefinitionDeployFo}
|
||||||
|
* @return {@link DeploymentVo}
|
||||||
|
* @since 2024/4/7 10:51
|
||||||
|
**/
|
||||||
|
DeploymentVo deployDefinition(DefinitionDeployFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表查询流程定义
|
||||||
|
*
|
||||||
|
* @return {@link List<DefinitionVo>}
|
||||||
|
* @since 2024/4/7 11:23
|
||||||
|
**/
|
||||||
|
List<DefinitionVo> listDefinition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除流程定义
|
||||||
|
*
|
||||||
|
* @param fo {@link DefinitionDeleteFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/7 13:51
|
||||||
|
**/
|
||||||
|
boolean deleteDefinition(DefinitionDeleteFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流程元素
|
||||||
|
*
|
||||||
|
* @param deploymentId 部署ID
|
||||||
|
*/
|
||||||
|
List<FlowElementVo> getStructure(String deploymentId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.service;
|
||||||
|
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.InstanceDeleteFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.InstanceStartFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.HistoricInstanceVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.InstanceVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例服务接口
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 14:31
|
||||||
|
*/
|
||||||
|
public interface IInstanceService {
|
||||||
|
/**
|
||||||
|
* 根据ID启动实例
|
||||||
|
*
|
||||||
|
* @param fo {@link InstanceStartFo}
|
||||||
|
* @return {@link InstanceVo}
|
||||||
|
* @since 2024/4/7 15:44
|
||||||
|
**/
|
||||||
|
InstanceVo startById(InstanceStartFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史流程实例
|
||||||
|
*
|
||||||
|
* @param processInstanceId {@link String}
|
||||||
|
* @return {@link HistoricInstanceVo}
|
||||||
|
* @since 2024/4/7 17:30
|
||||||
|
**/
|
||||||
|
HistoricInstanceVo getHistoricProcessInstance(String processInstanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除流程实例
|
||||||
|
*
|
||||||
|
* @param fo {@link InstanceDeleteFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/7 16:07
|
||||||
|
**/
|
||||||
|
boolean deleteInstance(InstanceDeleteFo fo);
|
||||||
|
}
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.service;
|
||||||
|
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.*;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.FlowVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.HistoricNodeVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.NodeElementVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.TaskVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程任务服务接口
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 11:11
|
||||||
|
*/
|
||||||
|
public interface ITaskService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据流程实例ID获取任务
|
||||||
|
*
|
||||||
|
* @param instanceId {@link String}
|
||||||
|
* @return {@link List<TaskVo>}
|
||||||
|
* @since 2024/4/8 14:15
|
||||||
|
**/
|
||||||
|
List<TaskVo> getTask(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 完成任务
|
||||||
|
*
|
||||||
|
* @param fo {@link TaskCompleteFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/8 14:21
|
||||||
|
**/
|
||||||
|
boolean complete(TaskCompleteFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单节点跳转多节点
|
||||||
|
*
|
||||||
|
* @param fo {@link MoveSingleToMultiFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/9 14:48
|
||||||
|
**/
|
||||||
|
boolean moveSingleToMulti(MoveSingleToMultiFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多节点跳转单节点
|
||||||
|
*
|
||||||
|
* @param fo {@link MoveMultiToSingleFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/9 14:48
|
||||||
|
**/
|
||||||
|
boolean moveMultiToSingle(MoveMultiToSingleFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点跳转
|
||||||
|
*
|
||||||
|
* @param fo {@link JumpFo}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/10 11:35
|
||||||
|
**/
|
||||||
|
boolean jump(JumpFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可回退的节点ID
|
||||||
|
*
|
||||||
|
* @param taskId {@link String}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/8 15:39
|
||||||
|
**/
|
||||||
|
List<String> getFallbacks(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退目标节点
|
||||||
|
*
|
||||||
|
* @param fo {@link TaskBackFo}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/8 16:11
|
||||||
|
**/
|
||||||
|
List<String> back(TaskBackFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上一级任务节点ID集合,用于自动处置的相邻选项
|
||||||
|
*
|
||||||
|
* @param fo {@link TaskPrevFo}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/8 16:30
|
||||||
|
**/
|
||||||
|
List<String> getPrevUserTask(TaskPrevFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下一级任务节点集合
|
||||||
|
*
|
||||||
|
* @param fo {@link TaskNextFo}
|
||||||
|
* @return {@link List< NodeElementVo >}
|
||||||
|
* @since 2024/4/9 9:20
|
||||||
|
**/
|
||||||
|
List<NodeElementVo> getNextUserTask(TaskNextFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线之后的任务节点
|
||||||
|
*
|
||||||
|
* @param fo {@link FlowTargetTaskFo}
|
||||||
|
* @return {@link String}
|
||||||
|
* @since 2024/4/17 17:45
|
||||||
|
**/
|
||||||
|
List<String> getTaskKeyAfterFlow(FlowTargetTaskFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤回
|
||||||
|
*
|
||||||
|
* @param taskId {@link String}
|
||||||
|
* @return {@link boolean}
|
||||||
|
* @since 2024/4/9 9:30
|
||||||
|
**/
|
||||||
|
boolean retract(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取出线Key集合(若出线的出口为网关,则一并获取网关的出线)
|
||||||
|
*
|
||||||
|
* @param fo {@link TaskOutgoingFo}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/9 10:54
|
||||||
|
**/
|
||||||
|
List<String> getOutgoingFlows(TaskOutgoingFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取出线
|
||||||
|
*
|
||||||
|
* @param fo 参数
|
||||||
|
*/
|
||||||
|
List<FlowVo> getOutgoing(TaskOutgoingFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完成的节点Key
|
||||||
|
*
|
||||||
|
* @param instanceId {@link String}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/9 13:51
|
||||||
|
**/
|
||||||
|
List<String> getKeysOfFinished(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进线的Key
|
||||||
|
*
|
||||||
|
* @param taskId {@link String}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/9 13:56
|
||||||
|
**/
|
||||||
|
List<String> getIncomingFlows(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取未经过的节点
|
||||||
|
*
|
||||||
|
* @param instanceId {@link String}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/29 10:01
|
||||||
|
**/
|
||||||
|
List<String> getToBePass(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的后续节点
|
||||||
|
*
|
||||||
|
* @param fo 参数
|
||||||
|
*/
|
||||||
|
List<String> getAfter(TaskAfterFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常补偿
|
||||||
|
*
|
||||||
|
* @param fo 参数
|
||||||
|
*/
|
||||||
|
List<TaskVo> compensate(CompensateFo fo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史节点
|
||||||
|
*
|
||||||
|
* @param instanceId 实例主键
|
||||||
|
*/
|
||||||
|
List<HistoricNodeVo> getHistoric(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史结束节点
|
||||||
|
*
|
||||||
|
* @param instanceId 实例主键
|
||||||
|
*/
|
||||||
|
List<String> getHistoricEnd(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取元素信息
|
||||||
|
*
|
||||||
|
* @param model 参数
|
||||||
|
*/
|
||||||
|
NodeElementVo getElementInfo(InfoModel model);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.yunzhupaas.workflow.common.util;
|
||||||
|
|
||||||
|
public class FlowUtil {
|
||||||
|
|
||||||
|
public static boolean isDM(String url) {
|
||||||
|
return url.startsWith("jdbc:dm");
|
||||||
|
}
|
||||||
|
}
|
||||||
31
yunzhupaas-workflow-flowable/pom.xml
Normal file
31
yunzhupaas-workflow-flowable/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-core</artifactId>
|
||||||
|
<version>1.0.0-RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>yunzhupaas-workflow-flowable</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flowable</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter</artifactId>
|
||||||
|
<version>${flowable.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunzhupaas</groupId>
|
||||||
|
<artifactId>yunzhupaas-workflow-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package com.yunzhupaas.workflow.flowable.cmd;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowNode;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.Command;
|
||||||
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.history.HistoricActivityInstance;
|
||||||
|
import org.flowable.engine.impl.HistoricActivityInstanceQueryImpl;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntity;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.engine.runtime.Execution;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
|
import org.flowable.task.service.HistoricTaskService;
|
||||||
|
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
|
||||||
|
import org.flowable.variable.service.VariableService;
|
||||||
|
import org.flowable.variable.service.impl.persistence.entity.VariableInstanceEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转命令类
|
||||||
|
* 参考:https://blog.csdn.net/zhsp419/article/details/114264451
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/9 17:45
|
||||||
|
*/
|
||||||
|
public class JumpCmd implements Command<Void> {
|
||||||
|
private final String processInstanceId;
|
||||||
|
|
||||||
|
private final List<String> sourceTaskDefIdList;
|
||||||
|
private final List<String> targetFlowNodeIdList;
|
||||||
|
|
||||||
|
private final String deleteReason;
|
||||||
|
|
||||||
|
private final BpmnModel bpmnModel;
|
||||||
|
private final RuntimeService runtimeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存撤回节点的变量map
|
||||||
|
*/
|
||||||
|
private final Map<String, List<VariableInstanceEntity>> varMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public JumpCmd(String processInstanceId, List<String> sourceTaskDefIdList, List<String> targetFlowNodeIdList,
|
||||||
|
String deleteReason, BpmnModel bpmnModel, RuntimeService runtimeService) {
|
||||||
|
this.processInstanceId = processInstanceId;
|
||||||
|
this.sourceTaskDefIdList = sourceTaskDefIdList;
|
||||||
|
this.deleteReason = deleteReason;
|
||||||
|
this.targetFlowNodeIdList = targetFlowNodeIdList;
|
||||||
|
this.bpmnModel = bpmnModel;
|
||||||
|
this.runtimeService = runtimeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(CommandContext commandContext) {
|
||||||
|
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||||
|
// 处理act_ru_execution
|
||||||
|
handleExecution(commandContext);
|
||||||
|
// 处理act_hi_actinst
|
||||||
|
handleActInst(commandContext);
|
||||||
|
|
||||||
|
targetFlowNodeIdList.forEach(targetId -> {
|
||||||
|
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(targetId);
|
||||||
|
// 创建子执行流,开启任务
|
||||||
|
ExecutionEntity processExecution = executionEntityManager.findById(processInstanceId);
|
||||||
|
ExecutionEntity childExecution = executionEntityManager.createChildExecution(processExecution);
|
||||||
|
childExecution.setCurrentFlowElement(flowNode);
|
||||||
|
|
||||||
|
// 设置执行变量
|
||||||
|
VariableService variableService = CommandContextUtil.getVariableService();
|
||||||
|
List<VariableInstanceEntity> variableInstanceEntities = varMap.get(flowNode.getId());
|
||||||
|
if (CollectionUtil.isNotEmpty(variableInstanceEntities)) {
|
||||||
|
variableInstanceEntities.forEach(var -> {
|
||||||
|
var.setExecutionId(childExecution.getId());
|
||||||
|
variableService.insertVariableInstance(var);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
executionEntityManager.insert(childExecution);
|
||||||
|
// 交给引擎流转
|
||||||
|
CommandContextUtil.getAgenda().planContinueProcessOperation(childExecution);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleActInst(CommandContext commandContext) {
|
||||||
|
for (String str : sourceTaskDefIdList) {
|
||||||
|
HistoricActivityInstanceQueryImpl query = new HistoricActivityInstanceQueryImpl()
|
||||||
|
.activityId(str).processInstanceId(processInstanceId).unfinished();
|
||||||
|
List<HistoricActivityInstance> activityInstances = CommandContextUtil
|
||||||
|
.getHistoricActivityInstanceEntityManager()
|
||||||
|
.findHistoricActivityInstancesByQueryCriteria(query);
|
||||||
|
for (HistoricActivityInstance activity : activityInstances) {
|
||||||
|
HistoricActivityInstanceEntity activityEntity = (HistoricActivityInstanceEntity) activity;
|
||||||
|
// 修改act_hi_actinst表
|
||||||
|
activityEntity.setDeleted(true);
|
||||||
|
activityEntity.setDeleteReason(deleteReason);
|
||||||
|
CommandContextUtil.getHistoricActivityInstanceEntityManager().update(activityEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleExecution(CommandContext commandContext) {
|
||||||
|
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
|
||||||
|
HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService();
|
||||||
|
VariableService variableService = CommandContextUtil.getVariableService();
|
||||||
|
for (String str : sourceTaskDefIdList) {
|
||||||
|
List<Execution> executionEntities = runtimeService.createExecutionQuery()
|
||||||
|
.processInstanceId(processInstanceId).activityId(str).list();
|
||||||
|
for (Execution parentExecution : executionEntities) {
|
||||||
|
// 关闭未完成的任务执行流
|
||||||
|
// 获取子级Executions,如子流程节点等需要处理
|
||||||
|
List<ExecutionEntity> childExecutions = executionEntityManager
|
||||||
|
.findChildExecutionsByParentExecutionId(parentExecution.getId());
|
||||||
|
for (ExecutionEntity childExecution : childExecutions) {
|
||||||
|
// 因为外键约束,首先要删除variable表中的execution相关数据
|
||||||
|
List<VariableInstanceEntity> variableInstances = variableService
|
||||||
|
.findVariableInstancesByExecutionId(childExecution.getId());
|
||||||
|
varMap.put(parentExecution.getActivityId(), variableInstances);
|
||||||
|
variableInstances.forEach(variableService::deleteVariableInstance);
|
||||||
|
executionEntityManager.deleteExecutionAndRelatedData(childExecution, deleteReason, false);
|
||||||
|
// 修改历史实例
|
||||||
|
HistoricTaskInstanceQueryImpl query = new HistoricTaskInstanceQueryImpl()
|
||||||
|
.executionId(childExecution.getId()).processInstanceId(processInstanceId);
|
||||||
|
List<HistoricTaskInstance> HistoricTaskInstances = historicTaskService
|
||||||
|
.findHistoricTaskInstancesByQueryCriteria(query);
|
||||||
|
if (CollectionUtil.isNotEmpty(HistoricTaskInstances)) {
|
||||||
|
for (HistoricTaskInstance HistoricTaskInstance : HistoricTaskInstances) {
|
||||||
|
HistoricTaskInstanceEntity entity = (HistoricTaskInstanceEntity) HistoricTaskInstance;
|
||||||
|
entity.setDeleteReason(deleteReason);
|
||||||
|
historicTaskService.updateHistoricTask(entity, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 父执行流关闭
|
||||||
|
List<VariableInstanceEntity> variableInstances = variableService
|
||||||
|
.findVariableInstancesByExecutionId(parentExecution.getId());
|
||||||
|
varMap.put(parentExecution.getActivityId(), variableInstances);
|
||||||
|
variableInstances.forEach(variableService::deleteVariableInstance);
|
||||||
|
ExecutionEntity parentExecution1 = (ExecutionEntity) parentExecution;
|
||||||
|
executionEntityManager.deleteExecutionAndRelatedData(parentExecution1, deleteReason, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package com.yunzhupaas.workflow.flowable.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeleteFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.DefinitionDeployFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.DefinitionVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.DeploymentVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.FlowElementVo;
|
||||||
|
import com.yunzhupaas.workflow.common.service.IDefinitionService;
|
||||||
|
import com.yunzhupaas.workflow.flowable.util.FlowableUtil;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
import org.flowable.engine.RepositoryService;
|
||||||
|
import org.flowable.engine.repository.Deployment;
|
||||||
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义实现层
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/3 11:36
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DefinitionServiceImpl implements IDefinitionService {
|
||||||
|
private final RepositoryService repositoryService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeploymentVo deployDefinition(DefinitionDeployFo fo) {
|
||||||
|
Deployment deployment;
|
||||||
|
try {
|
||||||
|
String resourceName;
|
||||||
|
if (StrUtil.isNotBlank(fo.getKey())) {
|
||||||
|
resourceName = fo.getKey();
|
||||||
|
} else {
|
||||||
|
resourceName = IdUtil.getSnowflakeNextIdStr();
|
||||||
|
}
|
||||||
|
deployment = repositoryService
|
||||||
|
.createDeployment()
|
||||||
|
.name(fo.getName())
|
||||||
|
.key(fo.getKey())
|
||||||
|
.addString(resourceName + ".bpmn20.xml", fo.getBpmnXml())
|
||||||
|
.disableSchemaValidation()
|
||||||
|
.deploy();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BizException(ResultCode.DEPLOY_ERROR.getMsg(), e);
|
||||||
|
}
|
||||||
|
DeploymentVo vo = new DeploymentVo();
|
||||||
|
vo.setDeploymentId(deployment.getId());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DefinitionVo> listDefinition() {
|
||||||
|
List<ProcessDefinition> definitions = repositoryService.createProcessDefinitionQuery().list();
|
||||||
|
List<DefinitionVo> list = new ArrayList<>();
|
||||||
|
if (CollectionUtil.isNotEmpty(definitions)) {
|
||||||
|
for (ProcessDefinition definition : definitions) {
|
||||||
|
DefinitionVo vo = new DefinitionVo();
|
||||||
|
vo.setDefinitionId(definition.getId());
|
||||||
|
vo.setDefinitionName(definition.getName());
|
||||||
|
vo.setDefinitionKey(definition.getKey());
|
||||||
|
vo.setDefinitionVersion(definition.getVersion());
|
||||||
|
vo.setDeploymentId(definition.getDeploymentId());
|
||||||
|
list.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteDefinition(DefinitionDeleteFo fo) {
|
||||||
|
if (null == fo.getCascade()) {
|
||||||
|
fo.setCascade(true);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 根据部署ID删除,并级联删除当前流程定义下的所有流程实例、job
|
||||||
|
repositoryService.deleteDeployment(fo.getDeploymentId(), fo.getCascade());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.DELETE_FAILURE.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowElementVo> getStructure(String deploymentId) {
|
||||||
|
List<FlowElementVo> vos = new ArrayList<>();
|
||||||
|
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||||
|
.singleResult();
|
||||||
|
if (null != definition) {
|
||||||
|
Process process = repositoryService.getBpmnModel(definition.getId()).getProcesses().get(0);
|
||||||
|
Collection<FlowElement> elements = FlowableUtil.getAllElements(process.getFlowElements(), null);
|
||||||
|
for (FlowElement element : elements) {
|
||||||
|
FlowElementVo vo = BeanUtil.copyProperties(element, FlowElementVo.class);
|
||||||
|
if (element instanceof Event) {
|
||||||
|
Event el = (Event) element;
|
||||||
|
vo.setIncomingList(
|
||||||
|
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
vo.setOutgoingList(
|
||||||
|
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
if (element instanceof Activity) {
|
||||||
|
Activity el = (Activity) element;
|
||||||
|
vo.setIncomingList(
|
||||||
|
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
vo.setOutgoingList(
|
||||||
|
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
if (element instanceof Gateway) {
|
||||||
|
Gateway el = (Gateway) element;
|
||||||
|
vo.setIncomingList(
|
||||||
|
el.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
vo.setOutgoingList(
|
||||||
|
el.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
vos.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vos;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package com.yunzhupaas.workflow.flowable.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.InstanceDeleteFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.InstanceStartFo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.HistoricInstanceVo;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.InstanceVo;
|
||||||
|
import com.yunzhupaas.workflow.common.service.IInstanceService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.engine.HistoryService;
|
||||||
|
import org.flowable.engine.RepositoryService;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
|
import org.flowable.engine.history.HistoricProcessInstance;
|
||||||
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例实现层
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/7 14:34
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class InstanceServiceImpl implements IInstanceService {
|
||||||
|
private final RepositoryService repositoryService;
|
||||||
|
private final RuntimeService runtimeService;
|
||||||
|
private final HistoryService historyService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InstanceVo startById(InstanceStartFo fo) {
|
||||||
|
ProcessDefinition definition = repositoryService
|
||||||
|
.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
InstanceVo vo = new InstanceVo();
|
||||||
|
ProcessInstance instance;
|
||||||
|
if (CollectionUtil.isNotEmpty(fo.getVariables())) {
|
||||||
|
instance = runtimeService.startProcessInstanceById(definition.getId(), fo.getVariables());
|
||||||
|
} else {
|
||||||
|
instance = runtimeService.startProcessInstanceById(definition.getId());
|
||||||
|
}
|
||||||
|
if (null != instance) {
|
||||||
|
vo.setInstanceId(instance.getId());
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HistoricInstanceVo getHistoricProcessInstance(String processInstanceId) {
|
||||||
|
HistoricProcessInstance historicInstance = historyService
|
||||||
|
.createHistoricProcessInstanceQuery()
|
||||||
|
.processInstanceId(processInstanceId)
|
||||||
|
.singleResult();
|
||||||
|
if (null == historicInstance) {
|
||||||
|
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
HistoricInstanceVo vo = new HistoricInstanceVo();
|
||||||
|
vo.setInstanceId(historicInstance.getId());
|
||||||
|
vo.setStartTime(historicInstance.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||||
|
vo.setEndTime(historicInstance.getEndTime() == null ? null
|
||||||
|
: historicInstance.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
|
||||||
|
vo.setDurationInMillis(historicInstance.getDurationInMillis());
|
||||||
|
vo.setDeleteReason(historicInstance.getDeleteReason());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteInstance(InstanceDeleteFo fo) {
|
||||||
|
try {
|
||||||
|
runtimeService.deleteProcessInstance(fo.getInstanceId(), fo.getDeleteReason());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.DELETE_FAILURE.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,619 @@
|
|||||||
|
package com.yunzhupaas.workflow.flowable.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.BizException;
|
||||||
|
import com.yunzhupaas.workflow.common.exception.ResultCode;
|
||||||
|
import com.yunzhupaas.workflow.common.model.fo.*;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.*;
|
||||||
|
import com.yunzhupaas.workflow.common.service.IInstanceService;
|
||||||
|
import com.yunzhupaas.workflow.common.service.ITaskService;
|
||||||
|
import com.yunzhupaas.workflow.flowable.cmd.JumpCmd;
|
||||||
|
import com.yunzhupaas.workflow.flowable.util.FlowableUtil;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
import org.flowable.engine.*;
|
||||||
|
import org.flowable.engine.history.HistoricActivityInstance;
|
||||||
|
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.flowable.task.api.TaskInfo;
|
||||||
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
|
import org.flowable.variable.api.history.HistoricVariableInstance;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程任务实现层
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 11:12
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TaskServiceImpl implements ITaskService {
|
||||||
|
private final TaskService taskService;
|
||||||
|
private final HistoryService historyService;
|
||||||
|
private final RuntimeService runtimeService;
|
||||||
|
private final RepositoryService repositoryService;
|
||||||
|
private final ManagementService managementService;
|
||||||
|
private final IInstanceService instanceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TaskVo> getTask(String instanceId) {
|
||||||
|
List<Task> list = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||||
|
List<TaskVo> vos = new ArrayList<>();
|
||||||
|
if (CollectionUtil.isNotEmpty(list)) {
|
||||||
|
for (Task task : list) {
|
||||||
|
TaskVo vo = new TaskVo();
|
||||||
|
vo.setTaskId(task.getId());
|
||||||
|
vo.setTaskName(task.getName());
|
||||||
|
vo.setTaskKey(task.getTaskDefinitionKey());
|
||||||
|
vo.setInstanceId(task.getProcessInstanceId());
|
||||||
|
vos.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(TaskCompleteFo fo) {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (CollectionUtil.isNotEmpty(fo.getVariables())) {
|
||||||
|
taskService.complete(fo.getTaskId(), fo.getVariables());
|
||||||
|
} else {
|
||||||
|
taskService.complete(fo.getTaskId());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.TASK_COMPLETE_ERROR.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean moveSingleToMulti(MoveSingleToMultiFo fo) {
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||||
|
.singleResult();
|
||||||
|
if (null == instance) {
|
||||||
|
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.moveSingleActivityIdToActivityIds(fo.getInstanceId(), fo.getSourceKey(), fo.getTargetKeys());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点跳转
|
||||||
|
* Set the activity id that should be changed to multiple activity ids
|
||||||
|
*/
|
||||||
|
public void moveSingleActivityIdToActivityIds(String processInstanceId, String activityId,
|
||||||
|
List<String> activityIds) {
|
||||||
|
runtimeService.createChangeActivityStateBuilder()
|
||||||
|
.processInstanceId(processInstanceId)
|
||||||
|
.moveSingleActivityIdToActivityIds(activityId, activityIds).changeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean moveMultiToSingle(MoveMultiToSingleFo fo) {
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||||
|
.singleResult();
|
||||||
|
if (null == instance) {
|
||||||
|
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.moveActivityIdsToSingleActivityId(fo.getInstanceId(), fo.getSourceKeys(), fo.getTargetKey());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点跳转
|
||||||
|
* Set the activity ids that should be changed to a single activity id
|
||||||
|
*/
|
||||||
|
public void moveActivityIdsToSingleActivityId(String processInstanceId, List<String> activityIds,
|
||||||
|
String activityId) {
|
||||||
|
runtimeService.createChangeActivityStateBuilder()
|
||||||
|
.processInstanceId(processInstanceId)
|
||||||
|
.moveActivityIdsToSingleActivityId(activityIds, activityId).changeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean jump(JumpFo fo) {
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(fo.getInstanceId())
|
||||||
|
.singleResult();
|
||||||
|
if (null == instance) {
|
||||||
|
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
|
||||||
|
JumpCmd jumpCmd = new JumpCmd(fo.getInstanceId(), fo.getSource(), fo.getTarget(), "custom jump", bpmnModel,
|
||||||
|
runtimeService);
|
||||||
|
managementService.executeCommand(jumpCmd);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(ResultCode.TASK_JUMP_ERROR.getMsg(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFallbacks(String taskId) {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||||
|
List<String> list = FlowableUtil.getPassActs(source, null, null);
|
||||||
|
return list.stream().distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据流程定义ID和任务KEY 获取节点元素
|
||||||
|
*/
|
||||||
|
public FlowElement getFlowElement(String processDefinitionId, String taskDefinitionKey) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.processDefinitionId(processDefinitionId).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
Process process = repositoryService.getBpmnModel(definition.getId()).getProcesses().get(0);
|
||||||
|
Collection<FlowElement> elements = FlowableUtil.getAllElements(process.getFlowElements(), null);
|
||||||
|
FlowElement source = null;
|
||||||
|
if (null != elements && !elements.isEmpty()) {
|
||||||
|
for (FlowElement element : elements) {
|
||||||
|
if (element.getId().equals(taskDefinitionKey)) {
|
||||||
|
source = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> back(TaskBackFo fo) {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||||
|
String definitionId;
|
||||||
|
String instanceId;
|
||||||
|
if (null == task) {
|
||||||
|
HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery().taskId(fo.getTaskId())
|
||||||
|
.singleResult();
|
||||||
|
definitionId = historicTask.getProcessDefinitionId();
|
||||||
|
instanceId = historicTask.getProcessInstanceId();
|
||||||
|
} else {
|
||||||
|
definitionId = task.getProcessDefinitionId();
|
||||||
|
instanceId = task.getProcessInstanceId();
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(fo.getTargetKey())) {
|
||||||
|
String[] split = fo.getTargetKey().split(",");
|
||||||
|
if (split.length == 0) {
|
||||||
|
throw new BizException("目标节点编码不能为空");
|
||||||
|
}
|
||||||
|
List<String> list = Arrays.asList(split);
|
||||||
|
return this.back(definitionId, instanceId, list);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> back(String definitionId, String instanceId, List<String> targetList) {
|
||||||
|
List<String> currentIds = new ArrayList<>();
|
||||||
|
for (String targetKey : targetList) {
|
||||||
|
FlowElement target = getFlowElement(definitionId, targetKey);
|
||||||
|
// 获取所有正常进行的任务节点Key,用于找出需要撤回的任务
|
||||||
|
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||||
|
List<String> runTaskKeyList = runTaskList.stream().map(Task::getTaskDefinitionKey)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// 需驳回的任务列表
|
||||||
|
List<UserTask> userTaskList = FlowableUtil.getChildUserTasks(target, runTaskKeyList, null, null);
|
||||||
|
List<String> collect = userTaskList.stream().map(UserTask::getId).collect(Collectors.toList());
|
||||||
|
currentIds.addAll(collect);
|
||||||
|
}
|
||||||
|
currentIds = currentIds.stream().distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
JumpFo jumpFo = new JumpFo();
|
||||||
|
jumpFo.setInstanceId(instanceId);
|
||||||
|
jumpFo.setSource(currentIds);
|
||||||
|
jumpFo.setTarget(targetList);
|
||||||
|
this.jump(jumpFo);
|
||||||
|
|
||||||
|
return currentIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getPrevUserTask(TaskPrevFo fo) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
// 获取当前节点
|
||||||
|
FlowElement source = getFlowElement(definition.getId(), fo.getTaskKey());
|
||||||
|
// 获取下一级用户任务
|
||||||
|
list = FlowableUtil.getParentActs(source, null, null);
|
||||||
|
} else {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||||
|
list = FlowableUtil.getParentActs(source, null, null);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NodeElementVo> getNextUserTask(TaskNextFo fo) {
|
||||||
|
List<UserTask> nextUserTasks = new ArrayList<>();
|
||||||
|
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
// 获取当前节点
|
||||||
|
FlowElement source = getFlowElement(definition.getId(), fo.getTaskKey());
|
||||||
|
// 获取下一级用户任务
|
||||||
|
nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||||
|
} else {
|
||||||
|
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(fo.getTaskId())
|
||||||
|
.singleResult();
|
||||||
|
if (null == taskInst) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||||
|
// 获取下一级用户任务
|
||||||
|
nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||||
|
}
|
||||||
|
List<NodeElementVo> vos = new ArrayList<>();
|
||||||
|
if (CollectionUtil.isNotEmpty(nextUserTasks)) {
|
||||||
|
for (UserTask task : nextUserTasks) {
|
||||||
|
NodeElementVo vo = new NodeElementVo();
|
||||||
|
vo.setId(task.getId());
|
||||||
|
vo.setName(task.getName());
|
||||||
|
vo.setIncomingList(
|
||||||
|
task.getIncomingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
vo.setOutgoingList(
|
||||||
|
task.getOutgoingFlows().stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
vos.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTaskKeyAfterFlow(FlowTargetTaskFo fo) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
// 获取当前节点
|
||||||
|
FlowElement source = getFlowElement(definition.getId(), fo.getFlowKey());
|
||||||
|
String taskKey = FlowableUtil.getTaskKeyAfterFlow(source);
|
||||||
|
list.add(taskKey);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retract(String taskId) {
|
||||||
|
// 需要撤回的任务实例
|
||||||
|
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
|
||||||
|
if (null != taskInst) {
|
||||||
|
ProcessInstance procInst = runtimeService.createProcessInstanceQuery()
|
||||||
|
.processInstanceId(taskInst.getProcessInstanceId())
|
||||||
|
.active().singleResult();
|
||||||
|
if (null != procInst) {
|
||||||
|
// 获取当前节点
|
||||||
|
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||||
|
// 获取下一级用户任务
|
||||||
|
List<UserTask> nextUserTasks = FlowableUtil.getNextUserTasks(source, null, null);
|
||||||
|
List<String> nextUserTaskKeys = nextUserTasks.stream().map(UserTask::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// 获取所有运行的任务节点,找到需要撤回的任务
|
||||||
|
List<Task> activateTasks = taskService.createTaskQuery()
|
||||||
|
.processInstanceId(taskInst.getProcessInstanceId()).list();
|
||||||
|
List<String> currentIds = new ArrayList<>();
|
||||||
|
for (Task task : activateTasks) {
|
||||||
|
// 检查激活的任务节点是否存在下一级中,如果存在,则加入到需要撤回的节点
|
||||||
|
if (CollUtil.contains(nextUserTaskKeys, task.getTaskDefinitionKey())) {
|
||||||
|
currentIds.add(task.getTaskDefinitionKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.moveActivityIdsToSingleActivityId(taskInst.getProcessInstanceId(), currentIds,
|
||||||
|
taskInst.getTaskDefinitionKey());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getOutgoingFlows(TaskOutgoingFo fo) {
|
||||||
|
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
return this.getOutgoingFlows(definition.getId(), fo.getTaskKey());
|
||||||
|
} else {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
return this.getOutgoingFlows(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取出线Key集合(若出线的出口为网关,则一并获取网关的出线)
|
||||||
|
*/
|
||||||
|
public List<String> getOutgoingFlows(String processDefinitionId, String taskDefinitionKey) {
|
||||||
|
FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey);
|
||||||
|
List<SequenceFlow> flows = new ArrayList<>();
|
||||||
|
flows = FlowableUtil.getOutFlowsWithGateway(source, flows);
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
if (!flows.isEmpty()) {
|
||||||
|
for (SequenceFlow flow : flows) {
|
||||||
|
list.add(flow.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list.stream().distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowVo> getOutgoing(TaskOutgoingFo fo) {
|
||||||
|
if (StrUtil.isNotBlank(fo.getDeploymentId())) {
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
|
||||||
|
.deploymentId(fo.getDeploymentId()).singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
return this.getOutgoing(definition.getId(), fo.getTaskKey());
|
||||||
|
} else {
|
||||||
|
Task task = taskService.createTaskQuery().taskId(fo.getTaskId()).singleResult();
|
||||||
|
if (null == task) {
|
||||||
|
throw new BizException(ResultCode.TASK_NOT_EXIST);
|
||||||
|
}
|
||||||
|
return this.getOutgoing(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FlowVo> getOutgoing(String processDefinitionId, String taskDefinitionKey) {
|
||||||
|
FlowElement source = getFlowElement(processDefinitionId, taskDefinitionKey);
|
||||||
|
return FlowableUtil.getOutFlows(source, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getKeysOfFinished(String instanceId) {
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId)
|
||||||
|
.singleResult();
|
||||||
|
if (null == instance) {
|
||||||
|
throw new BizException(ResultCode.INSTANCE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
// 获取当前节点之前的节点
|
||||||
|
List<String> keysOfBefore = getKeysOfBefore(instance);
|
||||||
|
// 获取流程实例下完成的历史活动
|
||||||
|
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
|
||||||
|
.processInstanceId(instanceId).finished().list();
|
||||||
|
if (CollectionUtil.isNotEmpty(list)) {
|
||||||
|
// 去除线,并去重
|
||||||
|
List<String> keysOfFinished = list.stream()
|
||||||
|
.filter(e -> !BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW.equals(e.getActivityType()))
|
||||||
|
.sorted(Comparator.comparing(HistoricActivityInstance::getStartTime))
|
||||||
|
.map(HistoricActivityInstance::getActivityId)
|
||||||
|
.distinct().collect(Collectors.toList());
|
||||||
|
if (CollectionUtil.isNotEmpty(keysOfBefore)) {
|
||||||
|
keysOfFinished.retainAll(keysOfBefore);
|
||||||
|
}
|
||||||
|
return keysOfFinished;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历当前节点,获取之前的节点
|
||||||
|
*/
|
||||||
|
public List<String> getKeysOfBefore(ProcessInstance instance) {
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
// 获取实例下的当前任务
|
||||||
|
List<Task> taskList = taskService.createTaskQuery().processInstanceId(instance.getId()).list();
|
||||||
|
if (CollectionUtil.isNotEmpty(taskList)) {
|
||||||
|
List<String> keys = taskList.stream().map(TaskInfo::getTaskDefinitionKey).collect(Collectors.toList());
|
||||||
|
for (String key : keys) {
|
||||||
|
FlowElement source = getFlowElement(instance.getProcessDefinitionId(), key);
|
||||||
|
List<String> list = FlowableUtil.getBefore(source, null, null);
|
||||||
|
res.addAll(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.stream().distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getIncomingFlows(String taskId) {
|
||||||
|
HistoricTaskInstance taskInst = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
|
||||||
|
if (null != taskInst) {
|
||||||
|
FlowElement source = getFlowElement(taskInst.getProcessDefinitionId(), taskInst.getTaskDefinitionKey());
|
||||||
|
List<SequenceFlow> flows = FlowableUtil.getElementIncomingFlows(source);
|
||||||
|
return flows.stream().map(BaseElement::getId).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取未经过的节点
|
||||||
|
@Override
|
||||||
|
public List<String> getToBePass(String instanceId) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
List<Task> currentList = taskService.createTaskQuery().processInstanceId(instanceId).list();
|
||||||
|
if (CollectionUtil.isNotEmpty(currentList)) {
|
||||||
|
List<String> collect = currentList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList());
|
||||||
|
// 根据当前的节点 递归后续的所有节点
|
||||||
|
for (Task task : currentList) {
|
||||||
|
FlowElement source = getFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
|
||||||
|
List<String> after = FlowableUtil.getAfter(source, null, null);
|
||||||
|
list.addAll(after);
|
||||||
|
}
|
||||||
|
list = list.stream().filter(e -> !collect.contains(e)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return list.stream().distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAfter(TaskAfterFo fo) {
|
||||||
|
String deploymentId = fo.getDeploymentId();
|
||||||
|
List<String> taskKeys = fo.getTaskKeys();
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||||
|
.singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
for (String taskKey : taskKeys) {
|
||||||
|
FlowElement source = getFlowElement(definition.getId(), taskKey);
|
||||||
|
List<String> after = FlowableUtil.getAfter(source, null, null);
|
||||||
|
list.addAll(after);
|
||||||
|
}
|
||||||
|
return list.stream().distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// complete 异常 补偿
|
||||||
|
@Override
|
||||||
|
public List<TaskVo> compensate(CompensateFo fo) {
|
||||||
|
String instanceId = fo.getInstanceId();
|
||||||
|
ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId)
|
||||||
|
.singleResult();
|
||||||
|
if (null == instance) {
|
||||||
|
HistoricProcessInstance historicInstance = historyService.createHistoricProcessInstanceQuery()
|
||||||
|
.processInstanceId(instanceId).singleResult();
|
||||||
|
Map<String, Object> variables = new HashMap<>();
|
||||||
|
List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery()
|
||||||
|
.processInstanceId(instanceId).list();
|
||||||
|
for (HistoricVariableInstance var : list) {
|
||||||
|
variables.put(var.getVariableName(), var.getValue());
|
||||||
|
}
|
||||||
|
String deploymentId = historicInstance.getDeploymentId();
|
||||||
|
|
||||||
|
InstanceStartFo startFo = new InstanceStartFo();
|
||||||
|
startFo.setDeploymentId(deploymentId);
|
||||||
|
startFo.setVariables(variables);
|
||||||
|
InstanceVo instanceVo = instanceService.startById(startFo);
|
||||||
|
instanceId = instanceVo.getInstanceId();
|
||||||
|
}
|
||||||
|
List<String> sourceList = fo.getSource().stream().sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<TaskVo> taskVoList = this.getTask(instanceId);
|
||||||
|
List<String> currentList = taskVoList.stream().map(TaskVo::getTaskKey).sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
|
// if (ObjectUtil.equals(sourceList, currentList)) {
|
||||||
|
// return null == instance ? taskVoList : new ArrayList<>();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 获取需要跳转的节点集合、目标节点集合
|
||||||
|
List<String> createList = sourceList.stream().filter(e -> !currentList.contains(e))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<String> deleteList = currentList.stream().filter(e -> !sourceList.contains(e))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
JumpFo jumpFo = new JumpFo();
|
||||||
|
jumpFo.setInstanceId(instanceId);
|
||||||
|
jumpFo.setSource(deleteList);
|
||||||
|
jumpFo.setTarget(createList);
|
||||||
|
this.jump(jumpFo);
|
||||||
|
|
||||||
|
List<TaskVo> vos = this.getTask(instanceId);
|
||||||
|
if (null != instance) {
|
||||||
|
vos.forEach(e -> e.setInstanceId(null));
|
||||||
|
}
|
||||||
|
return vos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HistoricNodeVo> getHistoric(String instanceId) {
|
||||||
|
List<HistoricNodeVo> vos;
|
||||||
|
|
||||||
|
Set<String> set = new HashSet<>();
|
||||||
|
set.add("userTask");
|
||||||
|
set.add("startEvent");
|
||||||
|
|
||||||
|
vos = this.getHistoricVos(instanceId, set);
|
||||||
|
|
||||||
|
return vos.stream().sorted(Comparator.comparing(HistoricNodeVo::getStartTime)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取历史结束节点
|
||||||
|
@Override
|
||||||
|
public List<String> getHistoricEnd(String instanceId) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
List<HistoricNodeVo> vos = this.getHistoricVos(instanceId, null);
|
||||||
|
if (CollectionUtil.isNotEmpty(vos)) {
|
||||||
|
list = vos.stream().map(HistoricNodeVo::getCode).distinct().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HistoricNodeVo> getHistoricVos(String instanceId, Set<String> set) {
|
||||||
|
List<HistoricNodeVo> vos = new ArrayList<>();
|
||||||
|
if (CollectionUtil.isEmpty(set)) {
|
||||||
|
set = new HashSet<>();
|
||||||
|
set.add("endEvent");
|
||||||
|
}
|
||||||
|
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
|
||||||
|
.activityTypes(set)
|
||||||
|
.processInstanceId(instanceId).list();
|
||||||
|
if (CollectionUtil.isNotEmpty(list)) {
|
||||||
|
for (HistoricActivityInstance act : list) {
|
||||||
|
HistoricNodeVo vo = new HistoricNodeVo();
|
||||||
|
vo.setCode(act.getActivityId());
|
||||||
|
vo.setTaskId(act.getTaskId());
|
||||||
|
vo.setStartTime(act.getStartTime().getTime());
|
||||||
|
vos.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeElementVo getElementInfo(InfoModel model) {
|
||||||
|
String deploymentId = model.getDeploymentId();
|
||||||
|
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId)
|
||||||
|
.singleResult();
|
||||||
|
if (null == definition) {
|
||||||
|
throw new BizException(ResultCode.DEFINITION_NOT_EXIST);
|
||||||
|
}
|
||||||
|
String definitionId = definition.getId();
|
||||||
|
String key = model.getKey();
|
||||||
|
NodeElementVo vo = new NodeElementVo();
|
||||||
|
FlowElement source = getFlowElement(definitionId, key);
|
||||||
|
if (null != source) {
|
||||||
|
vo.setId(source.getId());
|
||||||
|
List<SequenceFlow> outgoingFlows = FlowableUtil.getElementOutgoingFlows(source);
|
||||||
|
vo.setOutgoingList(outgoingFlows.stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
List<SequenceFlow> incomingFlows = FlowableUtil.getElementIncomingFlows(source);
|
||||||
|
vo.setIncomingList(incomingFlows.stream().map(SequenceFlow::getId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
package com.yunzhupaas.workflow.flowable.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.yunzhupaas.workflow.common.model.vo.FlowVo;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flowable工具类
|
||||||
|
*
|
||||||
|
* @author YUNZHUPAAS FlowableYUNZHUPAAS开发组
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/8 11:06
|
||||||
|
*/
|
||||||
|
public class FlowableUtil {
|
||||||
|
/**
|
||||||
|
* 获取全部节点元素
|
||||||
|
*
|
||||||
|
* @param flowElements {@link Collection<FlowElement>}
|
||||||
|
* @param allElements {@link Collection<FlowElement>}
|
||||||
|
* @return {@link Collection<FlowElement>}
|
||||||
|
* @since 2024/4/8 11:07
|
||||||
|
**/
|
||||||
|
public static Collection<FlowElement> getAllElements(Collection<FlowElement> flowElements,
|
||||||
|
Collection<FlowElement> allElements) {
|
||||||
|
allElements = allElements == null ? new ArrayList<>() : allElements;
|
||||||
|
for (FlowElement flowElement : flowElements) {
|
||||||
|
allElements.add(flowElement);
|
||||||
|
if (flowElement instanceof SubProcess) {
|
||||||
|
// 获取子流程元素
|
||||||
|
allElements = getAllElements(((SubProcess) flowElement).getFlowElements(), allElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的入口连线
|
||||||
|
*
|
||||||
|
* @param element {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @since 2024/4/8 11:10
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getElementIncomingFlows(FlowElement element) {
|
||||||
|
List<SequenceFlow> flows = null;
|
||||||
|
if (element instanceof FlowNode) {
|
||||||
|
flows = ((FlowNode) element).getIncomingFlows();
|
||||||
|
}
|
||||||
|
return flows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的出口连线
|
||||||
|
*
|
||||||
|
* @param element {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @since 2024/4/8 11:10
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement element) {
|
||||||
|
List<SequenceFlow> flows = null;
|
||||||
|
if (element instanceof FlowNode) {
|
||||||
|
flows = ((FlowNode) element).getOutgoingFlows();
|
||||||
|
}
|
||||||
|
return flows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可回退的节点(仅用户任务)
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param passActs {@link List<String>}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/8 15:27
|
||||||
|
**/
|
||||||
|
public static List<String> getPassActs(FlowElement source, Set<String> passFlows, List<String> passActs) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
passActs = passActs == null ? new ArrayList<>() : passActs;
|
||||||
|
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加经过的用户任务
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||||
|
passActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
}
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||||
|
passActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getPassActs(sequenceFlow.getSourceFlowElement(), passFlows, passActs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passActs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要撤回的节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param runTaskKeyList {@link List<String>}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param userTasks {@link List<UserTask>}
|
||||||
|
* @return {@link List<UserTask>}
|
||||||
|
* @since 2024/4/8 15:42
|
||||||
|
**/
|
||||||
|
public static List<UserTask> getChildUserTasks(FlowElement source, List<String> runTaskKeyList,
|
||||||
|
Set<String> passFlows, List<UserTask> userTasks) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
userTasks = userTasks == null ? new ArrayList<>() : userTasks;
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 用户任务
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof UserTask
|
||||||
|
&& runTaskKeyList.contains(sequenceFlow.getTargetFlowElement().getId())) {
|
||||||
|
userTasks.add((UserTask) sequenceFlow.getTargetFlowElement());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 子流程,从第一个节点开始获取
|
||||||
|
if (sequenceFlow.getTargetFlowElement() instanceof SubProcess) {
|
||||||
|
FlowElement flowElement = (FlowElement) ((SubProcess) sequenceFlow.getTargetFlowElement())
|
||||||
|
.getFlowElements().toArray()[0];
|
||||||
|
List<UserTask> tasks = getChildUserTasks(flowElement, runTaskKeyList, passFlows, null);
|
||||||
|
// 找到用户任务,不继续向下找
|
||||||
|
if (!tasks.isEmpty()) {
|
||||||
|
userTasks.addAll(tasks);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getChildUserTasks(sequenceFlow.getTargetFlowElement(), runTaskKeyList, passFlows, userTasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上一级节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param parentActs {@link List<String>}
|
||||||
|
* @return {@link List<Activity>}
|
||||||
|
* @since 2024/4/8 15:53
|
||||||
|
**/
|
||||||
|
public static List<String> getParentActs(FlowElement source, Set<String> passFlows, List<String> parentActs) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
parentActs = parentActs == null ? new ArrayList<>() : parentActs;
|
||||||
|
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加用户任务、子流程
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof UserTask) {
|
||||||
|
parentActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||||
|
parentActs.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getParentActs(sequenceFlow.getSourceFlowElement(), passFlows, parentActs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parentActs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下一级的用户任务
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param hasSequenceFlow {@link Set<String>}
|
||||||
|
* @param userTaskList {@link List<UserTask>}
|
||||||
|
* @return {@link List<UserTask>}
|
||||||
|
* @since 2024/4/8 16:34
|
||||||
|
**/
|
||||||
|
public static List<UserTask> getNextUserTasks(FlowElement source, Set<String> hasSequenceFlow,
|
||||||
|
List<UserTask> userTaskList) {
|
||||||
|
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
|
||||||
|
userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof UserTask) {
|
||||||
|
// 若节点为用户任务,加入到结果列表中
|
||||||
|
userTaskList.add((UserTask) targetFlowElement);
|
||||||
|
} else {
|
||||||
|
// 若节点非用户任务,继续递归查找下一个节点
|
||||||
|
getNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取元素之后的所有节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param hasSequenceFlow {@link Set<String>}
|
||||||
|
* @param list {@link List<String>}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/29 16:00
|
||||||
|
**/
|
||||||
|
public static List<String> getAfter(FlowElement source, Set<String> hasSequenceFlow, List<String> list) {
|
||||||
|
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
|
||||||
|
list = Optional.ofNullable(list).orElse(new ArrayList<>());
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 如果发现连线重复,说明循环了,跳过这个循环
|
||||||
|
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加已经走过的连线
|
||||||
|
hasSequenceFlow.add(sequenceFlow.getId());
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof UserTask) {
|
||||||
|
// 若节点为用户任务,加入到结果列表中
|
||||||
|
list.add(targetFlowElement.getId());
|
||||||
|
} else if (targetFlowElement instanceof EndEvent) {
|
||||||
|
list.add(targetFlowElement.getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 继续递归查找下一个节点
|
||||||
|
getAfter(targetFlowElement, hasSequenceFlow, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点的出口连线,若出线的出口是网关,则一并获取网关的出线
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @return {@link List<SequenceFlow>}
|
||||||
|
* @since 2024/4/9 9:58
|
||||||
|
**/
|
||||||
|
public static List<SequenceFlow> getOutFlowsWithGateway(FlowElement source, List<SequenceFlow> flows) {
|
||||||
|
flows = flows == null ? new ArrayList<>() : flows;
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
flows.add(sequenceFlow);
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof UserTask) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (targetFlowElement instanceof Gateway) {
|
||||||
|
Gateway gateway = (Gateway) targetFlowElement;
|
||||||
|
List<SequenceFlow> outgoingFlows = gateway.getOutgoingFlows();
|
||||||
|
flows.addAll(outgoingFlows);
|
||||||
|
getOutFlowsWithGateway(gateway, flows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取出线,上下级关系
|
||||||
|
*
|
||||||
|
* @param source 源
|
||||||
|
* @param flows 结果集合
|
||||||
|
*/
|
||||||
|
public static List<FlowVo> getOutFlows(FlowElement source, List<FlowVo> flows) {
|
||||||
|
flows = flows == null ? new ArrayList<>() : flows;
|
||||||
|
// 获取出口连线
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
|
||||||
|
if (null != sequenceFlows) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
FlowVo vo = new FlowVo();
|
||||||
|
vo.setKey(sequenceFlow.getId());
|
||||||
|
|
||||||
|
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (targetFlowElement instanceof Gateway) {
|
||||||
|
Gateway gateway = (Gateway) targetFlowElement;
|
||||||
|
List<FlowVo> list = getOutFlows(gateway, null);
|
||||||
|
vo.setChildren(list);
|
||||||
|
}
|
||||||
|
flows.add(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取之前的节点
|
||||||
|
*
|
||||||
|
* @param source {@link FlowElement}
|
||||||
|
* @param passFlows {@link Set<String>}
|
||||||
|
* @param keys {@link List<String>}
|
||||||
|
* @return {@link List<String>}
|
||||||
|
* @since 2024/4/9 11:51
|
||||||
|
**/
|
||||||
|
public static List<String> getBefore(FlowElement source, Set<String> passFlows, List<String> keys) {
|
||||||
|
passFlows = passFlows == null ? new HashSet<>() : passFlows;
|
||||||
|
keys = keys == null ? new ArrayList<>() : keys;
|
||||||
|
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
|
||||||
|
if (null != sequenceFlows && !sequenceFlows.isEmpty()) {
|
||||||
|
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
||||||
|
// 连线重复
|
||||||
|
if (passFlows.contains(sequenceFlow.getId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 添加经过的连线
|
||||||
|
passFlows.add(sequenceFlow.getId());
|
||||||
|
// 添加节点Key
|
||||||
|
keys.add(sequenceFlow.getSourceFlowElement().getId());
|
||||||
|
if (sequenceFlow.getSourceFlowElement() instanceof StartEvent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 迭代
|
||||||
|
getBefore(sequenceFlow.getSourceFlowElement(), passFlows, keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线之后的任务节点
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getTaskKeyAfterFlow(FlowElement source) {
|
||||||
|
if (source instanceof SequenceFlow) {
|
||||||
|
SequenceFlow sequenceFlow = (SequenceFlow) source;
|
||||||
|
FlowElement target = sequenceFlow.getTargetFlowElement();
|
||||||
|
if (target instanceof Gateway) {
|
||||||
|
List<SequenceFlow> outgoingFlows = ((Gateway) target).getOutgoingFlows();
|
||||||
|
if (CollectionUtil.isNotEmpty(outgoingFlows)) {
|
||||||
|
SequenceFlow flow = outgoingFlows.get(0);
|
||||||
|
return getTaskKeyAfterFlow(flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target instanceof UserTask) {
|
||||||
|
return target.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user