diff --git a/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/controller/BigScreenControllerP2.java b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/controller/BigScreenControllerP2.java index c623d9a..09f70a0 100644 --- a/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/controller/BigScreenControllerP2.java +++ b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/controller/BigScreenControllerP2.java @@ -24,11 +24,16 @@ import org.jeecg.common.vo.VOHisFormResult; import org.jeecg.common.vo.VOHisResult; import org.jeecg.common.vo.params.StationMaintainPage; import org.jeecg.common.vo.statistic.DeploySummaryVo; +import org.jeecg.common.vo.statistic.ScreenIndexSummaryDetailVo; +import org.jeecg.common.vo.statistic.ScreenIndexSummaryDetailVo2; +import org.jeecg.common.vo.statistic.ScreenSummaryVo; import org.jeecg.modules.appmana.service.*; import org.jeecg.modules.appmana.service.impl.CommonServiceImpl; import org.jeecg.modules.appmana.service.impl.IotCommonP2ServiceImpl; import org.jeecg.modules.appmana.service.impl.IotCommonP3ServiceImpl; +import org.jeecg.modules.appmana.service.impl.StaticticsServiceImpl; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; @@ -63,6 +68,12 @@ public class BigScreenControllerP2 { private ISurvGpsRecordService survGpsRecordService; @Autowired private ISurvEnterpriseInfoService survEnterpriseInfoService; + @Autowired + @Lazy + private CommonServiceImpl iotTools; + @Autowired + private StaticticsServiceImpl staticticsService; + @ApiOperationSupport(order = 1) @ApiOperation(value = "01. 查询设备下各检测项的历史数据", notes = "") @@ -222,4 +233,15 @@ public class BigScreenControllerP2 { } return result; } + + @PostMapping("/getIndexSummry2") + @ApiOperation("大屏首页统计2") + public Result> getIndexSummry2 (@RequestBody ScreenSummaryVo screenSummaryVo){ + String tenantId= iotTools.getTenantId(screenSummaryVo.getAuthId()); + List results = staticticsService.stationStatistic(screenSummaryVo); + + + + return Result.ok(results); + } } diff --git a/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/CommonServiceImpl.java b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/CommonServiceImpl.java index dfe606b..e67ac3d 100644 --- a/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/CommonServiceImpl.java +++ b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/CommonServiceImpl.java @@ -480,7 +480,7 @@ public class CommonServiceImpl { Map itemInfo = new HashMap<>(); List itemList = new ArrayList<>(); List timeList = new ArrayList<>(); - Map> dataMap = new HashMap<>(); + LinkedHashMap> dataMap = new LinkedHashMap<>(); if(StringUtils.isNotBlank(survSummaryDTO.getStationCode())){ //获取站点下的所有设备 @@ -725,7 +725,7 @@ public class CommonServiceImpl { deviceIdColumn, // 设备字段 deploy.getId(), // 设备ID dbFields, // 监测列 - 3 + 12 ); }else{ result = flexibleMonitorService.queryMonthlyStatsByRange( @@ -745,7 +745,7 @@ public class CommonServiceImpl { List timeList = new ArrayList<>(); - Map> dataMap = new HashMap<>(); + LinkedHashMap> dataMap = new LinkedHashMap<>(); if(result!=null && !result.isEmpty()){ for (Map item : result) { @@ -764,7 +764,7 @@ public class CommonServiceImpl { } } } - timeList = DateRangeUtil.convertDateFormatStream(timeList,"yyyy-MM-dd HH:mm:ss",timeFormat); + timeList = DateRangeUtil.convertDateTimeFormatStream(timeList,"yyyy-MM-dd HH:mm:ss",timeFormat); survSummaryVo.setTimeList(timeList); survSummaryVo.setDataMap(dataMap); diff --git a/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/StaticticsServiceImpl.java b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/StaticticsServiceImpl.java new file mode 100644 index 0000000..7bc1d86 --- /dev/null +++ b/zh-module-applet/zh-applet-admin/src/main/java/org/jeecg/modules/appmana/service/impl/StaticticsServiceImpl.java @@ -0,0 +1,314 @@ +package org.jeecg.modules.appmana.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.common.config.TenantContext; +import org.jeecg.common.constant.IotConstants; +import org.jeecg.common.constant.PollutionConstants; +import org.jeecg.common.constant.StatisticConstants; +import org.jeecg.common.entity.ScEquZhibiao; +import org.jeecg.common.entity.SurvDeviceDeploy; +import org.jeecg.common.entity.SurvStationInfo; +import org.jeecg.common.tenant.TenantContextHolder; +import org.jeecg.common.util.DateParseUtils; +import org.jeecg.common.util.DateRangeUtil; +import org.jeecg.common.util.DateTimeRangeUtil; +import org.jeecg.common.util.NamingConverter; +import org.jeecg.common.vo.statistic.ScreenIndexSummaryDetailVo; +import org.jeecg.common.vo.statistic.ScreenIndexSummaryDetailVo2; +import org.jeecg.common.vo.statistic.ScreenSummaryVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class StaticticsServiceImpl { + + @Autowired + @Lazy + private SurvStationInfoServiceImpl survStationInfoService; + @Autowired + @Lazy + private ScEquZhibiaoServiceImpl zhibiaoService; + @Autowired + @Lazy + private FlexibleMonitorServiceImpl flexibleMonitorService; + + /** + * 站点监测数据综合统计 + */ + public List stationStatistic(ScreenSummaryVo screenSummaryVo){ + List results = new ArrayList<>(); + //step1 根据查询模式 和时间段 确定参数组装 + if(StringUtils.isBlank(screenSummaryVo.getSummrayMode())){//默认小时数据 + screenSummaryVo.setSummrayMode(IotConstants.day_hours); + } + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startDate = null; + LocalDateTime endDate = null; + boolean isNow = true;//是否查询本日、本月、本年数据,默认为true,传入时间时为false + String timeFormat = "";//时间格式 + + String summaryMode= screenSummaryVo.getSummrayMode(); + String startTime = screenSummaryVo.getStartTime(); + String endTime = screenSummaryVo.getEndTime(); + + if(IotConstants.day_hours.equals(summaryMode)){ + timeFormat = "d日H时"; + if(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)){ + LocalDate localDate = LocalDate.parse(startTime,DateTimeFormatter.ofPattern("yyyy-MM-dd")); + if(!now.toLocalDate().isEqual(localDate)){//查询的时间不是当前日期 + isNow = false; + startDate = DateParseUtils.parseToLocalDateTime(startTime+" 00:00:00","yyyy-MM-dd HH:mm:ss"); + endDate = DateParseUtils.parseToLocalDateTime(endTime+" 23:59:59","yyyy-MM-dd HH:mm:ss").withNano(999999000); + } + }else{ + startDate = now.withHour(0).withMinute(0).withSecond(0); + endDate = now.withHour(23).withMinute(59).withSecond(59).withNano(999999000); + } + + } + else if(IotConstants.month_days.equals(summaryMode)){ + timeFormat = "M月d日"; + if(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) { + LocalDate localDate = LocalDate.parse(startTime + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + if (!(now.getYear() == localDate.getYear() && now.getMonthValue() == localDate.getMonthValue())) {//查询的时间不是当前日期 + isNow = false; + startDate = DateParseUtils.parseToLocalDateTime(startTime + "-01 00:00:00", "yyyy-MM-dd HH:mm:ss"); + endDate = DateParseUtils.parseToLocalDateTime(endTime + "-01 23:59:59", "yyyy-MM-dd HH:mm:ss"); + endDate = DateTimeRangeUtil.getMonthEnd(endDate).withNano(999999000); + } + }else{ + startDate = now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); + endDate = DateTimeRangeUtil.getMonthEnd(now).withNano(999999000); + } + } + else if(IotConstants.year_months.equals(summaryMode)){ + timeFormat = "yy年M月"; + if(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) { + LocalDate localDate = LocalDate.parse(startTime + "-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + if (!(now.getYear() == localDate.getYear())) {//查询的时间不是当前日期 + isNow = false; + startDate = DateParseUtils.parseToLocalDateTime(startTime + "-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss"); + endDate = DateParseUtils.parseToLocalDateTime(endTime + "-12-31 23:59:59", "yyyy-MM-dd HH:mm:ss"); + } + }else{ + startDate = now.withMonth(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); + endDate = now.withMonth(12).withDayOfMonth(31).withHour(23).withMinute(59).withSecond(59).withNano(999999000); + } + } + + //step2 查询站点和设备 + List stationList = survStationInfoService.getAllStationAndDevice(screenSummaryVo.getStationCode(),"","token"); + + //step3 统计站点数据 + for(SurvStationInfo stationInfo : stationList){ + ScreenIndexSummaryDetailVo2 summaryDetailVo = singleStationStatistic(stationInfo, isNow, startDate, endDate, summaryMode,timeFormat); + results.add(summaryDetailVo); + } + + return results; + } + + + public ScreenIndexSummaryDetailVo2 singleStationStatistic(SurvStationInfo stationInfo, boolean isNow, LocalDateTime startDate, LocalDateTime endDate, String summaryMode,String timeFormat){ + ScreenIndexSummaryDetailVo2 summaryDetailVo = new ScreenIndexSummaryDetailVo2(); + if(!stationInfo.getDeviceList().isEmpty()) { + + + + //step1: 查询指标 + List depIds = stationInfo.getDeviceList().stream().map(SurvDeviceDeploy::getId).collect(Collectors.toList()); + List allZhibiao = zhibiaoService.getAllChemical(depIds); + if(!allZhibiao.isEmpty()){ + Map> allZhibiaoMap = allZhibiao.stream().collect(Collectors.groupingBy(ScEquZhibiao::getEquId)); + LinkedHashMap> dataMap = new LinkedHashMap<>();//数据汇总,所有设备的指标汇总到此map + for (SurvDeviceDeploy deploy : stationInfo.getDeviceList()) { + if ("1004".equals(TenantContext.getTenant()) && PollutionConstants.STINK.equals(deploy.getDeployType())) {//河津不统计恶臭设备 + continue; + } + + //step1: 遍历设备,根据类型使用不同的参数 + String tableName = ""; + String timeColumn = ""; + String deviceIdColumn = ""; + + switch (deploy.getDeployType()) { +// case PollutionConstants.SOIL_SURV: + case PollutionConstants.WATER_QULITY: + tableName = "surv_hisdata_soil"; + timeColumn = "DATA_DATE_TIME"; + deviceIdColumn = "DEPLOY_ID"; + break; +// case PollutionConstants.AIR_SURV: +// tableName = "surv_hisdata_air"; +// timeColumn = "DATA_DATE_TIME"; +// deviceIdColumn = "DEPLOY_ID"; +// break; + case PollutionConstants.STINK: + tableName = "surv_hisdata_vocs"; + timeColumn = "DATA_DATE_TIME"; + deviceIdColumn = "DEPLOY_ID"; + break; + case PollutionConstants.WATER_LIVE: + tableName = "surv_hisdata_livestockwater"; + timeColumn = "DATA_DATE_TIME"; + deviceIdColumn = "DEVICE_ID"; + break; + case PollutionConstants.WATER_ORIENT: + tableName = "surv_hisdata_orientwater"; + timeColumn = "DATA_DATE_TIME"; + deviceIdColumn = "DEVICE_ID"; + break; + default: + break; + } + if(StringUtils.isBlank(tableName)){//跳过不统计的设备 + continue; + } + + //当前设备的指标 + List zhibiaoList = allZhibiaoMap.get(deploy.getId()); + + //step2: 查询指标 + Map zhibiaoMap = new HashMap<>(); + List zhibiaoKeys = new ArrayList<>(); + + if (zhibiaoList!=null && !zhibiaoList.isEmpty()){ + zhibiaoList.forEach(zhibiao ->{ + zhibiaoMap.put(zhibiao.getEntityField(),zhibiao); + zhibiaoKeys.add(zhibiao.getEntityField()); + }); + } + List dbFields = NamingConverter.camelsToDbFields(zhibiaoKeys); + + if(dbFields==null || dbFields.isEmpty()){//跳过未配置的设备 + continue; + } + + List> result = new ArrayList<>(); + if (IotConstants.day_hours.equals(summaryMode)) { + if(isNow){ + result = flexibleMonitorService.queryHourlyStats( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + 24 + ); + }else{ + result = flexibleMonitorService.queryHourlyStatsByRange( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + startDate, + endDate + ); + } + + } else if (IotConstants.month_days.equals(summaryMode)) { + + if(isNow){ + result = flexibleMonitorService.queryDailyStats( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + 30 + ); + }else{ + result = flexibleMonitorService.queryDailyStatsByRange( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + startDate, + endDate + ); + } + + } else if (IotConstants.year_months.equals(summaryMode)) { + + if(isNow){ + result = flexibleMonitorService.queryMonthlyStats( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + 12 + ); + }else{ + result = flexibleMonitorService.queryMonthlyStatsByRange( + tableName, // 表名 + timeColumn, // 时间字段 + deviceIdColumn, // 设备字段 + deploy.getId(), // 设备ID + dbFields, // 监测列 + startDate, + endDate + ); + } + } + + + List timeList = new ArrayList<>(); + + if(result!=null && !result.isEmpty()){ + + for (Map item : result) { + String timePoint = item.get(StatisticConstants.RESULT_TIME_COLUMN).toString(); + timeList.add(timePoint); + for (String db : dbFields) { + String dbKey = db+StatisticConstants.RESULT_VALUE_AVG; + String value = item.get(dbKey).toString(); + String zhibiaoKey = NamingConverter.dbFieldToCamel(dbKey.replace(StatisticConstants.RESULT_VALUE_AVG,"")); + List zhibiaoData = dataMap.get(zhibiaoKey); + if(zhibiaoData==null){ + zhibiaoData = new ArrayList<>(); + } + //保留4位小数 + BigDecimal decimal = new BigDecimal(value); + value = decimal.setScale(4, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString(); + zhibiaoData.add(value); + dataMap.put(zhibiaoKey,zhibiaoData); + } + } + } + timeList = DateRangeUtil.convertDateTimeFormatStream(timeList,"yyyy-MM-dd HH:mm:ss",timeFormat); + + summaryDetailVo.setDateStr(timeList); + summaryDetailVo.setDatas(dataMap); + } + } + + + + } + //设置站名等信息 + summaryDetailVo.setGroupId(stationInfo.getGroupId()); + summaryDetailVo.setGroupName(stationInfo.getGroupName()); + summaryDetailVo.setStationName(stationInfo.getStationName()); + summaryDetailVo.setStationShortName(stationInfo.getStationShortName()); + summaryDetailVo.setStationCode(stationInfo.getStationCode()); + + + + return summaryDetailVo; + } + +} diff --git a/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/util/DateRangeUtil.java b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/util/DateRangeUtil.java index 63d2ceb..fe1693b 100644 --- a/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/util/DateRangeUtil.java +++ b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/util/DateRangeUtil.java @@ -489,6 +489,36 @@ public class DateRangeUtil { } + /** + * 批量转换日期字符串格式(使用 Stream 流式处理) + * @param dateList 日期字符串列表 + * @param sourcePattern 源日期格式,如 "yyyy-MM-dd" + * @param targetPattern 目标日期格式,如 "yyyy/MM/dd" + * @return 转换后的日期字符串列表,保持原有顺序 + */ + public static List convertDateTimeFormatStream(List dateList, String sourcePattern, String targetPattern) { + if (dateList == null || dateList.isEmpty() || sourcePattern == null || targetPattern == null) { + return new ArrayList<>(); + } + + DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern(sourcePattern); + DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(targetPattern); + + return dateList.stream() + .map(dateStr -> { + try { + LocalDateTime date = LocalDateTime.parse(dateStr, sourceFormatter); + return date.format(targetFormatter); + } catch (DateTimeParseException e) { + e.printStackTrace(); + System.err.println("日期格式转换失败: " + dateStr + ", 格式: " + sourcePattern); + return dateStr; + } + }) + .collect(Collectors.toList()); + } + + // ==================== 使用示例 ==================== public static void main(String[] args) { diff --git a/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/ScreenIndexSummaryDetailVo2.java b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/ScreenIndexSummaryDetailVo2.java new file mode 100644 index 0000000..1398910 --- /dev/null +++ b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/ScreenIndexSummaryDetailVo2.java @@ -0,0 +1,25 @@ +package org.jeecg.common.vo.statistic; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.util.LinkedHashMap; +import java.util.List; + +@Data +public class ScreenIndexSummaryDetailVo2 { + @JSONField(name = "datas") + private LinkedHashMap> datas; + @JSONField(name = "dateStr") + private List dateStr; + @JSONField(name = "groupId") + private String groupId; + @JSONField(name = "groupName") + private String groupName; + @JSONField(name = "stationName") + private String stationName; + @JSONField(name = "stationShortName") + private String stationShortName; + @JSONField(name = "stationCode") + private String stationCode; +} diff --git a/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/SurvSummaryVo.java b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/SurvSummaryVo.java index 15e42f7..4e47a33 100644 --- a/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/SurvSummaryVo.java +++ b/zh-module-applet/zh-applet-common/src/main/java/org/jeecg/common/vo/statistic/SurvSummaryVo.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.jeecg.common.vo.iot.common.SurvItemInfo; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -20,5 +21,5 @@ public class SurvSummaryVo { @ApiModelProperty("X轴数据") private List timeList; @ApiModelProperty("Y轴数据") - private Map> dataMap; + private LinkedHashMap> dataMap; }