From 316243a5125cd52827a6a99757be73bb39b423f9 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 10:55:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E6=8C=89=E5=8D=8A=E5=B0=8F?= =?UTF-8?q?=E6=97=B6=E4=B8=80=E6=9D=A1=E6=95=B0=E6=8D=AE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DeviceDataAccumulateController.java | 3 +- .../service/DeviceDataAccumulateService.java | 2 +- .../back/service/common/CommonOpt.java | 42 +++--- .../common/LineDataHourAggregator.java | 126 +++++++++++++++++- .../impl/DeviceDataAccumulateServiceImpl.java | 15 ++- .../impl/DeviceDataMeasureServiceImpl.java | 5 +- 6 files changed, 157 insertions(+), 36 deletions(-) diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAccumulateController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAccumulateController.java index 7404568..616a149 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAccumulateController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAccumulateController.java @@ -116,6 +116,7 @@ public class DeviceDataAccumulateController { @Operation(summary = "获取7日趋势数据") @RequestMapping(value = "/getLineData",method = RequestMethod.POST) public SimpleDataResponse> getLineData( + @Parameter(name = "searchType", description = "1-按小时,2-全部数据", required = true) Integer searchType, @Parameter(name = "LoginName", description = "Login name", required = true, schema = @Schema(defaultValue = "admin")) @RequestHeader(required=true) String LoginName, @Parameter(name = "AccessToken", description = "Authentication token", required = true) @RequestHeader(required=true) String AccessToken, @Parameter(name = "UserId", description = "User ID", required = true, schema = @Schema(defaultValue = "1")) @RequestHeader(required=true) Long UserId, @@ -123,7 +124,7 @@ public class DeviceDataAccumulateController { @Parameter(name = "LanguageType", description = "Language type (0: Chinese, 1: English, 2: Japanese)", required = true, schema = @Schema(defaultValue = "2")) @RequestHeader(required=true) Integer LanguageType, @RequestBody LineDataSearchParams lineDataSearchParams ) throws BusinessException { - return deviceDataAccumulateService.getLineData(lineDataSearchParams, CompanyId, UserId, LanguageType); + return deviceDataAccumulateService.getLineData(searchType, lineDataSearchParams, CompanyId, UserId, LanguageType); } } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataAccumulateService.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataAccumulateService.java index c5db5b6..cf72fa3 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataAccumulateService.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataAccumulateService.java @@ -18,5 +18,5 @@ public interface DeviceDataAccumulateService { List handleDeviceAccumulateData(AccumulateDataSearchParam pageSearchParam); - SimpleDataResponse> getLineData(LineDataSearchParams lineDataSearchParams, Long companyId, Long userId, Integer languageType); + SimpleDataResponse> getLineData(Integer searchType, LineDataSearchParams lineDataSearchParams, Long companyId, Long userId, Integer languageType); } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/CommonOpt.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/CommonOpt.java index 45fe052..236842b 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/CommonOpt.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/CommonOpt.java @@ -445,56 +445,44 @@ public class CommonOpt { private void processResult(ResultSet result, LineData lineData, DeviceInfo deviceInfo, Double lastDayValue) { try { - // 用于存储 xData 和 yData List xDataList = new ArrayList<>(); List yDataList = new ArrayList<>(); - // 使用 DateTimeFormatter 来格式化时间 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - ObjectMapper mapper = new ObjectMapper(); + DateTimeFormatter formatter = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - // 用于存储每个小时最后一条数据(仅在 deviceType = 2 时使用) - Map lastHourData = new LinkedHashMap<>(); // 按插入顺序保存数据 + ZoneId JST = ZoneId.of("Asia/Tokyo"); - // 遍历查询结果 do { - // 获取 receive_ts 和 rawData long receiveTs = result.getLong("upload_at"); String value = result.getString("upload_value"); - // 如果 receiveTs 为 0(表示无效时间戳),跳过当前行 if (receiveTs == 0) { - continue; // 跳过当前循环的剩余部分,继续处理下一行 + continue; } - // 将 long 时间戳转换为 LocalDateTime(日本时区) + // 日本时区时间 Instant instant = Instant.ofEpochMilli(receiveTs); - String formattedDate = instant.atZone(ZoneId.of("Asia/Tokyo")) + String formattedDate = instant + .atZone(JST) .toLocalDateTime() .format(formatter); - // 将 rawData解析 添加到 yData -// String value = extractFirstValue(mapper, rawData); double todayValue = StringUtils.isBlank(value) ? 0.0 : new BigDecimal(value).doubleValue(); - //计算差值 - double yValue = todayValue;//默认今天值 - if (null != lastDayValue && yValue >= lastDayValue){ + // 默认今天值 + double yValue = todayValue; + + // 计算差值 + if (lastDayValue != null && todayValue >= lastDayValue) { yValue = todayValue - lastDayValue; } - // 按小时分组,每个小时只保存最后一条数据 - String hourKey = formattedDate.substring(0, 13) + ":00:00"; - lastHourData.put(hourKey, yValue); - } while (result.next()); + xDataList.add(formattedDate); + yDataList.add(CommonUtil.formatDecimal(yValue, deviceInfo.getDashboardDecimalPlaces())); - //只取每小时的最后一条数据 - for (Map.Entry entry : lastHourData.entrySet()) { - xDataList.add(entry.getKey()); // 添加每小时的时间 - yDataList.add(CommonUtil.formatDecimal(entry.getValue(), deviceInfo.getDashboardDecimalPlaces())); // 添加每小时最后一条数据的值 - } + } while (result.next()); - // 将处理后的数据加入到 lineData 中 lineData.getXData().addAll(xDataList); lineData.getYData().addAll(yDataList); diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java index 0aabcbe..04e96f6 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java @@ -2,12 +2,11 @@ package com.dongjian.dashboard.back.service.common; import com.dongjian.dashboard.back.vo.device.LineData; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; /** * 给计测设备,按小时聚合数据,求平均值 @@ -65,5 +64,124 @@ public class LineDataHourAggregator { lineData.setXData(newX); lineData.setYData(newY); } + + /** + * 给计测设备,按半小时聚合数据,求平均值 + * 00~29 分 → HH:00:00 + * 30~59 分 → HH:30:00 + */ + public static void aggregateAverageByHalfHour(LineData lineData) { + + List xData = lineData.getXData(); + List yData = lineData.getYData(); + + if (xData == null || yData == null || xData.size() != yData.size()) { + return; + } + + // halfHour -> List + Map> halfHourMap = new TreeMap<>(); + + for (int i = 0; i < xData.size(); i++) { + String timeStr = String.valueOf(xData.get(i)); + Object yVal = yData.get(i); + + if (yVal == null) { + continue; + } + + LocalDateTime time = LocalDateTime.parse(timeStr, INPUT_FMT); + + int minute = time.getMinute(); + int halfHourMinute = minute < 30 ? 0 : 30; + + LocalDateTime halfHourTime = time + .withMinute(halfHourMinute) + .withSecond(0) + .withNano(0); + + String halfHourKey = halfHourTime.format(INPUT_FMT); + + halfHourMap + .computeIfAbsent(halfHourKey, k -> new ArrayList<>()) + .add(Double.parseDouble(String.valueOf(yVal))); + } + + // 重新构建 xData / yData + List newX = new ArrayList<>(); + List newY = new ArrayList<>(); + + for (Map.Entry> entry : halfHourMap.entrySet()) { + newX.add(entry.getKey()); + + double avg = entry.getValue() + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0); + + newY.add(avg); + } + + lineData.setXData(newX); + lineData.setYData(newY); + } + + + /** + * 按半小时聚合,只保留每个半小时内的最后一条数据 + */ + public static void aggregateLastByHalfHour(LineData lineData) { + + List xData = lineData.getXData(); + List yData = lineData.getYData(); + + if (xData == null || yData == null || xData.size() != yData.size()) { + return; + } + + // halfHour -> lastValue + Map halfHourLastMap = new TreeMap<>(); + + for (int i = 0; i < xData.size(); i++) { + String timeStr = String.valueOf(xData.get(i)); + Object yVal = yData.get(i); + + if (yVal == null) { + continue; + } + + LocalDateTime time = LocalDateTime.parse(timeStr, INPUT_FMT); + + int minute = time.getMinute(); + int halfHourMinute = minute < 30 ? 0 : 30; + + LocalDateTime halfHourTime = time + .withMinute(halfHourMinute) + .withSecond(0) + .withNano(0); + + String halfHourKey = halfHourTime.format(INPUT_FMT); + + // 同一个半小时,后面的会覆盖前面的 → 自然就是“最后一条” + halfHourLastMap.put( + halfHourKey, + Double.parseDouble(String.valueOf(yVal)) + ); + } + + // 重新构建 xData / yData + List newX = new ArrayList<>(); + List newY = new ArrayList<>(); + + for (Map.Entry entry : halfHourLastMap.entrySet()) { + newX.add(entry.getKey()); + newY.add(entry.getValue()); + } + + lineData.setXData(newX); + lineData.setYData(newY); + } + } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAccumulateServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAccumulateServiceImpl.java index 4c2fe81..5218de3 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAccumulateServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAccumulateServiceImpl.java @@ -22,6 +22,7 @@ import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.model.DeviceRawdataRealtime; import com.dongjian.dashboard.back.service.DeviceDataAccumulateService; import com.dongjian.dashboard.back.service.common.CommonOpt; +import com.dongjian.dashboard.back.service.common.LineDataHourAggregator; import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.util.DateUtil; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; @@ -183,9 +184,19 @@ public class DeviceDataAccumulateServiceImpl implements DeviceDataAccumulateServ } @Override - public SimpleDataResponse> getLineData(LineDataSearchParams lineDataSearchParams, + public SimpleDataResponse> getLineData(Integer searchType, LineDataSearchParams lineDataSearchParams, Long companyId, Long userId, Integer languageType) { - return SimpleDataResponse.success(commonOpt.getLineData(companyId, lineDataSearchParams, 2)); + if (null == searchType) { + searchType = 2;//默认全部数据 + } + List lineDataList = commonOpt.getLineData(companyId, lineDataSearchParams, 2); + if (1 == searchType && CollectionUtils.isNotEmpty(lineDataList)) { + lineDataList.forEach(lineData -> { + //按半小时聚合 + LineDataHourAggregator.aggregateLastByHalfHour(lineData); + }); + } + return SimpleDataResponse.success(lineDataList); } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataMeasureServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataMeasureServiceImpl.java index fe304cc..ba06465 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataMeasureServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataMeasureServiceImpl.java @@ -238,7 +238,10 @@ public class DeviceDataMeasureServiceImpl implements DeviceDataMeasureService { } List lineDataList = commonOpt.getLineData(companyId, lineDataSearchParams, 3); if (1 == searchType && CollectionUtils.isNotEmpty(lineDataList)) { - lineDataList.forEach(LineDataHourAggregator::aggregateByHour); + lineDataList.forEach(lineData -> { + //按半小时聚合 + LineDataHourAggregator.aggregateAverageByHalfHour(lineData); + }); } return SimpleDataResponse.success(lineDataList); }