From 2fc382585ca4420ec5af2bc254954602d56cf671 Mon Sep 17 00:00:00 2001
From: zch <zangch@mesnac.com>
Date: Fri, 21 Mar 2025 13:04:31 +0800
Subject: [PATCH] =?UTF-8?q?refactor(ems):=20=E4=BC=98=E5=8C=96=E7=9B=91?=
 =?UTF-8?q?=E6=8E=A7=E4=BF=A1=E6=81=AF=E6=A0=91=E6=9E=84=E5=BB=BA=E6=96=B9?=
 =?UTF-8?q?=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- 添加了基于数据量的并行处理逻辑,提高大数据量处理效率
- 引入异步处理机制,优化数据库查询性能
- 保留了原有的方法逻辑,确保功能一致性
- 新增方法实现了更高效的温度数据加载和父子关系构建
---
 .../impl/EmsBaseMonitorInfoServiceImpl.java   | 85 ++++++++++++++++++-
 1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/ruoyi-ems/src/main/java/com/ruoyi/ems/base/service/impl/EmsBaseMonitorInfoServiceImpl.java b/ruoyi-ems/src/main/java/com/ruoyi/ems/base/service/impl/EmsBaseMonitorInfoServiceImpl.java
index 50b4bf2..2b228f5 100644
--- a/ruoyi-ems/src/main/java/com/ruoyi/ems/base/service/impl/EmsBaseMonitorInfoServiceImpl.java
+++ b/ruoyi-ems/src/main/java/com/ruoyi/ems/base/service/impl/EmsBaseMonitorInfoServiceImpl.java
@@ -2,7 +2,7 @@ package com.ruoyi.ems.base.service.impl;
 
 import java.math.BigDecimal;
 import java.util.*;
-
+import java.util.concurrent.CompletableFuture;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -148,6 +148,88 @@ public class EmsBaseMonitorInfoServiceImpl implements IEmsBaseMonitorInfoService
      * @return 树结构列表
      */
     @Override
+    public List<EmsBaseMonitorInfo> buildMonitorInfoTree(List<EmsBaseMonitorInfo> baseMonitorInfos) {
+        // 数据量阈值,低于此值使用单线程,高于此值使用多线程
+        final int THRESHOLD = 100;
+
+        // 1. 提取监控类型为1L的设备编号 - 根据数据量选择是否并行
+        List<String> monitorCodes;
+        if(baseMonitorInfos.size() > THRESHOLD) {
+            monitorCodes = baseMonitorInfos.parallelStream()
+                    .filter(item -> !ObjectUtils.isEmpty(item) && item.getMonitorType() == 1L)
+                    .map(EmsBaseMonitorInfo::getMonitorCode)
+                    .collect(Collectors.toList());
+        } else {
+            monitorCodes = baseMonitorInfos.stream()
+                    .filter(item -> !ObjectUtils.isEmpty(item) && item.getMonitorType() == 1L)
+                    .map(EmsBaseMonitorInfo::getMonitorCode)
+                    .collect(Collectors.toList());
+        }
+
+        // 2. 创建温度数据Map - 异步执行耗时的数据库查询
+        Map<String, BigDecimal> tempDataMap = new HashMap<>();
+
+        // 数据库查询通常是IO密集型,使用异步可以提高效率
+        if (CollectionUtils.isNotEmpty(monitorCodes)) {
+            // 使用CompletableFuture异步获取温度数据
+            List<TWTempertureData> tempDatas =
+                    CompletableFuture.supplyAsync(() ->
+                            tWTempertureDataMapper.selectLastTWTempertureDataByMonitorCodes(monitorCodes)
+                    ).join(); // 等待数据库查询完成
+
+            tempDataMap = tempDatas.stream()
+                    .filter(data -> !ObjectUtils.isEmpty(data) && data.getTempreture() != null)
+                    .collect(Collectors.toMap(
+                            TWTempertureData::getMonitorId,
+                            TWTempertureData::getTempreture,
+                            (v1, v2) -> v1));
+        }
+
+        // 3. 收集所有设备ID和构建父子关系映射 - 单线程处理简单逻辑
+        Set<Long> allIds = baseMonitorInfos.stream()
+                .map(EmsBaseMonitorInfo::getObjId)
+                .collect(Collectors.toSet());
+
+        Map<Long, List<EmsBaseMonitorInfo>> parentChildMap = new HashMap<>();
+
+        // 4. 设置温度值并构建父子关系 - 简单循环,数据量不大时开销小
+        for (EmsBaseMonitorInfo info : baseMonitorInfos) {
+            // 设置温度值
+            if (info.getMonitorType() == 1L) {
+                BigDecimal temperature = tempDataMap.get(info.getMonitorCode());
+                if (temperature != null) {
+                    info.setTemperature(temperature);
+                }
+            }
+
+            // 构建父子关系映射
+            Long parentId = info.getParentId();
+            if (parentId != null) {
+                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(info);
+            }
+        }
+
+        // 5. 找出所有顶级节点
+        List<EmsBaseMonitorInfo> rootNodes = baseMonitorInfos.stream()
+                .filter(info -> info.getParentId() == null || !allIds.contains(info.getParentId()))
+                .collect(Collectors.toList());
+
+        // 6. 为顶级节点设置子节点
+        for (EmsBaseMonitorInfo root : rootNodes) {
+            setChildren(root, parentChildMap);
+        }
+
+        return rootNodes.isEmpty() ? baseMonitorInfos : rootNodes;
+    }
+
+    /**
+     * 构建前端所需要树结构
+     *
+     * @param
+     * @return 树结构列表
+     */
+/*
+    @Override
     public List<EmsBaseMonitorInfo> buildMonitorInfoTree(List<EmsBaseMonitorInfo> baseMonitorInfos) {
         // 创建一个List来存储设备编号,只获取监控类型为1L的设备编号
         List<String> monitorCodes = baseMonitorInfos.stream()
@@ -206,6 +288,7 @@ public class EmsBaseMonitorInfoServiceImpl implements IEmsBaseMonitorInfoService
 
         return rootNodes.isEmpty() ? baseMonitorInfos : rootNodes;
     }
+*/
 
     /**
      * 为节点设置子节点(优化的递归实现)