yeg
2026-09-28 147428971be43eed90a79f3849f15000d3855390
battery-business/src/main/java/com/battery/business/service/impl/TDetectionCabinetServiceImpl.java
@@ -18,6 +18,7 @@
import com.battery.business.domain.TDetectionChannel;
import com.battery.business.domain.vo.DiscoveredCabinetVo;
import com.battery.business.mapper.TDetectionCabinetMapper;
import com.battery.business.service.IDeviceAdapterService;
import com.battery.business.service.ITDetectionCabinetService;
import com.battery.device.api.discovery.DeviceDiscoveryCandidateStore;
import com.battery.device.api.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate;
@@ -39,6 +40,7 @@
    private final TDetectionCabinetMapper detectionCabinetMapper;
    private final DeviceDiscoveryCandidateStore candidateStore;
    private final IDeviceAdapterService adapterService;
    /**
     * 构造检测柜业务服务。
@@ -48,8 +50,42 @@
    public TDetectionCabinetServiceImpl(TDetectionCabinetMapper detectionCabinetMapper,
            DeviceDiscoveryCandidateStore candidateStore)
    {
        this(detectionCabinetMapper, candidateStore, null);
    }
    /**
     * 构造检测柜业务服务。
     *
     * @param detectionCabinetMapper 检测柜数据访问对象
     * @param candidateStore 发现候选存储
     * @param adapterService 适配器实例服务;为空时列表不展示数据来源名称
     */
    @org.springframework.beans.factory.annotation.Autowired
    public TDetectionCabinetServiceImpl(TDetectionCabinetMapper detectionCabinetMapper,
            DeviceDiscoveryCandidateStore candidateStore,
            @org.springframework.lang.Nullable IDeviceAdapterService adapterService)
    {
        this.detectionCabinetMapper = detectionCabinetMapper;
        this.candidateStore = candidateStore;
        this.adapterService = adapterService;
    }
    /** 数据来源名称按适配器编码解析;代码装配实例没有数据库记录时退回展示编码。 */
    private Map<String, String> adapterNames()
    {
        if (adapterService == null) return Map.of();
        return adapterService.selectList(new com.battery.business.domain.TDeviceAdapter()).stream()
                .filter(item -> item.getAdapterCode() != null && item.getAdapterName() != null)
                .collect(java.util.stream.Collectors.toMap(
                        com.battery.business.domain.TDeviceAdapter::getAdapterCode,
                        com.battery.business.domain.TDeviceAdapter::getAdapterName, (left, right) -> right));
    }
    /** 适配器编码可能缺失(历史登记),缺失时不查询来源名称。 */
    private void applyAdapterName(TDetectionCabinet cabinet, Map<String, String> adapterNames)
    {
        if (cabinet == null || cabinet.getAdapterCode() == null) return;
        cabinet.setAdapterName(adapterNames.get(cabinet.getAdapterCode()));
    }
    /**
@@ -66,6 +102,7 @@
        {
            throw new ServiceException("检测柜不存在或已删除");
        }
        applyAdapterName(detectionCabinet, adapterNames());
        return applyRealtimeState(detectionCabinet, candidatesByCode());
    }
@@ -87,8 +124,10 @@
        detectionCabinet.setOnlineStatus(null);
        detectionCabinet.setTestStatus(null);
        Map<String, CabinetCandidate> candidates = candidatesByCode();
        Map<String, String> adapterNames = adapterNames();
        return detectionCabinetMapper.selectDetectionCabinetList(detectionCabinet).stream()
                .map(item -> applyRealtimeState(item, candidates))
                .peek(item -> applyAdapterName(item, adapterNames))
                .filter(item -> StringUtils.isBlank(requestedOnlineStatus)
                        || requestedOnlineStatus.equals(item.getOnlineStatus()))
                .filter(item -> StringUtils.isBlank(requestedTestStatus)
@@ -97,8 +136,10 @@
    }
    /**
     * 读取未过期且未登记的候选,离线设备仍保留身份并可选择。
     * 发现只返回设备事实,不从通道工作状态推断系统测试关系。
     * 读取未登记且未删除的候选,离线设备仍保留身份并可选择。
     * 候选不按时间过期(厂商存储里的通道登记是长期事实),只按"已登记且未删除"排除;
     * 每条附带最近数据时间并按它倒序,便于操作员判断哪几台真的在产出数据。
     * 发现只返回设备事实,不从通道工作状态推断系统测试关系,也不自动判定"在用"。
     *
     * @return 可供选择的检测柜设备摘要
     */
@@ -110,7 +151,11 @@
                .filter(candidate -> !registeredCodes.contains(candidate.deviceCode()))
                .map(candidate -> new DiscoveredCabinetVo(
                            candidate.deviceCode(), candidate.ip(), candidate.mac(), candidate.name(),
                            candidate.manufacturer(), candidate.model(), candidate.channels().size(), candidate.online() ? "在线" : "离线"))
                            candidate.manufacturer(), candidate.model(), candidate.channels().size(),
                            candidate.online() ? "在线" : "离线", candidate.lastDataAt()))
                .sorted(java.util.Comparator.comparing(DiscoveredCabinetVo::lastDataAt,
                        java.util.Comparator.nullsLast(java.util.Comparator.reverseOrder()))
                        .thenComparing(DiscoveredCabinetVo::deviceCode))
                .toList();
    }