From 695d042bd3d098c793721f9fd30a1f09967bb614 Mon Sep 17 00:00:00 2001 From: wyt <414651037@qq.com> Date: Mon, 8 Dec 2025 10:11:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=BB=84=E5=90=88=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/controller/SheepFileController.java | 189 +++++++++++++++++- .../zhyc/module/base/domain/SheepFile.java | 13 +- .../module/base/mapper/SheepFileMapper.java | 27 +++ .../base/service/ISheepFileService.java | 28 +++ .../service/impl/SheepFileServiceImpl.java | 137 +++++++++++++ .../resources/mapper/base/SheepFileMapper.xml | 133 +++++++++++- 6 files changed, 517 insertions(+), 10 deletions(-) diff --git a/zhyc-module/src/main/java/com/zhyc/module/base/controller/SheepFileController.java b/zhyc-module/src/main/java/com/zhyc/module/base/controller/SheepFileController.java index 6302bb3..6cd5a62 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/base/controller/SheepFileController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/base/controller/SheepFileController.java @@ -13,7 +13,9 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 羊只档案Controller @@ -32,23 +34,155 @@ public class SheepFileController extends BaseController * 查询羊只档案列表 */ @PreAuthorize("@ss.hasPermi('sheep_file:sheep_file:list')") - @GetMapping("/list") - public TableDataInfo list(SheepFile sheepFile) + @PostMapping("/list") // 改为 POST 请求 + public TableDataInfo list(@RequestBody(required = false) Map queryParams) { - startPage(); - List list = sheepFileService.selectSheepFileList(sheepFile); + // 解析查询参数 + SheepFile sheepFile = new SheepFile(); + Map customParams = new HashMap<>(); + + if (queryParams != null && !queryParams.isEmpty()) { + // 提取常规查询参数到 SheepFile 对象 + if (queryParams.containsKey("bsManageTags") && queryParams.get("bsManageTags") != null) { + sheepFile.setBsManageTags(queryParams.get("bsManageTags").toString()); + } + if (queryParams.containsKey("electronicTags") && queryParams.get("electronicTags") != null) { + sheepFile.setElectronicTags(queryParams.get("electronicTags").toString()); + } + if (queryParams.containsKey("drRanch") && queryParams.get("drRanch") != null) { + sheepFile.setDrRanch(queryParams.get("drRanch").toString()); + } + if (queryParams.containsKey("variety") && queryParams.get("variety") != null) { + sheepFile.setVariety(queryParams.get("variety").toString()); + } + if (queryParams.containsKey("name") && queryParams.get("name") != null) { + sheepFile.setName(queryParams.get("name").toString()); + } + if (queryParams.containsKey("gender") && queryParams.get("gender") != null) { + sheepFile.setGender(convertToLong(queryParams.get("gender"))); + } + if (queryParams.containsKey("statusId") && queryParams.get("statusId") != null) { + sheepFile.setStatusId(convertToLong(queryParams.get("statusId"))); + } + if (queryParams.containsKey("breed") && queryParams.get("breed") != null) { + sheepFile.setBreed(queryParams.get("breed").toString()); + } + + // 移除已经处理的参数,剩下的作为自定义筛选参数 + // 注意:不直接修改原参数,而是复制到新Map中 + for (Map.Entry entry : queryParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + // 跳过常规参数 + if ("bsManageTags".equals(key) || "electronicTags".equals(key) || + "drRanch".equals(key) || "variety".equals(key) || + "name".equals(key) || "gender".equals(key) || + "statusId".equals(key) || "breed".equals(key) || + "pageNum".equals(key) || "pageSize".equals(key)) { + continue; + } + + // 添加到自定义参数中 + if (value != null) { + customParams.put(key, value); + } + } + } + + startPage(); // 分页处理 + + // 调用支持复杂查询的Service方法 + List list = sheepFileService.selectSheepFileListByCondition(customParams, sheepFile); return getDataTable(list); } + /** + * 转换对象为Long类型 + */ + private Long convertToLong(Object obj) { + if (obj == null) { + return null; + } + if (obj instanceof Long) { + return (Long) obj; + } + if (obj instanceof Integer) { + return ((Integer) obj).longValue(); + } + if (obj instanceof String) { + try { + return Long.parseLong((String) obj); + } catch (NumberFormatException e) { + return null; + } + } + return null; + } + /** * 导出羊只档案列表 */ @PreAuthorize("@ss.hasPermi('sheep_file:sheep_file:export')") @Log(title = "羊只档案", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, SheepFile sheepFile) + @PostMapping("/export") // 改为 POST 请求 + public void export(HttpServletResponse response, @RequestBody(required = false) Map queryParams) { - List list = sheepFileService.selectSheepFileList(sheepFile); + // 解析查询参数 + SheepFile sheepFile = new SheepFile(); + Map customParams = new HashMap<>(); + + if (queryParams != null && !queryParams.isEmpty()) { + // 提取常规查询参数到 SheepFile 对象 + if (queryParams.containsKey("bsManageTags") && queryParams.get("bsManageTags") != null) { + sheepFile.setBsManageTags(queryParams.get("bsManageTags").toString()); + } + if (queryParams.containsKey("electronicTags") && queryParams.get("electronicTags") != null) { + sheepFile.setElectronicTags(queryParams.get("electronicTags").toString()); + } + if (queryParams.containsKey("drRanch") && queryParams.get("drRanch") != null) { + sheepFile.setDrRanch(queryParams.get("drRanch").toString()); + } + if (queryParams.containsKey("variety") && queryParams.get("variety") != null) { + sheepFile.setVariety(queryParams.get("variety").toString()); + } + if (queryParams.containsKey("name") && queryParams.get("name") != null) { + sheepFile.setName(queryParams.get("name").toString()); + } + if (queryParams.containsKey("gender") && queryParams.get("gender") != null) { + sheepFile.setGender(convertToLong(queryParams.get("gender"))); + } + if (queryParams.containsKey("statusId") && queryParams.get("statusId") != null) { + sheepFile.setStatusId(convertToLong(queryParams.get("statusId"))); + } + if (queryParams.containsKey("breed") && queryParams.get("breed") != null) { + sheepFile.setBreed(queryParams.get("breed").toString()); + } + + // 提取自定义筛选参数 + for (Map.Entry entry : queryParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + // 跳过常规参数和分页参数 + if ("bsManageTags".equals(key) || "electronicTags".equals(key) || + "drRanch".equals(key) || "variety".equals(key) || + "name".equals(key) || "gender".equals(key) || + "statusId".equals(key) || "breed".equals(key) || + "pageNum".equals(key) || "pageSize".equals(key)) { + continue; + } + + // 添加到自定义参数中 + if (value != null) { + customParams.put(key, value); + } + } + } + + // 调用支持复杂查询的Service方法获取数据(不分页) + List list = sheepFileService.selectSheepFileListByCondition(customParams, sheepFile); + ExcelUtil util = new ExcelUtil(SheepFile.class); util.exportExcel(response, list, "羊只档案数据"); } @@ -99,4 +233,45 @@ public class SheepFileController extends BaseController return success(sheepFileService.countInGroup()); } + /** + * 新增API:获取字段的唯一值列表 + * + * 这个API为前端自定义筛选功能提供数据支持 + * 当用户选择某个字段进行筛选时,前端调用此接口获取该字段的所有可能值 + * + * @param fieldName 字段名(数据库列名) + * @return AjaxResult 包含字段值列表的响应结果 + * + * 接口地址:GET /sheep_file/sheep_file/field/{fieldName} + * + * 使用示例: + * 前端请求:GET /sheep_file/sheep_file/field/bs_manage_tags + * 后端返回:{ "code": 200, "msg": "操作成功", "data": ["AF00001", "AF00002", "AF00003"] } + * + * 安全说明: + * - 使用白名单机制防止SQL注入 + * - 只有预定义的字段名可以被查询 + */ + @GetMapping("/field/{fieldName}") + public AjaxResult getFieldValues(@PathVariable String fieldName) { + try { + // 调用Service层获取字段唯一值 + List fieldValues = sheepFileService.getFieldValues(fieldName); + + // 返回成功响应,包含字段值列表 + return AjaxResult.success("获取字段值成功", fieldValues); + + } catch (IllegalArgumentException e) { + // 处理字段名不合法的异常 + // 这种情况通常是因为前端传入了不在白名单中的字段名 + return AjaxResult.error("请求的字段名不合法: " + e.getMessage()); + + } catch (Exception e) { + // 处理其他未知异常 + // 记录日志并返回友好的错误信息 + logger.error("获取字段值失败,字段名: " + fieldName, e); + return AjaxResult.error("系统错误,获取字段值失败"); + } + } + } diff --git a/zhyc-module/src/main/java/com/zhyc/module/base/domain/SheepFile.java b/zhyc-module/src/main/java/com/zhyc/module/base/domain/SheepFile.java index 460ab2d..bd85d0b 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/base/domain/SheepFile.java +++ b/zhyc-module/src/main/java/com/zhyc/module/base/domain/SheepFile.java @@ -101,11 +101,20 @@ public class SheepFile extends BaseEntity /** 断奶体重 */ @Excel(name = "断奶体重") - private Long weaningWeight; + private Double weaningWeight; /** 当前体重 */ @Excel(name = "当前体重") - private Long currentWeight; + private Double currentWeight; + + + /** 断奶日龄 */ + @Excel(name = "断奶日龄") + private Long weaningDayAge; + + /** 断奶日增重 */ + @Excel(name = "断奶日增重") + private Double weaningDailyGain; /** 繁育状态id */ @Excel(name = "繁育状态id") diff --git a/zhyc-module/src/main/java/com/zhyc/module/base/mapper/SheepFileMapper.java b/zhyc-module/src/main/java/com/zhyc/module/base/mapper/SheepFileMapper.java index 9d4fc5a..1a95888 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/base/mapper/SheepFileMapper.java +++ b/zhyc-module/src/main/java/com/zhyc/module/base/mapper/SheepFileMapper.java @@ -2,6 +2,7 @@ package com.zhyc.module.base.mapper; import com.zhyc.module.base.domain.SheepFile; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; @@ -58,6 +59,32 @@ public interface SheepFileMapper List> countParityOfLactation(); + /** + * 新增方法:获取指定字段的唯一值列表 + * + * 这个方法用于查询数据库中某个字段的所有不重复的值 + * 主要用于前端筛选条件中的下拉选项数据 + * + * @param fieldName 字段名(数据库表中的列名) + * @return 该字段的所有唯一值列表,按字母顺序排序 + * + * 使用场景示例: + * - 用户选择"耳号"字段时,返回所有不重复的耳号 + * - 用户选择"品种"字段时,返回所有不重复的品种名称 + */ + List selectFieldValues(String fieldName); + + /** + * 根据复杂条件查询羊只档案列表 + * + * @param params 查询参数映射 + * @param sheepFile 原有的查询条件(保持兼容) + * @return 羊只档案列表 + */ + List selectSheepFileListByCondition( + @Param("params") Map params, + @Param("sheepFile") SheepFile sheepFile + ); } diff --git a/zhyc-module/src/main/java/com/zhyc/module/base/service/ISheepFileService.java b/zhyc-module/src/main/java/com/zhyc/module/base/service/ISheepFileService.java index 8280603..15eaa6d 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/base/service/ISheepFileService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/base/service/ISheepFileService.java @@ -38,4 +38,32 @@ public interface ISheepFileService List> countByBreedStatus(); List> countByVariety(); List> countParityOfLactation(); + + /** + * 新增方法:获取指定字段的唯一值列表 + * + * 这个方法为前端筛选功能提供数据支持 + * 当用户选择某个字段进行筛选时,调用此方法获取该字段的所有可能值 + * + * @param fieldName 字段名(需要是数据库表中的列名) + * @return 该字段的所有唯一值列表 + * @throws IllegalArgumentException 当字段名不在白名单中时抛出异常 + * + * 示例用法: + * List earTags = getFieldValues("bs_manage_tags"); + * // 返回结果可能是:["AF00001", "AF00002", "AF00003", ...] + */ + List getFieldValues(String fieldName); + + /** + * 根据复杂条件查询羊只档案列表 + * + * @param params 查询参数映射 + * @param sheepFile 原有的查询条件 + * @return 羊只档案列表 + */ + List selectSheepFileListByCondition( + Map params, + SheepFile sheepFile + ); } diff --git a/zhyc-module/src/main/java/com/zhyc/module/base/service/impl/SheepFileServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/base/service/impl/SheepFileServiceImpl.java index 929321c..a616dff 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/base/service/impl/SheepFileServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/base/service/impl/SheepFileServiceImpl.java @@ -6,6 +6,7 @@ import com.zhyc.module.base.service.ISheepFileService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.HashMap; import java.util.List;import java.util.Map; /** @@ -69,5 +70,141 @@ public class SheepFileServiceImpl implements ISheepFileService { @Override public Long countInGroup() { return sheepFileMapper.countInGroup(); } + /** + * 获取指定字段的唯一值列表 + * + * 这个方法实现了获取字段唯一值的核心逻辑 + * 包含安全验证和业务处理 + * + * @param fieldName 字段名 + * @return 该字段的所有唯一值列表 + * @throws IllegalArgumentException 当字段名不在白名单中时抛出异常 + */ + @Override + public List getFieldValues(String fieldName) { + // 第一步:安全性验证 - 防止SQL注入攻击 + // 只允许预定义的字段名,确保查询的安全性 + if (!isValidFieldName(fieldName)) { + // 如果字段名不在白名单中,抛出异常并记录日志 + throw new IllegalArgumentException("非法的字段名: " + fieldName + ",请检查字段名是否正确"); + } + + // 第二步:调用Mapper层执行数据库查询 + // 这里会执行类似 SELECT DISTINCT fieldName FROM sheep_file 的SQL + List fieldValues = sheepFileMapper.selectFieldValues(fieldName); + + // 第三步:返回查询结果 + return fieldValues; + } + + @Override + public List selectSheepFileListByCondition(Map params, SheepFile sheepFile) { + // 验证参数中的字段名,防止SQL注入 + if (params != null && !params.isEmpty()) { + Map safeParams = new HashMap<>(); + + for (Map.Entry entry : params.entrySet()) { + String fieldName = entry.getKey(); + Object value = entry.getValue(); + + // 将前端字段名转换为数据库字段名 + String dbFieldName = convertToDbFieldName(fieldName); + + // 验证字段名是否安全(使用白名单) + if (isValidFieldName(dbFieldName)) { + safeParams.put(dbFieldName, value); + } else { + // 记录日志或抛出异常 + System.out.println("警告:忽略非法字段名: " + fieldName); + } + } + + return sheepFileMapper.selectSheepFileListByCondition(safeParams, sheepFile); + } + + // 如果没有额外参数,使用原有的查询方法 + return sheepFileMapper.selectSheepFileList(sheepFile); + } + + /** + * 将前端字段名转换为数据库字段名 + */ + private String convertToDbFieldName(String fieldName) { + // 将驼峰命名转换为下划线命名 + String result = fieldName.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase(); + return result; + } + + /** + * 扩展字段名白名单验证 + */ + private boolean isValidFieldName(String fieldName) { + // 扩展允许查询的字段白名单 + String[] allowedFields = { + "id", + "bs_manage_tags", // 管理耳号 + "electronic_tags", // 电子耳号 + "dr_ranch", // 牧场名称 + "sheepfold_name", // 羊舍名称 + "variety", // 品种 + "family", // 家系 + "name", // 羊只类型 + "gender", // 性别 + "birthday", // 出生日期 + "day_age", // 日龄 + "month_age", // 月龄 + "parity", // 胎次 + "birth_weight", // 出生体重 + "weaning_date", // 断奶日期 + "status_id", // 羊只状态 + "weaning_weight", // 断奶体重 + "current_weight", // 当前体重 + "weaning_day_age", // 断奶日龄 + "weaning_daily_gain", // 断奶日增重 + "breed", // 繁殖状态 + "father_manage_tags", // 父亲耳号 + "mother_manage_tags", // 母亲耳号 + "receptor_manage_tags", // 受体耳号 + "grandfather_manage_tags", // 祖父耳号 + "grandmother_manage_tags", // 祖母耳号 + "maternal_grandfather_manage_tags", // 外祖父耳号 + "maternal_grandmother_manage_tags", // 外祖母耳号 + "mating_date", // 配种日期 + "mating_type_id", // 配种类型 + "preg_date", // 孕检日期 + "lambing_date", // 产羔日期 + "lambing_day", // 产羔时怀孕天数 + "mating_day", // 配后天数 + "gestation_day", // 怀孕天数 + "expected_date", // 预产日期 + "post_lambing_day", // 产后天数 + "lactation_day", // 泌乳天数 + "anestrous_day", // 空怀天数 + "mating_counts", // 配种次数 + "mating_total", // 累计配种次数 + "miscarriage_counts", // 累计流产次数 + "comment", // 备注 + "controlled", // 是否性控 + "body", // 体况评分 + "breast", // 乳房评分 + "source", // 入群来源 + "source_date", // 入群日期 + "source_ranch", // 来源牧场 + "update_by", // 修改人 + "update_time", // 修改日期 + "create_by", // 创建人 + "create_time" // 创建日期 + }; + + for (String allowedField : allowedFields) { + if (allowedField.equals(fieldName)) { + return true; + } + } + + return false; + } + + } diff --git a/zhyc-module/src/main/resources/mapper/base/SheepFileMapper.xml b/zhyc-module/src/main/resources/mapper/base/SheepFileMapper.xml index fd67991..e7d43e9 100644 --- a/zhyc-module/src/main/resources/mapper/base/SheepFileMapper.xml +++ b/zhyc-module/src/main/resources/mapper/base/SheepFileMapper.xml @@ -26,6 +26,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -72,7 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, bs_manage_tags, ranch_id, dr_ranch, sheepfold_id, sheepfold_name, electronic_tags, variety_id, variety, family, name, gender, birthday, day_age, month_age, parity, birth_weight, weaning_date, status_id, weaning_weight, current_weight, breed_status_id, breed, bs_father_id, father_manage_tags, bs_mother_id, mother_manage_tags, receptor_id, receptor_manage_tags, father_father_id, grandfather_manage_tags, father_mother_id, grandmother_manage_tags, father_id, maternal_grandfather_manage_tags, mother_id, maternal_grandmother_manage_tags, mating_date, mating_type_id, preg_date, lambing_date, lambing_day, mating_day, gestation_day, expected_date, post_lambing_day, lactation_day, anestrous_day, mating_counts, mating_total, miscarriage_counts, comment, controlled, body, breast, source, source_date, source_ranch_id, source_ranch, update_by, update_time, create_by, create_time, is_delete from sheep_file + select id, bs_manage_tags, ranch_id, dr_ranch, sheepfold_id, sheepfold_name, electronic_tags, variety_id, variety, family, name, gender, birthday, day_age, month_age, parity, birth_weight, weaning_date, status_id, weaning_weight, current_weight,weaning_day_age,weaning_daily_gain,breed_status_id, breed, bs_father_id, father_manage_tags, bs_mother_id, mother_manage_tags, receptor_id, receptor_manage_tags, father_father_id, grandfather_manage_tags, father_mother_id, grandmother_manage_tags, father_id, maternal_grandfather_manage_tags, mother_id, maternal_grandmother_manage_tags, mating_date, mating_type_id, preg_date, lambing_date, lambing_day, mating_day, gestation_day, expected_date, post_lambing_day, lactation_day, anestrous_day, mating_counts, mating_total, miscarriage_counts, comment, controlled, body, breast, source, source_date, source_ranch_id, source_ranch, update_by, update_time, create_by, create_time, is_delete from sheep_file + + + \ No newline at end of file