依据:同目录
科研开放数据接口功能需求.md。对外只读开放 API;无前端页面、无新表。
| 项 | 说明 |
|---|---|
| 后端 | RuoYi v3.9.2(springboot2 分支):JDK 8、Spring MVC、MyBatis |
| 数据库 | 只读查询既有表 biz_pasture、biz_yak_asset、biz_yak_herd_inventory、biz_yak_outbound_report、biz_cooperative_development、biz_livestock_product_output、biz_family_ranch |
| 鉴权 | 独立 JWT + Servlet Filter;@Anonymous 绕过若依登录,Filter 校验 Bearer Token |
| 响应 | OpenApiResponse<T> + OpenApiPageResult<T>(与第三方 farming OpenAPI 同结构) |
代码包:baqing-admin → com.ruoyi.web.modules.industryservice.research
| 类 | 职责 |
|---|---|
ResearchOpenApiController |
HTTP 入口 |
ResearchOpenApiServiceImpl |
分页查询 + 脱敏 VO 转换 |
ResearchOpenApiTokenService |
签发/校验 JWT |
ResearchOpenApiAuthFilter |
除 /auth/token 外校验 Token |
ResearchOpenApiMasking / ResearchOpenApiSupport |
脱敏与响应组装 |
application.yml → research-open-api:
| 键 | 说明 |
|---|---|
enabled |
是否启用;false 时返回 503 |
app-key |
申请 Token 用(全局唯一) |
app-secret |
申请 Token 用 |
token-secret |
JWT 签名密钥(仅服务端,勿下发) |
token-expire-minutes |
Token 有效期,默认 120 |
max-page-size |
单页上限,默认 200 |
示例:
research-open-api:
enabled: true
app-key: research-open-demo-key
app-secret: research-open-demo-secret-change-me
token-secret: research-open-api-change-me-in-production
token-expire-minutes: 120
max-page-size: 200
Base Path:/open-api/v1/research
POST /open-api/v1/research/auth/token
Content-Type: application/json
{"appKey":"research-open-demo-key","appSecret":"research-open-demo-secret-change-me"}
成功响应 data:
{
"accessToken": "eyJhbGciOiJIUzUxMiJ9...",
"tokenType": "Bearer",
"expiresIn": 7200
}
JWT Claims:type=research_open_api;不含机构 ID。
GET /open-api/v1/research/pastures?pageNum=1&pageSize=20&keyword=
Authorization: Bearer <accessToken>
records[] 元素(ResearchPastureVo):
| 字段 | 类型 | 说明 |
|---|---|---|
pastureId |
long | 本地牧场 ID |
pastureName |
string | 牧场名称 |
farmType |
string | 类型 |
county / town |
string | 区县、乡镇 |
regionSummary |
string | 区县+乡镇摘要 |
latitude / longitude |
number | 约百米精度 |
floorArea / scaleBreeding / breedSpecies |
string | 规模类 |
introduction |
string | 简介 |
personInCharge |
string | 脱敏负责人 |
contactPhone |
string | 脱敏手机 |
GET /open-api/v1/research/yak-assets?pageNum=1&pageSize=20&assetStatus=1&gender=母&pastureId=
Authorization: Bearer <accessToken>
records[] 元素(ResearchYakAssetVo):
| 字段 | 类型 | 说明 |
|---|---|---|
subjectCode |
string | 科研主体码,如 YS00000088 |
pastureName / enclosureName |
string | 牧场、圈舍名称 |
gender / cattleVariety |
string | 性别、品种 |
ageMonths |
int | 月龄 |
birthYear / birthMonth |
int | 出生年月 |
assetStatus |
int | 1~4 |
assetStatusLabel |
string | 正常/死淘/丢失/出栏 |
entryWeightKg |
decimal | 入栏体重 |
source / breedingMethod / entryCycle |
string | 来源、养殖方式、周期 |
realtimeTemp / realtimeSteps / envTemp |
number | IoT 快照 |
fatherSubjectCode / motherSubjectCode |
string | 系谱 pseudonym |
GET /open-api/v1/research/yak-herd-inventories?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=
Authorization: Bearer <accessToken>
查询参数:
| 参数 | 说明 |
|---|---|
statYear |
所属年份(精确) |
statMonth |
所属月份(精确) |
townName |
所属乡镇名称模糊匹配 |
villageName |
所属村名称模糊匹配 |
pageNum / pageSize |
分页,同牧场列表 |
records[] 元素(ResearchYakHerdInventoryVo): 含 inventoryId、statYear、statMonth、townName、villageName 及畜群汇总数量字段;不含 townDeptId / villageDeptId、操作人、备注。
实现说明:直接查 BizYakHerdInventoryMapper(不走填报 Service 的部门数据权限)。
GET /open-api/v1/research/yak-outbound-reports?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=
Authorization: Bearer <accessToken>
查询参数: 同 §3.4(statYear / statMonth / townName / villageName / 分页)。
records[] 元素(ResearchYakOutboundReportVo): 含 outboundId、年月、乡镇村名及出栏汇总数量;不含部门 ID、操作人、备注。
实现说明:直接查 BizYakOutboundReportMapper(清空 params.dataScope)。
GET /open-api/v1/research/cooperative-developments?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=&cooperativeName=
Authorization: Bearer <accessToken>
查询参数: statYear / statMonth(精确);townName / villageName / cooperativeName(模糊);分页同前。
records[] 元素(ResearchCooperativeDevelopmentVo): 合作社发展业务字段;legalRepresentative 脱敏;不含部门 ID、操作人、备注。
实现说明:直接查 BizCooperativeDevelopmentMapper(清空 params.dataScope)。
GET /open-api/v1/research/livestock-product-outputs?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=
Authorization: Bearer <accessToken>
查询参数: statYear / statMonth(精确);townName / villageName(模糊);分页同前。
records[] 元素(ResearchLivestockProductOutputVo): outputId、年月、乡镇村、meatOutput/milkOutput(万吨);不含部门 ID、操作人、备注。
实现说明:直接查 BizLivestockProductOutputMapper(清空 params.dataScope)。
GET /open-api/v1/research/family-ranches?pageNum=1&pageSize=20&statYear=2026&statMonth=5&townName=&villageName=&enterpriseName=
Authorization: Bearer <accessToken>
查询参数: statYear / statMonth(精确);townName / villageName / enterpriseName(模糊);分页同前。
records[] 元素(ResearchFamilyRanchVo): 家庭牧场业务字段;legalRepresentative 脱敏;不含部门 ID、操作人、备注。
实现说明:直接查 BizFamilyRanchMapper(清空 params.dataScope)。
ResearchOpenApiController 标注 @Anonymous → Spring Security 放行。ResearchOpenApiAuthFilter 拦截 /open-api/v1/research/*(排除 /auth/token)。Authorization: Bearer …,ResearchOpenApiTokenService.validateToken 验签与过期。{ code:401, message:"..." },HTTP 401。Token 申请:appKey/appSecret 与配置项精确匹配后签发 JWT(HS512 + token-secret)。
复用既有 Service / Mapper:
| 接口 | Service | 表 | 条件 |
|---|---|---|---|
| 牧场列表 | IBizPastureService.selectBizPastureList |
biz_pasture |
del_flag=0 |
| 档案列表 | IBizYakAssetService.selectBizYakAssetList |
biz_yak_asset |
del_flag=0;支持 assetStatus、gender、pastureId |
| 存栏列表 | BizYakHerdInventoryMapper.selectBizYakHerdInventoryList |
biz_yak_herd_inventory |
年/月精确;乡镇/村名模糊;清空 params.dataScope |
| 出栏列表 | BizYakOutboundReportMapper.selectBizYakOutboundReportList |
biz_yak_outbound_report |
同上 |
| 合作社列表 | BizCooperativeDevelopmentMapper.selectBizCooperativeDevelopmentList |
biz_cooperative_development |
年/月精确;乡镇/村/合作社名模糊;清空 params.dataScope |
| 产量列表 | BizLivestockProductOutputMapper.selectBizLivestockProductOutputList |
biz_livestock_product_output |
年/月精确;乡镇/村名模糊;清空 params.dataScope |
| 家庭牧场列表 | BizFamilyRanchMapper.selectBizFamilyRanchList |
biz_family_ranch |
年/月精确;乡镇/村/企业名模糊;清空 params.dataScope |
实体 → VO:ResearchOpenApiSupport.toPastureVo / toYakAssetVo / toYakHerdInventoryVo / toYakOutboundReportVo / toCooperativeDevelopmentVo / toLivestockProductOutputVo / toFamilyRanchVo。
| 方法 | 说明 |
|---|---|
maskPhone |
复用 SubsidyGrantRecordMasking.maskPhone |
maskPersonName |
首字 + * |
regionSummary |
区县 + 乡镇 |
roundCoordinate |
经纬度 3 位小数 |
subjectCode |
YS + 8 位 id |
pseudonymCode |
系谱编号哈希短码 |
| code | HTTP | 场景 |
|---|---|---|
| 200 | 200 | 成功 |
| 401 | 401 | appKey/appSecret 错误、Token 缺失/无效/过期 |
| 400 | 200* | pageSize 超限(body.code=400) |
| 503 | 503 | enabled=false 或未配置凭证 |
* 业务错误仍返回 JSON body,HTTP 状态与 code 一致(Filter 401/503;Controller 内 ServiceException 写入 body.code)。
# 1. 申请 Token
curl -X POST "http://localhost:8010/open-api/v1/research/auth/token" \
-H "Content-Type: application/json" \
-d '{"appKey":"research-open-demo-key","appSecret":"research-open-demo-secret-change-me"}'
# 2. 牧场列表
curl "http://localhost:8010/open-api/v1/research/pastures?pageNum=1&pageSize=10" \
-H "Authorization: Bearer <accessToken>"
# 3. 牦牛档案
curl "http://localhost:8010/open-api/v1/research/yak-assets?pageNum=1&pageSize=10&assetStatus=1" \
-H "Authorization: Bearer <accessToken>"
# 4. 牦牛存栏
curl "http://localhost:8010/open-api/v1/research/yak-herd-inventories?pageNum=1&pageSize=10&statYear=2026&townName=雅安" \
-H "Authorization: Bearer <accessToken>"
# 5. 牦牛出栏
curl "http://localhost:8010/open-api/v1/research/yak-outbound-reports?pageNum=1&pageSize=10&statYear=2026&townName=雅安" \
-H "Authorization: Bearer <accessToken>"
# 6. 合作社发展
curl "http://localhost:8010/open-api/v1/research/cooperative-developments?pageNum=1&pageSize=10&statYear=2026&cooperativeName=合作" \
-H "Authorization: Bearer <accessToken>"
# 7. 畜牧产品产量
curl "http://localhost:8010/open-api/v1/research/livestock-product-outputs?pageNum=1&pageSize=10&statYear=2026&townName=雅安" \
-H "Authorization: Bearer <accessToken>"
# 8. 家庭牧场
curl "http://localhost:8010/open-api/v1/research/family-ranches?pageNum=1&pageSize=10&statYear=2026&enterpriseName=牧场" \
-H "Authorization: Bearer <accessToken>"
见同目录 科研开放数据接口测试用例.md。单元测试:
ResearchOpenApiMaskingTestResearchOpenApiTokenServiceTestResearchOpenApiControllerApiTest| 功能需求 | 技术落点 |
|---|---|
| §5 认证 | §2 配置、§4 Filter + TokenService |
| §6.2 牧场 | §3.2、§5 BizPasture |
| §6.3 档案 | §3.3、§5 BizYakAsset |
| §6.4 存栏 | §3.4、§5 BizYakHerdInventory |
| §6.5 出栏 | §3.5、§5 BizYakOutboundReport |
| §6.6 合作社 | §3.6、§5 BizCooperativeDevelopment |
| §6.7 产量 | §3.7、§5 BizLivestockProductOutput |
| §6.8 家庭牧场 | §3.8、§5 BizFamilyRanch |
| §7 脱敏 | §6 Masking |
| §3 不实现机构区分 | 单一 app-key/secret,JWT 无 clientId |
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.5 | 2026-07-22 | 新增家庭牧场开放列表(年/月/乡镇村/企业名模糊+分页;法人脱敏) |
| 1.4 | 2026-07-22 | 新增畜牧产品产量登记开放列表(年/月/乡镇村模糊+分页) |
| 1.3 | 2026-07-22 | 新增合作社发展开放列表(年/月/乡镇村/名称模糊+分页;法人脱敏) |
| 1.2 | 2026-07-22 | 新增牦牛出栏开放列表(年/月/乡镇村模糊+分页) |
| 1.1 | 2026-07-22 | 新增牦牛存栏开放列表(年/月/乡镇村模糊+分页) |
| 1.0 | 2026-07-04 | 初版:Token + 牧场/档案脱敏列表;全局一对凭证 |