feat(dms): 添加工作流支持并优化任务执行策略

- 在 DmsBillsInspectInstance、RemoteInspectInstanceServiceImpl、RemoteLubeInstanceServiceImpl 和 RemoteMaintInstanceServiceImpl 中添加工作流相关字段和方法
- 润滑、保养、点巡检计划中更新任务执行策略为丢弃后续任务,避免重复执行
- 增加异步处理工作流推进,避免死锁
- 优化登录状态管理和 RPC 上下文清理
- DmsBillsInspectInstance实体类加@TableField(exist = false)
master
zch 1 week ago
parent 53192c4ca6
commit 0f658f33dd

@ -107,9 +107,12 @@ public class DmsBillsInspectInstance extends TenantEntity {
@TableField(exist = false)
private List<DmsInspectInstanceDetail> dmsInspectInstanceDetailList;
@TableField(exist = false)
private String planInspectCode;
@TableField(exist = false)
private String inspectStatusStr;
}

@ -1,44 +1,116 @@
package org.dromara.dms.dubbo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.ttl.TtlRunnable;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rpc.RpcContext;
import org.dromara.common.core.constant.DmsConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.dms.api.RemoteInspectInstanceService;
import org.dromara.dms.domain.*;
import org.dromara.dms.mapper.*;
import org.dromara.dms.service.impl.DmsInspectProjectDeviceServiceImpl;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteCompleteTask;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.domain.RemoteStartProcessReturn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
@Service
@DubboService
@Slf4j
public class RemoteInspectInstanceServiceImpl implements RemoteInspectInstanceService {
private final DmsPlanInspectMapper dmsPlanInspectMapper;
private final DmsInspectRouteDetailMapper dmsInspectRouteDetailMapper;
private final DmsBillsInspectInstanceMapper dmsBillsInspectInstanceMapper;
private final DmsInspectInstanceDetailMapper dmsInspectInstanceDetailMapper;
private final DmsInspectInstanceDetailProjectMapper dmsInspectInstanceDetailProjectMapper;
private final DmsInspectProjectDeviceMapper dmsInspectProjectDeviceMapper;
@DubboReference(timeout = 10000)
private RemoteWorkflowService remoteWorkflowService;
@Override
@Transactional( rollbackFor = Exception.class )
@GlobalTransactional(rollbackFor = Exception.class)
public R<Integer> insertInspectInstance(String planInspectCode, String tenantId, Long userId){
// 【重要】在主线程中先登录,确保后续所有调用都有认证上下文
StpUtil.login(userId, "login");
try {
// 创建检查实例
R<Long> rInspectInstanceId = createInspectInstance(planInspectCode, tenantId, userId);
Long inspectInstanceId = rInspectInstanceId.getData();
String businessId = inspectInstanceId.toString();
if (!R.isSuccess(rInspectInstanceId)) {
return R.fail();
} else {
// 启动工作流
RemoteStartProcess remoteStartProcess = new RemoteStartProcess();
remoteStartProcess.setBusinessId(businessId);
remoteStartProcess.setFlowCode(DmsConstants.DMS_BILLS_INSPECT_INSTANCE_WF_CODE);
RemoteStartProcessReturn result = remoteWorkflowService.startWorkFlow(remoteStartProcess);
if (ObjectUtils.isEmpty(result)) {
return R.fail();
} else {
Long taskId = result.getTaskId();
// 【简化方案】异步处理工作流推进,避免死锁
CompletableFuture.runAsync(TtlRunnable.get(() -> {
try {
// 【关键】在异步线程中重新登录相同用户
StpUtil.login(userId, "login");
// 【执行业务】更新检查工单的工作流信息
updateInspectWorkflow(inspectInstanceId, taskId);
log.info("检查工单 {} 异步工作流处理完成", inspectInstanceId);
} catch (Exception e) {
log.error("检查工单 {} 异步工作流处理失败: {}", inspectInstanceId, e.getMessage(), e);
} finally {
// 【清理】清理登录状态,避免线程池复用时的状态污染
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出时的异常
}
// 清理RpcContext
try {
RpcContext.removeContext();
} catch (Exception ignored) {
// 忽略清理时的异常
}
}
}));
return R.ok(1);
}
}
} finally {
// 【主线程清理】确保主线程执行完成后清理登录状态
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出异常
}
}
}
private R<Long> createInspectInstance(String planInspectCode, String tenantId, Long userId) {
// 使用 replaceAll 方法将双引号替换为空字符串
String result = planInspectCode.replaceAll("\"", "");
// 根据检查计划代码查询检查计划信息
@ -58,30 +130,22 @@ public class RemoteInspectInstanceServiceImpl implements RemoteInspectInstanceSe
DmsBillsInspectInstance dmsBillsInspectInstance = new DmsBillsInspectInstance();
// 设置检查实例的相关属性
dmsBillsInspectInstance.setPlanInspectId(dmsPlanInspect.getPlanInspectId());
// dmsBillsInspectInstance.setWfProcessId(105l);
dmsBillsInspectInstance.setInspectType(dmsPlanInspect.getInspectType());//检查类型(1巡检 2点检)
dmsBillsInspectInstance.setPlanBeginTime(dmsPlanInspect.getPlanTime());
dmsBillsInspectInstance.setPlanEndTime(new Date(dmsPlanInspect.getPlanTime().getTime()+dmsPlanInspect.getTimeLimit()*1000l));
dmsBillsInspectInstance.setInspectRouteId(dmsPlanInspect.getInspectRouteId());
// dmsBillsInspectInstance.setDeviceAmount(dmsPlanInspect.getDeviceAmount());//设备数量FIXME:没有这个字段
dmsBillsInspectInstance.setPerformer(dmsPlanInspect.getPerformer());//执行人
// dmsBillsInspectInstance.setIsFlag("1");
dmsBillsInspectInstance.setInspectStatus(DmsConstants.DMS_BILLS_INSPECT_INSTANCE_INSPECT_STATUS_TO_INSPECT);//待巡检
dmsBillsInspectInstance.setCreateBy(userId);
dmsBillsInspectInstance.setTenantId(tenantId);
// 插入检查实例并返回影响的行数
int i = dmsBillsInspectInstanceMapper.insert(dmsBillsInspectInstance);
// List<DmsBillsInspectInstance> dmsBillsInspectInstances = dmsBillsInspectInstanceMapper.selectDmsBillsInspectInstanceList(dmsBillsInspectInstance);
//新建点巡检工单明细
/* DmsInspectRouteDetail queryInspectRouteDetail = new DmsInspectRouteDetail();
queryInspectRouteDetail.setInspectRouteId(dmsBillsInspectInstance.getInspectRouteId());*/
// 查询检查路线明细
MPJLambdaWrapper<DmsInspectRouteDetail> lqw = JoinWrappers.lambda(DmsInspectRouteDetail.class)
.eq(DmsInspectRouteDetail::getInspectRouteId, dmsBillsInspectInstance.getInspectRouteId());
List<DmsInspectRouteDetail> dmsInspectRouteDetails = dmsInspectRouteDetailMapper.selectList(lqw);
// 遍历检查路线明细,生成检查实例明细
for(DmsInspectRouteDetail dmsInspectRouteDetail:dmsInspectRouteDetails){
DmsInspectInstanceDetail dmsInspectInstanceDetail = new DmsInspectInstanceDetail();
@ -91,38 +155,60 @@ public class RemoteInspectInstanceServiceImpl implements RemoteInspectInstanceSe
dmsInspectInstanceDetail.setMachineId(deviceId);
dmsInspectInstanceDetail.setInstanceDetailStatus("1");//1待巡检 2巡检中 3已完成
dmsInspectInstanceDetail.setInspectStandard(dmsInspectRouteDetail.getInspectStandard());
dmsInspectInstanceDetail.setInspectStatus("0");//FIXME:为什么设置为异常?设备状态1正常 0异常
dmsInspectInstanceDetail.setInspectStatus("0");//设备状态1正常 0异常
dmsInspectInstanceDetail.setTenantId(tenantId);
dmsInspectInstanceDetail.setCreateBy(userId);
// dmsInspectInstanceDetail.setCreateTime(new Date());
dmsInspectInstanceDetailMapper.insert(dmsInspectInstanceDetail);
// 查询项目ID
Long projectId = dmsInspectInstanceDetailMapper.selectProjectId(dmsInspectRouteDetail.getInspectStandard());
DmsInspectProjectDevice queryInspectProjectDevice = new DmsInspectProjectDevice();
queryInspectProjectDevice.setTargetType("2");//FIXME:关联类型(1设备类型)
queryInspectProjectDevice.setTargetType("2");//关联类型
queryInspectProjectDevice.setTargetId(deviceId);
MPJLambdaWrapper<DmsInspectProjectDevice> DmsInspectProjectDeviceLQW = JoinWrappers.lambda(DmsInspectProjectDevice.class)
.eq(DmsInspectProjectDevice::getTargetType, "2")//FIXME:关联类型(1设备类型)
.eq(DmsInspectProjectDevice::getTargetType, "2")//关联类型
.eq(DmsInspectProjectDevice::getTargetId, deviceId);
List<DmsInspectProjectDevice> dmsInspectProjectDevices = dmsInspectProjectDeviceMapper.selectList(DmsInspectProjectDeviceLQW);
// for(DmsInspectProjectDevice dmsInspectProjectDevice:dmsInspectProjectDevices){
DmsInspectInstanceDetailProject dmsInspectInstanceDetailProject = new DmsInspectInstanceDetailProject();
dmsInspectInstanceDetailProject.setInstanceDetailId(dmsInspectInstanceDetail.getInstanceDetailId());
dmsInspectInstanceDetailProject.setInspectProjectId(projectId);
dmsInspectInstanceDetailProject.setTenantId(tenantId);
dmsInspectInstanceDetailProject.setCreateBy(userId);
dmsInspectInstanceDetailProjectMapper.insert(dmsInspectInstanceDetailProject);
// }
}
// 返回成功结果和影响的行数
return R.ok(i);
// 返回成功结果和检查实例ID
return R.ok(dmsBillsInspectInstance.getInspectInstanceId());
}
private void updateInspectWorkflow(Long businessId, Long taskId) {
try {
// 1. 更新工作流ID
DmsBillsInspectInstance inspectInstance = dmsBillsInspectInstanceMapper.selectById(businessId);
if (inspectInstance != null) {
inspectInstance.setWfDefinitionId(taskId);
dmsBillsInspectInstanceMapper.updateById(inspectInstance);
log.info("检查工单 {} 工作流ID更新成功: {}", businessId, taskId);
}
// 2. 推进工作流状态
RemoteCompleteTask completeTask = new RemoteCompleteTask();
completeTask.setTaskId(taskId);
completeTask.setMessage("检查工单启动,自动推进");
// 设置消息类型为非null的List
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system"); // 系统消息
completeTask.setMessageType(messageTypes);
// 【关键】调用工作流推进
remoteWorkflowService.completeTask(completeTask);
log.info("检查工单 {} 工作流推进成功", businessId);
} catch (Exception e) {
log.error("检查工单 {} 工作流更新失败: {}", businessId, e.getMessage(), e);
// 注意:这里不抛出异常,避免影响主流程
}
}
}

@ -1,34 +1,46 @@
package org.dromara.dms.dubbo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.ttl.TtlRunnable;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rpc.RpcContext;
import org.dromara.common.core.constant.DmsConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.uuid.Seq;
import org.dromara.dms.domain.*;
import org.dromara.dms.domain.bo.DmsBillsLubeInstanceBo;
import org.dromara.dms.domain.bo.DmsPlanLubeBo;
import org.dromara.dms.domain.vo.DmsBillsLubeInstanceVo;
import org.dromara.dms.domain.bo.*;
import org.dromara.dms.domain.vo.*;
import org.dromara.dms.domain.vo.DmsPlanLubeDetailVo;
import org.dromara.dms.mapper.*;
import org.dromara.dms.service.IDmsBillsLubeInstanceService;
import org.dromara.dms.service.IDmsPlanInspectService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteCompleteTask;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.domain.RemoteStartProcessReturn;
import org.springframework.stereotype.Service;
import org.dromara.dms.api.RemoteLubeInstanceService;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
@Service
@DubboService
@Slf4j
public class RemoteLubeInstanceServiceImpl implements RemoteLubeInstanceService {
private final DmsBillsLubeInstanceMapper dmsBillsLubeInstanceMapper;
private final DmsBillsLubeDetailMapper dmsBillsLubeDetailMapper;
@ -47,12 +59,75 @@ public class RemoteLubeInstanceServiceImpl implements RemoteLubeInstanceService
private final DmsInspectRouteDetailMapper dmsInspectRouteDetailMapper;
// private final RemoteWorkflowService remoteWorkflowService;
@DubboReference(timeout = 10000)
private final RemoteWorkflowService remoteWorkflowService;
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public R<Void> insertLubeInstance(String planLubeCode, String tenantId, Long userId) {
// 【重要】在主线程中先登录,确保后续所有调用都有认证上下文
StpUtil.login(userId, "login");
try {
R<Long> RLubeStanceId = LubeStance(planLubeCode, tenantId, userId);
Long LubeStanceId = RLubeStanceId.getData();
String businessId = LubeStanceId.toString();
if (!R.isSuccess(RLubeStanceId)) {
return R.fail();
}else {
RemoteStartProcess remoteStartProcess = new RemoteStartProcess();
remoteStartProcess.setBusinessId(businessId);
remoteStartProcess.setFlowCode(DmsConstants.DMS_BILLS_LUBE_INSTANCE_WF_CODE);
RemoteStartProcessReturn result = remoteWorkflowService.startWorkFlow(remoteStartProcess);
//TODO:赋值给工单的wfid
if(ObjectUtils.isEmpty(result)){
return R.fail();
}else {
Long taskId = result.getTaskId();
// 【简化方案】直接在异步线程中重新登录相同用户避免Token传递复杂性
CompletableFuture.runAsync(TtlRunnable.get(() -> {
try {
// 【关键】在异步线程中重新登录相同用户
// 这样可以确保生成有效的Token并自动设置到Sa-Token上下文中
StpUtil.login(userId, "login");
// 【执行业务】更新润滑工单的工作流信息
updateWarmFlow(LubeStanceId, taskId);
log.info("润滑工单 {} 异步工作流处理完成", LubeStanceId);
} catch (Exception e) {
log.error("润滑工单 {} 异步工作流处理失败: {}", LubeStanceId, e.getMessage(), e);
} finally {
// 【清理】清理登录状态,避免线程池复用时的状态污染
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出时的异常
}
// 清理RpcContext
try {
RpcContext.removeContext();
} catch (Exception ignored) {
// 忽略清理时的异常
}
}
}));
return R.ok();
}
}
} finally {
// 【主线程清理】确保主线程执行完成后清理登录状态
// 注意这里不影响异步线程因为每个线程都有自己的ThreadLocal
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出异常
}
}
}
private R<Long> LubeStance(String planLubeCode, String tenantId, Long userId){
// 去除润滑计划编号中的双引号
// String lubeInstanceCodeS = planLubeCode.replaceAll("\"", "");
@ -67,7 +142,6 @@ public class RemoteLubeInstanceServiceImpl implements RemoteLubeInstanceService
List<DmsPlanLubeDetailVo> dmsPlanLubeDetailList = dmsPlanLubeDetailMapper.selectVoList(dmsPlanLubeDetailWrapper);
dmsPlanLube.setDmsPlanLubeDetailList(dmsPlanLubeDetailList);
// 获取润滑计划详情列表
List<DmsPlanLubeDetailVo> planLubeDetails = dmsPlanLube.getDmsPlanLubeDetailList();
if (planLubeDetails == null || planLubeDetails.isEmpty()) {
@ -100,11 +174,14 @@ public class RemoteLubeInstanceServiceImpl implements RemoteLubeInstanceService
dmsBillsLubeInstance.setCreateBy(userId);
dmsBillsLubeInstance.setTenantId(tenantId);
// 插入润滑工单实例到数据库
int i = dmsBillsLubeInstanceMapper.insert(dmsBillsLubeInstance);
Boolean flag = dmsBillsLubeInstanceMapper.insert(dmsBillsLubeInstance) > 0;
Long LubeStanceId = dmsBillsLubeInstance.getLubeInstanceId();
DmsPlanLubeBo dmsPlanLubeBo = MapstructUtils.convert(dmsPlanLube, DmsPlanLubeBo.class);
// 批量插入润滑工单详情
List<DmsPlanLubeDetailVo> lubeDetails = dmsPlanLubeBo.getDmsPlanLubeDetailList();
List<DmsBillsLubeDetail> billsLubeDetails = new ArrayList<>();
int insert = 0;
for (DmsPlanLubeDetailVo planLubeDetail : lubeDetails) {
DmsBillsLubeDetail dmsBillsLubeDetail = new DmsBillsLubeDetail();
dmsBillsLubeDetail.setLubeInstanceId(dmsBillsLubeInstance.getLubeInstanceId());
@ -117,9 +194,39 @@ public class RemoteLubeInstanceServiceImpl implements RemoteLubeInstanceService
dmsBillsLubeDetail.setCreateBy(userId);
// dmsBillsLubeDetail.setCreateTime(new Date());
dmsBillsLubeDetailMapper.insert(dmsBillsLubeDetail);
insert = dmsBillsLubeDetailMapper.insert(dmsBillsLubeDetail);
}
return R.ok();
return R.ok(LubeStanceId);
}
private void updateWarmFlow(Long businessId,Long taskId){
try {
// 1. 更新工作流ID
DmsBillsLubeInstanceVo dmsBillsLubeInstanceVo = dmsBillsLubeInstanceService.queryById(businessId);
DmsBillsLubeInstance billsLubeInstance = MapstructUtils.convert(dmsBillsLubeInstanceVo, DmsBillsLubeInstance.class);
billsLubeInstance.setWfDefinitionId(taskId);
dmsBillsLubeInstanceMapper.updateById(billsLubeInstance);
log.info("润滑工单 {} 工作流ID更新成功: {}", businessId, taskId);
// 2. 推进工作流状态
RemoteCompleteTask completeTask = new RemoteCompleteTask();
completeTask.setTaskId(taskId);
completeTask.setMessage("润滑工单启动,自动推进");
// 设置消息类型为非null的List
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system"); // 系统消息
completeTask.setMessageType(messageTypes);
// 【关键】调用工作流推进可能会因为Token问题失败
remoteWorkflowService.completeTask(completeTask);
log.info("润滑工单 {} 工作流推进成功", businessId);
} catch (Exception e) {
log.error("润滑工单 {} 工作流更新失败: {}", businessId, e.getMessage(), e);
// 注意:这里不抛出异常,避免影响主流程
// 工作流推进失败时,工单仍然创建成功,但状态为草稿
}
}
}

@ -1,11 +1,16 @@
package org.dromara.dms.dubbo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.ttl.TtlRunnable;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rpc.RpcContext;
import org.dromara.common.core.constant.DmsConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.uuid.Seq;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.dms.api.RemoteMaintInstanceService;
@ -15,16 +20,22 @@ import org.dromara.dms.mapper.DmsBillsMaintDetailProjectMapper;
import org.dromara.dms.mapper.DmsBillsMaintInstanceMapper;
import org.dromara.dms.mapper.DmsPlanMaintMapper;
import org.dromara.system.api.model.LoginUser;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteCompleteTask;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.domain.RemoteStartProcessReturn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
@Service
@DubboService
@Slf4j
public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceService {
private final DmsPlanMaintMapper dmsPlanMaintMapper;
@ -32,10 +43,11 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
private final DmsBillsMaintInstanceMapper dmsBillsMaintInstanceMapper;
private final DmsBillsMaintDetailMapper dmsBillsMaintDetailMapper;
private final DmsBillsMaintDetailProjectMapper dmsBillsMaintDetailProjectMapper;
@DubboReference(timeout = 10000)
private RemoteWorkflowService remoteWorkflowService;
/**
*
@ -44,8 +56,71 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
* @return
*/
@Override
@Transactional( rollbackFor = Exception.class )
@GlobalTransactional(rollbackFor = Exception.class)
public R<Integer> insertDmsBillsMaintInstance(String planMaintCode , String tenantId, Long userId) {
// 【重要】在主线程中先登录,确保后续所有调用都有认证上下文
StpUtil.login(userId, "login");
try {
// 创建保养实例
R<Long> rMaintInstanceId = createMaintInstance(planMaintCode, tenantId, userId);
Long maintInstanceId = rMaintInstanceId.getData();
String businessId = maintInstanceId.toString();
if (!R.isSuccess(rMaintInstanceId)) {
return R.fail();
} else {
// 启动工作流
RemoteStartProcess remoteStartProcess = new RemoteStartProcess();
remoteStartProcess.setBusinessId(businessId);
remoteStartProcess.setFlowCode(DmsConstants.DMS_BILLS_MAINT_INSTANCE_WF_CODE);
RemoteStartProcessReturn result = remoteWorkflowService.startWorkFlow(remoteStartProcess);
if (ObjectUtils.isEmpty(result)) {
return R.fail();
} else {
Long taskId = result.getTaskId();
// 【简化方案】异步处理工作流推进,避免死锁
CompletableFuture.runAsync(TtlRunnable.get(() -> {
try {
// 【关键】在异步线程中重新登录相同用户
StpUtil.login(userId, "login");
// 【执行业务】更新保养工单的工作流信息
updateMaintWorkflow(maintInstanceId, taskId);
log.info("保养工单 {} 异步工作流处理完成", maintInstanceId);
} catch (Exception e) {
log.error("保养工单 {} 异步工作流处理失败: {}", maintInstanceId, e.getMessage(), e);
} finally {
// 【清理】清理登录状态,避免线程池复用时的状态污染
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出时的异常
}
// 清理RpcContext
try {
RpcContext.removeContext();
} catch (Exception ignored) {
// 忽略清理时的异常
}
}
}));
return R.ok(1);
}
}
} finally {
// 【主线程清理】确保主线程执行完成后清理登录状态
try {
StpUtil.logout();
} catch (Exception ignored) {
// 忽略登出异常
}
}
}
private R<Long> createMaintInstance(String planMaintCode, String tenantId, Long userId) {
String planMaintCodeS = planMaintCode.replaceAll("\"", "");
DmsPlanMaint dmsPlanMaint = dmsPlanMaintMapper.selectDmsPlanMaintJoinByPlanMaintCode(planMaintCodeS);
List<DmsPlanMaintDetail> planMaintDetails = dmsPlanMaint.getDmsPlanMaintDetailList();
@ -62,11 +137,8 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
dmsBillsMaintInstance.setMaintSupervisor(dmsPlanMaint.getMaintSupervisor());
dmsBillsMaintInstance.setMaintLevel(dmsPlanMaint.getMaintLevel());
Date lubeTime = dmsPlanMaint.getMaintTime();
Long timeLimit = dmsPlanMaint.getTimeLimit();
// dmsBillsMaintInstance.setIsFlag(1l);
// dmsBillsMaintInstance.setWfProcessId(103l);
dmsBillsMaintInstance.setPlanEndTime(new Date(lubeTime.getTime() + timeLimit * 1000l));
//字段没有自动填充,只能代码手动填充
@ -75,15 +147,10 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
int i = dmsBillsMaintInstanceMapper.insert(dmsBillsMaintInstance);
// DmsMaintInstanceActivity dmsMaintInstanceActivity = new DmsMaintInstanceActivity();
// dmsMaintInstanceActivity.setMaintInstanceId(dmsBillsMaintInstance.getMaintInstanceId());
// dmsMaintInstanceActivity.setProcessStepOrder(1L);
// int i1 = dmsMaintInstanceActivityMapper.insertDmsMaintInstanceActivity(dmsMaintInstanceActivity);
batchInsertDmsBillsMaintDetail(dmsPlanMaint, dmsBillsMaintInstance.getMaintInstanceId(), tenantId, userId);
return R.ok(i);
return R.ok(dmsBillsMaintInstance.getMaintInstanceId());
}
@Transactional( rollbackFor = Exception.class )
public void batchInsertDmsBillsMaintDetail(DmsPlanMaint dmsPlanMaint, Long maintInstanceId, String tenantId, Long userId) {
List<DmsPlanMaintDetail> planMaintDetails = dmsPlanMaint.getDmsPlanMaintDetailList();
@ -94,7 +161,6 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
dmsBillsMaintDetail.setMachineId(planMaintDetail.getMachineId());
dmsBillsMaintDetail.setMaintStationId(planMaintDetail.getMaintStationId());
dmsBillsMaintDetail.setMaintStandardId(planMaintDetail.getMaintStandardId());
// dmsBillsMaintDetail.setIsFlag(1L);
dmsBillsMaintDetail.setMaintStatus(1L);//保养状态1待保养 2保养中 3已完成
//字段没有自动填充,只能代码手动填充
@ -111,11 +177,10 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
for (DmsBaseMaintProject project : projects) {
DmsBillsMaintDetailProject billsMaintDetailProject = new DmsBillsMaintDetailProject();
billsMaintDetailProject.setBillsMaintDetailId(detail.getBillsMaintDetailId());
// DmsBaseMaintStation station = dmsBillsMaintDetailMapper.selectMainStation(detail.getStationId());
billsMaintDetailProject.setMaintProjectId(project.getMaintProjectId());
billsMaintDetailProject.setMaintProjectName(project.getMaintProjectName());
billsMaintDetailProject.setMaintProjectDesc(project.getMaintProjectDesc());
billsMaintDetailProject.setMaintProjectStatus("2");//保养项目状态0待保养 1保养完成FIXME:为什么是2
billsMaintDetailProject.setMaintProjectStatus("2");//保养项目状态0待保养 1保养完成
//字段没有自动填充,只能代码手动填充
billsMaintDetailProject.setCreateBy(userId);
@ -123,8 +188,35 @@ public class RemoteMaintInstanceServiceImpl implements RemoteMaintInstanceServic
dmsBillsMaintDetailProjectMapper.insert(billsMaintDetailProject);
}
}
}
private void updateMaintWorkflow(Long businessId, Long taskId) {
try {
// 1. 更新工作流ID
DmsBillsMaintInstance maintInstance = dmsBillsMaintInstanceMapper.selectById(businessId);
if (maintInstance != null) {
maintInstance.setWfDefinitionId(taskId);
dmsBillsMaintInstanceMapper.updateById(maintInstance);
log.info("保养工单 {} 工作流ID更新成功: {}", businessId, taskId);
}
// 2. 推进工作流状态
RemoteCompleteTask completeTask = new RemoteCompleteTask();
completeTask.setTaskId(taskId);
completeTask.setMessage("保养工单启动,自动推进");
// 设置消息类型为非null的List
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system"); // 系统消息
completeTask.setMessageType(messageTypes);
// 【关键】调用工作流推进
remoteWorkflowService.completeTask(completeTask);
log.info("保养工单 {} 工作流推进成功", businessId);
} catch (Exception e) {
log.error("保养工单 {} 工作流更新失败: {}", businessId, e.getMessage(), e);
// 注意:这里不抛出异常,避免影响主流程
}
}
}

@ -202,11 +202,11 @@ public class DmsPlanInspectServiceImpl implements IDmsPlanInspectService {
.setJobName("点巡检计划编号" + planInspectCode + "工单任务")
.setExecutorInfo("stanceInspect")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planInspectCode")
.setExtAttrs(planInspectCode)
.setUserId(LoginHelper.getUserId().toString())
@ -296,11 +296,11 @@ public class DmsPlanInspectServiceImpl implements IDmsPlanInspectService {
.setJobName("点巡检计划编号" + planInspectCode + "工单任务")
.setExecutorInfo("stanceInspect")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planInspectCode")
.setExtAttrs(planInspectCode)
.setUserId(LoginHelper.getUserId().toString())

@ -187,11 +187,11 @@ public class DmsPlanLubeServiceImpl implements IDmsPlanLubeService {
.setJobName("润滑计划编号" + planLubeCode + "工单任务")
.setExecutorInfo("stanceLube")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planLubeCode")
.setExtAttrs(planLubeCode)
.setUserId(LoginHelper.getUserId().toString())
@ -250,11 +250,11 @@ public class DmsPlanLubeServiceImpl implements IDmsPlanLubeService {
.setJobName("润滑计划编号" + planLubeCode + "工单任务")
.setExecutorInfo("stanceLube")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planLubeCode")
.setExtAttrs(planLubeCode)
.setUserId(LoginHelper.getUserId().toString())
@ -273,11 +273,11 @@ public class DmsPlanLubeServiceImpl implements IDmsPlanLubeService {
.setJobName("润滑计划编号" + planLubeCode + "工单任务")
.setExecutorInfo("stanceLube")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planLubeCode")
.setExtAttrs(planLubeCode)
.setUserId(LoginHelper.getUserId().toString())

@ -213,11 +213,11 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
.setJobName("保养计划编号" + planMaintCode + "工单任务")
.setExecutorInfo("stanceMaint")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planMaintCode")
.setExtAttrs(planMaintCode)
.setUserId(LoginHelper.getUserId().toString())
@ -302,11 +302,11 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
.setJobName("保养计划编号" + planMaintCode + "工单任务")
.setExecutorInfo("stanceMaint")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planMaintCode")
.setExtAttrs(planMaintCode)
.setUserId(LoginHelper.getUserId().toString())
@ -322,11 +322,11 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
.setJobName("保养计划编号" + planMaintCode + "工单任务")
.setExecutorInfo("stanceMaint")//执行器名称
.setExecutorTimeout(30)//执行超时时间
.setBlockStrategy(JobBlockStrategyEnum.CONCURRENCY)//阻塞策略:并发
.setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行
.setMaxRetryTimes(2)//最大重试次数
.setTriggerType(TriggerTypeEnum.CRON)//触发器类型cron
.setTriggerInterval(bo.getCronExpression())//间隔时长: cron表达式
.setRetryInterval(3)//重试间隔时长
.setRetryInterval(10)//重试间隔时长
.setArgsStr("planMaintCode")
.setExtAttrs(planMaintCode)
.setUserId(LoginHelper.getUserId().toString())

Loading…
Cancel
Save