ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.R; import com.ruoyi.system.dto.EditHiddenDangerResponsiblePersonDto; import com.ruoyi.system.enums.DeviceType; import com.ruoyi.system.model.*; import com.ruoyi.system.model.Record; import com.ruoyi.system.query.*; @@ -21,6 +22,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -73,7 +75,7 @@ List<String> properties = deviceUsageService.getDeviceUsageList(id); projectVo.setProperties( properties); ProjectInfo projectInfo = projectInfoService.getOne(new LambdaUpdateWrapper<ProjectInfo>().eq(ProjectInfo::getProjectId, id)); ProjectInfo projectInfo = projectInfoService.getOne(new LambdaUpdateWrapper<ProjectInfo>().eq(ProjectInfo::getProjectId, id).eq(ProjectInfo::getDeleted,false).orderByDesc(ProjectInfo::getCreateTime).last("limit 1")); if(projectInfo!=null){ projectVo.setProgress(projectInfo.getProgress()); } @@ -242,4 +244,68 @@ return R.ok(vo); } @ApiOperation(value = "获取项目大屏最新重大风险源",response = ProjectInfo.class) @GetMapping("/getProjectDangerousSource") public R<ProjectInfo> getProjectDangerousSource(@RequestParam Integer projectId) { ProjectInfo projectInfo = projectInfoService.getOne(new LambdaQueryWrapper<ProjectInfo>().eq(ProjectInfo::getProjectId,projectId).eq(ProjectInfo::getDeleted, false).orderByDesc(ProjectInfo::getCreateTime).last("limit 1")); return R.ok(projectInfo); } @ApiOperation(value = "获取项目重大风险源列表") @PostMapping("/getProjectDangerousSourceList") public R<Page<ProjectInfo>> getProjectDangerousSourceList(@RequestBody @Valid ProjectDangerousSourceListQuery query) { Page<ProjectInfo> page = new Page<>(query.getPageNum(), query.getPageSize()); LambdaQueryWrapper<ProjectInfo> wrapper = new LambdaQueryWrapper<ProjectInfo>().eq(ProjectInfo::getProjectId, query.getProjectId()).eq(ProjectInfo::getDeleted, false); if(query.getStartTime()!=null && !query.getStartTime().isEmpty()){ wrapper.ge(ProjectInfo::getCreateTime, query.getStartTime()); } if(query.getEndTime()!=null && !query.getEndTime().isEmpty()){ wrapper.le(ProjectInfo::getCreateTime, query.getEndTime()); } if(query.getContent()!=null && !query.getContent().isEmpty()){ wrapper.like(ProjectInfo::getDetail, query.getContent()); } Page<ProjectInfo> list = projectInfoService.page(page,wrapper); return R.ok(list); } @ApiOperation(value = "设备类型") @GetMapping("/deviceTypes") public R<?> deviceTypeOptions(@RequestParam(value = "title", required = false) String title) { return R.ok(SelectOptionVo.buildOptions(title, DeviceType.values())); } @ApiOperation(value = "各分项隐患趋势") @GetMapping("/getProjectHiddenDangerTrend") public R<List<ProjectHiddenDangerTrendVo>> getProjectHiddenDangerTrend(@RequestParam Integer projectId,@RequestParam(value = "desc", required = true) Boolean desc,@RequestParam(value = "type", required = true)Integer type) { List<ProjectHiddenDangerTrendVo> list = projectInfoService.getProjectHiddenDangerTrend(projectId); if(type==1){ if(desc){ list = list.stream().sorted(Comparator.comparingInt(ProjectHiddenDangerTrendVo::getThisMonth).reversed()).toList(); }else { list = list.stream().sorted(Comparator.comparingInt(ProjectHiddenDangerTrendVo::getThisMonth)).toList(); } }else { if(desc){ list = list.stream().sorted(Comparator.comparingDouble(ProjectHiddenDangerTrendVo::getRate).reversed()).toList(); }else { list = list.stream().sorted(Comparator.comparingDouble(ProjectHiddenDangerTrendVo::getRate)).toList(); } } return R.ok(list); } @ApiOperation(value = "各分项隐患趋势列表") @PostMapping("/getProjectHiddenDangerTrendList") public R<List<ProjectHiddenDangerList>> getProjectHiddenDangerTrendList(@RequestBody @Valid ProjectHiddenDangerTrendListQuery query) { List<ProjectHiddenDangerList> list = projectInfoService.getProjectHiddenDangerTrendList(query); return R.ok(list); } } ruoyi-system/src/main/java/com/ruoyi/system/enums/DeviceType.java
New file @@ -0,0 +1,70 @@ package com.ruoyi.system.enums; import com.ruoyi.system.service.IOptionVo; import lombok.Getter; @Getter public enum DeviceType implements IOptionVo { TOWER_CRANE("塔式起重机"), CONSTRUCTION_LIFT("施工升降机"), MATERIAL_HOIST("物料提升机"), BRIDGE_CRANE("桥式起重机"), SUSPENDED_SCAFFOLDING("附着式升降脚手架"), MOBILE_CRANE("流动式起重机"), HIGH_ALTITUDE_BASKET("高处作业吊篮"), GANTRY_CRANE("门式起重机"), GANTRY_TROLLEY_CRANE("架桥机"), OTHER("其他类型"); private final String desc; DeviceType(String desc) { this.desc = desc; } public static DeviceType getByDescription(String description) { for (DeviceType deviceType : DeviceType.values()) { if (deviceType.desc.equals(description)) { return deviceType; } } return null; } @Override public String getOptionCode() { return name(); } @Override public String getOptionName() { return desc; } public String hierarchyPath() { switch (this) { case TOWER_CRANE: return "/0"; case CONSTRUCTION_LIFT: return "/1"; case MATERIAL_HOIST: return "/5"; case BRIDGE_CRANE: return "/3"; case SUSPENDED_SCAFFOLDING: return "/7"; case MOBILE_CRANE: return "/4"; case HIGH_ALTITUDE_BASKET: return "/8"; case GANTRY_CRANE: return "/6"; case GANTRY_TROLLEY_CRANE: return "/2"; case OTHER: default: return "/"; } } } ruoyi-system/src/main/java/com/ruoyi/system/mapper/ProjectInfoMapper.java
@@ -2,6 +2,10 @@ import com.ruoyi.system.model.ProjectInfo; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.Record; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> @@ -13,4 +17,6 @@ */ public interface ProjectInfoMapper extends BaseMapper<ProjectInfo> { List<Record> getProjectHiddenDangerTrend(@Param("projectId") Integer projectId, @Param("startTime") String startTime, @Param("endTime") String endTime); } ruoyi-system/src/main/java/com/ruoyi/system/model/ProjectInfo.java
@@ -44,6 +44,7 @@ private LocalDateTime updateTime; @TableField("dangerous_options") @ApiModelProperty(value = "危大工程") private String dangerousOptions; @TableField("detail") @@ -56,6 +57,7 @@ private String progressThisSeason; @TableField("super_dangerous_options") @ApiModelProperty(value = "超危大工程") private String superDangerousOptions; @ApiModelProperty(value = "风险源") ruoyi-system/src/main/java/com/ruoyi/system/model/Record.java
@@ -10,6 +10,7 @@ import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Date; /** @@ -32,7 +33,7 @@ @TableId(value = "id", type = IdType.AUTO) private Integer id; @TableField("create_time") private Date createTime; private LocalDateTime createTime; private Boolean deleted; private String name; @TableField("update_time") ruoyi-system/src/main/java/com/ruoyi/system/model/SelectOptionVo.java
New file @@ -0,0 +1,46 @@ package com.ruoyi.system.model; import com.ruoyi.system.service.IOptionVo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * @ClassName SelectOptionBo * @Description * @Author daisyli * @Date 2023/9/11 **/ @Data @NoArgsConstructor @AllArgsConstructor @ApiModel(value = "下拉框选项") public class SelectOptionVo { @ApiModelProperty(value = "编码") String code; @ApiModelProperty(value = "名称") String name; public static <T> List<SelectOptionVo> buildOptions(String title, T[] list) { return buildOptions(title, Arrays.asList(list)); } public static <T> List<SelectOptionVo> buildOptions(String title, List<T> list) { List<SelectOptionVo> data = list.stream().map(item -> new SelectOptionVo(((IOptionVo)item).getOptionCode(), ((IOptionVo)item).getOptionName())).collect(Collectors.toList()); if(StringUtils.isNotBlank(title)) data.add(0, new SelectOptionVo("", title)); return data; } } ruoyi-system/src/main/java/com/ruoyi/system/query/ProjectDangerousSourceListQuery.java
New file @@ -0,0 +1,25 @@ package com.ruoyi.system.query; import com.ruoyi.common.core.domain.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; @Data @ApiModel("项目大屏最新重大风险源列表查询参数") public class ProjectDangerousSourceListQuery extends BasePage { @ApiModelProperty("项目id") @NotNull(message = "项目id不能为空") private Integer projectId; @ApiModelProperty("开始时间") private String startTime; @ApiModelProperty("结束时间") private String endTime; @ApiModelProperty("搜索内容") private String content; } ruoyi-system/src/main/java/com/ruoyi/system/query/ProjectHiddenDangerTrendListQuery.java
New file @@ -0,0 +1,29 @@ package com.ruoyi.system.query; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data @ApiModel("项目隐患趋势列表查询参数") public class ProjectHiddenDangerTrendListQuery { @ApiModelProperty("项目id") @NotNull(message = "项目id不能为空") private Integer projectId; @ApiModelProperty("开始时间") @NotBlank(message = "开始时间不能为空") private String startTime; @ApiModelProperty("结束时间") @NotBlank(message = "结束时间不能为空") private String endTime; @ApiModelProperty("内容") private String content; } ruoyi-system/src/main/java/com/ruoyi/system/service/IOptionVo.java
New file @@ -0,0 +1,17 @@ package com.ruoyi.system.service; public interface IOptionVo { /** * 获取选项编码 * @return */ String getOptionCode(); /** * 获取选项名称 * @return */ String getOptionName(); } ruoyi-system/src/main/java/com/ruoyi/system/service/ProjectInfoService.java
@@ -2,6 +2,12 @@ import com.ruoyi.system.model.ProjectInfo; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.query.ProjectHiddenDangerTrendListQuery; import com.ruoyi.system.vo.ProjectHiddenDangerList; import com.ruoyi.system.vo.ProjectHiddenDangerTrendVo; import javax.validation.Valid; import java.util.List; /** * <p> @@ -13,4 +19,8 @@ */ public interface ProjectInfoService extends IService<ProjectInfo> { List<ProjectHiddenDangerTrendVo> getProjectHiddenDangerTrend(Integer projectId); List<ProjectHiddenDangerList> getProjectHiddenDangerTrendList(@Valid ProjectHiddenDangerTrendListQuery query); } ruoyi-system/src/main/java/com/ruoyi/system/service/RecordService.java
@@ -27,4 +27,6 @@ ProblemVo getHiddenDangerDetail(Integer problemId); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ProjectInfoServiceImpl.java
@@ -1,10 +1,33 @@ package com.ruoyi.system.service.impl; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson2.JSONArray; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.system.model.ProjectInfo; import com.ruoyi.system.mapper.ProjectInfoMapper; import com.ruoyi.system.model.Record; import com.ruoyi.system.query.ProjectHiddenDangerTrendListQuery; import com.ruoyi.system.service.ProjectInfoService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.service.RecordService; import com.ruoyi.system.vo.ProjectHiddenDangerList; import com.ruoyi.system.vo.ProjectHiddenDangerNextList; import com.ruoyi.system.vo.ProjectHiddenDangerTrendVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.YearMonth; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; import java.util.Map; import static java.util.stream.Collectors.groupingBy; /** * <p> @@ -17,4 +40,133 @@ @Service public class ProjectInfoServiceImpl extends ServiceImpl<ProjectInfoMapper, ProjectInfo> implements ProjectInfoService { @Override public List<ProjectHiddenDangerTrendVo> getProjectHiddenDangerTrend(Integer projectId) { // 获取上月第一天的时间 LocalDate lastMonth = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()); List<Record> list = this.baseMapper.getProjectHiddenDangerTrend(projectId,lastMonth+" 00:00:00",LocalDate.now()+" 23:59:59"); for (Record record : list) { String hierarchyNames = record.getHierarchyNames(); JSONArray jsonArray = JSONArray.parseArray(hierarchyNames); // 取出倒数第4个 String name = jsonArray.getString(jsonArray.size()-4); record.setHierarchyName( name); } LocalDate thisMonth = LocalDate.now().minusMonths(0).with(TemporalAdjusters.firstDayOfMonth()); Map<String, List<Record>> map = list.stream().collect(groupingBy(Record::getHierarchyName)); List<ProjectHiddenDangerTrendVo> resultList = map.entrySet().stream().map(entry -> { ProjectHiddenDangerTrendVo vo = new ProjectHiddenDangerTrendVo(); vo.setName(entry.getKey()); List<Record> value = entry.getValue(); long count = value.stream().filter(record -> record.getCreateTime().isAfter(thisMonth.atStartOfDay())).count(); // 根据value集合中的createTime 选出本月的数据 vo.setThisMonth((int) count); vo.setLastMonth(value.size()-(int) count); int num = vo.getThisMonth() - vo.getLastMonth(); if (num != 0) { if(vo.getLastMonth()>0){ Double rate = BigDecimal.valueOf(num).divide(BigDecimal.valueOf(vo.getLastMonth()), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).doubleValue(); vo.setRate(rate); }else { vo.setRate(100.00d); } }else { vo.setRate(0.00d); } return vo; }).toList(); return resultList; } @Override public List<ProjectHiddenDangerList> getProjectHiddenDangerTrendList(ProjectHiddenDangerTrendListQuery query) { List<Record> list = this.baseMapper.getProjectHiddenDangerTrend(query.getProjectId(),getMonthBoundaries(query.getStartTime(),true)+" 00:00:00",getMonthBoundaries(query.getEndTime(),false)+" 23:59:59"); for (Record record : list) { String hierarchyNames = record.getHierarchyNames(); JSONArray jsonArray = JSONArray.parseArray(hierarchyNames); // 取出倒数第4个 String name = jsonArray.getString(jsonArray.size()-4); record.setHierarchyName( name); } // 算出跨度几个月 int months = calculateMonthsBetween(query.getStartTime(),query.getEndTime()); ArrayList<ProjectHiddenDangerList> projectHiddenDangerLists = new ArrayList<>(); Map<String, List<Record>> map = list.stream().collect(groupingBy(Record::getHierarchyName)); for (Map.Entry<String, List<Record>> stringListEntry : map.entrySet()) { String key = stringListEntry.getKey(); if(query.getContent()!=null && !query.getContent().isEmpty()){ if(!key.contains( query.getContent())){ continue; } } List<Record> value = stringListEntry.getValue(); ProjectHiddenDangerList projectHiddenDangerList1 = new ProjectHiddenDangerList(); projectHiddenDangerList1.setName(key); ArrayList<ProjectHiddenDangerNextList> projectHiddenDangerNextLists = new ArrayList<>(); for (int i = 0; i < months; i++) { ProjectHiddenDangerNextList projectHiddenDangerNextList = new ProjectHiddenDangerNextList(); LocalDate localDate = getMonthBoundaries(query.getStartTime(), true).plusMonths(i); String dateStr = localDate.toString().substring(0, 7); long count = value.stream().filter(record -> record.getCreateTime().toString().contains(dateStr)).count(); ProjectHiddenDangerList projectHiddenDangerList = new ProjectHiddenDangerList(); projectHiddenDangerList.setName(key); projectHiddenDangerNextList.setTime(dateStr); projectHiddenDangerNextList.setNum((int) count); projectHiddenDangerNextLists.add(projectHiddenDangerNextList); } projectHiddenDangerList1.setList(projectHiddenDangerNextLists); projectHiddenDangerLists.add(projectHiddenDangerList1); } return projectHiddenDangerLists; } public static LocalDate getMonthBoundaries(String yearMonthStr,boolean isInclusive) { // 解析字符串为YearMonth YearMonth yearMonth = YearMonth.parse(yearMonthStr); if(isInclusive){ // 获取第一天 LocalDate firstDay = yearMonth.atDay(1); return firstDay; }else { // 获取最后一天 LocalDate lastDay = yearMonth.atEndOfMonth(); return lastDay; } } public static int calculateMonthsBetween(String startYearMonth, String endYearMonth) { YearMonth start = YearMonth.parse(startYearMonth); YearMonth end = YearMonth.parse(endYearMonth); // 计算月份差 + 1(包含结束月份) return (int) ChronoUnit.MONTHS.between(start, end) + 1; } public static void main(String[] args) { LocalDate monthBoundaries = getMonthBoundaries("2025-03", true); System.out.println(monthBoundaries); System.out.println(getMonthBoundaries("2025-02",false)); System.out.println(calculateMonthsBetween("2025-03", "2026-01")); for (int count = 0; count < 11; count++) { // 根据2025-03 根据循环获取下一个月的时间 LocalDate monthBoundaries1 = getMonthBoundaries("2025-03", true).plusMonths(count); System.out.println(monthBoundaries1.toString().substring(0,7)); } } } ruoyi-system/src/main/java/com/ruoyi/system/vo/DeviceDetailCheckListVo.java
@@ -36,4 +36,10 @@ private Integer commentType=1; @ApiModelProperty("设备报告 1有 0无") private Integer containDeviceRes; @ApiModelProperty("安全报告 1有 0无") private Integer containSystemRes; } ruoyi-system/src/main/java/com/ruoyi/system/vo/ProjectHiddenDangerList.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.system.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data @ApiModel("项目隐患列表") public class ProjectHiddenDangerList { @ApiModelProperty("名称") private String name; @ApiModelProperty("数量集合") private List<ProjectHiddenDangerNextList> list; } ruoyi-system/src/main/java/com/ruoyi/system/vo/ProjectHiddenDangerNextList.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.system.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("项目隐患二级列表") public class ProjectHiddenDangerNextList { @ApiModelProperty("数量") private Integer num; @ApiModelProperty("时间") private String time; } ruoyi-system/src/main/java/com/ruoyi/system/vo/ProjectHiddenDangerTrendVo.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.system.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("项目各分享隐患趋势Vo") public class ProjectHiddenDangerTrendVo { @ApiModelProperty("隐患名称") private String name; @ApiModelProperty("本月数量") private Integer thisMonth; @ApiModelProperty("上月数量") private Integer lastMonth; @ApiModelProperty("环比趋势") private Double rate; } ruoyi-system/src/main/java/com/ruoyi/system/vo/ProjectVo.java
@@ -12,6 +12,7 @@ import java.util.Date; import java.util.List; @Data @ApiModel("项目信息") public class ProjectVo { ruoyi-system/src/main/resources/mapper/system/DeviceUsageMapper.xml
@@ -16,7 +16,7 @@ <result column="disabled" property="disabled" /> </resultMap> <select id="getDeviceUsageList" resultType="java.lang.String"> select t3.properties from device_usage t1 select t2.properties from device_usage t1 left join device t2 on t1.device_id = t2.id where t1.project_id =#{id} </select> @@ -52,7 +52,7 @@ from device t1 left join device_usage t2 on t1.id = t2.device_id where t2.project_id = #{projectId} and t2.deleted = 0 where t2.project_id = #{id} and t2.deleted = 0 group by t1.type </select> ruoyi-system/src/main/resources/mapper/system/ProjectInfoMapper.xml
@@ -26,5 +26,12 @@ <sql id="Base_Column_List"> id, create_time, deleted, name, update_time, dangerous_options, detail, progress, progress_this_season, super_dangerous_options, hazard_source, update_date, creator_id, check_task_id, project_id, hazard_source_types </sql> <select id="getProjectHiddenDangerTrend" resultType="com.ruoyi.system.model.Record" > select t2.id,t2.hierarchy_names,t2.create_time from task t1 left join record t2 on t1.id=t2.check_task_id where t1.project_id=#{projectId} and t1.deleted=0 and t2.create_time between #{startTime} and #{endTime} </select> </mapper> ruoyi-system/src/main/resources/mapper/system/ProjectMapper.xml
@@ -22,10 +22,11 @@ <result column="usage_type" property="usageType" /> <result column="creator_id" property="creatorId" /> <result column="client_id" property="clientId" /> <result column="premission" property="premission" /> <result column="permission" property="permission" /> </resultMap> <select id="getDeviceDetailCheckList" resultType="com.ruoyi.system.vo.DeviceDetailCheckListVo"> select t1.id,t2.name planName,t2.type planType,t1.date checkTime,t2.system_fuzzy fuzzyScore,t2.system_score score,t3.risk_level riskLevel select t1.id,t2.name planName,t2.type planType,t1.date checkTime,t1.system_fuzzy fuzzyScore,t1.system_score score,t3.risk_level riskLevel, t3.contain_device_res ,t3.contain_system_res from task t1 left join plan t2 on t1.plan_id = t2.id left join eval_result t3 on t1.id = t3.check_task_id ruoyi-system/src/main/resources/mapper/system/RecordMapper.xml
@@ -42,7 +42,7 @@ left join problem t2 on t1.problem_id = t2.id left join task t3 on t1.check_task_id = t3.id left join plan t4 on t3.plan_id = t4.id where t1.deleted = 0 where t1.deleted = 0 and t1.level is not null and t1.check_task_id in <foreach item="item" index="index" collection="taskIds" open="(" separator="," close=")"> #{item}