From e76f0739e647fe8a7e0e2618914e2faff554b1b7 Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期一, 17 十一月 2025 17:33:23 +0800
Subject: [PATCH] 解决冲突

---
 mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/DeviceConfigServiceImpl.java |  774 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 774 insertions(+), 0 deletions(-)

diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/DeviceConfigServiceImpl.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/DeviceConfigServiceImpl.java
new file mode 100644
index 0000000..55a9693
--- /dev/null
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/DeviceConfigServiceImpl.java
@@ -0,0 +1,774 @@
+package com.mes.device.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mes.device.entity.DeviceConfig;
+import com.mes.device.mapper.DeviceConfigMapper;
+import com.mes.device.service.DeviceConfigService;
+import com.mes.device.vo.DeviceConfigVO;
+import com.mes.device.vo.StatisticsVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 璁惧閰嶇疆鏈嶅姟瀹炵幇绫�
+ * @author huang
+ */
+@Slf4j
+@Service
+public class DeviceConfigServiceImpl extends ServiceImpl<DeviceConfigMapper, DeviceConfig> implements DeviceConfigService {
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    @Override
+    public boolean createDevice(DeviceConfig deviceConfig) {
+        try {
+            // 妫�鏌ヨ澶囩紪鍙锋槸鍚﹀凡瀛樺湪
+            if (isDeviceCodeExists(deviceConfig.getDeviceCode(), null)) {
+                log.warn("璁惧缂栧彿宸插瓨鍦�: {}", deviceConfig.getDeviceCode());
+                return false;
+            }
+            
+            // 鍒濆鍖栬澶囩姸鎬佷负绂荤嚎
+            if (deviceConfig.getStatus() == null) {
+                deviceConfig.setStatus("绂荤嚎");
+            }
+            
+            boolean result = save(deviceConfig);
+            if (result) {
+                log.info("鍒涘缓璁惧閰嶇疆鎴愬姛: {}", deviceConfig.getDeviceCode());
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鍒涘缓璁惧閰嶇疆澶辫触", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean updateDevice(DeviceConfig deviceConfig) {
+        try {
+            // 妫�鏌ヨ澶囩紪鍙锋槸鍚﹀凡瀛樺湪锛堟帓闄ゅ綋鍓嶈澶囷級
+            if (isDeviceCodeExists(deviceConfig.getDeviceCode(), deviceConfig.getId())) {
+                log.warn("璁惧缂栧彿宸插瓨鍦�: {}", deviceConfig.getDeviceCode());
+                return false;
+            }
+            
+            boolean result = updateById(deviceConfig);
+            if (result) {
+                log.info("鏇存柊璁惧閰嶇疆鎴愬姛: {}", deviceConfig.getDeviceCode());
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鏇存柊璁惧閰嶇疆澶辫触", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean deleteDevice(Long id) {
+        try {
+            boolean result = removeById(id);
+            if (result) {
+                log.info("鍒犻櫎璁惧閰嶇疆鎴愬姛: {}", id);
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鍒犻櫎璁惧閰嶇疆澶辫触", e);
+            return false;
+        }
+    }
+
+    @Override
+    public DeviceConfig getDeviceById(Long id) {
+        return getById(id);
+    }
+
+    @Override
+    public DeviceConfig getDeviceByCode(String deviceCode) {
+        LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DeviceConfig::getDeviceCode, deviceCode);
+        wrapper.eq(DeviceConfig::getIsDeleted, 0);
+        return getOne(wrapper);
+    }
+
+    @Override
+    public List<DeviceConfig> getDeviceList(Long projectId, String deviceType, String status) {
+        LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+        
+        if (projectId != null) {
+            wrapper.eq(DeviceConfig::getProjectId, projectId);
+        }
+        if (deviceType != null && !deviceType.isEmpty()) {
+            wrapper.eq(DeviceConfig::getDeviceType, deviceType);
+        }
+        if (status != null && !status.isEmpty()) {
+            wrapper.eq(DeviceConfig::getStatus, status);
+        }
+        
+        wrapper.eq(DeviceConfig::getIsDeleted, 0);
+        wrapper.orderByDesc(DeviceConfig::getCreatedTime);
+        
+        return list(wrapper);
+    }
+
+    @Override
+    public Page<DeviceConfigVO.DeviceInfo> getDeviceList(Long projectId, String deviceType, String deviceStatus, String keyword, Integer page, Integer size) {
+        // 鍒涘缓鍒嗛〉瀵硅薄
+       Page<DeviceConfig> pageQuery = new Page<>(page != null ? page : 1, size != null ? size : 10);
+        
+        // 鏋勫缓鏌ヨ鏉′欢
+        LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+        
+        if (projectId != null) {
+            wrapper.eq(DeviceConfig::getProjectId, projectId);
+        }
+        
+        // 璁惧绫诲瀷杩囨护
+        if (deviceType != null && !deviceType.trim().isEmpty()) {
+            String convertedDeviceType = convertDeviceTypeFromString(deviceType);
+            if (convertedDeviceType != null) {
+                wrapper.eq(DeviceConfig::getDeviceType, convertedDeviceType);
+            }
+        }
+        
+        // 璁惧鐘舵�佽繃婊�
+        if (deviceStatus != null && !deviceStatus.trim().isEmpty()) {
+            String convertedStatus = convertStatusFromString(deviceStatus);
+            if (convertedStatus != null) {
+                wrapper.eq(DeviceConfig::getStatus, convertedStatus);
+            }
+        }
+        
+        // 鍏抽敭璇嶆悳绱�
+        if (keyword != null && !keyword.trim().isEmpty()) {
+            wrapper.and(w -> w
+                .like(DeviceConfig::getDeviceName, keyword)
+                .or().like(DeviceConfig::getDeviceCode, keyword)
+                .or().like(DeviceConfig::getDescription, keyword));
+        }
+        
+        wrapper.eq(DeviceConfig::getIsDeleted, 0);
+        wrapper.orderByDesc(DeviceConfig::getCreatedTime);
+        
+        // 鎵ц鍒嗛〉鏌ヨ
+        Page<DeviceConfig> result = page(pageQuery, wrapper);
+        
+        // 杞崲涓篤O瀵硅薄
+        List<DeviceConfigVO.DeviceInfo> voList = result.getRecords().stream().map(device -> {
+            DeviceConfigVO.DeviceInfo vo = new DeviceConfigVO.DeviceInfo();
+            vo.setId(device.getId());
+            vo.setDeviceName(device.getDeviceName());
+            vo.setDeviceCode(device.getDeviceCode());
+            vo.setDeviceType(getDeviceTypeName(device.getDeviceType()));
+            vo.setPlcIp(device.getPlcIp());
+            vo.setPlcPort(device.getPlcPort());
+            vo.setPlcType(device.getPlcType());
+            vo.setModuleName(device.getModuleName());
+            vo.setIsPrimary(device.getIsPrimary());
+            vo.setEnabled(Boolean.TRUE.equals(device.getEnabled()));
+            vo.setIsEnabled(Boolean.TRUE.equals(device.getEnabled()));
+            vo.setStatus(getStatusName(device.getStatus()));
+            vo.setDeviceStatus(convertStatusToCode(device.getStatus()));
+            vo.setLastHeartbeat(device.getUpdatedTime());
+            vo.setLocation("榛樿浣嶇疆");
+            vo.setDescription(device.getDescription());
+            vo.setCreatedTime(device.getCreatedTime());
+            vo.setUpdatedTime(device.getUpdatedTime());
+            vo.setProjectId(device.getProjectId());
+            return vo;
+        }).collect(Collectors.toList());
+        
+        // 鍒涘缓杩斿洖鐨凱age瀵硅薄
+        Page<DeviceConfigVO.DeviceInfo> pageResult = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
+        pageResult.setRecords(voList);
+        
+        return pageResult;
+    }
+
+    @Override
+    public List<DeviceConfigVO.DeviceInfo> getDeviceVOList(Long projectId, String deviceType, String status) {
+        List<DeviceConfig> deviceList = getDeviceList(projectId, deviceType, status);
+        
+        return deviceList.stream().map(device -> {
+            DeviceConfigVO.DeviceInfo vo = new DeviceConfigVO.DeviceInfo();
+            vo.setId(device.getId());
+            vo.setDeviceName(device.getDeviceName());
+            vo.setDeviceCode(device.getDeviceCode());
+            vo.setDeviceType(getDeviceTypeName(device.getDeviceType()));
+            vo.setPlcIp(device.getPlcIp());
+            vo.setPlcPort(device.getPlcPort());
+            vo.setPlcType(device.getPlcType());
+            vo.setModuleName(device.getModuleName());
+            vo.setIsPrimary(device.getIsPrimary());
+            vo.setEnabled(Boolean.TRUE.equals(device.getEnabled()));
+            vo.setIsEnabled(Boolean.TRUE.equals(device.getEnabled()));
+            vo.setStatus(getStatusName(device.getStatus()));
+            vo.setDeviceStatus(convertStatusToCode(device.getStatus()));
+            vo.setDescription(device.getDescription());
+            vo.setLocation("榛樿浣嶇疆"); // TODO: 浠庢墿灞曞弬鏁版垨鍏宠仈琛ㄤ腑鑾峰彇
+            vo.setCreatedTime(device.getCreatedTime());
+            vo.setUpdatedTime(device.getUpdatedTime());
+            vo.setProjectId(device.getProjectId());
+            return vo;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 鑾峰彇璁惧绫诲瀷鍚嶇О
+     */
+    private String getDeviceTypeName(String deviceType) {
+        if (deviceType == null) return "鏈煡璁惧";
+        
+        // 鐩存帴杩斿洖璁惧绫诲瀷鍊硷紝鍥犱负瀹炰綋绫讳腑宸茬粡浣跨敤涓枃绫诲瀷
+        return deviceType;
+    }
+
+    /**
+     * 鑾峰彇璁惧鐘舵�佸悕绉�
+     */
+    private String getStatusName(String status) {
+        if (status == null) return "鏈煡鐘舵��";
+        
+        // 鐩存帴杩斿洖鐘舵�佸�硷紝鍥犱负瀹炰綋绫讳腑宸茬粡浣跨敤涓枃鐘舵��
+        return status;
+    }
+
+    /**
+     * 灏嗕腑鏂囩姸鎬佽浆鎹负鍓嶇浣跨敤鐨勭姸鎬佺紪鐮�
+     */
+    private String convertStatusToCode(String status) {
+        if (status == null) return "UNKNOWN";
+        switch (status) {
+            case "鍦ㄧ嚎":
+                return "ONLINE";
+            case "绂荤嚎":
+                return "OFFLINE";
+            case "缁存姢涓�":
+            case "缁存姢":
+                return "MAINTENANCE";
+            case "鏁呴殰":
+                return "FAULT";
+            default:
+                return status.toUpperCase();
+        }
+    }
+
+    /**
+     * 鏇存柊鍗曚釜璁惧鍚敤鐘舵��
+     */
+    private boolean updateDeviceEnabledState(Long id, boolean enabled) {
+        try {
+            DeviceConfig device = getById(id);
+            if (device == null) {
+                log.warn("璁惧涓嶅瓨鍦�: {}", id);
+                return false;
+            }
+            device.setEnabled(enabled);
+            device.setStatus(enabled ? DeviceConfig.Status.ONLINE : DeviceConfig.Status.OFFLINE);
+            boolean result = updateById(device);
+            if (result) {
+                log.info("鏇存柊璁惧鍚敤鐘舵�佹垚鍔�: {} -> {}", id, enabled);
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鏇存柊璁惧鍚敤鐘舵�佸け璐�", e);
+            return false;
+        }
+    }
+
+    /**
+     * 鎵归噺鏇存柊璁惧鍚敤鐘舵��
+     */
+    private boolean batchUpdateDeviceEnabledState(List<Long> ids, boolean enabled) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        try {
+            LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+            wrapper.in(DeviceConfig::getId, ids);
+
+            DeviceConfig updateEntity = new DeviceConfig();
+            updateEntity.setEnabled(enabled);
+            updateEntity.setStatus(enabled ? DeviceConfig.Status.ONLINE : DeviceConfig.Status.OFFLINE);
+
+            boolean result = update(updateEntity, wrapper);
+            if (result) {
+                log.info("鎵归噺鏇存柊璁惧鍚敤鐘舵�佹垚鍔�: {} 涓澶� -> {}", ids.size(), enabled);
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鎵归噺鏇存柊璁惧鍚敤鐘舵�佸け璐�", e);
+            return false;
+        }
+    }
+
+    /**
+     * 瀛楃涓茶浆鎹负璁惧绫诲瀷
+     */
+    private String convertDeviceTypeFromString(String deviceType) {
+        if (deviceType == null) return null;
+        
+        switch (deviceType.trim().toLowerCase()) {
+            case "load_vehicle":
+            case "涓婂ぇ杞�":
+            case "1":
+                return DeviceConfig.DeviceType.LOAD_VEHICLE;
+            case "large_glass":
+            case "澶х悊鐗�":
+            case "2":
+                return DeviceConfig.DeviceType.LARGE_GLASS;
+            case "glass_storage":
+            case "鐜荤拑瀛樺偍":
+            case "3":
+                return DeviceConfig.DeviceType.GLASS_STORAGE;
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * 瀛楃涓茶浆鎹负鐘舵��
+     */
+    private String convertStatusFromString(String deviceStatus) {
+        if (deviceStatus == null) return null;
+        
+        switch (deviceStatus.trim().toLowerCase()) {
+            case "online":
+            case "鍦ㄧ嚎":
+            case "1":
+                return "鍦ㄧ嚎";
+            case "offline":
+            case "绂荤嚎":
+            case "2":
+                return "绂荤嚎";
+            case "maintenance":
+            case "缁存姢":
+            case "缁存姢涓�":
+            case "3":
+                return "缁存姢涓�";
+            case "fault":
+            case "鏁呴殰":
+            case "4":
+                return "鏁呴殰";
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public boolean isDeviceCodeExists(String deviceCode, Long excludeId) {
+        LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DeviceConfig::getDeviceCode, deviceCode);
+        wrapper.eq(DeviceConfig::getIsDeleted, 0);
+        
+        if (excludeId != null) {
+            wrapper.ne(DeviceConfig::getId, excludeId);
+        }
+        
+        return count(wrapper) > 0;
+    }
+
+    @Override
+    public boolean updateDeviceStatus(Long id, String status) {
+        try {
+            DeviceConfig device = getById(id);
+            if (device == null) {
+                log.warn("璁惧涓嶅瓨鍦�: {}", id);
+                return false;
+            }
+            
+            device.setStatus(status);
+            boolean result = updateById(device);
+            if (result) {
+                log.info("鏇存柊璁惧鐘舵�佹垚鍔�: {} -> {}", id, status);
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鏇存柊璁惧鐘舵�佸け璐�", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean batchUpdateDeviceStatus(List<Long> ids, String status) {
+        try {
+            LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+            wrapper.in(DeviceConfig::getId, ids);
+            
+            DeviceConfig updateEntity = new DeviceConfig();
+            updateEntity.setStatus(status);
+            
+            boolean result = update(updateEntity, wrapper);
+            if (result) {
+                log.info("鎵归噺鏇存柊璁惧鐘舵�佹垚鍔�: {} 涓澶� -> {}", ids.size(), status);
+            }
+            return result;
+        } catch (Exception e) {
+            log.error("鎵归噺鏇存柊璁惧鐘舵�佸け璐�", e);
+            return false;
+        }
+    }
+
+    @Override
+    public Map<String, Object> getExtraParams(Long id) {
+        try {
+            DeviceConfig device = getById(id);
+            if (device == null || device.getExtraParams() == null) {
+                return new HashMap<>();
+            }
+            
+            return objectMapper.readValue(device.getExtraParams(), 
+                new TypeReference<Map<String, Object>>() {});
+        } catch (IOException e) {
+            log.error("瑙f瀽璁惧鎵╁睍鍙傛暟澶辫触", e);
+            return new HashMap<>();
+        }
+    }
+
+    @Override
+    public boolean updateExtraParams(Long id, Map<String, Object> extraParams) {
+        try {
+            DeviceConfig device = getById(id);
+            if (device == null) {
+                log.warn("璁惧涓嶅瓨鍦�: {}", id);
+                return false;
+            }
+            
+            String extraParamsJson = objectMapper.writeValueAsString(extraParams);
+            device.setExtraParams(extraParamsJson);
+            
+            boolean result = updateById(device);
+            if (result) {
+                log.info("鏇存柊璁惧鎵╁睍鍙傛暟鎴愬姛: {}", id);
+            }
+            return result;
+        } catch (IOException e) {
+            log.error("搴忓垪鍖栬澶囨墿灞曞弬鏁板け璐�", e);
+            return false;
+        }
+    }
+
+    @Override
+    public int getOnlineDeviceCount(Long projectId) {
+        // 绠�鍖栧疄鐜帮紝瀹為檯椤圭洰涓彲鑳介渶瑕佹牴鎹」鐩甀D杩囨护
+        LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DeviceConfig::getStatus, "鍦ㄧ嚎");
+        wrapper.eq(DeviceConfig::getIsDeleted, 0);
+        
+        if (projectId != null) {
+            wrapper.eq(DeviceConfig::getProjectId, projectId);
+        }
+        
+        return (int) count(wrapper);
+    }
+
+    @Override
+    public StatisticsVO.DeviceStatistics getDeviceStatistics(Long projectId) {
+        try {
+            // 璁惧鎬绘暟
+            LambdaQueryWrapper<DeviceConfig> totalWrapper = new LambdaQueryWrapper<>();
+            totalWrapper.eq(DeviceConfig::getIsDeleted, 0);
+            if (projectId != null) {
+                totalWrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            int totalDevices = (int) count(totalWrapper);
+            
+            // 鍦ㄧ嚎璁惧鏁�
+            LambdaQueryWrapper<DeviceConfig> onlineWrapper = new LambdaQueryWrapper<>();
+            onlineWrapper.eq(DeviceConfig::getStatus, "鍦ㄧ嚎");
+            onlineWrapper.eq(DeviceConfig::getIsDeleted, 0);
+            if (projectId != null) {
+                onlineWrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            int onlineDevices = (int) count(onlineWrapper);
+            
+            // 绂荤嚎璁惧鏁�
+            LambdaQueryWrapper<DeviceConfig> offlineWrapper = new LambdaQueryWrapper<>();
+            offlineWrapper.eq(DeviceConfig::getStatus, "绂荤嚎");
+            offlineWrapper.eq(DeviceConfig::getIsDeleted, 0);
+            if (projectId != null) {
+                offlineWrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            int offlineDevices = (int) count(offlineWrapper);
+            
+            // 娲昏穬璁惧鏁帮紙鍦ㄧ嚎璁惧锛�
+            int activeDevices = onlineDevices;
+            int inactiveDevices = offlineDevices;
+            
+            // 缁存姢涓澶囨暟
+            LambdaQueryWrapper<DeviceConfig> maintenanceWrapper = new LambdaQueryWrapper<>();
+            maintenanceWrapper.eq(DeviceConfig::getStatus, "缁存姢涓�");
+            maintenanceWrapper.eq(DeviceConfig::getIsDeleted, 0);
+            if (projectId != null) {
+                maintenanceWrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            int maintenanceDevices = (int) count(maintenanceWrapper);
+            
+            // 鏁呴殰璁惧鏁�
+            LambdaQueryWrapper<DeviceConfig> faultWrapper = new LambdaQueryWrapper<>();
+            faultWrapper.eq(DeviceConfig::getStatus, "鏁呴殰");
+            faultWrapper.eq(DeviceConfig::getIsDeleted, 0);
+            if (projectId != null) {
+                faultWrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            int faultDevices = (int) count(faultWrapper);
+            
+            // 璁$畻璁惧鍙敤鎬�
+            double deviceAvailability = totalDevices > 0 ? (double) activeDevices / totalDevices * 100 : 0.0;
+            
+            // 璁$畻骞冲潎姝e父杩愯鏃堕棿锛堟ā鎷熷�硷級
+            double averageUptime = 95.5; // 榛樿鍊硷紝瀹為檯搴旂敤涓彲浠ュ熀浜庡巻鍙叉暟鎹绠�
+            
+            // 鑾峰彇璁惧绫诲瀷缁熻
+            List<StatisticsVO.DeviceTypeStatistics> deviceTypeStats = getDeviceTypeStatistics(projectId);
+            
+            // 鍒涘缓璁惧缁熻瀵硅薄
+            StatisticsVO.DeviceStatistics deviceStatistics = new StatisticsVO.DeviceStatistics(
+                totalDevices,
+                onlineDevices,
+                offlineDevices,
+                activeDevices,
+                inactiveDevices,
+                faultDevices,
+                maintenanceDevices,
+                deviceTypeStats.size(),
+                deviceAvailability,
+                averageUptime,
+                new Date(),
+                deviceTypeStats
+            );
+            
+            log.info("鑾峰彇璁惧缁熻淇℃伅鎴愬姛: 鎬昏澶囨暟={}, 鍦ㄧ嚎璁惧鏁�={}, 鍙敤鎬�={}%", 
+                totalDevices, onlineDevices, String.format("%.2f", deviceAvailability));
+            
+            return deviceStatistics;
+        } catch (Exception e) {
+            log.error("鑾峰彇璁惧缁熻淇℃伅澶辫触", e);
+            // 杩斿洖榛樿缁熻淇℃伅
+            return new StatisticsVO.DeviceStatistics(0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, new Date(), new ArrayList<>());
+        }
+    }
+
+    /**
+     * 鑾峰彇璁惧绫诲瀷缁熻淇℃伅
+     */
+    private List<StatisticsVO.DeviceTypeStatistics> getDeviceTypeStatistics(Long projectId) {
+        try {
+            List<StatisticsVO.DeviceTypeStatistics> deviceTypeStats = new ArrayList<>();
+            
+            // 鑾峰彇鎵�鏈夎澶囩被鍨�
+            List<String> deviceTypeNames = getAllDeviceTypes();
+            
+            for (String deviceTypeName : deviceTypeNames) {
+                // 鎬绘暟
+                LambdaQueryWrapper<DeviceConfig> totalWrapper = new LambdaQueryWrapper<>();
+                totalWrapper.eq(DeviceConfig::getDeviceType, deviceTypeName);
+                totalWrapper.eq(DeviceConfig::getIsDeleted, 0);
+                if (projectId != null) {
+                    totalWrapper.eq(DeviceConfig::getProjectId, projectId);
+                }
+                Integer totalCount = Math.toIntExact(count(totalWrapper));
+                
+                // 鍦ㄧ嚎鏁�
+                LambdaQueryWrapper<DeviceConfig> onlineWrapper = new LambdaQueryWrapper<>();
+                onlineWrapper.eq(DeviceConfig::getDeviceType, deviceTypeName);
+                onlineWrapper.eq(DeviceConfig::getStatus, "鍦ㄧ嚎");
+                onlineWrapper.eq(DeviceConfig::getIsDeleted, 0);
+                if (projectId != null) {
+                    onlineWrapper.eq(DeviceConfig::getProjectId, projectId);
+                }
+                Integer onlineCount = Math.toIntExact(count(onlineWrapper));
+                
+                // 绂荤嚎鏁�
+                LambdaQueryWrapper<DeviceConfig> offlineWrapper = new LambdaQueryWrapper<>();
+                offlineWrapper.eq(DeviceConfig::getDeviceType, deviceTypeName);
+                offlineWrapper.eq(DeviceConfig::getStatus, "绂荤嚎");
+                offlineWrapper.eq(DeviceConfig::getIsDeleted, 0);
+                if (projectId != null) {
+                    offlineWrapper.eq(DeviceConfig::getProjectId, projectId);
+                }
+                Integer offlineCount = Math.toIntExact(count(offlineWrapper));
+                
+                // 鍙敤鎬�
+                double availability = totalCount > 0 ? (double) onlineCount / totalCount * 100 : 0.0;
+                
+                deviceTypeStats.add(new StatisticsVO.DeviceTypeStatistics(
+                    deviceTypeName, totalCount, onlineCount, offlineCount, availability
+                ));
+            }
+            
+            return deviceTypeStats;
+        } catch (Exception e) {
+            log.error("鑾峰彇璁惧绫诲瀷缁熻澶辫触", e);
+            return new ArrayList<>();
+        }
+    }
+
+    @Override
+    public Long getDeviceCount(Long projectId, String deviceType, String deviceStatus, String keyword) {
+        try {
+            LambdaQueryWrapper<DeviceConfig> wrapper = new LambdaQueryWrapper<>();
+            
+            if (projectId != null) {
+                wrapper.eq(DeviceConfig::getProjectId, projectId);
+            }
+            
+            // 璁惧绫诲瀷杩囨护
+            if (deviceType != null && !deviceType.trim().isEmpty()) {
+                String convertedDeviceType = convertDeviceTypeFromString(deviceType);
+                if (convertedDeviceType != null) {
+                    wrapper.eq(DeviceConfig::getDeviceType, convertedDeviceType);
+                }
+            }
+            
+            // 璁惧鐘舵�佽繃婊�
+            if (deviceStatus != null && !deviceStatus.trim().isEmpty()) {
+                String convertedStatus = convertStatusFromString(deviceStatus);
+                if (convertedStatus != null) {
+                    wrapper.eq(DeviceConfig::getStatus, convertedStatus);
+                }
+            }
+            
+            // 鍏抽敭璇嶆悳绱�
+            if (keyword != null && !keyword.trim().isEmpty()) {
+                wrapper.and(w -> w
+                    .like(DeviceConfig::getDeviceName, keyword)
+                    .or().like(DeviceConfig::getDeviceCode, keyword)
+                    .or().like(DeviceConfig::getDescription, keyword));
+            }
+            
+            wrapper.eq(DeviceConfig::getIsDeleted, 0);
+            return (long) count(wrapper);
+        } catch (Exception e) {
+            log.error("鑾峰彇璁惧鎬绘暟澶辫触", e);
+            return 0L;
+        }
+    }
+
+    @Override
+    public List<String> getAllDeviceTypes() {
+        List<String> deviceTypes = new ArrayList<>();
+        deviceTypes.add("PLC璁惧");
+        deviceTypes.add("浼犳劅鍣ㄨ澶�");
+        deviceTypes.add("鎵ц鍣ㄨ澶�");
+        deviceTypes.add("浜烘満鐣岄潰璁惧");
+        return deviceTypes;
+    }
+
+    @Override
+    public List<String> getAllDeviceStatuses() {
+        List<String> deviceStatuses = new ArrayList<>();
+        deviceStatuses.add("鍦ㄧ嚎");
+        deviceStatuses.add("绂荤嚎");
+        deviceStatuses.add("缁存姢涓�");
+        deviceStatuses.add("鏁呴殰");
+        return deviceStatuses;
+    }
+
+    @Override
+    public boolean enableDevice(Long id) {
+        return updateDeviceEnabledState(id, true);
+    }
+
+    @Override
+    public boolean disableDevice(Long id) {
+        return updateDeviceEnabledState(id, false);
+    }
+
+    @Override
+    public boolean batchEnableDevices(List<Long> deviceIds) {
+        return batchUpdateDeviceEnabledState(deviceIds, true);
+    }
+
+    @Override
+    public boolean batchDisableDevices(List<Long> deviceIds) {
+        return batchUpdateDeviceEnabledState(deviceIds, false);
+    }
+
+    @Override
+    public DeviceConfigVO.HealthCheckResult performHealthCheck(Long id) {
+        try {
+            DeviceConfig device = getById(id);
+            if (device == null) {
+                log.warn("璁惧涓嶅瓨鍦�: {}", id);
+                DeviceConfigVO.HealthCheckResult result = new DeviceConfigVO.HealthCheckResult();
+                result.setIsHealthy(false);
+                result.setOverallStatus("璁惧涓嶅瓨鍦�");
+                result.setCheckTime(LocalDateTime.now());
+                return result;
+            }
+            
+            // 绠�鍖栫殑鍋ュ悍妫�鏌ラ�昏緫
+            boolean isHealthy = true;
+            List<String> issues = new ArrayList<>();
+            
+            // 妫�鏌P鍜岀鍙i厤缃�
+            if (device.getPlcIp() == null || device.getPlcIp().trim().isEmpty()) {
+                isHealthy = false;
+                issues.add("IP鍦板潃閰嶇疆缂哄け");
+            }
+            
+            if (device.getPlcPort() == null || device.getPlcPort() <= 0) {
+                isHealthy = false;
+                issues.add("绔彛閰嶇疆鏃犳晥");
+            }
+            
+            // 妫�鏌ヨ澶囩姸鎬�
+            if (device.getStatus() != null && device.getStatus().equals(DeviceConfig.Status.FAULT)) {
+                isHealthy = false;
+                issues.add("璁惧鐘舵�佸紓甯�");
+            }
+            
+            String message = isHealthy ? "璁惧杩愯姝e父" : String.join(";", issues);
+            log.info("璁惧鍋ュ悍妫�鏌ュ畬鎴�: {} - {}", id, message);
+            
+            DeviceConfigVO.HealthCheckResult result = new DeviceConfigVO.HealthCheckResult();
+            result.setIsHealthy(isHealthy);
+            result.setOverallStatus(message);
+            result.setCheckTime(LocalDateTime.now());
+            return result;
+        } catch (Exception e) {
+            log.error("璁惧鍋ュ悍妫�鏌ュけ璐�: {}", id, e);
+            DeviceConfigVO.HealthCheckResult result = new DeviceConfigVO.HealthCheckResult();
+            result.setIsHealthy(false);
+            result.setOverallStatus("鍋ュ悍妫�鏌ュけ璐�: " + e.getMessage());
+            result.setCheckTime(LocalDateTime.now());
+            return result;
+        }
+    }
+
+    @Override
+    public List<DeviceConfigVO.DeviceTreeNode> getDeviceTree(Long projectId) {
+        try {
+            List<DeviceConfig> devices = getDeviceList(projectId, null, null);
+            
+            return devices.stream().map(device -> {
+                DeviceConfigVO.DeviceTreeNode node = new DeviceConfigVO.DeviceTreeNode();
+                node.setId(device.getId());
+                node.setLabel(device.getDeviceName() + " (" + device.getDeviceCode() + ")");
+                node.setType("device");
+                node.setStatus(getStatusName(device.getStatus()));
+                // 灏嗛澶栦俊鎭斁鍏ata瀵硅薄
+                Map<String, Object> data = new HashMap<>();
+                data.put("deviceId", device.getId());
+                data.put("deviceCode", device.getDeviceCode());
+                data.put("deviceType", getDeviceTypeName(device.getDeviceType()));
+                node.setData(data);
+                node.setChildren(null); // 璁惧鑺傜偣娌℃湁瀛愯妭鐐�
+                return node;
+            }).collect(Collectors.toList());
+        } catch (Exception e) {
+            log.error("鑾峰彇璁惧鏍戠粨鏋勫け璐�", e);
+            return new ArrayList<>();
+        }
+    }
+}
\ No newline at end of file

--
Gitblit v1.8.0