|
|
@@ -14,13 +14,13 @@
|
|
14
|
14
|
| **Excel** | Apache POI(与「牦牛存栏数据填报」一致) |
|
|
15
|
15
|
| **组织** | `sys_dept` 乡镇字典;复用 `TownDeptSupport` |
|
|
16
|
16
|
|
|
17
|
|
-**分层**:`BizYakOutboundReportController` → `IBizYakOutboundReportService` → `BizYakOutboundReportMapper` → `domain`;Excel 由 `YakOutboundReportExcelParser`(导入解析)、`YakOutboundReportExcelExporter`(按年导出)承担。
|
|
|
17
|
+**分层**:`BizYakOutboundReportController` → `IBizYakOutboundReportService` → `BizYakOutboundReportMapper` → `domain`;Excel 由 `YakOutboundReportExcelParser`(导入解析)、`YakOutboundReportExcelExporter`(按年月导出)承担。
|
|
18
|
18
|
|
|
19
|
19
|
**代码位置**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`(与产业数据模型同包)。
|
|
20
|
20
|
|
|
21
|
21
|
**模板文件**:`baqing-admin/src/main/resources/templates/yak_outbound_report_import_template.xlsx`(导入、导出、下载模板共用)。
|
|
22
|
22
|
|
|
23
|
|
-**参考实现**:`BizYakHerdInventory*`、`YakHerdInventoryExcelParser`、`TownDeptSupport`(存栏填报模块,模式一致)。
|
|
|
23
|
+**参考实现**:`BizYakHerdInventory*`、`YakHerdInventoryMonthSupport`、`TownDeptSupport`(存栏填报模块,年月模式一致)。
|
|
24
|
24
|
|
|
25
|
25
|
---
|
|
26
|
26
|
|
|
|
@@ -32,6 +32,7 @@
|
|
32
|
32
|
| --- | --- | --- | --- |
|
|
33
|
33
|
| `id` | `bigint(20)` | Y | 主键 |
|
|
34
|
34
|
| `stat_year` | `int(11)` | Y | 所属年份(自然年) |
|
|
|
35
|
+| `stat_month` | `int(11)` | Y | 所属月份(1~12) |
|
|
35
|
36
|
| `town_dept_id` | `bigint(20)` | Y | 所属乡镇,`sys_dept.dept_id` |
|
|
36
|
37
|
| `town_name` | `varchar(64)` | Y | 乡镇名称冗余 |
|
|
37
|
38
|
| `farmer_household_count` | `int(11)` | N | 农牧户户数 |
|
|
|
@@ -53,11 +54,12 @@
|
|
53
|
54
|
|
|
54
|
55
|
**索引与约束**
|
|
55
|
56
|
|
|
56
|
|
-- `UNIQUE uk_year_town (stat_year, town_dept_id)` — 年份+乡镇唯一,支撑导入 upsert。
|
|
57
|
|
-- `KEY idx_stat_year (stat_year)`
|
|
|
57
|
+- `UNIQUE uk_year_month_town (stat_year, stat_month, town_dept_id)` — 年月+乡镇唯一,支撑导入 upsert。
|
|
|
58
|
+- `KEY idx_stat_year_month (stat_year, stat_month)`
|
|
58
|
59
|
- `KEY idx_town_dept_id (town_dept_id)`
|
|
59
|
60
|
|
|
60
|
|
-**DDL 文件**:`sql/biz_yak_outbound_report.sql`
|
|
|
61
|
+**DDL 文件**:`sql/biz_yak_outbound_report.sql`(新库,已含 `stat_month`)。
|
|
|
62
|
+**已有库升级**(v1.1 按年表 `uk_year_town`):增加 `stat_month` 列(历史行默认 **12**),调整唯一键为 `uk_year_month_town`(实施阶段提供迁移 SQL,模式同存栏模块)。
|
|
61
|
63
|
|
|
62
|
64
|
### 2.2 乡镇字典(复用)
|
|
63
|
65
|
|
|
|
@@ -77,7 +79,11 @@ ORDER BY order_num;
|
|
77
|
79
|
|
|
78
|
80
|
### 2.3 可选年份
|
|
79
|
81
|
|
|
80
|
|
-与存栏模块一致:`YakOutboundReportYearSupport` 或复用 `YakHerdInventoryYearSupport` 逻辑,返回当前年起向前 5 年共 6 个年份。
|
|
|
82
|
+与存栏模块一致:复用 `YakHerdInventoryYearSupport.resolveYearOptions()`,返回当前年起向前 5 年共 6 个年份。
|
|
|
83
|
+
|
|
|
84
|
+### 2.4 可选月份
|
|
|
85
|
+
|
|
|
86
|
+复用 `YakHerdInventoryMonthSupport.resolveMonthOptions()` 返回 **1~12**;`validateStatPeriod(year, month)` 校验年份在 **§2.3** 范围内、月份合法且**非未来月**。出栏校验类 `YakOutboundReportValidation` 亦调用该 Support。
|
|
81
|
87
|
|
|
82
|
88
|
---
|
|
83
|
89
|
|
|
|
@@ -96,9 +102,10 @@ ORDER BY order_num;
|
|
96
|
102
|
| 3.5 | 删除 | DELETE | `/{ids}` | `remove` |
|
|
97
|
103
|
| 3.6 | 乡镇下拉 | GET | `/townOptions` | `list` |
|
|
98
|
104
|
| 3.7 | 年份下拉 | GET | `/yearOptions` | `list` |
|
|
99
|
|
-| 3.8 | 导入 | POST | `/importData` | `import` |
|
|
100
|
|
-| 3.9 | 下载导入模板 | GET | `/importTemplate` | `import` |
|
|
101
|
|
-| 3.10 | 按年份导出 | GET | `/export` | `export` |
|
|
|
105
|
+| 3.8 | 月份下拉 | GET | `/monthOptions` | `list` |
|
|
|
106
|
+| 3.9 | 导入 | POST | `/importData` | `import` |
|
|
|
107
|
+| 3.10 | 下载导入模板 | GET | `/importTemplate` | `import` |
|
|
|
108
|
+| 3.11 | 按年月导出 | GET | `/export` | `export` |
|
|
102
|
109
|
|
|
103
|
110
|
#### 3.1.1 列表 Query
|
|
104
|
111
|
|
|
|
@@ -106,6 +113,7 @@ ORDER BY order_num;
|
|
106
|
113
|
| --- | --- | --- |
|
|
107
|
114
|
| `pageNum` / `pageSize` | int | 默认 1 / 20 |
|
|
108
|
115
|
| `statYear` | int | 所属年份,精确 |
|
|
|
116
|
+| `statMonth` | int | 所属月份(1~12),精确 |
|
|
109
|
117
|
| `townDeptId` | long | 所属乡镇 dept_id,精确 |
|
|
110
|
118
|
|
|
111
|
119
|
**列表 VO**
|
|
|
@@ -113,6 +121,7 @@ ORDER BY order_num;
|
|
113
|
121
|
| 列标题 | 字段 |
|
|
114
|
122
|
| --- | --- |
|
|
115
|
123
|
| 所属年份 | `statYear` |
|
|
|
124
|
+| 所属月份 | `statMonth` |
|
|
116
|
125
|
| 所属乡镇 | `townName` |
|
|
117
|
126
|
| 农牧户户数 | `farmerHouseholdCount` |
|
|
118
|
127
|
| 农牧户人数 | `farmerPopulationCount` |
|
|
|
@@ -123,7 +132,7 @@ ORDER BY order_num;
|
|
123
|
132
|
|
|
124
|
133
|
返回需求 **§5.5** 指定字段(驼峰):
|
|
125
|
134
|
|
|
126
|
|
-`statYear`、`townName`、`farmerHouseholdCount`、`farmerPopulationCount`、`yakOutboundCount`、`selfConsumptionCattleCount`
|
|
|
135
|
+`statYear`、`statMonth`、`townName`、`farmerHouseholdCount`、`farmerPopulationCount`、`yakOutboundCount`、`selfConsumptionCattleCount`
|
|
127
|
136
|
|
|
128
|
137
|
可选附带 `id`、`townDeptId` 供前端跳转修改。
|
|
129
|
138
|
|
|
|
@@ -132,17 +141,18 @@ ORDER BY order_num;
|
|
132
|
141
|
| 字段 | 必填 | 校验 |
|
|
133
|
142
|
| --- | --- | --- |
|
|
134
|
143
|
| `statYear` | Y | 在 `yearOptions` 范围内 |
|
|
|
144
|
+| `statMonth` | Y | 1~12;非未来月 |
|
|
135
|
145
|
| `townDeptId` | Y | 须在乡镇字典内 |
|
|
136
|
146
|
| `farmerHouseholdCount` 等数量字段 | N | `>= 0` 整数 |
|
|
137
|
147
|
| `id` | 修改必填 | — |
|
|
138
|
148
|
|
|
139
|
|
-**唯一性(手工新增)**:`countByYearAndTownExcludeId > 0` 则拒绝。**导入**走 upsert。
|
|
|
149
|
+**唯一性(手工新增)**:`countByYearMonthAndTownExcludeId > 0` 则拒绝,提示「该年该月该乡镇已填报」。**导入**走 upsert。
|
|
140
|
150
|
|
|
141
|
151
|
#### 3.5.1 删除
|
|
142
|
152
|
|
|
143
|
153
|
`DELETE FROM biz_yak_outbound_report WHERE id IN (...)`,物理删除。
|
|
144
|
154
|
|
|
145
|
|
-#### 3.8 导入
|
|
|
155
|
+#### 3.9 导入
|
|
146
|
156
|
|
|
147
|
157
|
**请求**:`multipart/form-data`
|
|
148
|
158
|
|
|
|
@@ -150,15 +160,18 @@ ORDER BY order_num;
|
|
150
|
160
|
| --- | --- | --- |
|
|
151
|
161
|
| `file` | Y | `.xlsx` |
|
|
152
|
162
|
| `statYear` | Y | 填报年份 |
|
|
|
163
|
+| `statMonth` | Y | 填报月份(1~12) |
|
|
153
|
164
|
|
|
154
|
165
|
**Upsert**(`BizYakOutboundReportServiceImpl.upsertImportRow`):
|
|
155
|
166
|
|
|
156
|
|
-1. `selectByYearAndTown(statYear, townDeptId)`
|
|
|
167
|
+1. `selectByYearMonthAndTown(statYear, statMonth, townDeptId)`
|
|
157
|
168
|
2. 无记录 → `insert`;有记录 → `update` 全字段覆盖
|
|
158
|
169
|
|
|
|
170
|
+同一文件对**同一填报年月**多次导入:各乡镇行均为更新,不产生重复有效记录。
|
|
|
171
|
+
|
|
159
|
172
|
**响应 `data`**:`insertCount`、`updateCount`、`failCount`、`failMessages`、`warnMessages`(自食大于出栏等)
|
|
160
|
173
|
|
|
161
|
|
-#### 3.8.1 Excel 第 6 Sheet 解析约定
|
|
|
174
|
+#### 3.9.1 Excel 第 6 Sheet 解析约定
|
|
162
|
175
|
|
|
163
|
176
|
| 项 | 约定 |
|
|
164
|
177
|
| --- | --- |
|
|
|
@@ -189,27 +202,28 @@ ORDER BY order_num;
|
|
189
|
202
|
|
|
190
|
203
|
**导入事务**:逐乡镇独立处理,单乡镇失败不影响其余。
|
|
191
|
204
|
|
|
192
|
|
-#### 3.10 按年份导出
|
|
|
205
|
+#### 3.11 按年月导出
|
|
193
|
206
|
|
|
194
|
|
-**请求**:`GET /export?statYear=2026`
|
|
|
207
|
+**请求**:`GET /export?statYear=2026&statMonth=7`
|
|
195
|
208
|
|
|
196
|
209
|
| 参数 | 必填 | 说明 |
|
|
197
|
210
|
| --- | --- | --- |
|
|
198
|
211
|
| `statYear` | Y | 导出年份,须在 `yearOptions` 范围内 |
|
|
|
212
|
+| `statMonth` | Y | 导出月份(1~12);须通过 `validateStatPeriod` |
|
|
199
|
213
|
|
|
200
|
|
-**响应**:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` 文件流;文件名 `{statYear}年牦牛出栏数据.xlsx`。
|
|
|
214
|
+**响应**:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` 文件流;文件名 `{statYear}年{statMonth}月牦牛出栏数据.xlsx`。
|
|
201
|
215
|
|
|
202
|
|
-**实现**:`BizYakOutboundReportServiceImpl.exportByYear` → `YakOutboundReportExcelExporter.export`:
|
|
|
216
|
+**实现**:`BizYakOutboundReportServiceImpl.exportByYearMonth` → `YakOutboundReportExcelExporter.export`:
|
|
203
|
217
|
|
|
204
|
218
|
1. 加载 classpath 模板 `YakOutboundReportExcelExporter.TEMPLATE_CLASSPATH`
|
|
205
|
219
|
2. 解析出栏 Sheet(`YakOutboundReportExcelParser.resolveSheet`)
|
|
206
|
220
|
3. 替换表头中的四位年份为 `statYear`(含标题行与「年牲畜出栏数」表头区块;年份与「年」之间允许空格)
|
|
207
|
221
|
4. 将 Sheet 名称更新为 `{年份后两位}年出栏`(如 2024 → `24年出栏`)
|
|
208
|
|
-5. 查询 `stat_year = statYear` 的全部记录,按 `town_dept_id` 建 Map
|
|
|
222
|
+5. 查询 `stat_year = statYear AND stat_month = statMonth` 的全部记录,按 `town_dept_id` 建 Map
|
|
209
|
223
|
6. 遍历 `TownDeptSupport.listReportTowns()`,逐乡镇写行;无数据则仅写乡镇名
|
|
210
|
224
|
7. 末行写「合计」,对已填报乡镇数值列求和;K/O 列写入出栏/自食小计
|
|
211
|
225
|
|
|
212
|
|
-**与 3.9 区别**:`/importTemplate` 返回空白模板;`/export` 返回填充后的全县报表。
|
|
|
226
|
+**与 3.10 区别**:`/importTemplate` 返回空白模板;`/export` 返回填充后的全县报表。
|
|
213
|
227
|
|
|
214
|
228
|
---
|
|
215
|
229
|
|
|
|
@@ -219,12 +233,12 @@ ORDER BY order_num;
|
|
219
|
233
|
| --- | --- |
|
|
220
|
234
|
| **路径** | `ruoyi-ui/src/views/dataModel/yakOutboundReport/index.vue` |
|
|
221
|
235
|
| **API** | `ruoyi-ui/src/api/dataModel/yakOutboundReport.js` |
|
|
222
|
|
-| **列表** | 年份、乡镇筛选;列:所属年份、所属乡镇、农牧户户数、农牧户人数、牦牛出栏数、自食情况(牛) |
|
|
223
|
|
-| **详情** | 对话框只读,展示 **§5.5** 六字段 |
|
|
224
|
|
-| **表单** | 新增/修改展示全部数量字段;年份/乡镇下拉;`el-input-number` `:min="0"` `:precision="0"` |
|
|
225
|
|
-| **导入** | 先选「填报年份」→ 上传 → 展示导入结果摘要 |
|
|
|
236
|
+| **列表** | 年份、**月份**、乡镇筛选;**进入页面不默认年月**;列:所属年份、**所属月份**、所属乡镇、农牧户户数、农牧户人数、牦牛出栏数、自食情况(牛) |
|
|
|
237
|
+| **详情** | 对话框只读,展示 **§5.5** 七字段(含月份) |
|
|
|
238
|
+| **表单** | 新增/修改展示全部数量字段;年份/月份/乡镇下拉;**新增默认当前年月**;`el-input-number` `:min="0"` `:precision="0"` |
|
|
|
239
|
+| **导入** | 先选「填报年份」「填报月份」(**默认当前年月**)→ 上传 → 展示导入结果摘要 |
|
|
226
|
240
|
| **模板下载** | `GET /importTemplate`;空白模板 |
|
|
227
|
|
-| **按年份导出** | 列表先选「所属年份」→ `GET /export`;`download('dataModel/yakOutboundReport/export', { statYear })` |
|
|
|
241
|
+| **导出** | 弹窗选年月(**默认当前年月**)→ `GET /export?statYear=&statMonth=` |
|
|
228
|
242
|
|
|
229
|
243
|
---
|
|
230
|
244
|
|
|
|
@@ -248,20 +262,24 @@ ORDER BY order_num;
|
|
248
|
262
|
|
|
249
|
263
|
| 模块 | 表 | 模板 Sheet | 业务含义 |
|
|
250
|
264
|
| --- | --- | --- | --- |
|
|
251
|
|
-| 牦牛存栏数据填报 | `biz_yak_herd_inventory` | `牲畜数据.xlsx` 第 1 Sheet(畜群结构) | 年末存栏结构 |
|
|
252
|
|
-| 牦牛出栏数据填报 | `biz_yak_outbound_report` | `牲畜数据.xlsx` 第 6 Sheet | 年度出栏及自食 |
|
|
|
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 与大屏 / 养殖看板(暂不改)
|
|
253
|
271
|
|
|
254
|
|
-两模块共用 `TownDeptSupport`、年份范围规则、导入 upsert 模式;**本期不实现**跨表校验(如出栏数不大于存栏数)。
|
|
|
272
|
+产业总览中「牦牛出栏数」「农牧户户数」等字段当前仍通过 `HomeScreenStatsMapper.sumOutboundReport*ByStatYear` **仅按 `stat_year` 汇总**,不按月份过滤。同一年存在多个月份填报时可能重复累加;**后续单独设计看板口径**,本模块按年月维护明细。
|
|
255
|
273
|
|
|
256
|
274
|
---
|
|
257
|
275
|
|
|
258
|
276
|
## 7. 交付清单
|
|
259
|
277
|
|
|
260
|
|
-- [x] `sql/biz_yak_outbound_report.sql`
|
|
|
278
|
+- [x] `sql/biz_yak_outbound_report.sql`(含 `stat_month`)
|
|
261
|
279
|
- [x] `BizYakOutboundReport` Domain / Mapper / XML / Service / Controller
|
|
262
|
280
|
- [x] `YakOutboundReportExcelParser` + `YakOutboundReportExcelExporter` + 导入模板 xlsx(第 6 Sheet)
|
|
263
|
|
-- [x] 复用 `TownDeptSupport`、年份 Support
|
|
264
|
|
-- [ ] 前端列表/表单/导入/导出
|
|
|
281
|
+- [x] 复用 `TownDeptSupport`、`YakHerdInventoryYearSupport`、`YakHerdInventoryMonthSupport`
|
|
|
282
|
+- [ ] 前端列表/表单/导入/导出(年月 UI,对齐存栏模块)
|
|
265
|
283
|
- [x] 单元测试 + 接口测试
|
|
266
|
284
|
- [ ] `sql/biz_sys_menu_yak_outbound_report.sql`
|
|
267
|
285
|
|
|
|
@@ -273,3 +291,4 @@ ORDER BY order_num;
|
|
273
|
291
|
| --- | --- |
|
|
274
|
292
|
| 1.0 | 初稿:表结构、CRUD、第 6 Sheet 导入、物理删除、乡镇字典 |
|
|
275
|
293
|
| 1.1 | 实现按年份导出全县乡镇 Excel;`YakOutboundReportExcelExporter` |
|
|
|
294
|
+| 1.2 | 按年月填报:`stat_month`;`uk_year_month_town`;`/monthOptions`;导入/导出/CRUD 支持月份;复用 `YakHerdInventoryMonthSupport` |
|