wwh недель назад: 2
Родитель
Сommit
7fb8cde2e4

+ 4 - 126
doc/产业数据模型及服务/牦牛出栏数据填报/牦牛出栏数据填报前端技术方案.md

@@ -1,133 +1,11 @@
1 1
 # 牦牛出栏数据填报 — 前端技术方案
2 2
 
3
-> 依据:同目录 `牦牛出栏数据填报功能需求.md`、`牦牛出栏数据填报技术方案.md`;布局对齐 `dataModel/yakHerdInventory/index.vue`(双 `el-card` + 分页表格);字段 **小驼峰**。
4
-
5
----
6
-
7
-## 1. 页面与路由
8
-
9 3
 | 项 | 说明 |
10 4
 | --- | --- |
11
-| **Vue 路径** | `ruoyi-ui/src/views/dataModel/yakOutboundReport/index.vue` |
12
-| **组件名** | `YakOutboundReport` |
13
-| **菜单配置** | 组件路径:`dataModel/yakOutboundReport/index`(「产业数据模型及服务」目录下) |
14
-| **权限前缀** | `dataModel:yakOutboundReport:list\|query\|add\|edit\|remove\|import\|export` |
15
-
16
----
17
-
18
-## 2. API 模块
19
-
20
-| 项 | 说明 |
21
-| --- | --- |
22
-| **文件** | `ruoyi-ui/src/api/dataModel/yakOutboundReport.js` |
23
-| **Base** | `/dataModel/yakOutboundReport` |
24
-
25
-| 方法 | HTTP | 说明 |
26
-| --- | --- | --- |
27
-| `listYakOutboundReport` | GET | `/list` 分页列表 |
28
-| `getYakOutboundReport` | GET | `/{id}` 详情 |
29
-| `addYakOutboundReport` | POST | `/` 新增 |
30
-| `updateYakOutboundReport` | PUT | `/` 修改 |
31
-| `delYakOutboundReport` | DELETE | `/{ids}` 删除 |
32
-| `listYakOutboundReportYearOptions` | GET | `/yearOptions` 可选年份 |
33
-| `listYakOutboundReportMonthOptions` | GET | `/monthOptions` 可选月份(1~12) |
34
-| `listYakOutboundReportTownOptions` | GET | `/townOptions` 乡镇下拉 |
35
-| `importYakOutboundReport` | POST | `/importData`(`multipart/form-data`:`file` + `statYear` + `statMonth`) |
36
-| `downloadYakOutboundReportTemplate` | GET | `/importTemplate` 空白模板(`responseType: 'blob'`) |
37
-| `exportYakOutboundReport` | GET | `/export?statYear=&statMonth=` 按年月导出(`responseType: 'blob'`) |
38
-
39
-模板下载、按年月导出均使用 **GET** + `responseType: 'blob'`,勿用若依全局 `this.download()`(固定 **POST**)。
40
-
41
----
42
-
43
-## 3. 页面结构
44
-
45
-1. **筛选区**:所属年份、**所属月份**、所属乡镇(均可清空);**搜索**、**重置**、**新增**、**导入**、**导出**。  
46
-2. **列表区**:所属年份、**所属月份**、所属乡镇、农牧户户数、农牧户人数、牦牛出栏数、自食情况(牛);空值展示 `—`。  
47
-3. **操作列**:查看、修改、删除。  
48
-4. **新增/编辑弹窗**:年份、月份、乡镇必填;出栏及自食指标选填,`el-input-number`(`:min="0"` `:precision="0"`);备注选填;**新增时默认当前年月**。表单分四块:基本信息、农牧户情况、出栏情况、自食情况。  
49
-5. **查看弹窗**:只读展示需求 **§5.5** 七字段(年份、**月份**、乡镇、农牧户户数、农牧户人数、牦牛出栏数、自食牛头数);可跳转编辑。  
50
-6. **导入弹窗**:选「填报年份」「填报月份」(**默认当前年月**)→ 上传 `.xlsx` → 展示 insert/update/fail 及 fail/warn 明细。  
51
-7. **导出弹窗**:选「所属年份」「所属月份」(**默认当前年月**)→ `GET /export` 下载 `{年}年{月}月牦牛出栏数据.xlsx`。
52
-
53
----
54
-
55
-## 4. 业务规则(前端)
56
-
57
-| 规则 | 实现 |
58
-| --- | --- |
59
-| 年份范围 | 由 `/yearOptions` 动态加载(当前年起向前 5 年,共 6 年) |
60
-| 月份范围 | 页面 `monthOptions` 固定 1~12;展示 `{month}月`(i18n `statMonthLabel`) |
61
-| 乡镇下拉 | `/townOptions` 返回 `deptId` / `deptName` |
62
-| 列表筛选 | `statYear`、`statMonth`、`townDeptId` 精确匹配;**进入页面不默认年月** |
63
-| 重置 | 清空年份、月份、乡镇后重新查询 |
64
-| 数量字段 | 选填;填写时须为 ≥ 0 的整数 |
65
-| 单位后缀 | 户、人、头、只、匹(见 i18n `unit*`) |
66
-| 唯一性 | 同年同月同乡镇重复新增由后端拦截,前端展示 `msg` |
67
-| 导入 | `FormData` 含 `statYear`、`statMonth`;全局 loading;成功后 `$alert` 展示摘要与明细 |
68
-| 导出 | 弹框选年月;年月须在合法范围内 |
69
-| 删除 | `$modal.confirm` 后 `delYakOutboundReport(id)`,物理删除 |
70
-
71
----
72
-
73
-## 5. 字段映射(表单 / 接口 Body)
74
-
75
-| 前端 prop | 说明 | 单位 |
76
-| --- | --- | --- |
77
-| `statYear` | 所属年份 | — |
78
-| `statMonth` | 所属月份(1~12) | — |
79
-| `townDeptId` | 所属乡镇 | — |
80
-| `farmerHouseholdCount` | 农牧户户数 | 户 |
81
-| `farmerPopulationCount` | 农牧户人数 | 人 |
82
-| `yakOutboundCount` | 牦牛出栏数 | 头 |
83
-| `cattleOutboundCount` | 黄牛/奶牛/犏牛出栏数 | 头 |
84
-| `sheepOutboundCount` | 绵羊出栏数 | 只 |
85
-| `goatOutboundCount` | 山羊出栏数 | 只 |
86
-| `horseMuleOutboundCount` | 马骡出栏数 | 匹 |
87
-| `donkeyOutboundCount` | 驴出栏数 | 头 |
88
-| `selfConsumptionCattleCount` | 自食牛头数 | 头 |
89
-| `selfConsumptionSheepCount` | 自食绵羊只数 | 只 |
90
-| `selfConsumptionGoatCount` | 自食山羊只数 | 只 |
91
-| `remark` | 备注 | — |
92
-
93
----
94
-
95
-## 6. 国际化
96
-
97
-| 项 | 说明 |
98
-| --- | --- |
99
-| **语言包** | `dataModel.yakOutboundReport`、`dataModel.common` |
100
-| **文件** | `lang/zh/dataModel.js`、`lang/bo/dataModel.js` |
101
-| **Mixin** | `dataModelLocaleMixin`,`dmNs = 'yakOutboundReport'`,`dmT` / `dmCommon` |
102
-| **注册** | 已随 `dataModel` 模块在 `lang/zh-CN.js`、`lang/bo.js` 引入 |
103
-| **月份文案** | `queryStatMonth`、`colStatMonth`、`formStatMonth`、`importStatMonth`、`exportStatMonth`、`statMonthLabel` 等 |
104
-
105
----
106
-
107
-## 7. 联调说明
108
-
109
-1. 部署后端 `BizYakOutboundReportController` 及 `biz_yak_outbound_report` 表(含 `stat_month`)。  
110
-2. 已有库自 v1.1 按年表升级时执行迁移 SQL(历史 `stat_month` 默认 **12**)。  
111
-3. 菜单组件 `dataModel/yakOutboundReport/index`,权限与后端 §5 一致。  
112
-4. 验证:年月/乡镇筛选、CRUD、导入模板下载、导入结果反馈、按年月导出、双语切换。  
113
-5. 导入联调:选填报年月 → 上传 `牲畜数据.xlsx` 第 6 Sheet 格式文件;对照 `failMessages` / `warnMessages`。
114
-
115
----
116
-
117
-## 8. 文件清单
118
-
119
-| 类型 | 路径 |
120
-| --- | --- |
121 5
 | 页面 | `ruoyi-ui/src/views/dataModel/yakOutboundReport/index.vue` |
122 6
 | API | `ruoyi-ui/src/api/dataModel/yakOutboundReport.js` |
123
-| Mixin | `ruoyi-ui/src/mixins/dataModelLocaleMixin.js` |
124
-| i18n | `ruoyi-ui/src/lang/zh/dataModel.js`、`lang/bo/dataModel.js` |
125
-
126
----
7
+| 村树 | Treeselect + `/villageTree`;表单只选村 |
8
+| 列表 | 乡镇、村列;筛选含村 |
9
+| 导入摘要 | 新增条数(全量覆盖无更新计数) |
127 10
 
128
-## 9. 修订记录
129
-
130
-| 版本 | 说明 |
131
-| --- | --- |
132
-| 1.0 | 初版:列表/CRUD/详情/导入/模板下载/按年导出;汉藏 i18n;对齐功能需求 v1.1 |
133
-| 1.1 | 按年月填报:列表月份列与筛选;导入/导出/新增默认当前年月;列表不默认年月;`/monthOptions`;导出文件名含月份 |
11
+修订:v2.0 对齐村粒度与全量覆盖导入。

+ 23 - 275
doc/产业数据模型及服务/牦牛出栏数据填报/牦牛出栏数据填报功能需求.md

@@ -5,11 +5,9 @@
5 5
 | 项 | 说明 |
6 6
 | --- | --- |
7 7
 | 模块名称 | 牦牛出栏数据填报 |
8
-| 目标 | 按**乡镇 × 所属年月**填报、导入、维护县域农牧户牲畜**出栏及自食**统计数据,**每月导入一次**当月出栏;支撑养殖产业监管报表及历史对比 |
9
-| 关联系统 | 业务后台(增删改查、Excel 导入/导出);组织机构 `sys_dept`(乡镇字典) |
10
-| 修订依据 | 业务模板 `牲畜数据.xlsx` 第 **6** 个 Sheet(如「2026年度农牧户牲畜出栏及自食情况统计表」,附表 5);用户填报诉求 |
11
-
12
-本文档仅描述**功能需求与业务规则**,不涉及库表字段命名、接口路径、技术栈选型及实现细节(见同目录技术方案)。
8
+| 目标 | 按**村 × 所属年月**填报、导入、维护农牧户牲畜出栏及自食情况;**每月导入一次**当月快照 |
9
+| 关联系统 | 业务后台;`sys_dept`(乡镇、村) |
10
+| 修订依据 | 交接表 `牦牛出栏数据填报.xlsx`;运行模板 `yak_outbound_report_import_template.xlsx` |
13 11
 
14 12
 ---
15 13
 
@@ -17,290 +15,41 @@
17 15
 
18 16
 ### 2.1 填报粒度
19 17
 
20
-- 一条记录表示:**某一自然年、某一自然月、某一乡镇**的牲畜出栏及自食汇总数据(**不按村居拆行**)。  
21
-- 同一「所属年份 + 所属月份 + 所属乡镇」在系统中**仅允许一条记录**(物理删除后可重新填报)。  
22
-- **填报频率**:每个自然月导入/维护一次当月出栏快照;同月重复导入为**覆盖更新**。
23
-
24
-### 2.2 所属年份
25
-
26
-| 规则 | 说明 |
27
-| --- | --- |
28
-| 可选范围 | **当前自然年**起向前共 **6 个自然年**(含当年),即「当年、前 1 年 … 前 5 年」 |
29
-| 示例 | 若统计日为 2026 年,可选:2026、2025、2024、2023、2022、2021 |
30
-| 展示 | 列表、表单、导入、导出时均以**四位年份**展示与存储 |
31
-
32
-### 2.2.1 所属月份
33
-
34
-| 规则 | 说明 |
35
-| --- | --- |
36
-| 取值范围 | **1~12**(自然月) |
37
-| 填报限制 | **不可填报未来月份**(相对服务器当前年月) |
38
-| 展示 | 列表、表单、导入、导出均以「**N 月**」展示 |
39
-| 历史数据 | 升级前按年填报的数据,迁移时默认 `stat_month = 12` |
40
-
41
-### 2.3 所属乡镇
42
-
43
-| 规则 | 说明 |
44
-| --- | --- |
45
-| 数据来源 | `sys_dept` 组织树**二级节点** |
46
-| 纳入条件 | `parent_id` 为县级根节点(与现有数据一致时为 `100`),且 `order_num > 12`,且 `del_flag = '0'`、`status = '0'` |
47
-| 展示名 | 使用 `sys_dept.dept_name`(如「巴青乡」「杂色镇」等) |
48
-| 必填 | 新增、修改、导入时**必须**能解析到有效乡镇 |
18
+- 一条记录:**某一自然年、某一自然月、某一行政村**的出栏及自食汇总。  
19
+- 保存时由所选村反推所属乡镇。  
20
+- 唯一键:所属年份 + 所属月份 + 所属村。  
21
+- 同月重复导入为**该年月全量覆盖**(先删后插)。
49 22
 
50
-本期乡镇名单与 `sql/sys_dept_import_town.sql` 一致(10 个乡镇/镇)。
23
+### 2.2~2.4 年月 / 乡镇 / 村
51 24
 
52
-### 2.4 出栏及自食指标含义
25
+与存栏模块一致:年份向前 6 年、月份 1~12 不可未来月;乡镇为 `sys_dept` 二级合法节点;村为三级叶子;表单只选村。
53 26
 
54
-各数量字段均为**非负整数**,允许为空(未填报);若填写则 **≥ 0**。
27
+### 2.5 指标
55 28
 
56
-| 业务字段 | 单位 | 说明 |
57
-| --- | --- | --- |
58
-| 农牧户户数 | 户 | 纳入统计的农牧户数量 |
59
-| 农牧户人数 | 人 | 纳入统计的农牧户人口数 |
60
-| 牦牛出栏数 | 头 | 当月牦牛出栏合计 |
61
-| 黄牛/奶牛/犏牛出栏数 | 头 | 黄牛、奶牛、犏牛出栏合计 |
62
-| 绵羊出栏数 | 只 | 绵羊出栏合计 |
63
-| 山羊出栏数 | 只 | 山羊出栏合计 |
64
-| 马骡出栏数 | 匹 | 马、骡出栏合计 |
65
-| 驴出栏数 | 头 | 驴出栏合计 |
66
-| 自食牛头数 | 头 | 其中自食情况 — 牛 |
67
-| 自食绵羊只数 | 只 | 其中自食情况 — 绵羊 |
68
-| 自食山羊只数 | 只 | 其中自食情况 — 山羊 |
29
+**录入**:农牧户户数/人数;牦牛、黄牛/奶牛/犏牛、绵羊、山羊、马骡、驴出栏;自食牛/绵羊/山羊。  
69 30
 
70
-**说明**:模板中「出栏小计(头只匹)」「自食小计」为汇总列,**不入库**;系统可按需在前端或导出时计算展示,不作为持久化字段。
31
+**导出计算(不入库)**:出栏合计 = 六类出栏之和;自食合计 = 三类自食之和。  
71 32
 
72
-**交叉校验(建议,非阻断)**:自食牛/绵羊/山羊之和宜不超过对应出栏数;不一致时允许保存,导入结果可提示警告。
33
+自食大于对应出栏时允许保存,导入可返回警告。
73 34
 
74 35
 ---
75 36
 
76
-## 3. 功能范围
77
-
78
-**本期实现:**
37
+## 3~5. 功能要点
79 38
 
80 39
 | 能力 | 说明 |
81 40
 | --- | --- |
82
-| 分页列表 | 按所属年份、**所属月份**、所属乡镇筛选;见 **§5.1** |
83
-| 新增 | 手工填报一条乡镇**年月**数据;见 **§5.2** |
84
-| 修改 | 编辑已有记录;见 **§5.3** |
85
-| 删除 | **物理删除**;见 **§5.4** |
86
-| 详情 | 查看指定展示字段;见 **§5.5** |
87
-| Excel 导入 | 按模板批量导入**指定填报年月**下所有乡镇出栏数据;见 **§5.6** |
88
-| Excel 导出 | 按**指定所属年月**导出巴青县**全部乡镇**出栏数据;见 **§5.7** |
89
-| 乡镇下拉 | 从 `sys_dept` 动态加载合法乡镇;见 **§5.2** |
90
-| 年份下拉 | 当前年起向前 5 年;见 **§2.2** |
91
-| 月份下拉 | 1~12;见 **§2.2.1** |
92
-
93
-**本期不实现:**
94
-
95
-- 按村居维度的多行填报、审批流、版本对比  
96
-- 逻辑删除
97
-
98
----
99
-
100
-## 4. 业务流程
101
-
102
-```mermaid
103
-flowchart TD
104
-    A[选择所属年月] --> B{录入方式}
105
-    B -->|手工| C[选择乡镇并填写指标]
106
-    B -->|导入| D[上传 Excel 模板]
107
-    B -->|导出| X[下载全县乡镇 Excel]
108
-    C --> E[保存]
109
-    D --> F[解析并匹配乡镇]
110
-    F --> G{同年同月同乡镇是否存在}
111
-    G -->|否| H[新增]
112
-    G -->|是| I[更新覆盖]
113
-    E --> J[列表查询/详情]
114
-    H --> J
115
-    I --> J
116
-    X --> J
117
-```
118
-
119
----
120
-
121
-## 5. 详细功能需求
122
-
123
-### 5.1 列表查询
124
-
125
-**筛选**
126
-
127
-| 条件 | 规则 |
128
-| --- | --- |
129
-| 所属年份 | 选填;**精确**匹配;下拉范围为 **§2.2** |
130
-| 所属月份 | 选填;**精确**匹配(1~12);**列表进入时不默认选中** |
131
-| 所属乡镇 | 选填;**精确**匹配 `dept_id` |
132
-
133
-**列表规则**
134
-
135
-- 默认每页 **20** 条;排序:**所属年份倒序**、**所属月份倒序**,同年内同月按乡镇 `order_num` 升序。  
136
-- 支持**重置**筛选(年份、月份、乡镇均清空)。
137
-
138
-**列表展示列**
139
-
140
-| 列名 | 说明 |
141
-| --- | --- |
142
-| 所属年份 | 自然年 |
143
-| 所属月份 | 展示为「N 月」 |
144
-| 所属乡镇 | `town_name` |
145
-| 农牧户户数 | 户 |
146
-| 农牧户人数 | 人 |
147
-| 牦牛出栏数 | 头 |
148
-| 自食情况(牛) | 自食牛头数(头) |
149
-| 操作 | 查看、修改、删除 |
150
-
151
----
152
-
153
-### 5.2 新增
154
-
155
-| 项 | 要求 |
156
-| --- | --- |
157
-| 必填 | **所属年份**、**所属月份**、**所属乡镇** |
158
-| 选填 | 农牧户户数、农牧户人数、各出栏数、各自食数、备注 |
159
-| 乡镇 | 下拉仅含 **§2.3** 合法乡镇 |
160
-| 默认值 | 打开新增弹窗时,所属年份、所属月份**默认当前年月**(可改) |
161
-| 唯一性 | 同年同月同乡镇已存在记录时**禁止新增**,提示「该年该月该乡镇已填报」 |
162
-| 数字 | 选填项若填写须为非负整数 |
163
-
164
----
165
-
166
-### 5.3 修改
167
-
168
-| 项 | 要求 |
169
-| --- | --- |
170
-| 可改字段 | 除主键外均可改;**所属年份、所属月份、所属乡镇**修改后仍须满足唯一性 |
171
-| 必填 | 所属年份、所属月份、所属乡镇保持必填 |
172
-| 表单 | 展示 **§2.4** 全部可填指标(含黄牛/犏牛、绵羊、山羊、马骡、驴及自食绵羊/山羊等列表未展示字段) |
173
-
174
----
175
-
176
-### 5.4 删除
177
-
178
-| 项 | 要求 |
179
-| --- | --- |
180
-| 方式 | **物理删除**(记录从库中移除,**不做逻辑删除**) |
181
-| 确认 | 删除前二次确认 |
182
-| 效果 | 同年同月同乡镇可重新新增或导入 |
183
-
184
----
185
-
186
-### 5.5 详情
187
-
188
-| 项 | 要求 |
189
-| --- | --- |
190
-| 入口 | 列表「查看」 |
191
-| 展示字段 | **所属年份**、**所属月份**、**所属乡镇**、**农牧户户数**、**农牧户人数**、**牦牛出栏数**、**自食情况(牛)**(即自食牛头数) |
192
-| 模式 | 只读 |
193
-
194
-> 列表未展示的出栏分项(黄牛/犏牛、绵羊、山羊等)通过「修改」入口维护;若业务需要详情页展示全部指标,可在实施阶段扩展,**本期以用户指定 7 项为准**(含月份)。
195
-
196
----
197
-
198
-### 5.6 Excel 导入
199
-
200
-| 项 | 要求 |
201
-| --- | --- |
202
-| 模板来源 | `牲畜数据.xlsx` 第 **6** 个 Sheet(年度出栏及自食统计表,如「那曲市巴青县2026年度农牧户牲畜出栏及自食情况统计表」) |
203
-| 填报年月 | 导入前用户**必须选择**「填报年份」「填报月份」(月份 **§2.2.1**);Sheet 标题中年份与所选年份不一致时,**以用户所选填报年份为准**写入 `stat_year`;文件中**不写月份**时以所选为准 |
204
-| 解析范围 | 从数据区首行(乡镇列有值且为合法乡镇名)起,至「合计」行或乡镇为空的行结束;**跳过**标题、表头、填表单位等说明行 |
205
-| 乡镇匹配 | Excel「乡镇」列与 `sys_dept.dept_name` **精确匹配**(trim 后);模板中若为「扎色镇」,宜按 **§8** 同义映射为「杂色镇」 |
206
-| 唯一键 | **所属年份 + 所属月份 + 所属乡镇(`town_dept_id`)** |
207
-| 合并策略 | 按「年月 + 乡镇」**upsert**:已存在 → 全量覆盖更新;不存在 → 新增 |
208
-| 重复导入 | **允许**对同一文件在同一填报年月多次导入;第二次及以后 `updateCount` 增加、`insertCount` 为 0(乡镇均有数据时) |
209
-| 结果反馈 | 返回 `insertCount`、`updateCount`、失败条数及失败明细(行号、乡镇、原因) |
210
-| 文件限制 | `.xlsx`;大小上限与项目统一上传限制一致 |
211
-
212
-**模板列映射(第 6 个 Sheet,0-based 列号以实施对照模板冻结)**
213
-
214
-| 列号 | Excel 列 | 表头(约) | 映射字段 |
215
-| --- | --- | --- | --- |
216
-| 1 | B | 乡镇 | 所属乡镇 |
217
-| 2 | C | 户数 | 农牧户户数 |
218
-| 3 | D | 人数 | 农牧户人数 |
219
-| 4 | E | 牦牛(头) | 牦牛出栏数 |
220
-| 5 | F | 黄牛、奶牛、犏牛(头) | 黄牛/奶牛/犏牛出栏数 |
221
-| 6 | G | 绵羊(只) | 绵羊出栏数 |
222
-| 7 | H | 山羊(只) | 山羊出栏数 |
223
-| 8 | I | 马骡(匹) | 马骡出栏数 |
224
-| 9 | J | 驴(头) | 驴出栏数 |
225
-| 10 | K | 小计(头只匹) | **忽略**(汇总列) |
226
-| 11 | L | 牛(头) | 自食牛头数 |
227
-| 12 | M | 绵羊(只) | 自食绵羊只数 |
228
-| 13 | N | 山羊(只) | 自食山羊只数 |
229
-| 14 | O | 自食小计 | **忽略**(汇总列) |
230
-| 15 | P | 备注 | `remark` |
231
-
232
-数据区起始行:表头含「乡镇」「户数」「牦牛(头)」的下一行(模板存在合并单元格,实施时按代码常量定位,参考 **§8**)。
233
-
234
----
235
-
236
-### 5.7 Excel 导出
237
-
238
-| 项 | 要求 |
239
-| --- | --- |
240
-| 入口 | 列表页「导出」 |
241
-| 导出年月 | 用户**必须选择**「所属年份」「所属月份」(范围见 **§2.2**、**§2.2.1**);弹窗打开时**默认当前年月** |
242
-| 导出范围 | **巴青县全部乡镇**(**§2.3** 合法乡镇,按 `order_num` 排序),**不受**列表「所属乡镇」筛选限制 |
243
-| 模板 | 与导入共用:`baqing-admin/src/main/resources/templates/yak_outbound_report_import_template.xlsx`(业务源文件 `牲畜数据.xlsx` 第 6 Sheet) |
244
-| 填充规则 | 表头标题、表头「年牲畜出栏数」区块及 Sheet 页签中的年份均替换为所选年份;每个乡镇一行;有该**年月**填报数据的乡镇填入全部指标;未填报乡镇仅保留乡镇名称,指标为空 |
245
-| 合计行 | 数据区末行输出「合计」,对**已填报乡镇**的数值列求和;出栏小计(K 列)、自食小计(O 列)由分项加总后写入 |
246
-| 文件格式 | `.xlsx`;文件名示例:`2026年7月牦牛出栏数据.xlsx` |
247
-| 与导入关系 | 导出文件列结构与导入模板一致,可再次导入(同年月将 upsert) |
248
-
249
-**与「下载模板」区别**:「下载模板」为空白模板;「导出」为按库内**指定年月**数据填充后的全县报表。
250
-
251
----
252
-
253
-## 6. 权限矩阵
254
-
255
-| 操作 | 建议权限 |
256
-| --- | --- |
257
-| 列表查询 | `dataModel:yakOutboundReport:list` |
258
-| 详情 | `dataModel:yakOutboundReport:query` |
259
-| 新增 | `dataModel:yakOutboundReport:add` |
260
-| 修改 | `dataModel:yakOutboundReport:edit` |
261
-| 删除 | `dataModel:yakOutboundReport:remove` |
262
-| 导入 | `dataModel:yakOutboundReport:import` |
263
-| 导出 | `dataModel:yakOutboundReport:export` |
264
-
265
-数据权限:县级管理员可见全县;乡镇账号仅可见本乡镇数据(若启用部门数据权限,按 `town_dept_id` 与登录用户 `dept_id` 过滤)。
41
+| 列表 | 筛年/月/乡镇/村;列含乡镇、村、户数、人数、牦牛出栏、自食牛 |
42
+| 新增/修改 | 年、月、村必填;乡镇反推;唯一「年+月+村」 |
43
+| 导入 | 选填报年月;解析乡镇+村;失败则不写库;成功则全量覆盖 |
44
+| 导出 | 导出该月已填报村行;合计合并序号+乡镇+村;自户数起按列求和;填表时间为导出当日年月 |
266 45
 
267
----
268
-
269
-## 7. 提示与错误约定
270
-
271
-- 必填项未填、年份/月份/乡镇不合法、同年同月同乡镇重复新增、**未来月份**  
272
-- 导入:文件格式错误、乡镇无法匹配、数字非整数、行为空  
273
-- 导出:未选年月、年月不在可选范围  
274
-- 删除成功/失败、导入部分失败(展示明细)  
275
-
276
-采用项目统一 `AjaxResult` 文案风格。
277
-
278
----
279
-
280
-## 8. 非功能需求(建议)
281
-
282
-| 类别 | 建议 |
283
-| --- | --- |
284
-| 性能 | 列表分页;导入单次 ≤ 20 行(10 乡镇 + 合计行跳过) |
285
-| 审计 | 记录创建人、创建时间、更新人、更新时间 |
286
-| 模板差异 | 业务源文件 `牲畜数据.xlsx` 第 6 Sheet 乡镇「扎色镇」与 `sys_dept`「杂色镇」同义,导入宜做别名映射 |
287
-| 扩展 | 与「养殖产业数据」看板联动(**大屏/看板口径暂仍按年汇总,见技术方案**) |
46
+Excel 列:序号、乡镇、村、户数、人数、六类出栏、出栏合计、三类自食、自食合计。
288 47
 
289 48
 ---
290 49
 
291
-## 9. 需求追溯
50
+## 6. 权限
292 51
 
293
-| 能力 | 章节 |
294
-| --- | --- |
295
-| 表字段与必填 | §2、§5.2 |
296
-| 年份向前 5 年 | §2.2 |
297
-| 月份 1~12、不可填未来月 | §2.2.1 |
298
-| 乡镇 sys_dept | §2.3 |
299
-| 增删改查 | §5.1~5.5 |
300
-| 物理删除 | §5.4 |
301
-| Excel 导入第 6 Sheet | §5.6 |
302
-| Excel 按年月导出 | §5.7 |
303
-| 列表/详情字段 | §5.1、§5.5 |
52
+`dataModel:yakOutboundReport:list|query|add|edit|remove|import|export`
304 53
 
305 54
 ---
306 55
 
@@ -308,6 +57,5 @@ flowchart TD
308 57
 
309 58
 | 版本 | 说明 |
310 59
 | --- | --- |
311
-| 1.0 | 初稿:出栏及自食指标、乡镇年度填报、Excel 导入、物理删除 |
312
-| 1.1 | 增加 **§5.7 按年份导出** 全县乡镇 Excel;权限 `export` |
313
-| 1.2 | **按年月填报**:增加 `stat_month`;唯一键「年+月+乡镇」;每月导入一次;列表/导入/导出支持月份;列表进入不默认年月;新增/导入/导出默认当前年月 |
60
+| 1.0~1.x | 乡镇粒度、按年月、upsert 等历史版本 |
61
+| 2.0 | 按村填报;列含村;导入全量覆盖;导出合计按列求和;对齐交接模板 |

+ 26 - 272
doc/产业数据模型及服务/牦牛出栏数据填报/牦牛出栏数据填报技术方案.md

@@ -1,294 +1,48 @@
1 1
 # 牦牛出栏数据填报 — 技术方案
2 2
 
3
-> 依据:同目录 `牦牛出栏数据填报功能需求.md`;模板 `E:\luhao\工作交接\巴青项目\农牧数据\农业农村和科技水利局-业务办\牲畜数据.xlsx` 第 **6** 个 Sheet(2026 年度出栏及自食统计表)
3
+> 依据:同目录功能需求;模板 `baqing-admin/src/main/resources/templates/yak_outbound_report_import_template.xlsx`
4 4
 
5
----
5
+## 1. 架构
6 6
 
7
-## 1. 技术架构
7
+Controller `/dataModel/yakOutboundReport` → Service → Mapper;Excel:`YakOutboundReportExcelParser` / `YakOutboundReportExcelExporter`;校验:`YakOutboundReportValidation`(村反推乡镇)。
8 8
 
9
-| 项 | 说明 |
10
-| --- | --- |
11
-| **后端** | RuoYi **v3.9.2**(springboot2):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
12
-| **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` |
13
-| **前端** | 若依 Vue2 + Element UI |
14
-| **Excel** | Apache POI(与「牦牛存栏数据填报」一致) |
15
-| **组织** | `sys_dept` 乡镇字典;复用 `TownDeptSupport` |
16
-
17
-**分层**:`BizYakOutboundReportController` → `IBizYakOutboundReportService` → `BizYakOutboundReportMapper` → `domain`;Excel 由 `YakOutboundReportExcelParser`(导入解析)、`YakOutboundReportExcelExporter`(按年月导出)承担。
18
-
19
-**代码位置**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`(与产业数据模型同包)。
20
-
21
-**模板文件**:`baqing-admin/src/main/resources/templates/yak_outbound_report_import_template.xlsx`(导入、导出、下载模板共用)。
22
-
23
-**参考实现**:`BizYakHerdInventory*`、`YakHerdInventoryMonthSupport`、`TownDeptSupport`(存栏填报模块,年月模式一致)。
24
-
25
----
26
-
27
-## 2. 数据库设计
28
-
29
-### 2.1 表 `biz_yak_outbound_report`(牦牛出栏数据填报)
30
-
31
-| 字段 | 类型 | 非空 | 说明 |
32
-| --- | --- | --- | --- |
33
-| `id` | `bigint(20)` | Y | 主键 |
34
-| `stat_year` | `int(11)` | Y | 所属年份(自然年) |
35
-| `stat_month` | `int(11)` | Y | 所属月份(1~12) |
36
-| `town_dept_id` | `bigint(20)` | Y | 所属乡镇,`sys_dept.dept_id` |
37
-| `town_name` | `varchar(64)` | Y | 乡镇名称冗余 |
38
-| `farmer_household_count` | `int(11)` | N | 农牧户户数 |
39
-| `farmer_population_count` | `int(11)` | N | 农牧户人数 |
40
-| `yak_outbound_count` | `int(11)` | N | 牦牛出栏数(头) |
41
-| `cattle_outbound_count` | `int(11)` | N | 黄牛/奶牛/犏牛出栏数(头) |
42
-| `sheep_outbound_count` | `int(11)` | N | 绵羊出栏数(只) |
43
-| `goat_outbound_count` | `int(11)` | N | 山羊出栏数(只) |
44
-| `horse_mule_outbound_count` | `int(11)` | N | 马骡出栏数(匹) |
45
-| `donkey_outbound_count` | `int(11)` | N | 驴出栏数(头) |
46
-| `self_consumption_cattle_count` | `int(11)` | N | 自食牛头数(头) |
47
-| `self_consumption_sheep_count` | `int(11)` | N | 自食绵羊只数(只) |
48
-| `self_consumption_goat_count` | `int(11)` | N | 自食山羊只数(只) |
49
-| `create_by` / `create_time` | — | — | 审计 |
50
-| `update_by` / `update_time` | — | — | 审计 |
51
-| `remark` | `varchar(500)` | N | 备注 |
52
-
53
-**说明**:本表**不使用逻辑删除**,无 `del_flag`;删除为物理 `DELETE`。
54
-
55
-**索引与约束**
56
-
57
-- `UNIQUE uk_year_month_town (stat_year, stat_month, town_dept_id)` — 年月+乡镇唯一,支撑导入 upsert。  
58
-- `KEY idx_stat_year_month (stat_year, stat_month)`  
59
-- `KEY idx_town_dept_id (town_dept_id)`
60
-
61
-**DDL 文件**:`sql/biz_yak_outbound_report.sql`(新库,已含 `stat_month`)。  
62
-**已有库升级**(v1.1 按年表 `uk_year_town`):增加 `stat_month` 列(历史行默认 **12**),调整唯一键为 `uk_year_month_town`(实施阶段提供迁移 SQL,模式同存栏模块)。
63
-
64
-### 2.2 乡镇字典(复用)
65
-
66
-```sql
67
-SELECT dept_id, dept_name, order_num
68
-FROM sys_dept
69
-WHERE parent_id = 100
70
-  AND order_num > 12
71
-  AND del_flag = '0'
72
-  AND status = '0'
73
-ORDER BY order_num;
74
-```
75
-
76
-封装:`TownDeptSupport.listReportTowns()`、`requireReportTown(deptId)`。
77
-
78
-**乡镇别名(导入)**:模板「扎色镇」→ `sys_dept`「杂色镇」,在 `YakOutboundReportExcelParser.resolveTownDeptId` 或 `TownDeptSupport` 扩展 `normalizeTownName`。
9
+## 2. 表 `biz_yak_outbound_report`
79 10
 
80
-### 2.3 可选年份
11
+唯一键 `uk_year_month_village (stat_year, stat_month, village_dept_id)`;含 `town_*`、`village_*` 及出栏/自食明细字段。DDL:`sql/biz_yak_outbound_report.sql`(`DROP` 全量重建)。
81 12
 
82
-与存栏模块一致:复用 `YakHerdInventoryYearSupport.resolveYearOptions()`,返回当前年起向前 5 年共 6 个年份。
13
+## 3. 接口
83 14
 
84
-### 2.4 可选月份
85
-
86
-复用 `YakHerdInventoryMonthSupport.resolveMonthOptions()` 返回 **1~12**;`validateStatPeriod(year, month)` 校验年份在 **§2.3** 范围内、月份合法且**非未来月**。出栏校验类 `YakOutboundReportValidation` 亦调用该 Support。
87
-
88
----
89
-
90
-## 3. 接口设计
91
-
92
-**Base Path**:`/dataModel/yakOutboundReport`
93
-
94
-**权限前缀**:`dataModel:yakOutboundReport`
95
-
96
-| # | 说明 | Method | URI | 权限 |
97
-| --- | --- | --- | --- | --- |
98
-| 3.1 | 分页列表 | GET | `/list` | `list` |
99
-| 3.2 | 详情 | GET | `/{id}` | `query` |
100
-| 3.3 | 新增 | POST | `/` | `add` |
101
-| 3.4 | 修改 | PUT | `/` | `edit` |
102
-| 3.5 | 删除 | DELETE | `/{ids}` | `remove` |
103
-| 3.6 | 乡镇下拉 | GET | `/townOptions` | `list` |
104
-| 3.7 | 年份下拉 | GET | `/yearOptions` | `list` |
105
-| 3.8 | 月份下拉 | GET | `/monthOptions` | `list` |
106
-| 3.9 | 导入 | POST | `/importData` | `import` |
107
-| 3.10 | 下载导入模板 | GET | `/importTemplate` | `import` |
108
-| 3.11 | 按年月导出 | GET | `/export` | `export` |
109
-
110
-#### 3.1.1 列表 Query
111
-
112
-| 参数 | 类型 | 说明 |
113
-| --- | --- | --- |
114
-| `pageNum` / `pageSize` | int | 默认 1 / 20 |
115
-| `statYear` | int | 所属年份,精确 |
116
-| `statMonth` | int | 所属月份(1~12),精确 |
117
-| `townDeptId` | long | 所属乡镇 dept_id,精确 |
118
-
119
-**列表 VO**
120
-
121
-| 列标题 | 字段 |
15
+| URI | 说明 |
122 16
 | --- | --- |
123
-| 所属年份 | `statYear` |
124
-| 所属月份 | `statMonth` |
125
-| 所属乡镇 | `townName` |
126
-| 农牧户户数 | `farmerHouseholdCount` |
127
-| 农牧户人数 | `farmerPopulationCount` |
128
-| 牦牛出栏数 | `yakOutboundCount` |
129
-| 自食情况(牛) | `selfConsumptionCattleCount` |
130
-
131
-#### 3.2.1 详情
132
-
133
-返回需求 **§5.5** 指定字段(驼峰):
134
-
135
-`statYear`、`statMonth`、`townName`、`farmerHouseholdCount`、`farmerPopulationCount`、`yakOutboundCount`、`selfConsumptionCattleCount`
136
-
137
-可选附带 `id`、`townDeptId` 供前端跳转修改。
138
-
139
-#### 3.3.1 新增/修改 Body
140
-
141
-| 字段 | 必填 | 校验 |
142
-| --- | --- | --- |
143
-| `statYear` | Y | 在 `yearOptions` 范围内 |
144
-| `statMonth` | Y | 1~12;非未来月 |
145
-| `townDeptId` | Y | 须在乡镇字典内 |
146
-| `farmerHouseholdCount` 等数量字段 | N | `>= 0` 整数 |
147
-| `id` | 修改必填 | — |
148
-
149
-**唯一性(手工新增)**:`countByYearMonthAndTownExcludeId > 0` 则拒绝,提示「该年该月该乡镇已填报」。**导入**走 upsert。
17
+| CRUD `/list` `/{id}` POST/PUT/DELETE | 同常规 |
18
+| `/villageTree` | 县→乡镇→村 |
19
+| `/importData` | 年月全量覆盖 |
20
+| `/export` | 按年月导出已填报村数据 |
150 21
 
151
-#### 3.5.1 删除
22
+### Excel 列(0-based)
152 23
 
153
-`DELETE FROM biz_yak_outbound_report WHERE id IN (...)`,物理删除。
154
-
155
-#### 3.9 导入
156
-
157
-**请求**:`multipart/form-data`
158
-
159
-| 参数 | 必填 | 说明 |
160
-| --- | --- | --- |
161
-| `file` | Y | `.xlsx` |
162
-| `statYear` | Y | 填报年份 |
163
-| `statMonth` | Y | 填报月份(1~12) |
164
-
165
-**Upsert**(`BizYakOutboundReportServiceImpl.upsertImportRow`):
166
-
167
-1. `selectByYearMonthAndTown(statYear, statMonth, townDeptId)`  
168
-2. 无记录 → `insert`;有记录 → `update` 全字段覆盖  
169
-
170
-同一文件对**同一填报年月**多次导入:各乡镇行均为更新,不产生重复有效记录。
171
-
172
-**响应 `data`**:`insertCount`、`updateCount`、`failCount`、`failMessages`、`warnMessages`(自食大于出栏等)
173
-
174
-#### 3.9.1 Excel 第 6 Sheet 解析约定
175
-
176
-| 项 | 约定 |
24
+| 列 | 字段 |
177 25
 | --- | --- |
178
-| Sheet | `workbook.getSheetAt(5)`(第 6 个 Sheet,0-based 索引 5) |
179
-| 表头识别 | 扫描含「乡镇」且同行含「户数」「牦牛」的行;数据自 `headerRow + 1` 起 |
180
-| 终止行 | 乡镇为空,或乡镇名为「合计」 |
181
-| 列映射(0-based) | |
182
-
183
-| 列号 | 实体字段 |
184
-| --- | --- |
185
-| 1 | 乡镇 → `townDeptId` / `townName` |
186
-| 2 | `farmerHouseholdCount` |
187
-| 3 | `farmerPopulationCount` |
188
-| 4 | `yakOutboundCount` |
189
-| 5 | `cattleOutboundCount` |
190
-| 6 | `sheepOutboundCount` |
191
-| 7 | `goatOutboundCount` |
192
-| 8 | `horseMuleOutboundCount` |
193
-| 9 | `donkeyOutboundCount` |
194
-| 10 | **跳过**(出栏小计) |
195
-| 11 | `selfConsumptionCattleCount` |
196
-| 12 | `selfConsumptionSheepCount` |
197
-| 13 | `selfConsumptionGoatCount` |
198
-| 14 | **跳过**(自食小计) |
199
-| 15 | `remark` |
200
-
201
-> 模板存在合并单元格,部分行 POI 读列可能错位;解析器宜按表头行固定列号读取,并对空单元格按 0 或 null 处理(与存栏导入一致)。
202
-
203
-**导入事务**:逐乡镇独立处理,单乡镇失败不影响其余。
204
-
205
-#### 3.11 按年月导出
206
-
207
-**请求**:`GET /export?statYear=2026&statMonth=7`
208
-
209
-| 参数 | 必填 | 说明 |
210
-| --- | --- | --- |
211
-| `statYear` | Y | 导出年份,须在 `yearOptions` 范围内 |
212
-| `statMonth` | Y | 导出月份(1~12);须通过 `validateStatPeriod` |
213
-
214
-**响应**:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` 文件流;文件名 `{statYear}年{statMonth}月牦牛出栏数据.xlsx`。
215
-
216
-**实现**:`BizYakOutboundReportServiceImpl.exportByYearMonth` → `YakOutboundReportExcelExporter.export`:
217
-
218
-1. 加载 classpath 模板 `YakOutboundReportExcelExporter.TEMPLATE_CLASSPATH`  
219
-2. 解析出栏 Sheet(`YakOutboundReportExcelParser.resolveSheet`)  
220
-3. 替换表头中的四位年份为 `statYear`(含标题行与「年牲畜出栏数」表头区块;年份与「年」之间允许空格)  
221
-4. 将 Sheet 名称更新为 `{年份后两位}年出栏`(如 2024 → `24年出栏`)  
222
-5. 查询 `stat_year = statYear AND stat_month = statMonth` 的全部记录,按 `town_dept_id` 建 Map  
223
-6. 遍历 `TownDeptSupport.listReportTowns()`,逐乡镇写行;无数据则仅写乡镇名  
224
-7. 末行写「合计」,对已填报乡镇数值列求和;K/O 列写入出栏/自食小计  
225
-
226
-**与 3.10 区别**:`/importTemplate` 返回空白模板;`/export` 返回填充后的全县报表。
227
-
228
----
229
-
230
-## 4. 前端设计(要点)
231
-
232
-| 项 | 说明 |
233
-| --- | --- |
234
-| **路径** | `ruoyi-ui/src/views/dataModel/yakOutboundReport/index.vue` |
235
-| **API** | `ruoyi-ui/src/api/dataModel/yakOutboundReport.js` |
236
-| **列表** | 年份、**月份**、乡镇筛选;**进入页面不默认年月**;列:所属年份、**所属月份**、所属乡镇、农牧户户数、农牧户人数、牦牛出栏数、自食情况(牛) |
237
-| **详情** | 对话框只读,展示 **§5.5** 七字段(含月份) |
238
-| **表单** | 新增/修改展示全部数量字段;年份/月份/乡镇下拉;**新增默认当前年月**;`el-input-number` `:min="0"` `:precision="0"` |
239
-| **导入** | 先选「填报年份」「填报月份」(**默认当前年月**)→ 上传 → 展示导入结果摘要 |
240
-| **模板下载** | `GET /importTemplate`;空白模板 |
241
-| **导出** | 弹窗选年月(**默认当前年月**)→ `GET /export?statYear=&statMonth=` |
242
-
243
----
244
-
245
-## 5. 菜单与权限(示例)
246
-
247
-| 类型 | 名称 | 权限标识 |
248
-| --- | --- | --- |
249
-| 菜单 | 牦牛出栏数据填报 | `dataModel:yakOutboundReport:list` |
250
-| 按钮 | 查询 | `dataModel:yakOutboundReport:query` |
251
-| 按钮 | 新增 | `dataModel:yakOutboundReport:add` |
252
-| 按钮 | 修改 | `dataModel:yakOutboundReport:edit` |
253
-| 按钮 | 删除 | `dataModel:yakOutboundReport:remove` |
254
-| 按钮 | 导入 | `dataModel:yakOutboundReport:import` |
255
-| 按钮 | 导出 | `dataModel:yakOutboundReport:export` |
256
-
257
-挂载目录:**产业数据模型及服务**。菜单 SQL:`sql/biz_sys_menu_yak_outbound_report.sql`(实施阶段)。
258
-
259
----
260
-
261
-## 6. 与存栏填报模块的关系
262
-
263
-| 模块 | 表 | 模板 Sheet | 业务含义 |
264
-| --- | --- | --- | --- |
265
-| 牦牛存栏数据填报 | `biz_yak_herd_inventory` | `牲畜数据.xlsx` 第 1 Sheet(畜群结构) | 月末存栏结构 |
266
-| 牦牛出栏数据填报 | `biz_yak_outbound_report` | `牲畜数据.xlsx` 第 6 Sheet | 月度出栏及自食 |
267
-
268
-两模块共用 `TownDeptSupport`、年份范围规则、`YakHerdInventoryMonthSupport` 年月校验、导入 upsert 模式;**本期不实现**跨表校验(如出栏数不大于存栏数)。
269
-
270
-### 6.1 与大屏 / 养殖看板(暂不改)
26
+| 1~2 | 乡镇、村 |
27
+| 3~4 | 户数、人数 |
28
+| 5~10 | 六类出栏 |
29
+| 11 | 出栏合计(导出算) |
30
+| 12~14 | 自食牛/绵羊/山羊 |
31
+| 15 | 自食合计(导出算) |
271 32
 
272
-产业总览中「牦牛出栏数」「农牧户户数」等字段当前仍通过 `HomeScreenStatsMapper.sumOutboundReport*ByStatYear` **仅按 `stat_year` 汇总**,不按月份过滤。同一年存在多个月份填报时可能重复累加;**后续单独设计看板口径**,本模块按年月维护明细
33
+数据起始行:`headerRow + 1`(表头为含「乡镇」「村」「户数」「牦牛」的行)。
273 34
 
274
----
35
+## 4. 导入 / 导出
275 36
 
276
-## 7. 交付清单
37
+- 导入:校验全部成功 → `deleteByYearMonth` → 批量 insert。  
38
+- 导出:写村行 + 行内小计;合计行合并 0~2 列;自户数起求和;标题年/月与填表人/填表时间更新。
277 39
 
278
-- [x] `sql/biz_yak_outbound_report.sql`(含 `stat_month`)  
279
-- [x] `BizYakOutboundReport` Domain / Mapper / XML / Service / Controller  
280
-- [x] `YakOutboundReportExcelParser` + `YakOutboundReportExcelExporter` + 导入模板 xlsx(第 6 Sheet)  
281
-- [x] 复用 `TownDeptSupport`、`YakHerdInventoryYearSupport`、`YakHerdInventoryMonthSupport`  
282
-- [ ] 前端列表/表单/导入/导出(年月 UI,对齐存栏模块)  
283
-- [x] 单元测试 + 接口测试  
284
-- [ ] `sql/biz_sys_menu_yak_outbound_report.sql`  
40
+## 5. 大屏
285 41
 
286
----
42
+地图乡镇标注对 `biz_yak_outbound_report` / `biz_yak_herd_inventory` 按 `town_dept_id` **聚合 sum** 后再关联。
287 43
 
288 44
 ## 8. 修订记录
289 45
 
290 46
 | 版本 | 说明 |
291 47
 | --- | --- |
292
-| 1.0 | 初稿:表结构、CRUD、第 6 Sheet 导入、物理删除、乡镇字典 |
293
-| 1.1 | 实现按年份导出全县乡镇 Excel;`YakOutboundReportExcelExporter` |
294
-| 1.2 | 按年月填报:`stat_month`;`uk_year_month_town`;`/monthOptions`;导入/导出/CRUD 支持月份;复用 `YakHerdInventoryMonthSupport` |
48
+| 2.0 | 村粒度全量覆盖;列映射对齐交接模板;大屏按乡镇聚合 |

+ 8 - 3
sql/biz_yak_outbound_report.sql

@@ -1,10 +1,13 @@
1
-CREATE TABLE IF NOT EXISTS `biz_yak_outbound_report` (
1
+-- 牦牛出栏数据填报(物理删除,无 del_flag;全量覆盖建表,与最新 Excel 模板按村填报一致)
2
+DROP TABLE IF EXISTS `biz_yak_outbound_report`;
3
+CREATE TABLE `biz_yak_outbound_report` (
2 4
   `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
3 5
   `stat_year` int(11) NOT NULL COMMENT '所属年份',
4 6
   `stat_month` int(11) NOT NULL COMMENT '所属月份(1-12)',
5 7
   `town_dept_id` bigint(20) NOT NULL COMMENT '所属乡镇dept_id',
6 8
   `town_name` varchar(64) NOT NULL COMMENT '乡镇名称',
9
+  `village_dept_id` bigint(20) NOT NULL COMMENT '所属村dept_id',
10
+  `village_name` varchar(128) NOT NULL COMMENT '所属村名称',
7 11
   `farmer_household_count` int(11) DEFAULT NULL COMMENT '农牧户户数',
8 12
   `farmer_population_count` int(11) DEFAULT NULL COMMENT '农牧户人数',
9 13
   `yak_outbound_count` int(11) DEFAULT NULL COMMENT '牦牛出栏数(头)',
@@ -22,7 +25,8 @@ CREATE TABLE IF NOT EXISTS `biz_yak_outbound_report` (
22 25
   `update_time` datetime DEFAULT NULL COMMENT '更新时间',
23 26
   `remark` varchar(500) DEFAULT NULL COMMENT '备注',
24 27
   PRIMARY KEY (`id`),
25
-  UNIQUE KEY `uk_year_month_town` (`stat_year`, `stat_month`, `town_dept_id`),
28
+  UNIQUE KEY `uk_year_month_village` (`stat_year`, `stat_month`, `village_dept_id`),
26 29
   KEY `idx_stat_year_month` (`stat_year`, `stat_month`),
27
-  KEY `idx_town_dept_id` (`town_dept_id`)
30
+  KEY `idx_town_dept_id` (`town_dept_id`),
31
+  KEY `idx_village_dept_id` (`village_dept_id`)
28 32
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='牦牛出栏数据填报';