wwh hai 1 semana
pai
achega
8db5300eea

+ 25 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/research/controller/ResearchOpenApiController.java

@@ -22,6 +22,7 @@ import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchFarmerHo
22 22
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLargeLivestockFarmerVo;
23 23
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLivestockProductOutputVo;
24 24
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchPastureVo;
25
+import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchVaccinationDataVo;
25 26
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakAssetVo;
26 27
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakHerdInventoryVo;
27 28
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakOutboundReportVo;
@@ -319,4 +320,28 @@ public class ResearchOpenApiController
319 320
             return ResearchOpenApiSupport.error(code, ex.getMessage());
320 321
         }
321 322
     }
323
+
324
+    /**
325
+     * 疫苗接种数据列表(村级汇总)。
326
+     */
327
+    @GetMapping("/vaccination-data")
328
+    public OpenApiResponse<OpenApiPageResult<ResearchVaccinationDataVo>> listVaccinationData(
329
+            @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
330
+            @RequestParam(value = "pageSize", defaultValue = "20") int pageSize,
331
+            @RequestParam(value = "statYear", required = false) Integer statYear,
332
+            @RequestParam(value = "statMonth", required = false) Integer statMonth,
333
+            @RequestParam(value = "townName", required = false) String townName,
334
+            @RequestParam(value = "villageName", required = false) String villageName)
335
+    {
336
+        try
337
+        {
338
+            return ResearchOpenApiSupport.success(researchOpenApiService.listVaccinationData(
339
+                    pageNum, pageSize, statYear, statMonth, townName, villageName));
340
+        }
341
+        catch (ServiceException ex)
342
+        {
343
+            int code = ex.getCode() != null ? ex.getCode() : 500;
344
+            return ResearchOpenApiSupport.error(code, ex.getMessage());
345
+        }
346
+    }
322 347
 }

+ 113 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/research/domain/vo/ResearchVaccinationDataVo.java

@@ -0,0 +1,113 @@
1
+package com.ruoyi.web.modules.industryservice.research.domain.vo;
2
+
3
+import java.math.BigDecimal;
4
+
5
+/**
6
+ * 科研开放接口 — 疫苗接种填报记录(村级汇总;不含部门 ID / 备注)。
7
+ */
8
+public class ResearchVaccinationDataVo
9
+{
10
+    /** 疫苗接种记录 ID */
11
+    private Long vaccinationId;
12
+
13
+    /** 所属年份 */
14
+    private Integer statYear;
15
+
16
+    /** 所属月份(1~12) */
17
+    private Integer statMonth;
18
+
19
+    /** 所属乡镇名称 */
20
+    private String townName;
21
+
22
+    /** 所属村名称 */
23
+    private String villageName;
24
+
25
+    /** 应免数(头) */
26
+    private Integer shouldVaccinateCount;
27
+
28
+    /** 实免数(头) */
29
+    private Integer actualVaccinateCount;
30
+
31
+    /** 免疫率(%;(实免/应免)×100,保留 2 位小数) */
32
+    private BigDecimal immunityRate;
33
+
34
+    public Long getVaccinationId()
35
+    {
36
+        return vaccinationId;
37
+    }
38
+
39
+    public void setVaccinationId(Long vaccinationId)
40
+    {
41
+        this.vaccinationId = vaccinationId;
42
+    }
43
+
44
+    public Integer getStatYear()
45
+    {
46
+        return statYear;
47
+    }
48
+
49
+    public void setStatYear(Integer statYear)
50
+    {
51
+        this.statYear = statYear;
52
+    }
53
+
54
+    public Integer getStatMonth()
55
+    {
56
+        return statMonth;
57
+    }
58
+
59
+    public void setStatMonth(Integer statMonth)
60
+    {
61
+        this.statMonth = statMonth;
62
+    }
63
+
64
+    public String getTownName()
65
+    {
66
+        return townName;
67
+    }
68
+
69
+    public void setTownName(String townName)
70
+    {
71
+        this.townName = townName;
72
+    }
73
+
74
+    public String getVillageName()
75
+    {
76
+        return villageName;
77
+    }
78
+
79
+    public void setVillageName(String villageName)
80
+    {
81
+        this.villageName = villageName;
82
+    }
83
+
84
+    public Integer getShouldVaccinateCount()
85
+    {
86
+        return shouldVaccinateCount;
87
+    }
88
+
89
+    public void setShouldVaccinateCount(Integer shouldVaccinateCount)
90
+    {
91
+        this.shouldVaccinateCount = shouldVaccinateCount;
92
+    }
93
+
94
+    public Integer getActualVaccinateCount()
95
+    {
96
+        return actualVaccinateCount;
97
+    }
98
+
99
+    public void setActualVaccinateCount(Integer actualVaccinateCount)
100
+    {
101
+        this.actualVaccinateCount = actualVaccinateCount;
102
+    }
103
+
104
+    public BigDecimal getImmunityRate()
105
+    {
106
+        return immunityRate;
107
+    }
108
+
109
+    public void setImmunityRate(BigDecimal immunityRate)
110
+    {
111
+        this.immunityRate = immunityRate;
112
+    }
113
+}

+ 10 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/research/service/IResearchOpenApiService.java

@@ -10,6 +10,7 @@ import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchFarmerHo
10 10
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLargeLivestockFarmerVo;
11 11
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLivestockProductOutputVo;
12 12
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchPastureVo;
13
+import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchVaccinationDataVo;
13 14
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakAssetVo;
14 15
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakHerdInventoryVo;
15 16
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakOutboundReportVo;
@@ -108,4 +109,13 @@ public interface IResearchOpenApiService
108 109
      */
109 110
     OpenApiPageResult<ResearchLargeLivestockFarmerVo> listLargeLivestockFarmers(int pageNum, int pageSize,
110 111
             Integer statYear, Integer statMonth, String townName, String villageName, String enterpriseName);
112
+
113
+    /**
114
+     * 疫苗接种填报列表。
115
+     *
116
+     * @param townName 所属乡镇名称模糊匹配
117
+     * @param villageName 所属村名称模糊匹配
118
+     */
119
+    OpenApiPageResult<ResearchVaccinationDataVo> listVaccinationData(int pageNum, int pageSize,
120
+            Integer statYear, Integer statMonth, String townName, String villageName);
111 121
 }

+ 33 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/research/service/impl/ResearchOpenApiServiceImpl.java

@@ -15,6 +15,7 @@ import com.ruoyi.web.modules.industryservice.domain.BizFarmerHousehold;
15 15
 import com.ruoyi.web.modules.industryservice.domain.BizLargeLivestockFarmer;
16 16
 import com.ruoyi.web.modules.industryservice.domain.BizLivestockProductOutput;
17 17
 import com.ruoyi.web.modules.industryservice.domain.BizPasture;
18
+import com.ruoyi.web.modules.industryservice.domain.BizVaccinationData;
18 19
 import com.ruoyi.web.modules.industryservice.domain.BizYakAsset;
19 20
 import com.ruoyi.web.modules.industryservice.domain.BizYakHerdInventory;
20 21
 import com.ruoyi.web.modules.industryservice.domain.BizYakOutboundReport;
@@ -25,6 +26,7 @@ import com.ruoyi.web.modules.industryservice.mapper.BizFamilyRanchMapper;
25 26
 import com.ruoyi.web.modules.industryservice.mapper.BizFarmerHouseholdMapper;
26 27
 import com.ruoyi.web.modules.industryservice.mapper.BizLargeLivestockFarmerMapper;
27 28
 import com.ruoyi.web.modules.industryservice.mapper.BizLivestockProductOutputMapper;
29
+import com.ruoyi.web.modules.industryservice.mapper.BizVaccinationDataMapper;
28 30
 import com.ruoyi.web.modules.industryservice.mapper.BizYakHerdInventoryMapper;
29 31
 import com.ruoyi.web.modules.industryservice.mapper.BizYakOutboundReportMapper;
30 32
 import com.ruoyi.web.modules.industryservice.research.config.ResearchOpenApiProperties;
@@ -37,6 +39,7 @@ import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchFarmerHo
37 39
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLargeLivestockFarmerVo;
38 40
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLivestockProductOutputVo;
39 41
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchPastureVo;
42
+import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchVaccinationDataVo;
40 43
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakAssetVo;
41 44
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakHerdInventoryVo;
42 45
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakOutboundReportVo;
@@ -90,6 +93,9 @@ public class ResearchOpenApiServiceImpl implements IResearchOpenApiService
90 93
     @Autowired
91 94
     private BizLargeLivestockFarmerMapper bizLargeLivestockFarmerMapper;
92 95
 
96
+    @Autowired
97
+    private BizVaccinationDataMapper bizVaccinationDataMapper;
98
+
93 99
     @Override
94 100
     public ResearchTokenVo authenticate(String appKey, String appSecret)
95 101
     {
@@ -370,6 +376,33 @@ public class ResearchOpenApiServiceImpl implements IResearchOpenApiService
370 376
                 rows.stream().map(ResearchOpenApiSupport::toLargeLivestockFarmerVo).collect(Collectors.toList()));
371 377
     }
372 378
 
379
+    @Override
380
+    public OpenApiPageResult<ResearchVaccinationDataVo> listVaccinationData(int pageNum, int pageSize,
381
+            Integer statYear, Integer statMonth, String townName, String villageName)
382
+    {
383
+        tokenService.assertEnabled();
384
+        int safePageNum = normalizePageNum(pageNum);
385
+        int safePageSize = normalizePageSize(pageSize);
386
+        BizVaccinationData query = new BizVaccinationData();
387
+        query.setStatYear(statYear);
388
+        query.setStatMonth(statMonth);
389
+        if (StringUtils.isNotEmpty(townName))
390
+        {
391
+            query.setTownName(townName.trim());
392
+        }
393
+        if (StringUtils.isNotEmpty(villageName))
394
+        {
395
+            query.setVillageName(villageName.trim());
396
+        }
397
+        // 开放接口无登录上下文,清空 dataScope,避免走填报部门权限
398
+        query.getParams().put("dataScope", "");
399
+        PageHelper.startPage(safePageNum, safePageSize);
400
+        List<BizVaccinationData> rows = bizVaccinationDataMapper.selectBizVaccinationDataList(query);
401
+        PageInfo<BizVaccinationData> page = new PageInfo<>(rows);
402
+        return toPageResult(safePageNum, safePageSize, page.getTotal(),
403
+                rows.stream().map(ResearchOpenApiSupport::toVaccinationDataVo).collect(Collectors.toList()));
404
+    }
405
+
373 406
     private int normalizePageNum(int pageNum)
374 407
     {
375 408
         return pageNum > 0 ? pageNum : 1;

+ 20 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/research/support/ResearchOpenApiSupport.java

@@ -9,6 +9,7 @@ import com.ruoyi.web.modules.industryservice.domain.BizFarmerHousehold;
9 9
 import com.ruoyi.web.modules.industryservice.domain.BizLargeLivestockFarmer;
10 10
 import com.ruoyi.web.modules.industryservice.domain.BizLivestockProductOutput;
11 11
 import com.ruoyi.web.modules.industryservice.domain.BizPasture;
12
+import com.ruoyi.web.modules.industryservice.domain.BizVaccinationData;
12 13
 import com.ruoyi.web.modules.industryservice.domain.BizYakAsset;
13 14
 import com.ruoyi.web.modules.industryservice.domain.BizYakHerdInventory;
14 15
 import com.ruoyi.web.modules.industryservice.domain.BizYakOutboundReport;
@@ -21,6 +22,7 @@ import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchFarmerHo
21 22
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLargeLivestockFarmerVo;
22 23
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLivestockProductOutputVo;
23 24
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchPastureVo;
25
+import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchVaccinationDataVo;
24 26
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakAssetVo;
25 27
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakHerdInventoryVo;
26 28
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakOutboundReportVo;
@@ -398,4 +400,22 @@ public final class ResearchOpenApiSupport
398 400
         vo.setWagePaid(row.getWagePaid());
399 401
         return vo;
400 402
     }
403
+
404
+    public static ResearchVaccinationDataVo toVaccinationDataVo(BizVaccinationData row)
405
+    {
406
+        if (row == null)
407
+        {
408
+            return null;
409
+        }
410
+        ResearchVaccinationDataVo vo = new ResearchVaccinationDataVo();
411
+        vo.setVaccinationId(row.getId());
412
+        vo.setStatYear(row.getStatYear());
413
+        vo.setStatMonth(row.getStatMonth());
414
+        vo.setTownName(row.getTownName());
415
+        vo.setVillageName(row.getVillageName());
416
+        vo.setShouldVaccinateCount(row.getShouldVaccinateCount());
417
+        vo.setActualVaccinateCount(row.getActualVaccinateCount());
418
+        vo.setImmunityRate(row.getImmunityRate());
419
+        return vo;
420
+    }
401 421
 }

+ 6 - 0
baqing-admin/src/main/resources/mapper/industryservice/BizVaccinationDataMapper.xml

@@ -73,6 +73,12 @@
73 73
             <if test="villageDeptId != null">
74 74
                 and r.village_dept_id = #{villageDeptId}
75 75
             </if>
76
+            <if test="townName != null and townName != ''">
77
+                and r.town_name like concat('%', #{townName}, '%')
78
+            </if>
79
+            <if test="villageName != null and villageName != ''">
80
+                and r.village_name like concat('%', #{villageName}, '%')
81
+            </if>
76 82
             ${params.dataScope}
77 83
         </where>
78 84
         order by r.stat_year desc, r.stat_month desc, d.order_num asc, r.village_dept_id asc, r.id desc

+ 30 - 0
baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/research/controller/ResearchOpenApiControllerApiTest.java

@@ -29,6 +29,7 @@ import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchFarmerHo
29 29
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLargeLivestockFarmerVo;
30 30
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchLivestockProductOutputVo;
31 31
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchPastureVo;
32
+import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchVaccinationDataVo;
32 33
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakHerdInventoryVo;
33 34
 import com.ruoyi.web.modules.industryservice.research.domain.vo.ResearchYakOutboundReportVo;
34 35
 import com.ruoyi.web.modules.industryservice.research.service.IResearchOpenApiService;
@@ -342,4 +343,33 @@ class ResearchOpenApiControllerApiTest
342 343
                 .andExpect(jsonPath("$.code").value(200))
343 344
                 .andExpect(jsonPath("$.data.records[0].enterpriseName").value("测试养殖大户"));
344 345
     }
346
+
347
+    @Test
348
+    @DisplayName("GET /vaccination-data 成功")
349
+    void listVaccinationData() throws Exception
350
+    {
351
+        ResearchVaccinationDataVo row = new ResearchVaccinationDataVo();
352
+        row.setVaccinationId(1L);
353
+        row.setStatYear(2026);
354
+        row.setStatMonth(5);
355
+        row.setTownName("雅安镇");
356
+        row.setVillageName("荣嘎村");
357
+        OpenApiPageResult<ResearchVaccinationDataVo> page = new OpenApiPageResult<>();
358
+        page.setPageNum(1);
359
+        page.setPageSize(20);
360
+        page.setTotal(1L);
361
+        page.setRecords(Collections.singletonList(row));
362
+        when(researchOpenApiService.listVaccinationData(anyInt(), anyInt(), any(), any(), any(), any()))
363
+                .thenReturn(page);
364
+
365
+        mockMvc.perform(get("/open-api/v1/research/vaccination-data")
366
+                .param("statYear", "2026")
367
+                .param("statMonth", "5")
368
+                .param("townName", "雅安")
369
+                .param("villageName", "荣嘎"))
370
+                .andExpect(status().isOk())
371
+                .andExpect(jsonPath("$.code").value(200))
372
+                .andExpect(jsonPath("$.data.records[0].townName").value("雅安镇"))
373
+                .andExpect(jsonPath("$.data.records[0].villageName").value("荣嘎村"));
374
+    }
345 375
 }

+ 17 - 0
doc/产业数据模型及服务/科研开放数据接口/科研开放数据接口功能需求.md

@@ -37,6 +37,7 @@
37 37
 | 农牧户数据列表 | 分页返回村级农牧户填报 |
38 38
 | 共同富裕项目列表 | 分页返回共同富裕项目 |
39 39
 | 养殖大户数据列表 | 分页返回养殖大户填报;法人姓名脱敏 |
40
+| 疫苗接种数据列表 | 分页返回村级疫苗接种填报 |
40 41
 
41 42
 **本期不实现:**
42 43
 
@@ -249,6 +250,20 @@ sequenceDiagram
249 250
 
250 251
 **不返回**:部门 ID、创建人、备注等内部字段。
251 252
 
253
+### 6.13 疫苗接种数据列表
254
+
255
+| 项 | 说明 |
256
+| --- | --- |
257
+| 方法 | GET |
258
+| 路径 | `/vaccination-data` |
259
+| 鉴权 | Bearer Token |
260
+| 分页 | 同 §6.2 |
261
+| 筛选 | `statYear`、`statMonth`、`townName`(乡镇模糊)、`villageName`(村模糊) |
262
+
263
+**返回字段**:`vaccinationId`、年月、乡镇村、`shouldVaccinateCount`、`actualVaccinateCount`、`immunityRate`。
264
+
265
+**不返回**:部门 ID、创建人、备注等内部字段。
266
+
252 267
 ---
253 268
 
254 269
 ## 7. 脱敏规则摘要
@@ -295,6 +310,7 @@ sequenceDiagram
295 310
 | 农牧户数据填报 | 数据源 `biz_farmer_household` |
296 311
 | 共同富裕项目管理 | 数据源 `biz_common_prosperity_project` |
297 312
 | 养殖大户数据填报 | 数据源 `biz_large_livestock_farmer` |
313
+| 疫苗接种数据填报 | 数据源 `biz_vaccination_data` |
298 314
 | 若依权限体系 | **无**关联;开放接口走独立 Token |
299 315
 
300 316
 ---
@@ -315,5 +331,6 @@ sequenceDiagram
315 331
 | 农牧户列表 | §6.10 |
316 332
 | 共同富裕项目列表 | §6.11 |
317 333
 | 养殖大户列表 | §6.12 |
334
+| 疫苗接种列表 | §6.13 |
318 335
 | 脱敏合规 | §7 |
319 336
 | 本期不实现 | §3 |

+ 22 - 2
doc/产业数据模型及服务/科研开放数据接口/科研开放数据接口技术方案.md

@@ -9,7 +9,7 @@
9 9
 | 项 | 说明 |
10 10
 | --- | --- |
11 11
 | **后端** | RuoYi **v3.9.2**(**springboot2** 分支):JDK 8、Spring MVC、MyBatis |
12
-| **数据库** | 只读查询既有表 `biz_pasture`、`biz_yak_asset`、`biz_yak_herd_inventory`、`biz_yak_outbound_report`、`biz_cooperative_development`、`biz_livestock_product_output`、`biz_family_ranch`、`biz_disposable_income`、`biz_farmer_household`、`biz_common_prosperity_project`、`biz_large_livestock_farmer` |
12
+| **数据库** | 只读查询既有表 `biz_pasture`、`biz_yak_asset`、`biz_yak_herd_inventory`、`biz_yak_outbound_report`、`biz_cooperative_development`、`biz_livestock_product_output`、`biz_family_ranch`、`biz_disposable_income`、`biz_farmer_household`、`biz_common_prosperity_project`、`biz_large_livestock_farmer`、`biz_vaccination_data` |
13 13
 | **鉴权** | 独立 JWT + Servlet Filter;`@Anonymous` 绕过若依登录,Filter 校验 Bearer Token |
14 14
 | **响应** | `OpenApiResponse<T>` + `OpenApiPageResult<T>`(与第三方 farming OpenAPI 同结构) |
15 15
 
@@ -247,6 +247,19 @@ Authorization: Bearer <accessToken>
247 247
 
248 248
 实现说明:直接查 `BizLargeLivestockFarmerMapper`(清空 `params.dataScope`)。
249 249
 
250
+### 3.13 疫苗接种数据列表
251
+
252
+```
253
+GET /open-api/v1/research/vaccination-data?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=
254
+Authorization: Bearer <accessToken>
255
+```
256
+
257
+**查询参数:** `statYear` / `statMonth`(精确);`townName` / `villageName`(模糊);分页同前。
258
+
259
+**`records[]` 元素(ResearchVaccinationDataVo):** `vaccinationId`、年月、乡镇村、应免/实免数、免疫率;**不含**部门 ID、操作人、备注。
260
+
261
+实现说明:直接查 `BizVaccinationDataMapper`(清空 `params.dataScope`)。
262
+
250 263
 ---
251 264
 
252 265
 ## 4. 鉴权流程
@@ -277,8 +290,9 @@ Token 申请:`appKey`/`appSecret` 与配置项精确匹配后签发 JWT(HS51
277 290
 | 农牧户列表 | `BizFarmerHouseholdMapper.selectBizFarmerHouseholdList` | `biz_farmer_household` | 年/月精确;乡镇/村名模糊;清空 `params.dataScope` |
278 291
 | 共同富裕项目列表 | `BizCommonProsperityProjectMapper.selectBizCommonProsperityProjectList` | `biz_common_prosperity_project` | 项目名模糊;类型/实施年限精确 |
279 292
 | 养殖大户列表 | `BizLargeLivestockFarmerMapper.selectBizLargeLivestockFarmerList` | `biz_large_livestock_farmer` | 年/月精确;乡镇/村/企业名模糊;清空 `params.dataScope` |
293
+| 疫苗接种列表 | `BizVaccinationDataMapper.selectBizVaccinationDataList` | `biz_vaccination_data` | 年/月精确;乡镇/村名模糊;清空 `params.dataScope` |
280 294
 
281
-实体 → VO:`ResearchOpenApiSupport.toPastureVo` / `toYakAssetVo` / `toYakHerdInventoryVo` / `toYakOutboundReportVo` / `toCooperativeDevelopmentVo` / `toLivestockProductOutputVo` / `toFamilyRanchVo` / `toDisposableIncomeVo` / `toFarmerHouseholdVo` / `toCommonProsperityProjectVo` / `toLargeLivestockFarmerVo`。
295
+实体 → VO:`ResearchOpenApiSupport.toPastureVo` / `toYakAssetVo` / `toYakHerdInventoryVo` / `toYakOutboundReportVo` / `toCooperativeDevelopmentVo` / `toLivestockProductOutputVo` / `toFamilyRanchVo` / `toDisposableIncomeVo` / `toFarmerHouseholdVo` / `toCommonProsperityProjectVo` / `toLargeLivestockFarmerVo` / `toVaccinationDataVo`
282 296
 
283 297
 ---
284 298
 
@@ -359,6 +373,10 @@ curl "http://localhost:8010/open-api/v1/research/common-prosperity-projects?page
359 373
 # 12. 养殖大户
360 374
 curl "http://localhost:8010/open-api/v1/research/large-livestock-farmers?pageNum=1&pageSize=10&statYear=2026&enterpriseName=养殖" \
361 375
   -H "Authorization: Bearer <accessToken>"
376
+
377
+# 13. 疫苗接种
378
+curl "http://localhost:8010/open-api/v1/research/vaccination-data?pageNum=1&pageSize=10&statYear=2026&townName=雅安" \
379
+  -H "Authorization: Bearer <accessToken>"
362 380
 ```
363 381
 
364 382
 ---
@@ -389,6 +407,7 @@ curl "http://localhost:8010/open-api/v1/research/large-livestock-farmers?pageNum
389 407
 | §6.10 农牧户 | **§3.10**、**§5** BizFarmerHousehold |
390 408
 | §6.11 共同富裕项目 | **§3.11**、**§5** BizCommonProsperityProject |
391 409
 | §6.12 养殖大户 | **§3.12**、**§5** BizLargeLivestockFarmer |
410
+| §6.13 疫苗接种 | **§3.13**、**§5** BizVaccinationData |
392 411
 | §7 脱敏 | **§6** Masking |
393 412
 | §3 不实现机构区分 | 单一 app-key/secret,JWT 无 clientId |
394 413
 
@@ -398,6 +417,7 @@ curl "http://localhost:8010/open-api/v1/research/large-livestock-farmers?pageNum
398 417
 
399 418
 | 版本 | 日期 | 说明 |
400 419
 | --- | --- | --- |
420
+| 1.10 | 2026-07-22 | 新增疫苗接种开放列表(年/月/乡镇村模糊+分页) |
401 421
 | 1.9 | 2026-07-22 | 新增养殖大户开放列表(年/月/乡镇村/企业名模糊+分页;法人脱敏) |
402 422
 | 1.8 | 2026-07-22 | 新增共同富裕项目开放列表(项目名模糊/类型与实施年限精确+分页) |
403 423
 | 1.7 | 2026-07-22 | 新增农牧户开放列表(年/月/乡镇村模糊+分页) |

+ 5 - 1
doc/产业数据模型及服务/科研开放数据接口/科研开放数据接口测试用例.md

@@ -61,6 +61,8 @@
61 61
 | KYKF-API-028 | 共同富裕项目 | 名称/类型/年限筛选 | 接口测试 | curl | §6.11 | 已知项目名片段与类型 | GET 带筛选参数 | 条件生效;名称模糊、类型与年限精确 |
62 62
 | KYKF-API-029 | 养殖大户 | 分页列表 | 接口测试 | curl | §6.12 | 有效 Token;库有大户数据 | GET `/large-livestock-farmers?pageNum=1&pageSize=10` | `code=200`;法人已脱敏;无部门 ID |
63 63
 | KYKF-API-030 | 养殖大户 | 年/月/乡镇村/企业名筛选 | 接口测试 | curl | §6.12 | 已知企业名片段 | GET 带筛选参数 | 条件生效;名称模糊匹配 |
64
+| KYKF-API-031 | 疫苗接种 | 分页列表 | 接口测试 | curl | §6.13 | 有效 Token;库有接种数据 | GET `/vaccination-data?pageNum=1&pageSize=10` | `code=200`;无部门 ID |
65
+| KYKF-API-032 | 疫苗接种 | 年/月/乡镇村筛选 | 接口测试 | curl | §6.13 | 已知年月与乡镇名片段 | GET 带筛选参数 | 条件生效;名称模糊匹配 |
64 66
 
65 67
 ---
66 68
 
@@ -80,11 +82,12 @@
80 82
 | §6.10 农牧户列表 | — | API-025~026 |
81 83
 | §6.11 共同富裕项目列表 | — | API-027~028 |
82 84
 | §6.12 养殖大户列表 | — | API-029~030 |
85
+| §6.13 疫苗接种列表 | — | API-031~032 |
83 86
 | §7 脱敏 | UT-001~004 | API-012 |
84 87
 | §2 分页 | — | API-010 |
85 88
 | §3 无机构区分 | UT-005 | API-001(单一凭证) |
86 89
 
87
-**用例统计**:单元 **6**、接口 **30**,合计 **36** 条。
90
+**用例统计**:单元 **6**、接口 **32**,合计 **38** 条。
88 91
 
89 92
 ---
90 93
 
@@ -108,6 +111,7 @@ curl -s "$BASE/disposable-incomes?pageNum=1&pageSize=5&statYear=2025" -H "Author
108 111
 curl -s "$BASE/farmer-households?pageNum=1&pageSize=5&statYear=2026" -H "Authorization: Bearer $TOKEN"
109 112
 curl -s "$BASE/common-prosperity-projects?pageNum=1&pageSize=5&implYear=2025" -H "Authorization: Bearer $TOKEN"
110 113
 curl -s "$BASE/large-livestock-farmers?pageNum=1&pageSize=5&statYear=2026" -H "Authorization: Bearer $TOKEN"
114
+curl -s "$BASE/vaccination-data?pageNum=1&pageSize=5&statYear=2026" -H "Authorization: Bearer $TOKEN"
111 115
 ```
112 116
 
113 117
 (Windows 环境可用 PowerShell `Invoke-RestMethod`,见技术方案 **§8**。)