新统计方式

This commit is contained in:
zhangyue 2026-08-15 15:45:09 +08:00
parent 7da7e82fbf
commit cab1861edf
6 changed files with 397 additions and 5 deletions

View File

@ -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<List<ScreenIndexSummaryDetailVo2>> getIndexSummry2 (@RequestBody ScreenSummaryVo screenSummaryVo){
String tenantId= iotTools.getTenantId(screenSummaryVo.getAuthId());
List<ScreenIndexSummaryDetailVo2> results = staticticsService.stationStatistic(screenSummaryVo);
return Result.ok(results);
}
}

View File

@ -480,7 +480,7 @@ public class CommonServiceImpl {
Map<String, SurvItemInfo> itemInfo = new HashMap<>();
List<SurvItemInfo> itemList = new ArrayList<>();
List<String> timeList = new ArrayList<>();
Map<String,List<String>> dataMap = new HashMap<>();
LinkedHashMap<String,List<String>> 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<String> timeList = new ArrayList<>();
Map<String,List<String>> dataMap = new HashMap<>();
LinkedHashMap<String,List<String>> dataMap = new LinkedHashMap<>();
if(result!=null && !result.isEmpty()){
for (Map<String, Object> 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);

View File

@ -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<ScreenIndexSummaryDetailVo2> stationStatistic(ScreenSummaryVo screenSummaryVo){
List<ScreenIndexSummaryDetailVo2> 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<SurvStationInfo> 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<String> depIds = stationInfo.getDeviceList().stream().map(SurvDeviceDeploy::getId).collect(Collectors.toList());
List<ScEquZhibiao> allZhibiao = zhibiaoService.getAllChemical(depIds);
if(!allZhibiao.isEmpty()){
Map<String,List<ScEquZhibiao>> allZhibiaoMap = allZhibiao.stream().collect(Collectors.groupingBy(ScEquZhibiao::getEquId));
LinkedHashMap<String,List<String>> 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<ScEquZhibiao> zhibiaoList = allZhibiaoMap.get(deploy.getId());
//step2: 查询指标
Map<String,ScEquZhibiao> zhibiaoMap = new HashMap<>();
List<String> zhibiaoKeys = new ArrayList<>();
if (zhibiaoList!=null && !zhibiaoList.isEmpty()){
zhibiaoList.forEach(zhibiao ->{
zhibiaoMap.put(zhibiao.getEntityField(),zhibiao);
zhibiaoKeys.add(zhibiao.getEntityField());
});
}
List<String> dbFields = NamingConverter.camelsToDbFields(zhibiaoKeys);
if(dbFields==null || dbFields.isEmpty()){//跳过未配置的设备
continue;
}
List<Map<String, Object>> 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<String> timeList = new ArrayList<>();
if(result!=null && !result.isEmpty()){
for (Map<String, Object> 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<String> 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;
}
}

View File

@ -489,6 +489,36 @@ public class DateRangeUtil {
}
/**
* 批量转换日期字符串格式使用 Stream 流式处理
* @param dateList 日期字符串列表
* @param sourcePattern 源日期格式 "yyyy-MM-dd"
* @param targetPattern 目标日期格式 "yyyy/MM/dd"
* @return 转换后的日期字符串列表保持原有顺序
*/
public static List<String> convertDateTimeFormatStream(List<String> 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) {

View File

@ -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<String, List<String>> datas;
@JSONField(name = "dateStr")
private List<String> 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;
}

View File

@ -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<String> timeList;
@ApiModelProperty("Y轴数据")
private Map<String,List<String>> dataMap;
private LinkedHashMap<String,List<String>> dataMap;
}