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 01/52] =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E6=8C=89=E5=8D=8A?= =?UTF-8?q?=E5=B0=8F=E6=97=B6=E4=B8=80=E6=9D=A1=E6=95=B0=E6=8D=AE=E6=98=BE?= =?UTF-8?q?=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); } From b7e58dd9099fde0e125448b2e0de03452f43bdf0 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 11:24:36 +0800 Subject: [PATCH 02/52] =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E6=A8=AA=E5=9D=90?= =?UTF-8?q?=E6=A0=87=E8=A1=A5=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/LineDataHourAggregator.java | 46 +++++++++++++++++++ .../impl/DeviceDataAccumulateServiceImpl.java | 2 + .../impl/DeviceDataMeasureServiceImpl.java | 2 + 3 files changed, 50 insertions(+) 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 04e96f6..7cff13b 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 @@ -65,6 +65,52 @@ public class LineDataHourAggregator { lineData.setYData(newY); } + /** + * 将 LineData 补齐为【日本时区】当天 0:00 - 23:30 的 48 个半小时点 + * 没有数据的时间点,Y 值补 0 + */ + public static void fillTodayHalfHourPointsJST(LineData lineData) { + + List xData = lineData.getXData(); + List yData = lineData.getYData(); + + if (xData == null || yData == null || xData.size() != yData.size()) { + return; + } + + ZoneId JST = ZoneId.of("Asia/Tokyo"); + + // 现有数据转 Map + Map valueMap = new HashMap<>(); + for (int i = 0; i < xData.size(); i++) { + valueMap.put( + String.valueOf(xData.get(i)), + Double.parseDouble(String.valueOf(yData.get(i))) + ); + } + + // 日本“今天” + LocalDate todayJst = LocalDate.now(JST); + + List newX = new ArrayList<>(48); + List newY = new ArrayList<>(48); + + // 日本当天 00:00 + LocalDateTime start = todayJst.atStartOfDay(); + + for (int i = 0; i < 48; i++) { + LocalDateTime timePoint = start.plusMinutes(i * 30); + String key = timePoint.format(INPUT_FMT); + + newX.add(key); + newY.add(valueMap.getOrDefault(key, null)); + } + + lineData.setXData(newX); + lineData.setYData(newY); + } + + /** * 给计测设备,按半小时聚合数据,求平均值 * 00~29 分 → HH:00:00 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 5218de3..0070ae5 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 @@ -194,6 +194,8 @@ public class DeviceDataAccumulateServiceImpl implements DeviceDataAccumulateServ lineDataList.forEach(lineData -> { //按半小时聚合 LineDataHourAggregator.aggregateLastByHalfHour(lineData); + //补齐48个横坐标 + LineDataHourAggregator.fillTodayHalfHourPointsJST(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 ba06465..32f6b99 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 @@ -241,6 +241,8 @@ public class DeviceDataMeasureServiceImpl implements DeviceDataMeasureService { lineDataList.forEach(lineData -> { //按半小时聚合 LineDataHourAggregator.aggregateAverageByHalfHour(lineData); + //补齐48个横坐标 + LineDataHourAggregator.fillTodayHalfHourPointsJST(lineData); }); } return SimpleDataResponse.success(lineDataList); From 67658609bab18d6e086fc3f88981f9e70114ef00 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 13:14:23 +0800 Subject: [PATCH 03/52] =?UTF-8?q?=E5=91=8A=E8=AD=A6=E5=B7=B2=E8=BF=87?= =?UTF-8?q?=E5=8E=BB=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/config/language/msg/msg_cn.yml | 1 + .../resources/config/language/msg/msg_en.yml | 1 + .../resources/config/language/msg/msg_jp.yml | 1 + .../mappers/ex/DeviceInfoMapperExt.xml | 32 ++++++++++- .../back/vo/data/DeviceAlarmData.java | 6 ++ .../back/service/common/CommonOpt.java | 15 +++++ .../impl/DeviceDataAlarmServiceImpl.java | 4 ++ .../dashboard/back/util/DurationData.java | 55 +++++++++++++++++++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/DurationData.java diff --git a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_cn.yml b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_cn.yml index d882e5e..c91f1f4 100644 --- a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_cn.yml +++ b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_cn.yml @@ -77,6 +77,7 @@ msgcn: levelNameExist: 层级名称已存在 invalidParentLevel: 无效的父级层级 levelReferencedByChildren: 已被下级层级绑定,请先解绑后再删除 + elapsedTime: '{0}天{1}小时{2}分' operationLogMap: addRole: 新增角色 editRole: 编辑角色 diff --git a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_en.yml b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_en.yml index 4263fa6..96e74e0 100644 --- a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_en.yml +++ b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_en.yml @@ -77,6 +77,7 @@ msgen: levelNameExist: Level name already exists invalidParentLevel: Invalid parent level levelReferencedByChildren: It is bound by child levels. Please unbind them before deleting. + elapsedTime: '{0}d {1}h {2}m' operationLogMap: addRole: Add Role editRole: Edit Role diff --git a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_jp.yml b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_jp.yml index 373e8f4..cb30b1b 100644 --- a/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_jp.yml +++ b/dongjian-dashboard-back-common/src/main/resources/config/language/msg/msg_jp.yml @@ -77,6 +77,7 @@ msgjp: levelNameExist: 階層名は既に存在しています invalidParentLevel: 無効な上位階層です levelReferencedByChildren: 下位階層に紐づいています。削除する前に紐付けを解除してください。 + elapsedTime: '{0}日{1}時間{2}分間' operationLogMap: addRole: ロールを追加 editRole: ロールを編集 diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml index dcb3613..9849161 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml @@ -76,6 +76,15 @@ drr.receive_ts + + device_info.device_name + + + device_info.monitoring_point_name + + + data_provider.name + drr.receive_ts @@ -88,6 +97,7 @@ DESC + ,device_info.id desc @@ -179,6 +189,15 @@ bss.latest_ts + + device_info.device_name + + + device_info.monitoring_point_name + + + data_provider.name + bss.latest_ts @@ -191,6 +210,7 @@ DESC + ,device_info.id desc diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java index 2cf2a15..55dfd2f 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java @@ -33,5 +33,11 @@ public class DeviceAlarmData extends BaseData{ @Schema(description = "资产记号",example = "122") private String assetSymbol; + @Schema(description = "已过去时长(毫秒级时间戳)", example = "15306854254") + private Long elapsedTime; + + @Schema(description = "已过去时长", example = "177日3時間54分間") + private String elapsedTimeStr; + } 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 236842b..d07d65a 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 @@ -2,6 +2,7 @@ package com.dongjian.dashboard.back.service.common; import java.math.BigDecimal; import java.sql.*; +import java.text.MessageFormat; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; @@ -13,12 +14,14 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import com.dongjian.dashboard.back.common.Constants; +import com.dongjian.dashboard.back.common.language.msg.MsgLanguageChange; import com.dongjian.dashboard.back.common.response.ResponseCode; import com.dongjian.dashboard.back.common.response.SimpleDataResponse; import com.dongjian.dashboard.back.dao.ex.*; import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.model.*; import com.dongjian.dashboard.back.util.DESUtil; +import com.dongjian.dashboard.back.util.DurationData; import com.dongjian.dashboard.back.vo.building.BindedBuildingVO; import com.dongjian.dashboard.back.vo.company.AuroraInfo; import com.dongjian.dashboard.back.vo.device.LineData; @@ -67,6 +70,9 @@ public class CommonOpt { private DeviceRawdataRealtimeMapperExt deviceRawdataRealtimeMapperExt; @Autowired private DeviceInfoMapperExt deviceInfoMapperExt; + + @Autowired + private MsgLanguageChange msgLanguageChange; /** @@ -650,4 +656,13 @@ public class CommonOpt { return null; } } + + public String formatElapsedTime(Long elapsedTime, Integer languageType) { + DurationData durationData = DurationData.fromMilliseconds(elapsedTime); + return MessageFormat.format( + msgLanguageChange.getParameterMapByCode(languageType, "elapsedTime"), + durationData.getDays(), + durationData.getHours(), + durationData.getMinutes()); + } } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java index 9503d98..8a7fc46 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java @@ -98,6 +98,8 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { if (CollectionUtils.isNotEmpty(resultList)) { // 查询 favorited_device 表中所有设备的 device_id List favoritedDeviceIds = favoritedDeviceMapperExt.getFavoritedDeviceIds(); + + long currentTs = System.currentTimeMillis(); for (DeviceAlarmData data : resultList){ String deviceId = data.getDeviceId().toLowerCase(); // 判断设备是否在 favorited_device 表中 @@ -109,6 +111,8 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { data.setAlertLevelStr(msgLanguageChange.getParameterMapByCode(languageType, "alertLevel_" + data.getAlertLevel())); data.setConfirmStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "confirmStatus_" + data.getConfirmStatus())); data.setHandleStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "handleStatus_" + data.getHandleStatus())); + data.setElapsedTime(currentTs - data.getUploadTimestamp()); + data.setElapsedTimeStr(commonOpt.formatElapsedTime(data.getElapsedTime(), languageType)); } } diff --git a/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/DurationData.java b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/DurationData.java new file mode 100644 index 0000000..8c4c6f2 --- /dev/null +++ b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/DurationData.java @@ -0,0 +1,55 @@ +package com.dongjian.dashboard.back.util; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * 持续时间对象,包含结构化时间单位 + */ +public class DurationData { + private long days; + private long hours; + private long minutes; + private long seconds; + + // 构造函数 + public DurationData(long days, long hours, long minutes, long seconds) { + this.days = days; + this.hours = hours; + this.minutes = minutes; + this.seconds = seconds; + } + + // Getters + public long getDays() { return days; } + public long getHours() { return hours; } + public long getMinutes() { return minutes; } + public long getSeconds() { return seconds; } + + // 从毫秒创建 + public static DurationData fromMilliseconds(long ms) { + if (ms <= 0) { + return new DurationData(0, 0, 0, 0); + } + + long totalSeconds = ms / 1000; + long days = totalSeconds / (24 * 3600); + long hours = (totalSeconds % (24 * 3600)) / 3600; + long minutes = (totalSeconds % 3600) / 60; + long seconds = totalSeconds % 60; + + return new DurationData(days, hours, minutes, seconds); + } + + @Override + public String toString() { + return String.format("DurationData{days=%d, hours=%d, minutes=%d, seconds=%d}", + days, hours, minutes, seconds); + } + + public static void main(String[] args){ + DurationData durationData = DurationData.fromMilliseconds(15306504932L); + System.out.println(durationData); + System.out.println(durationData.getDays()); + } +} From f822491d32f6c4efe78cb5a9cefbbc49f4c7e510 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 14:04:34 +0800 Subject: [PATCH 04/52] =?UTF-8?q?=E7=B4=AF=E7=A7=AF=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=EF=BC=8CcategoryId=E5=A2=9E=E5=8A=A01006?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/dongjian/dashboard/back/common/Constants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java index 17b73e9..7904d83 100644 --- a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java +++ b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java @@ -70,7 +70,7 @@ public class Constants { CATEGORY_MAP.put(CATEGORY_MEASURE, new ArrayList<>(List.of(1003L))); - CATEGORY_MAP.put(CATEGORY_ACCUMULATE, new ArrayList<>(List.of(1002L))); + CATEGORY_MAP.put(CATEGORY_ACCUMULATE, new ArrayList<>(List.of(1002L,1006L))); CATEGORY_MAP.put(CATEGORY_STATUS, new ArrayList<>(List.of(1004L))); From c6e642b4fbd87d4ca8a7f4423e7b2cdc804ffddc Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 19:01:49 +0800 Subject: [PATCH 05/52] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=B4=AF=E7=A7=AF?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=89=8D=E6=97=A5=E5=80=BC=E3=80=81=E5=89=8D?= =?UTF-8?q?=E5=B9=B4=E5=80=BC=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DashboardRecordAccumulateMapperExt.java | 7 +++ .../DashboardRecordAccumulateMapperExt.xml | 19 ++++++++ .../back/vo/record/RecordAccumulateDto.java | 14 ++++++ .../back/service/common/CommonOpt.java | 43 +++++++++++++++++++ .../impl/DeviceDataAccumulateServiceImpl.java | 17 ++++++-- 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/record/RecordAccumulateDto.java diff --git a/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/aurora/DashboardRecordAccumulateMapperExt.java b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/aurora/DashboardRecordAccumulateMapperExt.java index 87c5eec..c165ce9 100644 --- a/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/aurora/DashboardRecordAccumulateMapperExt.java +++ b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/aurora/DashboardRecordAccumulateMapperExt.java @@ -2,6 +2,7 @@ package com.dongjian.dashboard.back.dao.aurora; import com.dongjian.dashboard.back.dao.auto.DashboardRecordAccumulateMapper; import com.dongjian.dashboard.back.vo.device.DeviceIncrement; +import com.dongjian.dashboard.back.vo.record.RecordAccumulateDto; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -33,4 +34,10 @@ public interface DashboardRecordAccumulateMapperExt extends DashboardRecordAccum @Param("targetSeconds") int targetSeconds ); + List selectByDay( + @Param("deviceIds") List deviceIds, + @Param("year") int year, + @Param("month") int month, + @Param("day") int day + ); } diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/aurora/DashboardRecordAccumulateMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/aurora/DashboardRecordAccumulateMapperExt.xml index b045c80..a62381b 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/aurora/DashboardRecordAccumulateMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/aurora/DashboardRecordAccumulateMapperExt.xml @@ -77,4 +77,23 @@ + + + \ No newline at end of file diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/record/RecordAccumulateDto.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/record/RecordAccumulateDto.java new file mode 100644 index 0000000..6195939 --- /dev/null +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/record/RecordAccumulateDto.java @@ -0,0 +1,14 @@ +package com.dongjian.dashboard.back.vo.record; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class RecordAccumulateDto { + private String deviceId; + private Double incrementToday; + private Integer dateHour; + private Integer dateMinute; + private Integer dateSecond; +} 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 d07d65a..0931806 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 @@ -24,7 +24,9 @@ import com.dongjian.dashboard.back.util.DESUtil; import com.dongjian.dashboard.back.util.DurationData; import com.dongjian.dashboard.back.vo.building.BindedBuildingVO; import com.dongjian.dashboard.back.vo.company.AuroraInfo; +import com.dongjian.dashboard.back.vo.device.DeviceIncrement; import com.dongjian.dashboard.back.vo.device.LineData; +import com.dongjian.dashboard.back.vo.record.RecordAccumulateDto; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.collections.CollectionUtils; @@ -665,4 +667,45 @@ public class CommonOpt { durationData.getHours(), durationData.getMinutes()); } + + public Map toDeviceIncrementMap( + List records, + int targetSeconds, + String field + ) { + Map result = new HashMap<>(); + Map diffMap = new HashMap<>(); + + for (RecordAccumulateDto r : records) { + String deviceIdLower = r.getDeviceId().toLowerCase(); + int secondsOfDay = r.getDateHour() * 3600 + r.getDateMinute() * 60 + r.getDateSecond(); + int diff = Math.abs(secondsOfDay - targetSeconds); + + if (diff > 600) { + continue; + } + + Integer bestDiff = diffMap.get(deviceIdLower); + if (bestDiff == null || diff < bestDiff) { + diffMap.put(deviceIdLower, diff); + + DeviceIncrement di = result.get(deviceIdLower); + if (di == null) { + di = new DeviceIncrement(); + di.setDeviceId(deviceIdLower); + } + + if ("yesterday".equals(field)) { + di.setYesterdayIncrement(r.getIncrementToday()); + } else { + di.setLastYearIncrement(r.getIncrementToday()); + } + + result.put(deviceIdLower, di); + } + } + + return result; + } + } 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 0070ae5..0a2e501 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 @@ -1,5 +1,6 @@ package com.dongjian.dashboard.back.service.impl; +import java.math.BigDecimal; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.time.LocalDate; @@ -28,6 +29,7 @@ import com.dongjian.dashboard.back.util.DateUtil; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; import com.dongjian.dashboard.back.vo.device.DeviceIncrement; import com.dongjian.dashboard.back.vo.device.LineData; +import com.dongjian.dashboard.back.vo.record.RecordAccumulateDto; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import org.apache.commons.collections.CollectionUtils; @@ -146,10 +148,17 @@ public class DeviceDataAccumulateServiceImpl implements DeviceDataAccumulateServ // 批量查询增量数据并构建 Map Map todayMap = dashboardRecordAccumulateMapperExt.selectTodayIncrement(todayDeviceIds, today.getYear(), today.getMonthValue(), today.getDayOfMonth()) .stream().collect(Collectors.toMap(di -> di.getDeviceId().toLowerCase(), Function.identity())); - Map yesterdayMap = dashboardRecordAccumulateMapperExt.selectYesterdayIncrement(deviceIds, yesterday.getYear(), yesterday.getMonthValue(), yesterday.getDayOfMonth(), targetSeconds) - .stream().collect(Collectors.toMap(di -> di.getDeviceId().toLowerCase(), Function.identity())); - Map lastYearMap = dashboardRecordAccumulateMapperExt.selectLastYearIncrement(deviceIds, lastYear.getYear(), lastYear.getMonthValue(), lastYear.getDayOfMonth(), targetSeconds) - .stream().collect(Collectors.toMap(di -> di.getDeviceId().toLowerCase(), Function.identity())); + +// Map yesterdayMap = dashboardRecordAccumulateMapperExt.selectYesterdayIncrement(deviceIds, yesterday.getYear(), yesterday.getMonthValue(), yesterday.getDayOfMonth(), targetSeconds) +// .stream().collect(Collectors.toMap(di -> di.getDeviceId().toLowerCase(), Function.identity())); + List yesterdayRecords = dashboardRecordAccumulateMapperExt.selectByDay(deviceIds, yesterday.getYear(), yesterday.getMonthValue(), yesterday.getDayOfMonth()); + Map yesterdayMap = commonOpt.toDeviceIncrementMap(yesterdayRecords, targetSeconds, "yesterday"); + +// Map lastYearMap = dashboardRecordAccumulateMapperExt.selectLastYearIncrement(deviceIds, lastYear.getYear(), lastYear.getMonthValue(), lastYear.getDayOfMonth(), targetSeconds) +// .stream().collect(Collectors.toMap(di -> di.getDeviceId().toLowerCase(), Function.identity())); + List lastYearRecords = dashboardRecordAccumulateMapperExt.selectByDay(deviceIds, lastYear.getYear(), lastYear.getMonthValue(), lastYear.getDayOfMonth()); + Map lastYearMap = commonOpt.toDeviceIncrementMap(lastYearRecords, targetSeconds, "lastYear"); + resultList.forEach(data -> { String deviceId = data.getDeviceId().toLowerCase(); From 7ef0631145378fc3809d4a09d80f9d2cf57b5f97 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 23 Jan 2026 22:59:01 +0800 Subject: [PATCH 06/52] =?UTF-8?q?ydata=E6=94=B9=E6=88=90=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/vo/device/LineData.java | 4 +- .../back/service/common/CommonOpt.java | 28 +-- .../common/LineDataHourAggregator.java | 195 +++++++++--------- 3 files changed, 110 insertions(+), 117 deletions(-) diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java index 2f7f2ad..6938200 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java @@ -4,7 +4,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Data public class LineData { @@ -16,6 +18,6 @@ public class LineData { private List xData = new ArrayList<>(); @Schema(description = "Y-axis data", example = "[]") - private List yData = new ArrayList<>(); + private Map> yData = new HashMap<>(); } 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 0931806..e88bdd7 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 @@ -39,13 +39,13 @@ import org.springframework.stereotype.Component; import com.dongjian.dashboard.back.util.CommonUtil; -/** +/** * @author Mr.Jiang -* @time 2022年5月28日 上午7:41:40 +* @time 2022年5月28日 上午7:41:40 */ @Component public class CommonOpt { - + private static Logger logger = LoggerFactory.getLogger(CommonOpt.class); public enum ExtractStrategy { @@ -61,7 +61,7 @@ public class CommonOpt { @Value("${spring.datasource.url}") private String dbUrl; - + @Autowired private BasicCompanyMapperExt basicCompanyMapperExt; @Autowired @@ -75,13 +75,13 @@ public class CommonOpt { @Autowired private MsgLanguageChange msgLanguageChange; - + /** * 根据自身企业ID获取子企业ID的list,list包含自身ID - * + * * @param companyId 自身ID - * + * * @return */ public List getSelfAndSubCompanyId(Long companyId) { @@ -91,7 +91,7 @@ public class CommonOpt { return idsList; } - + private void collectChildIds(List idsList, String parentCompanyIds) { Map searchChildMap = new HashMap(); searchChildMap.put("companyIds", parentCompanyIds); @@ -103,14 +103,14 @@ public class CommonOpt { } } - + /** * 过滤掉不属于targetCompany和它子企业的ID - * + * * @param targetCompanyId 指定企业ID - * + * * @param needProcessedCompanyIds 需要被处理的企业ID - * + * */ public List filterCompanyIds(Long targetCompanyId, String needProcessedCompanyIds) { List selfAndSubCompanyList = getSelfAndSubCompanyId(targetCompanyId); @@ -444,7 +444,7 @@ public class CommonOpt { } while (result.next()); lineData.getXData().addAll(xDataList); - lineData.getYData().addAll(yDataList); + lineData.getYData().put("common", yDataList); } catch (Exception e) { logger.error("Error processing result set", e); @@ -492,7 +492,7 @@ public class CommonOpt { } while (result.next()); lineData.getXData().addAll(xDataList); - lineData.getYData().addAll(yDataList); + lineData.getYData().put("common", yDataList); } catch (Exception e) { logger.error("Error processing result set", e); 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 7cff13b..e191ee8 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 @@ -22,43 +22,51 @@ public class LineDataHourAggregator { public static void aggregateByHour(LineData lineData) { List xData = lineData.getXData(); - List yData = lineData.getYData(); + Map> yDataMap = lineData.getYData(); - if (xData == null || yData == null || xData.size() != yData.size()) { + if (xData == null || yDataMap == null || yDataMap.isEmpty()) { return; } - // hour -> List - Map> hourMap = new TreeMap<>(); + // hour -> index + Map hourIndexMap = new TreeMap<>(); + Map>> hourValueMap = 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); String hourKey = time.format(HOUR_FMT); - hourMap.computeIfAbsent(hourKey, k -> new ArrayList<>()).add(Double.parseDouble(String.valueOf(yVal))); + hourIndexMap.putIfAbsent(hourKey, hourIndexMap.size()); + + for (Map.Entry> entry : yDataMap.entrySet()) { + Object yVal = entry.getValue().get(i); + if (yVal == null) { + continue; + } + + hourValueMap + .computeIfAbsent(hourKey, k -> new HashMap<>()) + .computeIfAbsent(entry.getKey(), k -> new ArrayList<>()) + .add(Double.parseDouble(String.valueOf(yVal))); + } } - // 重新构建 xData / yData List newX = new ArrayList<>(); - List newY = new ArrayList<>(); + Map> newY = new HashMap<>(); - for (Map.Entry> entry : hourMap.entrySet()) { - newX.add(entry.getKey()); + for (String hourKey : hourIndexMap.keySet()) { + newX.add(hourKey); - double avg = entry.getValue() - .stream() - .mapToDouble(Double::doubleValue) - .average() - .orElse(0); + Map> seriesMap = hourValueMap.get(hourKey); + if (seriesMap == null) { + continue; + } - newY.add(avg); + for (Map.Entry> e : seriesMap.entrySet()) { + double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); + newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); + } } lineData.setXData(newX); @@ -72,38 +80,42 @@ public class LineDataHourAggregator { public static void fillTodayHalfHourPointsJST(LineData lineData) { List xData = lineData.getXData(); - List yData = lineData.getYData(); + Map> yDataMap = lineData.getYData(); - if (xData == null || yData == null || xData.size() != yData.size()) { + if (xData == null || yDataMap == null) { return; } ZoneId JST = ZoneId.of("Asia/Tokyo"); + LocalDate todayJst = LocalDate.now(JST); + LocalDateTime start = todayJst.atStartOfDay(); + + // 原数据转 Map:time -> series -> value + Map> valueMap = new HashMap<>(); - // 现有数据转 Map - Map valueMap = new HashMap<>(); for (int i = 0; i < xData.size(); i++) { - valueMap.put( - String.valueOf(xData.get(i)), - Double.parseDouble(String.valueOf(yData.get(i))) - ); + String time = String.valueOf(xData.get(i)); + for (Map.Entry> e : yDataMap.entrySet()) { + valueMap + .computeIfAbsent(time, k -> new HashMap<>()) + .put(e.getKey(), e.getValue().get(i)); + } } - // 日本“今天” - LocalDate todayJst = LocalDate.now(JST); - List newX = new ArrayList<>(48); - List newY = new ArrayList<>(48); - - // 日本当天 00:00 - LocalDateTime start = todayJst.atStartOfDay(); + Map> newY = new HashMap<>(); for (int i = 0; i < 48; i++) { - LocalDateTime timePoint = start.plusMinutes(i * 30); - String key = timePoint.format(INPUT_FMT); - + LocalDateTime t = start.plusMinutes(i * 30); + String key = t.format(INPUT_FMT); newX.add(key); - newY.add(valueMap.getOrDefault(key, null)); + + Map seriesValues = valueMap.get(key); + for (String series : yDataMap.keySet()) { + newY + .computeIfAbsent(series, k -> new ArrayList<>()) + .add(seriesValues == null ? null : seriesValues.get(series)); + } } lineData.setXData(newX); @@ -119,54 +131,42 @@ public class LineDataHourAggregator { public static void aggregateAverageByHalfHour(LineData lineData) { List xData = lineData.getXData(); - List yData = lineData.getYData(); + Map> yDataMap = lineData.getYData(); - if (xData == null || yData == null || xData.size() != yData.size()) { + if (xData == null || yDataMap == null) { return; } - // halfHour -> List - Map> halfHourMap = new TreeMap<>(); + 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(String.valueOf(xData.get(i)), INPUT_FMT); - LocalDateTime time = LocalDateTime.parse(timeStr, INPUT_FMT); + int minute = time.getMinute() < 30 ? 0 : 30; + LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); + String key = halfHourTime.format(INPUT_FMT); - int minute = time.getMinute(); - int halfHourMinute = minute < 30 ? 0 : 30; + for (Map.Entry> e : yDataMap.entrySet()) { + Object yVal = e.getValue().get(i); + if (yVal == null) continue; - 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))); + halfHourMap + .computeIfAbsent(key, k -> new HashMap<>()) + .computeIfAbsent(e.getKey(), k -> new ArrayList<>()) + .add(Double.parseDouble(String.valueOf(yVal))); + } } - // 重新构建 xData / yData List newX = new ArrayList<>(); - List newY = new ArrayList<>(); + Map> newY = new HashMap<>(); - for (Map.Entry> entry : halfHourMap.entrySet()) { + for (Map.Entry>> entry : halfHourMap.entrySet()) { newX.add(entry.getKey()); - double avg = entry.getValue() - .stream() - .mapToDouble(Double::doubleValue) - .average() - .orElse(0); - - newY.add(avg); + for (Map.Entry> e : entry.getValue().entrySet()) { + double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); + newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); + } } lineData.setXData(newX); @@ -180,49 +180,40 @@ public class LineDataHourAggregator { public static void aggregateLastByHalfHour(LineData lineData) { List xData = lineData.getXData(); - List yData = lineData.getYData(); + Map> yDataMap = lineData.getYData(); - if (xData == null || yData == null || xData.size() != yData.size()) { + if (xData == null || yDataMap == null) { return; } - // halfHour -> lastValue - Map halfHourLastMap = new TreeMap<>(); + 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 time = LocalDateTime.parse(String.valueOf(xData.get(i)), INPUT_FMT); - LocalDateTime halfHourTime = time - .withMinute(halfHourMinute) - .withSecond(0) - .withNano(0); + int minute = time.getMinute() < 30 ? 0 : 30; + LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); + String key = halfHourTime.format(INPUT_FMT); - String halfHourKey = halfHourTime.format(INPUT_FMT); + for (Map.Entry> e : yDataMap.entrySet()) { + Object yVal = e.getValue().get(i); + if (yVal == null) continue; - // 同一个半小时,后面的会覆盖前面的 → 自然就是“最后一条” - halfHourLastMap.put( - halfHourKey, - Double.parseDouble(String.valueOf(yVal)) - ); + halfHourLastMap + .computeIfAbsent(key, k -> new HashMap<>()) + .put(e.getKey(), yVal); + } } - // 重新构建 xData / yData List newX = new ArrayList<>(); - List newY = new ArrayList<>(); + Map> newY = new HashMap<>(); - for (Map.Entry entry : halfHourLastMap.entrySet()) { + for (Map.Entry> entry : halfHourLastMap.entrySet()) { newX.add(entry.getKey()); - newY.add(entry.getValue()); + + for (Map.Entry e : entry.getValue().entrySet()) { + newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(e.getValue()); + } } lineData.setXData(newX); From 359c89d726ff693e445d6aa432926c75e41904d1 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Mon, 26 Jan 2026 14:06:07 +0800 Subject: [PATCH 07/52] =?UTF-8?q?=E5=9B=BE=E8=A1=A848=E5=B0=8F=E6=97=B6?= =?UTF-8?q?=E3=80=81=E7=B4=AF=E7=A7=AF=E5=A2=9E=E5=8A=A0=E5=89=8D=E5=B9=B4?= =?UTF-8?q?=E5=89=8D=E6=97=A5=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/vo/device/AccumulateLineData.java | 30 ++ .../dashboard/back/vo/device/LineData.java | 2 +- .../back/service/common/CommonOpt.java | 375 ++++++++++-------- .../service/common/LineDataAggregator.java | 333 ++++++++++++++++ .../common/LineDataHourAggregator.java | 224 ----------- .../impl/DeviceDataAccumulateServiceImpl.java | 12 +- .../impl/DeviceDataMeasureServiceImpl.java | 12 +- 7 files changed, 582 insertions(+), 406 deletions(-) create mode 100644 dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java create mode 100644 dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java delete mode 100644 dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java new file mode 100644 index 0000000..a2e250a --- /dev/null +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java @@ -0,0 +1,30 @@ +package com.dongjian.dashboard.back.vo.device; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +public class AccumulateLineData { + + @Schema(description = "属性编码, 默认:single,温湿度设备:temperature或者humidity") + private String attrCode; + + @Schema(description = "Y-axis data", example = "[]") + private Map subData = new HashMap<>(); + + + @Data + public static class childLineData { + @Schema(description = "X-axis data", example = "[]") + private List xData = new ArrayList<>(); + + @Schema(description = "Y-axis data", example = "[]") + private List yData = new ArrayList<>(); + } + +} diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java index 6938200..ceac7f5 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/LineData.java @@ -15,7 +15,7 @@ public class LineData { private String attrCode; @Schema(description = "X-axis data", example = "[]") - private List xData = new ArrayList<>(); + private List xData = new ArrayList<>(); @Schema(description = "Y-axis data", example = "[]") private Map> yData = new HashMap<>(); 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 e88bdd7..ef166fc 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 @@ -8,22 +8,24 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.alibaba.fastjson2.JSON; import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.language.msg.MsgLanguageChange; -import com.dongjian.dashboard.back.common.response.ResponseCode; -import com.dongjian.dashboard.back.common.response.SimpleDataResponse; import com.dongjian.dashboard.back.dao.ex.*; import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.model.*; import com.dongjian.dashboard.back.util.DESUtil; +import com.dongjian.dashboard.back.util.DateUtil; import com.dongjian.dashboard.back.util.DurationData; import com.dongjian.dashboard.back.vo.building.BindedBuildingVO; import com.dongjian.dashboard.back.vo.company.AuroraInfo; +import com.dongjian.dashboard.back.vo.device.AccumulateLineData; import com.dongjian.dashboard.back.vo.device.DeviceIncrement; import com.dongjian.dashboard.back.vo.device.LineData; import com.dongjian.dashboard.back.vo.record.RecordAccumulateDto; @@ -257,8 +259,10 @@ public class CommonOpt { } public List getPreDay(int days) { + // 日本时区 + ZoneId JST = ZoneId.of("Asia/Tokyo"); // 获取当前日期 - LocalDate currentDate = LocalDate.now(); + LocalDate currentDate = LocalDate.now(JST); // 设置日期格式化 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd"); // 用于存储日期的列表 @@ -272,94 +276,182 @@ public class CommonOpt { return dateList; } - public List getLineData(Long companyId, LineDataSearchParams lineDataSearchParams, int deviceType) { - List lineDataList = new ArrayList<>(); - for (String attrCode : lineDataSearchParams.getAttrCodeList()){ - DeviceInfo deviceInfo = getDeviceInfoByDeviceId(lineDataSearchParams.getDeviceId()); - if (null == deviceInfo){ - continue; - } + public List getAccumulateLineData(Long companyId, Integer searchType, LineDataSearchParams lineDataSearchParams) { + List result = new ArrayList<>(); + executeLineDataQuery( + result, + companyId, + searchType, + lineDataSearchParams, + (conn, lineData) -> { + + DeviceInfo deviceInfo = getDeviceInfoByDeviceId(lineDataSearchParams.getDeviceId()); + List dateList = getPreDay(1); + + for (String date : dateList) { + LocalDate current = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy_MM_dd")); + + LocalDate yesterday = current.minusDays(1); + LocalDate beforeYesterday = current.minusDays(2); + LocalDate lastYear = DateUtil.getLastYearSameIsoWeekDay(current); + LocalDate lastYearPrev = lastYear.minusDays(1); + + Double todayBase = getDayAccumulate(conn, yesterday, lineDataSearchParams.getDeviceId()); + Double yesterdayBase = getDayAccumulate(conn, beforeYesterday, lineDataSearchParams.getDeviceId()); + Double lastYearBase = getDayAccumulate(conn, lastYearPrev, lineDataSearchParams.getDeviceId()); + + AccumulateLineData acc = new AccumulateLineData(); + acc.setAttrCode(lineData.getAttrCode()); + + processAccumulateDay(conn, current, todayBase, "today", acc, deviceInfo); + if (searchType == 1) { + processAccumulateDay(conn, yesterday, yesterdayBase, "yesterday", acc, deviceInfo); + processAccumulateDay(conn, lastYear, lastYearBase, "lastYear", acc, deviceInfo); + LineDataAggregator.convertToLineDataHour(acc, lineData); + } else { + LineDataAggregator.convertToLineDataAll(acc, lineData); + } + } + }); + return result; + } + + private void executeLineDataQuery( + List result, + Long companyId, + Integer searchType, + LineDataSearchParams params, + BiConsumer dataProcessor) { + + DeviceInfo deviceInfo = getDeviceInfoByDeviceId(params.getDeviceId()); + if (deviceInfo == null) { + return; + } + + AuroraInfo auroraInfo = getAuroraInfoByApikey(Collections.singletonMap("companyId", companyId)); + if (auroraInfo == null || StringUtils.isBlank(auroraInfo.getAuroraUrl())) { + logger.error("AuroraInfo is not set for companyId: {}", companyId); + return; + } + + String jdbcUrl = null; + try { + jdbcUrl = buildAuroraJdbcUrl(auroraInfo); + } catch (ClassNotFoundException e) { + logger.error("Failed to build Aurora JDBC URL for companyId: {}", companyId, e); + return; + } + + for (String attrCode : params.getAttrCodeList()) { LineData lineData = new LineData(); lineData.setAttrCode(attrCode); - try { - Map apikeyParamMap = new HashMap<>(); - apikeyParamMap.put("companyId", companyId); - AuroraInfo apikeyInfo = getAuroraInfoByApikey(apikeyParamMap); - - if (null == apikeyInfo) { - logger.error("Failed to get AuroraInfo for companyId: {}", companyId); - lineDataList.add(lineData); - } - if (StringUtils.isNotBlank(apikeyInfo.getAuroraUrl())) { - Class.forName("com.mysql.cj.jdbc.Driver"); + try (Connection conn = DriverManager.getConnection( + jdbcUrl, + DESUtil.decrypt(auroraInfo.getAuroraUsername(), Constants.DES_SALT), + DESUtil.decrypt(auroraInfo.getAuroraPassword(), Constants.DES_SALT))) { - String regex = "(jdbc:mysql://)([^/]+)(/data_center_aeon_admin.*)"; - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(dbUrl); - String newJdbcUrl = ""; - if (matcher.find()) { - newJdbcUrl = matcher.replaceAll("$1" + apikeyInfo.getAuroraUrl() + "$3"); - } + dataProcessor.accept(conn, lineData); - try (Connection conn = DriverManager.getConnection( - newJdbcUrl.replace("data_center_aeon_admin", "aeon") + "&allowPublicKeyRetrieval=true", - DESUtil.decrypt(apikeyInfo.getAuroraUsername(), Constants.DES_SALT), - DESUtil.decrypt(apikeyInfo.getAuroraPassword(), Constants.DES_SALT))) { + } catch (Exception e) { + logger.error("executeLineDataQuery error", e); + } - List dateList = getPreDay(1); + result.add(lineData); + } + } - for (String date : dateList) { - //获取昨天的值,这里只针对累积设备 - Double lastDayValue = null; - if (deviceType == 2) { - lastDayValue = getLastDayValue(conn, date, lineDataSearchParams.getDeviceId()); - } + private String buildAuroraJdbcUrl(AuroraInfo auroraInfo) throws ClassNotFoundException { + Class.forName("com.mysql.cj.jdbc.Driver"); - // 提取年、月、日 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd"); - LocalDate currentDate = LocalDate.parse(date, formatter); - int year = currentDate.getYear(); - int month = currentDate.getMonthValue(); - int day = currentDate.getDayOfMonth(); - - String sql = ""; - if (deviceType == 2){ - sql = "SELECT upload_value, upload_at FROM dashboard_record_accumulate " + - "WHERE device_id = ? AND attr_code = ? AND date_year = ? AND date_month = ? AND date_day = ? order by id "; - } else if (deviceType == 3){ - sql = "SELECT upload_value, upload_at FROM dashboard_record_measure " + - "WHERE device_id = ? AND attr_code = ? AND date_year = ? AND date_month = ? AND date_day = ? order by id "; - } - logger.info("getLineData sql: {}", sql); - try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) { - preparedStatement.setString(1, lineDataSearchParams.getDeviceId()); - preparedStatement.setString(2, attrCode); - preparedStatement.setInt(3, year); // 设置年份 - preparedStatement.setInt(4, month); // 设置月份 - preparedStatement.setInt(5, day); // 设置日期 - try (ResultSet result = preparedStatement.executeQuery()) { - if (result.next()) { - if (deviceType == 2) { - processResult(result, lineData, deviceInfo, lastDayValue); - } else if (deviceType == 3) { - processResult(result, lineData, deviceInfo); - } - } - } - } - } - } catch (Exception e) { - logger.error("getLineData processing aurora error", e); - } + String regex = "(jdbc:mysql://)([^/]+)(/data_center_aeon_admin.*)"; + Matcher matcher = Pattern.compile(regex).matcher(dbUrl); + + if (!matcher.find()) { + throw new RuntimeException("Invalid dbUrl format"); + } + + return matcher.replaceAll("$1" + auroraInfo.getAuroraUrl() + "$3") + .replace("data_center_aeon_admin", "aeon") + + "&allowPublicKeyRetrieval=true"; + } + + private void processAccumulateDay( + Connection conn, + LocalDate date, + Double baseValue, + String yKey, + AccumulateLineData accumulateLineData, + DeviceInfo deviceInfo) { + + AccumulateLineData.childLineData childLineData = new AccumulateLineData.childLineData(); + + + String sql = "SELECT upload_value, upload_at FROM dashboard_record_accumulate " + + "WHERE device_id = ? AND attr_code = ? AND date_year = ? AND date_month = ? AND date_day = ? ORDER BY id"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceInfo.getDeviceId()); + ps.setString(2, accumulateLineData.getAttrCode()); + ps.setInt(3, date.getYear()); + ps.setInt(4, date.getMonthValue()); + ps.setInt(5, date.getDayOfMonth()); + + try (ResultSet rs = ps.executeQuery()) { + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + ZoneId JST = ZoneId.of("Asia/Tokyo"); + + while (rs.next()) { + long ts = rs.getLong("upload_at"); + String value = rs.getString("upload_value"); + + if (ts == 0) continue; + + String time = Instant.ofEpochMilli(ts) + .atZone(JST) + .toLocalDateTime() + .format(formatter); + + double current = StringUtils.isBlank(value) + ? 0 + : new BigDecimal(value).doubleValue(); + + double y = baseValue == null || current < baseValue + ? current + : current - baseValue; + + childLineData.getXData().add(time); + childLineData.getYData().add(CommonUtil.formatDecimal(y, deviceInfo.getDashboardDecimalPlaces())); } + } + } catch (Exception e) { + logger.error("processAccumulateDay error", e); + } - } catch (Exception e) { - logger.error("getLineData error", e); + accumulateLineData.getSubData().put(yKey, childLineData); + } + + private Double getDayAccumulate(Connection conn, LocalDate date, String deviceId) { + + String sql = "SELECT upload_value FROM dashboard_realtime_accumulate_day " + + "WHERE device_id = ? AND date_year = ? AND date_month = ? AND date_day = ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceId); + ps.setInt(2, date.getYear()); + ps.setInt(3, date.getMonthValue()); + ps.setInt(4, date.getDayOfMonth()); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return new BigDecimal(rs.getString("upload_value")).doubleValue(); + } } - lineDataList.add(lineData); + } catch (Exception e) { + logger.error("getDayAccumulate error", e); } - return lineDataList; + return null; } private DeviceInfo getDeviceInfoByDeviceId(String deviceId) { @@ -371,47 +463,56 @@ public class CommonOpt { return list.isEmpty() ? null : list.get(0); } - private Double getLastDayValue(Connection conn, String date, String deviceId) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy_MM_dd"); - // 解析日期字符串为 LocalDate 对象 - LocalDate previousDate = LocalDate.parse(date, formatter); - // 获取前一天的日期 - LocalDate previousDay = previousDate.minusDays(1); - // 获取年、月、日 - int year = previousDay.getYear(); - int month = previousDay.getMonthValue(); - int day = previousDay.getDayOfMonth(); - - String sql = "SELECT upload_value FROM dashboard_realtime_accumulate_day " + - "WHERE device_id = ? AND date_year = ? AND date_month = ? AND date_day = ?"; - - logger.info("getUploadValue sql: {}", sql); - - try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) { - preparedStatement.setString(1, deviceId); // 设置设备ID - preparedStatement.setInt(2, year); // 设置年份 - preparedStatement.setInt(3, month); // 设置月份 - preparedStatement.setInt(4, day); // 设置日期 + public List getMeasureLineData(Long companyId, Integer searchType, LineDataSearchParams lineDataSearchParams) { + List list = new ArrayList<>(); + executeLineDataQuery( + list, + companyId, + searchType, + lineDataSearchParams, + (conn, lineData) -> { + + DeviceInfo deviceInfo = getDeviceInfoByDeviceId(lineDataSearchParams.getDeviceId()); + List dateList = getPreDay(1); + + for (String date : dateList) { + LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy_MM_dd")); + + String sql = "SELECT upload_value, upload_at FROM dashboard_record_measure " + + "WHERE device_id = ? AND attr_code = ? AND date_year = ? AND date_month = ? AND date_day = ? ORDER BY id"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, lineDataSearchParams.getDeviceId()); + ps.setString(2, lineData.getAttrCode()); + ps.setInt(3, localDate.getYear()); + ps.setInt(4, localDate.getMonthValue()); + ps.setInt(5, localDate.getDayOfMonth()); + + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + processResult(rs, lineData, deviceInfo); + } + } + } catch (Exception e) { + logger.error("process measure data error", e); + } + } + }); - try (ResultSet result = preparedStatement.executeQuery()) { - if (result.next()) { - String uploadValue = result.getString("upload_value"); - logger.info("Found upload_value: {}", uploadValue); - return new BigDecimal(uploadValue).doubleValue(); - } else { - logger.warn("No data found for deviceId: {} on {}/{}/{}", deviceId, year, month, day); - } - } - } catch (SQLException e) { - logger.error("Error getLastDayValue query: ", e); + if (searchType == 1) { + list.forEach(ld -> { + LineDataAggregator.aggregateAverageByHalfHour(ld); + LineDataAggregator.fillTo48HalfHour(ld); + }); } - return null; + + return list; } private void processResult(ResultSet result, LineData lineData, DeviceInfo deviceInfo) { try { // 用于存储 xData 和 yData - List xDataList = new ArrayList<>(); + List xDataList = new ArrayList<>(); List yDataList = new ArrayList<>(); // 使用 DateTimeFormatter 来格式化时间 @@ -451,54 +552,6 @@ public class CommonOpt { } } - private void processResult(ResultSet result, LineData lineData, DeviceInfo deviceInfo, Double lastDayValue) { - try { - List xDataList = new ArrayList<>(); - List yDataList = new ArrayList<>(); - - DateTimeFormatter formatter = - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - ZoneId JST = ZoneId.of("Asia/Tokyo"); - - do { - long receiveTs = result.getLong("upload_at"); - String value = result.getString("upload_value"); - - if (receiveTs == 0) { - continue; - } - - // 日本时区时间 - Instant instant = Instant.ofEpochMilli(receiveTs); - String formattedDate = instant - .atZone(JST) - .toLocalDateTime() - .format(formatter); - - double todayValue = StringUtils.isBlank(value) ? 0.0 : new BigDecimal(value).doubleValue(); - - // 默认今天值 - double yValue = todayValue; - - // 计算差值 - if (lastDayValue != null && todayValue >= lastDayValue) { - yValue = todayValue - lastDayValue; - } - - xDataList.add(formattedDate); - yDataList.add(CommonUtil.formatDecimal(yValue, deviceInfo.getDashboardDecimalPlaces())); - - } while (result.next()); - - lineData.getXData().addAll(xDataList); - lineData.getYData().put("common", yDataList); - - } catch (Exception e) { - logger.error("Error processing result set", e); - } - } - public Map buildDeviceId85To111Map(List deviceIds) { return deviceIds.stream() .filter(id -> id.endsWith(SUFFIX_85) || id.endsWith(SUFFIX_85_9003)) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java new file mode 100644 index 0000000..5aa2b2f --- /dev/null +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java @@ -0,0 +1,333 @@ +package com.dongjian.dashboard.back.service.common; + +import com.dongjian.dashboard.back.vo.device.AccumulateLineData; +import com.dongjian.dashboard.back.vo.device.LineData; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * 完整整合版:LineData 聚合与转换工具类(统一使用 LineDataAligner 对齐) + */ +public class LineDataAggregator { + + /* =============================== + * 时间工具 + * =============================== */ + public static final class TimeAxisUtil { + public static final DateTimeFormatter DATETIME_FMT = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public static String hourKey(LocalDateTime time) { + return time.withMinute(0).withSecond(0).withNano(0).format(DATETIME_FMT); + } + + public static String halfHourKey(LocalDateTime time) { + int minute = time.getMinute() < 30 ? 0 : 30; + return time.withMinute(minute).withSecond(0).withNano(0).format(DATETIME_FMT); + } + + public static String alignToHalfHour(LocalTime time) { + int minute = time.getMinute() < 30 ? 0 : 30; + return LocalTime.of(time.getHour(), minute).format(DateTimeFormatter.ofPattern("HH:mm")); + } + + public static String extractDate(String datetime) { + return LocalDateTime.parse(datetime, DATETIME_FMT).toLocalDate().toString(); + } + + public static List generate48HalfHourPoints(String date) { + List list = new ArrayList<>(48); + LocalDateTime t = LocalDate.parse(date).atStartOfDay(); + for (int i = 0; i < 48; i++) { + list.add(t.plusMinutes(i * 30).format(DATETIME_FMT)); + } + return list; + } + } + + /* =============================== + * Y 对齐工具 + * =============================== */ + public static final class LineDataAligner { + + /** + * 对齐 X 轴,补 null + */ + public static Map> alignY( + List xAxis, + Map> seriesValueMap + ) { + Map> result = new LinkedHashMap<>(); + for (Map.Entry> entry : seriesValueMap.entrySet()) { + List aligned = new ArrayList<>(xAxis.size()); + Map valueMap = entry.getValue(); + for (String x : xAxis) { + aligned.add(valueMap.get(x)); + } + result.put(entry.getKey(), aligned); + } + return result; + } + } + + /* =============================== + * 聚合策略接口(可扩展) + * =============================== */ + @FunctionalInterface + public interface HalfHourCollector { + void collect(Map bucket, String key, LocalDateTime time, Object value); + } + + /* 平均值聚合实现 */ + public static class AvgCollector implements HalfHourCollector> { + @Override + public void collect(Map> bucket, String key, LocalDateTime time, Object value) { + bucket.computeIfAbsent(key, k -> new ArrayList<>()).add(Double.parseDouble(value.toString())); + } + } + + /* 取最后一条实现 */ + public static class LastValueCollector implements HalfHourCollector { + @Override + public void collect(Map bucket, String key, LocalDateTime time, Object value) { + TimeValue old = bucket.get(key); + if (old == null || time.isAfter(old.time)) { + bucket.put(key, new TimeValue(time, value)); + } + } + } + + /* =============================== + * 核心数据模型 + * =============================== */ + public static class TimeValue { + LocalDateTime time; + Object value; + + TimeValue(LocalDateTime time, Object value) { + this.time = time; + this.value = value; + } + } + + public static class HalfHourSeries { + String date; + List xList; + List yList; + + HalfHourSeries(String date) { + this(date, new ArrayList<>(), new ArrayList<>()); + } + + HalfHourSeries(String date, List xList, List yList) { + this.date = date; + this.xList = xList; + this.yList = yList; + } + + Map toMap() { + Map map = new HashMap<>(); + for (int i = 0; i < xList.size(); i++) { + map.put(xList.get(i), yList.get(i)); + } + return map; + } + } + + /* =============================== + * 工具方法 + * =============================== */ + private static Object safeGet(List list, int index) { + return (list != null && index < list.size()) ? list.get(index) : null; + } + + private static LocalDateTime parseTime(Object x) { + return LocalDateTime.parse(String.valueOf(x), TimeAxisUtil.DATETIME_FMT); + } + + /* =============================== + * 按小时聚合(平均值) + * =============================== */ + public static void aggregateByHour(LineData lineData) { + aggregateByHourOrHalfHour(lineData, new AvgCollector(), true); + } + + /* =============================== + * 按半小时聚合(平均值) + * =============================== */ + public static void aggregateAverageByHalfHour(LineData lineData) { + aggregateByHourOrHalfHour(lineData, new AvgCollector(), false); + } + + /* 公共聚合方法 */ + private static void aggregateByHourOrHalfHour( + LineData lineData, + HalfHourCollector collector, + boolean byHour + ) { + if (lineData == null) return; + + List xData = lineData.getXData(); + Map> yDataMap = lineData.getYData(); + if (xData == null || xData.isEmpty() || yDataMap == null || yDataMap.isEmpty()) return; + + Set allSeriesKeys = yDataMap.keySet(); + + Map> bucket = new TreeMap<>(); + for (int i = 0; i < xData.size(); i++) { + LocalDateTime time = parseTime(xData.get(i)); + String key = byHour ? TimeAxisUtil.hourKey(time) : TimeAxisUtil.halfHourKey(time); + + for (String series : allSeriesKeys) { + Object yVal = safeGet(yDataMap.get(series), i); + if (yVal == null) continue; + + bucket.computeIfAbsent(key, k -> new HashMap<>()); + collector.collect(bucket.get(key), series, time, yVal); + } + } + + // 构建临时 Map 用于统一对齐 + Map> tmpMap = new HashMap<>(); + boolean isAvg = collector instanceof AvgCollector; + + for (Map.Entry> entry : bucket.entrySet()) { + String xKey = entry.getKey(); + Map seriesMap = entry.getValue(); + for (String series : allSeriesKeys) { + Object val; + T tVal = seriesMap.get(series); + if (isAvg && tVal instanceof List) { + List list = (List) tVal; + val = list.stream().mapToDouble(Double::doubleValue).average().orElse(0); + } else if (!isAvg && tVal instanceof TimeValue) { + val = ((TimeValue) tVal).value; + } else { + val = tVal; + } + tmpMap.computeIfAbsent(series, k -> new HashMap<>()).put(xKey, val); + } + } + + List newX = new ArrayList<>(bucket.keySet()); + lineData.setXData(newX); + lineData.setYData(LineDataAligner.alignY(newX, tmpMap)); + } + + /* =============================== + * AccumulateLineData -> LineData + * 半小时取最后一条 + * =============================== */ + public static void convertToLineDataHour(AccumulateLineData accumulate, LineData lineData) { + if (accumulate == null || accumulate.getSubData() == null) return; + + Map seriesMap = new LinkedHashMap<>(); + for (Map.Entry entry : accumulate.getSubData().entrySet()) { + seriesMap.put(entry.getKey(), aggregateLastByHalfHour(entry.getValue())); + } + + HalfHourSeries today = seriesMap.get("today"); + if (today == null) throw new IllegalStateException("subData 必须包含 today"); + + // 构建最终 X + List finalX = new ArrayList<>(); + for (String hm : today.xList) finalX.add(today.date + " " + hm + ":00"); + + // 构建临时 Map + Map> tmpMap = new HashMap<>(); + for (Map.Entry entry : seriesMap.entrySet()) { + tmpMap.put(entry.getKey(), entry.getValue().toMap()); + } + + lineData.setXData(finalX); + lineData.setYData(LineDataAligner.alignY(today.xList, tmpMap)); + lineData.setAttrCode(accumulate.getAttrCode()); + + fillTo48HalfHour(lineData); + } + + private static HalfHourSeries aggregateLastByHalfHour(AccumulateLineData.childLineData child) { + if (child == null || child.getXData() == null || child.getYData() == null) + return new HalfHourSeries(null); + + Map bucket = new HashMap<>(); + String date = null; + int size = Math.min(child.getXData().size(), child.getYData().size()); + + for (int i = 0; i < size; i++) { + LocalDateTime time = LocalDateTime.parse(child.getXData().get(i).toString(), TimeAxisUtil.DATETIME_FMT); + Object value = child.getYData().get(i); + if (value == null) continue; + + if (date == null) date = time.toLocalDate().toString(); + String hm = TimeAxisUtil.alignToHalfHour(time.toLocalTime()); + + TimeValue old = bucket.get(hm); + if (old == null || time.isAfter(old.time)) bucket.put(hm, new TimeValue(time, value)); + } + + List sortedHM = new ArrayList<>(bucket.keySet()); + Collections.sort(sortedHM); + + List values = new ArrayList<>(); + for (String hm : sortedHM) values.add(bucket.get(hm).value); + + return new HalfHourSeries(date, sortedHM, values); + } + + /* =============================== + * 补齐 48 半小时点 + * =============================== */ + public static void fillTo48HalfHour(LineData lineData) { + List xData = lineData.getXData(); + Map> yData = lineData.getYData(); + if (xData == null || xData.isEmpty() || yData == null) return; + + String date = TimeAxisUtil.extractDate(xData.get(0)); + List fixedX = TimeAxisUtil.generate48HalfHourPoints(date); + + // 构建临时 Map + Map> tmpMap = new HashMap<>(); + for (Map.Entry> entry : yData.entrySet()) { + Map map = new HashMap<>(); + for (int i = 0; i < xData.size(); i++) { + map.put(xData.get(i), entry.getValue().get(i)); + } + tmpMap.put(entry.getKey(), map); + } + + lineData.setXData(new ArrayList<>(fixedX)); + lineData.setYData(LineDataAligner.alignY(fixedX, tmpMap)); + } + + /* =============================== + * 全量对齐 + * =============================== */ + public static void convertToLineDataAll(AccumulateLineData accumulate, LineData lineData) { + if (accumulate == null || accumulate.getSubData() == null) return; + + LinkedHashSet xSet = new LinkedHashSet<>(); + for (AccumulateLineData.childLineData child : accumulate.getSubData().values()) { + if (child.getXData() != null) xSet.addAll(child.getXData()); + } + List mergedX = new ArrayList<>(xSet); + + Map> tmpMap = new LinkedHashMap<>(); + for (Map.Entry entry : accumulate.getSubData().entrySet()) { + Map map = new LinkedHashMap<>(); + AccumulateLineData.childLineData child = entry.getValue(); + if (child.getXData() != null && child.getYData() != null) { + int size = Math.min(child.getXData().size(), child.getYData().size()); + for (int i = 0; i < size; i++) map.put(child.getXData().get(i), child.getYData().get(i)); + } + tmpMap.put(entry.getKey(), map); + } + + lineData.setXData(mergedX); + lineData.setYData(LineDataAligner.alignY(mergedX, tmpMap)); + } +} 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 deleted file mode 100644 index e191ee8..0000000 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataHourAggregator.java +++ /dev/null @@ -1,224 +0,0 @@ -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.*; - -/** - * 给计测设备,按小时聚合数据,求平均值 - */ -public class LineDataHourAggregator { - - private static final DateTimeFormatter INPUT_FMT = - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - private static final DateTimeFormatter HOUR_FMT = - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00:00"); - - public static void aggregateByHour(LineData lineData) { - - List xData = lineData.getXData(); - Map> yDataMap = lineData.getYData(); - - if (xData == null || yDataMap == null || yDataMap.isEmpty()) { - return; - } - - // hour -> index - Map hourIndexMap = new TreeMap<>(); - Map>> hourValueMap = new TreeMap<>(); - - for (int i = 0; i < xData.size(); i++) { - String timeStr = String.valueOf(xData.get(i)); - LocalDateTime time = LocalDateTime.parse(timeStr, INPUT_FMT); - String hourKey = time.format(HOUR_FMT); - - hourIndexMap.putIfAbsent(hourKey, hourIndexMap.size()); - - for (Map.Entry> entry : yDataMap.entrySet()) { - Object yVal = entry.getValue().get(i); - if (yVal == null) { - continue; - } - - hourValueMap - .computeIfAbsent(hourKey, k -> new HashMap<>()) - .computeIfAbsent(entry.getKey(), k -> new ArrayList<>()) - .add(Double.parseDouble(String.valueOf(yVal))); - } - } - - List newX = new ArrayList<>(); - Map> newY = new HashMap<>(); - - for (String hourKey : hourIndexMap.keySet()) { - newX.add(hourKey); - - Map> seriesMap = hourValueMap.get(hourKey); - if (seriesMap == null) { - continue; - } - - for (Map.Entry> e : seriesMap.entrySet()) { - double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); - newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); - } - } - - lineData.setXData(newX); - lineData.setYData(newY); - } - - /** - * 将 LineData 补齐为【日本时区】当天 0:00 - 23:30 的 48 个半小时点 - * 没有数据的时间点,Y 值补 0 - */ - public static void fillTodayHalfHourPointsJST(LineData lineData) { - - List xData = lineData.getXData(); - Map> yDataMap = lineData.getYData(); - - if (xData == null || yDataMap == null) { - return; - } - - ZoneId JST = ZoneId.of("Asia/Tokyo"); - LocalDate todayJst = LocalDate.now(JST); - LocalDateTime start = todayJst.atStartOfDay(); - - // 原数据转 Map:time -> series -> value - Map> valueMap = new HashMap<>(); - - for (int i = 0; i < xData.size(); i++) { - String time = String.valueOf(xData.get(i)); - for (Map.Entry> e : yDataMap.entrySet()) { - valueMap - .computeIfAbsent(time, k -> new HashMap<>()) - .put(e.getKey(), e.getValue().get(i)); - } - } - - List newX = new ArrayList<>(48); - Map> newY = new HashMap<>(); - - for (int i = 0; i < 48; i++) { - LocalDateTime t = start.plusMinutes(i * 30); - String key = t.format(INPUT_FMT); - newX.add(key); - - Map seriesValues = valueMap.get(key); - for (String series : yDataMap.keySet()) { - newY - .computeIfAbsent(series, k -> new ArrayList<>()) - .add(seriesValues == null ? null : seriesValues.get(series)); - } - } - - 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(); - Map> yDataMap = lineData.getYData(); - - if (xData == null || yDataMap == null) { - return; - } - - Map>> halfHourMap = new TreeMap<>(); - - for (int i = 0; i < xData.size(); i++) { - LocalDateTime time = LocalDateTime.parse(String.valueOf(xData.get(i)), INPUT_FMT); - - int minute = time.getMinute() < 30 ? 0 : 30; - LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); - String key = halfHourTime.format(INPUT_FMT); - - for (Map.Entry> e : yDataMap.entrySet()) { - Object yVal = e.getValue().get(i); - if (yVal == null) continue; - - halfHourMap - .computeIfAbsent(key, k -> new HashMap<>()) - .computeIfAbsent(e.getKey(), k -> new ArrayList<>()) - .add(Double.parseDouble(String.valueOf(yVal))); - } - } - - List newX = new ArrayList<>(); - Map> newY = new HashMap<>(); - - for (Map.Entry>> entry : halfHourMap.entrySet()) { - newX.add(entry.getKey()); - - for (Map.Entry> e : entry.getValue().entrySet()) { - double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); - newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); - } - } - - lineData.setXData(newX); - lineData.setYData(newY); - } - - - /** - * 按半小时聚合,只保留每个半小时内的最后一条数据 - */ - public static void aggregateLastByHalfHour(LineData lineData) { - - List xData = lineData.getXData(); - Map> yDataMap = lineData.getYData(); - - if (xData == null || yDataMap == null) { - return; - } - - Map> halfHourLastMap = new TreeMap<>(); - - for (int i = 0; i < xData.size(); i++) { - LocalDateTime time = LocalDateTime.parse(String.valueOf(xData.get(i)), INPUT_FMT); - - int minute = time.getMinute() < 30 ? 0 : 30; - LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); - String key = halfHourTime.format(INPUT_FMT); - - for (Map.Entry> e : yDataMap.entrySet()) { - Object yVal = e.getValue().get(i); - if (yVal == null) continue; - - halfHourLastMap - .computeIfAbsent(key, k -> new HashMap<>()) - .put(e.getKey(), yVal); - } - } - - List newX = new ArrayList<>(); - Map> newY = new HashMap<>(); - - for (Map.Entry> entry : halfHourLastMap.entrySet()) { - newX.add(entry.getKey()); - - for (Map.Entry e : entry.getValue().entrySet()) { - newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(e.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 0a2e501..58ce354 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 @@ -10,6 +10,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import com.alibaba.fastjson2.JSON; import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.language.msg.MsgLanguageChange; import com.dongjian.dashboard.back.common.response.PageInfo; @@ -23,7 +24,6 @@ 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; @@ -198,15 +198,7 @@ public class DeviceDataAccumulateServiceImpl implements DeviceDataAccumulateServ if (null == searchType) { searchType = 2;//默认全部数据 } - List lineDataList = commonOpt.getLineData(companyId, lineDataSearchParams, 2); - if (1 == searchType && CollectionUtils.isNotEmpty(lineDataList)) { - lineDataList.forEach(lineData -> { - //按半小时聚合 - LineDataHourAggregator.aggregateLastByHalfHour(lineData); - //补齐48个横坐标 - LineDataHourAggregator.fillTodayHalfHourPointsJST(lineData); - }); - } + List lineDataList = commonOpt.getAccumulateLineData(companyId, searchType, lineDataSearchParams); 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 32f6b99..7e5e1ec 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 @@ -17,7 +17,7 @@ import com.dongjian.dashboard.back.model.DeviceRawdataRealtime; import com.dongjian.dashboard.back.model.DeviceRawdataRealtimeExample; import com.dongjian.dashboard.back.service.DeviceDataMeasureService; import com.dongjian.dashboard.back.service.common.CommonOpt; -import com.dongjian.dashboard.back.service.common.LineDataHourAggregator; +//import com.dongjian.dashboard.back.service.common.LineDataHourAggregator; import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; import com.dongjian.dashboard.back.vo.data.DeviceMeasureData; @@ -236,15 +236,7 @@ public class DeviceDataMeasureServiceImpl implements DeviceDataMeasureService { if (null == searchType) { searchType = 2;//默认全部数据 } - List lineDataList = commonOpt.getLineData(companyId, lineDataSearchParams, 3); - if (1 == searchType && CollectionUtils.isNotEmpty(lineDataList)) { - lineDataList.forEach(lineData -> { - //按半小时聚合 - LineDataHourAggregator.aggregateAverageByHalfHour(lineData); - //补齐48个横坐标 - LineDataHourAggregator.fillTodayHalfHourPointsJST(lineData); - }); - } + List lineDataList = commonOpt.getMeasureLineData(companyId, searchType, lineDataSearchParams); return SimpleDataResponse.success(lineDataList); } From 97852cf58547e4ac4be85652d603ad0de7283110 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Mon, 26 Jan 2026 14:23:06 +0800 Subject: [PATCH 08/52] =?UTF-8?q?131=5F5=E5=90=8E=E7=BC=80=E8=AE=BE?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mappers/ex/DeviceInfoMapperExt.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml index 9849161..c09f402 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml @@ -52,7 +52,7 @@ #{deviceId} - and device_info.flag = 0 and (device_info.device_id LIKE '%\_85' or device_info.device_id LIKE '%\_85_9003') + and device_info.flag = 0 and (device_info.device_id LIKE '%\_85' or device_info.device_id LIKE '%\_85_9003' or device_info.device_id LIKE '%\_131_5') and basic_monitoring_asset.flag != 1 and basic_space.flag != 1 and basic_floor.flag != 1 and basic_building.flag != 1 and type.device_category_id in @@ -455,7 +455,7 @@ #{companyId} - and device_info.flag = 0 and (device_info.device_id LIKE '%\_85' or device_info.device_id LIKE '%\_85_9003') + and device_info.flag = 0 and (device_info.device_id LIKE '%\_85' or device_info.device_id LIKE '%\_85_9003' or device_info.device_id LIKE '%\_131_5') and basic_monitoring_asset.flag != 1 and basic_space.flag != 1 and basic_floor.flag != 1 and basic_building.flag != 1 and type.device_category_id in From 668f26bd84e7b4caa90557645ac7453588b993ee Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Mon, 26 Jan 2026 22:04:35 +0800 Subject: [PATCH 09/52] =?UTF-8?q?latest=5F=E6=98=AF=E7=A7=92ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/service/impl/DeviceDataBaStatusServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index 027626b..c9a071e 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -163,7 +163,7 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService if (0 == data.getStopRun()) { data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(data.getContinuousRunningTime())); } else if (StringUtils.isNotBlank(data.getLatestTs()) && currentTs >= Long.parseLong(data.getLatestTs())) { - long diff = currentTs - Long.parseLong(data.getLatestTs()); + long diff = currentTs/1000 - Long.parseLong(data.getLatestTs()); data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(diff)); } } From e200d1dba75e91314240bffb404dbfc56019a393 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Mon, 26 Jan 2026 22:07:07 +0800 Subject: [PATCH 10/52] =?UTF-8?q?latest=5F=E6=98=AF=E7=A7=92ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/easyexcel/SecondsToHMSConverter.java | 2 ++ .../back/service/impl/DeviceDataBaStatusServiceImpl.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/SecondsToHMSConverter.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/SecondsToHMSConverter.java index 2e85b4d..62fe18d 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/SecondsToHMSConverter.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/SecondsToHMSConverter.java @@ -28,6 +28,8 @@ public class SecondsToHMSConverter implements Converter { if (null == value) return ""; + value = value / 1000; + long hours = value / 3600; long minutes = (value % 3600) / 60; long seconds = value % 60; diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index c9a071e..027626b 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -163,7 +163,7 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService if (0 == data.getStopRun()) { data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(data.getContinuousRunningTime())); } else if (StringUtils.isNotBlank(data.getLatestTs()) && currentTs >= Long.parseLong(data.getLatestTs())) { - long diff = currentTs/1000 - Long.parseLong(data.getLatestTs()); + long diff = currentTs - Long.parseLong(data.getLatestTs()); data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(diff)); } } From ecb9d4ac2b6b01a170196941c944c2f6a0517747 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Tue, 27 Jan 2026 09:35:55 +0800 Subject: [PATCH 11/52] =?UTF-8?q?dashboard=E5=91=8A=E8=AD=A6=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=85=A8=E9=83=A8=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java index 8a7fc46..f3588c5 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java @@ -88,7 +88,7 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { } } - pageSearchParam.setCategoryIdList(Constants.CATEGORY_MAP.get(Constants.CATEGORY_ALARM)); + pageSearchParam.setCategoryIdList(Constants.ALL_CATEGORY_IDS); if (null != pageSearchParam.getDeviceGroupId()){ resultList = deviceInfoMapperExt.getDevice4AlarmDataByGroup(pageSearchParam); } else { From c15a8c31255066673b0b5778fb4ed5a635b4836b Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Tue, 27 Jan 2026 10:13:26 +0800 Subject: [PATCH 12/52] =?UTF-8?q?dashboard=E5=91=8A=E8=AD=A6=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E5=8F=AA=E6=9C=89=E5=91=8A=E8=AD=A6=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java index f3588c5..8a7fc46 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java @@ -88,7 +88,7 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { } } - pageSearchParam.setCategoryIdList(Constants.ALL_CATEGORY_IDS); + pageSearchParam.setCategoryIdList(Constants.CATEGORY_MAP.get(Constants.CATEGORY_ALARM)); if (null != pageSearchParam.getDeviceGroupId()){ resultList = deviceInfoMapperExt.getDevice4AlarmDataByGroup(pageSearchParam); } else { From e4f84a2239947f78b0739c7dffb8c7cd714ae365 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Tue, 27 Jan 2026 21:11:37 +0800 Subject: [PATCH 13/52] =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/common/Constants.java | 5 + .../DeviceDataBaStatusController.java | 18 + .../back/dao/auto/BaStatusHistoryMapper.java | 96 +++ .../back/dao/ex/BaStatusHistoryMapperExt.java | 9 + .../mappers/auto/BaStatusHistoryMapper.xml | 257 ++++++++ .../mybatis-generator/generatorConfig.xml | 5 + .../dashboard/back/model/BaStatusHistory.java | 166 ++++++ .../back/model/BaStatusHistoryExample.java | 552 ++++++++++++++++++ .../service/DeviceDataBaStatusService.java | 5 + .../back/service/common/CommonOpt.java | 10 +- .../impl/DeviceDataAccumulateServiceImpl.java | 2 +- .../impl/DeviceDataBaStatusServiceImpl.java | 77 ++- .../impl/DeviceDataMeasureServiceImpl.java | 2 +- .../dongjian/dashboard/back/util/Test.java | 39 +- 14 files changed, 1217 insertions(+), 26 deletions(-) create mode 100644 dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/auto/BaStatusHistoryMapper.java create mode 100644 dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/ex/BaStatusHistoryMapperExt.java create mode 100644 dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BaStatusHistoryMapper.xml create mode 100644 dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistory.java create mode 100644 dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistoryExample.java diff --git a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java index 7904d83..4edb1bb 100644 --- a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java +++ b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java @@ -1,5 +1,7 @@ package com.dongjian.dashboard.back.common; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; /** @@ -7,6 +9,9 @@ import java.util.*; * @time 2022年5月20日 下午2:01:41 */ public class Constants { + + public static final ZoneId ZONE_TOKYO = ZoneId.of("Asia/Tokyo"); + public static final DateTimeFormatter FORMATTER_YMDHMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //这个很重要,不要随便动 public static final String DES_SALT = "ci3b512jwy199511"; diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java index 6156013..3523a4f 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java @@ -6,13 +6,16 @@ import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; import com.dongjian.dashboard.back.common.response.ResponseCode; +import com.dongjian.dashboard.back.common.response.SimpleDataResponse; import com.dongjian.dashboard.back.configurator.aspect.OperationLog; import com.dongjian.dashboard.back.configurator.interceptor.AccessRequired; import com.dongjian.dashboard.back.dto.data.BaStatusDataSearchParam; +import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.easyexcel.ExportDeviceBaStatusDataDTO; import com.dongjian.dashboard.back.easyexcel.LanguageDynamicHeaderAdapter; import com.dongjian.dashboard.back.service.DeviceDataBaStatusService; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; +import com.dongjian.dashboard.back.vo.device.LineData; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; @@ -108,4 +111,19 @@ public class DeviceDataBaStatusController { .doWrite(exportList); } + @OperationLog(operation = "getLineData", remark = "") + @Operation(summary = "获取状态迁移图") + @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, + @Parameter(name = "CompanyId", description = "ID of the company to which the user belongs", required = false, schema = @Schema(defaultValue = "1")) @RequestHeader(required=false) Long CompanyId, + @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 deviceDataBaStatusService.getLineData(searchType, lineDataSearchParams, CompanyId, UserId, LanguageType); + } + } diff --git a/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/auto/BaStatusHistoryMapper.java b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/auto/BaStatusHistoryMapper.java new file mode 100644 index 0000000..a1a3387 --- /dev/null +++ b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/auto/BaStatusHistoryMapper.java @@ -0,0 +1,96 @@ +package com.dongjian.dashboard.back.dao.auto; + +import com.dongjian.dashboard.back.model.BaStatusHistory; +import com.dongjian.dashboard.back.model.BaStatusHistoryExample; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface BaStatusHistoryMapper { + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + long countByExample(BaStatusHistoryExample example); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int deleteByExample(BaStatusHistoryExample example); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int deleteByPrimaryKey(Long id); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int insert(BaStatusHistory record); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int insertSelective(BaStatusHistory record); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + List selectByExample(BaStatusHistoryExample example); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + BaStatusHistory selectByPrimaryKey(Long id); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int updateByExampleSelective(@Param("record") BaStatusHistory record, @Param("example") BaStatusHistoryExample example); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int updateByExample(@Param("record") BaStatusHistory record, @Param("example") BaStatusHistoryExample example); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int updateByPrimaryKeySelective(BaStatusHistory record); + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + int updateByPrimaryKey(BaStatusHistory record); +} \ No newline at end of file diff --git a/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/ex/BaStatusHistoryMapperExt.java b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/ex/BaStatusHistoryMapperExt.java new file mode 100644 index 0000000..f863644 --- /dev/null +++ b/dongjian-dashboard-back-dao/src/main/java/com/dongjian/dashboard/back/dao/ex/BaStatusHistoryMapperExt.java @@ -0,0 +1,9 @@ +package com.dongjian.dashboard.back.dao.ex; + +import com.dongjian.dashboard.back.dao.auto.BaStatusHistoryMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BaStatusHistoryMapperExt extends BaStatusHistoryMapper { + +} diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BaStatusHistoryMapper.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BaStatusHistoryMapper.xml new file mode 100644 index 0000000..771aef2 --- /dev/null +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BaStatusHistoryMapper.xml @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + id, device_info_id, is_running, update_ts + + + + + + delete from ba_status_history + where id = #{id,jdbcType=BIGINT} + + + + delete from ba_status_history + + + + + + + + SELECT LAST_INSERT_ID() + + insert into ba_status_history (device_info_id, is_running, update_ts + ) + values (#{deviceInfoId,jdbcType=INTEGER}, #{isRunning,jdbcType=INTEGER}, #{updateTs,jdbcType=VARCHAR} + ) + + + + + SELECT LAST_INSERT_ID() + + insert into ba_status_history + + + device_info_id, + + + is_running, + + + update_ts, + + + + + #{deviceInfoId,jdbcType=INTEGER}, + + + #{isRunning,jdbcType=INTEGER}, + + + #{updateTs,jdbcType=VARCHAR}, + + + + + + + update ba_status_history + + + id = #{record.id,jdbcType=BIGINT}, + + + device_info_id = #{record.deviceInfoId,jdbcType=INTEGER}, + + + is_running = #{record.isRunning,jdbcType=INTEGER}, + + + update_ts = #{record.updateTs,jdbcType=VARCHAR}, + + + + + + + + + update ba_status_history + set id = #{record.id,jdbcType=BIGINT}, + device_info_id = #{record.deviceInfoId,jdbcType=INTEGER}, + is_running = #{record.isRunning,jdbcType=INTEGER}, + update_ts = #{record.updateTs,jdbcType=VARCHAR} + + + + + + + update ba_status_history + + + device_info_id = #{deviceInfoId,jdbcType=INTEGER}, + + + is_running = #{isRunning,jdbcType=INTEGER}, + + + update_ts = #{updateTs,jdbcType=VARCHAR}, + + + where id = #{id,jdbcType=BIGINT} + + + + update ba_status_history + set device_info_id = #{deviceInfoId,jdbcType=INTEGER}, + is_running = #{isRunning,jdbcType=INTEGER}, + update_ts = #{updateTs,jdbcType=VARCHAR} + where id = #{id,jdbcType=BIGINT} + + \ No newline at end of file diff --git a/dongjian-dashboard-back-dao/src/main/resources/mybatis-generator/generatorConfig.xml b/dongjian-dashboard-back-dao/src/main/resources/mybatis-generator/generatorConfig.xml index b750704..f51a384 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mybatis-generator/generatorConfig.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mybatis-generator/generatorConfig.xml @@ -154,5 +154,10 @@ + + + +
+ \ No newline at end of file diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistory.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistory.java new file mode 100644 index 0000000..c6c761a --- /dev/null +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistory.java @@ -0,0 +1,166 @@ +package com.dongjian.dashboard.back.model; + +import java.io.Serializable; + +public class BaStatusHistory implements Serializable { + /** + * + * This field was generated by MyBatis Generator. + * This field corresponds to the database column ba_status_history.id + * + * @mbg.generated + */ + private Long id; + + /** + * + * This field was generated by MyBatis Generator. + * This field corresponds to the database column ba_status_history.device_info_id + * + * @mbg.generated + */ + private Integer deviceInfoId; + + /** + * + * This field was generated by MyBatis Generator. + * This field corresponds to the database column ba_status_history.is_running + * + * @mbg.generated + */ + private Integer isRunning; + + /** + * + * This field was generated by MyBatis Generator. + * This field corresponds to the database column ba_status_history.update_ts + * + * @mbg.generated + */ + private String updateTs; + + /** + * This field was generated by MyBatis Generator. + * This field corresponds to the database table ba_status_history + * + * @mbg.generated + */ + private static final long serialVersionUID = 1L; + + /** + * This method was generated by MyBatis Generator. + * This method returns the value of the database column ba_status_history.id + * + * @return the value of ba_status_history.id + * + * @mbg.generated + */ + public Long getId() { + return id; + } + + /** + * This method was generated by MyBatis Generator. + * This method sets the value of the database column ba_status_history.id + * + * @param id the value for ba_status_history.id + * + * @mbg.generated + */ + public void setId(Long id) { + this.id = id; + } + + /** + * This method was generated by MyBatis Generator. + * This method returns the value of the database column ba_status_history.device_info_id + * + * @return the value of ba_status_history.device_info_id + * + * @mbg.generated + */ + public Integer getDeviceInfoId() { + return deviceInfoId; + } + + /** + * This method was generated by MyBatis Generator. + * This method sets the value of the database column ba_status_history.device_info_id + * + * @param deviceInfoId the value for ba_status_history.device_info_id + * + * @mbg.generated + */ + public void setDeviceInfoId(Integer deviceInfoId) { + this.deviceInfoId = deviceInfoId; + } + + /** + * This method was generated by MyBatis Generator. + * This method returns the value of the database column ba_status_history.is_running + * + * @return the value of ba_status_history.is_running + * + * @mbg.generated + */ + public Integer getIsRunning() { + return isRunning; + } + + /** + * This method was generated by MyBatis Generator. + * This method sets the value of the database column ba_status_history.is_running + * + * @param isRunning the value for ba_status_history.is_running + * + * @mbg.generated + */ + public void setIsRunning(Integer isRunning) { + this.isRunning = isRunning; + } + + /** + * This method was generated by MyBatis Generator. + * This method returns the value of the database column ba_status_history.update_ts + * + * @return the value of ba_status_history.update_ts + * + * @mbg.generated + */ + public String getUpdateTs() { + return updateTs; + } + + /** + * This method was generated by MyBatis Generator. + * This method sets the value of the database column ba_status_history.update_ts + * + * @param updateTs the value for ba_status_history.update_ts + * + * @mbg.generated + */ + public void setUpdateTs(String updateTs) { + this.updateTs = updateTs == null ? null : updateTs.trim(); + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", deviceInfoId=").append(deviceInfoId); + sb.append(", isRunning=").append(isRunning); + sb.append(", updateTs=").append(updateTs); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistoryExample.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistoryExample.java new file mode 100644 index 0000000..75a14df --- /dev/null +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/model/BaStatusHistoryExample.java @@ -0,0 +1,552 @@ +package com.dongjian.dashboard.back.model; + +import java.util.ArrayList; +import java.util.List; + +public class BaStatusHistoryExample { + /** + * This field was generated by MyBatis Generator. + * This field corresponds to the database table ba_status_history + * + * @mbg.generated + */ + protected String orderByClause; + + /** + * This field was generated by MyBatis Generator. + * This field corresponds to the database table ba_status_history + * + * @mbg.generated + */ + protected boolean distinct; + + /** + * This field was generated by MyBatis Generator. + * This field corresponds to the database table ba_status_history + * + * @mbg.generated + */ + protected List oredCriteria; + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public BaStatusHistoryExample() { + oredCriteria = new ArrayList(); + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public String getOrderByClause() { + return orderByClause; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public boolean isDistinct() { + return distinct; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public List getOredCriteria() { + return oredCriteria; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + /** + * This method was generated by MyBatis Generator. + * This method corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + /** + * This class was generated by MyBatis Generator. + * This class corresponds to the database table ba_status_history + * + * @mbg.generated + */ + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(Long value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(Long value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(Long value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(Long value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(Long value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(Long value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(Long value1, Long value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(Long value1, Long value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdIsNull() { + addCriterion("device_info_id is null"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdIsNotNull() { + addCriterion("device_info_id is not null"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdEqualTo(Integer value) { + addCriterion("device_info_id =", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdNotEqualTo(Integer value) { + addCriterion("device_info_id <>", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdGreaterThan(Integer value) { + addCriterion("device_info_id >", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdGreaterThanOrEqualTo(Integer value) { + addCriterion("device_info_id >=", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdLessThan(Integer value) { + addCriterion("device_info_id <", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdLessThanOrEqualTo(Integer value) { + addCriterion("device_info_id <=", value, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdIn(List values) { + addCriterion("device_info_id in", values, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdNotIn(List values) { + addCriterion("device_info_id not in", values, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdBetween(Integer value1, Integer value2) { + addCriterion("device_info_id between", value1, value2, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andDeviceInfoIdNotBetween(Integer value1, Integer value2) { + addCriterion("device_info_id not between", value1, value2, "deviceInfoId"); + return (Criteria) this; + } + + public Criteria andIsRunningIsNull() { + addCriterion("is_running is null"); + return (Criteria) this; + } + + public Criteria andIsRunningIsNotNull() { + addCriterion("is_running is not null"); + return (Criteria) this; + } + + public Criteria andIsRunningEqualTo(Integer value) { + addCriterion("is_running =", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningNotEqualTo(Integer value) { + addCriterion("is_running <>", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningGreaterThan(Integer value) { + addCriterion("is_running >", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningGreaterThanOrEqualTo(Integer value) { + addCriterion("is_running >=", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningLessThan(Integer value) { + addCriterion("is_running <", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningLessThanOrEqualTo(Integer value) { + addCriterion("is_running <=", value, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningIn(List values) { + addCriterion("is_running in", values, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningNotIn(List values) { + addCriterion("is_running not in", values, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningBetween(Integer value1, Integer value2) { + addCriterion("is_running between", value1, value2, "isRunning"); + return (Criteria) this; + } + + public Criteria andIsRunningNotBetween(Integer value1, Integer value2) { + addCriterion("is_running not between", value1, value2, "isRunning"); + return (Criteria) this; + } + + public Criteria andUpdateTsIsNull() { + addCriterion("update_ts is null"); + return (Criteria) this; + } + + public Criteria andUpdateTsIsNotNull() { + addCriterion("update_ts is not null"); + return (Criteria) this; + } + + public Criteria andUpdateTsEqualTo(String value) { + addCriterion("update_ts =", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsNotEqualTo(String value) { + addCriterion("update_ts <>", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsGreaterThan(String value) { + addCriterion("update_ts >", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsGreaterThanOrEqualTo(String value) { + addCriterion("update_ts >=", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsLessThan(String value) { + addCriterion("update_ts <", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsLessThanOrEqualTo(String value) { + addCriterion("update_ts <=", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsLike(String value) { + addCriterion("update_ts like", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsNotLike(String value) { + addCriterion("update_ts not like", value, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsIn(List values) { + addCriterion("update_ts in", values, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsNotIn(List values) { + addCriterion("update_ts not in", values, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsBetween(String value1, String value2) { + addCriterion("update_ts between", value1, value2, "updateTs"); + return (Criteria) this; + } + + public Criteria andUpdateTsNotBetween(String value1, String value2) { + addCriterion("update_ts not between", value1, value2, "updateTs"); + return (Criteria) this; + } + } + + /** + * This class was generated by MyBatis Generator. + * This class corresponds to the database table ba_status_history + * + * @mbg.generated do_not_delete_during_merge + */ + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + /** + * This class was generated by MyBatis Generator. + * This class corresponds to the database table ba_status_history + * + * @mbg.generated + */ + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} \ No newline at end of file diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataBaStatusService.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataBaStatusService.java index a8b238b..204054b 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataBaStatusService.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/DeviceDataBaStatusService.java @@ -1,8 +1,11 @@ package com.dongjian.dashboard.back.service; import com.dongjian.dashboard.back.common.response.PageInfo; +import com.dongjian.dashboard.back.common.response.SimpleDataResponse; import com.dongjian.dashboard.back.dto.data.BaStatusDataSearchParam; +import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; +import com.dongjian.dashboard.back.vo.device.LineData; import java.util.List; @@ -14,4 +17,6 @@ public interface DeviceDataBaStatusService { PageInfo getDataList(BaStatusDataSearchParam pageSearchParam, Long companyId, Long userId, Integer languageType); List handleDeviceBaStatusData(BaStatusDataSearchParam pageSearchParam); + + 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 ef166fc..4cec390 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 @@ -260,7 +260,7 @@ public class CommonOpt { public List getPreDay(int days) { // 日本时区 - ZoneId JST = ZoneId.of("Asia/Tokyo"); + ZoneId JST = Constants.ZONE_TOKYO; // 获取当前日期 LocalDate currentDate = LocalDate.now(JST); // 设置日期格式化 @@ -399,8 +399,8 @@ public class CommonOpt { try (ResultSet rs = ps.executeQuery()) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - ZoneId JST = ZoneId.of("Asia/Tokyo"); + DateTimeFormatter formatter = Constants.FORMATTER_YMDHMS; + ZoneId JST = Constants.ZONE_TOKYO; while (rs.next()) { long ts = rs.getLong("upload_at"); @@ -516,7 +516,7 @@ public class CommonOpt { List yDataList = new ArrayList<>(); // 使用 DateTimeFormatter 来格式化时间 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + DateTimeFormatter formatter = Constants.FORMATTER_YMDHMS; ObjectMapper mapper = new ObjectMapper(); // 遍历查询结果 @@ -532,7 +532,7 @@ public class CommonOpt { // 将 long 时间戳转换为 LocalDateTime(日本时区) Instant instant = Instant.ofEpochMilli(receiveTs); - String formattedDate = instant.atZone(ZoneId.of("Asia/Tokyo")) + String formattedDate = instant.atZone(Constants.ZONE_TOKYO) .toLocalDateTime() .format(formatter); 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 58ce354..f0c111f 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 @@ -138,7 +138,7 @@ public class DeviceDataAccumulateServiceImpl implements DeviceDataAccumulateServ } } - LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Tokyo")); + LocalDateTime now = LocalDateTime.now(Constants.ZONE_TOKYO); LocalDate today = now.toLocalDate(); LocalDate yesterday = today.minusDays(1); LocalDate lastYear = DateUtil.getLastYearSameIsoWeekDay(today); diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index 027626b..4d1a553 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -3,20 +3,21 @@ package com.dongjian.dashboard.back.service.impl; import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.language.msg.MsgLanguageChange; import com.dongjian.dashboard.back.common.response.PageInfo; +import com.dongjian.dashboard.back.common.response.SimpleDataResponse; +import com.dongjian.dashboard.back.dao.ex.BaStatusHistoryMapperExt; import com.dongjian.dashboard.back.dao.ex.DeviceInfoMapperExt; import com.dongjian.dashboard.back.dao.ex.DeviceRawdataRealtimeMapperExt; import com.dongjian.dashboard.back.dao.ex.FavoritedDeviceMapperExt; import com.dongjian.dashboard.back.dto.data.BaStatusDataSearchParam; +import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.easyexcel.SecondsToHMSConverter; -import com.dongjian.dashboard.back.model.DeviceInfo; -import com.dongjian.dashboard.back.model.DeviceInfoExample; -import com.dongjian.dashboard.back.model.DeviceRawdataRealtime; -import com.dongjian.dashboard.back.model.DeviceRawdataRealtimeExample; +import com.dongjian.dashboard.back.model.*; import com.dongjian.dashboard.back.service.DeviceDataBaStatusService; import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; import com.dongjian.dashboard.back.vo.data.DeviceMeasureData; +import com.dongjian.dashboard.back.vo.device.LineData; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; @@ -30,6 +31,9 @@ import org.springframework.stereotype.Service; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -49,6 +53,8 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService @Autowired private FavoritedDeviceMapperExt favoritedDeviceMapperExt; @Autowired + private BaStatusHistoryMapperExt baStatusHistoryMapperExt; + @Autowired private DeviceRawdataRealtimeMapperExt deviceRawdataRealtimeMapperExt; @Autowired private MsgLanguageChange msgLanguageChange; @@ -172,4 +178,67 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService return resultList; } + @Override + public SimpleDataResponse> getLineData(Integer searchType, LineDataSearchParams lineDataSearchParams, Long companyId, Long userId, Integer languageType) { + List lineDataList = new ArrayList<>(); + + DeviceInfoExample devExample = new DeviceInfoExample(); + devExample.createCriteria() + .andCompanyIdEqualTo(companyId) + .andDeviceIdEqualTo(lineDataSearchParams.getDeviceId()); + List deviceInfoList = deviceInfoMapperExt.selectByExample(devExample); + if (CollectionUtils.isEmpty(deviceInfoList)) { + return SimpleDataResponse.success(lineDataList); + } + + DeviceInfo deviceInfo = deviceInfoList.get(0); + + // 今天 00:00:00.000 + LocalDate today = LocalDate.now(); + long startOfDay = today + .atStartOfDay(ZoneId.systemDefault()) + .toInstant() + .toEpochMilli(); + String startTs = String.valueOf(startOfDay); + + BaStatusHistoryExample bshExample = new BaStatusHistoryExample(); + BaStatusHistoryExample.Criteria criteria = bshExample.createCriteria(); + criteria.andUpdateTsGreaterThanOrEqualTo(startTs).andDeviceInfoIdEqualTo(deviceInfo.getId()); + + List result = baStatusHistoryMapperExt.selectByExample(bshExample); + if (CollectionUtils.isNotEmpty(result)) { + LineData lineData = new LineData(); + List yCommon = new ArrayList<>(); + for (BaStatusHistory item : result) { + String tsStr = item.getUpdateTs(); + if (tsStr == null || tsStr.isEmpty()) { + continue; // 跳过 + } + + long ts; + try { + ts = Long.parseLong(tsStr); + } catch (NumberFormatException e) { + logger.error("Invalid timestamp: {}", tsStr); + continue; // 非法时间戳跳过 + } + + // 毫秒 -> 日本时间 -> 格式化 + String formatted = Instant.ofEpochMilli(ts) + .atZone(Constants.ZONE_TOKYO) + .format(Constants.FORMATTER_YMDHMS); + + lineData.getXData().add(formatted); + yCommon.add(item.getIsRunning()); + } + + lineData.setAttrCode(lineDataSearchParams.getAttrCodeList()[0]); + lineData.getYData().put("common", yCommon); + + lineDataList.add(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 7e5e1ec..63e37aa 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 @@ -148,7 +148,7 @@ public class DeviceDataMeasureServiceImpl implements DeviceDataMeasureService { } } - ZoneId tokyoZone = ZoneId.of("Asia/Tokyo"); + ZoneId tokyoZone = Constants.ZONE_TOKYO; LocalDate tokyoToday = LocalDate.now(tokyoZone); int year = tokyoToday.getYear(); int month = tokyoToday.getMonthValue(); diff --git a/dongjian-dashboard-back-util/src/test/java/com/dongjian/dashboard/back/util/Test.java b/dongjian-dashboard-back-util/src/test/java/com/dongjian/dashboard/back/util/Test.java index 429b451..dcfc2b7 100644 --- a/dongjian-dashboard-back-util/src/test/java/com/dongjian/dashboard/back/util/Test.java +++ b/dongjian-dashboard-back-util/src/test/java/com/dongjian/dashboard/back/util/Test.java @@ -7,6 +7,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.regex.Matcher; @@ -22,23 +23,31 @@ public class Test { private final static long ondDayMillis = 3600 * 24 * 1000; private static final String betweenQuotesRegex = "\"([^\"]*)\""; + + private static final String[] suffixes = { "_85", "_85_9003", "_111", "_111_9003", "_S", "_s", "_131_5" }; public static void main(String[] args) throws ParseException{ - long ZeroTime = getTodayZeroTime(); - System.out.println(ZeroTime); - long startTime = ZeroTime - ondDayMillis; - System.out.println(startTime); - long endTime = ZeroTime - 1; - System.out.println(endTime); - - int days = 2; - System.out.println("前"+ days +"天的0点的毫秒级时间戳: " + getMinusZeroTimestamp(days)); - - int mins = 9; - minusInterval(mins); - - System.out.println(CommonUtil.extractContentBetweenQuotes("aurora_cluster_endpoint = \"company-13-aurora-cluster.cluster-cde6q2assvmn.ap-northeast-1.rds.amazonaws.com\"")); - +// long ZeroTime = getTodayZeroTime(); +// System.out.println(ZeroTime); +// long startTime = ZeroTime - ondDayMillis; +// System.out.println(startTime); +// long endTime = ZeroTime - 1; +// System.out.println(endTime); +// +// int days = 2; +// System.out.println("前"+ days +"天的0点的毫秒级时间戳: " + getMinusZeroTimestamp(days)); +// +// int mins = 9; +// minusInterval(mins); +// +// System.out.println(CommonUtil.extractContentBetweenQuotes("aurora_cluster_endpoint = \"company-13-aurora-cluster.cluster-cde6q2assvmn.ap-northeast-1.rds.amazonaws.com\"")); + + if (Arrays.stream(suffixes).anyMatch("AMMM_42_TL_TRED800073_131_5"::endsWith)){ + System.out.println("包含"); + } else { + System.out.println("不包含"); + } + } public static String extractContentBetweenQuotes(String text) { From ec026e6510a11776feb95c7a2a6f0c159677d06c Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 28 Jan 2026 11:12:08 +0800 Subject: [PATCH 14/52] =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E5=9B=BE=E8=A1=A5=E5=85=8524=E5=B0=8F=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/service/common/CommonOpt.java | 5 - .../impl/DeviceDataBaStatusServiceImpl.java | 102 +++++++++++++++++- 2 files changed, 99 insertions(+), 8 deletions(-) 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 4cec390..ae7dce7 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 @@ -159,11 +159,6 @@ public class CommonOpt { return getAuroraInfoByApikey(paramMap); } - public String buildAuroraJdbcUrl(String dbUrl, String auroraHost) { - String regex = "(jdbc:mysql://)([^/]+)(/data_center_aeon_admin.*)"; - return dbUrl.replaceAll(regex, "$1" + auroraHost + "$3"); - } - public String extractValue(ObjectMapper mapper, Long categoryId, String rawData) { if (Constants.DEVICE_TYPE_TEMPERATURE_HUMIDITY.contains(categoryId)){ List values = extractAllValues(mapper, rawData); diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index 4d1a553..5bb8fcc 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -31,9 +31,8 @@ import org.springframework.stereotype.Service; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; +import java.time.*; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -235,10 +234,107 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService lineData.setAttrCode(lineDataSearchParams.getAttrCodeList()[0]); lineData.getYData().put("common", yCommon); + fillToEndOfDay(lineData);//补全24小时的算法 + lineDataList.add(lineData); } return SimpleDataResponse.success(lineDataList); } + public static void fillToEndOfDay(LineData lineData) { + DateTimeFormatter DF = Constants.FORMATTER_YMDHMS; + + List xData = lineData.getXData(); + Map> yData = lineData.getYData(); + + // 至少 1 个点才能补 + if (xData == null || xData.isEmpty()) { + return; + } + + // 最后一个已有时间点 + LocalDateTime lastTime = LocalDateTime.parse( + xData.get(xData.size() - 1), DF + ); + + LocalDate date = lastTime.toLocalDate(); + + // 当天 00:00 + LocalDateTime startOfDay = date.atStartOfDay(); + + // 当天 24:00(次日 00:00) + LocalDateTime endOfDay = date.plusDays(1).atStartOfDay(); + + // 如果已经到 24 点,不补 + if (!lastTime.isBefore(endOfDay)) { + return; + } + + // 已有数据占据的时长(0 点 → 最后一个点) + long existSeconds = Duration.between(startOfDay, lastTime).getSeconds(); + long daySeconds = Duration.between(startOfDay, endOfDay).getSeconds(); // 86400 + + if (existSeconds <= 0 || daySeconds <= 0) { + return; + } + + int existCount = xData.size(); + + // 等比例推算全天应有点数 + double ratio = (double) existSeconds / daySeconds; + int totalCount = (int) Math.ceil(existCount / ratio); + int appendCount = totalCount - existCount; + + if (appendCount <= 0) { + return; + } + + // 防止点数爆炸 + int MAX_APPEND = 300; + appendCount = Math.min(appendCount, MAX_APPEND); + + // 剩余可补时长 + long appendSeconds = Duration.between(lastTime, endOfDay).getSeconds(); + + // 计算步长(兜底) + long stepSeconds = appendSeconds / appendCount; + if (stepSeconds <= 0) { + stepSeconds = appendSeconds; + } + + LocalDateTime cursor = lastTime; + boolean appended = false; + + // 按比例补点 + for (int i = 0; i < appendCount; i++) { + cursor = cursor.plusSeconds(stepSeconds); + + if (!cursor.isBefore(endOfDay)) { + break; + } + + xData.add(cursor.format(DF)); + appended = true; + + for (List series : yData.values()) { + series.add(null); + } + } + + // 保底:如果最后一个点仍然 < 23:59:59,强制补一个 + LocalDateTime finalTime = LocalDateTime.parse( + xData.get(xData.size() - 1), DF + ); + + LocalDateTime lastSecondOfDay = endOfDay.minusSeconds(1); + + if (finalTime.isBefore(lastSecondOfDay)) { + xData.add(lastSecondOfDay.format(DF)); + for (List series : yData.values()) { + series.add(null); + } + } + } + } From f0db8e6e43ab2c4edc2362fc2ea84465ebc10ea5 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 28 Jan 2026 17:18:46 +0800 Subject: [PATCH 15/52] =?UTF-8?q?=E5=91=8A=E8=AD=A6=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=A2=9E=E5=8A=A0searchType=3D4=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E3=80=81=E5=AF=BC=E5=87=BA=E8=A1=A8=E5=A4=B4=E5=AF=B9?= =?UTF-8?q?=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DeviceDataAccumulateController.java | 8 ++++ .../DeviceDataBaStatusController.java | 4 ++ .../DeviceDataMeasureController.java | 4 ++ .../mappers/ex/DeviceInfoMapperExt.xml | 41 +++++++++++++++++-- .../ExportDeviceAccumulateDataDTO.java | 27 ++++++------ .../ExportDeviceBaStatusDataDTO.java | 19 +++++---- .../easyexcel/ExportDeviceMeasureDataDTO.java | 17 ++++---- .../dashboard/back/vo/data/BaseData.java | 3 ++ .../back/service/common/CommonOpt.java | 14 +++++++ .../impl/DeviceDataAlarmServiceImpl.java | 18 +++++--- .../dashboard/back/util/CommonUtil.java | 27 ++++++++++++ 11 files changed, 146 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 616a149..dbde976 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 @@ -2,6 +2,7 @@ package com.dongjian.dashboard.back.controller; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.StringUtils; import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; @@ -14,6 +15,8 @@ import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.easyexcel.ExportDeviceAccumulateDataDTO; import com.dongjian.dashboard.back.easyexcel.LanguageDynamicHeaderAdapter; import com.dongjian.dashboard.back.service.DeviceDataAccumulateService; +import com.dongjian.dashboard.back.service.common.CommonOpt; +import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; import com.dongjian.dashboard.back.vo.device.LineData; import io.swagger.v3.oas.annotations.Operation; @@ -48,6 +51,8 @@ public class DeviceDataAccumulateController { @Autowired private DeviceDataAccumulateService deviceDataAccumulateService; + @Autowired + private CommonOpt commonOpt; @OperationLog(operation = "getCumulativeDataList", remark = "") @Operation(summary = "获取积算数据列表") @@ -99,6 +104,9 @@ public class DeviceDataAccumulateController { List exportList = list.stream().map(item -> { ExportDeviceAccumulateDataDTO dto = new ExportDeviceAccumulateDataDTO(); BeanUtils.copyProperties(item, dto); + dto.setLastYearRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getLastYearValue())); + dto.setYesterdayRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getYesterdayValue())); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); return dto; }).toList(); diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java index 3523a4f..020373d 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java @@ -14,6 +14,7 @@ import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.easyexcel.ExportDeviceBaStatusDataDTO; import com.dongjian.dashboard.back.easyexcel.LanguageDynamicHeaderAdapter; import com.dongjian.dashboard.back.service.DeviceDataBaStatusService; +import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; import com.dongjian.dashboard.back.vo.device.LineData; import io.swagger.v3.oas.annotations.Operation; @@ -48,6 +49,8 @@ public class DeviceDataBaStatusController { @Autowired private DeviceDataBaStatusService deviceDataBaStatusService; + @Autowired + private CommonOpt commonOpt; @OperationLog(operation = "getBaStatusDataList", remark = "") @Operation(summary = "获取状态数据列表") @@ -99,6 +102,7 @@ public class DeviceDataBaStatusController { List exportList = list.stream().map(item -> { ExportDeviceBaStatusDataDTO dto = new ExportDeviceBaStatusDataDTO(); BeanUtils.copyProperties(item, dto); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); return dto; }).toList(); diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java index 2e34f8d..6d067bd 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java @@ -14,6 +14,7 @@ import com.dongjian.dashboard.back.dto.device.LineDataSearchParams; import com.dongjian.dashboard.back.easyexcel.ExportDeviceMeasureDataDTO; import com.dongjian.dashboard.back.easyexcel.LanguageDynamicHeaderAdapter; import com.dongjian.dashboard.back.service.DeviceDataMeasureService; +import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.vo.data.DeviceMeasureData; import com.dongjian.dashboard.back.vo.device.LineData; import io.swagger.v3.oas.annotations.Operation; @@ -48,6 +49,8 @@ public class DeviceDataMeasureController { @Autowired private DeviceDataMeasureService deviceDataMeasureService; + @Autowired + private CommonOpt commonOpt; @OperationLog(operation = "getMeasureDataList", remark = "") @Operation(summary = "获取计测数据列表") @@ -99,6 +102,7 @@ public class DeviceDataMeasureController { List exportList = list.stream().map(item -> { ExportDeviceMeasureDataDTO dto = new ExportDeviceMeasureDataDTO(); BeanUtils.copyProperties(item, dto); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); return dto; }).toList(); diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml index c09f402..82ef762 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml @@ -6,6 +6,7 @@ basic_floor.floor_id as floorId, basic_floor.name as floorName, + basic_building.name as buildingName, device_info.id, device_info.device_id, device_info.device_name, @@ -305,8 +306,24 @@ 1 as classId, basic_monitoring_asset.`symbol` assetSymbol from - alert_history - left join device_info on alert_history.device_id = device_info.device_id + + + device_info + left join ( + SELECT + *, + ROW_NUMBER() OVER ( + PARTITION BY device_id + ORDER BY receive_ts DESC + ) AS rn + FROM alert_history + ) alert_history on alert_history.device_id = device_info.device_id AND alert_history.rn = 1 + + + alert_history + left join device_info on alert_history.device_id = device_info.device_id + + left join basic_monitoring_asset on device_info.asset_id = basic_monitoring_asset.equipment_id left join basic_space on basic_monitoring_asset.space_id = basic_space.space_id left join basic_floor on basic_space.floor_id = basic_floor.floor_id @@ -354,8 +371,24 @@ 1 as classId, basic_monitoring_asset.`symbol` assetSymbol from - alert_history - left join device_info on alert_history.device_id = device_info.device_id + + + device_info + left join ( + SELECT + *, + ROW_NUMBER() OVER ( + PARTITION BY device_id + ORDER BY receive_ts DESC + ) AS rn + FROM alert_history + ) alert_history on alert_history.device_id = device_info.device_id AND alert_history.rn = 1 + + + alert_history + left join device_info on alert_history.device_id = device_info.device_id + + left join basic_monitoring_asset on device_info.asset_id = basic_monitoring_asset.equipment_id left join basic_space on basic_monitoring_asset.space_id = basic_space.space_id left join basic_floor on basic_space.floor_id = basic_floor.floor_id diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceAccumulateDataDTO.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceAccumulateDataDTO.java index eedc59e..b1bfd38 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceAccumulateDataDTO.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceAccumulateDataDTO.java @@ -10,32 +10,35 @@ public class ExportDeviceAccumulateDataDTO { @ExcelProperty(value = {"上传时间", "Upload Time", "計測日時"}, converter = TimestampConverter.class) private Long uploadTimestamp; + @ExcelProperty({"设施名", "Facility Name", "施設名"}) + private String buildingName; + @ExcelProperty({"监视点名称", "Monitoring Point Name", "監視点名称"}) private String monitoringPointName; - @ExcelProperty({"楼层名称", "Floor Name", "フロア"}) + @ExcelProperty({"楼层名称", "Floor", "フロア"}) private String floorName; - @ExcelProperty({"监控点分类名称", "Monitoring Point Category Name", "分類"}) + @ExcelProperty({"监控点分类名称", "Category", "分類"}) private String monitoringPointCategoryName; - @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) - private String gatewayInfoName; +// @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) +// private String gatewayInfoName; - @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) - private String dataProviderName; +// @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) +// private String dataProviderName; - @ExcelProperty({"设备状态", "Device Status", "デバイス状態"}) + @ExcelProperty({"设备状态", "Device Status", "ステータスフラグ"}) private String status111; - @ExcelProperty({"累积值", "Cumulative Value", "計測値"}) + @ExcelProperty({"积算值", "Accumulated Value", "積算値"}) private String cumulativeValue; - @ExcelProperty({"昨日值", "Yesterday's Value", "前日値"}) - private String yesterdayValue; + @ExcelProperty({"前日比(%)", "Previous Day Ratio(%)", "前日比(%)"}) + private String yesterdayRatio; - @ExcelProperty({"去年值", "Last Year's Value", "前年値"}) - private String lastYearValue; + @ExcelProperty({"前年比(%)", "Previous Year Ratio(%)", "前年比(%)"}) + private String lastYearRatio; @ExcelProperty({"单位", "Unit", "単位"}) private String unit; diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceBaStatusDataDTO.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceBaStatusDataDTO.java index d6f7ef8..a882969 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceBaStatusDataDTO.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceBaStatusDataDTO.java @@ -10,6 +10,9 @@ public class ExportDeviceBaStatusDataDTO { @ExcelProperty(value = {"上传时间", "Upload Time", "計測日時"}, converter = TimestampConverter.class) private Long uploadTimestamp; + @ExcelProperty({"设施名", "Facility Name", "施設名"}) + private String buildingName; + @ExcelProperty({"监视点名称", "Monitoring Point Name", "監視点名称"}) private String monitoringPointName; @@ -19,17 +22,17 @@ public class ExportDeviceBaStatusDataDTO { @ExcelProperty({"监控点分类名称", "Monitoring Point Category Name", "分類"}) private String monitoringPointCategoryName; - @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) - private String gatewayInfoName; +// @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) +// private String gatewayInfoName; - @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) - private String dataProviderName; +// @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) +// private String dataProviderName; - @ExcelProperty({"设备状态", "Device Status", "デバイス状態"}) - private String status111; + @ExcelProperty({"状态", "Status", "状態"}) + private String runningStatus; - @ExcelProperty(value = {"运行状态", "Running status", "状態"}, converter = RunningStatusConverter.class) - private Integer runningStatus; + @ExcelProperty({"设备状态", "Device Status", "ステータスフラグ"}) + private String status111; @ExcelProperty(value = {"上次运行时间", "Last start time", "前回ON"}, converter = TimestampConverter.class) private Long lastStartTime; diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceMeasureDataDTO.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceMeasureDataDTO.java index 0006bb1..b0ff741 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceMeasureDataDTO.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/easyexcel/ExportDeviceMeasureDataDTO.java @@ -10,6 +10,9 @@ public class ExportDeviceMeasureDataDTO { @ExcelProperty(value = {"上传时间", "Upload Time", "計測日時"}, converter = TimestampConverter.class) private Long uploadTimestamp; + @ExcelProperty({"设施名", "Facility Name", "施設名"}) + private String buildingName; + @ExcelProperty({"监视点名称", "Monitoring Point Name", "監視点名称"}) private String monitoringPointName; @@ -19,22 +22,22 @@ public class ExportDeviceMeasureDataDTO { @ExcelProperty({"监控点分类名称", "Monitoring Point Category Name", "分類"}) private String monitoringPointCategoryName; - @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) - private String gatewayInfoName; +// @ExcelProperty({"网关信息名称", "Gateway Info Name", "接続先情報"}) +// private String gatewayInfoName; - @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) - private String dataProviderName; +// @ExcelProperty({"数据提供方名称", "Data Provider Name", "データソース"}) +// private String dataProviderName; - @ExcelProperty({"设备状态", "Device Status", "デバイス状態"}) + @ExcelProperty({"设备状态", "Device Status", "ステータスフラグ"}) private String status111; @ExcelProperty({"测量值", "Measurement value", "計測値"}) private String measurementValue; - @ExcelProperty({"最大值", "Maximum Value", "最高値"}) + @ExcelProperty({"最大值", "Maximum Value", "最大値"}) private String maxValue; - @ExcelProperty({"最小值", "Minimum Value", "最低値"}) + @ExcelProperty({"最小值", "Minimum Value", "最小値"}) private String minValue; @ExcelProperty({"单位", "Unit", "単位"}) diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/BaseData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/BaseData.java index 4a32f7f..04675b4 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/BaseData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/BaseData.java @@ -15,6 +15,9 @@ public class BaseData { @Schema(description = "device name", example = "12-34") private String deviceName; + @Schema(description = "building name", example = "66") + private String buildingName; + @Schema(description = "upload timestamp", example = "1740033000234") private Long uploadTimestamp; 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 ae7dce7..45ac70a 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 @@ -756,4 +756,18 @@ public class CommonOpt { return result; } + public String status111Mapping(String status111) { + if(StringUtils.isBlank(status111)){ + return null; + } + return switch (status111) { + case "0" -> "正常"; + case "128" -> "サ一ビス停止"; + case "64" -> "オーバーライド"; + case "32" -> "障害"; + case "16" -> "アラ一ム発生中"; + default -> null; + }; + } + } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java index 8a7fc46..23acb65 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java @@ -108,11 +108,19 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { } else { data.setCollected(0); } - data.setAlertLevelStr(msgLanguageChange.getParameterMapByCode(languageType, "alertLevel_" + data.getAlertLevel())); - data.setConfirmStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "confirmStatus_" + data.getConfirmStatus())); - data.setHandleStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "handleStatus_" + data.getHandleStatus())); - data.setElapsedTime(currentTs - data.getUploadTimestamp()); - data.setElapsedTimeStr(commonOpt.formatElapsedTime(data.getElapsedTime(), languageType)); + if (null != data.getAlertLevel()) { + data.setAlertLevelStr(msgLanguageChange.getParameterMapByCode(languageType, "alertLevel_" + data.getAlertLevel())); + } + if (null != data.getConfirmStatus()) { + data.setConfirmStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "confirmStatus_" + data.getConfirmStatus())); + } + if (null != data.getHandleStatus()) { + data.setHandleStatusStr(msgLanguageChange.getParameterMapByCode(languageType, "handleStatus_" + data.getHandleStatus())); + } + if (null != data.getUploadTimestamp()) { + data.setElapsedTime(currentTs - data.getUploadTimestamp()); + data.setElapsedTimeStr(commonOpt.formatElapsedTime(data.getElapsedTime(), languageType)); + } } } diff --git a/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/CommonUtil.java b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/CommonUtil.java index 2a380a1..557eb2a 100644 --- a/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/CommonUtil.java +++ b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/CommonUtil.java @@ -847,4 +847,31 @@ public class CommonUtil { System.out.println(formatDecimal("123.456,7.898", 2)); } + public static String ratio(String a, String b) { + if (StringUtils.isBlank(a) || StringUtils.isBlank(b)) { + return "-"; + } + + a = a.trim(); + b = b.trim(); + + BigDecimal numA; + BigDecimal numB; + try { + numA = new BigDecimal(a); + numB = new BigDecimal(b); + } catch (NumberFormatException e) { + logger.error("参数必须是合法数字字符串", e); + return "-"; + } + + // 除 0 校验 + if (numB.compareTo(BigDecimal.ZERO) == 0) { + logger.error("除数不能为 0"); + return "-"; + } + + BigDecimal result = numA.divide(numB, 2, RoundingMode.HALF_UP); + return result.multiply(new BigDecimal(100)).toPlainString() + "%"; + } } From eac52febd59c4a7984f7dd285e99c59facc7e392 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 28 Jan 2026 22:35:19 +0800 Subject: [PATCH 16/52] =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=9C=9F=E5=AE=9Eip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aspect/OperationLogAspect.java | 3 +- .../dongjian/dashboard/back/util/IPUtils.java | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/IPUtils.java diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/configurator/aspect/OperationLogAspect.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/configurator/aspect/OperationLogAspect.java index bfcd2ae..cef1282 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/configurator/aspect/OperationLogAspect.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/configurator/aspect/OperationLogAspect.java @@ -6,6 +6,7 @@ import com.dongjian.dashboard.back.common.config.DataSourceInterceptor; import com.dongjian.dashboard.back.dao.ex.DashboardOperationLogMapperExt; import com.dongjian.dashboard.back.model.DashboardOperationLog; import com.dongjian.dashboard.back.service.common.CommonOpt; +import com.dongjian.dashboard.back.util.IPUtils; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; @@ -69,7 +70,7 @@ public class OperationLogAspect { logEntry.setUri(uri); logEntry.setMethodName(method.getName()); logEntry.setClassName(signature.getDeclaringTypeName()); - logEntry.setIpAddress(request.getRemoteAddr()); + logEntry.setIpAddress(IPUtils.getClientIp(request)); String paramsJson = objectMapper.writeValueAsString(joinPoint.getArgs()); logEntry.setRequestParams(paramsJson); logEntry.setExecutionTimeMs(duration); diff --git a/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/IPUtils.java b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/IPUtils.java new file mode 100644 index 0000000..7716cc8 --- /dev/null +++ b/dongjian-dashboard-back-util/src/main/java/com/dongjian/dashboard/back/util/IPUtils.java @@ -0,0 +1,40 @@ +package com.dongjian.dashboard.back.util; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +@Slf4j +public class IPUtils { + + private IPUtils() {} + + public static String getClientIp(HttpServletRequest request) { + if (request == null) { + return ""; + } + + String ip = request.getHeader("X-Forwarded-For"); + if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { + return ip.split(",")[0].trim(); + } + + ip = request.getHeader("X-Real-IP"); + if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { + return ip; + } + + ip = request.getHeader("Proxy-Client-IP"); + if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { + return ip; + } + + ip = request.getHeader("WL-Proxy-Client-IP"); + if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { + return ip; + } + + return request.getRemoteAddr(); + } +} + From 1c7b2e67f624b15acc02e759c3396725c05c0599 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Thu, 29 Jan 2026 09:53:22 +0800 Subject: [PATCH 17/52] =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=9B=BE24=E5=B0=8F?= =?UTF-8?q?=E6=97=B6=E5=89=8D=E7=AB=AF=E5=A4=84=E7=90=86=EF=BC=8C=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/DeviceDataBaStatusServiceImpl.java | 97 ------------------- 1 file changed, 97 deletions(-) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index 5bb8fcc..243b435 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -234,107 +234,10 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService lineData.setAttrCode(lineDataSearchParams.getAttrCodeList()[0]); lineData.getYData().put("common", yCommon); - fillToEndOfDay(lineData);//补全24小时的算法 - lineDataList.add(lineData); } return SimpleDataResponse.success(lineDataList); } - public static void fillToEndOfDay(LineData lineData) { - DateTimeFormatter DF = Constants.FORMATTER_YMDHMS; - - List xData = lineData.getXData(); - Map> yData = lineData.getYData(); - - // 至少 1 个点才能补 - if (xData == null || xData.isEmpty()) { - return; - } - - // 最后一个已有时间点 - LocalDateTime lastTime = LocalDateTime.parse( - xData.get(xData.size() - 1), DF - ); - - LocalDate date = lastTime.toLocalDate(); - - // 当天 00:00 - LocalDateTime startOfDay = date.atStartOfDay(); - - // 当天 24:00(次日 00:00) - LocalDateTime endOfDay = date.plusDays(1).atStartOfDay(); - - // 如果已经到 24 点,不补 - if (!lastTime.isBefore(endOfDay)) { - return; - } - - // 已有数据占据的时长(0 点 → 最后一个点) - long existSeconds = Duration.between(startOfDay, lastTime).getSeconds(); - long daySeconds = Duration.between(startOfDay, endOfDay).getSeconds(); // 86400 - - if (existSeconds <= 0 || daySeconds <= 0) { - return; - } - - int existCount = xData.size(); - - // 等比例推算全天应有点数 - double ratio = (double) existSeconds / daySeconds; - int totalCount = (int) Math.ceil(existCount / ratio); - int appendCount = totalCount - existCount; - - if (appendCount <= 0) { - return; - } - - // 防止点数爆炸 - int MAX_APPEND = 300; - appendCount = Math.min(appendCount, MAX_APPEND); - - // 剩余可补时长 - long appendSeconds = Duration.between(lastTime, endOfDay).getSeconds(); - - // 计算步长(兜底) - long stepSeconds = appendSeconds / appendCount; - if (stepSeconds <= 0) { - stepSeconds = appendSeconds; - } - - LocalDateTime cursor = lastTime; - boolean appended = false; - - // 按比例补点 - for (int i = 0; i < appendCount; i++) { - cursor = cursor.plusSeconds(stepSeconds); - - if (!cursor.isBefore(endOfDay)) { - break; - } - - xData.add(cursor.format(DF)); - appended = true; - - for (List series : yData.values()) { - series.add(null); - } - } - - // 保底:如果最后一个点仍然 < 23:59:59,强制补一个 - LocalDateTime finalTime = LocalDateTime.parse( - xData.get(xData.size() - 1), DF - ); - - LocalDateTime lastSecondOfDay = endOfDay.minusSeconds(1); - - if (finalTime.isBefore(lastSecondOfDay)) { - xData.add(lastSecondOfDay.format(DF)); - for (List series : yData.values()) { - series.add(null); - } - } - } - } From 16dc1691cd20bbd8ebed50ae88f695b62c0f5938 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Thu, 29 Jan 2026 10:33:49 +0800 Subject: [PATCH 18/52] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E5=A7=93=E3=80=81=E5=90=8D=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mappers/auto/BasicUserMapper.xml | 42 +++++- .../mappers/ex/BasicUserMapperExt.xml | 2 + .../mappers/ex/OperationLogMapperExt.xml | 8 +- .../dashboard/back/dto/user/OptUserParam.java | 6 + .../dashboard/back/model/BasicUser.java | 68 +++++++++ .../back/model/BasicUserExample.java | 140 ++++++++++++++++++ .../dashboard/back/vo/user/UserPageDTO.java | 6 + .../back/service/impl/UserServiceImpl.java | 6 + 8 files changed, 272 insertions(+), 6 deletions(-) diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BasicUserMapper.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BasicUserMapper.xml index a165f53..708a2d6 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BasicUserMapper.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/BasicUserMapper.xml @@ -26,6 +26,8 @@ + + id, user_type, company_id, username, login_name, `password`, salt, email, mfa_secret, mfa_bind, mobile_number, last_login_time, flag, expire_time, create_time, creator_id, - modify_time, modifier_id, super_role, create_platform + modify_time, modifier_id, super_role, create_platform, last_name, first_name + + select + + distinct + + 'true' as QUERYID, + + from dashboard_notification_category + + + + + order by ${orderByClause} + + + + + + delete from dashboard_notification_category + where id = #{id,jdbcType=BIGINT} + + + + delete from dashboard_notification_category + + + + + + + + SELECT LAST_INSERT_ID() + + insert into dashboard_notification_category (company_id, `name`, remark, + flag, created_by, created_at, + updated_at, updated_by) + values (#{companyId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}, + #{flag,jdbcType=INTEGER}, #{createdBy,jdbcType=BIGINT}, #{createdAt,jdbcType=BIGINT}, + #{updatedAt,jdbcType=BIGINT}, #{updatedBy,jdbcType=BIGINT}) + + + + + SELECT LAST_INSERT_ID() + + insert into dashboard_notification_category + + + company_id, + + + `name`, + + + remark, + + + flag, + + + created_by, + + + created_at, + + + updated_at, + + + updated_by, + + + + + #{companyId,jdbcType=BIGINT}, + + + #{name,jdbcType=VARCHAR}, + + + #{remark,jdbcType=VARCHAR}, + + + #{flag,jdbcType=INTEGER}, + + + #{createdBy,jdbcType=BIGINT}, + + + #{createdAt,jdbcType=BIGINT}, + + + #{updatedAt,jdbcType=BIGINT}, + + + #{updatedBy,jdbcType=BIGINT}, + + + + + + + update dashboard_notification_category + + + id = #{record.id,jdbcType=BIGINT}, + + + company_id = #{record.companyId,jdbcType=BIGINT}, + + + `name` = #{record.name,jdbcType=VARCHAR}, + + + remark = #{record.remark,jdbcType=VARCHAR}, + + + flag = #{record.flag,jdbcType=INTEGER}, + + + created_by = #{record.createdBy,jdbcType=BIGINT}, + + + created_at = #{record.createdAt,jdbcType=BIGINT}, + + + updated_at = #{record.updatedAt,jdbcType=BIGINT}, + + + updated_by = #{record.updatedBy,jdbcType=BIGINT}, + + + + + + + + + update dashboard_notification_category + set id = #{record.id,jdbcType=BIGINT}, + company_id = #{record.companyId,jdbcType=BIGINT}, + `name` = #{record.name,jdbcType=VARCHAR}, + remark = #{record.remark,jdbcType=VARCHAR}, + flag = #{record.flag,jdbcType=INTEGER}, + created_by = #{record.createdBy,jdbcType=BIGINT}, + created_at = #{record.createdAt,jdbcType=BIGINT}, + updated_at = #{record.updatedAt,jdbcType=BIGINT}, + updated_by = #{record.updatedBy,jdbcType=BIGINT} + + + + + + + update dashboard_notification_category + + + company_id = #{companyId,jdbcType=BIGINT}, + + + `name` = #{name,jdbcType=VARCHAR}, + + + remark = #{remark,jdbcType=VARCHAR}, + + + flag = #{flag,jdbcType=INTEGER}, + + + created_by = #{createdBy,jdbcType=BIGINT}, + + + created_at = #{createdAt,jdbcType=BIGINT}, + + + updated_at = #{updatedAt,jdbcType=BIGINT}, + + + updated_by = #{updatedBy,jdbcType=BIGINT}, + + + where id = #{id,jdbcType=BIGINT} + + + + update dashboard_notification_category + set company_id = #{companyId,jdbcType=BIGINT}, + `name` = #{name,jdbcType=VARCHAR}, + remark = #{remark,jdbcType=VARCHAR}, + flag = #{flag,jdbcType=INTEGER}, + created_by = #{createdBy,jdbcType=BIGINT}, + created_at = #{createdAt,jdbcType=BIGINT}, + updated_at = #{updatedAt,jdbcType=BIGINT}, + updated_by = #{updatedBy,jdbcType=BIGINT} + where id = #{id,jdbcType=BIGINT} + + \ No newline at end of file diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/DashboardNotificationMapper.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/DashboardNotificationMapper.xml index 4ba4c67..c30f8a7 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/DashboardNotificationMapper.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/auto/DashboardNotificationMapper.xml @@ -10,6 +10,7 @@ + @@ -94,8 +95,8 @@ WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> - id, company_id, demand_time, category, flag, created_at, created_by, updated_at, - updated_by + id, company_id, demand_time, category, category_id, flag, created_at, created_by, + updated_at, updated_by device_info.id, diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java index e94be6f..614ad01 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java @@ -32,4 +32,7 @@ public class DeviceBaStatusData extends BaseData{ @Schema(description = "last stop time", example = "1720000000000", hidden = true) private String latestTs; + @Schema(description = "0=正常,1=告警", example = "1") + private Integer inAlarm; + } 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 45ac70a..1524384 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 @@ -761,11 +761,11 @@ public class CommonOpt { return null; } return switch (status111) { - case "0" -> "正常"; - case "128" -> "サ一ビス停止"; - case "64" -> "オーバーライド"; - case "32" -> "障害"; - case "16" -> "アラ一ム発生中"; + case "0" -> "NML"; + case "128" -> "MSK"; + case "64" -> "OVR"; + case "32" -> "TBL"; + case "16" -> "ALM"; default -> null; }; } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index 2c55682..e8b1274 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -103,6 +103,8 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService List deviceIds = resultList.stream() .map(DeviceBaStatusData::getDeviceId) .toList(); + //查询是否告警 + List inAlarmDeviceIds = deviceInfoMapperExt.selectAlertingDeviceIds(deviceIds); // 查询 111状态 数据 Map deviceId85To111Map = commonOpt.buildDeviceId85To111Map(deviceIds); @@ -173,6 +175,8 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(diff)); } } + + data.setInAlarm(inAlarmDeviceIds.contains(deviceId) ? 1 : 0); } } From 9d4d8b4b7652e04c0c9758fc6796fd946f08b513 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 4 Feb 2026 18:05:57 +0800 Subject: [PATCH 31/52] =?UTF-8?q?=E8=AD=A6=E6=8A=A5=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0inAlarm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/mappers/ex/DeviceInfoMapperExt.xml | 2 ++ .../dashboard/back/vo/data/DeviceAlarmData.java | 3 +++ .../back/vo/data/DeviceBaStatusData.java | 3 --- .../service/impl/DeviceDataAlarmServiceImpl.java | 15 +++++++++++++++ .../impl/DeviceDataBaStatusServiceImpl.java | 4 ---- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml index 5d90112..9041565 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/DeviceInfoMapperExt.xml @@ -309,6 +309,7 @@ alert_history.confirm_status, alert_history.handle_status, alert_history.id alertHistoryId, + alert_history.retain_alert, 1 as classId, basic_monitoring_asset.`symbol` assetSymbol from @@ -371,6 +372,7 @@ alert_history.confirm_status, alert_history.handle_status, alert_history.id alertHistoryId, + alert_history.retain_alert, 1 as classId, basic_monitoring_asset.`symbol` assetSymbol from diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java index 55dfd2f..62f1f9e 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceAlarmData.java @@ -39,5 +39,8 @@ public class DeviceAlarmData extends BaseData{ @Schema(description = "已过去时长", example = "177日3時間54分間") private String elapsedTimeStr; + @Schema(description = "0=正常,1=告警", example = "1") + private Integer inAlarm; + } diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java index 614ad01..e94be6f 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/data/DeviceBaStatusData.java @@ -32,7 +32,4 @@ public class DeviceBaStatusData extends BaseData{ @Schema(description = "last stop time", example = "1720000000000", hidden = true) private String latestTs; - @Schema(description = "0=正常,1=告警", example = "1") - private Integer inAlarm; - } diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java index 23acb65..e01502e 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataAlarmServiceImpl.java @@ -121,12 +121,27 @@ public class DeviceDataAlarmServiceImpl implements DeviceDataAlarmService { data.setElapsedTime(currentTs - data.getUploadTimestamp()); data.setElapsedTimeStr(commonOpt.formatElapsedTime(data.getElapsedTime(), languageType)); } + data.setInAlarm(isInAlarm(data.getHandleStatus(), data.getRetainAlert()) ? 1 : 0); } } return resultList; } + public static boolean isInAlarm(Integer handleStatus, Integer retainAlert) { + if (handleStatus == null) { + return false; + } + + // (handle_status != 3 AND handle_status != 4) + if (handleStatus != 3 && handleStatus != 4) { + return true; + } + + // (handle_status = 4 AND retain_alert = 1) + return handleStatus == 4 && Integer.valueOf(1).equals(retainAlert); + } + @Override @Transactional public SimpleDataResponse handleAlarm(HandleAlarmParams handleAlarmParams, Long userId, Long companyId, Integer languageType) { diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java index e8b1274..2c55682 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/DeviceDataBaStatusServiceImpl.java @@ -103,8 +103,6 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService List deviceIds = resultList.stream() .map(DeviceBaStatusData::getDeviceId) .toList(); - //查询是否告警 - List inAlarmDeviceIds = deviceInfoMapperExt.selectAlertingDeviceIds(deviceIds); // 查询 111状态 数据 Map deviceId85To111Map = commonOpt.buildDeviceId85To111Map(deviceIds); @@ -175,8 +173,6 @@ public class DeviceDataBaStatusServiceImpl implements DeviceDataBaStatusService data.setContinuousRunningTimeStr(SecondsToHMSConverter.covertSeconds(diff)); } } - - data.setInAlarm(inAlarmDeviceIds.contains(deviceId) ? 1 : 0); } } From 32cd70211217c9556088c774b2dfa3f99537b7a9 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 4 Feb 2026 18:41:14 +0800 Subject: [PATCH 32/52] =?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=AD=A6=E6=8A=A5=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/FavoritedDeviceServiceImpl.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java index c8612a6..babdb75 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java @@ -7,16 +7,15 @@ import com.dongjian.dashboard.back.common.response.ResponseCode; import com.dongjian.dashboard.back.common.response.SimpleDataResponse; import com.dongjian.dashboard.back.dao.ex.FavoritedDeviceMapperExt; import com.dongjian.dashboard.back.dto.data.AccumulateDataSearchParam; +import com.dongjian.dashboard.back.dto.data.AlarmDataSearchParam; import com.dongjian.dashboard.back.dto.data.BaStatusDataSearchParam; import com.dongjian.dashboard.back.dto.data.MeasureDataSearchParam; import com.dongjian.dashboard.back.dto.device.FavoritedDeviceSearchParams; import com.dongjian.dashboard.back.dto.device.OptFavoritedDeviceParams; -import com.dongjian.dashboard.back.service.DeviceDataAccumulateService; -import com.dongjian.dashboard.back.service.DeviceDataBaStatusService; -import com.dongjian.dashboard.back.service.DeviceDataMeasureService; -import com.dongjian.dashboard.back.service.FavoritedDeviceService; +import com.dongjian.dashboard.back.service.*; import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; +import com.dongjian.dashboard.back.vo.data.DeviceAlarmData; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; import com.dongjian.dashboard.back.vo.data.DeviceMeasureData; import com.dongjian.dashboard.back.vo.device.FavoritedDeviceVO; @@ -52,6 +51,8 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { DeviceDataBaStatusService deviceDataBaStatusService; @Autowired DeviceDataMeasureService deviceDataMeasureService; + @Autowired + DeviceDataAlarmService deviceDataAlarmService; @Override @@ -77,6 +78,7 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { List accumulateDeviceIds = new ArrayList<>(); List measureDeviceIds = new ArrayList<>(); List statusDeviceIds = new ArrayList<>(); + List alarmDeviceIds = new ArrayList<>(); for (FavoritedDeviceVO vo : favoritedDeviceVOList) { Long categoryId = vo.getCategoryId(); @@ -86,6 +88,8 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { measureDeviceIds.add(vo.getDeviceId()); } else if (Constants.CATEGORY_MAP.get(Constants.CATEGORY_STATUS).contains(categoryId)) { statusDeviceIds.add(vo.getDeviceId()); + } else if (Constants.CATEGORY_MAP.get(Constants.CATEGORY_ALARM).contains(categoryId)) { + alarmDeviceIds.add(vo.getDeviceId()); } } @@ -93,6 +97,7 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { Map accumulateDataMap = buildAccumulateDataMap(companyId, accumulateDeviceIds); Map measureDataMap = buildMeasureDataMap(companyId, measureDeviceIds); Map statusDataMap = buildStatusDataMap(companyId, statusDeviceIds); + Map alarmDataMap = buildAlarmDataMap(companyId, languageType, alarmDeviceIds); // 按收藏顺序生成结果 for (FavoritedDeviceVO vo : favoritedDeviceVOList) { @@ -106,6 +111,8 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { data = measureDataMap.get(deviceId); } else if (Constants.CATEGORY_MAP.get(Constants.CATEGORY_STATUS).contains(categoryId)) { data = statusDataMap.get(deviceId); + } else if (Constants.CATEGORY_MAP.get(Constants.CATEGORY_ALARM).contains(categoryId)) { + data = alarmDataMap.get(deviceId); } if (data != null) { @@ -116,6 +123,16 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { return new PageInfo<>(resultList); } + private Map buildAlarmDataMap(Long companyId, Integer languageType, List deviceIds) { + if (CollectionUtils.isEmpty(deviceIds)) return Collections.emptyMap(); + + AlarmDataSearchParam param = new AlarmDataSearchParam(); + param.setDeviceIdList(deviceIds); + param.setCompanyIdList(List.of(companyId)); + return deviceDataAlarmService.handleDeviceAlarmData(languageType, param).stream() + .collect(Collectors.toMap(DeviceAlarmData::getDeviceId, Function.identity(), (existing, replacement) -> replacement)); + } + private Map buildAccumulateDataMap(Long companyId, List deviceIds) { if (CollectionUtils.isEmpty(deviceIds)) return Collections.emptyMap(); From 8130e97089c29c127379fc239b9e5a6f16f590d6 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 4 Feb 2026 18:44:24 +0800 Subject: [PATCH 33/52] =?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=AD=A6=E6=8A=A5=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/service/impl/FavoritedDeviceServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java index babdb75..55ffb20 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/impl/FavoritedDeviceServiceImpl.java @@ -129,6 +129,7 @@ public class FavoritedDeviceServiceImpl implements FavoritedDeviceService { AlarmDataSearchParam param = new AlarmDataSearchParam(); param.setDeviceIdList(deviceIds); param.setCompanyIdList(List.of(companyId)); + param.setSearchType(4); return deviceDataAlarmService.handleDeviceAlarmData(languageType, param).stream() .collect(Collectors.toMap(DeviceAlarmData::getDeviceId, Function.identity(), (existing, replacement) -> replacement)); } From 0760418b5fdf6883d16949113956baa17e9fedda Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Wed, 4 Feb 2026 18:45:07 +0800 Subject: [PATCH 34/52] =?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=AD=A6=E6=8A=A5=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dongjian/dashboard/back/dto/data/AlarmDataSearchParam.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/dto/data/AlarmDataSearchParam.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/dto/data/AlarmDataSearchParam.java index 372d34a..712aa5c 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/dto/data/AlarmDataSearchParam.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/dto/data/AlarmDataSearchParam.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; @Data public class AlarmDataSearchParam extends DataSearchParam { - @Schema(description = "查询类型:1-告警一览,2-告警历史,3-未确认告警",example = "1") + @Schema(description = "查询类型:1-告警一览,2-告警历史,3-未确认告警,4-只查告警类型设备(不是历史)",example = "1") private Integer searchType; } From 5d4d03ba1dddc92352316d5a34c931ce2149ed90 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Fri, 6 Feb 2026 13:11:40 +0800 Subject: [PATCH 35/52] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/back/common/Constants.java | 2 + .../DeviceDataAccumulateController.java | 72 ++++++++++++++----- .../controller/DeviceDataAlarmController.java | 61 ++++++++++++---- .../DeviceDataBaStatusController.java | 65 +++++++++++++---- .../DeviceDataMeasureController.java | 65 +++++++++++++---- 5 files changed, 205 insertions(+), 60 deletions(-) diff --git a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java index 4edb1bb..1b08301 100644 --- a/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java +++ b/dongjian-dashboard-back-common/src/main/java/com/dongjian/dashboard/back/common/Constants.java @@ -12,6 +12,8 @@ public class Constants { public static final ZoneId ZONE_TOKYO = ZoneId.of("Asia/Tokyo"); public static final DateTimeFormatter FORMATTER_YMDHMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public static final int EXPORT_PAGE_SIZE = 600; //这个很重要,不要随便动 public static final String DES_SALT = "ci3b512jwy199511"; 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 ebfb77e..0e49135 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 @@ -2,7 +2,10 @@ package com.dongjian.dashboard.back.controller; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.util.StringUtils; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; @@ -19,11 +22,13 @@ import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceAccumulateData; import com.dongjian.dashboard.back.vo.device.LineData; +import com.github.pagehelper.PageHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -98,25 +103,58 @@ public class DeviceDataAccumulateController { String fileName = URLEncoder.encode("積算データ"+CommonUtil.generateExcelSuffix(), StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - PageInfo pageData = deviceDataAccumulateService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); - List list = pageData.getList(); + // ===== 固定导出分页大小===== + pageSearchParam.setPageSize(Constants.EXPORT_PAGE_SIZE); - List exportList = list.stream().map(item -> { - ExportDeviceAccumulateDataDTO dto = new ExportDeviceAccumulateDataDTO(); - BeanUtils.copyProperties(item, dto); - dto.setLastYearRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getLastYearValue())); - dto.setYesterdayRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getYesterdayValue())); - dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); - return dto; - }).toList(); - - // 构造 Excel header:每列三语组合为字符串 "中文||English||日本語" + // ===== 构建 Excel ===== List> head = LanguageDynamicHeaderAdapter.buildHead(ExportDeviceAccumulateDataDTO.class, LanguageType); - - EasyExcel.write(response.getOutputStream()) - .head(head) - .sheet("sheet1") - .doWrite(exportList); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).head(head).build(); + WriteSheet sheet = EasyExcel.writerSheet("sheet1").build(); + + // ===== 循环分页查询并写 Excel ===== + int pageNum = 1; + try { + while (true) { + pageSearchParam.setPageNum(pageNum); + + PageInfo pageData = deviceDataAccumulateService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); + + List list = pageData.getList(); + if (CollectionUtils.isEmpty(list)) { + break; // 没数据了,结束 + } + + for (DeviceAccumulateData item : list) { + ExportDeviceAccumulateDataDTO dto = new ExportDeviceAccumulateDataDTO(); + BeanUtils.copyProperties(item, dto); + dto.setLastYearRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getLastYearValue())); + dto.setYesterdayRatio(CommonUtil.ratio(item.getCumulativeValue(), item.getYesterdayValue())); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); + excelWriter.write(List.of(dto), sheet); + + // 手动置空,提醒 GC 回收 + dto = null; + item = null; + } + + // 手动清理分页数据和缓存 + list.clear(); + PageHelper.clearPage(); + + // 最后一页判断(加这个更安全) + if (pageNum >= pageData.getPages()) { + break; + } + + pageNum++; + } + } catch (Exception e) { + logger.error("export error", e); + throw e; + } finally { + excelWriter.finish(); + PageHelper.clearPage(); + } } diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAlarmController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAlarmController.java index 2d9b95b..8b5484b 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAlarmController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataAlarmController.java @@ -2,6 +2,9 @@ package com.dongjian.dashboard.back.controller; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; @@ -21,11 +24,13 @@ import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceAlarmData; import com.dongjian.dashboard.back.vo.data.HandleHistoryDataVO; import com.dongjian.dashboard.back.vo.device.WindowAlertVO; +import com.github.pagehelper.PageHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -98,22 +103,52 @@ public class DeviceDataAlarmController { String fileName = URLEncoder.encode("警報データ"+ CommonUtil.generateExcelSuffix(), StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - PageInfo pageData = deviceDataAlarmService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); - List list = pageData.getList(); + // ===== 固定导出分页大小 ===== + pageSearchParam.setPageSize(Constants.EXPORT_PAGE_SIZE); - List exportList = list.stream().map(item -> { - ExportDeviceAlarmDataDTO dto = new ExportDeviceAlarmDataDTO(); - BeanUtils.copyProperties(item, dto); - return dto; - }).toList(); - - // 构造 Excel header:每列三语组合为字符串 "中文||English||日本語" + // ===== 构建 Excel ===== List> head = LanguageDynamicHeaderAdapter.buildHead(ExportDeviceAlarmDataDTO.class, LanguageType); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).head(head).build(); + WriteSheet sheet = EasyExcel.writerSheet("sheet1").build(); - EasyExcel.write(response.getOutputStream()) - .head(head) - .sheet("sheet1") - .doWrite(exportList); + int pageNum = 1; + try { + while (true) { + pageSearchParam.setPageNum(pageNum); + + PageInfo pageData = deviceDataAlarmService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); + + List list = pageData.getList(); + if (CollectionUtils.isEmpty(list)) { + break; // 没数据了,结束 + } + + for (DeviceAlarmData item : list) { + ExportDeviceAlarmDataDTO dto = new ExportDeviceAlarmDataDTO(); + BeanUtils.copyProperties(item, dto); + excelWriter.write(List.of(dto), sheet); + + // 手动置空,提醒 GC 回收 + dto = null; + item = null; + } + + // 手动清理分页数据和缓存 + list.clear(); + PageHelper.clearPage(); + + if (pageNum >= pageData.getPages()) { + break; + } + pageNum++; + } + } catch (Exception e) { + logger.error("export alarm error", e); + throw e; + } finally { + excelWriter.finish(); + PageHelper.clearPage(); + } } @OperationLog(operation = "handleAlarm", remark = "") diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java index 375531b..217476e 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataBaStatusController.java @@ -2,6 +2,9 @@ package com.dongjian.dashboard.back.controller; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; @@ -18,11 +21,13 @@ import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceBaStatusData; import com.dongjian.dashboard.back.vo.device.LineData; +import com.github.pagehelper.PageHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -97,23 +102,53 @@ public class DeviceDataBaStatusController { String fileName = URLEncoder.encode("稼働設備"+ CommonUtil.generateExcelSuffix(), StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - PageInfo pageData = deviceDataBaStatusService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); - List list = pageData.getList(); + // ===== 固定导出分页大小 ===== + pageSearchParam.setPageSize(Constants.EXPORT_PAGE_SIZE); - List exportList = list.stream().map(item -> { - ExportDeviceBaStatusDataDTO dto = new ExportDeviceBaStatusDataDTO(); - BeanUtils.copyProperties(item, dto); - dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); - return dto; - }).toList(); - - // 构造 Excel header:每列三语组合为字符串 "中文||English||日本語" + // ===== 构建 Excel ===== List> head = LanguageDynamicHeaderAdapter.buildHead(ExportDeviceBaStatusDataDTO.class, LanguageType); - - EasyExcel.write(response.getOutputStream()) - .head(head) - .sheet("sheet1") - .doWrite(exportList); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).head(head).build(); + WriteSheet sheet = EasyExcel.writerSheet("sheet1").build(); + + int pageNum = 1; + try { + while (true) { + pageSearchParam.setPageNum(pageNum); + + PageInfo pageData = deviceDataBaStatusService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); + + List list = pageData.getList(); + if (CollectionUtils.isEmpty(list)) { + break; // 没数据了,结束 + } + + for (DeviceBaStatusData item : list) { + ExportDeviceBaStatusDataDTO dto = new ExportDeviceBaStatusDataDTO(); + BeanUtils.copyProperties(item, dto); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); + excelWriter.write(List.of(dto), sheet); + + // 手动置空,提醒 GC 回收 + dto = null; + item = null; + } + + // 手动清理分页数据和缓存 + list.clear(); + PageHelper.clearPage(); + + if (pageNum >= pageData.getPages()) { + break; + } + pageNum++; + } + } catch (Exception e) { + logger.error("export BA status error", e); + throw e; + } finally { + excelWriter.finish(); + PageHelper.clearPage(); + } } @OperationLog(operation = "getLineData", remark = "") diff --git a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java index 43f61a4..7db489b 100644 --- a/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java +++ b/dongjian-dashboard-back-controller/src/main/java/com/dongjian/dashboard/back/controller/DeviceDataMeasureController.java @@ -2,6 +2,9 @@ package com.dongjian.dashboard.back.controller; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.dongjian.dashboard.back.common.Constants; import com.dongjian.dashboard.back.common.exception.BusinessException; import com.dongjian.dashboard.back.common.response.PageInfo; import com.dongjian.dashboard.back.common.response.PageResponse; @@ -18,11 +21,13 @@ import com.dongjian.dashboard.back.service.common.CommonOpt; import com.dongjian.dashboard.back.util.CommonUtil; import com.dongjian.dashboard.back.vo.data.DeviceMeasureData; import com.dongjian.dashboard.back.vo.device.LineData; +import com.github.pagehelper.PageHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -97,23 +102,53 @@ public class DeviceDataMeasureController { String fileName = URLEncoder.encode("計測データ"+ CommonUtil.generateExcelSuffix(), StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - PageInfo pageData = deviceDataMeasureService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); - List list = pageData.getList(); + // ===== 固定导出分页大小 ===== + pageSearchParam.setPageSize(Constants.EXPORT_PAGE_SIZE); - List exportList = list.stream().map(item -> { - ExportDeviceMeasureDataDTO dto = new ExportDeviceMeasureDataDTO(); - BeanUtils.copyProperties(item, dto); - dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); - return dto; - }).toList(); - - // 构造 Excel header:每列三语组合为字符串 "中文||English||日本語" + // ===== 构建 Excel ===== List> head = LanguageDynamicHeaderAdapter.buildHead(ExportDeviceMeasureDataDTO.class, LanguageType); - - EasyExcel.write(response.getOutputStream()) - .head(head) - .sheet("sheet1") - .doWrite(exportList); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).head(head).build(); + WriteSheet sheet = EasyExcel.writerSheet("sheet1").build(); + + int pageNum = 1; + try { + while (true) { + pageSearchParam.setPageNum(pageNum); + + PageInfo pageData = deviceDataMeasureService.getDataList(pageSearchParam, CompanyId, UserId, LanguageType); + + List list = pageData.getList(); + if (CollectionUtils.isEmpty(list)) { + break; // 没数据了,结束 + } + + for (DeviceMeasureData item : list) { + ExportDeviceMeasureDataDTO dto = new ExportDeviceMeasureDataDTO(); + BeanUtils.copyProperties(item, dto); + dto.setStatus111(commonOpt.status111Mapping(item.getStatus111())); + excelWriter.write(List.of(dto), sheet); + + // 手动置空,提醒 GC 回收 + dto = null; + item = null; + } + + // 手动清理分页数据和缓存 + list.clear(); + PageHelper.clearPage(); + + if (pageNum >= pageData.getPages()) { + break; + } + pageNum++; + } + } catch (Exception e) { + logger.error("export measure data error", e); + throw e; + } finally { + excelWriter.finish(); + PageHelper.clearPage(); + } } @OperationLog(operation = "getLineData", remark = "") From c716f5e886378f2a49e30ca5f836d03d22a8f9bf Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Sat, 7 Feb 2026 11:39:34 +0800 Subject: [PATCH 36/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ccumulateLineData.java => SubLineData.java} | 2 +- .../back/service/common/CommonOpt.java | 12 ++++++------ .../service/common/LineDataAggregator.java | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) rename dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/{AccumulateLineData.java => SubLineData.java} (95%) diff --git a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/SubLineData.java similarity index 95% rename from dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java rename to dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/SubLineData.java index a2e250a..8e8d93e 100644 --- a/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/AccumulateLineData.java +++ b/dongjian-dashboard-back-model/src/main/java/com/dongjian/dashboard/back/vo/device/SubLineData.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Map; @Data -public class AccumulateLineData { +public class SubLineData { @Schema(description = "属性编码, 默认:single,温湿度设备:temperature或者humidity") private String attrCode; 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 1524384..3c9143b 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 @@ -25,7 +25,7 @@ import com.dongjian.dashboard.back.util.DateUtil; import com.dongjian.dashboard.back.util.DurationData; import com.dongjian.dashboard.back.vo.building.BindedBuildingVO; import com.dongjian.dashboard.back.vo.company.AuroraInfo; -import com.dongjian.dashboard.back.vo.device.AccumulateLineData; +import com.dongjian.dashboard.back.vo.device.SubLineData; import com.dongjian.dashboard.back.vo.device.DeviceIncrement; import com.dongjian.dashboard.back.vo.device.LineData; import com.dongjian.dashboard.back.vo.record.RecordAccumulateDto; @@ -295,7 +295,7 @@ public class CommonOpt { Double yesterdayBase = getDayAccumulate(conn, beforeYesterday, lineDataSearchParams.getDeviceId()); Double lastYearBase = getDayAccumulate(conn, lastYearPrev, lineDataSearchParams.getDeviceId()); - AccumulateLineData acc = new AccumulateLineData(); + SubLineData acc = new SubLineData(); acc.setAttrCode(lineData.getAttrCode()); processAccumulateDay(conn, current, todayBase, "today", acc, deviceInfo); @@ -376,10 +376,10 @@ public class CommonOpt { LocalDate date, Double baseValue, String yKey, - AccumulateLineData accumulateLineData, + SubLineData SubLineData, DeviceInfo deviceInfo) { - AccumulateLineData.childLineData childLineData = new AccumulateLineData.childLineData(); + SubLineData.childLineData childLineData = new SubLineData.childLineData(); String sql = "SELECT upload_value, upload_at FROM dashboard_record_accumulate " + @@ -387,7 +387,7 @@ public class CommonOpt { try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, deviceInfo.getDeviceId()); - ps.setString(2, accumulateLineData.getAttrCode()); + ps.setString(2, SubLineData.getAttrCode()); ps.setInt(3, date.getYear()); ps.setInt(4, date.getMonthValue()); ps.setInt(5, date.getDayOfMonth()); @@ -424,7 +424,7 @@ public class CommonOpt { logger.error("processAccumulateDay error", e); } - accumulateLineData.getSubData().put(yKey, childLineData); + SubLineData.getSubData().put(yKey, childLineData); } private Double getDayAccumulate(Connection conn, LocalDate date, String deviceId) { diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java index 5aa2b2f..db4961d 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java @@ -1,6 +1,6 @@ package com.dongjian.dashboard.back.service.common; -import com.dongjian.dashboard.back.vo.device.AccumulateLineData; +import com.dongjian.dashboard.back.vo.device.SubLineData; import com.dongjian.dashboard.back.vo.device.LineData; import java.time.LocalDate; @@ -219,14 +219,14 @@ public class LineDataAggregator { } /* =============================== - * AccumulateLineData -> LineData + * SubLineData -> LineData * 半小时取最后一条 * =============================== */ - public static void convertToLineDataHour(AccumulateLineData accumulate, LineData lineData) { + public static void convertToLineDataHour(SubLineData accumulate, LineData lineData) { if (accumulate == null || accumulate.getSubData() == null) return; Map seriesMap = new LinkedHashMap<>(); - for (Map.Entry entry : accumulate.getSubData().entrySet()) { + for (Map.Entry entry : accumulate.getSubData().entrySet()) { seriesMap.put(entry.getKey(), aggregateLastByHalfHour(entry.getValue())); } @@ -250,7 +250,7 @@ public class LineDataAggregator { fillTo48HalfHour(lineData); } - private static HalfHourSeries aggregateLastByHalfHour(AccumulateLineData.childLineData child) { + private static HalfHourSeries aggregateLastByHalfHour(SubLineData.childLineData child) { if (child == null || child.getXData() == null || child.getYData() == null) return new HalfHourSeries(null); @@ -307,19 +307,19 @@ public class LineDataAggregator { /* =============================== * 全量对齐 * =============================== */ - public static void convertToLineDataAll(AccumulateLineData accumulate, LineData lineData) { + public static void convertToLineDataAll(SubLineData accumulate, LineData lineData) { if (accumulate == null || accumulate.getSubData() == null) return; LinkedHashSet xSet = new LinkedHashSet<>(); - for (AccumulateLineData.childLineData child : accumulate.getSubData().values()) { + for (SubLineData.childLineData child : accumulate.getSubData().values()) { if (child.getXData() != null) xSet.addAll(child.getXData()); } List mergedX = new ArrayList<>(xSet); Map> tmpMap = new LinkedHashMap<>(); - for (Map.Entry entry : accumulate.getSubData().entrySet()) { + for (Map.Entry entry : accumulate.getSubData().entrySet()) { Map map = new LinkedHashMap<>(); - AccumulateLineData.childLineData child = entry.getValue(); + SubLineData.childLineData child = entry.getValue(); if (child.getXData() != null && child.getYData() != null) { int size = Math.min(child.getXData().size(), child.getYData().size()); for (int i = 0; i < size; i++) map.put(child.getXData().get(i), child.getYData().get(i)); From 356273f74df159a157259547a233554d0250e3d2 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Sat, 7 Feb 2026 22:09:16 +0800 Subject: [PATCH 37/52] =?UTF-8?q?=E8=AE=A1=E6=B5=8B=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=89=8D=E6=97=A5=E3=80=81=E5=89=8D?= =?UTF-8?q?=E5=B9=B4=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/service/common/CommonOpt.java | 90 ++++++++---- .../service/common/LineDataAggregator.java | 130 ++++++++++-------- 2 files changed, 139 insertions(+), 81 deletions(-) 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 3c9143b..92d030a 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 @@ -302,7 +302,7 @@ public class CommonOpt { if (searchType == 1) { processAccumulateDay(conn, yesterday, yesterdayBase, "yesterday", acc, deviceInfo); processAccumulateDay(conn, lastYear, lastYearBase, "lastYear", acc, deviceInfo); - LineDataAggregator.convertToLineDataHour(acc, lineData); + LineDataAggregator.convertToAccumulateLineData(acc, lineData); } else { LineDataAggregator.convertToLineDataAll(acc, lineData); } @@ -471,39 +471,77 @@ public class CommonOpt { List dateList = getPreDay(1); for (String date : dateList) { - LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy_MM_dd")); - - String sql = "SELECT upload_value, upload_at FROM dashboard_record_measure " + - "WHERE device_id = ? AND attr_code = ? AND date_year = ? AND date_month = ? AND date_day = ? ORDER BY id"; - - try (PreparedStatement ps = conn.prepareStatement(sql)) { - ps.setString(1, lineDataSearchParams.getDeviceId()); - ps.setString(2, lineData.getAttrCode()); - ps.setInt(3, localDate.getYear()); - ps.setInt(4, localDate.getMonthValue()); - ps.setInt(5, localDate.getDayOfMonth()); - - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - processResult(rs, lineData, deviceInfo); - } - } - } catch (Exception e) { - logger.error("process measure data error", e); + LocalDate today = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy_MM_dd")); + LocalDate yesterday = today.minusDays(1); + LocalDate lastYear = DateUtil.getLastYearSameIsoWeekDay(today); + + SubLineData sub = new SubLineData(); + sub.setAttrCode(lineData.getAttrCode()); + + processMeasureDay(conn, today, "today", sub, deviceInfo); + if (searchType == 1) { + processMeasureDay(conn, yesterday, "yesterday", sub, deviceInfo); + processMeasureDay(conn, lastYear, "lastYear", sub, deviceInfo); + LineDataAggregator.convertToMeasureLineDataAvg(sub, lineData); + } else { + LineDataAggregator.convertToLineDataAll(sub, lineData); } } }); - if (searchType == 1) { - list.forEach(ld -> { - LineDataAggregator.aggregateAverageByHalfHour(ld); - LineDataAggregator.fillTo48HalfHour(ld); - }); + return list; + } + + private void processMeasureDay( + Connection conn, + LocalDate date, + String yKey, + SubLineData sub, + DeviceInfo deviceInfo + ) { + SubLineData.childLineData child = new SubLineData.childLineData(); + + String sql = "SELECT upload_value, upload_at FROM dashboard_record_measure " + + "WHERE device_id = ? AND attr_code = ? " + + "AND date_year = ? AND date_month = ? AND date_day = ? ORDER BY id"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceInfo.getDeviceId()); + ps.setString(2, sub.getAttrCode()); + ps.setInt(3, date.getYear()); + ps.setInt(4, date.getMonthValue()); + ps.setInt(5, date.getDayOfMonth()); + + try (ResultSet rs = ps.executeQuery()) { + DateTimeFormatter formatter = Constants.FORMATTER_YMDHMS; + + while (rs.next()) { + long ts = rs.getLong("upload_at"); + String value = rs.getString("upload_value"); + if (ts == 0) continue; + + String time = Instant.ofEpochMilli(ts) + .atZone(Constants.ZONE_TOKYO) + .toLocalDateTime() + .format(formatter); + + child.getXData().add(time); + child.getYData().add( + CommonUtil.formatDecimal( + StringUtils.isBlank(value) ? "0" : value, + deviceInfo.getDashboardDecimalPlaces() + ) + ); + } + } + } catch (Exception e) { + logger.error("processMeasureDay error", e); } - return list; + sub.getSubData().put(yKey, child); } + private void processResult(ResultSet result, LineData lineData, DeviceInfo deviceInfo) { try { // 用于存储 xData 和 yData diff --git a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java index db4961d..4ea82a7 100644 --- a/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java +++ b/dongjian-dashboard-back-service/src/main/java/com/dongjian/dashboard/back/service/common/LineDataAggregator.java @@ -149,80 +149,100 @@ public class LineDataAggregator { return LocalDateTime.parse(String.valueOf(x), TimeAxisUtil.DATETIME_FMT); } - /* =============================== - * 按小时聚合(平均值) - * =============================== */ - public static void aggregateByHour(LineData lineData) { - aggregateByHourOrHalfHour(lineData, new AvgCollector(), true); - } + public static void convertToMeasureLineDataAvg(SubLineData accumulate, LineData lineData) { + if (accumulate == null || accumulate.getSubData() == null) return; - /* =============================== - * 按半小时聚合(平均值) - * =============================== */ - public static void aggregateAverageByHalfHour(LineData lineData) { - aggregateByHourOrHalfHour(lineData, new AvgCollector(), false); + // 1. 每个 series 做「半小时平均」 + Map seriesMap = new LinkedHashMap<>(); + for (Map.Entry entry : accumulate.getSubData().entrySet()) { + seriesMap.put(entry.getKey(), aggregateAvgByHalfHour(entry.getValue())); + } + + // 2. today 作为 X 轴基准 + HalfHourSeries today = seriesMap.get("today"); + if (today == null) { + throw new IllegalStateException("subData 必须包含 today"); + } + + // 3. 构建最终 X(yyyy-MM-dd HH:mm:00) + List finalX = new ArrayList<>(); + for (String hm : today.xList) { + finalX.add(today.date + " " + hm + ":00"); + } + + // 4. 构建临时 map,用 today.xList 对齐 + Map> tmpMap = new HashMap<>(); + for (Map.Entry entry : seriesMap.entrySet()) { + tmpMap.put(entry.getKey(), entry.getValue().toMap()); + } + + // 5. 写入 LineData + lineData.setXData(finalX); + lineData.setYData(LineDataAligner.alignY(today.xList, tmpMap)); + lineData.setAttrCode(accumulate.getAttrCode()); + + // 6. 补齐 48 半小时 + fillTo48HalfHour(lineData); } - /* 公共聚合方法 */ - private static void aggregateByHourOrHalfHour( - LineData lineData, - HalfHourCollector collector, - boolean byHour - ) { - if (lineData == null) return; + private static HalfHourSeries aggregateAvgByHalfHour(SubLineData.childLineData child) { + if (child == null || child.getXData() == null || child.getYData() == null) { + return new HalfHourSeries(null); + } - List xData = lineData.getXData(); - Map> yDataMap = lineData.getYData(); - if (xData == null || xData.isEmpty() || yDataMap == null || yDataMap.isEmpty()) return; + Map> bucket = new HashMap<>(); + String date = null; - Set allSeriesKeys = yDataMap.keySet(); + int size = Math.min(child.getXData().size(), child.getYData().size()); - Map> bucket = new TreeMap<>(); - for (int i = 0; i < xData.size(); i++) { - LocalDateTime time = parseTime(xData.get(i)); - String key = byHour ? TimeAxisUtil.hourKey(time) : TimeAxisUtil.halfHourKey(time); + for (int i = 0; i < size; i++) { + Object x = child.getXData().get(i); + Object y = child.getYData().get(i); + if (x == null || y == null) continue; + + LocalDateTime time; + try { + time = LocalDateTime.parse(x.toString(), TimeAxisUtil.DATETIME_FMT); + } catch (Exception e) { + continue; + } - for (String series : allSeriesKeys) { - Object yVal = safeGet(yDataMap.get(series), i); - if (yVal == null) continue; + if (date == null) { + date = time.toLocalDate().toString(); + } - bucket.computeIfAbsent(key, k -> new HashMap<>()); - collector.collect(bucket.get(key), series, time, yVal); + double num; + try { + num = Double.parseDouble(y.toString()); + } catch (Exception e) { + // 非数字直接丢 + continue; } + + String hm = TimeAxisUtil.alignToHalfHour(time.toLocalTime()); // HH:mm + bucket.computeIfAbsent(hm, k -> new ArrayList<>()).add(num); } - // 构建临时 Map 用于统一对齐 - Map> tmpMap = new HashMap<>(); - boolean isAvg = collector instanceof AvgCollector; - - for (Map.Entry> entry : bucket.entrySet()) { - String xKey = entry.getKey(); - Map seriesMap = entry.getValue(); - for (String series : allSeriesKeys) { - Object val; - T tVal = seriesMap.get(series); - if (isAvg && tVal instanceof List) { - List list = (List) tVal; - val = list.stream().mapToDouble(Double::doubleValue).average().orElse(0); - } else if (!isAvg && tVal instanceof TimeValue) { - val = ((TimeValue) tVal).value; - } else { - val = tVal; - } - tmpMap.computeIfAbsent(series, k -> new HashMap<>()).put(xKey, val); - } + List sortedHM = new ArrayList<>(bucket.keySet()); + Collections.sort(sortedHM); + + List values = new ArrayList<>(); + for (String hm : sortedHM) { + List list = bucket.get(hm); + double avg = list.stream().mapToDouble(Double::doubleValue).average().orElse(0D); + values.add(avg); } - List newX = new ArrayList<>(bucket.keySet()); - lineData.setXData(newX); - lineData.setYData(LineDataAligner.alignY(newX, tmpMap)); + return new HalfHourSeries(date, sortedHM, values); } + + /* =============================== * SubLineData -> LineData * 半小时取最后一条 * =============================== */ - public static void convertToLineDataHour(SubLineData accumulate, LineData lineData) { + public static void convertToAccumulateLineData(SubLineData accumulate, LineData lineData) { if (accumulate == null || accumulate.getSubData() == null) return; Map seriesMap = new LinkedHashMap<>(); From 5a398c0ffcd08a4e64a949d2cadbb024f68037c8 Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Sun, 8 Feb 2026 10:35:08 +0800 Subject: [PATCH 38/52] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/mappers/ex/OverviewInfoMapperExt.xml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml index 301329f..57cc7b4 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml @@ -64,14 +64,15 @@ INNER JOIN basic_monitoring_asset on basic_monitoring_asset.space_id = basic_space.space_id INNER JOIN device_info dinfo ON dinfo.asset_id = basic_monitoring_asset.equipment_id LEFT JOIN basic_asset_class_big on basic_asset_class_big.id = basic_monitoring_asset.class_big_id - LEFT JOIN type ty ON dinfo.type_id = ty.id + LEFT JOIN type ty ON dinfo.type_id = ty.id AND ty.flag = 0 + AND ty.device_category_id in + + #{categoryId} + WHERE bbuilding.company_id = #{companyId} AND bbuilding.flag = 0 AND basic_floor.flag = 0 AND basic_space.flag = 0 - AND basic_monitoring_asset.flag = 0 AND dinfo.flag = 0 AND basic_asset_class_big.flag = 0 AND ty.flag = 0 - AND ty.device_category_id in - - #{categoryId} - + AND basic_monitoring_asset.flag = 0 AND dinfo.flag = 0 AND basic_asset_class_big.flag = 0 + \ No newline at end of file From 608a33d218c06f4f5c3f30737126e043f70f7d3f Mon Sep 17 00:00:00 2001 From: "review512jwy@163.com" <“review512jwy@163.com”> Date: Sun, 8 Feb 2026 10:39:12 +0800 Subject: [PATCH 39/52] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/mappers/ex/OverviewInfoMapperExt.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml index 57cc7b4..a6d2fcd 100644 --- a/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml +++ b/dongjian-dashboard-back-dao/src/main/resources/mappers/ex/OverviewInfoMapperExt.xml @@ -19,15 +19,15 @@ INNER JOIN device_info dinfo ON dinfo.asset_id = basic_monitoring_asset.equipment_id INNER JOIN alert_history ah ON dinfo.device_id = ah.device_id LEFT JOIN basic_asset_class_big on basic_asset_class_big.id = basic_monitoring_asset.class_big_id - LEFT JOIN type ty ON dinfo.type_id = ty.id + LEFT JOIN type ty ON dinfo.type_id = ty.id AND ty.flag = 0 + AND ty.device_category_id in + + #{categoryId} + WHERE bbuilding.company_id = #{companyId} AND bbuilding.flag = 0 AND basic_floor.flag = 0 AND basic_space.flag = 0 AND basic_monitoring_asset.flag = 0 AND dinfo.flag = 0 AND basic_asset_class_big.flag = 0 AND ah.confirm_status = 0 AND ah.handle_status = 1 - AND ty.device_category_id in - - #{categoryId} -