diff --git a/klp-admin/src/main/resources/application.yml b/klp-admin/src/main/resources/application.yml index 76265db7..3c1f9bb9 100644 --- a/klp-admin/src/main/resources/application.yml +++ b/klp-admin/src/main/resources/application.yml @@ -160,6 +160,10 @@ security: - /klp/generateRecord - /klp/generateRecord/** + # 测接口 +# - /ems/energyConsumption +# - /ems/energyConsumption/** + # MyBatisPlus配置 # https://baomidou.com/config/ diff --git a/klp-ems/src/main/java/com/klp/ems/controller/EmsEnergyConsumptionController.java b/klp-ems/src/main/java/com/klp/ems/controller/EmsEnergyConsumptionController.java index 739fd0fc..4d75a934 100644 --- a/klp-ems/src/main/java/com/klp/ems/controller/EmsEnergyConsumptionController.java +++ b/klp-ems/src/main/java/com/klp/ems/controller/EmsEnergyConsumptionController.java @@ -4,9 +4,7 @@ import java.util.List; import java.util.Arrays; import com.klp.ems.domain.bo.EmsEnergyConsumptionQueryBo; -import com.klp.ems.domain.vo.EnergyChainRatioVo; -import com.klp.ems.domain.vo.SummaryDailyVo; -import com.klp.ems.domain.vo.SummaryMonthlyVo; +import com.klp.ems.domain.vo.*; import lombok.RequiredArgsConstructor; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.*; @@ -23,7 +21,6 @@ import com.klp.common.core.validate.AddGroup; import com.klp.common.core.validate.EditGroup; import com.klp.common.enums.BusinessType; import com.klp.common.utils.poi.ExcelUtil; -import com.klp.ems.domain.vo.EmsEnergyConsumptionVo; import com.klp.ems.domain.bo.EmsEnergyConsumptionBo; import com.klp.ems.service.IEmsEnergyConsumptionService; import com.klp.common.core.page.TableDataInfo; @@ -48,10 +45,10 @@ public class EmsEnergyConsumptionController extends BaseController { @GetMapping("/getEnergySummary") public R getEnergySummary(EmsEnergyConsumptionQueryBo queryBo){ if (StringUtils.hasText(queryBo.getMonth())) { - List data = iEmsEnergyConsumptionService.getEnergySummaryDaily(queryBo.getMonth()); + List data = iEmsEnergyConsumptionService.getEnergySummaryDailyFiltered(queryBo); return R.ok(data); }else if (StringUtils.hasText(queryBo.getYear())) { - List data = iEmsEnergyConsumptionService.getEnergySummaryMonthly(queryBo.getYear()); + List data = iEmsEnergyConsumptionService.getEnergySummaryMonthlyFiltered(queryBo); return R.ok(data); } else { return R.fail("year 或 month 必须提供一个"); @@ -62,11 +59,27 @@ public class EmsEnergyConsumptionController extends BaseController { * 获取能耗环比概况(没写完) */ @GetMapping("/getEnergyChainRatio") - public R getEnergyChainRatio() { - EnergyChainRatioVo energyChainRatioVo = iEmsEnergyConsumptionService.getEnergyChainRatio(); + public R getEnergyChainRatio(EmsEnergyConsumptionQueryBo queryBo) { + EnergyChainRatioVo energyChainRatioVo = iEmsEnergyConsumptionService.getEnergyChainRatioFiltered(queryBo); return R.ok(energyChainRatioVo); } + /** + * 同比分析:year 必填 + */ + @GetMapping("/getYearOnYear") + public R getYearOnYear(EmsEnergyConsumptionQueryBo queryBo) { + return R.ok(iEmsEnergyConsumptionService.getYearOnYear(queryBo)); + } + + /** + * 环比分析:periodType=day/week/month/year 与 dateKey + */ + @GetMapping("/getChainAnalysis") + public R getChainAnalysis(EmsEnergyConsumptionQueryBo queryBo) { + return R.ok(iEmsEnergyConsumptionService.getChainAnalysis(queryBo)); + } + /** * 查询能耗记录列表 */ diff --git a/klp-ems/src/main/java/com/klp/ems/domain/bo/EmsEnergyConsumptionQueryBo.java b/klp-ems/src/main/java/com/klp/ems/domain/bo/EmsEnergyConsumptionQueryBo.java index fce4c7fa..b4b2dd3f 100644 --- a/klp-ems/src/main/java/com/klp/ems/domain/bo/EmsEnergyConsumptionQueryBo.java +++ b/klp-ems/src/main/java/com/klp/ems/domain/bo/EmsEnergyConsumptionQueryBo.java @@ -13,4 +13,18 @@ public class EmsEnergyConsumptionQueryBo { * 月份,用于按天汇总(格式:yyyy-MM) */ private String month; + + /** 能源类型ID(可选) */ + private Long energyTypeId; + /** 计量设备ID(可选) */ + private Long meterId; + /** 区域ID(可选,含子区域) */ + private Long locationId; + + /** 周期类型:day/week/month/year(用于环比分析) */ + private String periodType; + /** 日期关键字: + * day=yyyy-MM-dd;week=年内周数(1-53);month=本年月份(1-12);year=yyyy + */ + private String dateKey; } diff --git a/klp-ems/src/main/java/com/klp/ems/domain/bo/MeterFilterBo.java b/klp-ems/src/main/java/com/klp/ems/domain/bo/MeterFilterBo.java new file mode 100644 index 00000000..63bd7c96 --- /dev/null +++ b/klp-ems/src/main/java/com/klp/ems/domain/bo/MeterFilterBo.java @@ -0,0 +1,13 @@ +package com.klp.ems.domain.bo; + +import lombok.Data; +import java.util.List; + +@Data +public class MeterFilterBo { + private Long energyTypeId; + private List locationIds; + private Long meterId; +} + + diff --git a/klp-ems/src/main/java/com/klp/ems/domain/bo/TimeRangeWithMetersBo.java b/klp-ems/src/main/java/com/klp/ems/domain/bo/TimeRangeWithMetersBo.java new file mode 100644 index 00000000..0220a963 --- /dev/null +++ b/klp-ems/src/main/java/com/klp/ems/domain/bo/TimeRangeWithMetersBo.java @@ -0,0 +1,13 @@ +package com.klp.ems.domain.bo; + +import lombok.Data; +import java.util.List; + +@Data +public class TimeRangeWithMetersBo { + private String start; + private String end; + private List meterIds; +} + + diff --git a/klp-ems/src/main/java/com/klp/ems/domain/vo/ChainAnalysisVo.java b/klp-ems/src/main/java/com/klp/ems/domain/vo/ChainAnalysisVo.java new file mode 100644 index 00000000..01c462c9 --- /dev/null +++ b/klp-ems/src/main/java/com/klp/ems/domain/vo/ChainAnalysisVo.java @@ -0,0 +1,23 @@ +package com.klp.ems.domain.vo; + +import lombok.Data; +import java.util.List; + +/** + * 环比分析返回:指定周期(天/周/月/年)本期与上期的序列 + */ +@Data +public class ChainAnalysisVo { + /** 周期类型:day/week/month/year */ + private String periodType; + /** 本期标签(例如当前月的每一天、当前年的每个月等) */ + private List currentLabels; + /** 上期标签 */ + private List previousLabels; + /** 本期数值 */ + private List currentValues; + /** 上期数值 */ + private List previousValues; +} + + diff --git a/klp-ems/src/main/java/com/klp/ems/domain/vo/EnergyChainRatioVo.java b/klp-ems/src/main/java/com/klp/ems/domain/vo/EnergyChainRatioVo.java index 5f1c321d..acf12836 100644 --- a/klp-ems/src/main/java/com/klp/ems/domain/vo/EnergyChainRatioVo.java +++ b/klp-ems/src/main/java/com/klp/ems/domain/vo/EnergyChainRatioVo.java @@ -1,16 +1,29 @@ package com.klp.ems.domain.vo; +import lombok.Data; + /** * 环比概况 */ +@Data public class EnergyChainRatioVo { - private Double todayUsage; // 今日用能 - private Double yesterdayUsage; // 昨日同期 - private Double thisMonthUsage; // 当月累计 - private Double lastMonthUsage; // 上月同期 - private Double lastYearUsage; // 去年同期 + /** 今日用能 */ + private Double todayUsage; + /** 昨日同期用能(昨日同一时间段累计) */ + private Double yesterdayUsage; + /** 当月用能(到当前时刻累计) */ + private Double thisMonthUsage; + /** 上月同期用能(上月到同一日同一时刻累计) */ + private Double lastMonthUsage; + /** 当前年用能(到当前时刻累计) */ + private Double currentYearUsage; + /** 去年同期用能(去年到同一日同一时刻累计) */ + private Double lastYearUsage; - private Double dailyChainRate; // 日环比 (%) - private Double monthlyChainRate; // 月环比 (%) - private Double yearOnYearRate; // 年同比 (%) + /** 日环比 (%) = (今日 - 昨日同期) / 昨日同期 * 100 */ + private Double dailyChainRate; + /** 月环比 (%) = (当月 - 上月同期) / 上月同期 * 100 */ + private Double monthlyChainRate; + /** 年同比 (%) = (当前年 - 去年同期) / 去年同期 * 100 */ + private Double yearOnYearRate; } diff --git a/klp-ems/src/main/java/com/klp/ems/domain/vo/YearOnYearVo.java b/klp-ems/src/main/java/com/klp/ems/domain/vo/YearOnYearVo.java new file mode 100644 index 00000000..fe7ed0c5 --- /dev/null +++ b/klp-ems/src/main/java/com/klp/ems/domain/vo/YearOnYearVo.java @@ -0,0 +1,21 @@ +package com.klp.ems.domain.vo; + +import lombok.Data; +import java.util.List; + +/** + * 同比分析返回 + */ +@Data +public class YearOnYearVo { + /** 年份,例如 2025 */ + private String year; + /** 上一年,例如 2024 */ + private String lastYear; + /** 当年每月总用能,长度最多12 */ + private List currentYearMonthly; + /** 上一年每月总用能,长度最多12 */ + private List lastYearMonthly; +} + + diff --git a/klp-ems/src/main/java/com/klp/ems/mapper/EmsEnergyConsumptionMapper.java b/klp-ems/src/main/java/com/klp/ems/mapper/EmsEnergyConsumptionMapper.java index ebcee756..949be339 100644 --- a/klp-ems/src/main/java/com/klp/ems/mapper/EmsEnergyConsumptionMapper.java +++ b/klp-ems/src/main/java/com/klp/ems/mapper/EmsEnergyConsumptionMapper.java @@ -1,6 +1,7 @@ package com.klp.ems.mapper; import com.klp.ems.domain.EmsEnergyConsumption; +import com.klp.ems.domain.bo.TimeRangeWithMetersBo; import com.klp.ems.domain.vo.EmsEnergyConsumptionVo; import com.klp.common.core.mapper.BaseMapperPlus; import com.klp.ems.domain.vo.SummaryDailyVo; @@ -20,4 +21,18 @@ public interface EmsEnergyConsumptionMapper extends BaseMapperPlus selectDailySummary(@Param("startDate") String startDate, @Param("endDate") String endDate); List selectMonthlySummary(@Param("year") String year); + + /** + * 统计某个时间区间的用能合计 + */ + Double sumConsumptionBetween(String startTime, String endTime); + + /** + * 统计某个时间区间、指定设备集合的用能合计 + */ + Double sumConsumptionBetweenWithMeters(TimeRangeWithMetersBo range); + + List selectDailySummaryWithMeters(TimeRangeWithMetersBo range); + + List selectMonthlySummaryWithMeters(TimeRangeWithMetersBo range); } diff --git a/klp-ems/src/main/java/com/klp/ems/mapper/EmsMeterMapper.java b/klp-ems/src/main/java/com/klp/ems/mapper/EmsMeterMapper.java index 635baea9..7ba24e12 100644 --- a/klp-ems/src/main/java/com/klp/ems/mapper/EmsMeterMapper.java +++ b/klp-ems/src/main/java/com/klp/ems/mapper/EmsMeterMapper.java @@ -3,6 +3,9 @@ package com.klp.ems.mapper; import com.klp.ems.domain.EmsMeter; import com.klp.ems.domain.vo.EmsMeterVo; import com.klp.common.core.mapper.BaseMapperPlus; +import com.klp.ems.domain.bo.MeterFilterBo; + +import java.util.List; /** * 计量设备(阈值移至此处)Mapper接口 @@ -12,4 +15,8 @@ import com.klp.common.core.mapper.BaseMapperPlus; */ public interface EmsMeterMapper extends BaseMapperPlus { + /** + * 根据可选条件筛选计量设备ID列表 + */ + java.util.List selectMeterIds(MeterFilterBo filter); } diff --git a/klp-ems/src/main/java/com/klp/ems/service/IEmsEnergyConsumptionService.java b/klp-ems/src/main/java/com/klp/ems/service/IEmsEnergyConsumptionService.java index 84f318cc..19376263 100644 --- a/klp-ems/src/main/java/com/klp/ems/service/IEmsEnergyConsumptionService.java +++ b/klp-ems/src/main/java/com/klp/ems/service/IEmsEnergyConsumptionService.java @@ -2,11 +2,14 @@ package com.klp.ems.service; import com.klp.ems.domain.vo.EmsEnergyConsumptionVo; import com.klp.ems.domain.bo.EmsEnergyConsumptionBo; +import com.klp.ems.domain.bo.EmsEnergyConsumptionQueryBo; import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.domain.PageQuery; import com.klp.ems.domain.vo.EnergyChainRatioVo; import com.klp.ems.domain.vo.SummaryDailyVo; import com.klp.ems.domain.vo.SummaryMonthlyVo; +import com.klp.ems.domain.vo.YearOnYearVo; +import com.klp.ems.domain.vo.ChainAnalysisVo; import java.util.Collection; import java.util.List; @@ -49,9 +52,25 @@ public interface IEmsEnergyConsumptionService { */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); - EnergyChainRatioVo getEnergyChainRatio(); - List getEnergySummaryDaily(String month); List getEnergySummaryMonthly(String year); + + /** + * 过滤版:按能耗类型/设备/区域(含子区域)聚合 + */ + EnergyChainRatioVo getEnergyChainRatioFiltered(EmsEnergyConsumptionQueryBo queryBo); + + /** + * 近期能耗趋势(过滤版):month 按天、year 按月 + */ + List getEnergySummaryDailyFiltered(EmsEnergyConsumptionQueryBo queryBo); + + List getEnergySummaryMonthlyFiltered(EmsEnergyConsumptionQueryBo queryBo); + + /** 同比分析:传入 year,返回当年与上一年逐月汇总(可过滤) */ + YearOnYearVo getYearOnYear(EmsEnergyConsumptionQueryBo queryBo); + + /** 环比分析:periodType=day/week/month/year + dateKey;可过滤 */ + ChainAnalysisVo getChainAnalysis(EmsEnergyConsumptionQueryBo queryBo); } diff --git a/klp-ems/src/main/java/com/klp/ems/service/impl/EmsEnergyConsumptionServiceImpl.java b/klp-ems/src/main/java/com/klp/ems/service/impl/EmsEnergyConsumptionServiceImpl.java index b01fe52c..30bdf176 100644 --- a/klp-ems/src/main/java/com/klp/ems/service/impl/EmsEnergyConsumptionServiceImpl.java +++ b/klp-ems/src/main/java/com/klp/ems/service/impl/EmsEnergyConsumptionServiceImpl.java @@ -6,24 +6,30 @@ import com.klp.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.klp.ems.domain.EmsLocation; import com.klp.ems.domain.bo.EmsEnergyConsumptionQueryBo; +import com.klp.ems.domain.bo.MeterFilterBo; +import com.klp.ems.domain.bo.TimeRangeWithMetersBo; import com.klp.ems.domain.vo.EnergyChainRatioVo; import com.klp.ems.domain.vo.SummaryDailyVo; import com.klp.ems.domain.vo.SummaryMonthlyVo; +import com.klp.ems.domain.vo.YearOnYearVo; +import com.klp.ems.domain.vo.ChainAnalysisVo; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import com.klp.ems.domain.bo.EmsEnergyConsumptionBo; import com.klp.ems.domain.vo.EmsEnergyConsumptionVo; import com.klp.ems.domain.EmsEnergyConsumption; import com.klp.ems.mapper.EmsEnergyConsumptionMapper; +import com.klp.ems.mapper.EmsMeterMapper; +import com.klp.ems.mapper.EmsLocationMapper; import com.klp.ems.service.IEmsEnergyConsumptionService; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.Map; -import java.util.Collection; +import java.time.temporal.WeekFields; +import java.util.*; /** * 能耗记录Service业务层处理 @@ -36,6 +42,8 @@ import java.util.Collection; public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionService { private final EmsEnergyConsumptionMapper baseMapper; + private final EmsMeterMapper meterMapper; + private final EmsLocationMapper locationMapper; /** * 查询能耗记录 @@ -119,16 +127,127 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer return baseMapper.deleteBatchIds(ids) > 0; } + private Double nz(Double v) { + return v == null ? 0D : v; + } + + private Double calcRate(Double current, Double base) { + if (base == null || base == 0D) { + return null; + } + return (current - base) / base * 100D; + } + @Override - public EnergyChainRatioVo getEnergyChainRatio() { - EnergyChainRatioVo energyChainRatioVo = new EnergyChainRatioVo(); + public EnergyChainRatioVo getEnergyChainRatioFiltered(EmsEnergyConsumptionQueryBo queryBo) { + // 解析区域(含子区域)-> 设备ID集合 + // 优先 meterId,其次 energyTypeId/locationIds + List meterIds; + if (queryBo.getMeterId() != null) { + meterIds = Collections.singletonList(queryBo.getMeterId()); + } else { + List locationIds = null; + if (queryBo.getLocationId() != null) { + locationIds = collectSubLocationIds(queryBo.getLocationId()); + } + MeterFilterBo filter = new MeterFilterBo(); + filter.setEnergyTypeId(queryBo.getEnergyTypeId()); + filter.setLocationIds(locationIds); + filter.setMeterId(null); + meterIds = meterMapper.selectMeterIds(filter); + } + if (meterIds == null || meterIds.isEmpty()) { + // 没有设备则全为0 + EnergyChainRatioVo vo = new EnergyChainRatioVo(); + vo.setTodayUsage(0D); + vo.setYesterdayUsage(0D); + vo.setThisMonthUsage(0D); + vo.setLastMonthUsage(0D); + vo.setCurrentYearUsage(0D); + vo.setLastYearUsage(0D); + vo.setDailyChainRate(null); + vo.setMonthlyChainRate(null); + vo.setYearOnYearRate(null); + return vo; + } + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfNow = now; + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + LocalDateTime endOfYesterdaySameTime = startOfYesterday.plusHours(now.getHour()).plusMinutes(now.getMinute()).plusSeconds(now.getSecond()); + LocalDateTime startOfThisMonth = now.withDayOfMonth(1).toLocalDate().atStartOfDay(); + LocalDateTime endOfThisMonthSameTime = startOfThisMonth.plusDays(now.getDayOfMonth() - 1) + .plusHours(now.getHour()).plusMinutes(now.getMinute()).plusSeconds(now.getSecond()); + LocalDateTime startOfLastMonth = startOfThisMonth.minusMonths(1); + LocalDateTime endOfLastMonthSameTime = startOfLastMonth.plusDays(now.getDayOfMonth() - 1) + .plusHours(now.getHour()).plusMinutes(now.getMinute()).plusSeconds(now.getSecond()); + LocalDateTime startOfThisYear = now.withDayOfYear(1).toLocalDate().atStartOfDay(); + LocalDateTime endOfThisYearSameTime = startOfThisYear.plusDays(now.getDayOfYear() - 1) + .plusHours(now.getHour()).plusMinutes(now.getMinute()).plusSeconds(now.getSecond()); + LocalDateTime startOfLastYear = startOfThisYear.minusYears(1); + LocalDateTime endOfLastYearSameTime = startOfLastYear.plusDays(now.getDayOfYear() - 1) + .plusHours(now.getHour()).plusMinutes(now.getMinute()).plusSeconds(now.getSecond()); + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + TimeRangeWithMetersBo range = new TimeRangeWithMetersBo(); + range.setMeterIds(meterIds); + range.setStart(fmt.format(startOfToday)); + range.setEnd(fmt.format(endOfNow)); + Double today = baseMapper.sumConsumptionBetweenWithMeters(range); + range.setStart(fmt.format(startOfYesterday)); + range.setEnd(fmt.format(endOfYesterdaySameTime)); + Double yesterday = baseMapper.sumConsumptionBetweenWithMeters(range); + range.setStart(fmt.format(startOfThisMonth)); + range.setEnd(fmt.format(endOfThisMonthSameTime)); + Double thisMonth = baseMapper.sumConsumptionBetweenWithMeters(range); + range.setStart(fmt.format(startOfLastMonth)); + range.setEnd(fmt.format(endOfLastMonthSameTime)); + Double lastMonth = baseMapper.sumConsumptionBetweenWithMeters(range); + range.setStart(fmt.format(startOfThisYear)); + range.setEnd(fmt.format(endOfThisYearSameTime)); + Double currentYear = baseMapper.sumConsumptionBetweenWithMeters(range); + range.setStart(fmt.format(startOfLastYear)); + range.setEnd(fmt.format(endOfLastYearSameTime)); + Double lastYear = baseMapper.sumConsumptionBetweenWithMeters(range); + EnergyChainRatioVo vo = new EnergyChainRatioVo(); + vo.setTodayUsage(nz(today)); + vo.setYesterdayUsage(nz(yesterday)); + vo.setThisMonthUsage(nz(thisMonth)); + vo.setLastMonthUsage(nz(lastMonth)); + vo.setCurrentYearUsage(nz(currentYear)); + vo.setLastYearUsage(nz(lastYear)); + vo.setDailyChainRate(calcRate(vo.getTodayUsage(), vo.getYesterdayUsage())); + vo.setMonthlyChainRate(calcRate(vo.getThisMonthUsage(), vo.getLastMonthUsage())); + vo.setYearOnYearRate(calcRate(vo.getCurrentYearUsage(), vo.getLastYearUsage())); + return vo; + } - - - return null; + private List collectSubLocationIds(Long rootId) { + // 简易递归:使用 MP 查询所有,再在内存递归(数据量大时建议写 SQL/CTE) + List all = locationMapper.selectList(null); + Map> tree = new HashMap<>(); + for (EmsLocation loc : all) { + Long pid = loc.getParentId(); + if (pid == null) pid = 0L; + tree.computeIfAbsent(pid, k -> new ArrayList<>()).add(loc.getLocationId()); + } + List result = new ArrayList<>(); + Deque stack = new ArrayDeque<>(); + stack.push(rootId); + result.add(rootId); + while (!stack.isEmpty()) { + Long id = stack.pop(); + List children = tree.get(id); + if (children != null) { + for (Long c : children) { + result.add(c); + stack.push(c); + } + } + } + return result; } @Override @@ -144,4 +263,196 @@ public class EmsEnergyConsumptionServiceImpl implements IEmsEnergyConsumptionSer public List getEnergySummaryMonthly(String year) { return baseMapper.selectMonthlySummary(year); } + + @Override + public List getEnergySummaryDailyFiltered(EmsEnergyConsumptionQueryBo queryBo) { + String month = queryBo.getMonth(); + LocalDate startDate = LocalDate.parse(month + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth()); + List meterIds = resolveMeters(queryBo.getEnergyTypeId(), queryBo.getMeterId(), queryBo.getLocationId()); + TimeRangeWithMetersBo range = new TimeRangeWithMetersBo(); + range.setStart(month + "-01"); + range.setEnd(endDate.toString()); + range.setMeterIds(meterIds); + return baseMapper.selectDailySummaryWithMeters(range); + } + + @Override + public List getEnergySummaryMonthlyFiltered(EmsEnergyConsumptionQueryBo queryBo) { + List meterIds = resolveMeters(queryBo.getEnergyTypeId(), queryBo.getMeterId(), queryBo.getLocationId()); + TimeRangeWithMetersBo range = new TimeRangeWithMetersBo(); + range.setStart(queryBo.getYear()); + range.setEnd(null); + range.setMeterIds(meterIds); + return baseMapper.selectMonthlySummaryWithMeters(range); + } + + @Override + public YearOnYearVo getYearOnYear(EmsEnergyConsumptionQueryBo queryBo) { + String year = queryBo.getYear(); + List meterIds = resolveMeters(queryBo.getEnergyTypeId(), queryBo.getMeterId(), queryBo.getLocationId()); + // 构造当年和上一年月份列表 + List current = new ArrayList<>(); + List previous = new ArrayList<>(); + for (int m = 1; m <= 12; m++) { + String ym = String.format("%s-%02d", year, m); + // 汇总该月 + LocalDate first = LocalDate.parse(ym + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDate last = first.withDayOfMonth(first.lengthOfMonth()); + TimeRangeWithMetersBo r1 = new TimeRangeWithMetersBo(); + r1.setMeterIds(meterIds); + r1.setStart(first.toString() + " 00:00:00"); r1.setEnd(last.toString() + " 23:59:59"); + Double sumThis = baseMapper.sumConsumptionBetweenWithMeters(r1); + current.add(nz(sumThis)); + + String lastYear = String.valueOf(Integer.parseInt(year) - 1); + String ymPrev = String.format("%s-%02d", lastYear, m); + LocalDate firstPrev = LocalDate.parse(ymPrev + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDate lastPrev = firstPrev.withDayOfMonth(firstPrev.lengthOfMonth()); + TimeRangeWithMetersBo r0 = new TimeRangeWithMetersBo(); + r0.setMeterIds(meterIds); + r0.setStart(firstPrev.toString() + " 00:00:00"); r0.setEnd(lastPrev.toString() + " 23:59:59"); + Double sumPrev = baseMapper.sumConsumptionBetweenWithMeters(r0); + previous.add(nz(sumPrev)); + } + YearOnYearVo vo = new YearOnYearVo(); + vo.setYear(year); + vo.setLastYear(String.valueOf(Integer.parseInt(year) - 1)); + vo.setCurrentYearMonthly(current); + vo.setLastYearMonthly(previous); + return vo; + } + + @Override + public ChainAnalysisVo getChainAnalysis(EmsEnergyConsumptionQueryBo queryBo) { + List meterIds = resolveMeters(queryBo.getEnergyTypeId(), queryBo.getMeterId(), queryBo.getLocationId()); + ChainAnalysisVo vo = new ChainAnalysisVo(); + vo.setPeriodType(queryBo.getPeriodType()); + DateTimeFormatter dt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + switch (queryBo.getPeriodType()) { + case "day": { + // dateKey = yyyy-MM-dd,按小时 + LocalDate day = LocalDate.parse(queryBo.getDateKey(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDate prevDay = day.minusDays(1); + List labels = new ArrayList<>(); + List curVals = new ArrayList<>(); + List prevVals = new ArrayList<>(); + for (int h = 0; h < 24; h++) { + labels.add(String.format("%02d:00", h)); + String s1 = day + String.format(" %02d:00:00", h); + String e1 = day + String.format(" %02d:59:59", h); + String s0 = prevDay + String.format(" %02d:00:00", h); + String e0 = prevDay + String.format(" %02d:59:59", h); + TimeRangeWithMetersBo r = new TimeRangeWithMetersBo(); + r.setMeterIds(meterIds); + r.setStart(s1); r.setEnd(e1); + curVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + r.setStart(s0); r.setEnd(e0); + prevVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + } + vo.setCurrentLabels(labels); + vo.setPreviousLabels(labels); + vo.setCurrentValues(curVals); + vo.setPreviousValues(prevVals); + break; + } + case "week": { + // dateKey = 年内周数(1-53),按天 + int year = LocalDate.now().getYear(); + int week = Integer.parseInt(queryBo.getDateKey()); + WeekFields wf = WeekFields.ISO; + LocalDate firstDayOfWeek = LocalDate.of(year, 1, 4).with(wf.weekOfWeekBasedYear(), week).with(wf.dayOfWeek(), 1); + LocalDate prevWeekFirst = firstDayOfWeek.minusWeeks(1); + List labels = new ArrayList<>(); + List curVals = new ArrayList<>(); + List prevVals = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + LocalDate d1 = firstDayOfWeek.plusDays(i); + LocalDate d0 = prevWeekFirst.plusDays(i); + labels.add(d1.getDayOfWeek().name()); + TimeRangeWithMetersBo r = new TimeRangeWithMetersBo(); + r.setMeterIds(meterIds); + r.setStart(d1.toString() + " 00:00:00"); r.setEnd(d1.toString() + " 23:59:59"); + curVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + r.setStart(d0.toString() + " 00:00:00"); r.setEnd(d0.toString() + " 23:59:59"); + prevVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + } + vo.setCurrentLabels(labels); + vo.setPreviousLabels(labels); + vo.setCurrentValues(curVals); + vo.setPreviousValues(prevVals); + break; + } + case "month": { + // dateKey = 月份(1-12),按天 + int year = LocalDate.now().getYear(); + int m = Integer.parseInt(queryBo.getDateKey()); + LocalDate first = LocalDate.of(year, m, 1); + LocalDate prevFirst = first.minusMonths(1); + int days = first.lengthOfMonth(); + List labels = new ArrayList<>(); + List curVals = new ArrayList<>(); + List prevVals = new ArrayList<>(); + for (int i = 1; i <= days; i++) { + LocalDate d1 = first.withDayOfMonth(i); + LocalDate d0 = prevFirst.withDayOfMonth(Math.min(i, prevFirst.lengthOfMonth())); + labels.add(String.valueOf(i)); + TimeRangeWithMetersBo r = new TimeRangeWithMetersBo(); + r.setMeterIds(meterIds); + r.setStart(d1.toString() + " 00:00:00"); r.setEnd(d1.toString() + " 23:59:59"); + curVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + r.setStart(d0.toString() + " 00:00:00"); r.setEnd(d0.toString() + " 23:59:59"); + prevVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + } + vo.setCurrentLabels(labels); + vo.setPreviousLabels(labels); + vo.setCurrentValues(curVals); + vo.setPreviousValues(prevVals); + break; + } + case "year": { + // dateKey = 年份(yyyy),按月 + int year = Integer.parseInt(queryBo.getDateKey()); + List labels = new ArrayList<>(); + List curVals = new ArrayList<>(); + List prevVals = new ArrayList<>(); + for (int m = 1; m <= 12; m++) { + LocalDate first = LocalDate.of(year, m, 1); + LocalDate last = first.withDayOfMonth(first.lengthOfMonth()); + LocalDate firstPrev = first.minusYears(1); + LocalDate lastPrev = firstPrev.withDayOfMonth(firstPrev.lengthOfMonth()); + labels.add(String.format("%02d", m)); + TimeRangeWithMetersBo r = new TimeRangeWithMetersBo(); + r.setMeterIds(meterIds); + r.setStart(first.toString() + " 00:00:00"); r.setEnd(last.toString() + " 23:59:59"); + curVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + r.setStart(firstPrev.toString() + " 00:00:00"); r.setEnd(lastPrev.toString() + " 23:59:59"); + prevVals.add(nz(baseMapper.sumConsumptionBetweenWithMeters(r))); + } + vo.setCurrentLabels(labels); + vo.setPreviousLabels(labels); + vo.setCurrentValues(curVals); + vo.setPreviousValues(prevVals); + break; + } + } + return vo; + } + + private List resolveMeters(Long energyTypeId, Long meterId, Long locationId) { + // 优先 meterId + if (meterId != null) { + return Collections.singletonList(meterId); + } + List locationIds = null; + if (locationId != null) { + locationIds = collectSubLocationIds(locationId); + } + MeterFilterBo filter = new MeterFilterBo(); + filter.setEnergyTypeId(energyTypeId); + filter.setLocationIds(locationIds); + filter.setMeterId(null); + return meterMapper.selectMeterIds(filter); + } } diff --git a/klp-ems/src/main/resources/mapper/EmsEnergyConsumptionMapper.xml b/klp-ems/src/main/resources/mapper/EmsEnergyConsumptionMapper.xml index 2aaacad3..7c58c1b5 100644 --- a/klp-ems/src/main/resources/mapper/EmsEnergyConsumptionMapper.xml +++ b/klp-ems/src/main/resources/mapper/EmsEnergyConsumptionMapper.xml @@ -48,4 +48,57 @@ month + + + + + + + + + diff --git a/klp-ems/src/main/resources/mapper/EmsMeterMapper.xml b/klp-ems/src/main/resources/mapper/EmsMeterMapper.xml index 4961a9b6..73a2c389 100644 --- a/klp-ems/src/main/resources/mapper/EmsMeterMapper.xml +++ b/klp-ems/src/main/resources/mapper/EmsMeterMapper.xml @@ -23,5 +23,21 @@ - +