فهرست منبع

采集设备后台接口实现

jiuling 11 ماه پیش
والد
کامیت
065441fd1b
15فایلهای تغییر یافته به همراه1035 افزوده شده و 0 حذف شده
  1. 101 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/controller/DeviceController.java
  2. 82 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/AlertRecord.java
  3. 80 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/Device.java
  4. 83 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/WeatherRealtimeData.java
  5. 43 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/dto/DeviceDto.java
  6. 71 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/enums/DeviceTypeEnum.java
  7. 62 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/vo/DeviceOverviewVO.java
  8. 19 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/AlertRecordMapper.java
  9. 62 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/DeviceMapper.java
  10. 18 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/WeatherRealtimeDataMapper.java
  11. 49 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/service/IDeviceService.java
  12. 154 0
      ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/service/impl/DeviceServiceImpl.java
  13. 44 0
      ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/AlertRecordMapper.xml
  14. 124 0
      ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/DeviceMapper.xml
  15. 43 0
      ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/WeatherRealtimeDataMapper.xml

+ 101 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/controller/DeviceController.java

@@ -0,0 +1,101 @@
+package com.ruoyi.uniapp.controller;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.uniapp.domain.WeatherRealtimeData;
+import com.ruoyi.uniapp.domain.dto.DeviceDto;
+import com.ruoyi.uniapp.domain.enums.DeviceTypeEnum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.core.web.page.TableDataInfo;
+import com.ruoyi.uniapp.domain.Device;
+import com.ruoyi.uniapp.domain.vo.DeviceOverviewVO;
+import com.ruoyi.uniapp.service.IDeviceService;
+
+/**
+ * 设备管理Controller
+ * 
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/device")
+public class DeviceController extends BaseController {
+
+    @Autowired
+    private IDeviceService deviceService;
+    
+    /**
+     * 查询设备列表
+     *//*
+    @GetMapping("/list")
+    public TableDataInfo list(Device device) {
+        startPage();
+        List<Device> list = deviceService.selectDeviceList(device);
+        return getDataTable(list);
+    }*/
+
+    /**
+     * 获取设备详细信息
+     */
+    @GetMapping("/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Integer id) {
+        return success(deviceService.selectDeviceById(id));
+    }
+
+    
+    /**
+     * 获取设备概览
+     */
+    @PostMapping("/overview")
+    public AjaxResult getOverview(@RequestBody DeviceDto device) {
+        if (device.getFieldId() == null){
+            return error("请选择所属地块!");
+        }
+        DeviceOverviewVO overview = deviceService.getDeviceOverview(device.getUserId(), device.getFieldId());
+        return success(overview);
+    }
+
+    /**
+     *根据条件(地块、用户、设备类型)查询设备列表
+     */
+    @PostMapping("/typeList")
+    public TableDataInfo listByType(@RequestBody DeviceDto device) {
+
+        //若缺少必要条件时,返回空表格数据
+        if (device.getFieldId() == null &&
+                device.getUserId() == null &&
+                device.getDeviceType() == null) {
+            return getDataTable(Collections.emptyList());
+        }
+
+        //设备类型不为空,则进行转换为对应code
+        String frontendType = device.getDeviceType();
+        if (StringUtils.isNotEmpty(frontendType)) {
+            String code = DeviceTypeEnum.getCodeByFrontendType(frontendType);
+            if (code == null) {
+                //若无法根据前端type获取到code时,可适时抛出异常或者返回空
+                return getDataTable(Collections.emptyList());
+            }
+            device.setDeviceTypeId(code);
+        }
+
+        startPage();
+
+        List<Device> list = deviceService.selectDeviceList(device);
+        return getDataTable(list);
+    }
+    
+    /**
+     * 获取设备采集器详情(包含气象/土壤数据和告警信息)
+     */
+    @GetMapping("/collector/detail/{deviceId}")
+    public R<WeatherRealtimeData> getDeviceCollectorDetail(@PathVariable("deviceId") String deviceId) {
+        WeatherRealtimeData detail = deviceService.getDeviceDetail(deviceId);
+        return R.ok(detail);
+    }
+} 

+ 82 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/AlertRecord.java

@@ -0,0 +1,82 @@
+package com.ruoyi.uniapp.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.annotation.Excel;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 告警记录对象 alert_record
+ * 
+ * @author ruoyi
+ */
+@Data
+public class AlertRecord extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 告警ID */
+    private Long alertId;
+
+    /** 设备编号 */
+    @Excel(name = "设备编号")
+    private String deviceId;
+
+    /** 设备名称 */
+    @Excel(name = "设备名称")
+    private String deviceName;
+
+    /** 设备类型 */
+    @Excel(name = "设备类型")
+    private String deviceType;
+
+    /** 告警级别(1:提示,2:警告,3:紧急) */
+    @Excel(name = "告警级别", readConverterExp = "1=提示,2=警告,3=紧急")
+    private Integer alertLevel;
+
+    /** 告警参数名称 */
+    @Excel(name = "告警参数名称")
+    private String parameterName;
+
+    /** 告警时参数值 */
+    @Excel(name = "告警时参数值")
+    private String parameterValue;
+
+    /** 参数单位 */
+    @Excel(name = "参数单位")
+    private String parameterUnit;
+
+    /** 阈值 */
+    @Excel(name = "阈值")
+    private String thresholdValue;
+
+    /** 告警内容 */
+    @Excel(name = "告警内容")
+    private String alertContent;
+
+    /** 告警时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "告警时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date alertTime;
+
+    /** 处理状态(0:未处理,1:已确认,2:已处理,3:已忽略) */
+    @Excel(name = "处理状态", readConverterExp = "0=未处理,1=已确认,2=已处理,3=已忽略")
+    private Integer processStatus;
+
+    /** 处理时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "处理时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date processTime;
+
+    /** 处理人 */
+    @Excel(name = "处理人")
+    private String processor;
+
+    /** 处理说明 */
+    @Excel(name = "处理说明")
+    private String processComment;
+
+    /** 所属农场ID */
+    @Excel(name = "所属农场ID")
+    private String farmId;
+} 

+ 80 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/Device.java

@@ -0,0 +1,80 @@
+package com.ruoyi.uniapp.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.annotation.Excel;
+import com.ruoyi.common.core.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 设备信息对象 device
+ * 
+ * @author ruoyi
+ */
+@Data
+public class Device extends BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    private Integer id;
+
+    /** 设备编号 */
+    @Excel(name = "设备编号")
+    private String deviceId;
+
+    /** 设备名称 */
+    @Excel(name = "设备名称")
+    private String deviceName;
+
+    /** 设备类型(1-传感器,2-摄像头,3-控制器,4-气象设备,5-农机设备) */
+    @Excel(name = "设备类型")
+    private String deviceTypeId;
+    
+    /** 所属农场ID */
+    @Excel(name = "所属农场ID")
+    private String farmId;
+
+    /** 设备型号 */
+    @Excel(name = "设备型号")
+    private String model;
+
+    /** GPS经度 */
+    @Excel(name = "GPS经度")
+    private BigDecimal longitude;
+
+    /** GPS纬度 */
+    @Excel(name = "GPS纬度")
+    private BigDecimal latitude;
+
+    /** 厂家 */
+    @Excel(name = "厂家")
+    private String manufacturer;
+
+    /** 安装日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "安装日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date installDate;
+
+    /** 状态: 0-离线, 1-在线, 2-故障, 3-维护中 */
+    @Excel(name = "状态", readConverterExp = "0=离线,1=在线,2=故障,3=维护中")
+    private Integer status;
+
+    /** 最后活动时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "最后活动时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date lastActiveTime;
+
+    /** 备注信息 */
+    @Excel(name = "备注信息")
+    private String remark;
+
+    /** 地块名称 */
+    private String fieldName;
+
+} 

+ 83 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/WeatherRealtimeData.java

@@ -0,0 +1,83 @@
+package com.ruoyi.uniapp.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.annotation.Excel;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * 气象站实时数据对象 weather_realtime_data
+ * 
+ * @author ruoyi
+ */
+@Data
+public class WeatherRealtimeData extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    private Long id;
+
+    /** 设备编号 */
+    @Excel(name = "设备编号")
+    private String deviceId;
+
+    /** 气温(°C) */
+    @Excel(name = "气温(°C)")
+    private BigDecimal temperature;
+
+    /** 湿度(%) */
+    @Excel(name = "湿度(%)")
+    private BigDecimal humidity;
+
+    /** 降雨量(mm) */
+    @Excel(name = "降雨量(mm)")
+    private BigDecimal rainfall;
+
+    /** 风向 */
+    @Excel(name = "风向")
+    private String windDirection;
+
+    /** 风速(m/s) */
+    @Excel(name = "风速(m/s)")
+    private BigDecimal windSpeed;
+
+    /** 气压(hPa) */
+    @Excel(name = "气压(hPa)")
+    private BigDecimal airPressure;
+
+    /** 光照强度(lux) */
+    @Excel(name = "光照强度(lux)")
+    private BigDecimal lightIntensity;
+
+    /** 土壤温度 */
+    @Excel(name = "土壤温度")
+    private BigDecimal soilTemperature;
+
+    /** 土壤水分 */
+    @Excel(name = "土壤水分")
+    private BigDecimal soilHumidity;
+
+    /** 土壤氮 */
+    @Excel(name = "土壤氮")
+    private BigDecimal soilN;
+
+    /** 土壤磷 */
+    @Excel(name = "土壤磷")
+    private BigDecimal soilP;
+
+    /** 土壤钾 */
+    @Excel(name = "土壤钾")
+    private BigDecimal soilK;
+
+    /** 采集时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "采集时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date collectTime;
+
+    /*告警列表*/
+    private List<AlertRecord> alertRecordList;
+} 

+ 43 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/dto/DeviceDto.java

@@ -0,0 +1,43 @@
+package com.ruoyi.uniapp.domain.dto;
+
+import lombok.Data;
+@Data
+public class DeviceDto {
+    /** 用户ID */
+    private String userId;
+
+    /* 设备编号 */
+    private String deviceId;
+
+    /* 设备查询参数 */
+    private String deviceQueryParams;
+
+    /** 所属农场名称 */
+    private String farmName;
+
+    /* 设备名称 */
+    private String deviceName;
+
+    /** 所属地块ID */
+    private String fieldId;
+
+    /* 设备类型(1-传感器,2-摄像头,3-控制器,4-气象设备,5-农机设备) */
+    private String deviceType;
+    private String deviceTypeId;
+
+    /** 所属地块名称 */
+    private String fieldName;
+
+    /** 是否有告警(非数据库字段) */
+    private Boolean hasAlert;
+
+    /** 告警数量(非数据库字段) */
+    private Integer alertCount;
+
+    /** 状态: 0-离线, 1-在线, 2-故障, 3-维护中 */
+    private Integer status;
+
+    private Integer pagenum;
+
+    private Integer pagesize;
+}

+ 71 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/enums/DeviceTypeEnum.java

@@ -0,0 +1,71 @@
+package com.ruoyi.uniapp.domain.enums;
+
+/**
+ * 设备类型枚举
+ */
+public enum DeviceTypeEnum {
+    
+    SENSOR("1", "采集设备", "sensor"),
+    MONITOR("2", "监控设备", "monitor"),
+    CONTROL("3", "控制设备", "control"),
+    WEATHER("4", "灌溉设备", "irrigation"),  // 在前端被展示为"灌溉设备"
+    TRACTOR("5", "农机设备", "tractor");
+
+    private final String code;
+    private final String name;
+    private final String frontendType;
+
+    DeviceTypeEnum(String code, String name, String frontendType) {
+        this.code = code;
+        this.name = name;
+        this.frontendType = frontendType;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    public String getFrontendType() {
+        return frontendType;
+    }
+
+    /**
+     *根据前端类型获取对应code
+     */
+    public static String getCodeByFrontendType(String frontendType) {
+        for (DeviceTypeEnum type : DeviceTypeEnum.values()) {
+            if (type.getFrontendType().equals(frontendType)) {
+                return type.getCode();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 根据代码获取枚举实例
+     */
+    public static DeviceTypeEnum getByCode(String code) {
+        for (DeviceTypeEnum type : DeviceTypeEnum.values()) {
+            if (type.getCode().equals(code)) {
+                return type;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * 根据前端类型获取枚举实例
+     */
+    public static DeviceTypeEnum getByFrontendType(String frontendType) {
+        for (DeviceTypeEnum type : DeviceTypeEnum.values()) {
+            if (type.getFrontendType().equals(frontendType)) {
+                return type;
+            }
+        }
+        return null;
+    }
+} 

+ 62 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/vo/DeviceOverviewVO.java

@@ -0,0 +1,62 @@
+package com.ruoyi.uniapp.domain.vo;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 设备概览VO,用于设备中心首页展示
+ */
+@Data
+public class DeviceOverviewVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 总设备数 */
+    private Integer totalDevices;
+    
+    /** 在线设备数 */
+    private Integer onlineDevices;
+    
+    /** 离线设备数 */
+    private Integer offlineDevices;
+    
+    /** 告警设备数 */
+    private Integer alertDevices;
+    
+    /** 当前查看地块名称 */
+    private String currentPlot;
+
+    /** 设备类型名称 */
+    private String name;
+
+    /** 在线设备数 */
+    private Integer online;
+
+    /** 离线设备数 */
+    private Integer offline;
+
+    /** 设备类型标识 */
+    private String type;
+
+    /** 设备图标 */
+    private String icon;
+
+    /** 告警数量 */
+    private Integer alerts;
+
+    /** 在线率 */
+    private Integer onlineRate;
+    
+    /** 设备分类列表 */
+    private List<DeviceOverviewVO> deviceList;
+
+    public DeviceOverviewVO(String name, String type, String icon) {
+        this.name = name;
+        this.type = type;
+        this.icon = icon;
+        this.online = 0;
+        this.offline = 0;
+        this.alerts = 0;
+        this.onlineRate = 0;
+    }
+} 

+ 19 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/AlertRecordMapper.java

@@ -0,0 +1,19 @@
+package com.ruoyi.uniapp.mapper;
+
+import java.util.List;
+import com.ruoyi.uniapp.domain.AlertRecord;
+
+/**
+ * 告警记录Mapper接口
+ * 
+ * @author ruoyi
+ */
+public interface AlertRecordMapper {
+    /**
+     * 查询设备的告警记录
+     * 
+     * @param deviceId 设备编号
+     * @return 告警记录集合
+     */
+    public List<AlertRecord> selectAlertRecordsByDeviceId(String deviceId);
+} 

+ 62 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/DeviceMapper.java

@@ -0,0 +1,62 @@
+package com.ruoyi.uniapp.mapper;
+
+import com.ruoyi.uniapp.domain.Device;
+import com.ruoyi.uniapp.domain.dto.DeviceDto;
+import com.ruoyi.uniapp.domain.vo.DeviceOverviewVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 设备Mapper接口
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface DeviceMapper {
+    /**
+     * 查询设备信息
+     * 
+     * @param id 设备ID
+     * @return 设备信息
+     */
+    public Device selectDeviceById(Integer id);
+
+    /**
+     * 查询设备列表
+     * 
+     * @param device 设备信息
+     * @return 设备集合
+     */
+    public List<Device> selectDeviceList(DeviceDto device);
+
+    
+    /**
+     * 按设备类型统计在线和离线设备数量
+     *
+     * @param fieldId 地块ID
+     * @param userId 用户ID
+     * @return 设备统计信息
+     */
+    public List<Map<String, Object>> countDevicesByType(@Param("fieldId") String fieldId , @Param("userId") String userId);
+    
+    /**
+     * 按设备类型统计告警数量
+     *
+     * @param farmId 农场ID,可为空
+     * @param fieldId 地块ID,可为空
+     * @return 告警统计信息
+     */
+    public List<Map<String, Object>> countAlertsByType(@Param("farmId") String farmId, @Param("fieldId") String fieldId);
+
+    /**
+     * 获取设备统计信息
+     *
+     * @param fieldId 地块ID
+     * @param userId 用户ID
+     * @return 包含totalDevices、onlineDevices、offlineDevices、alertDevices的Map
+     */
+    public DeviceOverviewVO countDeviceStatistics(@Param("fieldId") String fieldId , @Param("userId") String userId);
+} 

+ 18 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/WeatherRealtimeDataMapper.java

@@ -0,0 +1,18 @@
+package com.ruoyi.uniapp.mapper;
+
+import com.ruoyi.uniapp.domain.WeatherRealtimeData;
+
+/**
+ * 气象站实时数据Mapper接口
+ * 
+ * @author ruoyi
+ */
+public interface WeatherRealtimeDataMapper {
+    /**
+     * 查询最新的气象站实时数据
+     * 
+     * @param deviceId 设备编号
+     * @return 气象站实时数据
+     */
+    public WeatherRealtimeData selectLatestDataByDeviceId(String deviceId);
+} 

+ 49 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/service/IDeviceService.java

@@ -0,0 +1,49 @@
+package com.ruoyi.uniapp.service;
+
+import com.ruoyi.uniapp.domain.Device;
+import com.ruoyi.uniapp.domain.WeatherRealtimeData;
+import com.ruoyi.uniapp.domain.dto.DeviceDto;
+import com.ruoyi.uniapp.domain.vo.DeviceOverviewVO;
+
+import java.util.List;
+
+/**
+ * 设备管理Service接口
+ * 
+ * @author ruoyi
+ */
+public interface IDeviceService {
+    /**
+     * 查询设备信息
+     * 
+     * @param id 设备ID
+     * @return 设备信息
+     */
+    public Device selectDeviceById(Integer id);
+
+    /**
+     * 查询设备列表
+     * 
+     * @param device 设备信息
+     * @return 设备集合
+     */
+    public List<Device> selectDeviceList(DeviceDto device);
+
+    
+    /**
+     * 获取设备概览信息
+     *
+     * @param userId 用户ID
+     * @param fieldId 地块ID
+     * @return 设备概览信息
+     */
+    public DeviceOverviewVO getDeviceOverview(String userId, String fieldId);
+
+    /**
+     * 获取设备详情(包含气象/土壤数据和告警信息)
+     *
+     * @param deviceId 设备编号
+     * @return 设备详情数据
+     */
+    public WeatherRealtimeData getDeviceDetail(String deviceId);
+} 

+ 154 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/service/impl/DeviceServiceImpl.java

@@ -0,0 +1,154 @@
+package com.ruoyi.uniapp.service.impl;
+
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.uniapp.domain.AlertRecord;
+import com.ruoyi.uniapp.domain.WeatherRealtimeData;
+import com.ruoyi.uniapp.domain.dto.DeviceDto;
+import com.ruoyi.uniapp.mapper.AlertRecordMapper;
+import com.ruoyi.uniapp.mapper.WeatherRealtimeDataMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.uniapp.mapper.DeviceMapper;
+import com.ruoyi.uniapp.domain.Device;
+import com.ruoyi.uniapp.domain.enums.DeviceTypeEnum;
+import com.ruoyi.uniapp.domain.vo.DeviceOverviewVO;
+import com.ruoyi.uniapp.service.IDeviceService;
+
+/**
+ * 设备Service业务层处理
+ * 
+ * @author ruoyi
+ */
+@Service
+public class DeviceServiceImpl implements IDeviceService {
+    @Autowired
+    private DeviceMapper deviceMapper;
+
+    @Autowired
+    private WeatherRealtimeDataMapper weatherRealtimeDataMapper;
+
+    @Autowired
+    private AlertRecordMapper alertRecordMapper;
+
+    /**
+     * 查询设备信息
+     * 
+     * @param id 设备ID
+     * @return 设备信息
+     */
+    @Override
+    public Device selectDeviceById(Integer id) {
+        return deviceMapper.selectDeviceById(id);
+    }
+
+    /**
+     * 查询设备列表
+     * 
+     * @param device 设备信息
+     * @return 设备
+     */
+    @Override
+    public List<Device> selectDeviceList(DeviceDto device) {
+        return deviceMapper.selectDeviceList(device);
+    }
+    
+    /**
+     * 获取设备概览信息
+     *
+     * @param userId 用户ID
+     * @param fieldId 地块ID
+     * @return 设备概览信息
+     */
+    @Override
+    public DeviceOverviewVO getDeviceOverview(String userId, String fieldId) {
+
+        DeviceOverviewVO overview = deviceMapper.countDeviceStatistics(fieldId,userId);
+        
+        // 获取按设备类型分组的统计数据
+        List<Map<String, Object>> deviceStats = deviceMapper.countDevicesByType(fieldId,userId);
+        // TODO 等待告警模块完善
+        // List<Map<String, Object>> alertStats = deviceMapper.countAlertsByType(farmId, fieldId);
+        
+        // 初始化设备类型统计列表
+        Map<String, DeviceOverviewVO> deviceTypeMap = initDeviceTypeMap();
+        
+        // 填充设备数量数据
+        for (Map<String, Object> stat : deviceStats) {
+            String deviceTypeId = (String) stat.get("deviceTypeId");
+            DeviceTypeEnum deviceType = DeviceTypeEnum.getByCode(deviceTypeId);
+            
+            if (deviceType != null) {
+                String frontendType = deviceType.getFrontendType();
+                DeviceOverviewVO typeStats = deviceTypeMap.get(frontendType);
+                
+                if (typeStats != null) {
+                    typeStats.setOnline(((Number) stat.get("online")).intValue());
+                    typeStats.setOffline(((Number) stat.get("offline")).intValue());
+                }
+            }
+        }
+        
+        // 填充告警数据
+        /*for (Map<String, Object> stat : alertStats) {
+            String deviceTypeId = (String) stat.get("deviceTypeId");
+            DeviceTypeEnum deviceType = DeviceTypeEnum.getByCode(deviceTypeId);
+            
+            if (deviceType != null) {
+                String frontendType = deviceType.getFrontendType();
+                DeviceTypeStatsVO typeStats = deviceTypeMap.get(frontendType);
+                
+                if (typeStats != null) {
+                    typeStats.setAlerts(((Number) stat.get("alerts")).intValue());
+                }
+            }
+        }*/
+        
+        // 设置设备类型统计列表
+        overview.setDeviceList(new ArrayList<>(deviceTypeMap.values()));
+        
+        return overview;
+    }
+
+    /**
+     * 获取设备详情(包含气象/土壤数据和告警信息)
+     *
+     * @param deviceId 设备编号
+     * @return 设备详情数据
+     */
+    @Override
+    public WeatherRealtimeData getDeviceDetail(String deviceId) {
+        //获取最新的气象/土壤数据 /告警数据
+        WeatherRealtimeData weatherRealtimeData = weatherRealtimeDataMapper.selectLatestDataByDeviceId(deviceId);
+
+        if (weatherRealtimeData == null) {
+            return null;
+        }
+        // 获取当前设备的告警信息(未处理且最近三条;后续考虑增加分页查询)
+        List<AlertRecord> alertRecords = alertRecordMapper.selectAlertRecordsByDeviceId(deviceId);
+        if (alertRecords != null && !alertRecords.isEmpty()) {
+            weatherRealtimeData.setAlertRecordList(alertRecords);
+        }
+
+        return weatherRealtimeData;
+    }
+    
+    /**
+     * 初始化设备类型统计映射
+     */
+    private Map<String, DeviceOverviewVO> initDeviceTypeMap() {
+        Map<String, DeviceOverviewVO> deviceTypeMap = new LinkedHashMap<>();
+
+        deviceTypeMap.put("monitor", new DeviceOverviewVO("监控设备", "monitor", "/static/icons/camera.png"));
+        deviceTypeMap.put("sensor", new DeviceOverviewVO("采集设备", "sensor", "/static/icons/sensor.png"));
+        deviceTypeMap.put("control", new DeviceOverviewVO("控制设备", "control", "/static/icons/control.png"));
+        deviceTypeMap.put("irrigation", new DeviceOverviewVO("灌溉设备", "irrigation", "/static/icons/water.png"));
+        deviceTypeMap.put("tractor", new DeviceOverviewVO("农机设备", "tractor", "/static/icons/tractor.png"));
+
+        return deviceTypeMap;
+    }
+
+} 

+ 44 - 0
ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/AlertRecordMapper.xml

@@ -0,0 +1,44 @@
+<?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.ruoyi.uniapp.mapper.AlertRecordMapper">
+    
+    <resultMap type="com.ruoyi.uniapp.domain.AlertRecord" id="AlertRecordResult">
+        <id property="alertId" column="alert_id"/>
+        <result property="deviceId" column="device_id"/>
+        <result property="deviceName" column="device_name"/>
+        <result property="deviceType" column="device_type"/>
+        <result property="alertLevel" column="alert_level"/>
+        <result property="parameterName" column="parameter_name"/>
+        <result property="parameterValue" column="parameter_value"/>
+        <result property="parameterUnit" column="parameter_unit"/>
+        <result property="thresholdValue" column="threshold_value"/>
+        <result property="alertContent" column="alert_content"/>
+        <result property="alertTime" column="alert_time"/>
+        <result property="processStatus" column="process_status"/>
+        <result property="processTime" column="process_time"/>
+        <result property="processor" column="processor"/>
+        <result property="processComment" column="process_comment"/>
+        <result property="farmId" column="farm_id"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+    
+    <sql id="selectAlertRecordVo">
+        select alert_id, device_id, device_name, device_type, alert_level,
+        parameter_name, parameter_value, parameter_unit, threshold_value, alert_content,
+        alert_time, process_status, process_time, processor, process_comment, farm_id,
+        create_time, update_time
+        from alert_record
+    </sql>
+    
+    <select id="selectAlertRecordsByDeviceId" parameterType="String" resultMap="AlertRecordResult">
+        <include refid="selectAlertRecordVo"/>
+        where device_id = #{deviceId}
+        AND process_status = 0
+        order by alert_time desc
+        limit 3
+    </select>
+    
+</mapper> 

+ 124 - 0
ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/DeviceMapper.xml

@@ -0,0 +1,124 @@
+<?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.ruoyi.uniapp.mapper.DeviceMapper">
+    
+    <resultMap type="com.ruoyi.uniapp.domain.Device" id="DeviceResult">
+        <id property="id" column="id"/>
+        <result property="deviceId" column="device_id"/>
+        <result property="deviceName" column="device_name"/>
+        <result property="deviceTypeId" column="device_type_id"/>
+        <result property="farmId" column="farm_id"/>
+        <result property="model" column="model"/>
+        <result property="longitude" column="longitude"/>
+        <result property="latitude" column="latitude"/>
+        <result property="manufacturer" column="manufacturer"/>
+        <result property="installDate" column="install_date"/>
+        <result property="status" column="status"/>
+        <result property="lastActiveTime" column="last_active_time"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="remark" column="remark"/>
+        <result property="fieldName" column="field_name"/>
+    </resultMap>
+
+    <sql id="selectDeviceVo">
+        select d.id, d.device_id, d.device_name, d.device_type_id, d.farm_id, d.model, d.longitude,
+        d.latitude, d.manufacturer, d.install_date, d.status, d.last_active_time, d.create_time,
+        d.update_time, d.remark, f.field_name
+        from device d
+    </sql>
+
+    <select id="selectDeviceList" parameterType="com.ruoyi.uniapp.domain.dto.DeviceDto" resultMap="DeviceResult">
+        <include refid="selectDeviceVo"/>
+        LEFT JOIN field_device fd ON fd.device_id = d.id
+        LEFT JOIN field f ON f.id = fd.field_id
+        LEFT JOIN field_personnel fp ON fd.id = fp.field_id
+        <where>  
+            <if test="deviceId != null  and deviceId != ''"> and d.device_id = #{deviceId}</if>
+            <if test="fieldId != null  and fieldId != ''"> and fd.field_id = #{fieldId}</if>
+            <if test="userId != null  and userId != ''"> and fp.user_id = #{userId}</if>
+            <if test="deviceName != null  and deviceName != ''"> and d.device_name like concat('%', #{deviceName}, '%')</if>
+            <if test="deviceTypeId != null  and deviceTypeId != ''"> and d.device_type_id = #{deviceTypeId}</if>
+            <if test="status != null "> and d.status = #{status}</if>
+            <if test="deviceQueryParams != null and deviceQueryParams != ''">
+                and (
+                d.device_name like concat('%', #{deviceQueryParams}, '%') OR
+                d.device_id like concat('%', #{deviceQueryParams}, '%')
+                )
+            </if>
+            AND fd.`status` = 0
+            AND fp.`status` = 0
+        </where>
+        order by create_time desc
+    </select>
+    
+    <select id="selectDeviceById" parameterType="Integer" resultMap="DeviceResult">
+        <include refid="selectDeviceVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="countDeviceStatistics" resultType="com.ruoyi.uniapp.domain.vo.DeviceOverviewVO">
+        SELECT
+        COUNT(DISTINCT d.id) AS totalDevices,
+        SUM(CASE WHEN d.status = 1 THEN 1 ELSE 0 END) AS onlineDevices,
+        SUM(CASE WHEN d.status = 0 THEN 1 ELSE 0 END) AS offlineDevices
+        FROM device d
+        LEFT JOIN field_device fd ON fd.device_id = d.id
+        LEFT JOIN field_personnel fp ON fd.id = fp.field_id
+        <where>
+            <if test="fieldId != null and fieldId != ''">
+                AND fd.field_id = #{fieldId}
+            </if>
+            <if test="userId != null and userId != ''">
+                AND fp.user_id = #{userId}
+            </if>
+            AND fp.`status` = 0
+            AND fd.`status` = 0
+        </where>
+    </select>
+
+
+    <select id="countDevicesByType" resultType="java.util.Map">
+        SELECT
+        d.device_type_id AS deviceTypeId,
+        SUM( CASE WHEN d.STATUS = 1 THEN 1 ELSE 0 END ) AS online,
+        SUM( CASE WHEN d.STATUS = 0 THEN 1 ELSE 0 END ) AS offline
+        FROM
+        device d
+        LEFT JOIN field_device fd ON fd.device_id = d.id
+        LEFT JOIN field_personnel fp ON fd.field_id = fp.field_id
+        <where>
+            <if test="fieldId != null and fieldId != ''">
+                AND fd.field_id = #{fieldId}
+            </if>
+            <if test="userId != null and userId != ''">
+                AND fp.user_id = #{userId}
+            </if>
+            AND fd.`status` = 0
+            AND fp.`status` = 0
+        </where>
+        GROUP BY device_type_id
+    </select>
+    
+    <select id="countAlertsByType" resultType="java.util.Map">
+        SELECT 
+            d.device_type_id as deviceTypeId,
+            COUNT(a.id) as alerts
+        FROM 
+            device d
+        LEFT JOIN 
+            device_alert a ON d.device_id = a.device_id AND a.status = 0
+        <where>
+            <if test="farmId != null and farmId != ''">
+                AND d.farm_id = #{farmId}
+            </if>
+            <if test="fieldId != null and fieldId != ''">
+                AND d.field_id = #{fieldId}
+            </if>
+        </where>
+        GROUP BY d.device_type_id
+    </select>
+    
+</mapper> 

+ 43 - 0
ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/WeatherRealtimeDataMapper.xml

@@ -0,0 +1,43 @@
+<?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.ruoyi.uniapp.mapper.WeatherRealtimeDataMapper">
+    
+    <resultMap type="com.ruoyi.uniapp.domain.WeatherRealtimeData" id="WeatherRealtimeDataResult">
+        <id property="id" column="id"/>
+        <result property="deviceId" column="device_id"/>
+        <result property="temperature" column="temperature"/>
+        <result property="humidity" column="humidity"/>
+        <result property="rainfall" column="rainfall"/>
+        <result property="windDirection" column="wind_direction"/>
+        <result property="windSpeed" column="wind_speed"/>
+        <result property="airPressure" column="air_pressure"/>
+        <result property="lightIntensity" column="light_intensity"/>
+        <result property="soilTemperature" column="soil_temperature"/>
+        <result property="soilHumidity" column="soil_humidity"/>
+        <result property="soilN" column="soil_n"/>
+        <result property="soilP" column="soil_p"/>
+        <result property="soilK" column="soil_k"/>
+        <result property="collectTime" column="collect_time"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="createBy" column="create_by"/>
+        <result property="updateBy" column="update_by"/>
+    </resultMap>
+    
+    <sql id="selectWeatherRealtimeDataVo">
+        select wrd.id, wrd.device_id, wrd.temperature, wrd.humidity, wrd.rainfall, wrd.wind_direction, wrd.wind_speed,
+               wrd.air_pressure, wrd.light_intensity, wrd.soil_temperature, wrd.soil_humidity, wrd.soil_n, wrd.soil_p, wrd.soil_k,
+               wrd.collect_time, wrd.create_time, wrd.update_time, wrd.create_by, wrd.update_by
+        from weather_realtime_data wrd
+    </sql>
+    
+    <select id="selectLatestDataByDeviceId" parameterType="String" resultMap="WeatherRealtimeDataResult">
+        <include refid="selectWeatherRealtimeDataVo"/>
+        WHERE wrd.device_id = #{deviceId}
+        order by collect_time desc
+        LIMIT 1
+    </select>
+    
+</mapper>