opt: AI优化结构

This commit is contained in:
2026-04-24 14:50:37 +08:00
parent be3dce46f2
commit 298ae2fa27

View File

@@ -1,8 +1,10 @@
package org.nl.b_lms.sch.tasks.slitter.service.impl; 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.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.nl.b_lms.sch.point.dao.mapper.StIvtCutpointivtMapper; import org.nl.b_lms.sch.point.dao.mapper.StIvtCutpointivtMapper;
import org.nl.b_lms.sch.tasks.SlitterDownNewTrussTask; 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"; 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 @Autowired
private BstIvtStockingivtMapper bstIvtStockingivtMapper; private BstIvtStockingivtMapper bstIvtStockingivtMapper;
@Autowired @Autowired
@@ -2347,51 +2361,96 @@ public class SlitterServiceImpl implements SlitterService {
@Override @Override
public JSONObject doUpShaftToSlitterByDevice(JSONObject param) { public JSONObject doUpShaftToSlitterByDevice(JSONObject param) {
log.info("手持申请分切上料参数:{}", param); log.info("手持申请分切上料,请求参数:{}", param);
JSONObject res = new JSONObject();
res.put("status", HttpStatus.HTTP_OK); // 1. 校验必传参数
res.put("message", "创建桁架任务成功!"); checkParam(param);
RLock open = redissonClient.getLock("lock:doUpShaftToSlitterByDevice"); RLock lock = redissonClient.getLock(LOCK_KEY);
boolean openLock = false; boolean lockAcquired = false;
try { try {
openLock = open.tryLock(0, TimeUnit.SECONDS); // 2. 尝试获取分布式锁等待1s持有10s
} catch (InterruptedException e) { lockAcquired = lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, TimeUnit.SECONDS);
throw new RuntimeException(e); if (!lockAcquired) {
log.error("获取分布式锁失败,请求频繁,参数:{}", param);
throw new BadRequestException("系统繁忙,请稍后再试!");
} }
try {
if (openLock) { // 3. 核心业务逻辑
// param: area, device_code executeBusinessLogic(param);
// 4. 构造成功返回
return buildSuccessResult("创建桁架任务成功!");
} catch (InterruptedException e) {
log.error("获取锁线程中断,参数:{}", param, e);
Thread.currentThread().interrupt();
throw new RuntimeException("系统异常,请稍后再试");
} finally {
// 5. 安全释放锁:只有当前线程加的锁才能释放
if (lockAcquired && lock.isHeldByCurrentThread()) {
lock.unlock();
log.debug("分布式锁释放成功key{}", LOCK_KEY);
}
}
}
/**
* 校验必传参数
*/
private void checkParam(JSONObject param) {
String area = param.getString("area"); String area = param.getString("area");
String deviceCode = param.getString("device_code"); String deviceCode = param.getString("device_code");
StIvtCutpointivt extCode = cutpointivtService.getPintByExtCode(deviceCode, true);
if (ObjectUtil.isEmpty(extCode)) { if (ObjectUtil.isEmpty(area) || ObjectUtil.isEmpty(deviceCode)) {
throw new BadRequestException("该设备不存在或者被禁用,请检查!"); log.error("分切上料参数缺失param{}", param);
throw new BadRequestException("参数不完整,请检查 area 和 device_code");
} }
List<Deliverycachepointivt> cachePoints = slitterMapper.getReadyShaftCachePointByDevice(extCode); }
/**
* 执行业务逻辑
*/
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<Deliverycachepointivt> cachePointList = slitterMapper.getReadyShaftCachePointByDevice(deviceInfo);
List<BstIvtCutpointivt> cutPointList = slitterMapper.getReadyShaftPoint(deviceCode); List<BstIvtCutpointivt> cutPointList = slitterMapper.getReadyShaftPoint(deviceCode);
if (cachePoints.size() > 0) {
// 在缓存架子上 // 3. 业务分支处理
doUpShaftToSlitterByNew(param, cachePoints, extCode); if (!cachePointList.isEmpty()) {
} else if (cutPointList.size() > 0) { log.info("设备{}:轴在缓存架子上,执行缓存上架逻辑", deviceCode);
// 在对接位 doUpShaftToSlitterByNew(param, cachePointList, deviceInfo);
// 找到该分切计划的点位 } else if (!cutPointList.isEmpty()) {
BstIvtCutpointivt newCutPoint = cutPointList.get(0); log.info("设备{}:轴在对接位,执行对接位上架逻辑", deviceCode);
// 创建任务 BstIvtCutpointivt cutPoint = cutPointList.get(0);
JSONObject taskParam = new JSONObject(); JSONObject taskParam = new JSONObject();
taskParam.put("point_code", newCutPoint.getPoint_code()); taskParam.put("point_code", cutPoint.getPoint_code());
doUpShaftToSlitter(taskParam); doUpShaftToSlitter(taskParam);
} else { } else {
throw new BadRequestException("没有为设备[" + deviceCode + "]套好轴的位置!"); log.error("设备{}:未找到套好轴的位置", deviceCode);
} throw new BadRequestException("没有为设备[" + deviceCode + "]套好轴的位置!");
} else {
throw new BadRequestException("系统繁忙,稍后在试!!");
}
} finally {
if (openLock) {
open.unlock();
} }
} }
return res;
/**
* 构建成功返回结果
*/
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 设备实体 * @param device 设备实体
*/ */
public void doUpShaftToSlitterByNew(JSONObject param, List<Deliverycachepointivt> cachePoints, StIvtCutpointivt device) { public void doUpShaftToSlitterByNew(JSONObject param, List<Deliverycachepointivt> cachePoints, StIvtCutpointivt device) {
List<Deliverycachepointivt> actualPoints = cachePoints; log.info("开始执行分切缓存上料任务,设备编码:{},缓存点位数量:{}", device.getExt_code(), cachePoints.size());
// 1. 点位数量校验
if (cachePoints.size() > 2) { if (cachePoints.size() > 2) {
// todo: 需要过滤(正常不会出现,先不考虑) log.error("缓存点位数量超过2个设备{},点位:{}", device.getExt_code(), cachePoints);
throw new BadRequestException("计划冗余,请检查!"); throw new BadRequestException("计划冗余,请检查!");
} }
// 获取计划数据
List<String> qzznos = cachePoints.stream().map(Deliverycachepointivt::getQzzno).collect(Collectors.toList()); // 2. 获取气胀轴编号
List<PdmBiSlittingproductionplan> plans = slittingproductionplanService.getByQzzNos(qzznos); List<String> qzznos = cachePoints.stream()
if (plans.isEmpty()) { .map(Deliverycachepointivt::getQzzno)
throw new BadRequestException("计划不存在!请检查点位:" .filter(StrUtil::isNotBlank)
+ cachePoints.stream().map(Deliverycachepointivt::getPoint_code).collect(Collectors.toList()) .collect(Collectors.toList());
+ "的数据!");
if (qzznos.isEmpty()) {
log.error("缓存点位中未找到有效的卷料号");
throw new BadRequestException("缓存点位未找到卷料号!");
} }
JSONObject taskParam = new JSONObject();
// 根据计划筛选上下轴任务,并构建任务参数 // 3. 查询生产计划
List<PdmBiSlittingproductionplan> plans = slittingproductionplanService.getByQzzNos(qzznos);
if (CollUtil.isEmpty(plans)) {
log.error("未查询到分切计划,卷料号:{}", qzznos);
throw new BadRequestException("计划不存在!请检查点位数据!");
}
// 4. 筛选上下轴计划
PdmBiSlittingproductionplan nextUpPlan = plans.stream() PdmBiSlittingproductionplan nextUpPlan = plans.stream()
.filter(p -> SlitterConstant.SLITTER_SHAFT_UP.equals(p.getUp_or_down())) .filter(p -> SlitterConstant.SLITTER_SHAFT_UP.equals(p.getUp_or_down()))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
PdmBiSlittingproductionplan nextDownPlan = plans.stream() PdmBiSlittingproductionplan nextDownPlan = plans.stream()
.filter(p -> SlitterConstant.SLITTER_SHAFT_DOWN.equals(p.getUp_or_down())) .filter(p -> SlitterConstant.SLITTER_SHAFT_DOWN.equals(p.getUp_or_down()))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
Deliverycachepointivt upNeedPoint = actualPoints.stream()
.filter(p -> { // 5. 匹配对应点位
assert nextUpPlan != null; Deliverycachepointivt upNeedPoint = null;
return p.getQzzno().equals(nextUpPlan.getQzzno()); if (nextUpPlan != null) {
}) upNeedPoint = cachePoints.stream()
.filter(p -> nextUpPlan.getQzzno().equals(p.getQzzno()))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
Deliverycachepointivt downNeedPoint = actualPoints.stream() }
.filter(p -> {
assert nextDownPlan != null; Deliverycachepointivt downNeedPoint = null;
return p.getQzzno().equals(nextDownPlan.getQzzno()); if (nextDownPlan != null) {
}) downNeedPoint = cachePoints.stream()
.filter(p -> nextDownPlan.getQzzno().equals(p.getQzzno()))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
if (ObjectUtil.isNotEmpty(nextUpPlan) && ObjectUtil.isNotEmpty(nextDownPlan)) { }
// 上轴都不会空
// 双轴任务参数构建 // 6. 构建任务参数
assert downNeedPoint != null; 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_code1", downNeedPoint.getPoint_code());
taskParam.put("point_code2", device.getDown_point_code()); taskParam.put("point_code2", device.getDown_point_code());
assert upNeedPoint != null;
taskParam.put("point_code3", upNeedPoint.getPoint_code()); taskParam.put("point_code3", upNeedPoint.getPoint_code());
taskParam.put("point_code4", device.getUp_point_code()); taskParam.put("point_code4", device.getUp_point_code());
taskParam.put("vehicle_code1", upNeedPoint.getQzzno()); taskParam.put("vehicle_code1", upNeedPoint.getQzzno());
taskParam.put("vehicle_code2", downNeedPoint.getQzzno()); taskParam.put("vehicle_code2", downNeedPoint.getQzzno());
log.info("双轴任务构建完成,上轴卷:{},下轴卷:{}", upNeedPoint.getQzzno(), downNeedPoint.getQzzno());
} else { } else {
// 单轴任务参数构建 // 单轴任务
if (ObjectUtil.isNotEmpty(nextUpPlan)) { if (nextUpPlan != null) {
// 上轴任务 if (upNeedPoint == null) {
assert upNeedPoint != null; throw new BadRequestException("上轴任务未找到对应缓存点位!");
}
taskParam.put("point_code1", upNeedPoint.getPoint_code()); taskParam.put("point_code1", upNeedPoint.getPoint_code());
taskParam.put("point_code2", device.getUp_point_code()); taskParam.put("point_code2", device.getUp_point_code());
taskParam.put("vehicle_code1", upNeedPoint.getQzzno()); taskParam.put("vehicle_code1", upNeedPoint.getQzzno());
} else { log.info("单上轴任务,卷号:{}", upNeedPoint.getQzzno());
// 下轴任务 } else if (nextDownPlan != null) {
assert downNeedPoint != null; if (downNeedPoint == null) {
throw new BadRequestException("下轴任务未找到对应缓存点位!");
}
taskParam.put("point_code1", downNeedPoint.getPoint_code()); taskParam.put("point_code1", downNeedPoint.getPoint_code());
taskParam.put("point_code2", device.getDown_point_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("truss_type", "1");
taskParam.put("empty_site", "0"); taskParam.put("empty_site", "0");
taskParam.put("task_type", SlitterEnum.TASK_TYPE.code("缓存上空轴任务")); taskParam.put("task_type", SlitterEnum.TASK_TYPE.code("缓存上空轴任务"));
taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA); taskParam.put("product_area", SlitterConstant.SLITTER_TASK_AREA);
taskParam.put("u_containers", plans.stream().map(PdmBiSlittingproductionplan::getContainer_name).collect(Collectors.toList()));
// 创建任务 List<String> 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); upShaftTrussNewTask.createTask(taskParam);
} }