增加区域设备统计功能 #148

Merged
hnu202326010106 merged 1 commits from wanglei_branch into develop 2 weeks ago

@ -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<Map<String, Object>> 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<Map<String, Object>> getCampusDeviceStatsUnderCity(@PathVariable String cityId) {
try {
List<AreaDeviceStatsVO> 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));
}
}
}

@ -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
}

@ -48,4 +48,6 @@ public interface DeviceRepository extends JpaRepository<Device, String> {
// 按设备类型加载加载设备(支持区域筛选)
List<Device> findByDeviceTypeAndAreaId(Device.DeviceType deviceType, String areaId);
long countByAreaIdAndDeviceType(String areaId, Device.DeviceType deviceType);
}

@ -30,4 +30,6 @@ public interface DeviceTerminalMappingRepository extends JpaRepository<DeviceTer
// 3. 按终端ID删除所有关联映射删除终端时级联清理映射数据
void deleteByTerminalId(String terminalId);
long countByAreaId(String areaId);
}

@ -1,10 +1,14 @@
package com.campus.water.service;
import com.campus.water.entity.Area;
import com.campus.water.entity.Device;
import com.campus.water.mapper.AreaRepository;
import com.campus.water.entity.Admin;
import com.campus.water.mapper.AdminRepository;
import com.campus.water.mapper.DeviceRepository;
import com.campus.water.mapper.DeviceTerminalMappingRepository;
import com.campus.water.security.RoleConstants;
import com.campus.water.entity.vo.AreaDeviceStatsVO;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import org.springframework.stereotype.Service;
@ -13,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
*
@ -26,10 +31,17 @@ public class AreaService {
// 新增:管理员仓库注入
private final AdminRepository adminRepository;
// 改造构造器添加AdminRepository参数
public AreaService(AreaRepository areaRepository, AdminRepository adminRepository) {
// 新增注入现有设备、终端映射Repository无新增Mapper方法
private final DeviceRepository deviceRepository;
private final DeviceTerminalMappingRepository deviceTerminalMappingRepository;
public AreaService(AreaRepository areaRepository, AdminRepository adminRepository,
DeviceRepository deviceRepository,
DeviceTerminalMappingRepository deviceTerminalMappingRepository) {
this.areaRepository = areaRepository;
this.adminRepository = adminRepository;
this.deviceRepository = deviceRepository;
this.deviceTerminalMappingRepository = deviceTerminalMappingRepository;
}
/**
@ -218,4 +230,106 @@ public class AreaService {
}
}
/**
* +
* @param areaId ID/
* @return
*/
@Transactional(readOnly = true) // 只读事务提升查询性能,不修改数据
public AreaDeviceStatsVO getAreaDeviceStats(String areaId) {
// 1. 校验片区是否存在,获取片区基础信息
Area targetArea = getAreaById(areaId);
AreaDeviceStatsVO statsVO = new AreaDeviceStatsVO();
// 2. 填充片区基础信息复用Area实体字段
statsVO.setAreaId(targetArea.getAreaId());
statsVO.setAreaName(targetArea.getAreaName());
statsVO.setAreaTypeDesc(targetArea.getAreaType().getDesc());
// 3. 区分片区类型执行统计核心逻辑复用现有Mapper方法
if (Area.AreaType.campus.equals(targetArea.getAreaType())) {
// 校区:仅统计自身关联的设备/终端
fillSelfDeviceStats(statsVO, areaId);
} else if (Area.AreaType.zone.equals(targetArea.getAreaType())) {
// 市区:统计自身 + 下属所有校区的汇总数据
fillCityTotalDeviceStats(statsVO, areaId);
}
return statsVO;
}
/**
* /Mappercount
* @param statsVO VO
* @param areaId ID
*/
private void fillSelfDeviceStats(AreaDeviceStatsVO statsVO, String areaId) {
// 复用DeviceRepository.countByAreaIdAndDeviceType已存在无需新增
long waterMakerCount = deviceRepository.countByAreaIdAndDeviceType(
areaId, Device.DeviceType.water_maker); // 假设Device枚举包含WATER_MAKER/WATER_SUPPLY
long waterSupplyCount = deviceRepository.countByAreaIdAndDeviceType(
areaId, Device.DeviceType.water_supply);
// 复用DeviceTerminalMappingRepository.countByAreaId已存在无需新增
long terminalCount = deviceTerminalMappingRepository.countByAreaId(areaId);
// 赋值到VO强转int若数量过大可改为long兼容现有数据
statsVO.setWaterMakerCount((int) waterMakerCount);
statsVO.setWaterSupplyCount((int) waterSupplyCount);
statsVO.setTerminalCount((int) terminalCount);
}
/**
* /
* @param statsVO VO
* @param cityId ID
*/
private void fillCityTotalDeviceStats(AreaDeviceStatsVO statsVO, String cityId) {
// 第一步获取市区下属所有校区的ID列表复用现有getCampusesByCityId方法
List<Area> campusList = getCampusesByCityId(cityId);
List<String> campusIds = campusList.stream()
.map(Area::getAreaId)
.collect(Collectors.toList());
// 第二步:汇总下属所有校区的设备/终端数量循环复用现有count方法适配现有Mapper
long campusWaterMaker = 0;
long campusWaterSupply = 0;
long campusTerminal = 0;
if (!campusIds.isEmpty()) {
for (String campusId : campusIds) {
campusWaterMaker += deviceRepository.countByAreaIdAndDeviceType(campusId, Device.DeviceType.water_maker);
campusWaterSupply += deviceRepository.countByAreaIdAndDeviceType(campusId, Device.DeviceType.water_supply);
campusTerminal += deviceTerminalMappingRepository.countByAreaId(campusId);
}
}
// 第三步:直接赋值校区汇总数据(市区自身无数据)
statsVO.setWaterMakerCount((int) campusWaterMaker);
statsVO.setWaterSupplyCount((int) campusWaterSupply);
statsVO.setTerminalCount((int) campusTerminal);
}
/**
*
* @param cityId ID
* @return
*/
@Transactional(readOnly = true)
public List<AreaDeviceStatsVO> getCampusDeviceStatsUnderCity(String cityId) {
// 1. 校验市区存在且类型正确
Area cityArea = getAreaById(cityId);
if (!Area.AreaType.zone.equals(cityArea.getAreaType())) {
throw new RuntimeException("指定区域不是市区,无法查询下属校区统计");
}
// 2. 获取下属所有校区(复用现有方法)
List<Area> campusList = getCampusesByCityId(cityId);
// 3. 逐个生成校区统计结果复用getAreaDeviceStats方法
return campusList.stream()
.map(campus -> getAreaDeviceStats(campus.getAreaId()))
.collect(Collectors.toList());
}
}
Loading…
Cancel
Save