diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 9f555b02a7..0e92b32d00 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -399,6 +399,11 @@
${revision}
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-flowable
+ ${revision}
+
org.flowable
flowable-spring-boot-starter-basic
diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml
index 85533c9a28..21452b4d13 100644
--- a/yudao-framework/pom.xml
+++ b/yudao-framework/pom.xml
@@ -35,6 +35,7 @@
yudao-spring-boot-starter-biz-social
yudao-spring-boot-starter-biz-tenant
yudao-spring-boot-starter-biz-data-permission
+ yudao-spring-boot-starter-flowable
yudao-framework
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
index 6cfbba177f..93bd20fa48 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
@@ -29,6 +29,8 @@ public interface WebFilterOrderEnum {
int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面
+ int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
+
int DEMO_FILTER = Integer.MAX_VALUE;
}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml
new file mode 100644
index 0000000000..f778e2a542
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml
@@ -0,0 +1,31 @@
+
+
+
+ yudao-framework
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+
+ yudao-spring-boot-starter-flowable
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-security
+
+
+
+ org.flowable
+ flowable-spring-boot-starter-basic
+
+
+
+
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
new file mode 100644
index 0000000000..4061339d69
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.framework.flowable.config;
+
+import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
+import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class YudaoFlowableConfiguration {
+
+ /**
+ * 配置 flowable Web 过滤器
+ */
+ @Bean
+ public FilterRegistrationBean flowableWebFilter() {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(new FlowableWebFilter());
+ registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER);
+ return registrationBean;
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
new file mode 100644
index 0000000000..de8d6279d7
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.framework.flowable.core;
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
new file mode 100644
index 0000000000..641c699c9c
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.framework.flowable.core.util;
+
+import org.flowable.common.engine.impl.identity.Authentication;
+
+public class FlowableUtils {
+
+ public static void setAuthenticatedUserId(Long userId) {
+ Authentication.setAuthenticatedUserId(String.valueOf(userId));
+ }
+
+ public static void clearAuthenticatedUserId() {
+ Authentication.setAuthenticatedUserId(null);
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java
new file mode 100644
index 0000000000..d9845a394c
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.framework.flowable.core.web;
+
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+/**
+ * flowable Web 过滤器,将 userId 设置到 {@link org.flowable.common.engine.impl.identity.Authentication} 中
+ *
+ * @author jason
+ */
+public class FlowableWebFilter extends OncePerRequestFilter {
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
+ try {
+ // 设置工作流的用户
+ Long userId = SecurityFrameworkUtils.getLoginUserId();
+ if (userId != null) {
+ FlowableUtils.setAuthenticatedUserId(userId);
+ }
+ // 过滤
+ chain.doFilter(request, response);
+ } finally {
+ // 清理
+ FlowableUtils.clearAuthenticatedUserId();
+ }
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
new file mode 100644
index 0000000000..324d3de0ec
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.framework.flowable;
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000..c667d5e553
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
index 09822771da..ea48aaf908 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
@@ -23,8 +23,8 @@
- org.flowable
- flowable-spring-boot-starter-basic
+ cn.iocoder.boot
+ yudao-spring-boot-starter-flowable
org.flowable
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
new file mode 100644
index 0000000000..d7009a5c69
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.config;
+
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
+import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.spring.SpringProcessEngineConfiguration;
+import org.flowable.spring.boot.EngineConfigurationConfigurer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * BPM 模块的 Flowable 配置类
+ *
+ * @author jason
+ */
+@Configuration
+public class BpmFlowableConfiguration {
+
+ /**
+ *将自定义 listener 加入全局listener
+ * @param processInstanceListener 自定义监听 {@link ProcessInstance}
+ */
+ @Bean
+ public EngineConfigurationConfigurer addCustomerListenerConfigurer (BpmProcessInstanceEventListener processInstanceListener) {
+ return engineConfiguration -> {
+ List eventListeners = new ArrayList<>();
+ eventListeners.add(processInstanceListener);
+ engineConfiguration.setEventListeners(eventListeners);
+ };
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
new file mode 100644
index 0000000000..1b5d1c6e53
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
+
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import com.google.common.collect.ImmutableSet;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
+import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
+import org.flowable.engine.delegate.event.FlowableCancelledEvent;
+import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Set;
+/**
+ * 监听 {@link ProcessInstance} 的开始与完成,创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录
+ *
+ * @author jason
+ */
+@Component
+public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
+
+ @Resource
+ @Lazy
+ private BpmProcessInstanceService processInstanceService;
+
+ public static final Set PROCESS_INSTANCE_EVENTS = ImmutableSet.builder()
+ .add(FlowableEngineEventType.PROCESS_CREATED)
+ .add(FlowableEngineEventType.PROCESS_STARTED)
+ .add(FlowableEngineEventType.PROCESS_CANCELLED)
+ .build();
+
+ public BpmProcessInstanceEventListener(){
+ super(PROCESS_INSTANCE_EVENTS);
+ }
+
+ @Override
+ protected void processCreated(FlowableEngineEntityEvent event) {
+ processInstanceService.createProcessInstanceExt((ProcessInstance)event.getEntity());
+ }
+
+ @Override
+ protected void processStarted(FlowableProcessStartedEvent event) {
+ super.processStarted(event);
+ }
+
+
+ @Override
+ protected void processCancelled(FlowableCancelledEvent event) {
+ super.processCancelled(event);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
index 96a0bc1a71..7c26b644e4 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
@@ -89,6 +89,16 @@ public interface BpmProcessDefinitionService {
*/
ProcessDefinition getProcessDefinition(String id);
+ /**
+ * 获得编号对应的 ProcessDefinition
+ *
+ * 相比 {@link #getProcessDefinition(String)} 方法,category 的取值是正确
+ *
+ * @param id 编号
+ * @return 流程定义
+ */
+ ProcessDefinition getProcessDefinition2(String id);
+
/**
* 获得 deploymentId 对应的 ProcessDefinition
*
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
index f56a18fffa..d75a1bd68a 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -66,6 +66,11 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
return repositoryService.getProcessDefinition(id);
}
+ @Override
+ public ProcessDefinition getProcessDefinition2(String id) {
+ return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
+ }
+
@Override
public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
if (StrUtil.isEmpty(deploymentId)) {
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
index f1d25f1e2c..7b6e3638d3 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessI
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
@@ -73,4 +74,11 @@ public interface BpmProcessInstanceService {
* @return 历史的流程实例
*/
HistoricProcessInstance getHistoricProcessInstance(String id);
+
+ /**
+ * 创建 ProcessInstance 拓展记录
+ *
+ * @param instance 流程任务
+ */
+ void createProcessInstanceExt(ProcessInstance instance);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
index 77f14f3d15..f9295e0f7d 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -32,6 +34,7 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -142,6 +145,23 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
}
+ @Override
+ public void createProcessInstanceExt(ProcessInstance instance) {
+ // 获得流程定义
+ ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
+ // 插入 BpmProcessInstanceExtDO 对象
+ BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
+ .setProcessInstanceId(instance.getId())
+ .setProcessDefinitionId(definition.getId())
+ .setName(instance.getProcessDefinitionName())
+ .setStartUserId(Long.valueOf(instance.getStartUserId()))
+ .setCategory(definition.getCategory())
+ .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
+ .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
+
+ processInstanceExtMapper.insert(instanceExtDO);
+ }
+
private String createProcessInstance0(Long userId, ProcessDefinition definition,
Map variables, String businessKey) {
// 校验流程定义