完成初始版本,实现基本的流程
This commit is contained in:
135
.gitignore
vendored
Normal file
135
.gitignore
vendored
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store### Maven template
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
# Eclipse m2e generated files
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
.idea/artifacts
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/*.iml
|
||||||
|
.idea/modules
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
10
.idea/.gitignore
generated
vendored
Normal file
10
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Zeppelin 忽略的文件
|
||||||
|
/ZeppelinRemoteNotebooks/
|
||||||
6
.idea/ApifoxUploaderProjectSetting.xml
generated
Normal file
6
.idea/ApifoxUploaderProjectSetting.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ApifoxUploaderProjectSetting">
|
||||||
|
<option name="apiAccessToken" value="APS-0ZZaS4q0gUiFOlbBJMN8hAmS7viQNi4D" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
28
.idea/codeStyles/Project.xml
generated
Normal file
28
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<JavaCodeStyleSettings>
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</JavaCodeStyleSettings>
|
||||||
|
<JetCodeStyleSettings>
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</JetCodeStyleSettings>
|
||||||
|
<ScalaCodeStyleSettings>
|
||||||
|
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
|
||||||
|
</ScalaCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="kotlin">
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="temurin-1.8" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
25
pom.xml
Normal file
25
pom.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?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.lanyuanxiaoyao</groupId>
|
||||||
|
<artifactId>flowable</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.34</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.example;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.example.node.LeaveRequestNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.example.node.ManagerApprovalNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.example.node.SimpleFlowNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.Flow;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowInstanceRepository;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowRepository;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.memory.MemoryFlowInstanceRepository;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.memory.MemoryFlowRepository;
|
||||||
|
import com.lanyuanxiaoyao.flowable.service.FlowService;
|
||||||
|
|
||||||
|
public class FlowExample {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 1. 初始化仓储和服务
|
||||||
|
FlowRepository flowRepository = new MemoryFlowRepository();
|
||||||
|
FlowInstanceRepository instanceRepository = new MemoryFlowInstanceRepository();
|
||||||
|
FlowService flowService = new FlowService(flowRepository, instanceRepository);
|
||||||
|
|
||||||
|
// 2. 创建请假审批流程
|
||||||
|
Flow leaveFlow = createLeaveFlow(flowService);
|
||||||
|
System.out.println("创建请假流程:" + leaveFlow.getName());
|
||||||
|
System.out.println("审批节点:" + leaveFlow.getNodes());
|
||||||
|
|
||||||
|
// 3. 创建报销审批流程
|
||||||
|
Flow expenseFlow = createExpenseFlow(flowService);
|
||||||
|
System.out.println("\n创建报销流程:" + expenseFlow.getName());
|
||||||
|
System.out.println("审批节点:" + expenseFlow.getNodes());
|
||||||
|
|
||||||
|
// 4. 演示请假审批流程
|
||||||
|
demonstrateLeaveFlow(flowService, leaveFlow.getId());
|
||||||
|
|
||||||
|
// 5. 演示报销审批流程(带拒绝场景)
|
||||||
|
demonstrateExpenseFlow(flowService, expenseFlow.getId());
|
||||||
|
|
||||||
|
// 演示带有自定义节点操作的请假流程
|
||||||
|
demonstrateLeaveFlowWithCustomNodes(flowService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flow createLeaveFlow(FlowService flowService) {
|
||||||
|
Flow flow = new Flow();
|
||||||
|
flow.setName("员工请假审批流程");
|
||||||
|
flow.setDescription("处理员工请假申请的标准流程");
|
||||||
|
flow.addNode(new SimpleFlowNode("直属主管审批"));
|
||||||
|
flow.addNode(new SimpleFlowNode("部门经理审批"));
|
||||||
|
flow.addNode(new SimpleFlowNode("人力资源审批"));
|
||||||
|
return flowService.createFlow(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Flow createExpenseFlow(FlowService flowService) {
|
||||||
|
Flow flow = new Flow();
|
||||||
|
flow.setName("费用报销审批流程");
|
||||||
|
flow.setDescription("处理员工报销申请的标准流程");
|
||||||
|
flow.addNode(new SimpleFlowNode("财务初审"));
|
||||||
|
flow.addNode(new SimpleFlowNode("部门经理审批"));
|
||||||
|
flow.addNode(new SimpleFlowNode("财务总监审批"));
|
||||||
|
flow.addNode(new SimpleFlowNode("出纳打款"));
|
||||||
|
return flowService.createFlow(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void demonstrateLeaveFlow(FlowService flowService, String flowId) {
|
||||||
|
System.out.println("\n=== 开始请假审批流程演示 ===");
|
||||||
|
|
||||||
|
// 启动流程实例
|
||||||
|
FlowInstance instance = flowService.startFlow(flowId);
|
||||||
|
System.out.println("启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 直属主管审批
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("直属主管审批通过,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 部门经理审批
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("部门经理审批通过,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 人力资源审批
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("人力资源审批通过,流程状态:" + instance.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void demonstrateExpenseFlow(FlowService flowService, String flowId) {
|
||||||
|
System.out.println("\n=== 开始报销审批流程演示(带拒绝场景)===");
|
||||||
|
|
||||||
|
// 启动流程实例
|
||||||
|
FlowInstance instance = flowService.startFlow(flowId);
|
||||||
|
System.out.println("启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 财务初审通过
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("财务初审通过,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 部门经理拒绝
|
||||||
|
instance = flowService.reject(instance.getId());
|
||||||
|
System.out.println("部门经理拒绝,流程状态:" + instance.getStatus());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 尝试继续审批(应该会失败)
|
||||||
|
flowService.approve(instance.getId());
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
System.out.println("尝试继续审批被拒绝:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void demonstrateLeaveFlowWithCustomNodes(FlowService flowService) {
|
||||||
|
System.out.println("\n=== 开始自定义节点请假流程演示 ===");
|
||||||
|
|
||||||
|
// 创建流程定义
|
||||||
|
Flow flow = new Flow();
|
||||||
|
flow.setName("带自定义操作的请假流程");
|
||||||
|
flow.setDescription("包含节点操作的请假流程示例");
|
||||||
|
|
||||||
|
// 添加自定义节点
|
||||||
|
flow.addNode(new LeaveRequestNode());
|
||||||
|
flow.addNode(new ManagerApprovalNode());
|
||||||
|
|
||||||
|
Flow savedFlow = flowService.createFlow(flow);
|
||||||
|
System.out.println("创建流程:" + savedFlow.getName());
|
||||||
|
|
||||||
|
// 演示通过流程
|
||||||
|
demonstrateApproveFlow(flowService, savedFlow.getId());
|
||||||
|
|
||||||
|
// 演示拒绝流程
|
||||||
|
demonstrateRejectFlow(flowService, savedFlow.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void demonstrateApproveFlow(FlowService flowService, String flowId) {
|
||||||
|
System.out.println("\n=== 演示通过流程 ===");
|
||||||
|
|
||||||
|
// 启动流程实例
|
||||||
|
FlowInstance instance = flowService.startFlow(flowId);
|
||||||
|
System.out.println("\n启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 请假申请通过
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("\n请假申请通过,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 经理审批通过
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("\n经理审批通过,流程状态:" + instance.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void demonstrateRejectFlow(FlowService flowService, String flowId) {
|
||||||
|
System.out.println("\n=== 演示拒绝流程 ===");
|
||||||
|
|
||||||
|
// 启动新的流程实例
|
||||||
|
FlowInstance instance = flowService.startFlow(flowId);
|
||||||
|
System.out.println("\n启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 请假申请通过
|
||||||
|
instance = flowService.approve(instance.getId());
|
||||||
|
System.out.println("\n请假申请通过,当前节点:" + instance.getCurrentNode());
|
||||||
|
|
||||||
|
// 经理审批拒绝
|
||||||
|
instance = flowService.reject(instance.getId());
|
||||||
|
System.out.println("\n经理审批拒绝,流程状态:" + instance.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.example.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.node.AbstractFlowNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class LeaveRequestNode extends AbstractFlowNode {
|
||||||
|
public LeaveRequestNode() {
|
||||||
|
super("请假申请");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(FlowContext context) {
|
||||||
|
// 模拟设置请假信息
|
||||||
|
context.setVariable("days", 3);
|
||||||
|
context.setVariable("reason", "年假");
|
||||||
|
context.setVariable("requestTime", LocalDateTime.now());
|
||||||
|
System.out.println("执行请假申请节点:设置请假天数为3天,请假理由为年假");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApprove(FlowContext context) {
|
||||||
|
System.out.println("请假申请提交成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReject(FlowContext context) {
|
||||||
|
System.out.println("请假申请被撤销");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.example.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.node.AbstractFlowNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class ManagerApprovalNode extends AbstractFlowNode {
|
||||||
|
public ManagerApprovalNode() {
|
||||||
|
super("经理审批");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(FlowContext context) {
|
||||||
|
Integer days = context.getVariable("days", Integer.class);
|
||||||
|
String reason = context.getVariable("reason", String.class);
|
||||||
|
LocalDateTime requestTime = context.getVariable("requestTime", LocalDateTime.class);
|
||||||
|
|
||||||
|
System.out.println("执行经理审批节点:");
|
||||||
|
System.out.println("- 请假天数:" + days);
|
||||||
|
System.out.println("- 请假理由:" + reason);
|
||||||
|
System.out.println("- 申请时间:" + requestTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApprove(FlowContext context) {
|
||||||
|
context.setVariable("approvalTime", LocalDateTime.now());
|
||||||
|
context.setVariable("managerComment", "同意");
|
||||||
|
System.out.println("经理已批准请假申请");
|
||||||
|
System.out.println("- 审批意见:同意");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReject(FlowContext context) {
|
||||||
|
context.setVariable("approvalTime", LocalDateTime.now());
|
||||||
|
context.setVariable("managerComment", "请假天数过长,建议调整后重新提交");
|
||||||
|
System.out.println("经理已拒绝请假申请");
|
||||||
|
System.out.println("- 拒绝原因:请假天数过长,建议调整后重新提交");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.example.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.node.AbstractFlowNode;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
|
||||||
|
public class SimpleFlowNode extends AbstractFlowNode {
|
||||||
|
public SimpleFlowNode(String nodeId) {
|
||||||
|
super(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(FlowContext context) {
|
||||||
|
System.out.println("执行节点:" + getNodeId());
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/main/java/com/lanyuanxiaoyao/flowable/model/Flow.java
Normal file
57
src/main/java/com/lanyuanxiaoyao/flowable/model/Flow.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.model;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.node.FlowNode;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程定义类
|
||||||
|
* 用于定义一个完整的审批流程,包含流程的基本信息和所有审批节点
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Flow {
|
||||||
|
/**
|
||||||
|
* 流程定义ID
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程节点列表
|
||||||
|
* 按照列表顺序依次执行,每个节点都是一个可执行的审批操作
|
||||||
|
*/
|
||||||
|
private List<FlowNode> nodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后更新时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
public Flow() {
|
||||||
|
this.nodes = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个新的流程节点
|
||||||
|
* @param node 要添加的流程节点
|
||||||
|
*/
|
||||||
|
public void addNode(FlowNode node) {
|
||||||
|
nodes.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程上下文类
|
||||||
|
* 用于在流程节点执行过程中传递和存储数据
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FlowContext {
|
||||||
|
/**
|
||||||
|
* 对应的流程定义ID
|
||||||
|
*/
|
||||||
|
private String flowId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应的流程实例ID
|
||||||
|
*/
|
||||||
|
private String instanceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文变量存储
|
||||||
|
* 用于在节点间传递数据
|
||||||
|
*/
|
||||||
|
private Map<String, Object> variables;
|
||||||
|
|
||||||
|
public FlowContext() {
|
||||||
|
this.variables = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置上下文变量
|
||||||
|
* @param key 变量名
|
||||||
|
* @param value 变量值
|
||||||
|
*/
|
||||||
|
public void setVariable(String key, Object value) {
|
||||||
|
variables.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上下文变量
|
||||||
|
* @param key 变量名
|
||||||
|
* @return 变量值
|
||||||
|
*/
|
||||||
|
public Object getVariable(String key) {
|
||||||
|
return variables.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定类型的上下文变量
|
||||||
|
* @param key 变量名
|
||||||
|
* @param type 期望的变量类型
|
||||||
|
* @param <T> 变量类型
|
||||||
|
* @return 转换为指定类型的变量值
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getVariable(String key, Class<T> type) {
|
||||||
|
Object value = variables.get(key);
|
||||||
|
return value == null ? null : (T) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.model;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例类
|
||||||
|
* 代表一个正在执行的具体流程,记录了当前的执行状态和上下文数据
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FlowInstance {
|
||||||
|
/**
|
||||||
|
* 实例ID
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应的流程定义ID
|
||||||
|
*/
|
||||||
|
private String flowId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前执行到的节点ID
|
||||||
|
*/
|
||||||
|
private String currentNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前流程状态
|
||||||
|
* @see FlowStatus
|
||||||
|
*/
|
||||||
|
private FlowStatus status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后更新时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程上下文变量
|
||||||
|
* 用于存储流程执行过程中的数据,实现节点间的数据传递
|
||||||
|
*/
|
||||||
|
private Map<String, Object> contextVariables;
|
||||||
|
|
||||||
|
public FlowInstance() {
|
||||||
|
this.contextVariables = new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程状态枚举
|
||||||
|
* 用于表示流程实例的当前状态
|
||||||
|
*/
|
||||||
|
public enum FlowStatus {
|
||||||
|
/**
|
||||||
|
* 进行中:流程正在执行中
|
||||||
|
*/
|
||||||
|
PENDING("进行中"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已通过:流程已经完成并通过
|
||||||
|
*/
|
||||||
|
APPROVED("已通过"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已拒绝:流程被拒绝
|
||||||
|
*/
|
||||||
|
REJECTED("已拒绝");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态的中文描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
FlowStatus(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class AbstractFlowNode implements FlowNode {
|
||||||
|
@Getter
|
||||||
|
private final String nodeId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(FlowContext context) {
|
||||||
|
// 默认实现为空
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApprove(FlowContext context) {
|
||||||
|
// 默认实现为空
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReject(FlowContext context) {
|
||||||
|
// 默认实现为空
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/com/lanyuanxiaoyao/flowable/node/FlowNode.java
Normal file
29
src/main/java/com/lanyuanxiaoyao/flowable/node/FlowNode.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.node;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程节点接口
|
||||||
|
* 定义节点的基本操作
|
||||||
|
*/
|
||||||
|
public interface FlowNode {
|
||||||
|
/**
|
||||||
|
* 获取节点ID
|
||||||
|
*/
|
||||||
|
String getNodeId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点初始化时执行的操作
|
||||||
|
*/
|
||||||
|
void execute(FlowContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点通过时执行的操作
|
||||||
|
*/
|
||||||
|
void onApprove(FlowContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点拒绝时执行的操作
|
||||||
|
*/
|
||||||
|
void onReject(FlowContext context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.repository;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FlowInstanceRepository {
|
||||||
|
FlowInstance save(FlowInstance instance);
|
||||||
|
FlowInstance findById(String id);
|
||||||
|
List<FlowInstance> findAll();
|
||||||
|
List<FlowInstance> findByFlowId(String flowId);
|
||||||
|
void deleteById(String id);
|
||||||
|
FlowInstance update(FlowInstance instance);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.repository;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.Flow;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FlowRepository {
|
||||||
|
Flow save(Flow flow);
|
||||||
|
Flow findById(String id);
|
||||||
|
List<Flow> findAll();
|
||||||
|
void deleteById(String id);
|
||||||
|
Flow update(Flow flow);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.repository.memory;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowInstanceRepository;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class MemoryFlowInstanceRepository implements FlowInstanceRepository {
|
||||||
|
private final Map<String, FlowInstance> storage = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlowInstance save(FlowInstance instance) {
|
||||||
|
String id = UUID.randomUUID().toString();
|
||||||
|
instance.setId(id);
|
||||||
|
storage.put(id, instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlowInstance findById(String id) {
|
||||||
|
return storage.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowInstance> findAll() {
|
||||||
|
return new ArrayList<>(storage.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FlowInstance> findByFlowId(String flowId) {
|
||||||
|
return storage.values().stream()
|
||||||
|
.filter(instance -> instance.getFlowId().equals(flowId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteById(String id) {
|
||||||
|
storage.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlowInstance update(FlowInstance instance) {
|
||||||
|
if (instance.getId() == null) {
|
||||||
|
throw new IllegalArgumentException("Instance id cannot be null when updating");
|
||||||
|
}
|
||||||
|
storage.put(instance.getId(), instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.repository.memory;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.Flow;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowRepository;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class MemoryFlowRepository implements FlowRepository {
|
||||||
|
private final Map<String, Flow> storage = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flow save(Flow flow) {
|
||||||
|
String id = UUID.randomUUID().toString();
|
||||||
|
flow.setId(id);
|
||||||
|
storage.put(id, flow);
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flow findById(String id) {
|
||||||
|
return storage.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Flow> findAll() {
|
||||||
|
return new ArrayList<>(storage.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteById(String id) {
|
||||||
|
storage.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flow update(Flow flow) {
|
||||||
|
if (flow.getId() == null) {
|
||||||
|
throw new IllegalArgumentException("Flow id cannot be null when updating");
|
||||||
|
}
|
||||||
|
storage.put(flow.getId(), flow);
|
||||||
|
return flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
package com.lanyuanxiaoyao.flowable.service;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.Flow;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowRepository;
|
||||||
|
import com.lanyuanxiaoyao.flowable.repository.FlowInstanceRepository;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowStatus;
|
||||||
|
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||||
|
import com.lanyuanxiaoyao.flowable.node.FlowNode;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FlowService {
|
||||||
|
private final FlowRepository flowRepository;
|
||||||
|
private final FlowInstanceRepository instanceRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的流程定义
|
||||||
|
*/
|
||||||
|
public Flow createFlow(Flow flow) {
|
||||||
|
if (flow.getNodes() == null || flow.getNodes().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("流程节点不能为空");
|
||||||
|
}
|
||||||
|
flow.setCreateTime(LocalDateTime.now());
|
||||||
|
flow.setUpdateTime(LocalDateTime.now());
|
||||||
|
return flowRepository.save(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动一个新的流程实例
|
||||||
|
*/
|
||||||
|
public FlowInstance startFlow(String flowId) {
|
||||||
|
Flow flow = flowRepository.findById(flowId);
|
||||||
|
if (flow == null) {
|
||||||
|
throw new IllegalArgumentException("找不到对应的流程定义");
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowInstance instance = new FlowInstance();
|
||||||
|
instance.setFlowId(flowId);
|
||||||
|
instance.setCurrentNode(flow.getNodes().get(0).getNodeId());
|
||||||
|
instance.setStatus(FlowStatus.PENDING);
|
||||||
|
instance.setCreateTime(LocalDateTime.now());
|
||||||
|
instance.setUpdateTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 保存实例
|
||||||
|
instance = instanceRepository.save(instance);
|
||||||
|
|
||||||
|
// 创建上下文
|
||||||
|
FlowContext context = createContext(instance);
|
||||||
|
|
||||||
|
// 执行第一个节点
|
||||||
|
flow.getNodes().get(0).execute(context);
|
||||||
|
|
||||||
|
// 保存上下文变量
|
||||||
|
saveContext(instance, context);
|
||||||
|
return instanceRepository.update(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审批通过当前节点
|
||||||
|
*/
|
||||||
|
public FlowInstance approve(String instanceId) {
|
||||||
|
FlowInstance instance = getAndValidateInstance(instanceId);
|
||||||
|
if (FlowStatus.APPROVED.equals(instance.getStatus()) ||
|
||||||
|
FlowStatus.REJECTED.equals(instance.getStatus())) {
|
||||||
|
throw new IllegalStateException("当前流程已经结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
Flow flow = flowRepository.findById(instance.getFlowId());
|
||||||
|
List<FlowNode> nodes = flow.getNodes();
|
||||||
|
int currentIndex = -1;
|
||||||
|
|
||||||
|
// 查找当前节点
|
||||||
|
for (int i = 0; i < nodes.size(); i++) {
|
||||||
|
if (nodes.get(i).getNodeId().equals(instance.getCurrentNode())) {
|
||||||
|
currentIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建上下文并加载已有变量
|
||||||
|
FlowContext context = createContext(instance);
|
||||||
|
|
||||||
|
// 执行当前节点的通过操作
|
||||||
|
FlowNode currentNode = nodes.get(currentIndex);
|
||||||
|
currentNode.onApprove(context);
|
||||||
|
|
||||||
|
// 判断是否是最后一个节点
|
||||||
|
if (currentIndex == nodes.size() - 1) {
|
||||||
|
instance.setStatus(FlowStatus.APPROVED);
|
||||||
|
} else {
|
||||||
|
// 移动到下一个节点并执行
|
||||||
|
FlowNode nextNode = nodes.get(currentIndex + 1);
|
||||||
|
instance.setCurrentNode(nextNode.getNodeId());
|
||||||
|
nextNode.execute(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存上下文变量
|
||||||
|
saveContext(instance, context);
|
||||||
|
instance.setUpdateTime(LocalDateTime.now());
|
||||||
|
return instanceRepository.update(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拒绝当前节点,结束流程
|
||||||
|
*/
|
||||||
|
public FlowInstance reject(String instanceId) {
|
||||||
|
FlowInstance instance = getAndValidateInstance(instanceId);
|
||||||
|
if (FlowStatus.APPROVED.equals(instance.getStatus()) ||
|
||||||
|
FlowStatus.REJECTED.equals(instance.getStatus())) {
|
||||||
|
throw new IllegalStateException("当前流程已经结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建上下文并加载已有变量
|
||||||
|
FlowContext context = createContext(instance);
|
||||||
|
|
||||||
|
// 执行当前节点的拒绝操作
|
||||||
|
Flow flow = flowRepository.findById(instance.getFlowId());
|
||||||
|
for (FlowNode node : flow.getNodes()) {
|
||||||
|
if (node.getNodeId().equals(instance.getCurrentNode())) {
|
||||||
|
node.onReject(context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.setStatus(FlowStatus.REJECTED);
|
||||||
|
|
||||||
|
// 保存上下文变量
|
||||||
|
saveContext(instance, context);
|
||||||
|
instance.setUpdateTime(LocalDateTime.now());
|
||||||
|
return instanceRepository.update(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流程实例当前状态
|
||||||
|
*/
|
||||||
|
public FlowInstance getFlowInstance(String instanceId) {
|
||||||
|
return getAndValidateInstance(instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流程定义的所有节点
|
||||||
|
*/
|
||||||
|
public List<FlowNode> getFlowNodes(String flowId) {
|
||||||
|
Flow flow = flowRepository.findById(flowId);
|
||||||
|
if (flow == null) {
|
||||||
|
throw new IllegalArgumentException("找不到对应的流程定义");
|
||||||
|
}
|
||||||
|
return flow.getNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FlowInstance getAndValidateInstance(String instanceId) {
|
||||||
|
FlowInstance instance = instanceRepository.findById(instanceId);
|
||||||
|
if (instance == null) {
|
||||||
|
throw new IllegalArgumentException("找不到对应的流程实例");
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FlowContext createContext(FlowInstance instance) {
|
||||||
|
FlowContext context = new FlowContext();
|
||||||
|
context.setFlowId(instance.getFlowId());
|
||||||
|
context.setInstanceId(instance.getId());
|
||||||
|
// 从实例中加载已保存的变量
|
||||||
|
if (instance.getContextVariables() != null) {
|
||||||
|
context.getVariables().putAll(instance.getContextVariables());
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveContext(FlowInstance instance, FlowContext context) {
|
||||||
|
// 将上下文变量保存到实例中
|
||||||
|
instance.getContextVariables().clear();
|
||||||
|
instance.getContextVariables().putAll(context.getVariables());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user