From 3abe9cbd0fcbd51f3a9049cfe286cd75735be4a7 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 23 一月 2026 16:02:32 +0800
Subject: [PATCH] fix:委托方大屏接口修改

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java             |   20 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/model/Device.java                             |   98 +++++++++++++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ClientServiceImpl.java           |  132 +++++++++++++------------
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DashboardStatisticsController.java |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/DeviceMapper.java                      |   19 +++
 ruoyi-system/src/main/java/com/ruoyi/system/model/ClientParam.java                        |   10 +
 ruoyi-system/src/main/java/com/ruoyi/system/vo/FixedAssetDashboardVO.java                 |    3 
 7 files changed, 214 insertions(+), 70 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DashboardStatisticsController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DashboardStatisticsController.java
index bf4ca17..0602436 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DashboardStatisticsController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DashboardStatisticsController.java
@@ -139,7 +139,7 @@
      * @return 统计数据
      */
     @PostMapping("/index")
-    @ApiOperation("获取委托方大屏首页统计数据")
+    @ApiOperation(value = "获取委托方大屏首页统计数据",tags = {"委托方端"})
     public R<ClientDashboardVO> index(@RequestBody ClientDashboardQuery query) {
         ClientDashboardVO dashboard = clientService.getClientDashboard(query);
         return R.ok(dashboard);
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java
index e05bdaf..2c3d23f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ProjectController.java
@@ -12,6 +12,8 @@
 import com.ruoyi.system.service.*;
 import com.ruoyi.system.vo.*;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -354,4 +356,22 @@
         return R.ok(list);
     }
 
+    @ApiOperation(value = "获取项目列表")
+    @GetMapping("/list")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "clientId", value = "委托方ID", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "projectName", value = "项目名称", dataType = "string", paramType = "query")
+    })
+    public R<List<Project>> getList(Integer clientId, String projectName) {
+        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<Project>().eq(Project::getDeleted, false);
+        if(clientId!=null){
+            wrapper.eq(Project::getClientId, clientId);
+        }
+        if(projectName!=null && !projectName.isEmpty()){
+            wrapper.like(Project::getName, projectName);
+        }
+        List<Project> list = projectService.list(wrapper);
+        return R.ok(list);
+
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DeviceMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DeviceMapper.java
new file mode 100644
index 0000000..e6c617c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DeviceMapper.java
@@ -0,0 +1,19 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.system.model.Device;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 设备 Mapper 接口
+ * </p>
+ *
+ * @author administrator
+ * @since 2026-01-22
+ */
+@Mapper
+public interface DeviceMapper extends BaseMapper<Device> {
+    // 继承 BaseMapper 提供基础 CRUD 方法
+    // 批量查询使用 selectBatchIds 方法
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/ClientParam.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/ClientParam.java
index efde24e..8f06b80 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/ClientParam.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/ClientParam.java
@@ -59,9 +59,13 @@
     @TableField("device_template_id")
     private Integer deviceTemplateId;
 
-    @ApiModelProperty(value = "项目总数")
-    @TableField("project_num")
-    private Integer projectNum;
+    @ApiModelProperty(value = "房建项目总数")
+    @TableField("housing_project_num")
+    private Integer housingProjectNum;
+
+    @ApiModelProperty(value = "市政项目总数")
+    @TableField("municipal_project_num")
+    private Integer municipalProjectNum;
 
     @ApiModelProperty(value = "在建项目json")
     @TableField("under_construction_project")
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/Device.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/Device.java
new file mode 100644
index 0000000..5d2bcea
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/Device.java
@@ -0,0 +1,98 @@
+package com.ruoyi.system.model;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.ruoyi.system.enums.DeviceType;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 设备实体类
+ * </p>
+ *
+ * @author administrator
+ * @since 2026-01-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("device")
+@Slf4j
+public class Device extends Model<Device> {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    private Boolean deleted;
+
+    /**
+     * 设备编号
+     */
+    private String name;
+
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 设备是否正在使用中
+     */
+    private Boolean busy;
+
+    /**
+     * 出厂编号
+     */
+    @TableField("manufacturer_number")
+    private String manufacturerNumber;
+
+    /**
+     * 设备详细信息(JSON格式)
+     */
+    private String properties;
+
+    /**
+     * 设备类型(数据库存储值:1-10)
+     * 1-塔式起重机 2-施工升降机 3-物料提升机 4-桥式起重机
+     * 5-附着式升降脚手架 6-流动式起重机 7-高处作业吊篮
+     * 8-门式起重机 9-架桥机 10-其他
+     *
+     * 需要通过 getDeviceType() 方法转换为 DeviceType 枚举
+     */
+    private Integer type;
+
+    @TableField("creator_id")
+    private Integer creatorId;
+
+    /**
+     * 获取设备类型枚举
+     * <p>
+     * 数据库 type 值范围:1-10
+     * DeviceType 枚举序号:0-9
+     * 转换公式:DeviceType.values()[type - 1]
+     * </p>
+     *
+     * @return DeviceType 枚举,如果 type 无效则返回 OTHER
+     */
+    public DeviceType getDeviceType() {
+        if (type == null || type < 1 || type > 10) {
+            log.warn("设备类型值无效,deviceId: {}, type: {}", id, type);
+            return DeviceType.OTHER;
+        }
+        // 数据库值减1得到枚举序号
+        return DeviceType.values()[type - 1];
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ClientServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ClientServiceImpl.java
index 45264b2..11c5ca8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ClientServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ClientServiceImpl.java
@@ -6,20 +6,10 @@
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.system.mapper.CheckMapper;
-import com.ruoyi.system.mapper.ClientMapper;
-import com.ruoyi.system.mapper.DeviceUsageMapper;
-import com.ruoyi.system.mapper.PlanMapper;
-import com.ruoyi.system.mapper.ProjectMapper;
-import com.ruoyi.system.mapper.RecordMapper;
-import com.ruoyi.system.mapper.TaskMapper;
-import com.ruoyi.system.model.Check;
-import com.ruoyi.system.model.Client;
-import com.ruoyi.system.model.DeviceUsage;
-import com.ruoyi.system.model.Plan;
-import com.ruoyi.system.model.Project;
+import com.ruoyi.system.enums.DeviceType;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.model.*;
 import com.ruoyi.system.model.Record;
-import com.ruoyi.system.model.Task;
 import com.ruoyi.system.service.ClientService;
 import com.ruoyi.system.service.ProjectCategoryCalculator;
 import com.ruoyi.system.vo.*;
@@ -55,6 +45,8 @@
     private final DeviceUsageMapper deviceUsageMapper;
     private final RecordMapper recordMapper;
     private final ProjectCategoryCalculator projectCategoryCalculator;
+    private final ClientParamMapper clientParamMapper;
+    private final DeviceMapper deviceMapper;
 
     @Override
     public ClientDashboardVO getClientDashboard(ClientDashboardQuery query) {
@@ -145,6 +137,15 @@
                         .distinct()
                         .toList();
 
+                // 查询配置的项目总数
+                ClientParam clientParam = null;
+                if (clientId != null) {
+                    clientParam = clientParamMapper.selectOne(
+                        new LambdaQueryWrapper<ClientParam>()
+                            .eq(ClientParam::getClientId, clientId.intValue())
+                    );
+                }
+
                 // 房建检查覆盖率
                 List<Integer> housingProjectIds = projects.stream()
                         .filter(p -> p.getType() != null && p.getType() == 0)
@@ -153,8 +154,13 @@
                 long checkedHousingCount = checkedProjectIds.stream()
                         .filter(housingProjectIds::contains)
                         .count();
+
+                // 使用配置的房建项目总数,如果没有配置则使用实际数量
+                int configuredHousingNum = (clientParam != null && clientParam.getHousingProjectNum() != null)
+                        ? clientParam.getHousingProjectNum()
+                        : (int) housingCount;
                 vo.setHousingInspectionCoverage(
-                        housingCount > 0 ? (int) Math.round(checkedHousingCount * 100.0 / housingCount) : 0
+                        configuredHousingNum > 0 ? (int) Math.round(checkedHousingCount * 100.0 / configuredHousingNum) : 0
                 );
 
                 // 市政检查覆盖率
@@ -165,8 +171,13 @@
                 long checkedMunicipalCount = checkedProjectIds.stream()
                         .filter(municipalProjectIds::contains)
                         .count();
+
+                // 使用配置的市政项目总数,如果没有配置则使用实际数量
+                int configuredMunicipalNum = (clientParam != null && clientParam.getMunicipalProjectNum() != null)
+                        ? clientParam.getMunicipalProjectNum()
+                        : (int) municipalCount;
                 vo.setMunicipalInspectionCoverage(
-                        municipalCount > 0 ? (int) Math.round(checkedMunicipalCount * 100.0 / municipalCount) : 0
+                        configuredMunicipalNum > 0 ? (int) Math.round(checkedMunicipalCount * 100.0 / configuredMunicipalNum) : 0
                 );
             } else {
                 vo.setHousingInspectionCoverage(0);
@@ -234,47 +245,7 @@
         // 1. 统计项目总数
         vo.setProjectTotal(projects.size());
 
-        // 计算检查覆盖率
         List<Integer> projectIds = projects.stream().map(Project::getId).collect(Collectors.toList());
-        if (!projectIds.isEmpty()) {
-            // 1. 先查询符合条件的 Task
-            LambdaQueryWrapper<Task> taskWrapper = new LambdaQueryWrapper<>();
-            taskWrapper.in(Task::getProjectId, projectIds)
-                    .eq(Task::getDeleted, false);
-            List<Task> tasks = taskMapper.selectList(taskWrapper);
-
-            if (!tasks.isEmpty()) {
-                // 2. 获取 Task ID 列表
-                List<Integer> taskIds = tasks.stream().map(Task::getId).collect(Collectors.toList());
-
-                // 3. 建立 Task ID 到 Project ID 的映射
-                Map<Integer, Integer> taskToProjectMap = tasks.stream()
-                        .collect(Collectors.toMap(Task::getId, Task::getProjectId));
-
-                // 4. 查询 record 表中 record_type='error' 且 device_id 为 null 的记录(项目检查)
-                LambdaQueryWrapper<Record> recordWrapper = new LambdaQueryWrapper<>();
-                recordWrapper.eq(Record::getRecordType, "error")
-                        .isNull(Record::getDeviceId)
-                        .in(Record::getCheckTaskId, taskIds)
-                        .eq(Record::getDeleted, false);
-                List<Record> projectRecords = recordMapper.selectList(recordWrapper);
-
-                // 5. 通过 Task 映射获取有检查记录的项目 ID
-                long checkedProjectCount = projectRecords.stream()
-                        .map(Record::getCheckTaskId)
-                        .map(taskToProjectMap::get)
-                        .filter(Objects::nonNull)
-                        .distinct()
-                        .count();
-                vo.setInspectionCoverage(
-                        projects.size() > 0 ? (int) Math.round(checkedProjectCount * 100.0 / projects.size()) : 0
-                );
-            } else {
-                vo.setInspectionCoverage(0);
-            }
-        } else {
-            vo.setInspectionCoverage(0);
-        }
 
         // 2. 统计本月检查情况
         calculateMonthlyInspectionForFixed(vo, projects, projectIds, monthStart, monthEnd);
@@ -433,19 +404,54 @@
                 .in(DeviceUsage::getProjectId, projectIds);
         List<DeviceUsage> devices = deviceUsageMapper.selectList(deviceWrapper);
 
-        // 按设备名称分组统计
+        // 批量查询 Device 信息
+        List<Integer> deviceIds = devices.stream()
+                .map(DeviceUsage::getDeviceId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+
+        Map<Integer, Device> deviceMap = new HashMap<>();
+        if (!deviceIds.isEmpty()) {
+            List<Device> deviceList = deviceMapper.selectBatchIds(deviceIds);
+            deviceMap = deviceList.stream()
+                    .collect(Collectors.toMap(Device::getId, d -> d));
+            log.debug("批量查询到 {} 个设备信息", deviceMap.size());
+
+            // 检查是否有设备信息查询失败
+            if (deviceIds.size() != deviceMap.size()) {
+                log.warn("部分设备信息查询失败,期望 {} 个,实际查询到 {} 个",
+                         deviceIds.size(), deviceMap.size());
+            }
+        }
+
+        // 按设备类型名称分组统计
+        final Map<Integer, Device> finalDeviceMap = deviceMap;
         Map<String, List<DeviceUsage>> deviceGroupMap = devices.stream()
-                .filter(d -> d.getName() != null && !d.getName().isEmpty())
-                .collect(Collectors.groupingBy(DeviceUsage::getName));
+                .filter(d -> d.getDeviceId() != null)
+                .filter(d -> finalDeviceMap.containsKey(d.getDeviceId()))
+                .collect(Collectors.groupingBy(d -> {
+                    try {
+                        Device device = finalDeviceMap.get(d.getDeviceId());
+                        return device.getDeviceType().getDesc();
+                    } catch (Exception e) {
+                        log.error("获取设备类型失败,deviceId: {}", d.getDeviceId(), e);
+                        return DeviceType.OTHER.getDesc();
+                    }
+                }));
+
+        log.debug("设备按类型分组完成,共 {} 种类型", deviceGroupMap.size());
 
         // 查询设备检查记录
-        List<Integer> deviceIds = devices.stream().map(DeviceUsage::getId).collect(Collectors.toList());
+        List<Integer> deviceUsageIds = devices.stream()
+                .map(DeviceUsage::getId)
+                .collect(Collectors.toList());
         Map<Integer, Boolean> deviceInspectionMap = new HashMap<>();
-        if (!deviceIds.isEmpty()) {
+        if (!deviceUsageIds.isEmpty()) {
             LambdaQueryWrapper<Record> recordWrapper = new LambdaQueryWrapper<>();
             recordWrapper.eq(Record::getRecordType, "error")
                     .isNotNull(Record::getDeviceId)
-                    .in(Record::getDeviceId, deviceIds)
+                    .in(Record::getDeviceId, deviceUsageIds)
                     .eq(Record::getDeleted, false);
             List<Record> records = recordMapper.selectList(recordWrapper);
 
@@ -453,8 +459,8 @@
                     .map(Record::getDeviceId)
                     .collect(Collectors.toSet());
 
-            for (Integer deviceId : deviceIds) {
-                deviceInspectionMap.put(deviceId, inspectedDeviceIds.contains(deviceId));
+            for (Integer deviceUsageId : deviceUsageIds) {
+                deviceInspectionMap.put(deviceUsageId, inspectedDeviceIds.contains(deviceUsageId));
             }
         }
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/FixedAssetDashboardVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/FixedAssetDashboardVO.java
index 4ca1ba5..38079b8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/FixedAssetDashboardVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/FixedAssetDashboardVO.java
@@ -20,9 +20,6 @@
     @ApiModelProperty("项目总数")
     private Integer projectTotal;
 
-    @ApiModelProperty("检查覆盖率(百分比,如:77 表示 77%)")
-    private Integer inspectionCoverage;
-
     // ==================== 本月检查情况 ====================
     @ApiModelProperty("已检查项目数")
     private Integer inspectedCount;

--
Gitblit v1.7.1