|
|
|
|
@ -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<org.dromara.warm.flow.orm.entity.FlowTask> activeTasks = flwTaskService.selectByInstId(instanceId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤出当前活跃的任务(del_flag=0)
|
|
|
|
|
Optional<org.dromara.warm.flow.orm.entity.FlowTask> 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 {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 【新增方法】启动流程并自动推进到下一节点
|
|
|
|
|
* <p>
|
|
|
|
|
* 此方法将 startWorkFlow() 和 completeTask() 合并为一次调用,
|
|
|
|
|
* 但在内部使用两个独立的事务执行,避免数据库死锁。
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>
|
|
|
|
|
* 核心机制:
|
|
|
|
|
* <ul>
|
|
|
|
|
* <li>1. 启动流程(事务1):创建 flow_instance 和 flow_task</li>
|
|
|
|
|
* <li>2. 提交事务1,释放数据库锁</li>
|
|
|
|
|
* <li>3. 推进流程(事务2):完成当前任务,创建下一节点任务</li>
|
|
|
|
|
* </ul>
|
|
|
|
|
* </p>
|
|
|
|
|
*
|
|
|
|
|
* @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;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 在新事务中推进流程
|
|
|
|
|
* <p>
|
|
|
|
|
* 使用 REQUIRES_NEW 传播级别,确保在新事务中执行,
|
|
|
|
|
* 避免与 startWorkFlow() 的事务产生死锁。
|
|
|
|
|
* </p>
|
|
|
|
|
*
|
|
|
|
|
* @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());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|