longz
2026-08-07 d7d4ae6cfb28adf7ef92f44332ff492f0cc7069c
feat: 完善大屏与光储监控接口
1个文件已添加
7个文件已修改
219 ■■■■■ 已修改文件
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/TChargingPileService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/LargeScreenController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/20260807_energy_storage_monitoring_menu.sql 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingPileController.java
@@ -309,6 +309,13 @@
        return AjaxResult.success(chargeMonitoring);
    }
    @ResponseBody
    @GetMapping("/screenChargeMonitoring/{siteId}")
    @ApiOperation(value = "获取智慧充电大屏监控数据", tags = {"管理后台-智慧充电大屏"})
    public AjaxResult<ChargeMonitoring> screenChargeMonitoring(@PathVariable Integer siteId){
        return AjaxResult.success(chargingPileService.chargeMonitoringForScreen(siteId));
    }
    @RequiresPermissions(value = {"/chargingEquipmentMonitoring"}, logical = Logical.OR)
    @ResponseBody
    @GetMapping("/getChargingMonitoringSiteList")
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/TChargingPileService.java
@@ -101,6 +101,9 @@
     */
    ChargeMonitoring chargeMonitoring(Integer siteId);
    /** 智慧充电大屏监控数据,不按菜单权限过滤站点。 */
    ChargeMonitoring chargeMonitoringForScreen(Integer siteId);
    List<Site> getChargingMonitoringSiteList();
    
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
@@ -794,6 +794,22 @@
    @Override
    public ChargeMonitoring chargeMonitoring(Integer siteId) {
        Set<Integer> siteIds = resolveChargingMonitoringSiteIds(siteId);
        return buildChargeMonitoring(siteIds);
    }
    @Override
    public ChargeMonitoring chargeMonitoringForScreen(Integer siteId) {
        Set<Integer> siteIds;
        if (siteId != null && siteId > 0) {
            siteIds = Collections.singleton(siteId);
        } else {
            siteIds = siteService.list(new LambdaQueryWrapper<Site>()
                    .eq(Site::getDelFlag, 0)).stream().map(Site::getId).collect(Collectors.toSet());
        }
        return buildChargeMonitoring(siteIds);
    }
    private ChargeMonitoring buildChargeMonitoring(Set<Integer> siteIds) {
        List<Site> sites = siteService.list(new LambdaQueryWrapper<Site>()
                .in(Site::getId, siteIds)
                .eq(Site::getDelFlag, 0));
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/LargeScreenController.java
@@ -36,11 +36,11 @@
        return R.ok(chargingOrderService.getLargeScreenSummary(normalizeSiteIds(siteIds)));
    }
    @ApiOperation(tags = {"大屏-收入趋势"}, value = "当年按月充电收入")
    @ApiOperation(tags = {"大屏-收入趋势"}, value = "最近七日充电收入")
    @GetMapping("/incomeTrend")
    public R<List<SixChargingDto>> incomeTrend(@RequestParam("siteIds") List<Integer> siteIds) {
        return R.ok(chargingOrderService.getLargeScreenIncomeTrend(
                normalizeSiteIds(siteIds), LocalDate.now().withDayOfYear(1)));
                normalizeSiteIds(siteIds), LocalDate.now().minusDays(6)));
    }
    @ApiOperation(tags = {"大屏-停车场充电功率曲线图"},value = "停车场充电功率曲线图")
@@ -48,14 +48,14 @@
    public R<List<LargeChargingPowerVo>> getChargingPower(
            @RequestParam(value = "siteIds", required = false) List<Integer> siteIds){
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.minusDays(7).atStartOfDay();
        LocalDateTime endTime = today.atStartOfDay();
        LocalDateTime startTime = today.minusDays(6).atStartOfDay();
        LocalDateTime endTime = today.plusDays(1).atStartOfDay();
        List<LargeChargingPowerVo> powerData = chargingOrderService.getLargeScreenChargingPower(
                siteIds == null ? null : normalizeSiteIds(siteIds), startTime, endTime);
        Map<String, LargeChargingPowerVo> powerByDate = powerData.stream()
                .collect(Collectors.toMap(LargeChargingPowerVo::getTime, Function.identity(), (left, right) -> left));
        ArrayList<LargeChargingPowerVo> largeChargingPowerVos = new ArrayList<>();
        for (int count = 7; count > 0; count--) {
        for (int count = 6; count >= 0; count--) {
            String time = today.minusDays(count).toString();
            LargeChargingPowerVo largeChargingPowerVo = powerByDate.getOrDefault(time, new LargeChargingPowerVo());
            largeChargingPowerVo.setTime(time);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java
@@ -322,6 +322,10 @@
    // 接口用: 近 N 月收入趋势(M 行按 period 分组)
    List<SixChargingDto> incomeTrendFromStat(@Param("siteIds") List<Integer> siteIds, @Param("sixBefore") String sixBefore);
    List<SixChargingDto> incomeTrendFromOrders(@Param("siteIds") List<Integer> siteIds,
                                               @Param("startTime") String startTime,
                                               @Param("endTime") String endTime);
    // 接口用: 日功率曲线(D 行按 period 分组)
    List<Map<String, Object>> powerFromStat(@Param("siteIds") List<Integer> siteIds,
                                            @Param("dayStart") String dayStart, @Param("dayEnd") String dayEnd);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -7082,26 +7082,27 @@
        if (cached != null) {
            return cached;
        }
        LocalDate currentMonth = LocalDate.now().withDayOfMonth(1);
        LocalDate currentDay = LocalDate.now();
        List<SixChargingDto> result = new ArrayList<>();
        try {
            String sixBeforeMonth = sixBefore.withDayOfMonth(1).format(LARGE_SCREEN_MONTH_FMT);
            List<SixChargingDto> incomeList = this.baseMapper.incomeTrendFromStat(siteIds, sixBeforeMonth);
            Map<String, SixChargingDto> incomeByMonth = new HashMap<>();
            List<SixChargingDto> incomeList = this.baseMapper.incomeTrendFromOrders(siteIds,
                    sixBefore.atStartOfDay().format(LARGE_SCREEN_SQL_FMT),
                    currentDay.plusDays(1).atStartOfDay().format(LARGE_SCREEN_SQL_FMT));
            Map<String, SixChargingDto> incomeByDay = new HashMap<>();
            if (incomeList != null) {
                for (SixChargingDto income : incomeList) {
                    if (income != null && income.getMonth() != null) {
                        incomeByMonth.put(income.getMonth(), income);
                        incomeByDay.put(income.getMonth(), income);
                    }
                }
            }
            LocalDate month = sixBefore.withDayOfMonth(1);
            while (!month.isAfter(currentMonth)) {
                SixChargingDto income = incomeByMonth.get(month.format(LARGE_SCREEN_MONTH_FMT));
            LocalDate day = sixBefore;
            while (!day.isAfter(currentDay)) {
                SixChargingDto income = incomeByDay.get(day.format(LARGE_SCREEN_DAY_FMT));
                if (income == null) {
                    income = new SixChargingDto();
                }
                income.setMonth(String.format("%02d", month.getMonthValue()));
                income.setMonth(day.format(LARGE_SCREEN_DAY_FMT));
                if (income.getElectrovalence() == null) {
                    income.setElectrovalence(BigDecimal.ZERO);
                }
@@ -7109,18 +7110,18 @@
                    income.setServiceCharge(BigDecimal.ZERO);
                }
                result.add(income);
                month = month.plusMonths(1);
                day = day.plusDays(1);
            }
        } catch (Exception e) {
            log.warn("大屏收入趋势读取预聚合表失败, siteIds={}, sixBefore={}", siteIds, sixBefore, e);
            LocalDate month = sixBefore.withDayOfMonth(1);
            while (!month.isAfter(currentMonth)) {
            LocalDate day = sixBefore;
            while (!day.isAfter(currentDay)) {
                SixChargingDto income = new SixChargingDto();
                income.setMonth(String.format("%02d", month.getMonthValue()));
                income.setMonth(day.format(LARGE_SCREEN_DAY_FMT));
                income.setElectrovalence(BigDecimal.ZERO);
                income.setServiceCharge(BigDecimal.ZERO);
                result.add(income);
                month = month.plusMonths(1);
                day = day.plusDays(1);
            }
        }
        redisService.setCacheObject(cacheKey, result, LARGE_SCREEN_CACHE_SECONDS, TimeUnit.SECONDS);
@@ -7333,9 +7334,11 @@
            stat.put("orderCount", decimalValue(row, "order_count"));
            stat.put("userCount", BigDecimal.ZERO);
            stat.put("capacity", BigDecimal.ZERO);
            stat.put("electricFee", BigDecimal.ZERO);
            stat.put("serviceFee", BigDecimal.ZERO);
            stat.put("income", BigDecimal.ZERO);
            BigDecimal electricFee = decimalValue(row, "electric_fee");
            BigDecimal serviceFee = decimalValue(row, "service_fee");
            stat.put("electricFee", electricFee);
            stat.put("serviceFee", serviceFee);
            stat.put("income", electricFee.add(serviceFee));
            stat.put("totalPower", decimalValue(row, "total_power"));
            stat.put("registeredUserCount", 0L);
            statRows.add(stat);
@@ -7804,7 +7807,7 @@
        List<LocalDate> dates = new ArrayList<>();
        List<Integer> counts = new ArrayList<>();
        LocalDate today = LocalDate.now();
        for (int i = 7; i >= 1; i--) {//升序
        for (int i = 6; i >= 0; i--) {//升序,最近七日(含当天)
            LocalDate day = today.minusDays(i);
            LocalDateTime dayStart = day.atStartOfDay();
            LocalDateTime dayEnd = day.plusDays(1).atStartOfDay();
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml
@@ -3444,16 +3444,25 @@
        SELECT COUNT(*) FROM t_large_screen_user_site
    </select>
    <!-- 任务用: 按日切片聚合, 口径与 getLargeScreenChargingPower 一致(无 status 过滤) -->
    <!-- 任务用: 按日切片聚合,功率保持原口径;收入与月度切片一致。 -->
    <select id="daySliceAgg" resultType="java.util.Map">
        SELECT site_id AS site_id,
        SELECT charging_order.site_id AS site_id,
               COUNT(1) AS order_count,
               COALESCE(SUM(IFNULL(power, 0)), 0) AS total_power
        FROM t_charging_order
        WHERE del_flag = 0
          AND create_time &gt;= #{startTime}
          AND create_time &lt; #{endTime}
        GROUP BY site_id
               COALESCE(SUM(IFNULL(charging_order.power, 0)), 0) AS total_power,
               COALESCE(ROUND(SUM(CASE WHEN charging_order.status = 5
                   AND charging_order.recharge_payment_status = 2 THEN accounting.period_electric_price ELSE 0 END), 2), 0) AS electric_fee,
               COALESCE(ROUND(SUM(CASE WHEN charging_order.status = 5
                   AND charging_order.recharge_payment_status = 2 AND charging_order.order_source IN (0, 1) THEN accounting.period_service_price
                   WHEN charging_order.status = 5
                   AND charging_order.recharge_payment_status = 2 THEN accounting.period_service_price * 0.8
                   ELSE 0 END), 2), 0) AS service_fee
        FROM t_charging_order charging_order
        LEFT JOIN t_charging_order_accounting_strategy accounting
               ON accounting.charging_order_id = charging_order.id
        WHERE charging_order.del_flag = 0
          AND charging_order.create_time &gt;= #{startTime}
          AND charging_order.create_time &lt; #{endTime}
        GROUP BY charging_order.site_id
    </select>
    <!-- 任务用: 注册用户总数 -->
@@ -3499,13 +3508,13 @@
        </if>
    </select>
    <!-- 接口用: 近 N 月收入趋势(M 行按 period 分组, period 为 yyyy-MM 字典序可比) -->
    <!-- 接口用: 近 N 日收入趋势(D 行按 period 分组, period 为 yyyy-MM-dd 字典序可比) -->
    <select id="incomeTrendFromStat" resultType="com.ruoyi.order.dto.SixChargingDto">
        SELECT period AS month,
               COALESCE(SUM(electric_fee), 0) AS electrovalence,
               COALESCE(SUM(service_fee), 0) AS service_charge
        FROM t_large_screen_site_stat
        WHERE stat_type = 'M'
        WHERE stat_type = 'D'
          AND period &gt;= #{sixBefore}
        <if test="siteIds != null and siteIds.size() > 0">
            AND site_id IN
@@ -3516,6 +3525,30 @@
        GROUP BY period
    </select>
    <!-- 接口用: 最近七日收入,直接查询确保历史日切片升级后也能立即显示正确金额。 -->
    <select id="incomeTrendFromOrders" resultType="com.ruoyi.order.dto.SixChargingDto">
        SELECT DATE_FORMAT(charging_order.create_time, '%Y-%m-%d') AS month,
               COALESCE(ROUND(SUM(accounting.period_electric_price), 2), 0) AS electrovalence,
               COALESCE(ROUND(SUM(CASE WHEN charging_order.order_source IN (0, 1) THEN accounting.period_service_price
                   ELSE accounting.period_service_price * 0.8 END), 2), 0) AS service_charge
        FROM t_charging_order charging_order
        LEFT JOIN t_charging_order_accounting_strategy accounting
               ON accounting.charging_order_id = charging_order.id
        WHERE charging_order.del_flag = 0
          AND charging_order.status = 5
          AND charging_order.recharge_payment_status = 2
          AND charging_order.create_time &gt;= #{startTime}
          AND charging_order.create_time &lt; #{endTime}
        <if test="siteIds != null and siteIds.size() > 0">
            AND charging_order.site_id IN
            <foreach collection="siteIds" item="siteId" open="(" separator="," close=")">
                #{siteId}
            </foreach>
        </if>
        GROUP BY DATE_FORMAT(charging_order.create_time, '%Y-%m-%d')
        ORDER BY month
    </select>
    <!-- 接口用: 日功率曲线(D 行按 period 分组, period 为 yyyy-MM-dd 字典序可比) -->
    <select id="powerFromStat" resultType="java.util.Map">
        SELECT period AS day,
sql/20260807_energy_storage_monitoring_menu.sql
New file
@@ -0,0 +1,87 @@
-- 光储监控菜单调整:设备管理重命名,报表重命名,并将视频监控置于数据菜单首位。
UPDATE sys_menu
SET menu_name = '光储监控设备管理', update_time = NOW()
WHERE parent_id = 0
  AND menu_type = 'M'
  AND (path = '/deviceManagement' OR perms = '/deviceManagement');
SET @energy_data_id := (
    SELECT menu_id
    FROM sys_menu
    WHERE parent_id = 0
      AND menu_type = 'M'
      AND (path = '/energyReport' OR perms = '/energyReport')
    ORDER BY menu_id
    LIMIT 1
);
UPDATE sys_menu
SET menu_name = '光储监控数据', update_time = NOW()
WHERE menu_id = @energy_data_id;
INSERT INTO sys_menu
    (menu_name, parent_id, order_num, path, component, query, is_frame, is_cache,
     menu_type, visible, status, perms, icon, create_by, create_time, remark)
SELECT '视频监控', @energy_data_id, 1, '/videoMonitor', 'videoMonitor', NULL, 1, 0,
       'C', '0', 0, '/energyReport/videoMonitor', '#', 'admin', NOW(), '光储监控数据-视频监控'
WHERE @energy_data_id IS NOT NULL
  AND NOT EXISTS (
      SELECT 1 FROM sys_menu
      WHERE parent_id = @energy_data_id AND path = '/videoMonitor'
  );
SET @video_monitor_id := (
    SELECT menu_id
    FROM sys_menu
    WHERE parent_id = @energy_data_id AND path = '/videoMonitor'
    ORDER BY menu_id
    LIMIT 1
);
UPDATE sys_menu
SET menu_name = '视频监控', order_num = 1, component = 'videoMonitor', menu_type = 'C',
    visible = '0', status = 0, perms = '/energyReport/videoMonitor', update_time = NOW()
WHERE menu_id = @video_monitor_id;
UPDATE sys_menu
SET order_num = order_num + 1, update_time = NOW()
WHERE parent_id = @energy_data_id
  AND menu_id <> @video_monitor_id
  AND order_num >= 1;
-- 已拥有“光储监控数据”目录权限的角色同步获得视频监控权限。
INSERT IGNORE INTO sys_role_menu (role_id, menu_id)
SELECT role_id, @video_monitor_id
FROM sys_role_menu
WHERE menu_id = @energy_data_id;
-- 光储监控设备管理的子菜单名称及顺序。
SET @device_monitoring_id := (
    SELECT menu_id FROM sys_menu
    WHERE parent_id = 0
      AND menu_type = 'M'
      AND (path = '/deviceManagement' OR perms = '/deviceManagement')
    ORDER BY menu_id
    LIMIT 1
);
UPDATE sys_menu
SET menu_name = '监控摄像头列表', order_num = 1, update_time = NOW()
WHERE parent_id = @device_monitoring_id AND path = '/deviceManagement/list';
UPDATE sys_menu
SET menu_name = '光伏电站管理', order_num = 2, update_time = NOW()
WHERE parent_id = @device_monitoring_id AND path = '/deviceManagement/photovoltaicStation/list';
UPDATE sys_menu
SET menu_name = '储能电站管理', order_num = 3, update_time = NOW()
WHERE parent_id = @device_monitoring_id AND path = '/deviceManagement/energyStorage/list';
UPDATE sys_menu
SET menu_name = '光伏逆变器管理', order_num = 4, update_time = NOW()
WHERE parent_id = @device_monitoring_id AND path = '/deviceManagement/photovoltaicInverter/list';
UPDATE sys_menu
SET menu_name = '储能能量链管理', order_num = 5, update_time = NOW()
WHERE parent_id = @device_monitoring_id AND path = '/deviceManagement/energyChain/list';