Bladeren bron

大屏首页

wwh 1 week geleden
bovenliggende
commit
10c63226c4

+ 116 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/TownDeptSupport.java

@@ -230,6 +230,122 @@ public class TownDeptSupport
230 230
         return Collections.unmodifiableList(options);
231 231
     }
232 232
 
233
+    /**
234
+     * 大屏等全县场景:全部填报乡镇(不按登录人/数据权限收窄)。
235
+     */
236
+    public List<SysDept> listAllReportTowns()
237
+    {
238
+        SysDept query = new SysDept();
239
+        query.setParentId(YakHerdInventoryRules.TOWN_PARENT_ID);
240
+        query.setStatus("0");
241
+        List<SysDept> depts = deptService.selectDeptListWithoutDataScope(query);
242
+        List<SysDept> towns = new ArrayList<>();
243
+        if (depts == null)
244
+        {
245
+            return towns;
246
+        }
247
+        for (SysDept dept : depts)
248
+        {
249
+            if (isActiveReportTown(dept))
250
+            {
251
+                towns.add(dept);
252
+            }
253
+        }
254
+        towns.sort((a, b) -> Integer.compare(
255
+                a.getOrderNum() == null ? 0 : a.getOrderNum(),
256
+                b.getOrderNum() == null ? 0 : b.getOrderNum()));
257
+        return towns;
258
+    }
259
+
260
+    /**
261
+     * 大屏等全县场景:指定填报乡镇下全部村(不按登录人收窄)。
262
+     */
263
+    public List<SysDept> listAllVillagesUnderTown(Long townDeptId)
264
+    {
265
+        List<SysDept> villages = new ArrayList<>();
266
+        if (townDeptId == null)
267
+        {
268
+            return villages;
269
+        }
270
+        SysDept town = deptService.selectDeptById(townDeptId);
271
+        if (!isActiveReportTown(town))
272
+        {
273
+            return villages;
274
+        }
275
+        SysDept query = new SysDept();
276
+        query.setParentId(townDeptId);
277
+        query.setStatus("0");
278
+        List<SysDept> depts = deptService.selectDeptListWithoutDataScope(query);
279
+        if (depts == null)
280
+        {
281
+            return villages;
282
+        }
283
+        for (SysDept dept : depts)
284
+        {
285
+            if (isActiveDept(dept))
286
+            {
287
+                villages.add(dept);
288
+            }
289
+        }
290
+        villages.sort((a, b) -> Integer.compare(
291
+                a.getOrderNum() == null ? 0 : a.getOrderNum(),
292
+                b.getOrderNum() == null ? 0 : b.getOrderNum()));
293
+        return villages;
294
+    }
295
+
296
+    /**
297
+     * 大屏等全县场景:县 → 乡镇 → 村树(不按登录人/数据权限收窄)。
298
+     */
299
+    public List<TreeSelect> buildAllVillageTree()
300
+    {
301
+        List<TreeSelect> townNodes = new ArrayList<>();
302
+        for (SysDept town : listAllReportTowns())
303
+        {
304
+            TreeSelect townNode = new TreeSelect();
305
+            townNode.setId(town.getDeptId());
306
+            townNode.setLabel(town.getDeptName());
307
+            List<TreeSelect> children = new ArrayList<>();
308
+            for (SysDept village : listAllVillagesUnderTown(town.getDeptId()))
309
+            {
310
+                TreeSelect villageNode = new TreeSelect();
311
+                villageNode.setId(village.getDeptId());
312
+                villageNode.setLabel(village.getDeptName());
313
+                children.add(villageNode);
314
+            }
315
+            townNode.setChildren(children);
316
+            townNodes.add(townNode);
317
+        }
318
+
319
+        SysDept county = deptService.selectDeptById(YakHerdInventoryRules.TOWN_PARENT_ID);
320
+        TreeSelect countyNode = new TreeSelect();
321
+        countyNode.setId(YakHerdInventoryRules.TOWN_PARENT_ID);
322
+        countyNode.setLabel(county != null && StringUtils.isNotEmpty(county.getDeptName())
323
+                ? county.getDeptName()
324
+                : "巴青县");
325
+        countyNode.setChildren(townNodes);
326
+
327
+        List<TreeSelect> roots = new ArrayList<>();
328
+        roots.add(countyNode);
329
+        return roots;
330
+    }
331
+
332
+    /**
333
+     * 大屏等全县场景:乡镇下拉选项(不按登录人收窄)。
334
+     */
335
+    public List<Map<String, Object>> toAllOptionList()
336
+    {
337
+        List<Map<String, Object>> options = new ArrayList<>();
338
+        for (SysDept town : listAllReportTowns())
339
+        {
340
+            Map<String, Object> item = new LinkedHashMap<>();
341
+            item.put("deptId", town.getDeptId());
342
+            item.put("deptName", town.getDeptName());
343
+            item.put("orderNum", town.getOrderNum());
344
+            options.add(item);
345
+        }
346
+        return Collections.unmodifiableList(options);
347
+    }
348
+
233 349
     /**
234 350
      * 当前登录人锁定的填报乡镇 id(乡镇/村人员);非此类人员返回 null(不限制)。
235 351
      */

+ 20 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/screen/controller/HomeScreenController.java

@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestParam;
9 9
 import org.springframework.web.bind.annotation.RestController;
10 10
 import com.ruoyi.common.core.controller.BaseController;
11 11
 import com.ruoyi.common.core.domain.AjaxResult;
12
+import com.ruoyi.common.core.domain.TreeSelect;
12 13
 import com.ruoyi.common.core.page.TableDataInfo;
13 14
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenCooperativeDevelopmentListItemVo;
14 15
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenFamilyRanchListItemVo;
@@ -268,4 +269,23 @@ public class HomeScreenController extends BaseController
268 269
                 homeScreenService.listBreedingEntityQuantities(statYear, statMonth, townDeptId, villageDeptId);
269 270
         return getDataTable(list);
270 271
     }
272
+
273
+    /**
274
+     * 乡镇列表(全县填报乡镇;不按登录人数据权限收窄)。
275
+     */
276
+    @GetMapping("/townOptions")
277
+    public AjaxResult townOptions()
278
+    {
279
+        return success(homeScreenService.listTownOptions());
280
+    }
281
+
282
+    /**
283
+     * 村树结构(县 → 乡镇 → 村;全县口径)。
284
+     */
285
+    @GetMapping("/villageTree")
286
+    public AjaxResult villageTree()
287
+    {
288
+        List<TreeSelect> tree = homeScreenService.listVillageTree();
289
+        return success(tree);
290
+    }
271 291
 }

+ 12 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/screen/service/IHomeScreenService.java

@@ -1,6 +1,8 @@
1 1
 package com.ruoyi.web.modules.screen.service;
2 2
 
3 3
 import java.util.List;
4
+import java.util.Map;
5
+import com.ruoyi.common.core.domain.TreeSelect;
4 6
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenCooperativeDevelopmentListItemVo;
5 7
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenDashboardVo;
6 8
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenFamilyRanchListItemVo;
@@ -124,4 +126,14 @@ public interface IHomeScreenService
124 126
      */
125 127
     List<HomeScreenBreedingEntityQuantityListItemVo> listBreedingEntityQuantities(
126 128
             Integer statYear, Integer statMonth, Long townDeptId, Long villageDeptId);
129
+
130
+    /**
131
+     * 大屏乡镇下拉(全县填报乡镇,不按登录人数据权限收窄)。
132
+     */
133
+    List<Map<String, Object>> listTownOptions();
134
+
135
+    /**
136
+     * 大屏村树(县 → 乡镇 → 村,全县口径)。
137
+     */
138
+    List<TreeSelect> listVillageTree();
127 139
 }

+ 18 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/screen/service/impl/HomeScreenServiceImpl.java

@@ -8,8 +8,10 @@ import java.time.ZoneId;
8 8
 import java.util.Collections;
9 9
 import java.util.Date;
10 10
 import java.util.List;
11
+import java.util.Map;
11 12
 import org.springframework.beans.factory.annotation.Autowired;
12 13
 import org.springframework.stereotype.Service;
14
+import com.ruoyi.common.core.domain.TreeSelect;
13 15
 import com.ruoyi.web.modules.industryservice.domain.BizCooperativeDevelopment;
14 16
 import com.ruoyi.web.modules.industryservice.domain.BizDisposableIncome;
15 17
 import com.ruoyi.web.modules.industryservice.domain.BizFamilyRanch;
@@ -31,6 +33,7 @@ import com.ruoyi.web.modules.industryservice.mapper.BizLivestockOwnershipHouseho
31 33
 import com.ruoyi.web.modules.industryservice.mapper.BizYakHerdInventoryMapper;
32 34
 import com.ruoyi.web.modules.industryservice.mapper.BizYakOutboundReportMapper;
33 35
 import com.ruoyi.web.modules.industryservice.support.BreedingIndustryRules;
36
+import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
34 37
 import com.ruoyi.web.modules.prosperity.support.AchievementReportValidation;
35 38
 import com.ruoyi.web.modules.screen.domain.dto.HomeScreenHerdGenderSumDto;
36 39
 import com.ruoyi.web.modules.screen.domain.dto.HomeScreenStatPeriodDto;
@@ -103,6 +106,9 @@ public class HomeScreenServiceImpl implements IHomeScreenService
103 106
     @Autowired
104 107
     private BizLivestockOwnershipHouseholdMapper bizLivestockOwnershipHouseholdMapper;
105 108
 
109
+    @Autowired
110
+    private TownDeptSupport townDeptSupport;
111
+
106 112
     @Override
107 113
     public HomeScreenDashboardVo loadDashboard(String statYear)
108 114
     {
@@ -553,6 +559,18 @@ public class HomeScreenServiceImpl implements IHomeScreenService
553 559
                 statYear, statMonth, townDeptId, villageDeptId);
554 560
     }
555 561
 
562
+    @Override
563
+    public List<Map<String, Object>> listTownOptions()
564
+    {
565
+        return townDeptSupport.toAllOptionList();
566
+    }
567
+
568
+    @Override
569
+    public List<TreeSelect> listVillageTree()
570
+    {
571
+        return townDeptSupport.buildAllVillageTree();
572
+    }
573
+
556 574
     private static Date toDate(LocalDate localDate)
557 575
     {
558 576
         return Date.from(localDate.atStartOfDay(ZoneId.of(BreedingIndustryRules.ZONE_SHANGHAI)).toInstant());

+ 50 - 0
baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/TownDeptSupportScopeTest.java

@@ -90,6 +90,56 @@ class TownDeptSupportScopeTest
90 90
         assertEquals(1, townDeptSupport.listReportTowns().size());
91 91
     }
92 92
 
93
+    @Test
94
+    @DisplayName("全县口径:listAllReportTowns 不依赖登录人收窄")
95
+    void allReportTownsIgnoresLoginScope()
96
+    {
97
+        SysDept townA = town(200L, "雅安镇", 20);
98
+        SysDept townB = town(201L, "巴青镇", 21);
99
+        SysDept village = village(300L, "雅安镇荣嘎村", 200L);
100
+        loginAs(300L, 9L);
101
+        when(deptService.selectDeptById(any())).thenAnswer(invocation -> {
102
+            Long id = invocation.getArgument(0);
103
+            if (Long.valueOf(300L).equals(id))
104
+            {
105
+                return village;
106
+            }
107
+            if (Long.valueOf(200L).equals(id))
108
+            {
109
+                return townA;
110
+            }
111
+            if (Long.valueOf(201L).equals(id))
112
+            {
113
+                return townB;
114
+            }
115
+            if (Long.valueOf(YakHerdInventoryRules.TOWN_PARENT_ID).equals(id))
116
+            {
117
+                return county();
118
+            }
119
+            return null;
120
+        });
121
+        when(deptService.selectDeptListWithoutDataScope(any())).thenAnswer(invocation -> {
122
+            SysDept q = invocation.getArgument(0);
123
+            if (Long.valueOf(YakHerdInventoryRules.TOWN_PARENT_ID).equals(q.getParentId()))
124
+            {
125
+                return java.util.Arrays.asList(townA, townB);
126
+            }
127
+            if (Long.valueOf(200L).equals(q.getParentId()))
128
+            {
129
+                return Collections.singletonList(village);
130
+            }
131
+            return Collections.emptyList();
132
+        });
133
+
134
+        assertEquals(2, townDeptSupport.listAllReportTowns().size());
135
+        assertEquals(1, townDeptSupport.listAllVillagesUnderTown(200L).size());
136
+        assertEquals(2, townDeptSupport.toAllOptionList().size());
137
+
138
+        List<TreeSelect> tree = townDeptSupport.buildAllVillageTree();
139
+        assertEquals(1, tree.size());
140
+        assertEquals(2, tree.get(0).getChildren().size());
141
+    }
142
+
93 143
     private static void loginAs(Long deptId, Long userId)
94 144
     {
95 145
         SysUser user = new SysUser();

+ 36 - 0
baqing-admin/src/test/java/com/ruoyi/web/modules/screen/controller/HomeScreenControllerApiTest.java

@@ -440,6 +440,42 @@ class HomeScreenControllerApiTest
440 440
                 .andExpect(jsonPath("$.rows[0].largeLivestockFarmerCount").value(5));
441 441
     }
442 442
 
443
+    @Test
444
+    @DisplayName("DP-SY-API-050 GET townOptions 乡镇列表")
445
+    void api050_townOptions() throws Exception
446
+    {
447
+        java.util.Map<String, Object> item = new java.util.LinkedHashMap<>();
448
+        item.put("deptId", 101L);
449
+        item.put("deptName", "巴青镇");
450
+        item.put("orderNum", 20);
451
+        when(homeScreenService.listTownOptions()).thenReturn(Collections.singletonList(item));
452
+        mockMvc.perform(get("/bigScreen/home/townOptions"))
453
+                .andExpect(status().isOk())
454
+                .andExpect(jsonPath("$.code").value(200))
455
+                .andExpect(jsonPath("$.data[0].deptId").value(101))
456
+                .andExpect(jsonPath("$.data[0].deptName").value("巴青镇"));
457
+    }
458
+
459
+    @Test
460
+    @DisplayName("DP-SY-API-051 GET villageTree 村树")
461
+    void api051_villageTree() throws Exception
462
+    {
463
+        com.ruoyi.common.core.domain.TreeSelect root = new com.ruoyi.common.core.domain.TreeSelect();
464
+        root.setId(100L);
465
+        root.setLabel("巴青县");
466
+        com.ruoyi.common.core.domain.TreeSelect town = new com.ruoyi.common.core.domain.TreeSelect();
467
+        town.setId(101L);
468
+        town.setLabel("巴青镇");
469
+        root.setChildren(Collections.singletonList(town));
470
+        when(homeScreenService.listVillageTree()).thenReturn(Collections.singletonList(root));
471
+        mockMvc.perform(get("/bigScreen/home/villageTree"))
472
+                .andExpect(status().isOk())
473
+                .andExpect(jsonPath("$.code").value(200))
474
+                .andExpect(jsonPath("$.data[0].id").value(100))
475
+                .andExpect(jsonPath("$.data[0].label").value("巴青县"))
476
+                .andExpect(jsonPath("$.data[0].children[0].id").value(101));
477
+    }
478
+
443 479
     private static com.ruoyi.web.modules.screen.domain.vo.HomeScreenTownMapVo sampleTownMap()
444 480
     {
445 481
         com.ruoyi.web.modules.screen.domain.vo.HomeScreenTownMapMarkerVo marker =

+ 28 - 0
baqing-admin/src/test/java/com/ruoyi/web/modules/screen/service/impl/HomeScreenServiceImplTest.java

@@ -59,6 +59,7 @@ import com.ruoyi.web.modules.screen.domain.vo.HomeScreenTownMapMarkerVo;
59 59
 import com.ruoyi.web.modules.screen.domain.vo.HomeScreenTownMapVo;
60 60
 import com.ruoyi.web.modules.screen.mapper.HomeScreenStandardMapper;
61 61
 import com.ruoyi.web.modules.screen.mapper.HomeScreenStatsMapper;
62
+import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
62 63
 
63 64
 /**
64 65
  * DP-SY-UT-010 等编排测试
@@ -101,6 +102,9 @@ class HomeScreenServiceImplTest
101 102
     @Mock
102 103
     private BizLivestockOwnershipHouseholdMapper bizLivestockOwnershipHouseholdMapper;
103 104
 
105
+    @Mock
106
+    private TownDeptSupport townDeptSupport;
107
+
104 108
     @InjectMocks
105 109
     private HomeScreenServiceImpl service;
106 110
 
@@ -597,6 +601,30 @@ class HomeScreenServiceImplTest
597 601
         assertEquals(0, service.listBreedingEntityQuantities(null, null, null, null).size());
598 602
     }
599 603
 
604
+    @Test
605
+    @DisplayName("DP-SY-UT-041 乡镇列表走全县口径")
606
+    void ut041_townOptionsCountyWide()
607
+    {
608
+        java.util.Map<String, Object> item = new java.util.LinkedHashMap<>();
609
+        item.put("deptId", 101L);
610
+        item.put("deptName", "巴青镇");
611
+        when(townDeptSupport.toAllOptionList()).thenReturn(Collections.singletonList(item));
612
+        assertEquals(1, service.listTownOptions().size());
613
+        assertEquals("巴青镇", service.listTownOptions().get(0).get("deptName"));
614
+    }
615
+
616
+    @Test
617
+    @DisplayName("DP-SY-UT-042 村树走全县口径")
618
+    void ut042_villageTreeCountyWide()
619
+    {
620
+        com.ruoyi.common.core.domain.TreeSelect root = new com.ruoyi.common.core.domain.TreeSelect();
621
+        root.setId(100L);
622
+        root.setLabel("巴青县");
623
+        when(townDeptSupport.buildAllVillageTree()).thenReturn(Collections.singletonList(root));
624
+        assertEquals(1, service.listVillageTree().size());
625
+        assertEquals(100L, service.listVillageTree().get(0).getId());
626
+    }
627
+
600 628
     @Test
601 629
     @DisplayName("DP-SY-UT-027 产业总览存栏出栏取所选年最大填报月")
602 630
     void ut027_overviewFromReportTables()

+ 3 - 0
doc/大屏/首页/大屏首页功能需求.md

@@ -100,6 +100,8 @@
100 100
 | **有无畜户数据明细** | 独立接口分页查询 `biz_livestock_ownership_household`;条件同农牧户明细;按**年、月倒序**;返回全部业务列表字段 |
101 101
 | **牦牛存出栏情况明细** | 独立接口分页;按 `(stat_year, stat_month, village_dept_id)` 关联 `biz_yak_herd_inventory` 与 `biz_yak_outbound_report`;年/月/乡镇/村均可选(**未传年月不过滤,支持跨多年全量翻页**);按**年、月倒序**;返回年、月、乡镇、村、牦牛总存栏数、牦牛总出栏数 |
102 102
 | **养殖主体数量明细** | 独立接口分页;以 `biz_farmer_household` 为主表,按村年月左关联 `biz_cooperative_development` / `biz_family_ranch` / `biz_large_livestock_farmer` 计数;年/月/乡镇/村均可选(**未传年月不过滤,支持跨多年全量翻页**;前端筛选项可默认当前年月);按**年、月倒序**;返回年、月、乡镇、村、农牧户数、合作社数、家庭牧场数、养殖大户数 |
103
+| **乡镇列表** | 独立接口返回全县填报乡镇(`parent_id=100` 且 `order_num>12`);**不按**登录人数据权限收窄 |
104
+| **村树结构** | 独立接口返回县 → 乡镇 → 村树(`TreeSelect`);全县口径 |
103 105
 | **草畜失衡预警明细** | 独立接口分页查询 `biz_grass_livestock_imbalance_warning`;条件:年/月/乡镇/村;按**预警时间倒序**;返回年、月、乡镇、村、主体名称、主体类型、核定载畜量、年底存栏、是否草畜平衡 |
104 106
 | **出栏统计** | 所选年 **Y** 的 1~12 月;各月全县村级 `yak_outbound_count` 合计;纯柱状图无趋势线;接口字段 **`outboundMonthly`** |
105 107
 | **地图标注** | 所选年 **Y** 内存栏/出栏表各自**最大填报月**,按乡镇汇总各村 `yak_total` / `yak_outbound_count`;**随 Y 切换** |
@@ -501,6 +503,7 @@ flowchart TB
501 503
 
502 504
 | 版本 | 日期 | 说明 |
503 505
 | --- | --- | --- |
506
+| 1.16 | 2026-07-23 | 新增大屏乡镇列表、村树接口(全县口径) |
504 507
 | 1.15 | 2026-07-23 | 新增养殖主体数量明细分页接口(农牧户主表左关联合作社/家庭牧场/养殖大户) |
505 508
 | 1.14 | 2026-07-23 | 牦牛存出栏明细:年月未传不过滤(跨年全量翻页);SQL 改为存栏主表+UNION ALL 补仅出栏 |
506 509
 | 1.13 | 2026-07-23 | 新增牦牛存出栏情况明细分页接口(关联存栏/出栏填报表) |

+ 11 - 0
doc/大屏/首页/大屏首页技术方案.md

@@ -212,6 +212,8 @@
212 212
 | 3.12 | 有无畜户数据明细 | GET | `/bigScreen/home/livestockOwnershipHouseholds` | 同上 |
213 213
 | 3.13 | 牦牛存出栏情况明细 | GET | `/bigScreen/home/yakInventoryOutbounds` | 同上 |
214 214
 | 3.14 | 养殖主体数量明细 | GET | `/bigScreen/home/breedingEntityQuantities` | 同上 |
215
+| 3.15 | 乡镇列表 | GET | `/bigScreen/home/townOptions` | 同上 |
216
+| 3.16 | 村树结构 | GET | `/bigScreen/home/villageTree` | 同上 |
215 217
 
216 218
 前端:切换 `statYear` → **3.1** + **3.2**(`pageNum=1`)+ **3.3**;仅翻页 / 切 Tab → **3.2**;进入首页 → **3.1** + **3.2** + **3.3**。
217 219
 
@@ -610,6 +612,14 @@
610 612
 | `familyRanchCount` | 家庭牧场(个) |
611 613
 | `largeLivestockFarmerCount` | 养殖大户(个) |
612 614
 
615
+### 3.15 乡镇列表
616
+
617
+无 Query。响应 `data[]`:`deptId`、`deptName`、`orderNum`。全县填报乡镇(与地图标注乡镇口径一致),**不按**登录人数据权限收窄。
618
+
619
+### 3.16 村树结构
620
+
621
+无 Query。响应 `data[]` 为 `TreeSelect`:县(根)→ 乡镇 → 村;仅叶子村为筛选目标。全县口径。
622
+
613 623
 ---
614 624
 
615 625
 ## 4. 前端实现要点
@@ -653,6 +663,7 @@ SQL 示例:`sql/big_screen_home_perm.sql`(挂载「大屏」父菜单下)
653 663
 
654 664
 | 版本 | 日期 | 说明 |
655 665
 | --- | --- | --- |
666
+| 1.17 | 2026-07-23 | 新增大屏 `/townOptions`、`/villageTree`(全县口径) |
656 667
 | 1.16 | 2026-07-23 | 新增养殖主体数量明细分页接口 `/breedingEntityQuantities` |
657 668
 | 1.15 | 2026-07-23 | `/yakInventoryOutbounds`:年月未传不过滤;SQL 改为存栏主表 LEFT JOIN + UNION ALL 补仅出栏 |
658 669
 | 1.14 | 2026-07-23 | 新增牦牛存出栏情况明细分页接口 `/yakInventoryOutbounds` |

+ 5 - 0
doc/大屏/首页/大屏首页测试用例.md

@@ -93,6 +93,8 @@
93 93
 | DP-SY-UT-038 | 有无畜户明细 | 条件过滤与默认年月 | 单元测试 | JUnit5 | §2.5 | Mock `biz_livestock_ownership_household` | `listLivestockOwnershipHouseholds(...)` | 字段完整;未传年月默认当前年月 |
94 94
 | DP-SY-UT-039 | 存出栏情况明细 | 关联与跨年全量 | 单元测试 | JUnit5 | §2.5 | Mock `selectYakInventoryOutboundList` | `listYakInventoryOutbounds(...)` | 返回存栏/出栏;未传年月不过滤(传 null) |
95 95
 | DP-SY-UT-040 | 养殖主体数量明细 | 关联计数与跨年全量 | 单元测试 | JUnit5 | §2.5 | Mock `selectBreedingEntityQuantityList` | `listBreedingEntityQuantities(...)` | 返回四类数量;未传年月不过滤 |
96
+| DP-SY-UT-041 | 乡镇列表 | 全县口径 | 单元测试 | JUnit5 | §2.5 | Mock `toAllOptionList` | `listTownOptions()` | 返回乡镇选项 |
97
+| DP-SY-UT-042 | 村树 | 全县口径 | 单元测试 | JUnit5 | §2.5 | Mock `buildAllVillageTree` | `listVillageTree()` | 返回县根节点 |
96 98
 
97 99
 ---
98 100
 
@@ -148,6 +150,8 @@
148 150
 | DP-SY-API-047 | 有无畜户明细 | 分页与字段 | 接口测试 | Postman/curl | §2.5 | 填报表有样本 | `GET .../livestockOwnershipHouseholds?statYear=2026&statMonth=9` | `code` 成功;含有畜/无畜户数字段 |
149 151
 | DP-SY-API-048 | 存出栏情况明细 | 分页与关联字段 | 接口测试 | Postman/curl | §2.5 | 存栏/出栏有样本 | `GET .../yakInventoryOutbounds?statYear=2026&statMonth=6` | `code` 成功;`rows[]` 含年/月/乡镇/村/`yakTotal`/`yakOutboundCount`;按时间倒序 |
150 152
 | DP-SY-API-049 | 养殖主体数量明细 | 分页与四类计数 | 接口测试 | Postman/curl | §2.5 | 农牧户等有样本 | `GET .../breedingEntityQuantities?statYear=2026&statMonth=5` | `code` 成功;含 `farmerHouseholdCount`/`cooperativeCount`/`familyRanchCount`/`largeLivestockFarmerCount` |
153
+| DP-SY-API-050 | 乡镇列表 | 全县选项 | 接口测试 | Postman/curl | §2.5 | 部门有填报乡镇 | `GET .../townOptions` | `data[]` 含 `deptId`/`deptName` |
154
+| DP-SY-API-051 | 村树 | 县乡镇村 | 接口测试 | Postman/curl | §2.5 | 部门有村 | `GET .../villageTree` | `data[0]` 为县,含乡镇 children |
151 155
 
152 156
 ---
153 157
 
@@ -264,6 +268,7 @@ await page.route('**/bigScreen/home/dashboard**', route =>
264 268
 
265 269
 | 版本 | 说明 |
266 270
 | --- | --- |
271
+| 1.7 | 新增大屏乡镇列表、村树接口(UT-041~042、API-050~051) |
267 272
 | 1.6 | 新增养殖主体数量明细接口(UT-040、API-049) |
268 273
 | 1.5 | 存出栏明细:年月未传不过滤,支持跨年全量翻页(UT-039) |
269 274
 | 1.4 | 新增牦牛存出栏情况明细接口(UT-039、API-048) |

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java

@@ -19,6 +19,14 @@ public interface ISysDeptService
19 19
      */
20 20
     public List<SysDept> selectDeptList(SysDept dept);
21 21
 
22
+    /**
23
+     * 查询部门列表(不做数据权限过滤,供大屏全县字典等场景)。
24
+     *
25
+     * @param dept 部门信息
26
+     * @return 部门信息集合
27
+     */
28
+    public List<SysDept> selectDeptListWithoutDataScope(SysDept dept);
29
+
22 30
     /**
23 31
      * 查询部门树结构信息
24 32
      * 

+ 6 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java

@@ -48,6 +48,12 @@ public class SysDeptServiceImpl implements ISysDeptService
48 48
         return deptMapper.selectDeptList(dept);
49 49
     }
50 50
 
51
+    @Override
52
+    public List<SysDept> selectDeptListWithoutDataScope(SysDept dept)
53
+    {
54
+        return deptMapper.selectDeptList(dept);
55
+    }
56
+
51 57
     /**
52 58
      * 查询部门树结构信息
53 59
      *