feat(dms): 新增故障报修工单审批和确认功能- 添加审批和确认工单的接口和实现逻辑

- 更新工作流推进机制,增加重试功能
- 优化工单状态和审批状态的处理
- 新增相关常量定义
master
zch 2 weeks ago
parent d45241c20f
commit f464130fd3

@ -111,4 +111,5 @@ public interface RemoteWorkflowService {
* @return IDnull
*/
Long getCurrentTaskIdByInstanceId(Long instanceId);
}

@ -15,6 +15,11 @@ public class DmsConstants {
public static final String DMS_BILLS_FAULT_INSTANCE_STATUS_REPAIRING = "1";//维修中
public static final String DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH = "2";//维修完成
/**故障报修工单审批状态按照PDA标准在PDA实体类DeviceRepair中*/
public static final String DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_PENDING = "1";//待审批
public static final String DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_APPROVED = "2";//审批成功
public static final String DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_REJECTED = "3";//审批失败
/**故障报修工单实例状态*/
public static final String DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_FINISH = "0";//已结束
public static final String DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_EXECUTING = "1";//执行中

@ -14,6 +14,7 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.dms.domain.bo.DmsBillsFaultInstanceBo;
import org.dromara.dms.domain.vo.DmsBillsFaultInstanceVo;
@ -128,6 +129,37 @@ public class DmsBillsFaultInstanceController extends BaseController {
return toAjax(dmsBillsFaultInstanceService.updateWfDefinitionIdById(repairInstanceId, wfDefinitionId));
}
/**
*
*
* @param repairInstanceId ID
* @param approveStatus 2-3-
* @param message
*/
@SaCheckPermission("dms:dmsBillsFaultInstance:approve")
@Log(title = "故障报修工单审批", businessType = BusinessType.UPDATE)
@PostMapping("/approve")
public R<Void> approve(@RequestParam Long repairInstanceId,
@RequestParam String approveStatus,
@RequestParam(required = false) String message) {
return toAjax(dmsBillsFaultInstanceService.approveWorkOrder(repairInstanceId, approveStatus, message));
}
/**
*
*
* @param repairInstanceId ID
* @param confirmResult 1-
*/
@SaCheckPermission("dms:dmsBillsFaultInstance:confirm")
@Log(title = "故障报修工单确认", businessType = BusinessType.UPDATE)
@PostMapping("/confirm")
public R<Void> confirm(@RequestParam Long repairInstanceId,
@RequestParam String confirmResult) {
String confirmUser = LoginHelper.getUsername();
return toAjax(dmsBillsFaultInstanceService.confirmRepairResult(repairInstanceId, confirmResult, confirmUser));
}
// @PostMapping("faultRecordExport")
// public void faultRecordExport(DmsBillsFaultInstance dmsBillsFaultInstance, HttpServletResponse response) throws Exception {
// Map<String, Object> beanParams = new HashMap<>();

@ -96,6 +96,9 @@ public class DmsMobileController extends BaseController {
mobileInstance.setDeviceName(voInstance.getMachineName());
mobileInstance.setDeviceLocation(voInstance.getMachineLocation());
mobileInstance.setDeviceSpec(voInstance.getMachineSpec());
// 设置审批状态字段确保PDA端能获取到审批信息
mobileInstance.setApproveStatus(voInstance.getApproveStatus());
// ID字段类型转换 - Long到String并处理字段映射差异
if (voInstance.getRepairInstanceId() != null) {
@ -159,7 +162,6 @@ public class DmsMobileController extends BaseController {
dictList.add(dict);
}
}
return AjaxResult.success(dictList);
}
@ -238,7 +240,7 @@ public class DmsMobileController extends BaseController {
DeviceBeen deviceBeen = MapstructUtils.convert(dmsBaseDeviceLedger, DeviceBeen.class);
// 手动处理字段映射差异machineId -> deviceId确保类型安全转换
if (dmsBaseDeviceLedger.getMachineId() != null) {
deviceBeen.setDeviceId(dmsBaseDeviceLedger.getMachineId().intValue());
deviceBeen.setDeviceId(dmsBaseDeviceLedger.getMachineId());
}
return AjaxResult.success(deviceBeen);
}
@ -442,8 +444,13 @@ public class DmsMobileController extends BaseController {
@PostMapping("/startRepair")
@RepeatSubmit
public AjaxResult startRepair(@RequestBody DmsFaultInstanceActivityBo dmsFaultInstanceActivity) {
int i = dmsBillsFaultInstanceService.startRepair(dmsFaultInstanceActivity);
return AjaxResult.success(i);
try {
int i = dmsBillsFaultInstanceService.startRepair(dmsFaultInstanceActivity);
return AjaxResult.success(i);
} catch (ServiceException e) {
log.error("开始维修失败:{}", e.getMessage());
return AjaxResult.error(e.getMessage());
}
}
/**
@ -455,18 +462,22 @@ public class DmsMobileController extends BaseController {
@RepeatSubmit
public AjaxResult completeRepair(DmsFaultInstanceActivityBo dmsFaultInstanceActivity,
@RequestParam(value = "files", required = false) List<MultipartFile> files) throws JsonProcessingException {
dmsFaultInstanceActivity.setRepairConfirm("2");
dmsFaultInstanceActivity.setConfirmTime(new Date());
String parts1 = dmsFaultInstanceActivity.getParts1();
ObjectMapper objectMapper = new ObjectMapper();
List<DmsFaultComponentsParts> parts2 = objectMapper.readValue(parts1, new TypeReference<List<DmsFaultComponentsParts>>() {
});
dmsFaultInstanceActivity.setParts(parts2);
List<String> fileUrls = handleFileUploads(files);
dmsFaultInstanceActivity.setFileUrls(fileUrls);
//FIXME:关于工作流相关的本页代码以及调用方法都需测试完善修改
int i = dmsBillsFaultInstanceService.completeRepair(dmsFaultInstanceActivity);
return AjaxResult.success(i);
try {
// 注意这里不再设置repairConfirm因为在Service层会自动设置为0待确认
dmsFaultInstanceActivity.setConfirmTime(new Date());
String parts1 = dmsFaultInstanceActivity.getParts1();
ObjectMapper objectMapper = new ObjectMapper();
List<DmsFaultComponentsParts> parts2 = objectMapper.readValue(parts1, new TypeReference<List<DmsFaultComponentsParts>>() {
});
dmsFaultInstanceActivity.setParts(parts2);
List<String> fileUrls = handleFileUploads(files);
dmsFaultInstanceActivity.setFileUrls(fileUrls);
int i = dmsBillsFaultInstanceService.completeRepair(dmsFaultInstanceActivity);
return AjaxResult.success(i);
} catch (ServiceException e) {
log.error("完成维修失败:{}", e.getMessage());
return AjaxResult.error(e.getMessage());
}
}
@ -490,7 +501,7 @@ public class DmsMobileController extends BaseController {
DmsInspectInstanceDetailMobile detailMobile = MapstructUtils.convert(detailVo, DmsInspectInstanceDetailMobile.class);
// 手动处理字段映射差异machineId -> deviceId
if (detailVo.getMachineId() != null) {
detailMobile.setDeviceId(detailVo.getMachineId().intValue());
detailMobile.setDeviceId(detailVo.getMachineId());
}
detailMobileList.add(detailMobile);
}
@ -509,10 +520,10 @@ public class DmsMobileController extends BaseController {
@RepeatSubmit
public AjaxResult scanInspectInstanceDetail(@Validated DmsBillsInspectInstanceScanBo dmsBillsInspectInstanceScan) {
DmsInspectInstanceDetailVo dmsInspectInstanceDetailVo = dmsBillsInspectInstanceService.scanInspectInstanceDetail(dmsBillsInspectInstanceScan);
// 【关键修复】完全避免使用MapstructUtils自动转换采用手动映射
DmsInspectInstanceDetailMobile dmsInspectInstanceDetailMobile = new DmsInspectInstanceDetailMobile();
// 手动映射基本字段
dmsInspectInstanceDetailMobile.setInstanceDetailId(dmsInspectInstanceDetailVo.getInstanceDetailId());
dmsInspectInstanceDetailMobile.setInspectInstanceId(dmsInspectInstanceDetailVo.getInspectInstanceId());
@ -527,18 +538,18 @@ public class DmsMobileController extends BaseController {
// 手动处理字段映射差异machineId -> deviceId
if (dmsInspectInstanceDetailVo.getMachineId() != null) {
dmsInspectInstanceDetailMobile.setDeviceId(dmsInspectInstanceDetailVo.getMachineId().intValue());
dmsInspectInstanceDetailMobile.setDeviceId(dmsInspectInstanceDetailVo.getMachineId());
}
// 【方案对比实现】处理项目列表:使用流和类型过滤 vs 强制转换
if (dmsInspectInstanceDetailVo.getDmsInspectInstanceDetailProjectList() != null) {
List<DeviceInspectionItem> deviceInspectionItemList = new ArrayList<>();
// 【方案A流和类型过滤 - 类型安全,性能稍低】
List<?> rawProjectList = dmsInspectInstanceDetailVo.getDmsInspectInstanceDetailProjectList();
for (Object projectObj : rawProjectList) {
DeviceInspectionItem deviceInspectionItem = new DeviceInspectionItem();
// 运行时类型检查,支持多种类型
if (projectObj instanceof DmsInspectInstanceDetailProject) {
DmsInspectInstanceDetailProject project = (DmsInspectInstanceDetailProject) projectObj;
@ -550,16 +561,16 @@ public class DmsMobileController extends BaseController {
log.warn("未知的项目类型: {}", projectObj.getClass().getName());
continue; // 跳过未知类型,保证程序稳定性
}
deviceInspectionItemList.add(deviceInspectionItem);
}
dmsInspectInstanceDetailMobile.setDmsInspectInstanceDetailProjectList(deviceInspectionItemList);
}
return AjaxResult.success(dmsInspectInstanceDetailMobile);
}
/**
* DmsInspectInstanceDetailProjectDeviceInspectionItem
*/
@ -569,15 +580,15 @@ public class DmsMobileController extends BaseController {
deviceInspectionItem.setInspectProjectName(project.getInspectProjectName());
deviceInspectionItem.setInspectProjectProperty(project.getInspectProjectProperty());
deviceInspectionItem.setInspectProjectDesc(project.getInspectProjectDesc());
if (project.getInspectProjectResult() != null) {
deviceInspectionItem.setInspectProjectResult(project.getInspectProjectResult().toString());
} else {
// 【PDA适配】确保为null而不是空字符串
deviceInspectionItem.setInspectProjectResult(null);
}
if (project.getDefValue() != null) {
deviceInspectionItem.setDefValue(project.getDefValue().doubleValue());
}
@ -588,7 +599,7 @@ public class DmsMobileController extends BaseController {
deviceInspectionItem.setLowLimit(project.getLowLimit().doubleValue());
}
}
/**
* DmsInspectInstanceDetailProjectVoDeviceInspectionItem
*/
@ -598,17 +609,17 @@ public class DmsMobileController extends BaseController {
deviceInspectionItem.setInspectProjectName(projectVo.getInspectProjectName());
deviceInspectionItem.setInspectProjectProperty(projectVo.getInspectProjectProperty());
deviceInspectionItem.setInspectProjectDesc(projectVo.getInspectProjectDesc());
// 【PDA适配】不设置statusName让PDA端自己计算
// deviceInspectionItem.setStatusName() 由PDA端的getStatusName()方法自动计算
if (projectVo.getInspectProjectResult() != null) {
deviceInspectionItem.setInspectProjectResult(projectVo.getInspectProjectResult().toString());
} else {
// 【PDA适配】确保为null而不是空字符串
deviceInspectionItem.setInspectProjectResult(null);
}
if (projectVo.getDefValue() != null) {
deviceInspectionItem.setDefValue(projectVo.getDefValue().doubleValue());
}
@ -689,7 +700,6 @@ public class DmsMobileController extends BaseController {
DmsBillsMaintDetail result = dmsBillsMaintInstanceService.startMaint(dmsBillsMaintDetail);
// 转换为Mobile对象确保与PDA端兼容
MaintainDetail maintainDetail = MapstructUtils.convert(result, MaintainDetail.class);
// 手动处理字段映射差异machineId -> deviceId
if (result.getMachineId() != null) {
maintainDetail.setDeviceId(result.getMachineId());
@ -706,7 +716,6 @@ public class DmsMobileController extends BaseController {
maintainDetail.setMaintProtocol(result.getMaintProtocol());
maintainDetail.setMaintOperationDescription(result.getMaintOperationDescription());
maintainDetail.setOperationDescription(result.getOperationDescription());
// 处理嵌套对象的字段映射dmsBillsMaintDetailProjectList
if (result.getDmsBillsMaintDetailProjectList() != null) {
List<MaintainProject> maintainProjectList = new ArrayList<>();
@ -730,7 +739,6 @@ public class DmsMobileController extends BaseController {
}
maintainDetail.setDmsBillsMaintDetailProjectList(maintainProjectList);
}
return AjaxResult.success(maintainDetail);
}
@ -744,7 +752,7 @@ public class DmsMobileController extends BaseController {
public AjaxResult completeMaint(@RequestBody DmsBillsMaintDetailMobileBo dmsBillsMaintDetailMobileBo) {
// 将PDA端Bo转换为后端实体处理字段名差异和项目列表
DmsBillsMaintDetail dmsBillsMaintDetail = dmsBillsMaintDetailMobileBo.toEntity();
// 处理项目列表的转换
if (dmsBillsMaintDetailMobileBo.getDmsBillsMaintDetailProjectList() != null) {
List<DmsBillsMaintDetailProjectVo> projectList = new ArrayList<>();
@ -755,7 +763,7 @@ public class DmsMobileController extends BaseController {
}
dmsBillsMaintDetail.setDmsBillsMaintDetailProjectList(projectList);
}
int i = dmsBillsMaintInstanceService.completeMaint(dmsBillsMaintDetail);
return AjaxResult.success(i);
}
@ -771,29 +779,88 @@ public class DmsMobileController extends BaseController {
// @RepeatSubmit
public AjaxResult getNewestLubeInstance(DmsBillsLubeInstanceBo dmsBillsLubeInstance) {
DmsBillsLubeInstanceVo newestLubeInstance = dmsBillsLubeInstanceService.getNewestBillsLubeInstance(dmsBillsLubeInstance);
// 使用MapstructUtils进行高性能对象转换避免时间字段序列化问题
DmsBillsLubeInstanceMobile mobileInstance = MapstructUtils.convert(newestLubeInstance, DmsBillsLubeInstanceMobile.class);
// 【PDA适配】如果查询结果为空直接返回
if (newestLubeInstance == null) {
return AjaxResult.success(null);
}
// 【关键修复】使用手动转换而不是MapstructUtils避免序列化问题
DmsBillsLubeInstanceMobile mobileInstance = new DmsBillsLubeInstanceMobile();
// 手动设置基本字段
mobileInstance.setLubeInstanceId(newestLubeInstance.getLubeInstanceId());
mobileInstance.setPlanLubeId(newestLubeInstance.getPlanLubeId());
mobileInstance.setBillsLubeCode(newestLubeInstance.getBillsLubeCode());
mobileInstance.setLubeGroup(newestLubeInstance.getLubeGroup());
mobileInstance.setLubeSupervisor(newestLubeInstance.getLubeSupervisor());
mobileInstance.setRemark(newestLubeInstance.getRemark());
// 【类型转换】处理状态字段的类型转换String -> Long
if (newestLubeInstance.getLubeLevel() != null) {
try {
mobileInstance.setLubeLevel(Long.valueOf(newestLubeInstance.getLubeLevel()));
} catch (NumberFormatException e) {
log.warn("润滑级别转换失败: {}", newestLubeInstance.getLubeLevel());
mobileInstance.setLubeLevel(null);
}
}
if (newestLubeInstance.getLubeStatus() != null) {
try {
mobileInstance.setLubeStatus(Long.valueOf(newestLubeInstance.getLubeStatus()));
} catch (NumberFormatException e) {
log.warn("润滑状态转换失败: {}", newestLubeInstance.getLubeStatus());
mobileInstance.setLubeStatus(null);
}
}
// 处理嵌套对象的字段映射dmsBillsLubeDetailList
if (newestLubeInstance.getDmsBillsLubeDetailList() != null) {
List<LubricationDetail> lubricationDetailList = new ArrayList<>();
for (var detailVo : newestLubeInstance.getDmsBillsLubeDetailList()) {
LubricationDetail lubricationDetail = MapstructUtils.convert(detailVo, LubricationDetail.class);
LubricationDetail lubricationDetail = new LubricationDetail();
// 手动设置字段,确保类型匹配
lubricationDetail.setBillsLubeDetailId(detailVo.getBillsLubeDetailId());
lubricationDetail.setLubeInstanceId(detailVo.getLubeInstanceId());
lubricationDetail.setLubeStationId(detailVo.getLubeStationId());
lubricationDetail.setLubeStandardId(detailVo.getLubeStandardId());
lubricationDetail.setOperationDescription(detailVo.getOperationDescription());
// 手动处理字段映射差异machineId -> deviceId
if (detailVo.getMachineId() != null) {
lubricationDetail.setDeviceId(detailVo.getMachineId());
}
// 处理其他字段映射machineCode -> deviceCode, machineName -> deviceName
lubricationDetail.setDeviceCode(detailVo.getMachineCode());
lubricationDetail.setDeviceName(detailVo.getMachineName());
lubricationDetail.setTypeName(detailVo.getDeviceTypeName());
lubricationDetail.setLubeStationName(detailVo.getLubeStationName());
lubricationDetail.setLubeProtocol(detailVo.getLubeProtocol());
lubricationDetail.setLubeOperationDescription(detailVo.getLubeOperationDescription());
// 【新增】添加润滑标准编码字段的映射
lubricationDetail.setLubeStandardCode(detailVo.getLubeStandardCode());
// 【类型转换】处理维护状态字段的类型转换String -> Long
if (detailVo.getMaintStatus() != null) {
try {
lubricationDetail.setMaintStatus(Long.valueOf(detailVo.getMaintStatus()));
} catch (NumberFormatException e) {
log.warn("润滑明细维护状态转换失败: {}", detailVo.getMaintStatus());
lubricationDetail.setMaintStatus(null);
}
} else {
lubricationDetail.setMaintStatus(null);
}
lubricationDetailList.add(lubricationDetail);
}
mobileInstance.setDmsBillsLubeDetailList(lubricationDetailList);
}
// 注意润滑Mobile类中的时间字段已被注释无需格式化
// 如果将来启用时间字段,请添加相应的格式化方法
// 【PDA兼容性】直接返回标准的AjaxResult让Spring Boot自动序列化为JSON
return AjaxResult.success(mobileInstance);
}
@ -821,5 +888,4 @@ public class DmsMobileController extends BaseController {
return AjaxResult.success(i);
}
}

@ -117,5 +117,25 @@ public interface IDmsBillsFaultInstanceService {
* @param wfDefinitionId ID
* @return truefalse
*/
public Boolean updateWfDefinitionIdById(Long repairInstanceId, Long wfDefinitionId);
Boolean updateWfDefinitionIdById(Long repairInstanceId, Long wfDefinitionId);
/**
*
*
* @param repairInstanceId ID
* @param approveStatus 2-3-
* @param message
* @return
*/
Boolean approveWorkOrder(Long repairInstanceId, String approveStatus, String message);
/**
*
*
* @param repairInstanceId ID
* @param confirmResult 1-
* @param confirmUser
* @return
*/
Boolean confirmRepairResult(Long repairInstanceId, String confirmResult, String confirmUser);
}

@ -65,7 +65,7 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
private final IDmsInstanceFileService DmsInstanceFileService;
@DubboReference(timeout = 15000, retries = 1)
@DubboReference(timeout = 30000, retries = 2)
private final RemoteWorkflowService remoteWorkflowService;
private final DmsFaultInstanceActivityMapper dmsFaultInstanceActivityMapper;
@ -185,6 +185,8 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
add.setBillsFaultCode(Seq.getId(Seq.dmsBillsFaultInstanceSeqType, Seq.dmsBillsFaultInstanceSeqCode));
// 设置报修状态为待维修
add.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_TO_REPAIR);
// 设置审批状态为待审批按照PDA标准
add.setApproveStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_PENDING);
// 设置实例类型为手动录入
add.setInstanceType(DmsConstants.DMS_BILLS_FAULT_INSTANCE_TYPE_MAUAL);
@ -193,12 +195,16 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
bo.setRepairInstanceId(add.getRepairInstanceId());
}
//FIXME:工作流相关
//工作流相关:自动启动工作流
RemoteStartProcess remoteStartProcess = new RemoteStartProcess();
remoteStartProcess.setFlowCode(DmsConstants.DMS_BILLS_FAULT_INSTANCE_WF_CODE);
remoteStartProcess.setBusinessId(add.getRepairInstanceId().toString());
RemoteStartProcessReturn remoteStartProcessReturn = remoteWorkflowService.startWorkFlow(remoteStartProcess);
Long taskId = remoteStartProcessReturn.getTaskId();
Long processInstanceId = remoteStartProcessReturn.getProcessInstanceId();
// // 更新工作流实例ID
// add.setWfDefinitionId(processInstanceId);
// ** 异步线程上下文传递【核心问题】 **
// 在主线程中,用户的登录信息(Token)是存放在一个叫 ThreadLocal 的"线程口袋"里的。
@ -214,14 +220,37 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
try {
// 3. 【设置上下文】: 在子线程任务开始时,立刻用 StpUtil.setTokenValue() 把传递过来的Token放进子线程自己的"口袋"。
StpUtil.setTokenValue(tokenValue);
// 4. 【执行业务】: 现在子线程就像登录过一样可以带着Token去调用其他需要权限的服务了。
updateWorkFlow(add, taskId);
// 4. 【延迟执行】: 稍微延迟,确保主事务完全提交
Thread.sleep(100);
// 5. 【重试机制】: 最多重试3次每次间隔递增
int maxRetries = 3;
for (int i = 0; i < maxRetries; i++) {
try {
// 执行业务现在子线程就像登录过一样可以带着Token去调用其他需要权限的服务了
updateWorkFlow(add, taskId, processInstanceId);
log.info("异步工作流推进成功repairInstanceId: {}, 重试次数: {}", add.getRepairInstanceId(), i);
break; // 成功则退出重试循环
} catch (Exception retryException) {
log.warn("异步工作流推进失败repairInstanceId: {}, 重试次数: {}/{}, 错误: {}",
add.getRepairInstanceId(), i + 1, maxRetries, retryException.getMessage());
if (i == maxRetries - 1) {
// 最后一次重试失败,记录错误
log.error("异步工作流推进最终失败repairInstanceId: {}, 请手动处理", add.getRepairInstanceId(), retryException);
// TODO: 可以考虑记录到失败表,后续补偿处理
} else {
// 等待后重试,递增延迟时间
Thread.sleep((i + 1) * 1000);
}
}
}
} catch (Exception e) {
// 简单记录错误,不影响主流程
System.err.println("异步更新工作流失败repairInstanceId: " + add.getRepairInstanceId() + ", 错误: " + e.getMessage());
// 可以考虑记录到失败表,后续补偿处理
log.error("异步更新工作流异常repairInstanceId: {}", add.getRepairInstanceId(), e);
}
}));
// 创建故障实例活动对象
DmsFaultInstanceActivity dmsFaultInstanceActivity = new DmsFaultInstanceActivity();
// 设置维修实例ID
@ -242,7 +271,7 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
if (add.getOutsourcingId() != null) {
dmsFaultInstanceActivity.setOutsourcingId(add.getOutsourcingId());
}
// 设置处理状态为待领取
// 设置处理状态为待审批
dmsFaultInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_TO_PICK);
// 设置流程步骤顺序
dmsFaultInstanceActivity.setProcessStepOrder(1l);
@ -256,29 +285,326 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
return flag;
}
/**
*
*
* @param repairInstanceId ID
* @param approveStatus 2-3-
* @param message
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public Boolean approveWorkOrder(Long repairInstanceId, String approveStatus, String message) {
// 查询工单信息
DmsBillsFaultInstance workOrder = baseMapper.selectById(repairInstanceId);
if (workOrder == null) {
throw new ServiceException("工单不存在");
}
// 检查当前状态是否可以审批(必须是待审批状态)
if (!DmsConstants.DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_PENDING.equals(workOrder.getApproveStatus())) {
throw new ServiceException("工单当前状态不允许审批");
}
// 更新审批状态
workOrder.setApproveStatus(approveStatus);
if (DmsConstants.DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_APPROVED.equals(approveStatus)) {
// 审批通过:保持待维修状态
workOrder.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_TO_REPAIR);
} else if (DmsConstants.DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_REJECTED.equals(approveStatus)) {
// 审批拒绝:设置为维修完成状态(终止工单)
workOrder.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH);
}
// 更新工单状态
boolean updateResult = baseMapper.updateById(workOrder) > 0;
if (updateResult && workOrder.getWfDefinitionId() != null) {
// 推进工作流
Long currentTaskId = remoteWorkflowService.getCurrentTaskIdByInstanceId(workOrder.getWfDefinitionId());
if (currentTaskId != null) {
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
remoteCompleteTask.setTaskId(currentTaskId);
remoteCompleteTask.setMessage(message);
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system");
remoteCompleteTask.setMessageType(messageTypes);
// 设置工作流变量 - approveStatus用于互斥网关判断
Map<String, Object> variables = new HashMap<>();
variables.put("approveStatus", approveStatus);
remoteCompleteTask.setVariables(variables);
remoteWorkflowService.completeTask(remoteCompleteTask);
}
}
return updateResult;
}
/**
*
*
* @param dmsFaultInstanceActivity
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public int startRepair(DmsFaultInstanceActivityBo dmsFaultInstanceActivity) {
// 根据维修实例ID查询故障实例信息
DmsBillsFaultInstance dmsBillsFaultInstance = baseMapper.selectById(dmsFaultInstanceActivity.getRepairInstanceId());
if (dmsBillsFaultInstance == null) {
throw new ServiceException("工单不存在");
}
// 检查审批状态按照PDA标准只有状态为"2"审批成功才可以开始维修)
if (!DmsConstants.DMS_BILLS_FAULT_INSTANCE_APPROVE_STATUS_APPROVED.equals(dmsBillsFaultInstance.getApproveStatus())) {
throw new ServiceException("工单未审批通过,无法开始维修");
}
// 检查工单状态
String dmsBillsStatus = dmsBillsFaultInstance.getBillsStatus();
if (!dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_TO_REPAIR)) {
throw new ServiceException("工单状态不允许开始维修");
}
// 获取当前日期和登录用户名
Date currentDate = new Date();
String userName = LoginHelper.getLoginUser() == null ? LoginHelper.getUsername() : LoginHelper.getLoginUser().getNickname();
// 设置工单状态为维修中
dmsBillsFaultInstance.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_REPAIRING);
// 设置实际开始时间
dmsBillsFaultInstance.setRealBeginTime(currentDate);
// 推进工作流
if (dmsBillsFaultInstance.getWfDefinitionId() != null) {
Long currentTaskId = remoteWorkflowService.getCurrentTaskIdByInstanceId(dmsBillsFaultInstance.getWfDefinitionId());
if (currentTaskId != null) {
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
remoteCompleteTask.setTaskId(currentTaskId);
remoteCompleteTask.setMessage("开始维修");
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system");
remoteCompleteTask.setMessageType(messageTypes);
boolean b = remoteWorkflowService.completeTask(remoteCompleteTask);
if (!b) {
throw new ServiceException("工作流推进失败");
}
}
}
// 更新工单状态
baseMapper.updateById(dmsBillsFaultInstance);
// 设置维修实例活动记录
dmsFaultInstanceActivity.setRepairInstanceId(dmsBillsFaultInstance.getRepairInstanceId());
dmsFaultInstanceActivity.setMachineId(dmsBillsFaultInstance.getMachineId());
dmsFaultInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_EXECUTING);
dmsFaultInstanceActivity.setProcessStepOrder(2L);
dmsFaultInstanceActivity.setStartTime(currentDate);
dmsFaultInstanceActivity.setHandleUserId(LoginHelper.getUserId());
dmsFaultInstanceActivity.setHandleBy(userName);
dmsFaultInstanceActivity.setHandleTime(currentDate);
// 插入新的故障实例活动记录
boolean result = dmsFaultInstanceActivityService.insertByBo(dmsFaultInstanceActivity);
return result ? 1 : 0;
}
/**
*
*
* @param dmsFaultInstanceActivity
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public int completeRepair(DmsFaultInstanceActivityBo dmsFaultInstanceActivity) {
// 批量插入实例的附件文件信息
batchInsertInstanceAfterFiles(dmsFaultInstanceActivity.getFileUrls(), dmsFaultInstanceActivity.getInstanceActivityId());
// 获取需要插入的备件列表
List<DmsFaultComponentsParts> parts = dmsFaultInstanceActivity.getParts();
if (!CollectionUtils.isEmpty(parts)) {
for (DmsFaultComponentsParts part : parts) {
part.setFaultId(dmsFaultInstanceActivity.getRepairInstanceId());
}
dmsFaultInstanceActivityMapper.insertParts(parts);
}
// 根据维修实例ID查询对应的工单实例
DmsBillsFaultInstance dmsBillsFaultInstance = baseMapper.selectById(dmsFaultInstanceActivity.getRepairInstanceId());
if (dmsBillsFaultInstance == null) {
throw new ServiceException("工单不存在");
}
// 检查工单状态
String dmsBillsStatus = dmsBillsFaultInstance.getBillsStatus();
if (!dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_REPAIRING)) {
throw new ServiceException("工单状态不允许完成维修,请先开始维修");
}
// 获取当前日期和时间
Date currentDate = new Date();
String userName = LoginHelper.getLoginUser() == null ? LoginHelper.getUsername() : LoginHelper.getLoginUser().getNickname();
// 设置工单状态为维修完成,确认状态为待确认
dmsBillsFaultInstance.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH);
dmsBillsFaultInstance.setRealEndTime(currentDate);
dmsBillsFaultInstance.setRepairConfirm("0"); // 设置为待确认状态
// 推进工作流
if (dmsBillsFaultInstance.getWfDefinitionId() != null) {
Long currentTaskId = remoteWorkflowService.getCurrentTaskIdByInstanceId(dmsBillsFaultInstance.getWfDefinitionId());
if (currentTaskId != null) {
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
remoteCompleteTask.setTaskId(currentTaskId);
remoteCompleteTask.setMessage("完成维修");
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system");
remoteCompleteTask.setMessageType(messageTypes);
boolean b = remoteWorkflowService.completeTask(remoteCompleteTask);
if (!b) {
throw new ServiceException("工作流推进失败");
}
}
}
// 更新工单状态
baseMapper.updateById(dmsBillsFaultInstance);
// 设置工单活动状态为已完成,并记录结束时间和维修人员
dmsFaultInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_FINISH);
dmsFaultInstanceActivity.setEndTime(currentDate);
dmsFaultInstanceActivity.setRepairer(userName);
// 更新故障实例活动记录
DmsFaultInstanceActivity faultInstanceActivity = MapstructUtils.convert(dmsFaultInstanceActivity, DmsFaultInstanceActivity.class);
int i = dmsFaultInstanceActivityMapper.updateById(faultInstanceActivity);
return i;
}
/**
*
*
* @param repairInstanceId ID
* @param confirmResult 1-
* @param confirmUser
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public Boolean confirmRepairResult(Long repairInstanceId, String confirmResult, String confirmUser) {
// 查询工单信息
DmsBillsFaultInstance workOrder = baseMapper.selectById(repairInstanceId);
if (workOrder == null) {
throw new ServiceException("工单不存在");
}
// 检查当前状态是否可以确认
if (!DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH.equals(workOrder.getBillsStatus())) {
throw new ServiceException("工单尚未完成维修,无法确认");
}
if (!"0".equals(workOrder.getRepairConfirm())) {
throw new ServiceException("工单已经确认过了");
}
// 更新确认状态
workOrder.setRepairConfirm(confirmResult);
workOrder.setConfirmUser(confirmUser);
workOrder.setConfirmTime(new Date());
// 推进工作流到最终完成状态
if (workOrder.getWfDefinitionId() != null) {
Long currentTaskId = remoteWorkflowService.getCurrentTaskIdByInstanceId(workOrder.getWfDefinitionId());
if (currentTaskId != null) {
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
remoteCompleteTask.setTaskId(currentTaskId);
remoteCompleteTask.setMessage("主管确认完成");
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system");
remoteCompleteTask.setMessageType(messageTypes);
// 设置工作流变量 - repairConfirm用于互斥网关判断
// 确认通过传0确认不通过传1
Map<String, Object> variables = new HashMap<>();
if ("1".equals(confirmResult)) {
// 确认完成 -> 工作流变量设为0确认通过
variables.put("repairConfirm", "0");
} else {
// 其他情况 -> 工作流变量设为1确认不通过
variables.put("repairConfirm", "1");
}
remoteCompleteTask.setVariables(variables);
remoteWorkflowService.completeTask(remoteCompleteTask);
}
}
return baseMapper.updateById(workOrder) > 0;
}
/**
*
* @param dmsBillsFaultInstance
* @param dmsBillsFaultInstance
* @param taskId ID
* @param processInstanceId ID
* @return
*/
private Boolean updateWorkFlow(DmsBillsFaultInstance dmsBillsFaultInstance, Long taskId){
dmsBillsFaultInstance.setWfDefinitionId(taskId);
private Boolean updateWorkFlow(DmsBillsFaultInstance dmsBillsFaultInstance, Long taskId, Long processInstanceId){
try {
// 1. 首先更新工单的工作流实例ID确保关联关系建立
dmsBillsFaultInstance.setWfDefinitionId(processInstanceId);
boolean updateResult = baseMapper.updateById(dmsBillsFaultInstance) > 0;
if (!updateResult) {
log.error("更新工单工作流实例ID失败repairInstanceId: {}, processInstanceId: {}",
dmsBillsFaultInstance.getRepairInstanceId(), processInstanceId);
return false;
}
log.info("成功更新工单工作流实例IDrepairInstanceId: {}, processInstanceId: {}",
dmsBillsFaultInstance.getRepairInstanceId(), processInstanceId);
// 2. 然后推进工作流(工单创建后自动推进到审批节点)
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
// 必填字段
remoteCompleteTask.setTaskId(taskId);
remoteCompleteTask.setMessage("自动推进");
// 关键设置messageType为非null的List解决原始错误
remoteCompleteTask.setMessage("工单创建完成,自动推进到审批节点");
// 设置消息类型
List<String> messageTypes = new ArrayList<>();
messageTypes.add("system"); // 系统消息
messageTypes.add("system");
remoteCompleteTask.setMessageType(messageTypes);
boolean b = remoteWorkflowService.completeTask(remoteCompleteTask);
if (!b) {
// 设置工作流变量(如果需要)
Map<String, Object> variables = new HashMap<>();
variables.put("businessId", dmsBillsFaultInstance.getRepairInstanceId().toString());
variables.put("initiator", LoginHelper.getUsername());
remoteCompleteTask.setVariables(variables);
boolean completeResult = remoteWorkflowService.completeTask(remoteCompleteTask);
if (!completeResult) {
log.error("工作流推进失败repairInstanceId: {}, taskId: {}",
dmsBillsFaultInstance.getRepairInstanceId(), taskId);
return false;
}
log.info("工作流推进成功repairInstanceId: {}, taskId: {}",
dmsBillsFaultInstance.getRepairInstanceId(), taskId);
return true;
} catch (Exception e) {
log.error("更新工作流异常repairInstanceId: {}, taskId: {}, processInstanceId: {}",
dmsBillsFaultInstance.getRepairInstanceId(), taskId, processInstanceId, e);
return false;
}else {
return baseMapper.updateById(dmsBillsFaultInstance) > 0;
}
}
@ -481,201 +807,6 @@ public class DmsBillsFaultInstanceServiceImpl implements IDmsBillsFaultInstanceS
}
}
/**
*
*
* @param dmsFaultInstanceActivity
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public int startRepair(DmsFaultInstanceActivityBo dmsFaultInstanceActivity) {
// 定义一个布尔变量b用于存储更新结果
Boolean b = false;
// 根据维修实例ID查询故障实例信息
DmsBillsFaultInstance dmsBillsFaultInstance = baseMapper
.selectFaultInstanceJoinFirstById(dmsFaultInstanceActivity.getRepairInstanceId());//join 第一步activity
// 获取工单状态
String dmsBillsStatus = dmsBillsFaultInstance.getBillsStatus();
// 如果工单状态为已完成,抛出异常
if (dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH)) {//维修完成
throw new ServiceException("已经维修完成");
}
// 获取当前日期和登录用户名
Date currentDate = new Date();
String userName = LoginHelper.getLoginUser()==null ? LoginHelper.getUsername() :LoginHelper.getLoginUser().getNickname();
// 如果工单状态为待维修
if (dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_TO_REPAIR)) {//待维修
// 设置工单状态为维修中
dmsBillsFaultInstance.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_REPAIRING);
// 设置实际开始时间
dmsBillsFaultInstance.setRealBeginTime(currentDate);
//启动工作流
Long taskId = getOrCreateTaskId(dmsBillsFaultInstance);
// ** 异步线程上下文传递【核心问题】 **
// 在主线程中,用户的登录信息(Token)是存放在一个叫 ThreadLocal 的"线程口袋"里的。
// 当我们使用 CompletableFuture.runAsync() 开启一个异步线程(子线程)时,
// 这个"口袋"里的东西默认是不会被带到子线程去的。
//
// ** 【解决方案】 **
// 1. 【捕获Token】: 在主线程里,我们先用 StpUtil.getTokenValue() 把Token拿出来存好。
final String tokenValue = StpUtil.getTokenValue();
// 2. 【传递与恢复】: 使用 TtlRunnable (TransmittableThreadLocal Runnable) 包装我们的异步任务。
// 它就像一个特殊的"接力棒",能在线程切换时把主线程"口袋"里的东西包括Token传递给子线程。
CompletableFuture.runAsync(TtlRunnable.get(() -> {
try {
// 3. 【设置上下文】: 在子线程任务开始时,立刻用 StpUtil.setTokenValue() 把传递过来的Token放进子线程自己的"口袋"。
StpUtil.setTokenValue(tokenValue);
// 4. 【执行业务】: 现在子线程就像登录过一样可以带着Token去调用其他需要权限的服务了。
updateWorkFlow(dmsBillsFaultInstance, taskId);
} catch (Exception e) {
// 简单记录错误,不影响主流程
System.err.println("异步更新工作流失败repairInstanceId: " + dmsBillsFaultInstance.getRepairInstanceId() + ", 错误: " + e.getMessage());
// 可以考虑记录到失败表,后续补偿处理
}
}));
// 设置维修实例ID
dmsFaultInstanceActivity.setRepairInstanceId(dmsBillsFaultInstance.getRepairInstanceId());
// FIXME: 工作流相关代码(暂时注释掉)
// dmsFaultInstanceActivity.setProcessActivityId(WfConstants.WF_BILLS_FAULT_INSTANCE_PROCESS_ACTIVITY_SECOND_ID);
// 设置机器ID
dmsFaultInstanceActivity.setMachineId(dmsBillsFaultInstance.getMachineId());
// 设置处理状态为执行中
dmsFaultInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_EXECUTING);
// 设置步骤顺序
dmsFaultInstanceActivity.setProcessStepOrder(2L);
// 设置开始时间
dmsFaultInstanceActivity.setStartTime(currentDate);
// 设置处理用户ID
dmsFaultInstanceActivity.setHandleUserId(LoginHelper.getUserId());
// 设置处理人名称
dmsFaultInstanceActivity.setHandleBy(userName);
// 设置处理时间
dmsFaultInstanceActivity.setHandleTime(currentDate);
// 插入新的故障实例活动记录
b = dmsFaultInstanceActivityService.insertByBo(dmsFaultInstanceActivity);
// 创建第一个实例活动对象并设置其属性
DmsFaultInstanceActivityBo firstInstanceActivity = new DmsFaultInstanceActivityBo();
firstInstanceActivity.setInstanceActivityId(dmsBillsFaultInstance.getInstanceActivityId());
// 设置处理状态为已完成
firstInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_FINISH);
// 设置结束时间
firstInstanceActivity.setEndTime(currentDate);
// FIXME: 需重新梳理代码dmsFaultInstanceActivityService
// 更新第一个实例活动记录
dmsFaultInstanceActivityService.updateByBo(firstInstanceActivity);
} else {// 如果工单状态为维修中
// 更新故障实例活动记录
b = dmsFaultInstanceActivityService.updateByBo(dmsFaultInstanceActivity);
}
// 返回结果1表示成功
return b ? 1 : 0;
}
// startRepair方法内提取的获取或创建taskId的方法
private Long getOrCreateTaskId(DmsBillsFaultInstance dmsBillsFaultInstance) {
Long taskId = dmsBillsFaultInstance.getWfDefinitionId();
if (StringUtils.isNull(taskId)) {
// 启动工作流
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setFlowCode(DmsConstants.DMS_BILLS_FAULT_INSTANCE_WF_CODE);
String businessId = dmsBillsFaultInstance.getRepairInstanceId().toString();
startProcess.setBusinessId(businessId);
RemoteStartProcessReturn remoteStartProcessReturn = remoteWorkflowService.startWorkFlow(startProcess);
taskId = remoteStartProcessReturn.getTaskId();
if (StringUtils.isNull(taskId)) {
throw new ServiceException("流程启动失败");
}
}
return taskId;
}
/**
*
*
* @param dmsFaultInstanceActivity
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public int completeRepair(DmsFaultInstanceActivityBo dmsFaultInstanceActivity) {
// 批量插入实例的附件文件信息
batchInsertInstanceAfterFiles(dmsFaultInstanceActivity.getFileUrls(),dmsFaultInstanceActivity.getInstanceActivityId());
// 获取需要插入的备件列表
List<DmsFaultComponentsParts> parts = dmsFaultInstanceActivity.getParts();
// 如果备件列表不为空则设置每个备件的故障ID并插入数据库
if (!CollectionUtils.isEmpty(parts)){
for (DmsFaultComponentsParts part : parts) {
part.setFaultId(dmsFaultInstanceActivity.getRepairInstanceId());
}
dmsFaultInstanceActivityMapper.insertParts(parts);
}
// 根据维修实例ID查询对应的工单实例
DmsBillsFaultInstanceVo dmsBillsFaultInstance = this.
queryById(dmsFaultInstanceActivity.getRepairInstanceId());
// 获取当前工单的状态
String dmsBillsStatus = dmsBillsFaultInstance.getBillsStatus();
// 如果状态为已完成,抛出异常提示已经维修完成
if (dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH)) {//维修完成
throw new ServiceException("已经维修完成");
}
// 如果状态为待维修,抛出异常提示请先开始维修
if (dmsBillsStatus.equals(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_TO_REPAIR)) {//待维修
throw new ServiceException("请先开始维修");
}
// 获取当前日期和时间
Date currentDate = new Date();
// 获取当前登录用户的用户名或昵称
String userName = LoginHelper.getLoginUser()==null ? LoginHelper.getUsername() :LoginHelper.getLoginUser().getNickname();
// 设置工单状态为已完成,并记录实际结束时间
dmsBillsFaultInstance.setBillsStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_STATUS_FINISH);
dmsBillsFaultInstance.setRealEndTime(currentDate);
// 将工单实例转换为数据库实体对象并更新数据库
DmsBillsFaultInstance faultInstance = MapstructUtils.convert(dmsBillsFaultInstance, DmsBillsFaultInstance.class);
if(StringUtils.isNull(dmsBillsFaultInstance.getWfDefinitionId())){
throw new ServiceException("流程未启动");
}else{
//FIXME:完成第一步,待测试待完善
RemoteCompleteTask remoteCompleteTask = new RemoteCompleteTask();
remoteCompleteTask.setTaskId(dmsBillsFaultInstance.getWfDefinitionId());
remoteCompleteTask.setMessage("同意");
remoteWorkflowService.completeTask(remoteCompleteTask);
baseMapper.updateById(faultInstance);
// 设置工单活动状态为已完成,并记录结束时间和维修人员
dmsFaultInstanceActivity.setProcessHandleStatus(DmsConstants.DMS_BILLS_FAULT_INSTANCE_ACTIVITY_HANDLE_STATUS_FINISH);
dmsFaultInstanceActivity.setEndTime(currentDate);
dmsFaultInstanceActivity.setRepairer(userName);
// 将工单活动实例转换为数据库实体对象并更新数据库
DmsFaultInstanceActivity faultInstanceActivity = MapstructUtils.convert(dmsFaultInstanceActivity, DmsFaultInstanceActivity.class);
int i = dmsFaultInstanceActivityMapper.updateById(faultInstanceActivity);
// 返回更新操作影响的行数
return i;
}
}
public void batchInsertInstanceAfterFiles(List<String> fileUrls, Long instanceActivityId) {
// 判断文件URL列表是否不为空且非空集合
if (fileUrls != null && !fileUrls.isEmpty()) {

Loading…
Cancel
Save