Junjie
2026-04-27 2cc61346cc0a3e5338aa8957f79f4c99c204f339
src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java
@@ -18,12 +18,15 @@
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.entity.BasStation;
import com.zy.asrs.entity.StationFlowCapacity;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDualCrnpService;
import com.zy.asrs.service.BasStationService;
import com.zy.asrs.service.StationFlowCapacityService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.WrkStsType;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import org.slf4j.Logger;
@@ -34,6 +37,7 @@
import org.springframework.transaction.support.TransactionTemplate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@@ -49,6 +53,14 @@
    private static final String DIRECTION_OUT = "OUT";
    private static final long APPLY_LOCK_SECONDS = 120L;
    private static final String APPLY_LOCK_BUSY_REASON = "申请调参锁失败,锁不可用,可能已有任务或 Redis 异常";
    private static final List<Long> FINAL_WRK_STS_LIST = Arrays.asList(
            WrkStsType.COMPLETE_INBOUND.sts,
            WrkStsType.SETTLE_INBOUND.sts,
            WrkStsType.COMPLETE_OUTBOUND.sts,
            WrkStsType.SETTLE_OUTBOUND.sts,
            WrkStsType.COMPLETE_LOC_MOVE.sts,
            WrkStsType.COMPLETE_CRN_MOVE.sts
    );
    @Autowired
    private AiAutoTuneJobService aiAutoTuneJobService;
@@ -64,6 +76,8 @@
    private BasDualCrnpService basDualCrnpService;
    @Autowired
    private StationFlowCapacityService stationFlowCapacityService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
@@ -323,14 +337,14 @@
            if (config == null) {
                return CurrentValue.rejected("运行参数不存在: " + validatedChange.getTargetKey());
            }
            return numericCurrentValue(config.getValue(), false, validatedChange.getTargetKey());
            return numericCurrentValue(config.getValue(), validatedChange.getTargetKey());
        }
        if (AutoTuneTargetType.STATION.equals(targetType)) {
            BasStation station = basStationService.getById(targetId);
            if (station == null) {
                return CurrentValue.rejected("站点不存在: " + validatedChange.getTargetId());
            }
            return numericCurrentValue(toText(station.getOutTaskLimit()), true, validatedChange.getTargetKey());
            return stationOutTaskLimitCurrentValue(station.getOutTaskLimit(), validatedChange.getTargetKey());
        }
        if (AutoTuneTargetType.CRN.equals(targetType)) {
            BasCrnp crnp = basCrnpService.getById(targetId);
@@ -338,28 +352,29 @@
                return CurrentValue.rejected("堆垛机不存在: " + validatedChange.getTargetId());
            }
            Integer value = "maxOutTask".equals(validatedChange.getTargetKey()) ? crnp.getMaxOutTask() : crnp.getMaxInTask();
            return numericCurrentValue(toText(value), false, validatedChange.getTargetKey());
            return numericCurrentValue(toText(value), validatedChange.getTargetKey());
        }
        BasDualCrnp dualCrnp = basDualCrnpService.getById(targetId);
        if (dualCrnp == null) {
            return CurrentValue.rejected("双工位堆垛机不存在: " + validatedChange.getTargetId());
        }
        Integer value = "maxOutTask".equals(validatedChange.getTargetKey()) ? dualCrnp.getMaxOutTask() : dualCrnp.getMaxInTask();
        return numericCurrentValue(toText(value), false, validatedChange.getTargetKey());
        return numericCurrentValue(toText(value), validatedChange.getTargetKey());
    }
    private CurrentValue numericCurrentValue(String oldValue, boolean nullOrNegativeAsZero, String targetKey) {
        if (oldValue == null || oldValue.trim().isEmpty()) {
            if (nullOrNegativeAsZero) {
                return CurrentValue.accepted(null, 0);
    private CurrentValue stationOutTaskLimitCurrentValue(Integer outTaskLimit, String targetKey) {
        if (outTaskLimit == null || outTaskLimit < 0) {
            return CurrentValue.rejected(targetKey + " 当前为不限制,需要人工先初始化为有限值后才能自动调参");
            }
        return numericCurrentValue(toText(outTaskLimit), targetKey);
    }
    private CurrentValue numericCurrentValue(String oldValue, String targetKey) {
        if (oldValue == null || oldValue.trim().isEmpty()) {
            return CurrentValue.rejected(targetKey + " 当前值为空,无法计算步长");
        }
        try {
            Integer parsedValue = Integer.valueOf(oldValue.trim());
            if (nullOrNegativeAsZero && parsedValue < 0) {
                return CurrentValue.accepted(oldValue, 0);
            }
            return CurrentValue.accepted(oldValue, parsedValue);
        } catch (Exception exception) {
            return CurrentValue.rejected(targetKey + " 当前值不是整数,无法计算步长");
@@ -678,7 +693,7 @@
        job.setTriggerType(AutoTuneTriggerType.normalize(request.getTriggerType()));
        job.setStatus(AutoTuneJobStatus.RUNNING.getCode());
        job.setStartTime(now);
        job.setHasActiveTasks(0);
        job.setHasActiveTasks(resolveHasActiveTasksForAudit());
        job.setPromptSceneCode(PROMPT_SCENE_CODE);
        job.setSummary(dryRun ? "AI自动调参 dry-run: " + safeReason(request.getReason()) : safeReason(request.getReason()));
        job.setIntervalBefore(readIntervalMinutes());
@@ -697,7 +712,7 @@
        job.setTriggerType(AutoTuneTriggerType.ROLLBACK.getCode());
        job.setStatus(AutoTuneJobStatus.RUNNING.getCode());
        job.setStartTime(now);
        job.setHasActiveTasks(0);
        job.setHasActiveTasks(resolveHasActiveTasksForAudit());
        job.setPromptSceneCode(PROMPT_SCENE_CODE);
        job.setSummary(safeReason(reason));
        job.setIntervalBefore(readIntervalMinutes());
@@ -711,6 +726,21 @@
        return job;
    }
    private int resolveHasActiveTasksForAudit() {
        if (wrkMastService == null) {
            LOGGER.warn("AI自动调参审计无法获取 WrkMastService,hasActiveTasks 按 0 记录");
            return 0;
        }
        try {
            QueryWrapper<WrkMast> queryWrapper = new QueryWrapper<>();
            queryWrapper.and(wrapper -> wrapper.notIn("wrk_sts", FINAL_WRK_STS_LIST).or().isNull("wrk_sts"));
            return wrkMastService.count(queryWrapper) > 0 ? 1 : 0;
        } catch (RuntimeException exception) {
            LOGGER.warn("AI自动调参审计查询未完成任务失败,hasActiveTasks 按 0 记录", exception);
            return 0;
        }
    }
    private void finishJob(AiAutoTuneJob job,
                           AutoTuneApplyRequest request,
                           List<AiAutoTuneChange> auditChanges,