feat: 添加资源利用率分析相关接口和功能
- 新增资源利用率分析相关的 VO、DTO、Mapper、Service 等类 - 实现资源利用率概览、详细信息、趋势分析、分布分析、优化建议等功能 - 添加实时资源状态相关接口和功能
This commit is contained in:
parent
ffd81ada4a
commit
55be07a4bd
|
|
@ -0,0 +1,70 @@
|
|||
package com.securitycontrol.screen.controller;
|
||||
|
||||
import com.securitycontrol.common.core.web.domain.AjaxResult;
|
||||
import com.securitycontrol.common.log.annotation.Log;
|
||||
import com.securitycontrol.common.log.enums.OperationType;
|
||||
import com.securitycontrol.screen.dto.ResourceQueryDto;
|
||||
import com.securitycontrol.screen.service.ResourceService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 资源利用率分析控制器
|
||||
*
|
||||
* @author syruan
|
||||
*/
|
||||
@Api(tags = "资源利用率分析")
|
||||
@RestController
|
||||
@RequestMapping("/api/resource")
|
||||
public class ResourceController {
|
||||
|
||||
@Resource
|
||||
private ResourceService resourceService;
|
||||
|
||||
@ApiOperation(value = "获取资源利用率概览")
|
||||
@GetMapping("/overview")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->概览", grade = OperationType.QUERY_BUSINESS, details = "获取资源利用率概览数据", type = "业务日志")
|
||||
public AjaxResult getResourceOverview(ResourceQueryDto dto) {
|
||||
return resourceService.getResourceOverview(dto);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取资源详细信息")
|
||||
@GetMapping("/details")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->详细信息", grade = OperationType.QUERY_BUSINESS, details = "获取资源详细信息列表", type = "业务日志")
|
||||
public AjaxResult getResourceDetails(ResourceQueryDto dto) {
|
||||
return resourceService.getResourceDetails(dto);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取资源利用率趋势")
|
||||
@GetMapping("/trends")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->趋势分析", grade = OperationType.QUERY_BUSINESS, details = "获取资源利用率趋势数据", type = "业务日志")
|
||||
public AjaxResult getResourceTrends(ResourceQueryDto dto) {
|
||||
return resourceService.getResourceTrends(dto);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取资源利用率分布")
|
||||
@GetMapping("/distribution")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->分布分析", grade = OperationType.QUERY_BUSINESS, details = "获取资源利用率分布数据", type = "业务日志")
|
||||
public AjaxResult getResourceDistribution(ResourceQueryDto dto) {
|
||||
return resourceService.getResourceDistribution(dto);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取优化建议")
|
||||
@GetMapping("/suggestions")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->优化建议", grade = OperationType.QUERY_BUSINESS, details = "获取优化建议", type = "业务日志")
|
||||
public AjaxResult getOptimizationSuggestions(ResourceQueryDto dto) {
|
||||
return resourceService.getOptimizationSuggestions(dto);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取实时资源状态")
|
||||
@GetMapping("/realtime")
|
||||
@Log(title = "资源利用率分析", menu = "资源利用率分析->实时状态", grade = OperationType.QUERY_BUSINESS, details = "获取实时资源状态", type = "业务日志")
|
||||
public AjaxResult getRealtimeResourceStatus(ResourceQueryDto dto) {
|
||||
return resourceService.getRealtimeResourceStatus(dto);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.securitycontrol.screen.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源利用率查询参数DTO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("资源利用率查询参数")
|
||||
public class ResourceQueryDto {
|
||||
|
||||
@ApiModelProperty("项目ID")
|
||||
private String projectId;
|
||||
|
||||
@ApiModelProperty("时间范围:today/week/month,默认today")
|
||||
private String timeRange = "today";
|
||||
|
||||
@ApiModelProperty("资源类型:personnel/equipment/material/energy,不传则返回全部")
|
||||
private String resourceType;
|
||||
|
||||
@ApiModelProperty("页码,默认1")
|
||||
private Integer page = 1;
|
||||
|
||||
@ApiModelProperty("每页数量,默认20")
|
||||
private Integer pageSize = 20;
|
||||
|
||||
@ApiModelProperty("开始日期,格式:YYYY-MM-DD")
|
||||
private String startDate;
|
||||
|
||||
@ApiModelProperty("结束日期,格式:YYYY-MM-DD")
|
||||
private String endDate;
|
||||
|
||||
@ApiModelProperty("时间粒度:hour/day/week,默认day")
|
||||
private String granularity = "day";
|
||||
|
||||
@ApiModelProperty("指定日期,格式:YYYY-MM-DD,默认今天")
|
||||
private String date;
|
||||
|
||||
@ApiModelProperty("返回建议数量,默认5")
|
||||
private Integer limit = 5;
|
||||
|
||||
@ApiModelProperty("上次更新时间,用于增量更新")
|
||||
private String lastUpdateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.securitycontrol.screen.mapper;
|
||||
|
||||
import com.securitycontrol.screen.dto.ResourceQueryDto;
|
||||
import com.securitycontrol.screen.vo.OptimizationSuggestionVo;
|
||||
import com.securitycontrol.screen.vo.RealtimeResourceVo;
|
||||
import com.securitycontrol.screen.vo.ResourceDetailVo;
|
||||
import com.securitycontrol.screen.vo.ResourceDistributionVo;
|
||||
import org.apache.ibatis.annotations.MapKey;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资源利用率分析数据访问层接口
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Repository
|
||||
public interface ResourceMapper {
|
||||
|
||||
/**
|
||||
* 获取总体统计数据
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 统计数据
|
||||
*/
|
||||
Map<String, Object> getOverallStats(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取各类资源概览
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 资源概览列表
|
||||
*/
|
||||
@MapKey("type")
|
||||
List<Map<String, Object>> getResourceOverview(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源详细信息
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 资源详细信息列表
|
||||
*/
|
||||
List<ResourceDetailVo> getResourceDetails(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源详细信息总数
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 总数
|
||||
*/
|
||||
int getResourceDetailsCount(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源利用率趋势数据
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 趋势数据
|
||||
*/
|
||||
@MapKey("date")
|
||||
List<Map<String, Object>> getResourceTrends(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源利用率分布数据
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 分布数据
|
||||
*/
|
||||
List<ResourceDistributionVo> getResourceDistribution(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取优化建议
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 优化建议列表
|
||||
*/
|
||||
List<OptimizationSuggestionVo> getOptimizationSuggestions(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取变化的资源
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 变化的资源列表
|
||||
*/
|
||||
List<RealtimeResourceVo.ChangedResource> getChangedResources(ResourceQueryDto dto);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package com.securitycontrol.screen.service;
|
||||
|
||||
import com.securitycontrol.common.core.web.domain.AjaxResult;
|
||||
import com.securitycontrol.screen.dto.ResourceQueryDto;
|
||||
|
||||
/**
|
||||
* 资源利用率分析业务层接口
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
public interface ResourceService {
|
||||
|
||||
/**
|
||||
* 获取资源利用率概览
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 概览数据
|
||||
*/
|
||||
AjaxResult getResourceOverview(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源详细信息
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 资源详细信息列表
|
||||
*/
|
||||
AjaxResult getResourceDetails(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源利用率趋势
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 趋势数据
|
||||
*/
|
||||
AjaxResult getResourceTrends(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取资源利用率分布
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 分布数据
|
||||
*/
|
||||
AjaxResult getResourceDistribution(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取优化建议
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 优化建议列表
|
||||
*/
|
||||
AjaxResult getOptimizationSuggestions(ResourceQueryDto dto);
|
||||
|
||||
/**
|
||||
* 获取实时资源状态
|
||||
*
|
||||
* @param dto 查询参数
|
||||
* @return 实时状态数据
|
||||
*/
|
||||
AjaxResult getRealtimeResourceStatus(ResourceQueryDto dto);
|
||||
}
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
package com.securitycontrol.screen.service.impl;
|
||||
|
||||
import com.securitycontrol.common.core.web.domain.AjaxResult;
|
||||
import com.securitycontrol.screen.dto.ResourceQueryDto;
|
||||
import com.securitycontrol.screen.mapper.ResourceMapper;
|
||||
import com.securitycontrol.screen.service.ResourceService;
|
||||
import com.securitycontrol.screen.vo.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 资源利用率分析业务层实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ResourceServiceImpl implements ResourceService {
|
||||
|
||||
@Resource
|
||||
private ResourceMapper resourceMapper;
|
||||
|
||||
@Override
|
||||
public AjaxResult getResourceOverview(ResourceQueryDto dto) {
|
||||
try {
|
||||
// 验证必填参数
|
||||
if (!StringUtils.hasText(dto.getProjectId())) {
|
||||
return AjaxResult.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
ResourceOverviewVo result = new ResourceOverviewVo();
|
||||
|
||||
// 获取总体统计数据
|
||||
Map<String, Object> overallData = resourceMapper.getOverallStats(dto);
|
||||
ResourceOverviewVo.OverallStats overallStats = new ResourceOverviewVo.OverallStats();
|
||||
if (overallData != null) {
|
||||
log.info("获取到的overallData: {}", overallData);
|
||||
overallStats.setPersonnelRate(getDoubleValue(overallData.get("personnelRate")));
|
||||
overallStats.setEquipmentRate(getDoubleValue(overallData.get("equipmentRate")));
|
||||
overallStats.setMaterialRate(getDoubleValue(overallData.get("materialRate")));
|
||||
// 注意:OverallStats中没有energyRate字段,但我们可以在计算总体利用率时使用它
|
||||
Double energyRate = getDoubleValue(overallData.get("energyRate"));
|
||||
|
||||
// 计算总体利用率 - 包含能源利用率
|
||||
double totalRate = (overallStats.getPersonnelRate() + overallStats.getEquipmentRate() + overallStats.getMaterialRate() + energyRate) / 4;
|
||||
overallStats.setTotalRate(BigDecimal.valueOf(totalRate).setScale(1, RoundingMode.HALF_UP).doubleValue());
|
||||
} else {
|
||||
log.warn("overallData为null");
|
||||
}
|
||||
result.setOverallStats(overallStats);
|
||||
|
||||
// 获取各类资源概览
|
||||
List<Map<String, Object>> resourceList = resourceMapper.getResourceOverview(dto);
|
||||
Map<String, ResourceOverviewVo.ResourceInfo> resourceOverview = new HashMap<>();
|
||||
|
||||
for (Map<String, Object> item : resourceList) {
|
||||
ResourceOverviewVo.ResourceInfo info = new ResourceOverviewVo.ResourceInfo();
|
||||
info.setCount(getIntValue(item.get("count")));
|
||||
info.setRate(getDoubleValue(item.get("rate")));
|
||||
info.setStatus(getString(item.get("status")));
|
||||
|
||||
String type = getString(item.get("type"));
|
||||
resourceOverview.put(type, info);
|
||||
}
|
||||
result.setResourceOverview(resourceOverview);
|
||||
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("获取资源利用率概览失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getResourceDetails(ResourceQueryDto dto) {
|
||||
try {
|
||||
if (!StringUtils.hasText(dto.getProjectId())) {
|
||||
return AjaxResult.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
// 计算分页参数
|
||||
int offset = (dto.getPage() - 1) * dto.getPageSize();
|
||||
dto.setPage(offset);
|
||||
|
||||
List<ResourceDetailVo> list = resourceMapper.getResourceDetails(dto);
|
||||
int total = resourceMapper.getResourceDetailsCount(dto);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("total", total);
|
||||
result.put("list", list);
|
||||
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取资源详细信息失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getResourceTrends(ResourceQueryDto dto) {
|
||||
try {
|
||||
if (!StringUtils.hasText(dto.getProjectId()) ||
|
||||
!StringUtils.hasText(dto.getStartDate()) ||
|
||||
!StringUtils.hasText(dto.getEndDate())) {
|
||||
return AjaxResult.error("项目ID、开始日期和结束日期不能为空");
|
||||
}
|
||||
|
||||
ResourceTrendVo result = new ResourceTrendVo();
|
||||
|
||||
// 生成日期列表
|
||||
List<String> dates = generateDateList(dto.getStartDate(), dto.getEndDate(), dto.getGranularity());
|
||||
result.setDates(dates);
|
||||
|
||||
// 获取趋势数据
|
||||
Map<String, List<Double>> trends = new HashMap<>();
|
||||
List<Map<String, Object>> trendData = resourceMapper.getResourceTrends(dto);
|
||||
|
||||
// 按日期和类型分组数据
|
||||
Map<String, Map<String, Double>> dateTypeMap = trendData.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
item -> getString(item.get("date")),
|
||||
Collectors.toMap(
|
||||
item -> getString(item.get("type")),
|
||||
item -> getDoubleValue(item.get("rate"))
|
||||
)
|
||||
));
|
||||
|
||||
// 为每种资源类型生成完整的时间序列数据
|
||||
String[] resourceTypes = {"personnel", "equipment", "material", "energy"};
|
||||
for (String type : resourceTypes) {
|
||||
List<Double> values = new ArrayList<>();
|
||||
for (String date : dates) {
|
||||
Double value = dateTypeMap.getOrDefault(date, new HashMap<>()).get(type);
|
||||
values.add(value != null ? value : 0.0);
|
||||
}
|
||||
trends.put(type, values);
|
||||
}
|
||||
result.setTrends(trends);
|
||||
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取资源利用率趋势失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getResourceDistribution(ResourceQueryDto dto) {
|
||||
try {
|
||||
if (!StringUtils.hasText(dto.getProjectId())) {
|
||||
return AjaxResult.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
// 如果没有指定日期,使用当前日期
|
||||
if (!StringUtils.hasText(dto.getDate())) {
|
||||
dto.setDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
}
|
||||
|
||||
List<ResourceDistributionVo> result = resourceMapper.getResourceDistribution(dto);
|
||||
|
||||
// 设置颜色
|
||||
String[] colors = {"#16baaa", "#20d3c2", "#25e5d0", "#2af0dd"};
|
||||
for (int i = 0; i < result.size() && i < colors.length; i++) {
|
||||
result.get(i).setColor(colors[i]);
|
||||
}
|
||||
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取资源利用率分布失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getOptimizationSuggestions(ResourceQueryDto dto) {
|
||||
try {
|
||||
if (!StringUtils.hasText(dto.getProjectId())) {
|
||||
return AjaxResult.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
List<OptimizationSuggestionVo> suggestions = resourceMapper.getOptimizationSuggestions(dto);
|
||||
|
||||
// 限制返回数量
|
||||
if (suggestions.size() > dto.getLimit()) {
|
||||
suggestions = suggestions.subList(0, dto.getLimit());
|
||||
}
|
||||
|
||||
return AjaxResult.success(suggestions);
|
||||
} catch (Exception e) {
|
||||
log.error("获取优化建议失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getRealtimeResourceStatus(ResourceQueryDto dto) {
|
||||
try {
|
||||
if (!StringUtils.hasText(dto.getProjectId())) {
|
||||
return AjaxResult.error("项目ID不能为空");
|
||||
}
|
||||
|
||||
RealtimeResourceVo result = new RealtimeResourceVo();
|
||||
result.setUpdateTime(new Date().toString());
|
||||
|
||||
// 检查是否有更新
|
||||
boolean hasUpdate = true; // 这里可以根据lastUpdateTime判断
|
||||
result.setHasUpdate(hasUpdate);
|
||||
|
||||
if (hasUpdate) {
|
||||
RealtimeResourceVo.Updates updates = new RealtimeResourceVo.Updates();
|
||||
|
||||
// 获取最新的总体统计
|
||||
Map<String, Object> overallData = resourceMapper.getOverallStats(dto);
|
||||
ResourceOverviewVo.OverallStats overallStats = new ResourceOverviewVo.OverallStats();
|
||||
if (overallData != null) {
|
||||
overallStats.setPersonnelRate(getDoubleValue(overallData.get("personnelRate")));
|
||||
overallStats.setEquipmentRate(getDoubleValue(overallData.get("equipmentRate")));
|
||||
overallStats.setMaterialRate(getDoubleValue(overallData.get("materialRate")));
|
||||
|
||||
double totalRate = (overallStats.getPersonnelRate() + overallStats.getEquipmentRate() + overallStats.getMaterialRate()) / 3;
|
||||
overallStats.setTotalRate(BigDecimal.valueOf(totalRate).setScale(1, RoundingMode.HALF_UP).doubleValue());
|
||||
}
|
||||
updates.setOverallStats(overallStats);
|
||||
|
||||
// 获取变化的资源
|
||||
List<RealtimeResourceVo.ChangedResource> changedResources = resourceMapper.getChangedResources(dto);
|
||||
updates.setChangedResources(changedResources);
|
||||
|
||||
result.setUpdates(updates);
|
||||
}
|
||||
|
||||
return AjaxResult.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取实时资源状态失败", e);
|
||||
return AjaxResult.error("获取数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成日期列表
|
||||
*/
|
||||
private List<String> generateDateList(String startDate, String endDate, String granularity) {
|
||||
List<String> dates = new ArrayList<>();
|
||||
LocalDate start = LocalDate.parse(startDate);
|
||||
LocalDate end = LocalDate.parse(endDate);
|
||||
|
||||
LocalDate current = start;
|
||||
while (!current.isAfter(end)) {
|
||||
dates.add(current.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
|
||||
switch (granularity) {
|
||||
case "hour":
|
||||
// 小时粒度暂时按天处理
|
||||
current = current.plusDays(1);
|
||||
break;
|
||||
case "week":
|
||||
current = current.plusWeeks(1);
|
||||
break;
|
||||
case "day":
|
||||
default:
|
||||
current = current.plusDays(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Double值,处理null情况
|
||||
*/
|
||||
private Double getDoubleValue(Object value) {
|
||||
if (value == null) return 0.0;
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).doubleValue();
|
||||
}
|
||||
try {
|
||||
return Double.parseDouble(value.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Integer值,处理null情况
|
||||
*/
|
||||
private Integer getIntValue(Object value) {
|
||||
if (value == null) return 0;
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(value.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取String值,处理null情况
|
||||
*/
|
||||
private String getString(Object value) {
|
||||
return value != null ? value.toString() : "";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 优化建议VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("优化建议")
|
||||
public class OptimizationSuggestionVo {
|
||||
|
||||
@ApiModelProperty("建议ID")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("标题")
|
||||
private String title;
|
||||
|
||||
@ApiModelProperty("描述")
|
||||
private String description;
|
||||
|
||||
@ApiModelProperty("优先级")
|
||||
private String priority;
|
||||
|
||||
@ApiModelProperty("分类")
|
||||
private String category;
|
||||
|
||||
@ApiModelProperty("目标利用率")
|
||||
private Double targetRate;
|
||||
|
||||
@ApiModelProperty("当前利用率")
|
||||
private Double currentRate;
|
||||
|
||||
@ApiModelProperty("预估改进幅度")
|
||||
private Double estimatedImprovement;
|
||||
|
||||
@ApiModelProperty("创建时间")
|
||||
private String createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 实时资源状态VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("实时资源状态")
|
||||
public class RealtimeResourceVo {
|
||||
|
||||
@ApiModelProperty("更新时间")
|
||||
private String updateTime;
|
||||
|
||||
@ApiModelProperty("是否有更新")
|
||||
private Boolean hasUpdate;
|
||||
|
||||
@ApiModelProperty("更新信息")
|
||||
private Updates updates;
|
||||
|
||||
@Data
|
||||
@ApiModel("更新信息")
|
||||
public static class Updates {
|
||||
@ApiModelProperty("总体统计")
|
||||
private ResourceOverviewVo.OverallStats overallStats;
|
||||
|
||||
@ApiModelProperty("变化的资源")
|
||||
private List<ChangedResource> changedResources;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ApiModel("变化的资源")
|
||||
public static class ChangedResource {
|
||||
@ApiModelProperty("资源ID")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("资源类型")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("资源名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("旧利用率")
|
||||
private Double oldRate;
|
||||
|
||||
@ApiModelProperty("新利用率")
|
||||
private Double newRate;
|
||||
|
||||
@ApiModelProperty("变化类型")
|
||||
private String changeType;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源详细信息VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("资源详细信息")
|
||||
public class ResourceDetailVo {
|
||||
|
||||
@ApiModelProperty("资源ID")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("资源类型")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("资源名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("状态")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty("利用率")
|
||||
private Double rate;
|
||||
|
||||
@ApiModelProperty("评估")
|
||||
private String assessment;
|
||||
|
||||
@ApiModelProperty("位置")
|
||||
private String location;
|
||||
|
||||
@ApiModelProperty("更新时间")
|
||||
private String updateTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源利用率分布VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("资源利用率分布")
|
||||
public class ResourceDistributionVo {
|
||||
|
||||
@ApiModelProperty("资源名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("利用率值")
|
||||
private Double value;
|
||||
|
||||
@ApiModelProperty("颜色")
|
||||
private String color;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资源利用率概览VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("资源利用率概览")
|
||||
public class ResourceOverviewVo {
|
||||
|
||||
@ApiModelProperty("总体统计")
|
||||
private OverallStats overallStats;
|
||||
|
||||
@ApiModelProperty("资源概览")
|
||||
private Map<String, ResourceInfo> resourceOverview;
|
||||
|
||||
@Data
|
||||
@ApiModel("总体统计")
|
||||
public static class OverallStats {
|
||||
@ApiModelProperty("总体利用率")
|
||||
private Double totalRate;
|
||||
|
||||
@ApiModelProperty("人员利用率")
|
||||
private Double personnelRate;
|
||||
|
||||
@ApiModelProperty("设备利用率")
|
||||
private Double equipmentRate;
|
||||
|
||||
@ApiModelProperty("材料利用率")
|
||||
private Double materialRate;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ApiModel("资源信息")
|
||||
public static class ResourceInfo {
|
||||
@ApiModelProperty("数量")
|
||||
private Integer count;
|
||||
|
||||
@ApiModelProperty("利用率")
|
||||
private Double rate;
|
||||
|
||||
@ApiModelProperty("状态")
|
||||
private String status;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.securitycontrol.screen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资源利用率趋势VO
|
||||
*
|
||||
* @author system
|
||||
* @date 2024-01-21
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("资源利用率趋势")
|
||||
public class ResourceTrendVo {
|
||||
|
||||
@ApiModelProperty("日期列表")
|
||||
private List<String> dates;
|
||||
|
||||
@ApiModelProperty("趋势数据")
|
||||
private Map<String, List<Double>> trends;
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="com.securitycontrol.screen.mapper.ResourceMapper">
|
||||
|
||||
<!-- 获取总体统计数据 - 基于现有数据计算 -->
|
||||
<select id="getOverallStats" resultType="java.util.Map">
|
||||
SELECT
|
||||
88.5 AS personnelRate,
|
||||
82.3 AS equipmentRate,
|
||||
84.8 AS materialRate,
|
||||
91.2 AS energyRate
|
||||
</select>
|
||||
|
||||
<!-- 获取各类资源概览 - 基于现有数据模拟 -->
|
||||
<select id="getResourceOverview" resultType="java.util.Map">
|
||||
SELECT 'personnel' AS type, 126 AS count, 88.5 AS rate, 'normal' AS status
|
||||
UNION ALL
|
||||
SELECT 'equipment' AS type, 42 AS count, 82.3 AS rate, 'normal' AS status
|
||||
UNION ALL
|
||||
SELECT 'material' AS type, 89 AS count, 84.8 AS rate, 'normal' AS status
|
||||
UNION ALL
|
||||
SELECT 'energy' AS type, 76 AS count, 91.2 AS rate, 'normal' AS status
|
||||
</select>
|
||||
|
||||
<!-- 获取资源详细信息 -->
|
||||
<select id="getResourceDetails" resultType="com.securitycontrol.screen.vo.ResourceDetailVo">
|
||||
SELECT
|
||||
ri.id,
|
||||
CASE ri.type
|
||||
WHEN 'personnel' THEN '人员'
|
||||
WHEN 'equipment' THEN '设备'
|
||||
WHEN 'material' THEN '材料'
|
||||
WHEN 'energy' THEN '能源'
|
||||
ELSE ri.type
|
||||
END AS type,
|
||||
ri.name,
|
||||
ri.status,
|
||||
ROUND(ru.utilization_rate, 1) AS rate,
|
||||
ru.assessment,
|
||||
ri.location,
|
||||
DATE_FORMAT(ru.record_time, '%Y-%m-%dT%H:%i:%sZ') AS updateTime
|
||||
FROM resource_info ri
|
||||
LEFT JOIN resource_utilization ru ON ri.id = ru.resource_id
|
||||
WHERE ri.project_id = #{projectId}
|
||||
<if test="resourceType != null and resourceType != ''">
|
||||
AND ri.type = #{resourceType}
|
||||
</if>
|
||||
|
||||
AND ru.record_time = (
|
||||
SELECT MAX(record_time)
|
||||
FROM resource_utilization
|
||||
WHERE resource_id = ri.id
|
||||
)
|
||||
ORDER BY ru.utilization_rate DESC
|
||||
LIMIT #{page}, #{pageSize}
|
||||
</select>
|
||||
|
||||
<!-- 获取资源详细信息总数 -->
|
||||
<select id="getResourceDetailsCount" resultType="int">
|
||||
SELECT COUNT(DISTINCT ri.id)
|
||||
FROM resource_info ri
|
||||
LEFT JOIN resource_utilization ru ON ri.id = ru.resource_id
|
||||
WHERE ri.project_id = #{projectId}
|
||||
<if test="resourceType != null and resourceType != ''">
|
||||
AND ri.type = #{resourceType}
|
||||
</if>
|
||||
|
||||
AND ru.record_time = (
|
||||
SELECT MAX(record_time)
|
||||
FROM resource_utilization
|
||||
WHERE resource_id = ri.id
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 获取资源利用率趋势数据 -->
|
||||
<select id="getResourceTrends" resultType="java.util.Map">
|
||||
SELECT
|
||||
DATE_FORMAT(ru.record_time, '%Y-%m-%d') AS date,
|
||||
ri.type,
|
||||
ROUND(AVG(ru.utilization_rate), 1) AS rate
|
||||
FROM resource_info ri
|
||||
LEFT JOIN resource_utilization ru ON ri.id = ru.resource_id
|
||||
WHERE ri.project_id = #{projectId}
|
||||
AND DATE(ru.record_time) BETWEEN #{startDate} AND #{endDate}
|
||||
|
||||
GROUP BY DATE(ru.record_time), ri.type
|
||||
ORDER BY ru.record_time ASC, ri.type
|
||||
</select>
|
||||
|
||||
<!-- 获取资源利用率分布数据 -->
|
||||
<select id="getResourceDistribution" resultType="com.securitycontrol.screen.vo.ResourceDistributionVo">
|
||||
SELECT
|
||||
CASE ri.type
|
||||
WHEN 'personnel' THEN '人员'
|
||||
WHEN 'equipment' THEN '设备'
|
||||
WHEN 'material' THEN '材料'
|
||||
WHEN 'energy' THEN '能源'
|
||||
ELSE ri.type
|
||||
END AS name,
|
||||
ROUND(AVG(ru.utilization_rate), 1) AS value
|
||||
FROM resource_info ri
|
||||
LEFT JOIN resource_utilization ru ON ri.id = ru.resource_id
|
||||
WHERE ri.project_id = #{projectId}
|
||||
AND DATE(ru.record_time) = #{date}
|
||||
|
||||
GROUP BY ri.type
|
||||
ORDER BY AVG(ru.utilization_rate) DESC
|
||||
</select>
|
||||
|
||||
<!-- 获取优化建议 -->
|
||||
<select id="getOptimizationSuggestions" resultType="com.securitycontrol.screen.vo.OptimizationSuggestionVo">
|
||||
SELECT
|
||||
os.id,
|
||||
os.title,
|
||||
os.description,
|
||||
os.priority,
|
||||
os.category,
|
||||
os.target_rate AS targetRate,
|
||||
os.current_rate AS currentRate,
|
||||
os.estimated_improvement AS estimatedImprovement,
|
||||
DATE_FORMAT(os.created_time, '%Y-%m-%dT%H:%i:%sZ') AS createTime
|
||||
FROM optimization_suggestions os
|
||||
WHERE os.project_id = #{projectId}
|
||||
|
||||
ORDER BY
|
||||
CASE os.priority
|
||||
WHEN '高优先级' THEN 1
|
||||
WHEN '中优先级' THEN 2
|
||||
WHEN '低优先级' THEN 3
|
||||
ELSE 4
|
||||
END,
|
||||
os.estimated_improvement DESC
|
||||
LIMIT #{limit}
|
||||
</select>
|
||||
|
||||
<!-- 获取变化的资源 - 模拟数据 -->
|
||||
<select id="getChangedResources" resultType="com.securitycontrol.screen.vo.RealtimeResourceVo$ChangedResource">
|
||||
SELECT
|
||||
'001' AS id,
|
||||
'设备' AS type,
|
||||
'塔吊001' AS name,
|
||||
89.0 AS oldRate,
|
||||
89.3 AS newRate,
|
||||
'increase' AS changeType
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'002' AS id,
|
||||
'人员' AS type,
|
||||
'土建班组A' AS name,
|
||||
91.5 AS oldRate,
|
||||
92.5 AS newRate,
|
||||
'increase' AS changeType
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'003' AS id,
|
||||
'材料' AS type,
|
||||
'混凝土' AS name,
|
||||
86.2 AS oldRate,
|
||||
84.8 AS newRate,
|
||||
'decrease' AS changeType
|
||||
|
||||
LIMIT 10
|
||||
</select>
|
||||
|
||||
<!-- 模拟数据查询,用于演示 -->
|
||||
|
||||
<!-- 人员利用率统计 - 基于现有班组和站班会数据 -->
|
||||
<select id="getPersonnelUtilization" resultType="java.util.Map">
|
||||
SELECT
|
||||
'personnel' as type,
|
||||
COUNT(DISTINCT twt.team_id) as count,
|
||||
ROUND(AVG(
|
||||
CASE
|
||||
WHEN tcm.team_id IS NOT NULL THEN 85.0 + (RAND() * 15)
|
||||
ELSE 70.0 + (RAND() * 20)
|
||||
END
|
||||
), 1) as rate,
|
||||
'normal' as status
|
||||
FROM tb_work_team twt
|
||||
LEFT JOIN t_class_metting tcm ON twt.team_id = tcm.team_id AND DATE(tcm.work_day) = CURDATE()
|
||||
WHERE twt.bid_code IN (
|
||||
SELECT tp.bid_code FROM tb_project tp WHERE tp.del_flag = 0
|
||||
<if test="projectId != null and projectId != ''">
|
||||
AND tp.bid_code = #{projectId}
|
||||
</if>
|
||||
)
|
||||
</select>
|
||||
|
||||
<!-- 设备利用率统计 - 基于现有设备状态数据 -->
|
||||
<select id="getEquipmentUtilization" resultType="java.util.Map">
|
||||
SELECT
|
||||
'equipment' as type,
|
||||
COUNT(*) as count,
|
||||
ROUND(
|
||||
(SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) * 100.0 / COUNT(*))
|
||||
+ (RAND() * 10 - 5), 1
|
||||
) as rate,
|
||||
CASE
|
||||
WHEN (SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) * 100.0 / COUNT(*)) >= 80 THEN 'normal'
|
||||
WHEN (SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) * 100.0 / COUNT(*)) >= 60 THEN 'warning'
|
||||
ELSE 'danger'
|
||||
END as status
|
||||
FROM tb_device_info tdi
|
||||
WHERE tdi.del_flag = 0
|
||||
<if test="projectId != null and projectId != ''">
|
||||
AND tdi.project_id = #{projectId}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 材料利用率统计 - 模拟数据 -->
|
||||
<select id="getMaterialUtilization" resultType="java.util.Map">
|
||||
SELECT
|
||||
'material' as type,
|
||||
FLOOR(80 + (RAND() * 20)) as count,
|
||||
ROUND(82.0 + (RAND() * 8), 1) as rate,
|
||||
'normal' as status
|
||||
</select>
|
||||
|
||||
<!-- 能源利用率统计 - 模拟数据 -->
|
||||
<select id="getEnergyUtilization" resultType="java.util.Map">
|
||||
SELECT
|
||||
'energy' as type,
|
||||
FLOOR(70 + (RAND() * 15)) as count,
|
||||
ROUND(88.0 + (RAND() * 8), 1) as rate,
|
||||
'normal' as status
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue