From 298ae2fa27c40c87af166000250dda68e878b678 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Fri, 24 Apr 2026 14:50:37 +0800 Subject: [PATCH] =?UTF-8?q?opt:=20AI=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SlitterServiceImpl.java | 258 ++++++++++++------ 1 file changed, 177 insertions(+), 81 deletions(-) diff --git a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/slitter/service/impl/SlitterServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/slitter/service/impl/SlitterServiceImpl.java index 3f1fe7187..e3e55e2f7 100644 --- a/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/slitter/service/impl/SlitterServiceImpl.java +++ b/lms/nladmin-system/src/main/java/org/nl/b_lms/sch/tasks/slitter/service/impl/SlitterServiceImpl.java @@ -1,8 +1,10 @@ package org.nl.b_lms.sch.tasks.slitter.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.nl.b_lms.sch.point.dao.mapper.StIvtCutpointivtMapper; import org.nl.b_lms.sch.tasks.SlitterDownNewTrussTask; @@ -106,6 +108,18 @@ public class SlitterServiceImpl implements SlitterService { * 合单配送 */ public final static String IS_COMBINED_ORDER = "IS_COMBINED_ORDER"; + /** + * 分布式锁KEY 常量 + */ + private static final String LOCK_KEY = "lock:doUpShaftToSlitterByDevice"; + /** + * 锁等待时间 1秒 + */ + private static final long LOCK_WAIT_TIME = 1; + /** + * 锁持有时间 10秒 + */ + private static final long LOCK_LEASE_TIME = 10; @Autowired private BstIvtStockingivtMapper bstIvtStockingivtMapper; @Autowired @@ -2347,51 +2361,96 @@ public class SlitterServiceImpl implements SlitterService { @Override public JSONObject doUpShaftToSlitterByDevice(JSONObject param) { - log.info("手持申请分切上料参数:{}", param); - JSONObject res = new JSONObject(); - res.put("status", HttpStatus.HTTP_OK); - res.put("message", "创建桁架任务成功!"); - RLock open = redissonClient.getLock("lock:doUpShaftToSlitterByDevice"); - boolean openLock = false; + log.info("手持申请分切上料,请求参数:{}", param); + + // 1. 校验必传参数 + checkParam(param); + RLock lock = redissonClient.getLock(LOCK_KEY); + boolean lockAcquired = false; + try { - openLock = open.tryLock(0, TimeUnit.SECONDS); + // 2. 尝试获取分布式锁:等待1s,持有10s + lockAcquired = lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, TimeUnit.SECONDS); + if (!lockAcquired) { + log.error("获取分布式锁失败,请求频繁,参数:{}", param); + throw new BadRequestException("系统繁忙,请稍后再试!"); + } + + // 3. 核心业务逻辑 + executeBusinessLogic(param); + + // 4. 构造成功返回 + return buildSuccessResult("创建桁架任务成功!"); + } catch (InterruptedException e) { - throw new RuntimeException(e); - } - try { - if (openLock) { - // param: area, device_code - String area = param.getString("area"); - String deviceCode = param.getString("device_code"); - StIvtCutpointivt extCode = cutpointivtService.getPintByExtCode(deviceCode, true); - if (ObjectUtil.isEmpty(extCode)) { - throw new BadRequestException("该设备不存在或者被禁用,请检查!"); - } - List cachePoints = slitterMapper.getReadyShaftCachePointByDevice(extCode); - List cutPointList = slitterMapper.getReadyShaftPoint(deviceCode); - if (cachePoints.size() > 0) { - // 在缓存架子上 - doUpShaftToSlitterByNew(param, cachePoints, extCode); - } else if (cutPointList.size() > 0) { - // 在对接位 - // 找到该分切计划的点位 - BstIvtCutpointivt newCutPoint = cutPointList.get(0); - // 创建任务 - JSONObject taskParam = new JSONObject(); - taskParam.put("point_code", newCutPoint.getPoint_code()); - doUpShaftToSlitter(taskParam); - } else { - throw new BadRequestException("没有为设备[" + deviceCode + "]套好轴的位置!"); - } - } else { - throw new BadRequestException("系统繁忙,稍后在试!!"); - } + log.error("获取锁线程中断,参数:{}", param, e); + Thread.currentThread().interrupt(); + throw new RuntimeException("系统异常,请稍后再试"); } finally { - if (openLock) { - open.unlock(); + // 5. 安全释放锁:只有当前线程加的锁才能释放 + if (lockAcquired && lock.isHeldByCurrentThread()) { + lock.unlock(); + log.debug("分布式锁释放成功,key:{}", LOCK_KEY); } } - return res; + } + + /** + * 校验必传参数 + */ + private void checkParam(JSONObject param) { + String area = param.getString("area"); + String deviceCode = param.getString("device_code"); + + if (ObjectUtil.isEmpty(area) || ObjectUtil.isEmpty(deviceCode)) { + log.error("分切上料参数缺失,param:{}", param); + throw new BadRequestException("参数不完整,请检查 area 和 device_code!"); + } + } + + /** + * 执行业务逻辑 + */ + private void executeBusinessLogic(JSONObject param) { + String area = param.getString("area"); + String deviceCode = param.getString("device_code"); + + log.info("开始处理分切上料,设备:{},区域:{}", deviceCode, area); + + // 1. 查询设备信息 + StIvtCutpointivt deviceInfo = cutpointivtService.getPintByExtCode(deviceCode, true); + if (ObjectUtil.isEmpty(deviceInfo)) { + throw new BadRequestException("该设备不存在或已禁用,请检查!"); + } + + // 2. 查询缓存点位 + 可用点位 + List cachePointList = slitterMapper.getReadyShaftCachePointByDevice(deviceInfo); + List cutPointList = slitterMapper.getReadyShaftPoint(deviceCode); + + // 3. 业务分支处理 + if (!cachePointList.isEmpty()) { + log.info("设备{}:轴在缓存架子上,执行缓存上架逻辑", deviceCode); + doUpShaftToSlitterByNew(param, cachePointList, deviceInfo); + } else if (!cutPointList.isEmpty()) { + log.info("设备{}:轴在对接位,执行对接位上架逻辑", deviceCode); + BstIvtCutpointivt cutPoint = cutPointList.get(0); + JSONObject taskParam = new JSONObject(); + taskParam.put("point_code", cutPoint.getPoint_code()); + doUpShaftToSlitter(taskParam); + } else { + log.error("设备{}:未找到套好轴的位置", deviceCode); + throw new BadRequestException("没有为设备[" + deviceCode + "]套好轴的位置!"); + } + } + + /** + * 构建成功返回结果 + */ + private JSONObject buildSuccessResult(String message) { + JSONObject result = new JSONObject(); + result.put("status", HttpStatus.HTTP_OK); + result.put("message", message); + return result; } /** @@ -2402,78 +2461,115 @@ public class SlitterServiceImpl implements SlitterService { * @param device 设备实体 */ public void doUpShaftToSlitterByNew(JSONObject param, List cachePoints, StIvtCutpointivt device) { - List actualPoints = cachePoints; + log.info("开始执行分切缓存上料任务,设备编码:{},缓存点位数量:{}", device.getExt_code(), cachePoints.size()); + + // 1. 点位数量校验 if (cachePoints.size() > 2) { - // todo: 需要过滤(正常不会出现,先不考虑) + log.error("缓存点位数量超过2个,设备:{},点位:{}", device.getExt_code(), cachePoints); throw new BadRequestException("计划冗余,请检查!"); } - // 获取计划数据 - List qzznos = cachePoints.stream().map(Deliverycachepointivt::getQzzno).collect(Collectors.toList()); - List plans = slittingproductionplanService.getByQzzNos(qzznos); - if (plans.isEmpty()) { - throw new BadRequestException("计划不存在!请检查点位:" - + cachePoints.stream().map(Deliverycachepointivt::getPoint_code).collect(Collectors.toList()) - + "的数据!"); + + // 2. 获取气胀轴编号 + List qzznos = cachePoints.stream() + .map(Deliverycachepointivt::getQzzno) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toList()); + + if (qzznos.isEmpty()) { + log.error("缓存点位中未找到有效的卷料号"); + throw new BadRequestException("缓存点位未找到卷料号!"); } - JSONObject taskParam = new JSONObject(); - // 根据计划筛选上下轴任务,并构建任务参数 + + // 3. 查询生产计划 + List plans = slittingproductionplanService.getByQzzNos(qzznos); + if (CollUtil.isEmpty(plans)) { + log.error("未查询到分切计划,卷料号:{}", qzznos); + throw new BadRequestException("计划不存在!请检查点位数据!"); + } + + // 4. 筛选上下轴计划 PdmBiSlittingproductionplan nextUpPlan = plans.stream() .filter(p -> SlitterConstant.SLITTER_SHAFT_UP.equals(p.getUp_or_down())) .findFirst() .orElse(null); + PdmBiSlittingproductionplan nextDownPlan = plans.stream() .filter(p -> SlitterConstant.SLITTER_SHAFT_DOWN.equals(p.getUp_or_down())) .findFirst() .orElse(null); - Deliverycachepointivt upNeedPoint = actualPoints.stream() - .filter(p -> { - assert nextUpPlan != null; - return p.getQzzno().equals(nextUpPlan.getQzzno()); - }) - .findFirst() - .orElse(null); - Deliverycachepointivt downNeedPoint = actualPoints.stream() - .filter(p -> { - assert nextDownPlan != null; - return p.getQzzno().equals(nextDownPlan.getQzzno()); - }) - .findFirst() - .orElse(null); - if (ObjectUtil.isNotEmpty(nextUpPlan) && ObjectUtil.isNotEmpty(nextDownPlan)) { - // 上轴都不会空 - // 双轴任务参数构建 - assert downNeedPoint != null; + + // 5. 匹配对应点位 + Deliverycachepointivt upNeedPoint = null; + if (nextUpPlan != null) { + upNeedPoint = cachePoints.stream() + .filter(p -> nextUpPlan.getQzzno().equals(p.getQzzno())) + .findFirst() + .orElse(null); + } + + Deliverycachepointivt downNeedPoint = null; + if (nextDownPlan != null) { + downNeedPoint = cachePoints.stream() + .filter(p -> nextDownPlan.getQzzno().equals(p.getQzzno())) + .findFirst() + .orElse(null); + } + + // 6. 构建任务参数 + JSONObject taskParam = new JSONObject(); + boolean isDoubleShaft = nextUpPlan != null && nextDownPlan != null; + + if (isDoubleShaft) { + // 双轴任务 + if (downNeedPoint == null || upNeedPoint == null) { + log.error("双轴任务点位缺失,upNeedPoint:{},downNeedPoint:{}", upNeedPoint, downNeedPoint); + throw new BadRequestException("双轴任务点位不完整!"); + } taskParam.put("point_code1", downNeedPoint.getPoint_code()); taskParam.put("point_code2", device.getDown_point_code()); - assert upNeedPoint != null; taskParam.put("point_code3", upNeedPoint.getPoint_code()); taskParam.put("point_code4", device.getUp_point_code()); taskParam.put("vehicle_code1", upNeedPoint.getQzzno()); taskParam.put("vehicle_code2", downNeedPoint.getQzzno()); + log.info("双轴任务构建完成,上轴卷:{},下轴卷:{}", upNeedPoint.getQzzno(), downNeedPoint.getQzzno()); } else { - // 单轴任务参数构建 - if (ObjectUtil.isNotEmpty(nextUpPlan)) { - // 上轴任务 - assert upNeedPoint != null; + // 单轴任务 + if (nextUpPlan != null) { + if (upNeedPoint == null) { + throw new BadRequestException("上轴任务未找到对应缓存点位!"); + } taskParam.put("point_code1", upNeedPoint.getPoint_code()); taskParam.put("point_code2", device.getUp_point_code()); taskParam.put("vehicle_code1", upNeedPoint.getQzzno()); - } else { - // 下轴任务 - assert downNeedPoint != null; + log.info("单上轴任务,卷号:{}", upNeedPoint.getQzzno()); + } else if (nextDownPlan != null) { + if (downNeedPoint == null) { + throw new BadRequestException("下轴任务未找到对应缓存点位!"); + } taskParam.put("point_code1", downNeedPoint.getPoint_code()); taskParam.put("point_code2", device.getDown_point_code()); - taskParam.put("vehicle_code2", downNeedPoint.getQzzno()); + taskParam.put("vehicle_code1", downNeedPoint.getQzzno()); + log.info("单下轴任务,卷号:{}", downNeedPoint.getQzzno()); + } else { + log.error("未找到上轴/下轴类型计划,plans:{}", plans); + throw new BadRequestException("未匹配到有效上下轴计划!"); } } - // 构建任务的其他参数 + // 7. 公共任务参数 taskParam.put("truss_type", "1"); taskParam.put("empty_site", "0"); taskParam.put("task_type", SlitterEnum.TASK_TYPE.code("缓存上空轴任务")); taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA); - taskParam.put("u_containers", plans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList())); - // 创建任务 + + List containers = plans.stream() + .map(PdmBiSlittingproductionplan::getContainer_name) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toList()); + taskParam.put("u_containers", containers); + + // 8. 创建任务 + log.info("最终创建桁架任务参数:{}", taskParam); upShaftTrussNewTask.createTask(taskParam); }