diff --git a/src/main/java/com/campus/water/controller/web/AreaController.java b/src/main/java/com/campus/water/controller/web/AreaController.java index 6acf470..d303526 100644 --- a/src/main/java/com/campus/water/controller/web/AreaController.java +++ b/src/main/java/com/campus/water/controller/web/AreaController.java @@ -2,6 +2,7 @@ package com.campus.water.controller.web; import com.campus.water.entity.Area; import com.campus.water.service.AreaService; +import com.campus.water.entity.vo.AreaDeviceStatsVO; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -148,4 +149,47 @@ public class AreaController { .body(buildResponse(500, "查询区域详情失败:" + e.getMessage(), null)); } } + + /** + * 获取指定片区设备统计 + * 权限:超级管理员/区域管理员(与新增/修改区域权限一致) + * 响应:校区返回自身数据,市区返回下属校区汇总数据 + */ + @GetMapping("/device-stats/{areaId}") + @PreAuthorize("hasAnyRole('SUPER_ADMIN', 'AREA_ADMIN')") + public ResponseEntity> getAreaDeviceStats(@PathVariable String areaId) { + try { + AreaDeviceStatsVO statsVO = areaService.getAreaDeviceStats(areaId); + return ResponseEntity.ok(buildResponse(200, "统计成功", statsVO)); + } catch (RuntimeException e) { + // 业务异常(片区不存在、参数错误等)返回400 + return ResponseEntity.badRequest().body(buildResponse(400, e.getMessage(), null)); + } catch (Exception e) { + // 系统异常返回500 + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(buildResponse(500, "统计片区设备失败:" + e.getMessage(), null)); + } + } + + /** + * 获取市区下所有校区单独统计 + * 权限:超级管理员/区域管理员(与新增/修改区域权限一致) + * 响应:返回该市区下每个校区的设备统计,不进行汇总 + */ + @GetMapping("/device-stats/city/{cityId}/campuses") + @PreAuthorize("hasAnyRole('SUPER_ADMIN', 'AREA_ADMIN')") + public ResponseEntity> getCampusDeviceStatsUnderCity(@PathVariable String cityId) { + try { + List statsVOList = areaService.getCampusDeviceStatsUnderCity(cityId); + return ResponseEntity.ok(buildResponse(200, "统计成功", statsVOList)); + } catch (RuntimeException e) { + // 业务异常(非市区、市区不存在等)返回400 + return ResponseEntity.badRequest().body(buildResponse(400, e.getMessage(), null)); + } catch (Exception e) { + // 系统异常返回500 + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(buildResponse(500, "统计市区下属校区设备失败:" + e.getMessage(), null)); + } + } + } \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/vo/AreaDeviceStatsVO.java b/src/main/java/com/campus/water/entity/vo/AreaDeviceStatsVO.java new file mode 100644 index 0000000..5d332c2 --- /dev/null +++ b/src/main/java/com/campus/water/entity/vo/AreaDeviceStatsVO.java @@ -0,0 +1,16 @@ +package com.campus.water.entity.vo; + +import lombok.Data; + +/** + * 片区设备统计VO(适配现有实体,无新增依赖) + */ +@Data +public class AreaDeviceStatsVO { + private String areaId; // 对应Area.areaId + private String areaName; // 对应Area.areaName + private String areaTypeDesc; // 对应Area.AreaType.desc(市区/校园) + private int waterMakerCount; // 制水机数量 + private int waterSupplyCount; // 供水机数量 + private int terminalCount; // 终端数量(基于DeviceTerminalMapping) +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/mapper/DeviceRepository.java b/src/main/java/com/campus/water/mapper/DeviceRepository.java index ab8db1d..82f5963 100644 --- a/src/main/java/com/campus/water/mapper/DeviceRepository.java +++ b/src/main/java/com/campus/water/mapper/DeviceRepository.java @@ -48,4 +48,6 @@ public interface DeviceRepository extends JpaRepository { // 按设备类型加载加载设备(支持区域筛选) List findByDeviceTypeAndAreaId(Device.DeviceType deviceType, String areaId); + + long countByAreaIdAndDeviceType(String areaId, Device.DeviceType deviceType); } \ No newline at end of file diff --git a/src/main/java/com/campus/water/mapper/DeviceTerminalMappingRepository.java b/src/main/java/com/campus/water/mapper/DeviceTerminalMappingRepository.java index 69e7a36..5a53e54 100644 --- a/src/main/java/com/campus/water/mapper/DeviceTerminalMappingRepository.java +++ b/src/main/java/com/campus/water/mapper/DeviceTerminalMappingRepository.java @@ -30,4 +30,6 @@ public interface DeviceTerminalMappingRepository extends JpaRepository