From e177df656fb2747a5ffff5a3328931f6db7cf2ad Mon Sep 17 00:00:00 2001 From: zyk Date: Wed, 4 Feb 2026 09:09:26 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BA=A7=E7=BE=94=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=85=A8=E9=83=A8=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/mapper/produce/breed/ScLambingRecordMapper.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zhyc-module/src/main/resources/mapper/produce/breed/ScLambingRecordMapper.xml b/zhyc-module/src/main/resources/mapper/produce/breed/ScLambingRecordMapper.xml index ca99ee7..9dc5c66 100644 --- a/zhyc-module/src/main/resources/mapper/produce/breed/ScLambingRecordMapper.xml +++ b/zhyc-module/src/main/resources/mapper/produce/breed/ScLambingRecordMapper.xml @@ -159,6 +159,7 @@ br.ram_id as ram_id, ram.bs_manage_tags as male_ear_number, ram.variety as male_breed, + ram.family as male_lineage, br.create_time as breeding_date, DATEDIFF(CURDATE(), br.create_time) as pregnancy_days, br.technician as technician @@ -212,8 +213,6 @@ technician = #{technician}, score = #{score}, comment = #{comment}, - update_by = #{updateBy}, - update_time = #{updateTime}, where id = #{id} From bbc19b47cacceb3a07d1c32d298c350688f5dad7 Mon Sep 17 00:00:00 2001 From: zyk Date: Tue, 10 Feb 2026 14:04:43 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E7=B9=81=E8=82=B2=E5=A4=9A=E8=80=B3?= =?UTF-8?q?=E5=8F=B7=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../breed/controller/ScDryMilkController.java | 18 ++++-- .../controller/ScSheepDeathController.java | 14 +++++ .../controller/ScWeanRecordController.java | 23 ++++--- .../produce/breed/domain/ScDryMilk.java | 10 +++ .../produce/breed/domain/ScSheepDeath.java | 1 + .../produce/breed/domain/ScWeanRecord.java | 15 +++-- .../produce/breed/mapper/ScDryMilkMapper.java | 7 +++ .../breed/mapper/ScSheepDeathMapper.java | 8 +++ .../breed/mapper/ScWeanRecordMapper.java | 5 +- .../breed/service/IScDryMilkService.java | 8 +++ .../breed/service/IScSheepDeathService.java | 8 +++ .../breed/service/IScWeanRecordService.java | 3 +- .../service/impl/ScDryMilkServiceImpl.java | 5 ++ .../service/impl/ScSheepDeathServiceImpl.java | 4 ++ .../service/impl/ScWeanRecordServiceImpl.java | 5 -- .../mapper/produce/breed/ScDryMilkMapper.xml | 14 ++++- .../produce/breed/ScSheepDeathMapper.xml | 61 +++++++++++++++++-- .../produce/breed/ScWeanRecordMapper.xml | 19 +++--- 18 files changed, 186 insertions(+), 42 deletions(-) diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScDryMilkController.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScDryMilkController.java index 7b8913e..a00bcd4 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScDryMilkController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScDryMilkController.java @@ -79,14 +79,20 @@ public class ScDryMilkController extends BaseController /** * 远程搜索耳号列表 */ + /** + * 模糊查询母羊耳号列表 + */ + @PreAuthorize("@ss.hasPermi('drymilk:drymilk:query')") // 根据实际权限修改 @GetMapping("/searchEarNumbers") - public AjaxResult searchEarNumbers(@RequestParam(value = "query", required = false) String query) - { - if (query == null) query = ""; - List list = scDryMilkService.selectSheepEarNumberList(query); - return AjaxResult.success(list); + public AjaxResult searchEarNumbers(@RequestParam("query") String query) { + try { + List earNumbers = scDryMilkService.searchEarNumbers(query); + return success(earNumbers); + } catch (Exception e) { + logger.error("搜索耳号异常", e); + return error("搜索耳号失败:" + e.getMessage()); + } } - /** * 远程搜索技术员列表 */ diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScSheepDeathController.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScSheepDeathController.java index 8a62b95..22e7daf 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScSheepDeathController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScSheepDeathController.java @@ -41,6 +41,20 @@ public class ScSheepDeathController extends BaseController @Autowired private ISwDiseaseService swDiseaseService; + /** + * 模糊查询母羊耳号列表 + */ + @PreAuthorize("@ss.hasPermi('/sheep_death/death:query')") // 根据实际权限修改 + @GetMapping("/search_ear_numbers") + public AjaxResult searchEarNumbers(@RequestParam("query") String query) { + try { + List earNumbers = scSheepDeathService.searchEarNumbers(query); + return success(earNumbers); + } catch (Exception e) { + logger.error("搜索耳号异常", e); + return error("搜索耳号失败:" + e.getMessage()); + } + } /** * 查询羊只死淘记录列表 */ diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScWeanRecordController.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScWeanRecordController.java index 4579927..3d15de7 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScWeanRecordController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScWeanRecordController.java @@ -36,15 +36,6 @@ public class ScWeanRecordController extends BaseController { return getDataTable(list); } - /** - * 【新增】模糊查询耳号列表 (用于前端下拉框远程搜索) - */ - @PreAuthorize("@ss.hasPermi('Weaning:weaning_record:list')") - @GetMapping("/search_ear_numbers") - public AjaxResult searchEarNumbers(@RequestParam("query") String query) { - List list = scWeanRecordService.searchEarNumbers(query); - return success(list); - } /** * 导出断奶记录列表 @@ -129,5 +120,19 @@ public class ScWeanRecordController extends BaseController { return toAjax(scWeanRecordService.deleteScWeanRecordByIds(ids)); } + /** + * 模糊查询母羊耳号列表 + */ + @PreAuthorize("@ss.hasPermi('breed:lambing_records:query')") // 根据实际权限修改 + @GetMapping("/search_ear_numbers") + public AjaxResult searchEarNumbers(@RequestParam("query") String query) { + try { + List earNumbers = scWeanRecordService.searchEarNumbers(query); + return success(earNumbers); + } catch (Exception e) { + logger.error("搜索耳号异常", e); + return error("搜索耳号失败:" + e.getMessage()); + } + } } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScDryMilk.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScDryMilk.java index 5c0f51f..26747cd 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScDryMilk.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScDryMilk.java @@ -18,6 +18,16 @@ public class ScDryMilk extends BaseEntity { private static final long serialVersionUID = 1L; + /** 全部羊耳号列表(用于多耳号查询) */ + private List allEarNumbers; + + public List getAllEarNumbers() { + return allEarNumbers; + } + + public void setAllEarNumbers(List allEarNumbers) { + this.allEarNumbers = allEarNumbers; + } /** 主键id */ private Long id; diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScSheepDeath.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScSheepDeath.java index 54e7171..dc51324 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScSheepDeath.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScSheepDeath.java @@ -18,6 +18,7 @@ public class ScSheepDeath extends BaseEntity { private static final long serialVersionUID = 1L; + /** 主键ID */ private Long id; diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScWeanRecord.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScWeanRecord.java index 9c5088a..76b5951 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScWeanRecord.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/domain/ScWeanRecord.java @@ -22,6 +22,17 @@ public class ScWeanRecord extends BaseEntity { /** 主键ID */ private Long id; + /** 全部羊耳号列表(用于多耳号查询) */ + private List allEarNumbers; + + public List getAllEarNumbers() { + return allEarNumbers; + } + + public void setAllEarNumbers(List allEarNumbers) { + this.allEarNumbers = allEarNumbers; + } + /** 羊只ID */ @Excel(name = "羊只ID") private Long sheepId; @@ -51,10 +62,6 @@ public class ScWeanRecord extends BaseEntity { @Excel(name = "电子耳号") private String electronicTags; - // --- 新增查询字段 --- - - /** 多耳号查询列表 */ - private List allEarNumbers; /** 是否在群 (1是 0否) */ private String isInHerd; diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScDryMilkMapper.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScDryMilkMapper.java index 2fbeff2..cbe1bad 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScDryMilkMapper.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScDryMilkMapper.java @@ -69,4 +69,11 @@ public interface ScDryMilkMapper * 远程搜索技术员列表 */ public List searchTechnicianList(@Param("query") String query); + /** + * 模糊查询母羊耳号列表 + * + * @param query 查询关键字 + * @return 耳号列表 + */ + List searchEarNumbers(@Param("query") String query); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScSheepDeathMapper.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScSheepDeathMapper.java index b0e1a9d..9a36129 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScSheepDeathMapper.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScSheepDeathMapper.java @@ -85,4 +85,12 @@ public interface ScSheepDeathMapper * 远程搜索:处理人 */ public List selectDistinctHandler(@Param("query") String query); + + /** + * 模糊查询母羊耳号列表 + * + * @param query 查询关键字 + * @return 耳号列表 + */ + List searchEarNumbers(@Param("query") String query); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScWeanRecordMapper.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScWeanRecordMapper.java index 3958729..591e74c 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScWeanRecordMapper.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScWeanRecordMapper.java @@ -68,9 +68,10 @@ public interface ScWeanRecordMapper public int updateBasSheepWeaningInfo(ScWeanRecord scWeanRecord); /** - * 【新增】模糊查询耳号列表 (用于前端远程搜索) + * 模糊查询母羊耳号列表 + * * @param query 查询关键字 * @return 耳号列表 */ - public List searchEarNumbers(@Param("query") String query); + List searchEarNumbers(@Param("query") String query); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScDryMilkService.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScDryMilkService.java index 5b3b4e7..b70ca40 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScDryMilkService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScDryMilkService.java @@ -66,4 +66,12 @@ public interface IScDryMilkService * 远程搜索技术员列表 */ public List selectTechnicianList(String query); + + /** + * 模糊查询母羊耳号列表 + * + * @param query 查询关键字 + * @return 耳号列表 + */ + public List searchEarNumbers(String query); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScSheepDeathService.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScSheepDeathService.java index b0f6bfb..dc48433 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScSheepDeathService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScSheepDeathService.java @@ -82,4 +82,12 @@ public interface IScSheepDeathService * 远程搜索:处理人 */ public List selectDistinctHandler(String query); + + /** + * 模糊查询母羊耳号列表 + * + * @param query 查询关键字 + * @return 耳号列表 + */ + public List searchEarNumbers(String query); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScWeanRecordService.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScWeanRecordService.java index ee113bb..e038f91 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScWeanRecordService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScWeanRecordService.java @@ -61,7 +61,8 @@ public interface IScWeanRecordService public Long selectSheepIdByEarNumber(String earNumber); /** - * 【新增】模糊查询耳号列表 + * 模糊查询母羊耳号列表 + * * @param query 查询关键字 * @return 耳号列表 */ diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScDryMilkServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScDryMilkServiceImpl.java index d699682..8b514aa 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScDryMilkServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScDryMilkServiceImpl.java @@ -104,4 +104,9 @@ public class ScDryMilkServiceImpl implements IScDryMilkService public List selectTechnicianList(String query) { return scDryMilkMapper.searchTechnicianList(query); } + + @Override + public List searchEarNumbers(String query) { + return scDryMilkMapper.searchEarNumbers(query); + } } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScSheepDeathServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScSheepDeathServiceImpl.java index 1ae2435..b0fff0c 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScSheepDeathServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScSheepDeathServiceImpl.java @@ -49,6 +49,10 @@ public class ScSheepDeathServiceImpl implements IScSheepDeathService { return scSheepDeathMapper.selectSheepFileByManageTags(manageTags); } + @Override + public List searchEarNumbers(String query) { + return scSheepDeathMapper.searchEarNumbers(query); + } @Override @Transactional diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScWeanRecordServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScWeanRecordServiceImpl.java index 7931efc..baf2eec 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScWeanRecordServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScWeanRecordServiceImpl.java @@ -114,11 +114,6 @@ public class ScWeanRecordServiceImpl implements IScWeanRecordService return scWeanRecordMapper.selectSheepIdByEarNumber(earNumber); } - /** - * 【新增】模糊查询耳号列表 (用于前端远程搜索) - * @param query 查询关键字 - * @return 耳号列表 - */ @Override public List searchEarNumbers(String query) { return scWeanRecordMapper.searchEarNumbers(query); diff --git a/zhyc-module/src/main/resources/mapper/produce/breed/ScDryMilkMapper.xml b/zhyc-module/src/main/resources/mapper/produce/breed/ScDryMilkMapper.xml index 8b0f903..564f6cd 100644 --- a/zhyc-module/src/main/resources/mapper/produce/breed/ScDryMilkMapper.xml +++ b/zhyc-module/src/main/resources/mapper/produce/breed/ScDryMilkMapper.xml @@ -33,6 +33,16 @@ \ No newline at end of file diff --git a/zhyc-module/src/main/resources/mapper/produce/breed/ScSheepDeathMapper.xml b/zhyc-module/src/main/resources/mapper/produce/breed/ScSheepDeathMapper.xml index b5ba0c9..49f390f 100644 --- a/zhyc-module/src/main/resources/mapper/produce/breed/ScSheepDeathMapper.xml +++ b/zhyc-module/src/main/resources/mapper/produce/breed/ScSheepDeathMapper.xml @@ -39,15 +39,52 @@ select d.id, d.sheep_id, d.manage_tags, d.event_type, d.death_date, d.disease_type_id, d.disease_subtype_id, d.disposal_direction, d.technician, d.handler, d.work_group, d.create_by, d.create_time, d.comment, d.update_by, d.update_time, d.is_delete, - s.variety, s.name as sheep_type_name, s.gender, s.day_age, s.parity, s.sheepfold_name, - s.breed as breed_status, s.post_lambing_day, s.lactation_day, s.gestation_day + + /* --- 关联数据获取 --- */ + /* 1. 品种名称 (假设品种表是 bas_variety) */ + (SELECT variety FROM bas_sheep_variety WHERE id = s.variety_id) as variety, + + /* 2. 羊只类型名称 (从字典表获取) */ + (SELECT dict_label FROM sys_dict_data WHERE dict_type = 'sys_sheep_type' AND dict_value = s.type_id) as sheep_type_name, + + /* 3. 性别直接获取 */ + s.gender, + + /* 4. 计算日龄 (当前日期 - 出生日期) */ + DATEDIFF(NOW(), s.birthday) as day_age, + + /* 5. 胎次 */ + s.parity, + + /* 6. 羊舍名称 (假设羊舍表是 bas_sheepfold) */ + (SELECT sheepfold_name FROM da_sheepfold WHERE id = s.sheepfold_id) as sheepfold_name, + + /* 7. 繁育状态 (从字典表获取) */ + (SELECT breed FROM bas_breed_status WHERE id = s.status_id) as breed, + + /* 8. 其他数值字段 */ + s.post_lambing_day, + s.lactation_day, + s.gestation_day + from sc_sheep_death d - left join sheep_file s on d.manage_tags = s.bs_manage_tags + /* 关键修改:直接关联 bas_sheep 表,而不是视图 */ + /* 同时只通过 manage_tags 关联,忽略 status_id 的限制 */ + left join bas_sheep s on d.manage_tags = s.manage_tags AND s.is_delete = 0 - + SELECT DISTINCT sf.bs_manage_tags + FROM sheep_file sf + WHERE sf.bs_manage_tags LIKE CONCAT(#{query}, '%') + AND sf.is_delete = 0 + ORDER BY sf.bs_manage_tags + LIMIT 50 + + + \ No newline at end of file From 4818ed5fc5f61a83d56a37bfd2b410b47367ba3a Mon Sep 17 00:00:00 2001 From: zyk Date: Tue, 3 Mar 2026 10:21:46 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E9=85=8D=E7=A7=8D=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ScBreedPlanGenerateController.java | 114 ++++- .../mapper/ScBreedPlanGenerateMapper.java | 22 + .../service/IScBreedPlanGenerateService.java | 9 + .../impl/ScBreedPlanGenerateServiceImpl.java | 473 ++++++++++++------ .../breed/ScBreedPlanGenerateMapper.xml | 141 ++++-- 5 files changed, 519 insertions(+), 240 deletions(-) diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScBreedPlanGenerateController.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScBreedPlanGenerateController.java index 513d72f..5d5ad72 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScBreedPlanGenerateController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/controller/ScBreedPlanGenerateController.java @@ -10,6 +10,7 @@ import com.zhyc.module.produce.breed.service.IScBreedPlanGenerateService; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import com.zhyc.common.annotation.Log; import com.zhyc.common.core.controller.BaseController; import com.zhyc.common.core.domain.AjaxResult; @@ -65,7 +66,89 @@ public class ScBreedPlanGenerateController extends BaseController } /** - * 自动生成配种计划 + * 导出已选母羊公羊配对表(供用户下载后手动填写/确认配对) + */ + @PreAuthorize("@ss.hasPermi('mating_plan:generate:export')") + @Log(title = "导出配对模板", businessType = BusinessType.EXPORT) + @PostMapping("/exportPairs") + public void exportSelectedPairs(HttpServletResponse response, @RequestBody Map params) + { + try { + List eweIdsRaw = (List) params.get("eweIds"); + List ramIdsRaw = (List) params.get("ramIds"); + + if (eweIdsRaw == null || ramIdsRaw == null) { + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"参数不能为空\"}"); + return; + } + + List eweIds = eweIdsRaw.stream() + .map(obj -> obj instanceof Integer ? ((Integer) obj).longValue() + : obj instanceof Long ? (Long) obj : Long.valueOf(obj.toString())) + .collect(Collectors.toList()); + + List ramIds = ramIdsRaw.stream() + .map(obj -> obj instanceof Integer ? ((Integer) obj).longValue() + : obj instanceof Long ? (Long) obj : Long.valueOf(obj.toString())) + .collect(Collectors.toList()); + + scBreedPlanGenerateService.exportSelectedPairs(response, eweIds, ramIds); + } catch (Exception e) { + logger.error("导出配对表失败", e); + try { + response.setContentType("application/json;charset=utf-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"导出失败:" + e.getMessage() + "\"}"); + } catch (Exception ex) { + logger.error("返回错误信息失败", ex); + } + } + } + + /** + * 解析导入的配对Excel,返回配对预览数据(不生成计划) + */ + @PreAuthorize("@ss.hasPermi('mating_plan:generate:add')") + @PostMapping("/parsePairs") + public AjaxResult parsePairsFromExcel(@RequestParam("file") MultipartFile file) + { + try { + List> pairs = scBreedPlanGenerateService.parsePairsFromExcel(file); + return success(pairs); + } catch (Exception e) { + logger.error("解析配对Excel失败", e); + return error("解析失败:" + e.getMessage()); + } + } + + /** + * 根据导入的配对数据生成配种计划 + */ + @PreAuthorize("@ss.hasPermi('mating_plan:generate:auto')") + @PostMapping("/generateFromPairs") + @Log(title = "导入生成配种计划", businessType = BusinessType.INSERT) + public AjaxResult generateBreedPlanFromPairs(@RequestBody Map params) + { + try { + Integer planType = params.get("planType") != null ? (Integer) params.get("planType") : 1; + + @SuppressWarnings("unchecked") + List> pairs = (List>) params.get("pairs"); + + if (pairs == null || pairs.isEmpty()) { + return error("配对数据不能为空"); + } + + ScBreedPlanGenerate planGenerate = scBreedPlanGenerateService.autoGenerateBreedPlanFromPairs(planType, pairs); + return success(planGenerate); + } catch (Exception e) { + logger.error("导入生成配种计划失败", e); + return error("生成失败:" + e.getMessage()); + } + } + + /** + * 自动生成配种计划(原有逻辑保留,按比例自动分配) */ @PreAuthorize("@ss.hasPermi('mating_plan:generate:auto')") @PostMapping("/auto") @@ -73,13 +156,9 @@ public class ScBreedPlanGenerateController extends BaseController public AjaxResult autoGenerateBreedPlan(@RequestBody Map params) { try { - // 获取计划类型 Integer planType = params.get("planType") != null ? (Integer) params.get("planType") : 1; - - // 计划名称由系统自动生成,不再从前端传入 String planName = null; - // 安全的类型转换 List eweIdsRaw = (List) params.get("eweIds"); List ramIdsRaw = (List) params.get("ramIds"); @@ -88,27 +167,13 @@ public class ScBreedPlanGenerateController extends BaseController } List eweIds = eweIdsRaw.stream() - .map(obj -> { - if (obj instanceof Integer) { - return ((Integer) obj).longValue(); - } else if (obj instanceof Long) { - return (Long) obj; - } else { - return Long.valueOf(obj.toString()); - } - }) + .map(obj -> obj instanceof Integer ? ((Integer) obj).longValue() + : obj instanceof Long ? (Long) obj : Long.valueOf(obj.toString())) .collect(Collectors.toList()); List ramIds = ramIdsRaw.stream() - .map(obj -> { - if (obj instanceof Integer) { - return ((Integer) obj).longValue(); - } else if (obj instanceof Long) { - return (Long) obj; - } else { - return Long.valueOf(obj.toString()); - } - }) + .map(obj -> obj instanceof Integer ? ((Integer) obj).longValue() + : obj instanceof Long ? (Long) obj : Long.valueOf(obj.toString())) .collect(Collectors.toList()); ScBreedPlanGenerate planGenerate = scBreedPlanGenerateService.autoGenerateBreedPlan(planType, planName, eweIds, ramIds); @@ -222,7 +287,6 @@ public class ScBreedPlanGenerateController extends BaseController scBreedPlanGenerateService.exportBreedPlanDetails(response, id); } catch (Exception e) { logger.error("导出配种计划详情失败", e); - // 在出错时返回错误信息给前端 try { response.setContentType("application/json;charset=utf-8"); response.getWriter().write("{\"code\":500,\"msg\":\"导出失败:" + e.getMessage() + "\"}"); @@ -246,7 +310,7 @@ public class ScBreedPlanGenerateController extends BaseController /** * 模糊查询母羊耳号列表 */ - @PreAuthorize("@ss.hasPermi('mating_plan:generate:query')") // 根据实际权限修改 + @PreAuthorize("@ss.hasPermi('mating_plan:generate:query')") @GetMapping("/search_ear_numbers") public AjaxResult searchEarNumbers(@RequestParam("query") String query) { try { diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScBreedPlanGenerateMapper.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScBreedPlanGenerateMapper.java index a9d1e66..eca393b 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScBreedPlanGenerateMapper.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/mapper/ScBreedPlanGenerateMapper.java @@ -136,4 +136,26 @@ public interface ScBreedPlanGenerateMapper * @return 耳号列表 */ List searchEarNumbers(@Param("query") String query); + + /** + * 根据ID列表查询羊只耳号 + * + * @param ids 羊只ID列表 + * @param gender 性别:1=母羊,2=公羊 + * @return 包含 id、manage_tags 的 Map 列表 + */ + List> selectEarNumbersByIds( + @Param("ids") List ids, + @Param("gender") int gender); + + /** + * 根据管理耳号查询羊只ID + * + * @param manageTags 管理耳号 + * @param gender 性别:1=母羊,2=公羊 + * @return 羊只ID + */ + Long selectSheepIdByManageTags( + @Param("manageTags") String manageTags, + @Param("gender") int gender); } \ No newline at end of file diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScBreedPlanGenerateService.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScBreedPlanGenerateService.java index cabf073..b89001e 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScBreedPlanGenerateService.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/IScBreedPlanGenerateService.java @@ -4,7 +4,9 @@ import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import com.zhyc.module.produce.breed.domain.ScBreedPlanGenerate; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; /** * 配种计划生成Service接口 @@ -44,6 +46,13 @@ public interface IScBreedPlanGenerateService */ public List> selectEligibleRam(@RequestParam(value = "manageTags", required = false) String manageTags); + void exportSelectedPairs(HttpServletResponse response, List eweIds, List ramIds); + + List> parsePairsFromExcel(MultipartFile file); + + @Transactional + ScBreedPlanGenerate autoGenerateBreedPlanFromPairs(Integer planType, List> pairs); + /** * 自动生成配种计划 * diff --git a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScBreedPlanGenerateServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScBreedPlanGenerateServiceImpl.java index c76eb04..f8212a9 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScBreedPlanGenerateServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/produce/breed/service/impl/ScBreedPlanGenerateServiceImpl.java @@ -3,9 +3,11 @@ package com.zhyc.module.produce.breed.service.impl; import java.util.List; import java.util.Map; import java.util.HashMap; +import java.util.ArrayList; import java.util.Date; import java.text.SimpleDateFormat; import java.io.IOException; +import java.io.InputStream; import javax.servlet.http.HttpServletResponse; import com.zhyc.module.produce.breed.domain.ScBreedPlan; @@ -16,6 +18,7 @@ import com.zhyc.module.produce.breed.service.IScBreedPlanGenerateService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import com.zhyc.common.utils.SecurityUtils; import org.springframework.util.StringUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; @@ -40,9 +43,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 查询配种计划生成 - * - * @param id 配种计划生成主键 - * @return 配种计划生成 */ @Override public ScBreedPlanGenerate selectScBreedPlanGenerateById(Long id) @@ -52,9 +52,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 查询配种计划生成列表 - * - * @param scBreedPlanGenerate 配种计划生成 - * @return 配种计划生成 */ @Override public List selectScBreedPlanGenerateList(ScBreedPlanGenerate scBreedPlanGenerate) @@ -64,8 +61,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 筛选符合条件的母羊 - * - * @return 符合条件的母羊列表 */ @Override public List> selectEligibleEwe(@RequestParam(value = "manageTags", required = false) String manageTags) @@ -75,8 +70,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 筛选符合条件的公羊 - * - * @return 符合条件的公羊列表 */ @Override public List> selectEligibleRam(@RequestParam(value = "manageTags", required = false) String manageTags) @@ -85,26 +78,302 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi } /** - * 自动生成配种计划 + * 导出已选母羊公羊配对表 + * 按轮询方式将母羊分配给公羊,导出Excel,两列:母羊耳号、公羊耳号 + * + * @param response HTTP响应 + * @param eweIds 已选母羊ID列表 + * @param ramIds 已选公羊ID列表 + */ + @Override + public void exportSelectedPairs(HttpServletResponse response, List eweIds, List ramIds) + { + try { + // 查询母羊耳号(gender=1) + List> eweList = scBreedPlanGenerateMapper.selectEarNumbersByIds(eweIds, 1); + // 查询公羊耳号(gender=2) + List> ramList = scBreedPlanGenerateMapper.selectEarNumbersByIds(ramIds, 2); + + // 建立ID->耳号 的快速查找 + Map eweEarMap = new HashMap<>(); + for (Map e : eweList) { + eweEarMap.put(Long.valueOf(e.get("id").toString()), e.get("manage_tags").toString()); + } + Map ramEarMap = new HashMap<>(); + for (Map r : ramList) { + ramEarMap.put(Long.valueOf(r.get("id").toString()), r.get("manage_tags").toString()); + } + + // 母羊列、公羊列各自独立写入,行数取两者最大值,不做轮询配对 + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("配种配对表"); + + // 母羊表头样式(粉色) + CellStyle eweHeaderStyle = workbook.createCellStyle(); + Font eweFont = workbook.createFont(); + eweFont.setBold(true); + eweFont.setFontHeightInPoints((short) 12); + eweHeaderStyle.setFont(eweFont); + eweHeaderStyle.setAlignment(HorizontalAlignment.CENTER); + eweHeaderStyle.setFillForegroundColor(IndexedColors.ROSE.getIndex()); + eweHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + setBorder(eweHeaderStyle); + + // 公羊表头样式(浅蓝) + CellStyle ramHeaderStyle = workbook.createCellStyle(); + Font ramFont = workbook.createFont(); + ramFont.setBold(true); + ramFont.setFontHeightInPoints((short) 12); + ramHeaderStyle.setFont(ramFont); + ramHeaderStyle.setAlignment(HorizontalAlignment.CENTER); + ramHeaderStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); + ramHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + setBorder(ramHeaderStyle); + + CellStyle dataStyle = workbook.createCellStyle(); + dataStyle.setAlignment(HorizontalAlignment.CENTER); + setBorder(dataStyle); + + // 写入表头 + Row headerRow = sheet.createRow(0); + Cell c1 = headerRow.createCell(0); + c1.setCellValue("母羊耳号"); + c1.setCellStyle(eweHeaderStyle); + Cell c2 = headerRow.createCell(1); + c2.setCellValue("公羊耳号"); + c2.setCellStyle(ramHeaderStyle); + + // 母羊列和公羊列各自独立写入,行数取两者最大值 + int maxRows = Math.max(eweIds.size(), ramIds.size()); + for (int i = 0; i < maxRows; i++) { + Row row = sheet.createRow(i + 1); + Cell dc1 = row.createCell(0); + if (i < eweIds.size()) { + dc1.setCellValue(eweEarMap.getOrDefault(eweIds.get(i), "")); + } + dc1.setCellStyle(dataStyle); + Cell dc2 = row.createCell(1); + if (i < ramIds.size()) { + dc2.setCellValue(ramEarMap.getOrDefault(ramIds.get(i), "")); + } + dc2.setCellStyle(dataStyle); + } + + sheet.setColumnWidth(0, 5000); + sheet.setColumnWidth(1, 5000); + + // 响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = java.net.URLEncoder.encode("配种配对表", "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + workbook.write(response.getOutputStream()); + workbook.close(); + + } catch (IOException e) { + throw new RuntimeException("导出配对表失败", e); + } + } + + /** 给样式设置边框 */ + private void setBorder(CellStyle style) { + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + } + + /** + * 解析导入的配对Excel,返回配对预览列表 + * Excel格式:第一列=母羊耳号,第二列=公羊耳号,第一行为表头(跳过) + * + * @param file 上传的Excel文件 + * @return 配对列表,每项包含 eweEarNo、ramEarNo、eweId(可能null)、ramId(可能null) + */ + @Override + public List> parsePairsFromExcel(MultipartFile file) + { + List> result = new ArrayList<>(); + try (InputStream is = file.getInputStream(); + Workbook workbook = WorkbookFactory.create(is)) { + + Sheet sheet = workbook.getSheetAt(0); + int lastRow = sheet.getLastRowNum(); + + // 从第2行(index=1)开始,跳过表头 + for (int i = 1; i <= lastRow; i++) { + Row row = sheet.getRow(i); + if (row == null) continue; + + String eweEarNo = getCellStringValue(row.getCell(0)); + String ramEarNo = getCellStringValue(row.getCell(1)); + + if (eweEarNo.isEmpty() && ramEarNo.isEmpty()) continue; + + Map pair = new HashMap<>(); + pair.put("eweEarNo", eweEarNo); + pair.put("ramEarNo", ramEarNo); + pair.put("rowIndex", i); + + // 尝试查找对应的ID(用于校验) + Long eweId = null; + Long ramId = null; + if (!eweEarNo.isEmpty()) { + eweId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(eweEarNo, 1); // 母羊 gender=1 + } + if (!ramEarNo.isEmpty()) { + ramId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(ramEarNo, 2); // 公羊 gender=2 + } + + pair.put("eweId", eweId); + pair.put("ramId", ramId); + // 校验状态 + if (eweEarNo.isEmpty()) { + pair.put("valid", false); + pair.put("error", "母羊耳号不能为空"); + } else if (ramEarNo.isEmpty()) { + pair.put("valid", false); + pair.put("error", "公羊耳号不能为空"); + } else if (eweId == null) { + pair.put("valid", false); + pair.put("error", "母羊耳号[" + eweEarNo + "]未找到"); + } else if (ramId == null) { + pair.put("valid", false); + pair.put("error", "公羊耳号[" + ramEarNo + "]未找到"); + } else { + pair.put("valid", true); + pair.put("error", ""); + } + + result.add(pair); + } + + } catch (Exception e) { + throw new RuntimeException("解析Excel失败:" + e.getMessage(), e); + } + return result; + } + + /** 安全读取单元格字符串值 */ + private String getCellStringValue(Cell cell) { + if (cell == null) return ""; + switch (cell.getCellType()) { + case STRING: return cell.getStringCellValue().trim(); + case NUMERIC: return String.valueOf((long) cell.getNumericCellValue()); + default: return ""; + } + } + + /** + * 根据导入的配对数据(耳号列表)生成配种计划 + * pairs 中每项包含 eweEarNo 和 ramEarNo(或 eweId/ramId) * * @param planType 计划类型 - * @param planName 计划名称 - * @param eweIds 母羊ID列表 - * @param ramIds 公羊ID列表 + * @param pairs 配对数据列表 * @return 生成的配种计划 */ @Override @Transactional + public ScBreedPlanGenerate autoGenerateBreedPlanFromPairs(Integer planType, List> pairs) + { + // 收集所有有效的 eweId / ramId(去重统计用) + List eweIds = new ArrayList<>(); + List ramIds = new ArrayList<>(); + + for (Map pair : pairs) { + Long eweId = null; + Long ramId = null; + + // 优先用已解析的 ID;其次用耳号现查 + if (pair.get("eweId") != null) { + eweId = Long.valueOf(pair.get("eweId").toString()); + } else if (pair.get("eweEarNo") != null) { + eweId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(pair.get("eweEarNo").toString(), 1); // 母羊 gender=1 + } + if (pair.get("ramId") != null) { + ramId = Long.valueOf(pair.get("ramId").toString()); + } else if (pair.get("ramEarNo") != null) { + ramId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(pair.get("ramEarNo").toString(), 2); // 公羊 gender=2 + } + + if (eweId == null || ramId == null) continue; // 跳过无效行 + + eweIds.add(eweId); + if (!ramIds.contains(ramId)) ramIds.add(ramId); + } + + if (eweIds.isEmpty()) { + throw new RuntimeException("没有有效的配对数据,请检查耳号是否存在"); + } + + // 创建计划汇总记录 + ScBreedPlanGenerate planGenerate = new ScBreedPlanGenerate(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String dateStr = sdf.format(new Date()); + + String planTypeName; + switch (planType) { + case 1: planTypeName = "供体母羊配种计划"; break; + case 2: planTypeName = "同期发情人工授精计划"; break; + case 3: planTypeName = "本交配种计划"; break; + case 4: planTypeName = "自然发情人工授精计划"; break; + default: planTypeName = "配种计划"; break; + } + + planGenerate.setPlanName(dateStr + planTypeName); + planGenerate.setPlanType(planType); + planGenerate.setPlanDate(new Date()); + planGenerate.setTotalEweCount(eweIds.size()); + planGenerate.setTotalRamCount(ramIds.size()); + double ratio = ramIds.isEmpty() ? 0 : (double) eweIds.size() / ramIds.size(); + planGenerate.setBreedRatio(String.format("%.1f:1", ratio)); + planGenerate.setStatus(0); // 待审批 + planGenerate.setCreateBy(SecurityUtils.getUsername()); + planGenerate.setCreateTime(new Date()); + + scBreedPlanGenerateMapper.insertScBreedPlanGenerate(planGenerate); + + // 按导入的配对逐条插入临时计划(保留用户指定的配对关系) + for (Map pair : pairs) { + Long eweId = null; + Long ramId = null; + + if (pair.get("eweId") != null) { + eweId = Long.valueOf(pair.get("eweId").toString()); + } else if (pair.get("eweEarNo") != null) { + eweId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(pair.get("eweEarNo").toString(), 1); // 母羊 gender=1 + } + if (pair.get("ramId") != null) { + ramId = Long.valueOf(pair.get("ramId").toString()); + } else if (pair.get("ramEarNo") != null) { + ramId = scBreedPlanGenerateMapper.selectSheepIdByManageTags(pair.get("ramEarNo").toString(), 2); // 公羊 gender=2 + } + + if (eweId == null || ramId == null) continue; + + ScBreedPlan breedPlan = new ScBreedPlan(); + breedPlan.setRamId(ramId.toString()); + breedPlan.setEweId(eweId.toString()); + breedPlan.setBreedType(Long.valueOf(planType)); + scBreedPlanGenerateMapper.insertTempBreedPlan(planGenerate.getId(), breedPlan); + } + + return planGenerate; + } + + /** + * 自动生成配种计划(按比例自动分配,原有逻辑不变) + */ + @Override + @Transactional public ScBreedPlanGenerate autoGenerateBreedPlan(Integer planType, String planName, List eweIds, List ramIds) { - // 创建配种计划生成记录 ScBreedPlanGenerate planGenerate = new ScBreedPlanGenerate(); - // 自动生成计划名称:日期+计划类型 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateStr = sdf.format(new Date()); - String planTypeName = ""; - + String planTypeName; switch (planType) { case 1: planTypeName = "供体母羊配种计划"; break; case 2: planTypeName = "同期发情人工授精计划"; break; @@ -112,7 +381,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi case 4: planTypeName = "自然发情人工授精计划"; break; default: planTypeName = "未知配种计划"; break; } - planName = dateStr + planTypeName; planGenerate.setPlanName(planName); @@ -120,26 +388,18 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi planGenerate.setPlanDate(new Date()); planGenerate.setTotalEweCount(eweIds.size()); planGenerate.setTotalRamCount(ramIds.size()); - - // 计算配种比例 double ratio = (double) eweIds.size() / ramIds.size(); planGenerate.setBreedRatio(String.format("%.1f:1", ratio)); - planGenerate.setStatus(0); // 待审批 + planGenerate.setStatus(0); planGenerate.setCreateBy(SecurityUtils.getUsername()); planGenerate.setCreateTime(new Date()); - // 保存配种计划生成记录 scBreedPlanGenerateMapper.insertScBreedPlanGenerate(planGenerate); - - // 生成具体的配种计划 generateBreedPlanDetails(planGenerate.getId(), eweIds, ramIds, planType); return planGenerate; } - /** - * 生成具体的配种计划详情 - */ private void generateBreedPlanDetails(Long planGenerateId, List eweIds, List ramIds, Integer planType) { int ramIndex = 0; @@ -149,9 +409,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi ScBreedPlan breedPlan = new ScBreedPlan(); breedPlan.setRamId(ramIds.get(ramIndex).toString()); breedPlan.setEweId(eweIds.get(i).toString()); - - // 2. 修改:直接使用 planType 作为 breedType (假设一一对应) - // 1=供体母羊配种, 2=同期发情人工授精, 3=本交, 4=自然发情人工授精 breedPlan.setBreedType(Long.valueOf(planType)); scBreedPlanGenerateMapper.insertTempBreedPlan(planGenerateId, breedPlan); @@ -164,9 +421,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 新增配种计划生成 - * - * @param scBreedPlanGenerate 配种计划生成 - * @return 结果 */ @Override public int insertScBreedPlanGenerate(ScBreedPlanGenerate scBreedPlanGenerate) @@ -177,9 +431,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 修改配种计划生成 - * - * @param scBreedPlanGenerate 配种计划生成 - * @return 结果 */ @Override public int updateScBreedPlanGenerate(ScBreedPlanGenerate scBreedPlanGenerate) @@ -190,44 +441,27 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 获取审批配种计划详情 - * - * @param id 配种计划ID - * @return 审批配种计划详情 */ @Override public Map getApproveBreedPlanDetails(Long id) { Map result = new HashMap<>(); - - // 获取配种计划基本信息 ScBreedPlanGenerate planGenerate = scBreedPlanGenerateMapper.selectScBreedPlanGenerateById(id); result.put("planInfo", planGenerate); - - // 获取详细的配种计划信息 List> planDetails = scBreedPlanGenerateMapper.selectApproveBreedPlanDetails(id); result.put("planDetails", planDetails); - - // 获取可选择的公羊列表 List> availableRams = scBreedPlanGenerateMapper.selectEligibleRam(); result.put("availableRams", availableRams); - return result; } /** * 确认审批配种计划 - * - * @param planId 配种计划ID - * @param planDetails 配种计划详情 - * @param status 审批状态 - * @param approveRemark 审批意见 - * @return 结果 */ @Override @Transactional public int confirmApproveBreedPlan(Long planId, List> planDetails, Integer status, String approveRemark) { - // 更新审批状态 ScBreedPlanGenerate planGenerate = new ScBreedPlanGenerate(); planGenerate.setId(planId); planGenerate.setStatus(status); @@ -238,16 +472,13 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi int result = scBreedPlanGenerateMapper.updateScBreedPlanGenerate(planGenerate); - // 如果审批通过,更新临时配种计划并转为正式计划 if (result > 0 && status == 1) { - // 更新临时配种计划中的公羊分配 if (planDetails != null && !planDetails.isEmpty()) { for (Map detail : planDetails) { Long tempId = Long.valueOf(detail.get("id").toString()); Long ramId = Long.valueOf(detail.get("ram_id").toString()); Long breedType = Long.valueOf(detail.get("breed_type").toString()); - // 更新临时配种计划 Map updateParams = new HashMap<>(); updateParams.put("id", tempId); updateParams.put("ramId", ramId); @@ -255,65 +486,41 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi scBreedPlanGenerateMapper.updateTempBreedPlan(updateParams); } } - - // 将临时配种计划转为正式配种计划 scBreedPlanGenerateMapper.transferTempToFormal(planId); } - return result; } /** * 获取配种计划详情 - * - * @param id 配种计划ID - * @return 配种计划详情 */ @Override public Map getBreedPlanDetails(Long id) { Map result = new HashMap<>(); - - // 获取配种计划基本信息 ScBreedPlanGenerate planGenerate = scBreedPlanGenerateMapper.selectScBreedPlanGenerateById(id); result.put("planInfo", planGenerate); - - // 获取配种计划详情列表 List> planDetails = scBreedPlanGenerateMapper.selectBreedPlanDetails(id); result.put("planDetails", planDetails); - return result; } /** - * 导出配种计划详情 - * - * @param response HTTP响应 - * @param id 配种计划ID + * 导出配种计划详情(已审批) */ @Override public void exportBreedPlanDetails(HttpServletResponse response, Long id) { try { - // 获取配种计划基本信息 ScBreedPlanGenerate planGenerate = scBreedPlanGenerateMapper.selectScBreedPlanGenerateById(id); - if (planGenerate == null) { - throw new RuntimeException("配种计划不存在"); - } + if (planGenerate == null) throw new RuntimeException("配种计划不存在"); + if (planGenerate.getStatus() != 1) throw new RuntimeException("只有已审批的配种计划才能导出"); - // 检查是否已审批 - if (planGenerate.getStatus() != 1) { - throw new RuntimeException("只有已审批的配种计划才能导出"); - } - - // 获取配种计划详情 List> planDetails = scBreedPlanGenerateMapper.selectBreedPlanDetails(id); - // 创建工作簿 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("配种计划详情"); - // 创建样式 CellStyle titleStyle = workbook.createCellStyle(); Font titleFont = workbook.createFont(); titleFont.setBold(true); @@ -350,28 +557,14 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi int rowNum = 0; - // 标题 Row titleRow = sheet.createRow(rowNum++); Cell titleCell = titleRow.createCell(0); titleCell.setCellValue(planGenerate.getPlanName() + " - 配种计划详情"); titleCell.setCellStyle(titleStyle); sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 19)); - // 空行 rowNum++; - String typeName = ""; - switch (planGenerate.getPlanType()) { - case 1: typeName = "供体母羊配种计划"; break; - case 2: typeName = "同期发情人工授精计划"; break; - case 3: typeName = "本交配种计划"; break; - case 4: typeName = "自然发情人工授精计划"; break; - default: typeName = "未知"; break; - } - - // 基本信息 - Row infoRow1 = sheet.createRow(rowNum++); - infoRow1.createCell(0).setCellValue("计划类型:"); String planTypeNameStr; Integer type = planGenerate.getPlanType(); if (type != null) { @@ -385,6 +578,9 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi } else { planTypeNameStr = ""; } + + Row infoRow1 = sheet.createRow(rowNum++); + infoRow1.createCell(0).setCellValue("计划类型:"); infoRow1.createCell(1).setCellValue(planTypeNameStr); infoRow1.createCell(3).setCellValue("计划日期:"); infoRow1.createCell(4).setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(planGenerate.getPlanDate())); @@ -401,55 +597,39 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi infoRow3.createCell(3).setCellValue("创建人:"); infoRow3.createCell(4).setCellValue(planGenerate.getCreateBy()); - // 空行 rowNum++; - // 分组表头 Row groupHeaderRow = sheet.createRow(rowNum++); - Cell groupHeaderCell1 = groupHeaderRow.createCell(1); - groupHeaderCell1.setCellValue("母羊信息"); - groupHeaderCell1.setCellStyle(eweHeaderStyle); - sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum-1, 1, 12)); + Cell gc1 = groupHeaderRow.createCell(1); + gc1.setCellValue("母羊信息"); + gc1.setCellStyle(eweHeaderStyle); + sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12)); + Cell gc2 = groupHeaderRow.createCell(13); + gc2.setCellValue("公羊信息"); + gc2.setCellStyle(ramHeaderStyle); + sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 13, 19)); - Cell groupHeaderCell2 = groupHeaderRow.createCell(13); - groupHeaderCell2.setCellValue("公羊信息"); - groupHeaderCell2.setCellStyle(ramHeaderStyle); - sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum-1, 13, 19)); - - // 详细表头 Row headerRow = sheet.createRow(rowNum++); String[] headers = { "序号", - // 母羊信息 "母羊耳号", "母羊品种", "母羊家系", "母羊类别", "繁育状态", "胎次", "月龄", "体重", "核心羊群", "是否种用", "羊舍", "备注", - // 公羊信息 "公羊耳号", "公羊品种", "公羊家系", "公羊类别", "生日", "月龄", "体重", - // 配种信息 "配种类型" }; - for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); - if (i == 0 || i == headers.length - 1) { - cell.setCellStyle(headerStyle); - } else if (i <= 12) { - cell.setCellStyle(eweHeaderStyle); - } else { - cell.setCellStyle(ramHeaderStyle); - } + if (i == 0 || i == headers.length - 1) cell.setCellStyle(headerStyle); + else if (i <= 12) cell.setCellStyle(eweHeaderStyle); + else cell.setCellStyle(ramHeaderStyle); } - // 数据行 for (int i = 0; i < planDetails.size(); i++) { Map detail = planDetails.get(i); Row dataRow = sheet.createRow(rowNum++); int colNum = 0; - // 序号 dataRow.createCell(colNum++).setCellValue(i + 1); - - // 母羊信息 dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ewe_manage_tags")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ewe_variety")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ewe_family")); @@ -462,8 +642,6 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi dataRow.createCell(colNum++).setCellValue(getBooleanValue(detail, "ewe_is_breeding") ? "是" : "否"); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ewe_sheepfold_name")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ewe_comment")); - - // 公羊信息 dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ram_manage_tags")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ram_variety")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ram_family")); @@ -472,48 +650,36 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ram_month_age")); dataRow.createCell(colNum++).setCellValue(getStringValue(detail, "ram_current_weight")); - // 配种类型 Object breedTypeObj = detail.get("breed_type"); String breedTypeName = "未知类型"; if (breedTypeObj != null) { try { - int typeValue = Integer.parseInt(breedTypeObj.toString()); - switch (typeValue) { + int tv = Integer.parseInt(breedTypeObj.toString()); + switch (tv) { case 1: breedTypeName = "供体母羊配种"; break; case 2: breedTypeName = "同期发情人工授精"; break; case 3: breedTypeName = "本交"; break; case 4: breedTypeName = "自然发情人工授精"; break; - default: breedTypeName = "未知类型"; } - } catch (NumberFormatException e) { - // ignore - } + } catch (NumberFormatException ignored) {} } - dataRow.createCell(colNum++).setCellValue(breedTypeName); - // 应用数据样式 + dataRow.createCell(colNum).setCellValue(breedTypeName); + for (int j = 0; j < headers.length; j++) { - if (dataRow.getCell(j) != null) { - dataRow.getCell(j).setCellStyle(dataStyle); - } + if (dataRow.getCell(j) != null) dataRow.getCell(j).setCellStyle(dataStyle); } } - // 自动调整列宽 for (int i = 0; i < headers.length; i++) { sheet.autoSizeColumn(i); - // 设置最小宽度 - if (sheet.getColumnWidth(i) < 2000) { - sheet.setColumnWidth(i, 2000); - } + if (sheet.getColumnWidth(i) < 2000) sheet.setColumnWidth(i, 2000); } - // 设置响应头 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = java.net.URLEncoder.encode(planGenerate.getPlanName() + "_配种计划详情", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - // 输出到响应流 workbook.write(response.getOutputStream()); workbook.close(); @@ -522,17 +688,11 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi } } - /** - * 安全获取字符串值 - */ private String getStringValue(Map map, String key) { Object value = map.get(key); return value != null ? value.toString() : ""; } - /** - * 安全获取布尔值 - */ private boolean getBooleanValue(Map map, String key) { Object value = map.get(key); if (value == null) return false; @@ -543,15 +703,11 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 批量删除配种计划生成 - * - * @param ids 需要删除的配种计划生成主键 - * @return 结果 */ @Override @Transactional public int deleteScBreedPlanGenerateByIds(Long[] ids) { - // 删除相关的临时配种计划 for (Long id : ids) { scBreedPlanGenerateMapper.deleteTempBreedPlanByPlanId(id); } @@ -560,18 +716,15 @@ public class ScBreedPlanGenerateServiceImpl implements IScBreedPlanGenerateServi /** * 删除配种计划生成信息 - * - * @param id 配种计划生成主键 - * @return 结果 */ @Override @Transactional public int deleteScBreedPlanGenerateById(Long id) { - // 先删除相关的临时配种计划 scBreedPlanGenerateMapper.deleteTempBreedPlanByPlanId(id); return scBreedPlanGenerateMapper.deleteScBreedPlanGenerateById(id); } + @Override public List searchEarNumbers(String query) { return scBreedPlanGenerateMapper.searchEarNumbers(query); diff --git a/zhyc-module/src/main/resources/mapper/produce/breed/ScBreedPlanGenerateMapper.xml b/zhyc-module/src/main/resources/mapper/produce/breed/ScBreedPlanGenerateMapper.xml index f8cb78b..05c7ae0 100644 --- a/zhyc-module/src/main/resources/mapper/produce/breed/ScBreedPlanGenerateMapper.xml +++ b/zhyc-module/src/main/resources/mapper/produce/breed/ScBreedPlanGenerateMapper.xml @@ -54,77 +54,77 @@ @@ -325,4 +325,35 @@ ORDER BY sf.bs_manage_tags LIMIT 50 + + + + + + + + + \ No newline at end of file From 2f646ba797dfa1a5652d5ab321d6df67867394af Mon Sep 17 00:00:00 2001 From: HashMap Date: Tue, 3 Mar 2026 15:54:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?refactor(frozen-sale/all):=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=A2=9E=E5=8A=A0=E5=AD=97=E6=AE=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为数据库中新增的`user_id` `dept_id` 提供结构支持 [重构依据](https://www.yuque.com/piaobo-igrka/xvqmhp/ofcoxh57lywwubgy?singleDoc#) BREAKING CHANGE: 可能产生隐性数据一致性问题 可能导致某些业务逻辑出现问题 --- .../frozen/controller/DdSaleController.java | 3 + .../com/zhyc/module/frozen/domain/DdSale.java | 122 ++---------------- .../service/impl/DdSaleServiceImpl.java | 2 + .../mapper/frozen/sale/DdSaleMapper.xml | 11 +- 4 files changed, 23 insertions(+), 115 deletions(-) diff --git a/zhyc-module/src/main/java/com/zhyc/module/frozen/controller/DdSaleController.java b/zhyc-module/src/main/java/com/zhyc/module/frozen/controller/DdSaleController.java index b3605c3..6c7c1a7 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/frozen/controller/DdSaleController.java +++ b/zhyc-module/src/main/java/com/zhyc/module/frozen/controller/DdSaleController.java @@ -84,6 +84,9 @@ public class DdSaleController extends BaseController { @Log(title = "销售主单", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody DdSale ddSale) { + // 适配数据分离 + ddSale.setDeptId(getDeptId()); + ddSale.setUserId(getUserId()); return toAjax(ddSaleService.insertDdSale(ddSale)); } diff --git a/zhyc-module/src/main/java/com/zhyc/module/frozen/domain/DdSale.java b/zhyc-module/src/main/java/com/zhyc/module/frozen/domain/DdSale.java index dc112c6..8ba6c42 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/frozen/domain/DdSale.java +++ b/zhyc-module/src/main/java/com/zhyc/module/frozen/domain/DdSale.java @@ -4,6 +4,10 @@ import java.math.BigDecimal; import java.util.List; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.zhyc.common.annotation.Excel; @@ -11,10 +15,12 @@ import com.zhyc.common.core.domain.BaseEntity; /** * 销售主单对象 dd_sl - * + * * @author HashMap * @date 2025-12-01 */ +@EqualsAndHashCode(callSuper = true) +@Data public class DdSale extends BaseEntity { private static final long serialVersionUID = 1L; @@ -59,119 +65,11 @@ public class DdSale extends BaseEntity @Excel(name = "技术员") private String tech; + private Long userId; + private Long deptId; + /** 销售明细信息 */ private List ddSaleItemList; - - public void setId(Long id) - { - this.id = id; - } - - public Long getId() - { - return id; - } - - public void setSaleDate(Date saleDate) - { - this.saleDate = saleDate; - } - - public Date getSaleDate() - { - return saleDate; - } - - public void setCustName(String custName) - { - this.custName = custName; - } - - public String getCustName() - { - return custName; - } - - public void setCustPhone(String custPhone) - { - this.custPhone = custPhone; - } - - public String getCustPhone() - { - return custPhone; - } - - public void setCustAddr(String custAddr) - { - this.custAddr = custAddr; - } - - public String getCustAddr() - { - return custAddr; - } - - public void setSalesper(String salesper) - { - this.salesper = salesper; - } - - public String getSalesper() - { - return salesper; - } - - public void setQuaranNo(String quaranNo) - { - this.quaranNo = quaranNo; - } - - public String getQuaranNo() - { - return quaranNo; - } - - public void setApprNo(String apprNo) - { - this.apprNo = apprNo; - } - - public String getApprNo() - { - return apprNo; - } - - public void setPrice(BigDecimal price) - { - this.price = price; - } - - public BigDecimal getPrice() - { - return price; - } - - public void setTech(String tech) - { - this.tech = tech; - } - - public String getTech() - { - return tech; - } - - public List getDdSaleItemList() - { - return ddSaleItemList; - } - - public void setDdSaleItemList(List ddSaleItemList) - { - this.ddSaleItemList = ddSaleItemList; - } - @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) diff --git a/zhyc-module/src/main/java/com/zhyc/module/frozen/service/impl/DdSaleServiceImpl.java b/zhyc-module/src/main/java/com/zhyc/module/frozen/service/impl/DdSaleServiceImpl.java index e10d949..10ca01d 100644 --- a/zhyc-module/src/main/java/com/zhyc/module/frozen/service/impl/DdSaleServiceImpl.java +++ b/zhyc-module/src/main/java/com/zhyc/module/frozen/service/impl/DdSaleServiceImpl.java @@ -3,6 +3,7 @@ package com.zhyc.module.frozen.service.impl; import java.util.HashSet; import java.util.List; +import com.zhyc.common.annotation.DataScope; import com.zhyc.common.utils.DateUtils; import com.zhyc.module.frozen.domain.DdFe; import com.zhyc.module.frozen.domain.DdFs; @@ -58,6 +59,7 @@ public class DdSaleServiceImpl implements IDdSaleService { * @return 销售主单 */ @Override + @DataScope(deptAlias = "dd_sl_alias" , userAlias = "dd_sl_alias") public List selectDdSaleList(DdSale ddSale) { return ddSaleMapper.selectDdSaleList(ddSale); } diff --git a/zhyc-module/src/main/resources/mapper/frozen/sale/DdSaleMapper.xml b/zhyc-module/src/main/resources/mapper/frozen/sale/DdSaleMapper.xml index 4532ca4..74479e0 100644 --- a/zhyc-module/src/main/resources/mapper/frozen/sale/DdSaleMapper.xml +++ b/zhyc-module/src/main/resources/mapper/frozen/sale/DdSaleMapper.xml @@ -38,7 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, sale_date, cust_name, cust_phone, cust_addr, salesper, quaran_no, appr_no, price, tech, remark, create_by, create_time from dd_sl + select id, sale_date, cust_name, cust_phone, cust_addr, salesper, quaran_no, appr_no, price, tech, remark, create_by, create_time from dd_sl dd_sl_alias @@ -83,7 +84,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" remark, create_by, create_time, - + user_id, + dept_id, + #{saleDate}, #{custName}, @@ -97,7 +100,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{remark}, #{createBy}, #{createTime}, - + #{userId}, + #{deptId}, +