9 files modified
8 files added
| | |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.GasPageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.*; |
| | | import com.gkhy.fourierSpecialGasMonitor.service.MonitorDataService; |
| | | import com.gkhy.fourierSpecialGasMonitor.service.SummaryStatsService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | |
| | | |
| | | @Autowired |
| | | private MonitorDataService monitorDataService; |
| | | |
| | | @Autowired |
| | | private SummaryStatsService summaryStatsService; |
| | | |
| | | @PostMapping("/gas/lineChart") |
| | | public Result gasLineChart(@RequestBody GasLineChartReqDTO reqDto){ |
| | |
| | | Result result = monitorDataService.gasConcentrationExport(gasConcentrationExportBO); |
| | | return result; |
| | | } |
| | | |
| | | @PostMapping("/gasAtmosphere/stats") |
| | | public Result gasAtmosphereStats(@RequestBody PageQuery<SummaryStatsReqDTO> pageQuery){ |
| | | Result result = summaryStatsService.listSummaryStats(pageQuery); |
| | | return result; |
| | | } |
| | | |
| | | @PostMapping("/gasAtmosphere/extremum") |
| | | public Result gasAtmosphereExtremum(@RequestBody SummaryStatsReqDTO reqDTO){ |
| | | Result result = monitorDataService.gasAtmosphereExtremum(reqDTO); |
| | | return result; |
| | | } |
| | | } |
| | |
| | | return parantList; |
| | | } |
| | | |
| | | /** |
| | | * 递归解析菜单数据,获取菜单树状结构 |
| | | * @param parantItem |
| | | * @param childItemList |
| | | * @return |
| | | */ |
| | | private List<MenuItemDomainDTO> praseChildMenuItems(MenuItemDomainDTO parantItem, List<MenuItemDomainDTO> childItemList){ |
| | | if(childItemList == null || childItemList.size() == 0 || parantItem == null) |
| | | return null; |
| | | List<MenuItemDomainDTO> resultList = new ArrayList<>(); |
| | | // childItemList.forEach(child -> { |
| | | |
| | | // private List<MenuItemDomainDTO> praseChildMenuItems(MenuItemDomainDTO parantItem, List<MenuItemDomainDTO> childItemList){ |
| | | // if(childItemList == null || childItemList.size() == 0 || parantItem == null) |
| | | // return null; |
| | | // List<MenuItemDomainDTO> resultList = new ArrayList<>(); |
| | | //// childItemList.forEach(child -> { |
| | | //// if(parantItem.getId().equals(child.getParentId())){ |
| | | //// resultList.add(child); |
| | | //// } |
| | | //// }); |
| | | // for(MenuItemDomainDTO child : childItemList){ |
| | | // if(parantItem.getId().equals(child.getParentId())){ |
| | | // resultList.add(child); |
| | | // } |
| | | // }); |
| | | for(MenuItemDomainDTO child : childItemList){ |
| | | if(parantItem.getId().equals(child.getParentId())){ |
| | | resultList.add(child); |
| | | // } |
| | | // if(resultList.size() > 0){ |
| | | // for (MenuItemDomainDTO child : childItemList){ |
| | | // List<MenuItemDomainDTO> childList = praseChildMenuItems(child,childItemList); |
| | | // if(childList != null && childList.size() > 0) |
| | | // child.setSubMenuItemList(childList); |
| | | // } |
| | | // } |
| | | // return resultList; |
| | | // } |
| | | |
| | | /** |
| | | * 递归解析菜单数据,获取菜单树状结构 |
| | | * @param parentItem |
| | | * @param allItems |
| | | * @return |
| | | */ |
| | | private List<MenuItemDomainDTO> praseChildMenuItems(MenuItemDomainDTO parentItem, List<MenuItemDomainDTO> allItems) { |
| | | if (allItems == null || allItems.isEmpty() || parentItem == null) { |
| | | return null; |
| | | } |
| | | List<MenuItemDomainDTO> directChildren = new ArrayList<>(); |
| | | // 1. 先找出当前父菜单的直接子菜单(parentId等于当前父菜单的id) |
| | | for (MenuItemDomainDTO item : allItems) { |
| | | if (parentItem.getId().equals(item.getParentId())) { |
| | | directChildren.add(item); |
| | | } |
| | | } |
| | | if(resultList.size() > 0){ |
| | | for (MenuItemDomainDTO child : childItemList){ |
| | | List<MenuItemDomainDTO> childList = praseChildMenuItems(child,childItemList); |
| | | if(childList != null && childList.size() > 0) |
| | | child.setSubMenuItemList(childList); |
| | | // 2. 只对直接子菜单递归,找它们的子菜单(孙菜单) |
| | | if (!directChildren.isEmpty()) { |
| | | for (MenuItemDomainDTO child : directChildren) { // 关键:遍历directChildren而非allItems |
| | | List<MenuItemDomainDTO> grandChildren = praseChildMenuItems(child, allItems); |
| | | if (grandChildren != null && !grandChildren.isEmpty()) { |
| | | child.setSubMenuItemList(grandChildren); |
| | | } |
| | | } |
| | | } |
| | | return resultList; |
| | | return directChildren; |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.entity; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import javax.persistence.*; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Entity |
| | | @Table(name = "summary_stats") |
| | | @Data |
| | | public class SummaryStats { |
| | | |
| | | @Id |
| | | @GeneratedValue(strategy = GenerationType.IDENTITY) |
| | | private Long id; |
| | | |
| | | private LocalDateTime time; |
| | | |
| | | //温度 |
| | | private Double tempMin; |
| | | private Double tempMax; |
| | | private Double tempAvg; |
| | | private Double temp; |
| | | |
| | | //湿度 |
| | | private Double humidityMin; |
| | | private Double humidityMax; |
| | | private Double humidityAvg; |
| | | private Double humidity; |
| | | |
| | | //风速 |
| | | private Double windSpeedMin; |
| | | private Double windSpeedMax; |
| | | private Double windSpeedAvg; |
| | | private Double windSpeed; |
| | | |
| | | //风向 |
| | | private Integer windDirectionMin; |
| | | private Integer windDirectionMax; |
| | | private Double windDirectionAvg; |
| | | private int windDirection; |
| | | |
| | | //压力 |
| | | private Double pressureMin; |
| | | private Double pressureMax; |
| | | private Double pressureAvg; |
| | | private Double pressure; |
| | | |
| | | public SummaryStats(Double tempMin, Double tempMax, Double tempAvg, |
| | | Double humidityMin, Double humidityMax, Double humidityAvg, |
| | | Double windSpeedMin, Double windSpeedMax, Double windSpeedAvg, |
| | | Integer windDirectionMin, Integer windDirectionMax, Double windDirectionAvg, |
| | | Double pressureMin, Double pressureMax, Double pressureAvg) { |
| | | this.tempMin = tempMin; |
| | | this.tempMax = tempMax; |
| | | this.tempAvg = tempAvg; |
| | | this.humidityMin = humidityMin; |
| | | this.humidityMax = humidityMax; |
| | | this.humidityAvg = humidityAvg; |
| | | this.windSpeedMin = windSpeedMin; |
| | | this.windSpeedMax = windSpeedMax; |
| | | this.windSpeedAvg = windSpeedAvg; |
| | | this.windDirectionMin = windDirectionMin; |
| | | this.windDirectionMax = windDirectionMax; |
| | | this.windDirectionAvg = windDirectionAvg; |
| | | this.pressureMin = pressureMin; |
| | | this.pressureMax = pressureMax; |
| | | this.pressureAvg = pressureAvg; |
| | | } |
| | | |
| | | public SummaryStats() { |
| | | |
| | | } |
| | | |
| | | |
| | | public boolean isEmpty(){ |
| | | return tempMin == null&&humidityMin==null&&windSpeedMin==null&&pressureMin==null&& windDirectionMin == null; |
| | | } |
| | | |
| | | public Long getId() { |
| | | return id; |
| | | } |
| | | |
| | | public void setId(Long id) { |
| | | this.id = id; |
| | | } |
| | | |
| | | public LocalDateTime getTime() { |
| | | return time; |
| | | } |
| | | |
| | | public void setTime(LocalDateTime time) { |
| | | this.time = time; |
| | | } |
| | | |
| | | public Double getTempMin() { |
| | | return tempMin; |
| | | } |
| | | |
| | | public void setTempMin(Double tempMin) { |
| | | this.tempMin = tempMin; |
| | | } |
| | | |
| | | public Double getTempMax() { |
| | | return tempMax; |
| | | } |
| | | |
| | | public void setTempMax(Double tempMax) { |
| | | this.tempMax = tempMax; |
| | | } |
| | | |
| | | public Double getTempAvg() { |
| | | return tempAvg; |
| | | } |
| | | |
| | | public void setTempAvg(Double tempAvg) { |
| | | this.tempAvg = tempAvg; |
| | | } |
| | | |
| | | public Double getTemp() { |
| | | return temp; |
| | | } |
| | | |
| | | public void setTemp(Double temp) { |
| | | this.temp = temp; |
| | | } |
| | | |
| | | public Double getHumidityMin() { |
| | | return humidityMin; |
| | | } |
| | | |
| | | public void setHumidityMin(Double humidityMin) { |
| | | this.humidityMin = humidityMin; |
| | | } |
| | | |
| | | public Double getHumidityMax() { |
| | | return humidityMax; |
| | | } |
| | | |
| | | public void setHumidityMax(Double humidityMax) { |
| | | this.humidityMax = humidityMax; |
| | | } |
| | | |
| | | public Double getHumidityAvg() { |
| | | return humidityAvg; |
| | | } |
| | | |
| | | public void setHumidityAvg(Double humidityAvg) { |
| | | this.humidityAvg = humidityAvg; |
| | | } |
| | | |
| | | public Double getHumidity() { |
| | | return humidity; |
| | | } |
| | | |
| | | public void setHumidity(Double humidity) { |
| | | this.humidity = humidity; |
| | | } |
| | | |
| | | public Double getWindSpeedMin() { |
| | | return windSpeedMin; |
| | | } |
| | | |
| | | public void setWindSpeedMin(Double windSpeedMin) { |
| | | this.windSpeedMin = windSpeedMin; |
| | | } |
| | | |
| | | public Double getWindSpeedMax() { |
| | | return windSpeedMax; |
| | | } |
| | | |
| | | public void setWindSpeedMax(Double windSpeedMax) { |
| | | this.windSpeedMax = windSpeedMax; |
| | | } |
| | | |
| | | public Double getWindSpeedAvg() { |
| | | return windSpeedAvg; |
| | | } |
| | | |
| | | public void setWindSpeedAvg(Double windSpeedAvg) { |
| | | this.windSpeedAvg = windSpeedAvg; |
| | | } |
| | | |
| | | public Double getWindSpeed() { |
| | | return windSpeed; |
| | | } |
| | | |
| | | public void setWindSpeed(Double windSpeed) { |
| | | this.windSpeed = windSpeed; |
| | | } |
| | | |
| | | public int getWindDirectionMin() { |
| | | return windDirectionMin; |
| | | } |
| | | |
| | | public void setWindDirectionMin(int windDirectionMin) { |
| | | this.windDirectionMin = windDirectionMin; |
| | | } |
| | | |
| | | public int getWindDirectionMax() { |
| | | return windDirectionMax; |
| | | } |
| | | |
| | | public void setWindDirectionMax(int windDirectionMax) { |
| | | this.windDirectionMax = windDirectionMax; |
| | | } |
| | | |
| | | public Double getWindDirectionAvg() { |
| | | return windDirectionAvg; |
| | | } |
| | | |
| | | public void setWindDirectionAvg(Double windDirectionAvg) { |
| | | this.windDirectionAvg = windDirectionAvg; |
| | | } |
| | | |
| | | public int getWindDirection() { |
| | | return windDirection; |
| | | } |
| | | |
| | | public void setWindDirection(int windDirection) { |
| | | this.windDirection = windDirection; |
| | | } |
| | | |
| | | public Double getPressureMin() { |
| | | return pressureMin; |
| | | } |
| | | |
| | | public void setPressureMin(Double pressureMin) { |
| | | this.pressureMin = pressureMin; |
| | | } |
| | | |
| | | public Double getPressureMax() { |
| | | return pressureMax; |
| | | } |
| | | |
| | | public void setPressureMax(Double pressureMax) { |
| | | this.pressureMax = pressureMax; |
| | | } |
| | | |
| | | public Double getPressureAvg() { |
| | | return pressureAvg; |
| | | } |
| | | |
| | | public void setPressureAvg(Double pressureAvg) { |
| | | this.pressureAvg = pressureAvg; |
| | | } |
| | | |
| | | public Double getPressure() { |
| | | return pressure; |
| | | } |
| | | |
| | | public void setPressure(Double pressure) { |
| | | this.pressure = pressure; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.entity.req; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | public class SummaryStatsReqDTO { |
| | | private LocalDateTime startTime; |
| | | |
| | | private LocalDateTime endTime; |
| | | |
| | | private String type; |
| | | |
| | | private Integer dateType; |
| | | private String date; |
| | | } |
| | |
| | | |
| | | private String angle; |
| | | |
| | | //温度 |
| | | private Double temp; |
| | | |
| | | //湿度 |
| | | private Double humidity; |
| | | |
| | | //风速 |
| | | private Double windSpeed; |
| | | |
| | | //风向 |
| | | private int windDirection; |
| | | |
| | | //压力 |
| | | private Double pressure; |
| | | |
| | | private int gasName01; |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.entity.resp; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | public class SummaryStatsPageRespDTO { |
| | | |
| | | private Long id; |
| | | private LocalDateTime time; |
| | | private Object value; |
| | | private Object min; |
| | | private Object max; |
| | | private Object avg; |
| | | |
| | | public SummaryStatsPageRespDTO( Object max,Object min, Object avg) { |
| | | this.min = min; |
| | | this.max = max; |
| | | this.avg = avg; |
| | | } |
| | | |
| | | public SummaryStatsPageRespDTO() { |
| | | |
| | | } |
| | | |
| | | public Long getId() { |
| | | return id; |
| | | } |
| | | |
| | | public void setId(Long id) { |
| | | this.id = id; |
| | | } |
| | | |
| | | public LocalDateTime getTime() { |
| | | return time; |
| | | } |
| | | |
| | | public void setTime(LocalDateTime time) { |
| | | this.time = time; |
| | | } |
| | | |
| | | public Object getValue() { |
| | | return value; |
| | | } |
| | | |
| | | public void setValue(Object value) { |
| | | this.value = value; |
| | | } |
| | | |
| | | public Object getMin() { |
| | | return min; |
| | | } |
| | | |
| | | public void setMin(Object min) { |
| | | this.min = min; |
| | | } |
| | | |
| | | public Object getMax() { |
| | | return max; |
| | | } |
| | | |
| | | public void setMax(Object max) { |
| | | this.max = max; |
| | | } |
| | | |
| | | public Object getAvg() { |
| | | return avg; |
| | | } |
| | | |
| | | public void setAvg(Object avg) { |
| | | this.avg = avg; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.enums; |
| | | |
| | | public enum StatsTypeEnum { |
| | | TEMP("temp", "temp", "tempMin", "tempMax", "tempAvg"), |
| | | HUMIDITY("humidity", "humidity", "humidityMin", "humidityMax", "humidityAvg"), |
| | | WIND_SPEED("windSpeed", "windSpeed", "windSpeedMin", "windSpeedMax", "windSpeedAvg"), |
| | | WIND_DIRECTION("windDirection", "windDirection", "windDirectionMin", "windDirectionMax", "windDirectionAvg"), |
| | | PRESSURE("pressure", "pressure", "pressureMin", "pressureMax", "pressureAvg"); |
| | | |
| | | private String type; // 与传入的 type 字符串对应 |
| | | private String valueField; // 对应 value 的字段名 |
| | | private String minField; // 最小值字段名 |
| | | private String maxField; // 最大值字段名 |
| | | private String avgField; // 平均值字段名 |
| | | |
| | | StatsTypeEnum(String type, String valueField, String minField, String maxField, String avgField) { |
| | | this.type = type; |
| | | this.valueField = valueField; |
| | | this.minField = minField; |
| | | this.maxField = maxField; |
| | | this.avgField = avgField; |
| | | } |
| | | |
| | | // 根据 type 字符串获取枚举 |
| | | public static StatsTypeEnum getByType(String type) { |
| | | if (type == null) { |
| | | return null; |
| | | } |
| | | for (StatsTypeEnum mapper : values()) { |
| | | if (mapper.type.equalsIgnoreCase(type)) { // 忽略大小写(可选,根据需求调整) |
| | | return mapper; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // getter 方法 |
| | | public String getType() { return type; } |
| | | public String getValueField() { return valueField; } |
| | | public String getMinField() { return minField; } |
| | | public String getMaxField() { return maxField; } |
| | | public String getAvgField() { return avgField; } |
| | | } |
| | |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasCategory; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasConcentration; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO; |
| | | import org.springframework.data.jpa.repository.JpaRepository; |
| | | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
| | | import org.springframework.data.jpa.repository.Query; |
| | | import org.springframework.data.repository.query.Param; |
| | | import org.springframework.security.core.parameters.P; |
| | | import org.springframework.stereotype.Repository; |
| | | |
| | | import javax.persistence.OrderBy; |
| | |
| | | GasConcentration findTopByOrderByDataReceivingTimeDesc(); |
| | | |
| | | List<GasConcentration> findAllByDataReceivingTimeBetweenOrderByDataReceivingTimeDesc(LocalDateTime startTime, LocalDateTime endTime); |
| | | |
| | | //分别查询temp,humidity,windSpeed,windDirection,pressure的平均值,最小值,最大值 |
| | | @Query("SELECT new com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats(MIN(g.temp), MAX(g.temp), FUNCTION('ROUND', AVG(g.temp), 2)," + |
| | | "MIN(g.humidity), MAX(g.humidity), FUNCTION('ROUND', AVG(g.humidity), 2), " + |
| | | "MIN(g.windSpeed), MAX(g.windSpeed), FUNCTION('ROUND', AVG(g.windSpeed), 2), " + |
| | | "MIN(g.windDirection), MAX(g.windDirection), FUNCTION('ROUND', AVG(g.windDirection), 2), " + |
| | | "MIN(g.pressure), MAX(g.pressure), FUNCTION('ROUND', AVG(g.pressure), 2) " + |
| | | ") FROM GasConcentration g WHERE g.time BETWEEN :startTime AND :endTime") |
| | | SummaryStats findStats(@Param("startTime") LocalDateTime startTime,@Param("endTime") LocalDateTime endTime); |
| | | |
| | | |
| | | @Query("SELECT new com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO( " + |
| | | "MAX(CASE WHEN :type = 'temp' THEN g.temp " + |
| | | "WHEN :type = 'humidity' THEN g.humidity " + |
| | | "WHEN :type = 'windSpeed' THEN g.windSpeed " + |
| | | "WHEN :type = 'windDirection' THEN g.windDirection " + |
| | | "WHEN :type = 'pressure' THEN g.pressure END), " + |
| | | "MIN(CASE WHEN :type = 'temp' THEN g.temp " + |
| | | "WHEN :type = 'humidity' THEN g.humidity " + |
| | | "WHEN :type = 'windSpeed' THEN g.windSpeed " + |
| | | "WHEN :type = 'windDirection' THEN g.windDirection " + |
| | | "WHEN :type = 'pressure' THEN g.pressure END), " + |
| | | "FUNCTION('ROUND', AVG(CASE WHEN :type = 'temp' THEN g.temp " + |
| | | "WHEN :type = 'humidity' THEN g.humidity " + |
| | | "WHEN :type = 'windSpeed' THEN g.windSpeed " + |
| | | "WHEN :type = 'windDirection' THEN g.windDirection " + |
| | | "WHEN :type = 'pressure' THEN g.pressure END), 2) " + |
| | | ") FROM GasConcentration g " + |
| | | "WHERE g.time BETWEEN :startTime AND :endTime") |
| | | SummaryStatsPageRespDTO findSummaryStatsByTypeAndTimeRange(@Param("type")String type,@Param("startTime") LocalDateTime startTime,@Param("endTime") LocalDateTime endTime); |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.repository; |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import org.springframework.data.jpa.repository.JpaRepository; |
| | | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
| | | import org.springframework.stereotype.Repository; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | |
| | | @Repository |
| | | public interface SummaryStatsRepository extends JpaRepository<SummaryStats,Long>, JpaSpecificationExecutor<SummaryStats> { |
| | | } |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.service; |
| | | |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.Result; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.model.PageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasConcentration; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasWarnUser; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.GasAtmospherePageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.GasPageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.GasConcentrationExportBO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | import org.springframework.data.domain.Page; |
| | | |
| | | import java.time.LocalDateTime; |
| | |
| | | List<GasConcentration> listDatabyTimeSlotAndPosition(LocalDateTime startTime, LocalDateTime endTime, Integer position); |
| | | |
| | | List<GasConcentration> gasConcentrationExport(GasConcentrationExportBO gasConcentrationExportBO); |
| | | |
| | | SummaryStats findStats(LocalDateTime startTime,LocalDateTime endTime); |
| | | |
| | | Result gasAtmosphereExtremum(SummaryStatsReqDTO reqDTO); |
| | | } |
| | |
| | | Result gasFluxExport(GasFluxExportBO gasFluxExportBO); |
| | | |
| | | Result gasConcentrationExport(GasConcentrationExportBO gasConcentrationExportBO); |
| | | |
| | | Result gasAtmosphereExtremum(SummaryStatsReqDTO reqDTO); |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.service; |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.Result; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.model.PageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | |
| | | public interface SummaryStatsService { |
| | | void save(SummaryStats stats); |
| | | |
| | | Result listSummaryStats(PageQuery<SummaryStatsReqDTO> pageQuery); |
| | | } |
| | |
| | | import com.gkhy.fourierSpecialGasMonitor.repository.GasConcentrationRepository; |
| | | import com.gkhy.fourierSpecialGasMonitor.service.*; |
| | | import com.gkhy.fourierSpecialGasMonitor.utils.SendMessageUtil; |
| | | import com.gkhy.fourierSpecialGasMonitor.utils.SummaryUtils; |
| | | import com.gkhy.fourierSpecialGasMonitor.websocket.GasConcentrationExcWebsocketServer; |
| | | import com.gkhy.fourierSpecialGasMonitor.websocket.GasConcentrationWebsocketServer; |
| | | import com.gkhy.fourierSpecialGasMonitor.websocket.GasDeviceExcWebsocketServer; |
| | |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Field; |
| | | import java.text.MessageFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | |
| | | |
| | | @Autowired |
| | | private GasFluxWebsocketServer gasFluxWebsocketServer; |
| | | |
| | | @Autowired |
| | | private SummaryStatsService summaryStatsService; |
| | | |
| | | private static final ReentrantLock lock = new ReentrantLock(); |
| | | |
| | |
| | | GasConcentration save = gasConcentrationService.save(gasConcentration); |
| | | if (save == null) |
| | | throw new DataReceiveException(this.getClass(), ForeignResultCode.SYSTEM_ERROR_DATABASE_FAIL.getCode(),"气体实时数据保存失败"); |
| | | //计算平局值,最大值,最小值 |
| | | computeAndSaveDailySummaryStats(save); |
| | | dataCacheAndPush(save); |
| | | execDataCountAndPush(reqDto); |
| | | return ForeignResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * 计算并保存当天的气体浓度统计数据(若统计为空则初始化,否则更新) |
| | | * @param newData 新插入的气体浓度数据 |
| | | */ |
| | | private void computeAndSaveDailySummaryStats(GasConcentration newData) { |
| | | // 定义当天时间范围(00:00:00 至当前时间) |
| | | LocalDateTime todayStart = LocalDate.now().atStartOfDay(); |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | |
| | | // 查询当天已有的统计数据 |
| | | SummaryStats dailyStats = gasConcentrationService.findStats(todayStart, now); |
| | | |
| | | // 若统计数据为空,创建新对象并初始化(用新数据作为初始值) |
| | | if (dailyStats == null || dailyStats.isEmpty()) { |
| | | dailyStats = new SummaryStats(); |
| | | SummaryUtils.initSummaryStats(dailyStats, newData); |
| | | } else { |
| | | // 若统计数据已存在,更新统计值(根据新数据重新计算 min/max/avg) |
| | | SummaryUtils.updateSummaryStats(dailyStats, newData); |
| | | } |
| | | |
| | | |
| | | dailyStats.setTemp(newData.getTemp()); |
| | | dailyStats.setHumidity(newData.getHumidity()); |
| | | dailyStats.setWindSpeed(newData.getWindSpeed()); |
| | | dailyStats.setWindDirection(newData.getWindDirection()); |
| | | dailyStats.setPressure(newData.getPressure()); |
| | | // 补充通用字段(时间取最新数据的时间) |
| | | dailyStats.setTime(newData.getTime()); |
| | | |
| | | // 保存统计结果 |
| | | summaryStatsService.save(dailyStats); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | private void execDataCountAndPush(UploadGasConcentrationReqDTO reqDto){ |
| | | RBucket<List<GasCategory>> bucket = redissonClient.getBucket(SystemCacheKeyEnum.KEY_GAS_CATEGORY.getKey()); |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.service.impl; |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.Result; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.SearchResult; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.enums.ResultCode; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.exception.BusinessException; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.model.PageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasConcentration; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasFlux; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasWarnLog; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasWarnUser; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.*; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.FindGasWarnLogPageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.FindGasWarnUserPageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.GasAtmospherePageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.query.GasPageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.GasConcentrationExportBO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.FindGasWarnUserPageRespDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.enums.DeleteStatusEnum; |
| | | import com.gkhy.fourierSpecialGasMonitor.repository.GasConcentrationRepository; |
| | | import com.gkhy.fourierSpecialGasMonitor.service.GasConcentrationService; |
| | | import com.gkhy.fourierSpecialGasMonitor.utils.SummaryUtils; |
| | | import io.micrometer.core.instrument.util.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.domain.Page; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.persistence.criteria.*; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.Year; |
| | | import java.time.YearMonth; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | |
| | | List<GasConcentration> result = gasConcentrationRepository.findAll(specification); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public SummaryStats findStats(LocalDateTime startTime,LocalDateTime endTime) { |
| | | return gasConcentrationRepository.findStats(startTime,endTime); |
| | | } |
| | | |
| | | @Override |
| | | public Result gasAtmosphereExtremum(SummaryStatsReqDTO reqDTO) { |
| | | Result success = Result.success(); |
| | | |
| | | // 1. 参数校验 |
| | | SummaryUtils summaryUtils = new SummaryUtils(); |
| | | summaryUtils.validateParams(reqDTO); |
| | | |
| | | String type = reqDTO.getType(); // 气体类型(如 "temp"、"humidity") |
| | | Integer dateType = reqDTO.getDateType(); // 时间粒度(1-日、2-月、3-年) |
| | | String date = reqDTO.getDate(); // 日期(如 "2025-11-10"、"2025-11"、"2025") |
| | | |
| | | // 2. 根据 dateType 解析时间范围 |
| | | LocalDateTime startTime = null; |
| | | LocalDateTime endTime = null; |
| | | String formatDate = null; // 格式化后的日期(用于返回) |
| | | |
| | | switch (dateType) { |
| | | case 1: // 日查询(date格式:yyyy-MM-dd) |
| | | LocalDate day = LocalDate.parse(date); |
| | | startTime = day.atStartOfDay(); // 当天00:00:00 |
| | | endTime = day.atTime(23, 59, 59); // 当天23:59:59 |
| | | formatDate = day.format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | break; |
| | | case 2: // 月查询(date格式:yyyy-MM) |
| | | YearMonth month = YearMonth.parse(date); |
| | | startTime = month.atDay(1).atStartOfDay(); // 当月1日00:00:00 |
| | | endTime = month.atEndOfMonth().atTime(23, 59, 59); // 当月最后一天23:59:59 |
| | | formatDate = month.format(DateTimeFormatter.ofPattern("yyyy-MM")); |
| | | break; |
| | | case 3: // 年查询(date格式:yyyy) |
| | | Year year = Year.parse(date); |
| | | startTime = year.atDay(1).atStartOfDay(); // 当年1月1日00:00:00 |
| | | endTime = year.atMonth(12).atEndOfMonth().atTime(23, 59, 59); // 当年12月最后一天23:59:59 |
| | | formatDate = year.toString(); |
| | | break; |
| | | default: |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_ILLEGAL.getCode(),"无效的dateType,必须为1(日)、2(月)、3(年)"); |
| | | } |
| | | |
| | | // 3. 动态查询指定类型和时间范围的统计值 |
| | | SummaryStatsPageRespDTO summaryStatsByTypeAndTimeRange = gasConcentrationRepository.findSummaryStatsByTypeAndTimeRange(type, startTime, endTime); |
| | | |
| | | success.setData(summaryStatsByTypeAndTimeRange); |
| | | |
| | | // 5. 返回结果 |
| | | return success; |
| | | } |
| | | } |
| | |
| | | result.setMsg("气体浓度数据导出成功"); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public Result gasAtmosphereExtremum(SummaryStatsReqDTO reqDTO) { |
| | | return gasConcentrationService.gasAtmosphereExtremum(reqDTO); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.service.impl; |
| | | |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.Result; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.domain.SearchResult; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.enums.ResultCode; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.exception.BusinessException; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.model.PageQuery; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.GasAtmospherePageRespDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.repository.SummaryStatsRepository; |
| | | import com.gkhy.fourierSpecialGasMonitor.service.SummaryStatsService; |
| | | import com.gkhy.fourierSpecialGasMonitor.utils.SummaryUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.domain.Page; |
| | | import org.springframework.data.domain.PageRequest; |
| | | import org.springframework.data.domain.Pageable; |
| | | import org.springframework.data.domain.Sort; |
| | | import org.springframework.data.jpa.domain.Specification; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.persistence.criteria.CriteriaBuilder; |
| | | import javax.persistence.criteria.CriteriaQuery; |
| | | import javax.persistence.criteria.Predicate; |
| | | import javax.persistence.criteria.Root; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | |
| | | |
| | | @Service |
| | | public class SummaryStatsServiceImpl implements SummaryStatsService { |
| | | |
| | | @Autowired |
| | | private SummaryStatsRepository summaryStatsRepository; |
| | | |
| | | @Override |
| | | public void save(SummaryStats stats) { |
| | | summaryStatsRepository.save(stats); |
| | | } |
| | | |
| | | @Override |
| | | public Result listSummaryStats(PageQuery<SummaryStatsReqDTO> pageQuery) { |
| | | // 分页参数校验(复用已有逻辑,补充非空判断) |
| | | if (pageQuery == null || pageQuery.getPageIndex() == null || pageQuery.getPageSize() == null) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL, "分页参数不能为空"); |
| | | } |
| | | // 校验分页索引和大小合法性(避免负数或过大值) |
| | | if (pageQuery.getPageIndex() < 1 || pageQuery.getPageSize() < 1 || pageQuery.getPageSize() > 1000) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR, "分页索引必须≥1,分页大小必须在1-1000之间"); |
| | | } |
| | | |
| | | //查询参数校验(处理 searchParams 为 null 的情况) |
| | | SummaryStatsReqDTO searchParams = pageQuery.getSearchParams(); |
| | | if (searchParams == null) { |
| | | searchParams = new SummaryStatsReqDTO(); // 避免后续调用 NPE |
| | | } |
| | | LocalDateTime startTime = searchParams.getStartTime(); |
| | | LocalDateTime endTime = searchParams.getEndTime(); |
| | | String type = searchParams.getType(); // type 改为 String 类型 |
| | | |
| | | // 校验 type 合法性(允许为 null,若不为 null 则必须是指定值) |
| | | List<String> validTypes = Arrays.asList("temp", "humidity", "windSpeed", "windDirection", "pressure"); |
| | | if (type != null && !validTypes.contains(type)) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR, |
| | | "type 必须为 temp、humidity、windSpeed、windDirection、pressure 中的一种"); |
| | | } |
| | | |
| | | // 初始化返回结果 |
| | | SearchResult<List<SummaryStatsPageRespDTO>> searchResult = new SearchResult<>(); |
| | | searchResult.setPageIndex(pageQuery.getPageIndex()); |
| | | searchResult.setPageSize(pageQuery.getPageSize()); |
| | | searchResult.setSuccess(); |
| | | // 构建查询条件(使用 List 而非 Set,逻辑更清晰;补充时间范围非空判断) |
| | | Specification<SummaryStats> specification = (root, query, criteriaBuilder) -> { |
| | | List<Predicate> predicates = new ArrayList<>(); |
| | | // 时间范围条件:仅当 start/endTime 非空时添加(避免 null 导致的查询异常) |
| | | if (startTime != null && endTime != null) { |
| | | predicates.add(criteriaBuilder.between(root.get("time"), startTime, endTime)); |
| | | } else if (startTime != null) { |
| | | predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("time"), startTime)); |
| | | } else if (endTime != null) { |
| | | predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("time"), endTime)); |
| | | } |
| | | // 可扩展其他条件(如按位置、设备筛选) |
| | | return criteriaBuilder.and(predicates.toArray(new Predicate[0])); |
| | | }; |
| | | // 构建分页参数(封装分页索引转换逻辑,避免硬编码) |
| | | Pageable pageable = PageRequest.of(pageQuery.getPageIndex()-1, pageQuery.getPageSize(), Sort.Direction.DESC, "time"); |
| | | // 执行查询 |
| | | Page<SummaryStats> statsPage = summaryStatsRepository.findAll(specification, pageable); |
| | | if (statsPage.isEmpty()) { |
| | | return searchResult; // 空结果直接返回 |
| | | } |
| | | |
| | | SummaryUtils summaryUtils = new SummaryUtils(); |
| | | // 转换结果(使用枚举映射处理 type 逻辑) |
| | | List<SummaryStatsPageRespDTO> respDTOS = statsPage.getContent().stream() |
| | | .map(stats -> summaryUtils.convertToResp(stats, type)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 填充返回结果 |
| | | searchResult.setTotal(statsPage.getTotalElements()); |
| | | searchResult.setPages(statsPage.getTotalPages()); |
| | | searchResult.setData(respDTOS); |
| | | return searchResult; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.gkhy.fourierSpecialGasMonitor.utils; |
| | | |
| | | import com.alibaba.druid.util.StringUtils; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.enums.ResultCode; |
| | | import com.gkhy.fourierSpecialGasMonitor.commons.exception.BusinessException; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.GasConcentration; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO; |
| | | import com.gkhy.fourierSpecialGasMonitor.enums.StatsTypeEnum; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.BeanUtils; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.time.LocalDate; |
| | | import java.time.Year; |
| | | import java.time.YearMonth; |
| | | import java.time.format.DateTimeParseException; |
| | | import java.util.Arrays; |
| | | |
| | | public class SummaryUtils { |
| | | |
| | | private final Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 初始化统计数据(当当天无数据时,用新数据作为初始值) |
| | | */ |
| | | public static void initSummaryStats(SummaryStats stats, GasConcentration data) { |
| | | // 初始化 temp 相关统计(min/max/avg 均为当前数据值) |
| | | stats.setTempMin(data.getTemp()); |
| | | stats.setTempMax(data.getTemp()); |
| | | stats.setTempAvg(data.getTemp()); |
| | | |
| | | // 初始化 humidity 相关统计 |
| | | stats.setHumidityMin(data.getHumidity()); |
| | | stats.setHumidityMax(data.getHumidity()); |
| | | stats.setHumidityAvg(data.getHumidity()); |
| | | |
| | | // 初始化 windSpeed 相关统计 |
| | | Double windSpeed = data.getWindSpeed(); |
| | | stats.setWindSpeedMin(windSpeed); |
| | | stats.setWindSpeedMax(windSpeed); |
| | | stats.setWindSpeedAvg(windSpeed); |
| | | |
| | | // 初始化 windDirection 相关统计(处理可能的 null) |
| | | Integer windDirection = data.getWindDirection(); |
| | | stats.setWindDirectionMin(windDirection); |
| | | stats.setWindDirectionMax(windDirection); |
| | | stats.setWindDirectionAvg(windDirection != null ? windDirection.doubleValue() : null); |
| | | |
| | | // 初始化 pressure 相关统计 |
| | | Double pressure = data.getPressure(); |
| | | stats.setPressureMin(pressure); |
| | | stats.setPressureMax(pressure); |
| | | stats.setPressureAvg(pressure); |
| | | } |
| | | |
| | | /** |
| | | * 更新统计数据(根据新数据重新计算 min/max/avg) |
| | | */ |
| | | public static void updateSummaryStats(SummaryStats stats, GasConcentration newData) { |
| | | // 更新 temp:min 取更小值,max 取更大值,avg 重新计算(需注意:avg 不能直接用当前 avg 计算,需累计总和/数量) |
| | | // 注意:此处简化处理,实际 avg 需基于总样本数计算(建议在数据库查询时直接聚合,而非内存中更新) |
| | | Double newTemp = newData.getTemp(); |
| | | stats.setTempMin(min(stats.getTempMin(), newTemp)); |
| | | stats.setTempMax(max(stats.getTempMax(), newTemp)); |
| | | |
| | | // 更新 humidity |
| | | Double newHumidity = newData.getHumidity(); |
| | | stats.setHumidityMin(min(stats.getHumidityMin(), newHumidity)); |
| | | stats.setHumidityMax(max(stats.getHumidityMax(), newHumidity)); |
| | | |
| | | // 更新 windSpeed |
| | | Double newWindSpeed = newData.getWindSpeed(); |
| | | stats.setWindSpeedMin(min(stats.getWindSpeedMin(), newWindSpeed)); |
| | | stats.setWindSpeedMax(max(stats.getWindSpeedMax(), newWindSpeed)); |
| | | |
| | | // 更新 windDirection |
| | | Integer newWindDir = newData.getWindDirection(); |
| | | stats.setWindDirectionMin(min(stats.getWindDirectionMin(), newWindDir)); |
| | | stats.setWindDirectionMax(max(stats.getWindDirectionMax(), newWindDir)); |
| | | |
| | | // 更新 pressure |
| | | Double newPressure = newData.getPressure(); |
| | | stats.setPressureMin(min(stats.getPressureMin(), newPressure)); |
| | | stats.setPressureMax(max(stats.getPressureMax(), newPressure)); |
| | | } |
| | | |
| | | /** |
| | | * 安全计算两个 Double 的最小值(处理 null) |
| | | */ |
| | | private static Double min(Double a, Double b) { |
| | | if (a == null) return b; |
| | | if (b == null) return a; |
| | | return Math.min(a, b); |
| | | } |
| | | |
| | | /** |
| | | * 安全计算两个 Integer 的最小值(处理 null) |
| | | */ |
| | | private static Integer min(Integer a, Integer b) { |
| | | if (a == null) return b; |
| | | if (b == null) return a; |
| | | return Math.min(a, b); |
| | | } |
| | | |
| | | // 同理实现 max 方法(Double 和 Integer 版本) |
| | | private static Double max(Double a, Double b) { |
| | | if (a == null) return b; |
| | | if (b == null) return a; |
| | | return Math.max(a, b); |
| | | } |
| | | |
| | | private static Integer max(Integer a, Integer b) { |
| | | if (a == null) return b; |
| | | if (b == null) return a; |
| | | return Math.max(a, b); |
| | | } |
| | | |
| | | public void validateParams(SummaryStatsReqDTO reqDTO) { |
| | | if (reqDTO == null) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"请求参数不能为空"); |
| | | } |
| | | if (StringUtils.isEmpty(reqDTO.getType())) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"气体类型(type)不能为空"); |
| | | } |
| | | if (reqDTO.getDateType() == null || !Arrays.asList(1, 2, 3).contains(reqDTO.getDateType())) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_ILLEGAL.getCode(),"dateType必须为1(日)、2(月)、3(年)"); |
| | | } |
| | | if (StringUtils.isEmpty(reqDTO.getDate())) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"日期(date)不能为空"); |
| | | } |
| | | // 校验date格式(根据dateType) |
| | | try { |
| | | switch (reqDTO.getDateType()) { |
| | | case 1: |
| | | LocalDate.parse(reqDTO.getDate()); // 校验 yyyy-MM-dd |
| | | break; |
| | | case 2: |
| | | YearMonth.parse(reqDTO.getDate()); // 校验 yyyy-MM |
| | | break; |
| | | case 3: |
| | | Year.parse(reqDTO.getDate()); // 校验 yyyy |
| | | break; |
| | | } |
| | | } catch (DateTimeParseException e) { |
| | | throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_ILLEGAL.getCode(),"日期格式错误,dateType=" + reqDTO.getDateType() + "时,date应为" + |
| | | (reqDTO.getDateType() == 1 ? "yyyy-MM-dd" : reqDTO.getDateType() == 2 ? "yyyy-MM" : "yyyy")); |
| | | } |
| | | } |
| | | |
| | | |
| | | public SummaryStatsPageRespDTO convertToResp(SummaryStats stats, String type) { |
| | | SummaryStatsPageRespDTO respDTO = new SummaryStatsPageRespDTO(); |
| | | BeanUtils.copyProperties(stats, respDTO); // 复制公共字段(如 time) |
| | | |
| | | if (type == null) { |
| | | return respDTO; // 若 type 为 null,不设置指标相关字段 |
| | | } |
| | | |
| | | StatsTypeEnum mapper = StatsTypeEnum.getByType(type); |
| | | if (mapper == null) { |
| | | return respDTO; // 无效 type(理论上已在参数校验时拦截) |
| | | } |
| | | |
| | | try { |
| | | // 反射获取字段值(通过枚举映射的字段名) |
| | | Field valueField = SummaryStats.class.getDeclaredField(mapper.getValueField()); |
| | | Field minField = SummaryStats.class.getDeclaredField(mapper.getMinField()); |
| | | Field maxField = SummaryStats.class.getDeclaredField(mapper.getMaxField()); |
| | | Field avgField = SummaryStats.class.getDeclaredField(mapper.getAvgField()); |
| | | |
| | | valueField.setAccessible(true); |
| | | minField.setAccessible(true); |
| | | maxField.setAccessible(true); |
| | | avgField.setAccessible(true); |
| | | |
| | | // 设置到响应 DTO |
| | | respDTO.setValue(valueField.get(stats)); |
| | | respDTO.setMin(minField.get(stats)); |
| | | respDTO.setMax(maxField.get(stats)); |
| | | respDTO.setAvg(avgField.get(stats)); |
| | | } catch (NoSuchFieldException | IllegalAccessException e) { |
| | | logger.error("转换 SummaryStats 到 DTO 失败,type={}, stats={}", type, stats, e); |
| | | } |
| | | return respDTO; |
| | | } |
| | | } |