Selaa lähdekoodia

完成“我的地块”相关功能

jiuling 11 kuukautta sitten
vanhempi
sitoutus
1fd86cbc14

+ 3 - 0
ruoyi-modules/ruoyi-system/pom.xml

@@ -91,6 +91,9 @@
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <classifier>exec</classifier>
+                </configuration>
                 <executions>
                     <execution>
                         <goals>

+ 6 - 8
ruoyi-modules/ruoyi-uniapp/pom.xml

@@ -17,13 +17,6 @@
 
     <dependencies>
 
-        <!-- RuoYi System 模块 -->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-system</artifactId>
-            <version>3.6.5</version>
-        </dependency>
-
     	<!-- SpringCloud Alibaba Nacos -->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
@@ -85,7 +78,12 @@
             <version>0.9.1</version>
         </dependency>
 
-
+        <!-- RuoYi System 模块 -->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-system</artifactId>
+            <version>3.6.5</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 81 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/controller/FieldController.java

@@ -0,0 +1,81 @@
+package com.ruoyi.uniapp.controller;
+
+
+import java.util.List;
+import java.util.Map;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.core.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.web.page.TableDataInfo;
+import com.ruoyi.uniapp.domain.Field;
+import com.ruoyi.uniapp.domain.vo.FieldVO;
+import com.ruoyi.uniapp.service.IFieldService;
+
+/**
+ * 地块信息 控制层
+ * 
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/field")
+public class FieldController extends BaseController {
+    @Autowired
+    private IFieldService fieldService;
+
+
+    /**
+     * 根据用户ID查询关联地块列表
+     */
+    @PostMapping("/list/user")
+    public R<PageInfo<FieldVO>> listByUserId(@RequestBody Field field) {
+        if (field.getUserId() == null){
+            return R.fail("查询用户关联地块信息失败");
+        }
+
+        Object pageNum = field.getParams().get("pageNum");
+        Object pageSize = field.getParams().get("pageSize");
+        if (null != pageNum && null != pageSize){
+            PageInfo<FieldVO> fieldVOPageInfo = fieldService.selectFieldListByUserId(field.getUserId(), new Integer(pageNum.toString()), new Integer(pageSize.toString()));
+            return R.ok(fieldVOPageInfo);
+        }
+        return R.fail("分页查询参数缺失");
+
+    }
+
+    
+    /**
+     * 根据用户ID搜索地块信息
+     */
+    @PostMapping("/search/user")
+    public R<PageInfo<FieldVO>> searchByUserId(@RequestBody Field field) {
+        if (field.getUserId() == null || field.getUserId() <= 0) {
+            return R.fail("用户ID不能为空或小于等于0");
+        }
+        Object pageNum = field.getParams().get("pageNum");
+        Object pageSize = field.getParams().get("pageSize");
+        Object keyword = field.getParams().get("keyword");
+        String keywordValue = keyword.toString();
+        if (null != pageNum && null != pageSize){
+            PageInfo<FieldVO> fieldVOPageInfo = fieldService.searchFieldsByUserIdAndKeyword(field.getUserId(), StringUtils.trimToNull(keywordValue), new Integer(pageNum.toString()), new Integer(pageSize.toString()));
+            return R.ok(fieldVOPageInfo);
+        }
+        // 构建带有分页信息的返回对象
+        return R.fail("搜索地块信息失败");
+    }
+
+
+    /**
+     * 根据用户ID查询关联地块列表
+     */
+    @GetMapping("/count/{userId}")
+    public R<FieldVO> countUserPlots(@PathVariable("userId") Long userId) {
+        FieldVO fieldCounts = fieldService.countFieldTotalByUser(userId);
+        return R.ok(fieldCounts);
+    }
+} 

+ 1 - 1
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/controller/UniAppLoginController.java

@@ -43,7 +43,7 @@ public class UniAppLoginController extends BaseController
         return userService.uniappLogin(loginBody,request);
     }
     /**
-     * 小程序登录
+     * 小程序退出登录
      */
     @PostMapping("/logout")
     public R<?> logout(HttpServletRequest request)

+ 111 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/Field.java

@@ -0,0 +1,111 @@
+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;
+
+/**
+ * 地块信息对象 field
+ * 
+ * @author ruoyi
+ */
+@Data
+public class Field extends BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    private Long id;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 地块编号 */
+    @Excel(name = "地块编号")
+    private String fieldCode;
+
+    /** 地块名称 */
+    @Excel(name = "地块名称")
+    private String fieldName;
+
+    /** 所属农场ID */
+    @Excel(name = "所属农场ID")
+    private Long farmId;
+    
+    /** 所属农场名称(非数据库字段) */
+    @Excel(name = "所属农场名称")
+    private String farmName;
+
+    /** 地块类型(水田、旱地、果园、菜地、其他) */
+    @Excel(name = "地块类型")
+    private String fieldType;
+
+    /** 种植作物(字典) */
+    @Excel(name = "种植作物")
+    private String growCrops;
+
+    /** 面积(亩) */
+    @Excel(name = "面积(亩)")
+    private BigDecimal size;
+
+    /** 土壤类型(粘土、沙质土、壤土、沙壤土、其他) */
+    @Excel(name = "土壤类型")
+    private String soilType;
+
+    /** 灌溉方式(喷灌、滴灌、微喷灌、漫灌、其他) */
+    @Excel(name = "灌溉方式")
+    private String irrigationType;
+
+    /** 使用状态(0-使用中,1-未使用,2-维护中) */
+    @Excel(name = "使用状态", readConverterExp = "0=使用中,1=未使用,2=维护中")
+    private String status;
+
+    /** 负责人ID */
+    private Long managerId;
+
+    /** 负责人名字 */
+    @Excel(name = "负责人")
+    private String managerName;
+
+    /** 地块描述 */
+    @Excel(name = "地块描述")
+    private String description;
+
+    /** 地理位置数据(GeoJSON格式) */
+    private String locationData;
+
+    /** 是否删除 */
+    private Integer isDeleted;
+    
+    /** 设备数量(非数据库字段) */
+    private Integer deviceCount;
+    
+    /** 在线设备数量(非数据库字段) */
+    private Integer onlineDevices;
+    
+    /** 告警数量(非数据库字段) */
+    private Integer alerts;
+
+    /*
+     * 地块总数
+     * */
+    private Integer plotsTotal;
+
+    /*
+     * 使用中数量
+     * */
+    private Integer inUseCount;
+
+    /*
+     * 空闲数量
+     * */
+    private Integer leiSureCount;
+
+} 

+ 75 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/enums/FieldStatusEnum.java

@@ -0,0 +1,75 @@
+package com.ruoyi.uniapp.domain.enums;
+
+/**
+ * 地块使用状态枚举
+ * 
+ * @author ruoyi
+ */
+public enum FieldStatusEnum {
+    
+    ACTIVE("0", "active", "使用中"),
+    IDLE("1", "idle", "闲置"),
+    MAINTENANCE("2", "maintenance", "维护中");
+    
+    private final String code;
+    private final String status;
+    private final String info;
+    
+    FieldStatusEnum(String code, String status, String info) {
+        this.code = code;
+        this.status = status;
+        this.info = info;
+    }
+    
+    public String getCode() {
+        return code;
+    }
+    
+    public String getStatus() {
+        return status;
+    }
+    
+    public String getInfo() {
+        return info;
+    }
+    
+    /**
+     * 根据code获取对应的前端状态标识
+     * 
+     * @param code 状态编码
+     * @return 前端状态标识
+     */
+    public static String getStatusByCode(String code) {
+        if (code == null) {
+            return ACTIVE.getStatus();
+        }
+        
+        for (FieldStatusEnum statusEnum : FieldStatusEnum.values()) {
+            if (statusEnum.getCode().equals(code)) {
+                return statusEnum.getStatus();
+            }
+        }
+        
+        return ACTIVE.getStatus();
+    }
+    
+    /**
+     * 根据code获取对应的状态信息
+     * 
+     * @param code 状态编码
+     * @return 状态信息
+     */
+    public static String getInfoByCode(String code) {
+        if (code == null) {
+            return ACTIVE.getInfo();
+        }
+        
+        for (FieldStatusEnum statusEnum : FieldStatusEnum.values()) {
+            if (statusEnum.getCode().equals(code)) {
+                return statusEnum.getInfo();
+            }
+        }
+        
+        return ACTIVE.getInfo();
+    }
+} 

+ 51 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/enums/FieldTypeEnum.java

@@ -0,0 +1,51 @@
+package com.ruoyi.uniapp.domain.enums;
+
+/**
+ * 地块类型枚举
+ * 
+ * @author ruoyi
+ */
+public enum FieldTypeEnum {
+    
+    PADDY_FIELD("0", "水田"),
+    DRY_LAND("1", "旱地"),
+    ORCHARD("2", "果园"),
+    VEGETABLE_FIELD("3", "菜地"),
+    OTHER("4", "其他");
+    
+    private final String code;
+    private final String info;
+    
+    FieldTypeEnum(String code, String info) {
+        this.code = code;
+        this.info = info;
+    }
+    
+    public String getCode() {
+        return code;
+    }
+    
+    public String getInfo() {
+        return info;
+    }
+    
+    /**
+     * 根据code获取对应的地块类型信息
+     * 
+     * @param code 类型编码
+     * @return 类型信息
+     */
+    public static String getInfoByCode(String code) {
+        if (code == null) {
+            return null;
+        }
+        
+        for (FieldTypeEnum typeEnum : FieldTypeEnum.values()) {
+            if (typeEnum.getCode().equals(code)) {
+                return typeEnum.getInfo();
+            }
+        }
+        
+        return code;
+    }
+} 

+ 76 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/domain/vo/FieldVO.java

@@ -0,0 +1,76 @@
+package com.ruoyi.uniapp.domain.vo;
+
+import java.math.BigDecimal;
+import lombok.Data;
+
+/**
+ * 地块信息视图对象
+ * 
+ * @author ruoyi
+ */
+@Data
+public class FieldVO {
+    /*
+     * 地块ID
+     * */
+    private Long id;
+    /*
+     * 地块编号
+     * */
+    private String code;
+    /*
+     * 地块名称
+     * */
+    private String name;
+    /*
+     * 所属农场名称
+     * */
+    private String farmName;
+    /*
+     * 负责人
+     * */
+    private String manager;
+    /*
+     * 面积(亩)
+     * */
+    private BigDecimal area;
+    /*
+     * 地块类型
+     * */
+    private String type;
+    /*
+     * 种植作物
+     * */
+    private String crop;
+    /*
+     * 使用状态(active-使用中,idle-未使用,maintenance-维护中)
+     * */
+    private String status;
+    /*
+     * 设备数量
+     * */
+    private Integer deviceCount;
+    /*
+     * 在线设备数量
+     * */
+    private Integer onlineDevices;
+    /*
+    * 告警数量
+    * */
+    private Integer alerts;
+
+    /*
+     * 地块总数
+     * */
+    private Integer plotsTotal;
+
+    /*
+     * 使用中数量
+     * */
+    private Integer inUseCount;
+
+    /*
+     * 空闲数量
+     * */
+    private Integer leiSureCount;
+}

+ 57 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/mapper/FieldMapper.java

@@ -0,0 +1,57 @@
+package com.ruoyi.uniapp.mapper;
+
+import java.util.List;
+import java.util.Map;
+import com.ruoyi.uniapp.domain.Field;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 地块信息 数据层
+ * 
+ * @author ruoyi
+ */
+public interface FieldMapper {
+    
+    /**
+     * 根据用户ID查询用户关联的地块信息列表
+     * 
+     * @param userId 用户ID
+     * @return 地块信息集合
+     */
+    public List<Field> selectFieldListByUserId(@Param("userId") Long userId);
+
+    
+    /**
+     * 根据用户ID和关键词搜索地块
+     * 
+     * @param userId 用户ID
+     * @param keyword 搜索关键字
+     * @return 地块信息集合
+     */
+    public List<Field> searchFieldsByUserIdAndKeyword(@Param("userId") Long userId, @Param("keyword") String keyword);
+
+
+    /**
+     * 获取用户的地块总数、状态数量;
+     *
+     * @param userId 地块ID
+     * @return 地块总数、状态数量
+     */
+    public Field countFieldTotalByUser(Long userId);
+    
+    /**
+     * 批量获取地块设备数量
+     *
+     * @param fieldIds 地块ID列表
+     * @return 地块ID与设备数量的映射
+     */
+    public List<Map<String, Object>> batchCountDevicesByFieldIds(@Param("fieldIds") List<Long> fieldIds);
+    
+    /**
+     * 批量获取地块在线设备数量
+     *
+     * @param fieldIds 地块ID列表
+     * @return 地块ID与在线设备数量的映射
+     */
+    public List<Map<String, Object>> batchCountOnlineDevicesByFieldIds(@Param("fieldIds") List<Long> fieldIds);
+} 

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

@@ -0,0 +1,49 @@
+package com.ruoyi.uniapp.service;
+
+import java.util.List;
+
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.uniapp.domain.Field;
+import com.ruoyi.uniapp.domain.vo.FieldVO;
+
+/**
+ * 地块信息 服务层
+ * 
+ * @author ruoyi
+ */
+public interface IFieldService {
+    
+    /**
+     * 根据用户ID查询用户关联的地块列表
+     * 
+     * @param userId 用户ID
+     * @return 地块信息集合
+     */
+    public PageInfo<FieldVO> selectFieldListByUserId(Long userId, Integer pageNum, Integer pageSize);
+
+    
+    /**
+     * 根据用户ID和关键词搜索地块
+     * 
+     * @param userId 用户ID
+     * @param keyword 搜索关键词
+     * @return 地块信息集合
+     */
+    public PageInfo<FieldVO> searchFieldsByUserIdAndKeyword(Long userId, String keyword,Integer pageNum, Integer pageSize);
+
+    /**
+     * 获取用户的地块总数、状态数量;
+     *
+     * @param userId 地块ID
+     * @return 地块总数、状态数量
+     */
+    public FieldVO countFieldTotalByUser(Long userId);
+    
+    /**
+     * 转换地块实体为VO对象
+     * 
+     * @param field 地块实体
+     * @return 地块VO对象
+     */
+    public FieldVO convertToVO(Field field);
+} 

+ 193 - 0
ruoyi-modules/ruoyi-uniapp/src/main/java/com/ruoyi/uniapp/service/impl/FieldServiceImpl.java

@@ -0,0 +1,193 @@
+package com.ruoyi.uniapp.service.impl;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.nacos.client.naming.utils.CollectionUtils;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.uniapp.mapper.FieldMapper;
+import com.ruoyi.uniapp.domain.Field;
+import com.ruoyi.uniapp.domain.enums.FieldStatusEnum;
+import com.ruoyi.uniapp.domain.enums.FieldTypeEnum;
+import com.ruoyi.uniapp.domain.vo.FieldVO;
+import com.ruoyi.uniapp.service.IFieldService;
+
+/**
+ * 地块信息 服务层实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class FieldServiceImpl implements IFieldService {
+    @Autowired
+    private FieldMapper fieldMapper;
+
+    /**
+     * 根据用户ID查询用户关联的地块列表
+     *
+     * @param userId    用户ID
+     * @param pageNum   页码
+     * @param pageSize  每页数量
+     * @return 分页信息
+     */
+    public PageInfo<FieldVO> selectFieldListByUserId(Long userId, Integer pageNum, Integer pageSize) {
+        if (userId == null) {
+            return new PageInfo<>(Collections.emptyList());
+        }
+
+        try {
+            PageHelper.startPage(ObjectUtil.defaultIfNull(pageNum, 1), ObjectUtil.defaultIfNull(pageSize, 10));
+            List<Field> fields = fieldMapper.selectFieldListByUserId(userId);
+            PageInfo<Field> sourcePageInfo = new PageInfo<>(fields);
+            return processFields(fields, sourcePageInfo);
+        } catch (Exception e) {
+            return new PageInfo<>(Collections.emptyList());
+        }
+    }
+
+
+    /**
+     * 根据用户ID和关键词搜索地块
+     * 
+     * @param userId 用户ID
+     * @param keyword 搜索关键词
+     * @return 地块信息集合
+     */
+    @Override
+    public PageInfo<FieldVO> searchFieldsByUserIdAndKeyword(Long userId, String keyword, Integer pageNum, Integer pageSize) {
+        if (userId == null) {
+            return new PageInfo<>(Collections.emptyList());
+        }
+
+        try {
+            PageHelper.startPage(ObjectUtil.defaultIfNull(pageNum, 1), ObjectUtil.defaultIfNull(pageSize, 10));
+            List<Field> fields = fieldMapper.searchFieldsByUserIdAndKeyword(userId, keyword);
+            PageInfo<Field> sourcePageInfo = new PageInfo<>(fields);
+            return processFields(fields, sourcePageInfo);
+        } catch (Exception e) {
+            return new PageInfo<>(Collections.emptyList());
+        }
+    }
+
+
+    @Override
+    public FieldVO countFieldTotalByUser(Long userId) {
+        Field field = fieldMapper.countFieldTotalByUser(userId);
+
+        FieldVO fieldVO = new FieldVO();
+        fieldVO.setPlotsTotal(field.getPlotsTotal() != null ? field.getPlotsTotal() : 0);
+        fieldVO.setInUseCount(field.getInUseCount() != null ? field.getInUseCount() : 0);
+        fieldVO.setLeiSureCount(field.getLeiSureCount() != null ? field.getLeiSureCount() : 0);
+        return fieldVO;
+    }
+
+    /**
+     * 转换地块实体为VO对象
+     * 
+     * @param field 地块实体
+     * @return 地块VO对象
+     */
+    @Override
+    public FieldVO convertToVO(Field field) {
+        if (field == null) {
+            return null;
+        }
+        
+        FieldVO vo = new FieldVO();
+        vo.setId(field.getId());
+        vo.setCode(field.getFieldCode());
+        vo.setName(field.getFieldName());
+        vo.setFarmName(field.getFarmName());
+        vo.setManager(field.getManagerName());
+        vo.setArea(field.getSize());
+        
+        // 使用枚举处理地块类型
+        vo.setType(FieldTypeEnum.getInfoByCode(field.getFieldType()));
+        
+        vo.setCrop(field.getGrowCrops());
+        
+        // 使用枚举处理地块状态
+        vo.setStatus(FieldStatusEnum.getStatusByCode(field.getStatus()));
+        
+        // 设备信息
+        vo.setDeviceCount(field.getDeviceCount());
+        vo.setOnlineDevices(field.getOnlineDevices());
+        vo.setAlerts(field.getAlerts());
+        
+        return vo;
+    }
+
+    private PageInfo<FieldVO> processFields(List<Field> fields, PageInfo<Field> sourcePageInfo) {
+        if (CollectionUtils.isEmpty(fields)) {
+            return new PageInfo<>(Collections.emptyList());
+        }
+
+        // 批量查询设备数量和告警信息
+        batchEnrichFieldsWithDeviceInfo(fields);
+
+        // 转换为VO列表
+        List<FieldVO> voList = fields.stream()
+                .map(this::convertToVO)
+                .collect(Collectors.toList());
+
+        // 创建新的分页信息对象并复制属性
+        PageInfo<FieldVO> resultPage = new PageInfo<>(voList);
+        BeanUtils.copyProperties(sourcePageInfo, resultPage, "list");
+
+        return resultPage;
+    }
+    
+    /**
+     * 批量为地块实体填充设备和告警信息
+     * 
+     * @param fields 地块实体列表
+     */
+    private void batchEnrichFieldsWithDeviceInfo(List<Field> fields) {
+        if (fields == null || fields.isEmpty()) {
+            return;
+        }
+        
+        // 提取所有地块ID
+        List<Long> fieldIds = fields.stream()
+                                   .map(Field::getId)
+                                   .collect(Collectors.toList());
+        
+        // 批量查询设备数量
+        List<Map<String, Object>> deviceCountResults = fieldMapper.batchCountDevicesByFieldIds(fieldIds);
+        Map<Long, Integer> deviceCountMap = new HashMap<>();
+        for (Map<String, Object> result : deviceCountResults) {
+            Long fieldId = ((Number) result.get("fieldId")).longValue();
+            Integer count = ((Number) result.get("deviceCount")).intValue();
+            deviceCountMap.put(fieldId, count);
+        }
+        
+        // 批量查询在线设备数量
+        List<Map<String, Object>> onlineDeviceCountResults = fieldMapper.batchCountOnlineDevicesByFieldIds(fieldIds);
+        Map<Long, Integer> onlineDeviceCountMap = new HashMap<>();
+        for (Map<String, Object> result : onlineDeviceCountResults) {
+            Long fieldId = ((Number) result.get("fieldId")).longValue();
+            Integer count = ((Number) result.get("onlineDevices")).intValue();
+            onlineDeviceCountMap.put(fieldId, count);
+        }
+        
+        // 将结果应用到地块对象上
+        for (Field field : fields) {
+            // 设置设备数量
+            Integer deviceCount = deviceCountMap.get(field.getId());
+            field.setDeviceCount(deviceCount != null ? deviceCount : 0);
+            
+            // 设置在线设备数量
+            Integer onlineDevices = onlineDeviceCountMap.get(field.getId());
+            field.setOnlineDevices(onlineDevices != null ? onlineDevices : 0);
+            
+            // 设置告警数量 TODO 等告警列表完善之后再查询
+            field.setAlerts(0);
+        }
+    }
+} 

+ 115 - 0
ruoyi-modules/ruoyi-uniapp/src/main/resources/mapper/FieldMapper.xml

@@ -0,0 +1,115 @@
+<?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.FieldMapper">
+    
+    <resultMap type="com.ruoyi.uniapp.domain.Field" id="FieldResult">
+        <id property="id" column="id"/>
+        <result property="fieldCode" column="field_code"/>
+        <result property="fieldName" column="field_name"/>
+        <result property="farmId" column="farm_id"/>
+        <result property="fieldType" column="field_type"/>
+        <result property="growCrops" column="grow_crops"/>
+        <result property="size" column="size"/>
+        <result property="soilType" column="soil_type"/>
+        <result property="irrigationType" column="irrigation_type"/>
+        <result property="status" column="status"/>
+        <result property="managerId" column="manager_id"/>
+        <result property="managerName" column="manager_name"/>
+        <result property="description" column="description"/>
+        <result property="locationData" column="location_data"/>
+        <result property="createTime" column="created_time"/>
+        <result property="updateTime" column="updated_time"/>
+        <result property="createBy" column="created_by"/>
+        <result property="updateBy" column="updated_by"/>
+        <result property="isDeleted" column="is_deleted"/>
+        <result column="plotsTotal" property="plotsTotal"/>
+        <result column="inUseCount" property="inUseCount"/>
+        <result column="leiSureCount" property="leiSureCount"/>
+    </resultMap>
+    
+    <sql id="selectFieldWithFarm">
+        select
+            f.id, f.field_code, f.field_name, f.farm_id,
+            f.field_type, f.grow_crops, f.size, f.soil_type, f.irrigation_type, 
+            f.status, f.manager_id, f.manager_name, f.description, f.location_data, 
+            f.created_time, f.updated_time, f.created_by, f.updated_by, f.is_deleted
+        from field f
+    </sql>
+    
+    <!-- 根据用户ID查询关联的地块列表 -->
+    <select id="selectFieldListByUserId" parameterType="Long" resultMap="FieldResult">
+        <include refid="selectFieldWithFarm"/>
+        inner join field_personnel fp on f.id = fp.field_id
+        <where>
+            f.is_deleted = 0
+            and fp.is_deleted = 0
+            and fp.status = '0'
+            and fp.user_id = #{userId}
+        </where>
+    </select>
+
+    
+    <!-- 根据用户ID和关键词搜索地块 -->
+    <select id="searchFieldsByUserIdAndKeyword" resultMap="FieldResult">
+        <include refid="selectFieldWithFarm"/>
+        inner join field_personnel fp on f.id = fp.field_id
+        <where>
+            f.is_deleted = 0
+            and fp.is_deleted = 0
+            and fp.status = '0'
+            and fp.user_id = #{userId}
+            <if test="keyword != null and keyword != ''">
+                and (
+                    f.field_code like concat('%', #{keyword}, '%') OR
+                    f.field_name like concat('%', #{keyword}, '%') OR
+                    f.manager_name like concat('%', #{keyword}, '%')
+                )
+            </if>
+        </where>
+    </select>
+
+    <select id="countFieldTotalByUser" parameterType="Long" resultMap="FieldResult">
+        SELECT
+            COUNT(*) AS plotsTotal,
+            COUNT(CASE WHEN f.status = '0' THEN 1 END) AS inUseCount,
+            COUNT(CASE WHEN f.status = '1' THEN 1 END) AS leiSureCount
+        FROM field f
+                 LEFT JOIN field_personnel fp on f.id = fp.field_id
+        where fp.user_id = #{userId}
+    </select>
+
+    <!-- 批量查询地块的设备数量 -->
+    <select id="batchCountDevicesByFieldIds" resultType="java.util.Map">
+        SELECT 
+            field_id as fieldId,
+            COUNT(1) as deviceCount
+        FROM field_device
+        WHERE field_id IN
+        <foreach collection="fieldIds" item="fieldId" open="(" separator="," close=")">
+            #{fieldId}
+        </foreach>
+        AND status = '0'
+        AND is_deleted = 0
+        GROUP BY field_id
+    </select>
+    
+    <!-- 批量查询地块的在线设备数量 -->
+    <select id="batchCountOnlineDevicesByFieldIds" resultType="java.util.Map">
+        SELECT 
+            fd.field_id as fieldId,
+            COUNT(1) as onlineDevices
+        FROM field_device fd
+        LEFT JOIN device d ON fd.device_id = d.id
+        WHERE fd.field_id IN
+        <foreach collection="fieldIds" item="fieldId" open="(" separator="," close=")">
+            #{fieldId}
+        </foreach>
+        AND fd.status = '0'
+        AND fd.is_deleted = 0
+        AND d.status = '1'
+        GROUP BY fd.field_id
+    </select>
+    
+</mapper>