ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java
@@ -225,6 +225,11 @@ } @Override public R<BigDecimal> getLargeScreenTotalCapacity(@RequestParam("siteIds") List<Integer> siteIds){ return R.fail("获取站点集合累计充电量失败:" + throwable.getMessage()); } @Override public R<List<Long>> getAppUserIdsBySiteIds(List<Integer> siteIds) { return R.fail("查询站点充电用户失败:" + throwable.getMessage()); } ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java
@@ -327,6 +327,12 @@ R<BigDecimal> getSumDegreeBySiteIds(@RequestParam("siteIds") List<Integer> SiteIds); /** * 充电桩大屏 获取站点集合中累计充电量(已结束+已支付订单口径, 与 large-screen/summary 一致) */ @GetMapping("/t-charging-order/getLargeScreenTotalCapacity") R<BigDecimal> getLargeScreenTotalCapacity(@RequestParam("siteIds") List<Integer> siteIds); /** * 查询指定站点中实际发生过充电的用户ID */ @PostMapping("/t-charging-order/getAppUserIdsBySiteIds") ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/service/impl/TScreenContentServiceImpl.java
@@ -40,33 +40,31 @@ @Override public EmissionReductionVO emissionReduction(List<Integer> siteIds) { ScreenTopVO top = top(Arrays.asList(25, 26)); //需调用接口 计算光伏减排 EmissionReductionVO vo = new EmissionReductionVO(); //获取总电量 计算累计充电二氧化碳减排量 BigDecimal charge=top.getCarCharge(); //获取总电量 计算累计充电二氧化碳减排量(与大屏累计充电量同口径: 已结束+已支付订单) BigDecimal charge = BigDecimal.ZERO; R<BigDecimal> r = chargingOrderClient.getLargeScreenTotalCapacity(siteIds); if (r.getCode() == 200 && r.getData() != null) { charge = r.getData(); } BigDecimal multiplier = new BigDecimal("0.1564"); //计算累计充电二氧化碳减排量 if (charge.compareTo(BigDecimal.ZERO) != 0) { // 定义乘数和除数 // 0.1404 // 计算:charge × 0.1404 ÷ 1000 // 计算:charge × 0.1564 ÷ 1000 charge = charge .multiply(multiplier) // 乘以 0.1404 .divide(new BigDecimal("1000"),2, RoundingMode.HALF_DOWN); // 除以 1000,保留6位小数,四舍五入 .multiply(multiplier) // 乘以 0.1564 .divide(new BigDecimal("1000"),2, RoundingMode.HALF_DOWN); // 除以 1000,保留2位小数,四舍五入 } // vo.setCharge(charge); vo.setCharge(charge.add(new BigDecimal(32.61))); vo.setCharge(charge); //获取累计储能放电量 String s = KsolarUtils.getElectricity().split("_")[0]; vo.setEnergyStorage(new BigDecimal(s).multiply(multiplier) // 乘以 0.1404 vo.setEnergyStorage(new BigDecimal(s).multiply(multiplier) // 乘以 0.1564 .divide(new BigDecimal("1000"),2, RoundingMode.HALF_DOWN)); vo.setEnergyStorage(vo.getEnergyStorage().add(new BigDecimal(0.31))); //获取累计发电 vo.setPhotovoltaic(KsolarUtils.getYearAllEnergy()); vo.setPhotovoltaic(vo.getPhotovoltaic().add(new BigDecimal(4.2))); //总数: BigDecimal total = vo.getPhotovoltaic().add(vo.getEnergyStorage()).add(vo.getCharge()); @@ -84,7 +82,7 @@ //百分比计算 public static BigDecimal calculateRatio(BigDecimal part, BigDecimal total) { if (total.compareTo(BigDecimal.ZERO) == 0) { throw new ArithmeticException("分母不能为零"); return BigDecimal.ZERO; } return part.divide(total, 4, RoundingMode.HALF_UP); } @@ -120,9 +118,9 @@ BigDecimal carCharge=new BigDecimal("0.00"); BigDecimal greenElectricity=new BigDecimal("0.00"); if (siteIds!=null && !siteIds.isEmpty()){ //获取充电量 R<BigDecimal> r = chargingOrderClient.getSumDegreeBySiteIds(Arrays.asList(25,26)); if (r.getCode()==200){ //获取充电量(与大屏累计充电量同口径: 已结束+已支付订单) R<BigDecimal> r = chargingOrderClient.getLargeScreenTotalCapacity(siteIds); if (r.getCode()==200 && r.getData()!=null){ charge=r.getData(); } //汽车放电量 ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/vo/EmissionReductionVO.java
@@ -8,7 +8,7 @@ @Data public class EmissionReductionVO { @ApiModelProperty("累计光伏发电二氧化碳减排量(吨)") private BigDecimal photovoltaic = new BigDecimal("1.39"); private BigDecimal photovoltaic; @ApiModelProperty("累计光伏发电二氧化碳减排量(占比率)") private BigDecimal photovoltaicRate ; ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -3168,6 +3168,15 @@ return R.ok(new BigDecimal(sumDegreeBySiteIds)); } /** * 充电桩数据大屏 获取站点集合中累计充电量(与 /large-screen/summary 同口径: 已结束+已支付订单) */ @ResponseBody @GetMapping("/getLargeScreenTotalCapacity") public R<BigDecimal> getLargeScreenTotalCapacity(@RequestParam("siteIds") List<Integer> siteIds){ return R.ok(chargingOrderService.getLargeScreenTotalCapacity(siteIds)); } @ResponseBody @PostMapping("/addChargingOrder") public R<Long> addChargingOrder(@RequestBody TChargingOrder chargingOrder){ ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
@@ -15,7 +15,6 @@ import com.ruoyi.order.api.vo.ChargingOrderBalanceIncomeDetailVO; import com.ruoyi.order.api.vo.TChargingOrderVo; import com.ruoyi.order.dto.*; import com.ruoyi.order.vo.OrderCountByDate; import com.ruoyi.order.vo.LargeChargingPowerVo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -236,6 +235,9 @@ // 接口用: 注册用户数(G 行) Long registeredFromStat(); // 接口用: 大屏累计充电量(M 行汇总, 与 summaryFromStat 同源) BigDecimal capacityFromStat(@Param("siteIds") List<Integer> siteIds); SixChargingDto getLargeScreenSettlementIncome(@Param("siteIdsCsv") String siteIdsCsv, @Param("startTime") String startTime, @Param("endTime") String endTime); @@ -265,7 +267,9 @@ Long countCar(@Param("brands") List<String> brands); List<OrderCountByDate> countOrdersByDate(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("gunIds") List<Integer> gunIds); Long countOrdersInRangeByGunIds(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("gunIds") List<Integer> gunIds); Double getSumDegreeBySiteIds(@Param("siteIds") List<Integer> siteIds); ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
@@ -321,6 +321,11 @@ List<LargeChargingPowerVo> getLargeScreenChargingPower(List<Integer> siteIds, LocalDateTime startTime, LocalDateTime endTime); /** * 大屏累计充电量(与 /large-screen/summary 同口径: 已结束+已支付订单, 读预聚合表 M 行) */ BigDecimal getLargeScreenTotalCapacity(List<Integer> siteIds); /** * 重建大屏预聚合表(每日全量: 全部月份切片 + 近90天日切片 + 全局注册用户数) */ void rebuildLargeScreenStat(); ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -68,7 +68,6 @@ import com.ruoyi.order.vo.EndOfChargePageInfo; import com.ruoyi.order.vo.ChargingSimulationVO; import com.ruoyi.order.vo.IcbcAdminSubOrderVO; import com.ruoyi.order.vo.OrderCountByDate; import com.ruoyi.order.vo.StatisticsOfBatteryVO; import com.ruoyi.order.vo.LargeChargingPowerVo; import com.ruoyi.order.vo.ReservationRecommendationVO; @@ -6809,6 +6808,26 @@ } @Override public BigDecimal getLargeScreenTotalCapacity(List<Integer> siteIds) { String cacheKey = largeScreenCacheKey("capacity", siteIds); BigDecimal cached = redisService.getCacheObject(cacheKey); if (cached != null) { return cached; } BigDecimal capacity = BigDecimal.ZERO; try { BigDecimal fromStat = this.baseMapper.capacityFromStat(siteIds); if (fromStat != null) { capacity = fromStat; } } catch (Exception e) { log.warn("大屏累计充电量读取预聚合表失败, siteIds={}", siteIds, e); } redisService.setCacheObject(cacheKey, capacity, LARGE_SCREEN_CACHE_SECONDS, TimeUnit.SECONDS); return capacity; } @Override public void rebuildLargeScreenStat() { log.info("大屏预聚合表全量重建开始"); long start = System.currentTimeMillis(); @@ -7329,6 +7348,11 @@ */ @Override public R<StatisticsOfBatteryVO> getStatisticsOfBattery(List<Integer> siteIds) { String cacheKey = largeScreenCacheKey("battery", siteIds); StatisticsOfBatteryVO cached = redisService.getCacheObject(cacheKey); if (cached != null) { return R.ok(cached); } StatisticsOfBatteryVO vo = new StatisticsOfBatteryVO(); List<Integer> effectiveSiteIds = siteIds == null ? Arrays.asList(25, 26) : siteIds; if (effectiveSiteIds.isEmpty()) { @@ -7343,39 +7367,52 @@ return R.ok(vo); } List<Integer> gunIds = r.getData(); //统计 // 统计: gunIds 分批查询, 避免超大 IN 列表撑爆 MyCat 规划器 Long total = 0L; if (gunIds != null && !gunIds.isEmpty()) { total = this.baseMapper.selectCount(new LambdaQueryWrapper<TChargingOrder>() .eq(TChargingOrder::getDelFlag, 0)//未删除 .in(TChargingOrder::getStatus, Arrays.asList(3, 5))//充电中、已结束 .in(TChargingOrder::getChargingGunId, gunIds));//符合条件的充电枪 for (List<Integer> chunk : chunkList(gunIds, 500)) { Long chunkCount = this.baseMapper.selectCount(new LambdaQueryWrapper<TChargingOrder>() .eq(TChargingOrder::getDelFlag, 0)//未删除 .in(TChargingOrder::getStatus, Arrays.asList(3, 5))//充电中、已结束 .in(TChargingOrder::getChargingGunId, chunk));//符合条件的充电枪 total += chunkCount == null ? 0L : chunkCount; } } vo.setTotal(total.intValue()); List<LocalDate> dates = new ArrayList<>(); List<Integer> counts = new ArrayList<>(); LocalDate today = LocalDate.now(); LocalDateTime startDate = today.minusDays(7).atStartOfDay(); LocalDateTime endDate = today.minusDays(1).atTime(LocalTime.MAX); Map<LocalDate, Long> countByDate = new HashMap<>(); if (gunIds != null && !gunIds.isEmpty()) { List<OrderCountByDate> orderCounts = this.baseMapper.countOrdersByDate(startDate, endDate, gunIds); if (orderCounts != null) { for (OrderCountByDate orderCount : orderCounts) { countByDate.put(orderCount.getDate(), orderCount.getCount()); } } } for (int i = 7; i >= 1; i--) {//升序 LocalDate day = today.minusDays(i); LocalDateTime dayStart = day.atStartOfDay(); LocalDateTime dayEnd = day.plusDays(1).atStartOfDay(); long dayCount = 0L; if (gunIds != null && !gunIds.isEmpty()) { for (List<Integer> chunk : chunkList(gunIds, 500)) { Long chunkCount = this.baseMapper.countOrdersInRangeByGunIds(dayStart, dayEnd, chunk); dayCount += chunkCount == null ? 0L : chunkCount; } } dates.add(day); counts.add(countByDate.getOrDefault(day, 0L).intValue()); counts.add((int) dayCount); } vo.setDates(dates); vo.setCounts(counts); redisService.setCacheObject(cacheKey, vo, LARGE_SCREEN_CACHE_SECONDS, TimeUnit.SECONDS); return R.ok(vo); } /** * 列表分批, 控制单条 SQL 的 IN 列表规模 */ private <T> List<List<T>> chunkList(List<T> list, int size) { List<List<T>> chunks = new ArrayList<>(); for (int i = 0; i < list.size(); i += size) { chunks.add(list.subList(i, Math.min(i + size, list.size()))); } return chunks; } @Override public Double getSumDegreeBySiteIds(List<Integer> siteIds) { Double sumDegreeBySiteIds = this.baseMapper.getSumDegreeBySiteIds(siteIds); ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
@@ -2535,21 +2535,19 @@ </select> <select id="countOrdersByDate" resultType="com.ruoyi.order.vo.OrderCountByDate"> SELECT DATE(create_time) AS `date`, COUNT(*) AS `count` <!-- 电池安全检测按日计数: 单日有界 COUNT, 无 GROUP BY/ORDER BY, 规避 MyCat 规划器 在函数列上排序(MycatMemSort)失败的报错; 天级分组由 Java 端循环完成 --> <select id="countOrdersInRangeByGunIds" resultType="java.lang.Long"> SELECT COUNT(1) FROM t_charging_order WHERE del_flag = 0 and status in (3,5) and charging_gun_id in WHERE del_flag = 0 AND status IN (3, 5) AND charging_gun_id IN <foreach item="item" index="index" collection="gunIds" open="(" separator="," close=")"> #{item} </foreach> and create_time BETWEEN #{startTime} AND #{endTime} GROUP BY DATE(create_time) ORDER BY DATE(create_time) ASC AND create_time >= #{startTime} AND create_time < #{endTime} </select> @@ -3244,4 +3242,17 @@ AND site_id = 0 LIMIT 1 </select> <!-- 接口用: 大屏累计充电量(与 summary 同源: 已结束+已支付订单, M 行汇总) --> <select id="capacityFromStat" resultType="java.math.BigDecimal"> SELECT COALESCE(SUM(capacity), 0) FROM t_large_screen_site_stat WHERE stat_type = 'M' <if test="siteIds != null and siteIds.size() > 0"> AND site_id IN <foreach collection="siteIds" item="siteId" open="(" separator="," close=")"> #{siteId} </foreach> </if> </select> </mapper> ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TScreenContentServiceImpl.java
@@ -34,20 +34,21 @@ @Override public EmissionReductionVO emissionReduction(List<Integer> siteIds) { ScreenTopVO top = top(siteIds); //需调用接口 计算光伏减排 EmissionReductionVO vo = new EmissionReductionVO(); //获取总电量 计算累计充电二氧化碳减排量 BigDecimal charge = top.getCarCharge(); //获取总电量 计算累计充电二氧化碳减排量(与大屏累计充电量同口径: 已结束+已支付订单) BigDecimal charge = BigDecimal.ZERO; R<BigDecimal> r = chargingOrderClient.getLargeScreenTotalCapacity(siteIds); if (r.getCode() == 200 && r.getData() != null) { charge = r.getData(); } BigDecimal multiplier = new BigDecimal("0.1564"); //计算累计充电二氧化碳减排量 if (charge.compareTo(BigDecimal.ZERO) != 0) { // 定义乘数和除数 // 0.1404 // 计算:charge × 0.1404 ÷ 1000 // 计算:charge × 0.1564 ÷ 1000 charge = charge .multiply(multiplier) // 乘以 0.1404 .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_DOWN); // 除以 1000,保留6位小数,四舍五入 .multiply(multiplier) // 乘以 0.1564 .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_DOWN); // 除以 1000,保留2位小数,四舍五入 } vo.setCharge(charge); @@ -112,9 +113,9 @@ BigDecimal carCharge = new BigDecimal("0.00"); BigDecimal greenElectricity = new BigDecimal("0.00"); if (siteIds != null && !siteIds.isEmpty()) { //获取充电量 R<BigDecimal> r = chargingOrderClient.getSumDegreeBySiteIds(siteIds); if (r.getCode() == 200) { //获取充电量(与大屏累计充电量同口径: 已结束+已支付订单) R<BigDecimal> r = chargingOrderClient.getLargeScreenTotalCapacity(siteIds); if (r.getCode() == 200 && r.getData() != null) { charge = r.getData(); } //汽车放电量 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/EmissionReductionVO.java
@@ -8,7 +8,7 @@ @Data public class EmissionReductionVO { @ApiModelProperty("累计光伏发电二氧化碳减排量(吨)") private BigDecimal photovoltaic = new BigDecimal("1.39"); private BigDecimal photovoltaic; @ApiModelProperty("累计光伏发电二氧化碳减排量(占比率)") private BigDecimal photovoltaicRate ;