西藏巴青项目

牦牛存栏数据填报技术方案.md 10KB

牦牛存栏数据填报 — 技术方案

依据:同目录 牦牛存栏数据填报功能需求.md;模板 E:\luhao\工作交接\巴青项目\农牧数据\农业农村和科技水利局-业务办\畜群结构\2026年.xlsx(第一个 Sheet)。


1. 技术架构

说明
后端 RuoYi v3.9.2(springboot2):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid
数据库 MySQL 5.7.39,InnoDB,utf8mb4
前端 若依 Vue2 + Element UI
Excel Apache POI 或项目已有 EasyExcel(与若依导入规范一致)
组织 sys_dept 乡镇字典;SysDeptMapper 查询二级节点

分层BizYakHerdInventoryControllerIBizYakHerdInventoryServiceBizYakHerdInventoryMapperdomain;Excel 由 YakHerdInventoryExcelParser(导入解析)、YakHerdInventoryExcelExporter(按年导出)承担。

代码位置baqing-admincom.ruoyi.web.modules.industryservice(与产业数据模型同包)。

模板文件baqing-admin/src/main/resources/templates/yak_herd_inventory_import_template.xlsx(导入、导出、下载模板共用)。


2. 数据库设计

2.1 表 biz_yak_herd_inventory(牦牛存栏数据填报)

字段 类型 非空 说明
id bigint(20) Y 主键
stat_year int(11) Y 所属年份(自然年)
town_dept_id bigint(20) Y 所属乡镇,sys_dept.dept_id
town_name varchar(64) Y 乡镇名称冗余,便于列表展示
village_dept_id bigint(20) N 预留所属村居,sys_dept.dept_id(乡镇下三级节点)
village_name varchar(128) N 预留所属村居名称冗余
village_count int(11) N 村居数
herdsman_household_count int(11) N 牧户数
yak_total int(11) N 牦牛存栏数
bull_total int(11) N 公牛存栏数
cow_total int(11) N 母牛存栏数
breeding_bull_count int(11) N 种公牛存栏数
bull_castrated_count int(11) N 公牛/阉畜存栏数
cow_under_1_count int(11) N 1 岁以下母牛存栏数
cow_1_3_count int(11) N 1~3 岁母牛存栏数
cow_3_12_count int(11) N 3~12 岁母牛存栏数
cow_over_12_count int(11) N 12 岁以上母牛存栏数
del_flag char(1) Y 0 正常 2 删除
create_by / create_time 审计
update_by / update_time 审计
remark varchar(500) N 备注

索引与约束

  • 应用层校验:同年同乡镇仅一条 del_flag='0' 有效记录(countActiveByYearAndTownExcludeId)。
  • KEY idx_stat_year (stat_year)
  • KEY idx_town_dept_id (town_dept_id)
  • KEY idx_del_flag (del_flag)

DDL 文件sql/biz_yak_herd_inventory.sql

2.2 乡镇字典查询(sys_dept

SELECT dept_id, dept_name, order_num
FROM sys_dept
WHERE parent_id = 100
  AND order_num > 12
  AND del_flag = '0'
  AND status = '0'
ORDER BY order_num;

前端乡镇下拉、导入匹配均调用封装方法 TownDeptSupport.listReportTowns()(名称与根 parent_id 可配置化 ruoyi.town-dept-parent-id=100ruoyi.town-dept-min-order-num=12)。

2.3 可选年份

// 当前年起向前 5 年,共 6 个
int current = Year.now().getValue();
for (int y = current; y >= current - 5; y--) { ... }

3. 接口设计

Base Path/dataModel/yakHerdInventory

权限前缀dataModel:yakHerdInventory

# 说明 Method URI 权限
3.1 分页列表 GET /list list
3.2 详情 GET /{id} query
3.3 新增 POST / add
3.4 修改 PUT / edit
3.5 删除 DELETE /{ids} remove
3.6 乡镇下拉 GET /townOptions list
3.7 年份下拉 GET /yearOptions list
3.8 导入 POST /importData import
3.9 下载导入模板 GET /importTemplate import
3.10 按年份导出 GET /export export

3.1.1 列表 Query

参数 类型 说明
pageNum / pageSize int 默认 1 / 20
statYear int 所属年份,精确
townDeptId long 所属乡镇 dept_id,精确

列表 VO 字段(列标题与需求 §5.1 一致):

列标题 字段
所属年份 statYear
乡镇 townName
村居数 villageCount
牧户数 herdsmanHouseholdCount
存栏数 yakTotal
公牛存栏数 bullTotal
母牛存栏数 cowTotal

3.2.1 详情

返回 BizYakHerdInventory 全字段(驼峰),含预留村居、分龄母牛、种公牛、阉畜、备注及 createBy / createTime / updateBy / updateTime 等。

3.3.1 新增/修改 Body

字段 必填 校验
statYear Y yearOptions 范围内
townDeptId Y 须在乡镇字典内
villageDeptId N 预留;若填写须为有效 sys_dept.dept_id,且 parent_id = townDeptId(可选校验)
villageName N 预留村居名称
*Count N >= 0 整数
id 修改必填

唯一性existsActive(statYear, townDeptId, excludeId) 为 true 则拒绝。

3.8 导入

请求multipart/form-data

参数 必填 说明
file Y .xlsx
statYear Y 填报年份

响应 data

字段 说明
insertCount 新增条数
updateCount 更新条数
failCount 失败条数
failMessages 第8行[杂色镇]: 乡镇未识别
warnMessages 分龄加总与母牛合计不一致等警告(可选)

3.8.1 Excel 第一个 Sheet 解析约定(2026年.xlsx

约定
Sheet workbook.getSheetAt(0)
标题行 前若干行为「巴青县…畜群结构…统计表」及填表说明,自动扫描首列含「序号」且相邻列含「乡镇」的行作为表头行 headerRow
数据行 headerRow + 1 起至「乡镇」列为空
列映射(默认,实施对照模板微调)
列号(0-based) Excel 列 实体字段
1 B 乡镇(按 dept_name 解析 townDeptId
2 C villageCount
3 D herdsmanHouseholdCount
4 E yakTotal(存栏数)
5 F 与 E 同值(模板镜像列,导出时同步写入)
6 G bullTotal
9 J breedingBullCount
10 K bullCastratedCount
11 L cowTotal
12 M cowUnder1Count
13 N cow13Count
14 O cow312Count
15 P cowOver12Count
16 Q remark

数据区起始行:headerRow + 3(表头行由「序号」「乡镇」自动识别)。模板存在合并单元格,列号以代码常量为准。

导入事务:逐乡镇独立处理,单乡镇失败不影响其余。

3.10 按年份导出

请求GET /export?statYear=2026

参数 必填 说明
statYear Y 导出年份,须在 yearOptions 范围内

响应application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 文件流;文件名 {statYear}年牦牛存栏数据.xlsx

实现BizYakHerdInventoryServiceImpl.exportByYearYakHerdInventoryExcelExporter.export

  1. 加载 classpath 模板 YakHerdInventoryExcelExporter.TEMPLATE_CLASSPATH
  2. 替换表头中的四位年份为 statYear
  3. 查询 stat_year = statYeardel_flag='0' 的全部记录,按 town_dept_id 建 Map
  4. 遍历 TownDeptSupport.listReportTowns(),逐乡镇写行;无数据则仅写乡镇名
  5. 末行写「合计」,对已填报乡镇数值列求和

与 3.9 区别/importTemplate 返回空白模板;/export 返回填充后的全县报表。


4. 前端设计(要点)

说明
路径 ruoyi-ui/src/views/dataModel/yakHerdInventory/index.vue
API ruoyi-ui/src/api/dataModel/yakHerdInventory.js
列表 年份、乡镇筛选;列:所属年份、乡镇、村居数、牧户数、存栏数、公牛存栏数、母牛存栏数
详情 抽屉/对话框只读展示全部字段
表单 抽屉或对话框;年份/乡镇下拉;数字 el-input-number :min="0" :precision="0"
导入 先选「填报年份」→ 上传 → 展示导入结果摘要
模板下载 GET /importTemplate;空白模板
按年份导出 列表先选「所属年份」→ GET /exportdownload('dataModel/yakHerdInventory/export', { statYear })

5. 菜单与权限(示例)

类型 名称 权限标识
菜单 牦牛存栏数据填报 dataModel:yakHerdInventory:list
按钮 查询 dataModel:yakHerdInventory:query
按钮 新增 dataModel:yakHerdInventory:add
按钮 修改 dataModel:yakHerdInventory:edit
按钮 删除 dataModel:yakHerdInventory:remove
按钮 导入 dataModel:yakHerdInventory:import
按钮 导出 dataModel:yakHerdInventory:export

挂载目录:产业数据模型及服务。菜单 SQL 见 sql/biz_sys_menu_yak_herd_inventory.sql


6. 与养殖产业数据看板的关系

「养殖产业数据」看板(doc/.../养殖产业数据)当前以生物资产台账汇总为主;本表为乡镇级手工/导入汇总的权威填报源。后续若看板需展示「乡镇填报存栏」,可增加只读聚合接口读取 biz_yak_herd_inventory 指定 stat_year 全县加总,本期不实现


7. 交付清单

  • sql/biz_yak_herd_inventory.sql
  • BizYakHerdInventory Domain / Mapper / XML / Service / Controller
  • YakHerdInventoryExcelParser + YakHerdInventoryExcelExporter
  • TownDeptSupport 乡镇字典
  • 前端列表/表单/导入/导出
  • 单元测试 + 导入/导出集成测试(yak_herd_inventory_2026.xlsx

8. 修订记录

版本 说明
1.0 初稿:表结构、CRUD、导入、sys_dept 乡镇、年份前推 5 年
1.1 增加预留字段 village_dept_id(非必填)
1.2 实现按年份导出全县乡镇 Excel;列映射与代码对齐;交付清单勾选