diff --git a/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java b/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java
index 31a2b162..9995f186 100644
--- a/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java
+++ b/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java
@@ -89,7 +89,7 @@ public interface RemoteWorkflowService {
* 办理任务
* 系统后台发起审批 无用户信息 需要忽略权限
* completeTask.getVariables().put("ignore", true);
- *
+ *
* @param taskId 任务ID
* @param message 办理意见
*/
@@ -98,7 +98,7 @@ public interface RemoteWorkflowService {
/**
* 【新增方法】根据业务ID获取当前活跃任务ID
* 用于润滑工单完成时获取正确的任务ID
- *
+ *
* @param businessId 业务ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
@@ -106,10 +106,30 @@ public interface RemoteWorkflowService {
/**
* 【新增方法】根据流程实例ID获取当前活跃任务ID
- *
+ *
* @param instanceId 流程实例ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
Long getCurrentTaskIdByInstanceId(Long instanceId);
+ /**
+ * 从hwbm的新版本plus框架中直接复制,未经过测试
+ * 【新增方法】启动流程并自动推进到下一节点
+ *
+ * 此方法将 startWorkFlow() 和 completeTask() 合并为一次调用,
+ * 但在内部使用两个独立的事务执行,避免数据库死锁。
+ *
+ *
+ * 适用场景:
+ *
+ * - 后端业务代码需要启动工作流并立即推进到审批节点
+ * - 避免在同一事务中多次操作 flow_instance 和 flow_task 表导致死锁
+ *
+ *
+ *
+ * @param startProcess 启动流程参数(包含 flowCode, businessId, variables 等)
+ * @return 结果 true=成功, false=失败
+ */
+ boolean startCompleteTask(RemoteStartProcess startProcess);
+
}
diff --git a/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/domain/RemoteStartProcess.java b/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/domain/RemoteStartProcess.java
index f7f12a53..3c53ec9b 100644
--- a/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/domain/RemoteStartProcess.java
+++ b/ruoyi-api/hwmom-api-workflow/src/main/java/org/dromara/workflow/api/domain/RemoteStartProcess.java
@@ -1,6 +1,7 @@
package org.dromara.workflow.api.domain;
+import cn.hutool.core.util.ObjectUtil;
import lombok.Data;
import java.io.Serial;
@@ -35,6 +36,13 @@ public class RemoteStartProcess implements Serializable {
*/
private Map variables;
+ /**
+ * 从hwbm的新版本plus框架中直接复制,未经过测试
+ * 业务扩展对象
+ * 包含业务相关的扩展信息,如业务编号、办理人等
+ */
+ private Object bizExt;
+
public Map getVariables() {
if (variables == null) {
return new HashMap<>(16);
@@ -42,4 +50,13 @@ public class RemoteStartProcess implements Serializable {
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
+
+ //从hwbm的新版本plus框架中直接复制,未经过测试
+ public Object getBizExt() {
+ if (ObjectUtil.isNull(bizExt)) {
+ bizExt = new Object();
+ }
+ return bizExt;
+ }
+
}
diff --git a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/FlowInstanceBizExt.java b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/FlowInstanceBizExt.java
new file mode 100644
index 00000000..283a483f
--- /dev/null
+++ b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/FlowInstanceBizExt.java
@@ -0,0 +1,60 @@
+package org.dromara.workflow.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.tenant.core.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 从hwbm的新版本plus框架中直接复制,未经过测试!
+ * 流程实例业务扩展对象 flow_instance_biz_ext
+ *
+ * @author may
+ * @date 2025-08-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("flow_instance_biz_ext")
+public class FlowInstanceBizExt extends TenantEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @TableId(value = "id")
+ private Long id;
+
+ /**
+ * 流程实例ID
+ */
+ private Long instanceId;
+
+ /**
+ * 业务ID
+ */
+ private String businessId;
+
+ /**
+ * 业务编码
+ */
+ private String businessCode;
+
+ /**
+ * 业务标题
+ */
+ private String businessTitle;
+
+ /**
+ * 删除标志(0代表存在 1代表删除)
+ */
+ @TableLogic
+ private String delFlag;
+
+
+}
diff --git a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java
index ea21a81e..eb8b64d4 100644
--- a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java
+++ b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java
@@ -1,6 +1,7 @@
package org.dromara.workflow.domain.bo;
+import cn.hutool.core.util.ObjectUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
@@ -39,6 +40,13 @@ public class StartProcessBo implements Serializable {
*/
private Map variables;
+ /**
+ * 从hwbm的新版本plus框架中直接复制,未经过测试
+ * 业务扩展对象
+ * 包含业务相关的扩展信息,如业务编号、办理人等
+ */
+ private Object bizExt;
+
public Map getVariables() {
if (variables == null) {
return new HashMap<>(16);
@@ -46,4 +54,13 @@ public class StartProcessBo implements Serializable {
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
+
+
+ //从hwbm的新版本plus框架中直接复制,未经过测试
+ public Object getBizExt() {
+ if (ObjectUtil.isNull(bizExt)) {
+ bizExt = new Object();
+ }
+ return bizExt;
+ }
}
diff --git a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/dubbo/RemoteWorkflowServiceImpl.java b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/dubbo/RemoteWorkflowServiceImpl.java
index bf4a3b37..a8a5391e 100644
--- a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/dubbo/RemoteWorkflowServiceImpl.java
+++ b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/dubbo/RemoteWorkflowServiceImpl.java
@@ -83,4 +83,10 @@ public class RemoteWorkflowServiceImpl implements RemoteWorkflowService {
return workflowService.getCurrentTaskIdByInstanceId(instanceId);
}
+ //从hwbm的新版本plus框架中直接复制,未经过测试
+ @Override
+ public boolean startCompleteTask(RemoteStartProcess startProcess) {
+ return workflowService.startCompleteTask(startProcess);
+ }
+
}
diff --git a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/WorkflowService.java b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/WorkflowService.java
index 746046d3..e54341bc 100644
--- a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/WorkflowService.java
+++ b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/WorkflowService.java
@@ -95,7 +95,7 @@ public interface WorkflowService {
/**
* 【新增方法】根据业务ID获取当前活跃任务ID
* 用于润滑工单完成时获取正确的任务ID
- *
+ *
* @param businessId 业务ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
@@ -103,10 +103,23 @@ public interface WorkflowService {
/**
* 【新增方法】根据流程实例ID获取当前活跃任务ID
- *
+ *
* @param instanceId 流程实例ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
Long getCurrentTaskIdByInstanceId(Long instanceId);
+ /**
+ * 从hwbm的新版本plus框架中直接复制,未经过测试!
+ * 【新增方法】启动流程并自动推进到下一节点
+ *
+ * 此方法将 startWorkFlow() 和 completeTask() 合并为一次调用,
+ * 但在内部使用两个独立的事务执行,避免数据库死锁。
+ *
+ *
+ * @param startProcess 启动流程参数(包含 flowCode, businessId, variables 等)
+ * @return 结果 true=成功, false=失败
+ */
+ boolean startCompleteTask(RemoteStartProcess startProcess);
+
}
diff --git a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
index f9a04515..252aef2c 100644
--- a/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
+++ b/ruoyi-modules/hwmom-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
@@ -4,12 +4,15 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.orm.entity.FlowInstance;
import org.dromara.workflow.api.domain.RemoteCompleteTask;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.domain.RemoteStartProcessReturn;
import org.dromara.workflow.common.ConditionalOnEnable;
+import org.dromara.workflow.common.enums.MessageTypeEnum;
+import org.dromara.workflow.domain.FlowInstanceBizExt;
import org.dromara.workflow.domain.bo.CompleteTaskBo;
import org.dromara.workflow.domain.bo.StartProcessBo;
import org.dromara.workflow.service.IFlwDefinitionService;
@@ -17,7 +20,10 @@ import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.service.WorkflowService;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -154,7 +160,7 @@ public class WorkflowServiceImpl implements WorkflowService {
/**
* 【新增方法】根据业务ID获取当前活跃任务ID
* 用于润滑工单完成时获取正确的任务ID
- *
+ *
* @param businessId 业务ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
@@ -165,14 +171,14 @@ public class WorkflowServiceImpl implements WorkflowService {
if (instanceId == null) {
return null;
}
-
+
// 通过流程实例ID获取当前活跃任务ID
return getCurrentTaskIdByInstanceId(instanceId);
}
/**
* 【新增方法】根据流程实例ID获取当前活跃任务ID
- *
+ *
* @param instanceId 流程实例ID
* @return 当前活跃任务ID,如果没有找到返回null
*/
@@ -181,16 +187,16 @@ public class WorkflowServiceImpl implements WorkflowService {
if (instanceId == null) {
return null;
}
-
+
try {
// 获取该流程实例下的所有活跃任务
List activeTasks = flwTaskService.selectByInstId(instanceId);
-
+
// 过滤出当前活跃的任务(del_flag=0)
Optional activeTask = activeTasks.stream()
.filter(task -> "0".equals(task.getDelFlag()))
.findFirst();
-
+
return activeTask.map(org.dromara.warm.flow.orm.entity.FlowTask::getId).orElse(null);
} catch (Exception e) {
log.error("获取当前活跃任务失败,instanceId: {}", instanceId, e);
@@ -198,4 +204,129 @@ public class WorkflowServiceImpl implements WorkflowService {
}
}
+ /**
+ * 【新增方法】启动流程并自动推进到下一节点
+ *
+ * 此方法将 startWorkFlow() 和 completeTask() 合并为一次调用,
+ * 但在内部使用两个独立的事务执行,避免数据库死锁。
+ *
+ *
+ * 核心机制:
+ *
+ * - 1. 启动流程(事务1):创建 flow_instance 和 flow_task
+ * - 2. 提交事务1,释放数据库锁
+ * - 3. 推进流程(事务2):完成当前任务,创建下一节点任务
+ *
+ *
+ *
+ * @param startProcess 启动流程参数
+ * @return 结果 true=成功, false=失败
+ */
+// @Override
+// public boolean startCompleteTask(RemoteStartProcess startProcess) {
+// try {
+// // 阶段1:启动流程(独立事务)
+// // startWorkFlow() 方法已有 @Transactional 注解,会在独立事务中执行
+// RemoteStartProcessReturn startResult = flwTaskService.startWorkFlow(
+// BeanUtil.toBean(startProcess, StartProcessBo.class)
+// );
+//
+// if (startResult == null || startResult.getTaskId() == null) {
+// log.error("启动工作流失败,flowCode: {}, businessId: {}",
+// startProcess.getFlowCode(), startProcess.getBusinessId());
+// return false;
+// }
+//
+// Long taskId = startResult.getTaskId();
+//
+// // 阶段1事务已提交,数据库锁已释放
+//
+// // 阶段2:推进流程(新独立事务)
+// // 使用 REQUIRES_NEW 确保在新事务中执行,避免与阶段1的事务冲突
+// return completeTaskInNewTransaction(taskId, startProcess);
+//
+// } catch (Exception e) {
+// log.error("startCompleteTask 执行异常,flowCode: {}, businessId: {}, error: {}",
+// startProcess.getFlowCode(), startProcess.getBusinessId(), e.getMessage(), e);
+// return false;
+// }
+// }
+
+ /**
+ * 在新事务中推进流程
+ *
+ * 使用 REQUIRES_NEW 传播级别,确保在新事务中执行,
+ * 避免与 startWorkFlow() 的事务产生死锁。
+ *
+ *
+ * @param taskId 任务ID
+ * @param startProcess 启动参数(包含 variables)
+ * @return 结果 true=成功, false=失败
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
+ protected boolean completeTaskInNewTransaction(Long taskId, RemoteStartProcess startProcess) {
+ try {
+ RemoteCompleteTask completeTask = new RemoteCompleteTask();
+ completeTask.setTaskId(taskId);
+
+ // 传递 variables(如果有)
+ // variables 可以包含流程分支条件、message、messageType、notice 等参数
+ if (startProcess.getVariables() != null && !startProcess.getVariables().isEmpty()) {
+ completeTask.setVariables(startProcess.getVariables());
+ }
+
+ // 调用 completeTask(在新事务中)
+ boolean result = flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo.class));
+
+ if (result) {
+ log.info("工作流启动并推进成功,flowCode: {}, businessId: {}, taskId: {}",
+ startProcess.getFlowCode(), startProcess.getBusinessId(), taskId);
+ } else {
+ log.warn("工作流推进失败,flowCode: {}, businessId: {}, taskId: {}",
+ startProcess.getFlowCode(), startProcess.getBusinessId(), taskId);
+ }
+
+ return result;
+
+ } catch (Exception e) {
+ log.error("completeTaskInNewTransaction 执行异常,taskId: {}, businessId: {}, error: {}",
+ taskId, startProcess.getBusinessId(), e.getMessage(), e);
+ throw e; // 重新抛出异常,触发事务回滚
+ }
+ }
+
+ /**
+ * 启动流程并办理第一个任务
+ * 从hwbm的新版本plus框架中直接复制,未经过测试
+ *
+ * @param startProcess 参数
+ */
+ @Override
+ public boolean startCompleteTask(RemoteStartProcess startProcess) {
+ try {
+ StartProcessBo processBo = new StartProcessBo();
+ processBo.setBusinessId(startProcess.getBusinessId());
+ processBo.setFlowCode(startProcess.getFlowCode());
+ processBo.setVariables(startProcess.getVariables());
+// processBo.setHandler(startProcess.getHandler());
+ processBo.setBizExt(BeanUtil.toBean(startProcess.getBizExt(), FlowInstanceBizExt.class));
+
+ RemoteStartProcessReturn result = flwTaskService.startWorkFlow(processBo);
+ CompleteTaskBo taskBo = new CompleteTaskBo();
+ taskBo.setTaskId(result.getTaskId());
+ taskBo.setMessageType(Collections.singletonList(MessageTypeEnum.SYSTEM_MESSAGE.getCode()));
+ taskBo.setVariables(startProcess.getVariables());
+// taskBo.setHandler(startProcess.getHandler());
+
+ boolean flag = flwTaskService.completeTask(taskBo);
+ if (!flag) {
+ throw new ServiceException("流程发起异常");
+ }
+ return true;
+ } catch (Exception e) {
+ throw new ServiceException(e.getMessage());
+ }
+ }
+
+
}