diff --git a/pom.xml b/pom.xml index 0cbb550..4bfa9e8 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,12 @@ 5.8.25 + + + org.springframework.boot + spring-boot-starter-validation + + org.springframework.boot diff --git a/src/main/java/com/southern/power/grid/controller/DnerController.java b/src/main/java/com/southern/power/grid/controller/DnerController.java index 8b8f016..83b88b2 100644 --- a/src/main/java/com/southern/power/grid/controller/DnerController.java +++ b/src/main/java/com/southern/power/grid/controller/DnerController.java @@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.validation.Valid; import java.util.List; /** @@ -36,9 +37,8 @@ public class DnerController { private IDnerSiteAreaConfigurationService dnerSiteAreaConfigurationService; @PostMapping("/area-tree/query") - public Result> queryAreaTree(@RequestBody AreaTreeReq req) { - // TODO 使用POST请求,后续新增高级筛选时,加入请求入参 - return Result.success(dnerSiteAreaConfigurationService.queryAreaTree()); + public Result> queryAreaTree(@RequestBody @Valid AreaTreeReq req) { + return Result.success(dnerSiteAreaConfigurationService.queryAreaTree(req)); } /** diff --git a/src/main/java/com/southern/power/grid/dao/DnerSiteAreaConfigurationMapper.java b/src/main/java/com/southern/power/grid/dao/DnerSiteAreaConfigurationMapper.java index e2c609d..0f89b64 100644 --- a/src/main/java/com/southern/power/grid/dao/DnerSiteAreaConfigurationMapper.java +++ b/src/main/java/com/southern/power/grid/dao/DnerSiteAreaConfigurationMapper.java @@ -1,8 +1,10 @@ package com.southern.power.grid.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.southern.power.grid.entity.AreaTreeReq; import com.southern.power.grid.entity.DnerSiteAreaConfiguration; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -15,4 +17,8 @@ import java.util.List; @Mapper public interface DnerSiteAreaConfigurationMapper extends BaseMapper { List selectAll(); + + List selectHourlyChartAreaTree(@Param("param") AreaTreeReq req); + + List selectDailyChartAreaTree(@Param("param") AreaTreeReq req); } diff --git a/src/main/java/com/southern/power/grid/entity/AreaTreeReq.java b/src/main/java/com/southern/power/grid/entity/AreaTreeReq.java index 4de8824..4a3764e 100644 --- a/src/main/java/com/southern/power/grid/entity/AreaTreeReq.java +++ b/src/main/java/com/southern/power/grid/entity/AreaTreeReq.java @@ -2,6 +2,8 @@ package com.southern.power.grid.entity; import lombok.Data; +import javax.validation.constraints.NotBlank; + /** * 区域树请求入参 * @@ -10,5 +12,112 @@ import lombok.Data; **/ @Data public class AreaTreeReq { + /** + * daily-日K图 + * hourly-分时图 + */ + @NotBlank(message = "查询类型不能为空") + String queryType; + /** + * 是否开启高级筛选 0-未开启 1-开启 + */ + String advancedFilterFlag; + + // ================= 用于高级筛选的属性 ==================== + /** + * 过去XX小时/天 + */ + Integer rainPastTime; + + /** + * 过去XX小时/天的累计降雨量超过的mm + */ + Double pastTimeRainCount; + + /** + * 过去XX小时/天 + */ + Integer avgTempPastTime; + + /** + * 过去XX小时/天的平均气温超过的℃ + */ + Double pastTimeAvgTempCount; + + /** + * 过去XX小时/天 + */ + Integer maxWindPastTime; + + /** + * 过去XX小时/天的极大风速超过的m/s + */ + Double pastTimeMaxWindCount; + + /** + * 过去XX小时/天 + */ + Integer powerOutageTimePastTime; + + /** + * 过去XX小时/天的停电时长超过的小时数 + */ + Double pastTimePowerOutageHourCount; + + /** + * 过去XX小时/天 + */ + Integer powerOutageUserPastTime; + + /** + * 过去XX小时/天的停电用户数超过的户数 + */ + Integer pastTimePowerOutageUserCount; + + /** + * 过去XX小时/天 + */ + Integer powerOutageRatioPastTime; + + /** + * 未复电用户数/总停电用户数大于等于的百分比 + */ + Double pastTimePowerOutageRatioCount; + + // ============== 其他属性 ============ + /** + * 当前时间 + */ + String currentDateTime; + + /** + * 累计降雨量开始查询时间 + */ + String rainStartDateTime; + + /** + * 平均气温开始查询时间 + */ + String avgTempStartDateTime; + + /** + * 极大风速开始查询时间 + */ + String maxWindStartDateTime; + + /** + * 停电时长开始查询时间 + */ + String powerOutageTimeStartDateTime; + + /** + * 停电用户数开始查询时间 + */ + String powerOutageUserStartDateTime; + + /** + * 未复电用户数/总停电用户数百分比 + */ + String powerOutageRatioStartDateTime; } diff --git a/src/main/java/com/southern/power/grid/enums/ChartQueryTypeEnum.java b/src/main/java/com/southern/power/grid/enums/ChartQueryTypeEnum.java new file mode 100644 index 0000000..a69dca9 --- /dev/null +++ b/src/main/java/com/southern/power/grid/enums/ChartQueryTypeEnum.java @@ -0,0 +1,28 @@ +package com.southern.power.grid.enums; + +import lombok.Getter; + +/** + * 图查询类型 + * + * @author: junzhangfm + * @date: 2026/3/17 + **/ +@Getter +public enum ChartQueryTypeEnum { + DAILY_CHART("DAILY", "日K图查询"), + + HOURLY_CHART("HOURLY", "分时图查询") + ; + + // 状态值 + private final String code; + // 状态描述 + private final String desc; + + ChartQueryTypeEnum(String code, String desc) { + this.code = code; + this.desc = desc; + } + +} diff --git a/src/main/java/com/southern/power/grid/enums/ImportTaskStatusEnum.java b/src/main/java/com/southern/power/grid/enums/ImportTaskStatusEnum.java index f9a419f..ee0d476 100644 --- a/src/main/java/com/southern/power/grid/enums/ImportTaskStatusEnum.java +++ b/src/main/java/com/southern/power/grid/enums/ImportTaskStatusEnum.java @@ -1,11 +1,14 @@ package com.southern.power.grid.enums; +import lombok.Getter; + /** * 导入任务状态枚举 * * @author: junzhangfm * @date: 2026/3/16 **/ +@Getter public enum ImportTaskStatusEnum { // 定义 5 个状态:编码 + 描述 WAITING("WAITING", "等待执行"), @@ -16,6 +19,7 @@ public enum ImportTaskStatusEnum { // 状态值(存入数据库的值) private final String code; + // 状态描述 private final String desc; @@ -24,13 +28,4 @@ public enum ImportTaskStatusEnum { this.desc = desc; } - // 获取状态值(你要的就是这个) - public String getCode() { - return code; - } - - // 获取描述 - public String getDesc() { - return desc; - } } diff --git a/src/main/java/com/southern/power/grid/exception/GlobalExceptionHandler.java b/src/main/java/com/southern/power/grid/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..e78f4d2 --- /dev/null +++ b/src/main/java/com/southern/power/grid/exception/GlobalExceptionHandler.java @@ -0,0 +1,34 @@ +package com.southern.power.grid.exception; + +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * TODO + * + * @author: junzhangfm + * @date: 2026/3/17 + **/ +@RestControllerAdvice +public class GlobalExceptionHandler { + + // 捕获参数校验异常 + @ExceptionHandler(BindException.class) + public Map handleValidException(BindException e) { + FieldError fieldError = e.getBindingResult().getFieldError(); + String msg = "参数校验失败,请核对入参"; + if (!Objects.isNull(fieldError)) { + msg = fieldError.getField() + ":" + fieldError.getDefaultMessage(); + } + Map map = new HashMap<>(); + map.put("code", 400); + map.put("msg", msg); + return map; + } +} diff --git a/src/main/java/com/southern/power/grid/service/IDnerSiteAreaConfigurationService.java b/src/main/java/com/southern/power/grid/service/IDnerSiteAreaConfigurationService.java index 36006e1..99ebdbd 100644 --- a/src/main/java/com/southern/power/grid/service/IDnerSiteAreaConfigurationService.java +++ b/src/main/java/com/southern/power/grid/service/IDnerSiteAreaConfigurationService.java @@ -1,7 +1,7 @@ package com.southern.power.grid.service; -import com.alibaba.fastjson2.JSONArray; import com.baomidou.mybatisplus.extension.service.IService; +import com.southern.power.grid.entity.AreaTreeReq; import com.southern.power.grid.entity.AreaTreeVO; import com.southern.power.grid.entity.DnerSiteAreaConfiguration; @@ -19,5 +19,5 @@ public interface IDnerSiteAreaConfigurationService extends IService queryAreaTree(); + List queryAreaTree(AreaTreeReq req); } diff --git a/src/main/java/com/southern/power/grid/service/impl/DnerSiteAreaConfigurationServiceImpl.java b/src/main/java/com/southern/power/grid/service/impl/DnerSiteAreaConfigurationServiceImpl.java index 11bda1f..8307b90 100644 --- a/src/main/java/com/southern/power/grid/service/impl/DnerSiteAreaConfigurationServiceImpl.java +++ b/src/main/java/com/southern/power/grid/service/impl/DnerSiteAreaConfigurationServiceImpl.java @@ -2,12 +2,18 @@ package com.southern.power.grid.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.southern.power.grid.dao.DnerSiteAreaConfigurationMapper; +import com.southern.power.grid.entity.AreaTreeReq; import com.southern.power.grid.entity.AreaTreeVO; import com.southern.power.grid.entity.DnerSiteAreaConfiguration; +import com.southern.power.grid.enums.ChartQueryTypeEnum; import com.southern.power.grid.service.IDnerSiteAreaConfigurationService; +import com.southern.power.grid.utils.TimeUtil; import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; /** @@ -20,10 +26,44 @@ import java.util.*; public class DnerSiteAreaConfigurationServiceImpl extends ServiceImpl implements IDnerSiteAreaConfigurationService { + @Autowired + private DnerSiteAreaConfigurationMapper dnerSiteAreaConfigurationMapper; + @Override - public List queryAreaTree() { + public List queryAreaTree(AreaTreeReq req) { + // 判断是否开启高级筛选 + String advancedFilterFlag ="0"; + if ((!Objects.isNull(req.getRainPastTime()) && req.getRainPastTime() != 0) + || (!Objects.isNull(req.getAvgTempPastTime()) && req.getAvgTempPastTime() != 0) + || (!Objects.isNull(req.getMaxWindPastTime()) && req.getMaxWindPastTime() != 0) + || (!Objects.isNull(req.getPowerOutageTimePastTime()) && req.getPowerOutageTimePastTime() != 0) + || (!Objects.isNull(req.getPowerOutageUserPastTime()) && req.getPowerOutageUserPastTime() != 0) + || (!Objects.isNull(req.getPowerOutageRatioPastTime()) && req.getPowerOutageRatioPastTime() != 0)) { + advancedFilterFlag = "1"; // 开启高级筛选 + } + req.setAdvancedFilterFlag(advancedFilterFlag); // 查询出所有的省市区 - List dataList = list(); + List dataList; + if (ChartQueryTypeEnum.HOURLY_CHART.getCode().equals(req.getQueryType())) { + // 分时图 + if ("1".equals(advancedFilterFlag)) { + String currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00")); + req.setCurrentDateTime(currentDateTime); + if (!Objects.isNull(req.getRainPastTime()) && req.getRainPastTime() != 0) { + req.setRainStartDateTime(TimeUtil.getBeforeHourTime(currentDateTime, req.getRainPastTime())); + } + if (!Objects.isNull(req.getAvgTempPastTime()) && req.getAvgTempPastTime() != 0) { + req.setAvgTempStartDateTime(TimeUtil.getBeforeHourTime(currentDateTime, req.getAvgTempPastTime())); + } + } + dataList = dnerSiteAreaConfigurationMapper.selectHourlyChartAreaTree(req); + } else { + // 日K图 + if ("1".equals(advancedFilterFlag)) { + req.setCurrentDateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + } + dataList = dnerSiteAreaConfigurationMapper.selectDailyChartAreaTree(req); + } // 最终树 List result = new ArrayList<>(); // 1. 构建所有省份节点 diff --git a/src/main/java/com/southern/power/grid/utils/TimeUtil.java b/src/main/java/com/southern/power/grid/utils/TimeUtil.java index d3a81ab..d5cc15d 100644 --- a/src/main/java/com/southern/power/grid/utils/TimeUtil.java +++ b/src/main/java/com/southern/power/grid/utils/TimeUtil.java @@ -22,10 +22,11 @@ public class TimeUtil { /** * 获取开始时间到结束时间的小时数组,仅当天的第一条数据会展示年月日 + * 比如[2026-03-13 22:00, 23:00, 2026-03-14 00:00, 01:00] * * @param startTime 开始时间 * @param endTime 结束时间 - * @return + * @return 结果 */ public static List generateHourList(String startTime, String endTime) { LocalDateTime start = LocalDateTime.parse(startTime, FULL); @@ -54,11 +55,11 @@ public class TimeUtil { } /** - * 获取开始时间到结束时间的小时数组 + * 获取开始时间到结束时间的小时数组,比如[2026-03-13 23:00, 2026-03-14 00:00, 2026-03-14 01:00] * * @param startTime 开始时间 * @param endTime 结束时间 - * @return + * @return 结果 */ public static List generateHourListAll(String startTime, String endTime) { LocalDateTime start = LocalDateTime.parse(startTime, FULL); @@ -117,11 +118,46 @@ public class TimeUtil { return beforeDay.format(formatter); } + /** + * 获取当前时间,精确到小时,比如2026-03-17 11:00 + * + * @return 字符串结果 + */ + public static String getCurrentHourTime() { + return LocalDateTime.now() // 获取当前时间 + .withMinute(0) // 分钟设置为0 + .withSecond(0) // 秒设置为0 + .withNano(0) // 毫秒设置为0 + .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00")); // 转换为字符串 + } + + /** + * 获取前n个小时的时间 + * + * @param hourTime 指定时间,比如2026-03-17 11:00 + * @param beforeHourNum 前n小时,比如2 + * @return 前n小时的时间,比如2026-03-17 09:00 + */ + public static String getBeforeHourTime(String hourTime, int beforeHourNum) { + // 定义格式 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"); + + // 1. 把字符串转成 LocalDateTime + LocalDateTime dateTime = LocalDateTime.parse(hourTime, formatter); + + // 2. 减去 n 小时(核心方法) + LocalDateTime beforeHour = dateTime.minusHours(beforeHourNum); + + // 3. 格式化返回(精确到小时,分钟固定 00) + return beforeHour.format(formatter); + } + public static void main(String[] args) { -// List strings = generateHourListAll("2026-03-13 22:00", "2026-03-14 02:00"); +// List strings = generateHourList("2026-03-13 22:00", "2026-03-14 01:00"); // List strings = getBetweenDates("2026-03-10", "2026-03-14"); // String strings = getBeforeNumDays("2026-03-15", 5); - System.out.println(14/5); + String beforeHourTime = getBeforeHourTime("2026-03-17 11:00", 2); + System.out.println(beforeHourTime); } private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); diff --git a/src/main/resources/mapper/DnerSiteAreaConfigurationMapper.xml b/src/main/resources/mapper/DnerSiteAreaConfigurationMapper.xml index a40b601..205a732 100644 --- a/src/main/resources/mapper/DnerSiteAreaConfigurationMapper.xml +++ b/src/main/resources/mapper/DnerSiteAreaConfigurationMapper.xml @@ -25,4 +25,37 @@ create_by, create_time, update_by, update_time FROM dner_site_area_configuration + + + + \ No newline at end of file