|
|
@@ -1,6 +1,6 @@
|
|
1
|
1
|
# 牦牛存栏数据填报 — 技术方案
|
|
2
|
2
|
|
|
3
|
|
-> 依据:同目录 `牦牛存栏数据填报功能需求.md`;模板 `E:\luhao\工作交接\巴青项目\农牧数据\农业农村和科技水利局-业务办\畜群结构\2026年.xlsx`(第一个 Sheet)。
|
|
|
3
|
+> 依据:同目录 `牦牛存栏数据填报功能需求.md`;模板 `baqing-admin/src/main/resources/templates/yak_herd_inventory_import_template.xlsx`。
|
|
4
|
4
|
|
|
5
|
5
|
---
|
|
6
|
6
|
|
|
|
@@ -10,13 +10,13 @@
|
|
10
|
10
|
| --- | --- |
|
|
11
|
11
|
| **后端** | RuoYi **v3.9.2**(springboot2):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
|
|
12
|
12
|
| **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` |
|
|
13
|
|
-| **前端** | 若依 Vue2 + Element UI |
|
|
14
|
|
-| **Excel** | Apache POI 或项目已有 EasyExcel(与若依导入规范一致) |
|
|
15
|
|
-| **组织** | `sys_dept` 乡镇字典;`SysDeptMapper` 查询二级节点 |
|
|
|
13
|
+| **前端** | 若依 Vue2 + Element UI + `@riophae/vue-treeselect` |
|
|
|
14
|
+| **Excel** | Apache POI |
|
|
|
15
|
+| **组织** | `sys_dept` 乡镇/村字典;`TownDeptSupport` |
|
|
16
|
16
|
|
|
17
|
|
-**分层**:`BizYakHerdInventoryController` → `IBizYakHerdInventoryService` → `BizYakHerdInventoryMapper` → `domain`;Excel 由 `YakHerdInventoryExcelParser`(导入解析)、`YakHerdInventoryExcelExporter`(按年导出)承担。
|
|
|
17
|
+**分层**:`BizYakHerdInventoryController` → `IBizYakHerdInventoryService` → `BizYakHerdInventoryMapper` → `domain`;Excel 由 `YakHerdInventoryExcelParser`(导入)、`YakHerdInventoryExcelExporter`(导出)承担;校验与派生计算由 `YakHerdInventoryValidation`。
|
|
18
|
18
|
|
|
19
|
|
-**代码位置**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`(与产业数据模型同包)。
|
|
|
19
|
+**代码位置**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`。
|
|
20
|
20
|
|
|
21
|
21
|
**模板文件**:`baqing-admin/src/main/resources/templates/yak_herd_inventory_import_template.xlsx`(导入、导出、下载模板共用)。
|
|
22
|
22
|
|
|
|
@@ -29,69 +29,73 @@
|
|
29
|
29
|
| 字段 | 类型 | 非空 | 说明 |
|
|
30
|
30
|
| --- | --- | --- | --- |
|
|
31
|
31
|
| `id` | `bigint(20)` | Y | 主键 |
|
|
32
|
|
-| `stat_year` | `int(11)` | Y | 所属年份(自然年) |
|
|
|
32
|
+| `stat_year` | `int(11)` | Y | 所属年份 |
|
|
33
|
33
|
| `stat_month` | `int(11)` | Y | 所属月份(1~12) |
|
|
34
|
|
-| `town_dept_id` | `bigint(20)` | Y | 所属乡镇,`sys_dept.dept_id` |
|
|
35
|
|
-| `town_name` | `varchar(64)` | Y | 乡镇名称冗余,便于列表展示 |
|
|
36
|
|
-| `village_dept_id` | `bigint(20)` | N | **预留**所属村居,`sys_dept.dept_id`(乡镇下三级节点) |
|
|
37
|
|
-| `village_name` | `varchar(128)` | N | **预留**所属村居名称冗余 |
|
|
|
34
|
+| `town_dept_id` | `bigint(20)` | Y | 所属乡镇,`sys_dept.dept_id`(由村反推) |
|
|
|
35
|
+| `town_name` | `varchar(64)` | Y | 乡镇名称冗余 |
|
|
|
36
|
+| `village_dept_id` | `bigint(20)` | Y | 所属村,`sys_dept.dept_id` |
|
|
|
37
|
+| `village_name` | `varchar(128)` | Y | 村名称冗余 |
|
|
38
|
38
|
| `village_count` | `int(11)` | N | 村居数 |
|
|
39
|
39
|
| `herdsman_household_count` | `int(11)` | N | 牧户数 |
|
|
40
|
|
-| `yak_total` | `int(11)` | N | 牦牛存栏数 |
|
|
41
|
|
-| `bull_total` | `int(11)` | N | 公牛存栏数 |
|
|
42
|
|
-| `cow_total` | `int(11)` | N | 母牛存栏数 |
|
|
43
|
|
-| `breeding_bull_count` | `int(11)` | N | 种公牛存栏数 |
|
|
44
|
|
-| `bull_castrated_count` | `int(11)` | N | 公牛/阉畜存栏数 |
|
|
45
|
|
-| `cow_under_1_count` | `int(11)` | N | 1 岁以下母牛存栏数 |
|
|
46
|
|
-| `cow_1_3_count` | `int(11)` | N | 1~3 岁母牛存栏数 |
|
|
47
|
|
-| `cow_3_12_count` | `int(11)` | N | 3~12 岁母牛存栏数 |
|
|
48
|
|
-| `cow_over_12_count` | `int(11)` | N | 12 岁以上母牛存栏数 |
|
|
|
40
|
+| `breeding_bull_count` | `int(11)` | N | 种公牛 |
|
|
|
41
|
+| `bull_castrated_count` | `int(11)` | N | 公牛/阉畜 |
|
|
|
42
|
+| `bull_total` | `int(11)` | N | 公牛合计(派生) |
|
|
|
43
|
+| `cow_young_count` | `int(11)` | N | 0~1.5 岁幼畜(不含 1.5 岁) |
|
|
|
44
|
+| `cow_adult_count` | `int(11)` | N | 1.5 岁以上成畜(含 1.5 岁) |
|
|
|
45
|
+| `cow_total` | `int(11)` | N | 母牛合计(派生) |
|
|
|
46
|
+| `milking_cow_count` | `int(11)` | N | 产奶母牛 |
|
|
|
47
|
+| `fertile_cow_count` | `int(11)` | N | 能繁母牛 |
|
|
|
48
|
+| `dairy_total` | `int(11)` | N | 奶牛合计(派生) |
|
|
|
49
|
+| `sheep_total` | `int(11)` | N | 羊总数 |
|
|
|
50
|
+| `milking_sheep_count` | `int(11)` | N | 产奶羊 |
|
|
|
51
|
+| `insured_yak_count` | `int(11)` | N | 保险牦牛 |
|
|
|
52
|
+| `yak_total` | `int(11)` | N | 牦牛总存栏(派生) |
|
|
|
53
|
+| `grand_total` | `int(11)` | N | 总合计(派生) |
|
|
|
54
|
+| `yak_sheep_total` | `int(11)` | N | 总量牦牛+羊(派生) |
|
|
49
|
55
|
| `create_by` / `create_time` | — | — | 审计 |
|
|
50
|
56
|
| `update_by` / `update_time` | — | — | 审计 |
|
|
51
|
57
|
| `remark` | `varchar(500)` | N | 备注 |
|
|
52
|
58
|
|
|
53
|
|
-**说明**:本表**不使用逻辑删除**,无 `del_flag` 字段;删除操作为物理删除。
|
|
|
59
|
+**说明**:本表**不使用逻辑删除**;删除为物理删除。旧四档母牛年龄字段(`cow_under_1_count` 等)已废弃,以 `cow_young_count` / `cow_adult_count` 为准。
|
|
54
|
60
|
|
|
55
|
61
|
**索引与约束**
|
|
56
|
62
|
|
|
57
|
|
-- `UNIQUE uk_year_month_town (stat_year, stat_month, town_dept_id)` — 年月+乡镇唯一,支撑导入 upsert。
|
|
|
63
|
+- `UNIQUE uk_year_month_village (stat_year, stat_month, village_dept_id)`
|
|
58
|
64
|
- `KEY idx_stat_year_month (stat_year, stat_month)`
|
|
59
|
|
-- `KEY idx_town_dept_id (town_dept_id)`
|
|
|
65
|
+- `KEY idx_town_dept_id (town_dept_id)`
|
|
|
66
|
+- `KEY idx_village_dept_id (village_dept_id)`
|
|
60
|
67
|
|
|
61
|
|
-**DDL 文件**:`sql/biz_yak_herd_inventory.sql`(新库);已有库执行 `sql/biz_yak_herd_inventory_stat_month.sql`(历史行 `stat_month` 默认 **12**)。
|
|
|
68
|
+**DDL 文件**:`sql/biz_yak_herd_inventory.sql`(全量覆盖建表)。已有库若仍为乡镇唯一键,执行 `sql/biz_yak_herd_inventory_village_uk.sql`(去掉 `uk_year_month_town`,改为村唯一)。
|
|
62
|
69
|
|
|
63
|
|
-### 2.2 乡镇字典查询(`sys_dept`)
|
|
|
70
|
+### 2.2 派生计算(`YakHerdInventoryValidation.recalculateDerived`)
|
|
64
|
71
|
|
|
65
|
|
-```sql
|
|
66
|
|
-SELECT dept_id, dept_name, order_num
|
|
67
|
|
-FROM sys_dept
|
|
68
|
|
-WHERE parent_id = 100
|
|
69
|
|
- AND order_num > 12
|
|
70
|
|
- AND del_flag = '0'
|
|
71
|
|
- AND status = '0'
|
|
72
|
|
-ORDER BY order_num;
|
|
|
72
|
+```text
|
|
|
73
|
+bull_total = breeding_bull_count + bull_castrated_count
|
|
|
74
|
+cow_total = cow_young_count + cow_adult_count
|
|
|
75
|
+dairy_total = milking_cow_count + fertile_cow_count
|
|
|
76
|
+yak_total = bull_total + cow_total + insured_yak_count
|
|
|
77
|
+grand_total = yak_total + dairy_total + sheep_total
|
|
|
78
|
+yak_sheep_total = bull_total + cow_total + insured_yak_count + sheep_total
|
|
73
|
79
|
```
|
|
74
|
80
|
|
|
75
|
|
-前端乡镇下拉、导入匹配均调用封装方法 `TownDeptSupport.listReportTowns()`(名称与根 `parent_id` 可配置化 `ruoyi.town-dept-parent-id=100`、`ruoyi.town-dept-min-order-num=12`)。
|
|
|
81
|
+保存与导入落库前一律重算覆盖。
|
|
76
|
82
|
|
|
77
|
|
-### 2.3 可选年份
|
|
|
83
|
+### 2.3 乡镇 / 村字典
|
|
78
|
84
|
|
|
79
|
|
-```java
|
|
80
|
|
-// 当前年起向前 5 年,共 6 个
|
|
81
|
|
-int current = Year.now().getValue();
|
|
82
|
|
-for (int y = current; y >= current - 5; y--) { ... }
|
|
83
|
|
-```
|
|
|
85
|
+- 乡镇:`TownDeptSupport.listReportTowns()`(`parent_id=100` 且 `order_num>12`)。
|
|
|
86
|
+- 村树:`TownDeptSupport.buildVillageTree()` → 县→乡镇→村;父节点不 `disabled`(便于展开),前端 `disable-branch-nodes` 仅允许选村。
|
|
|
87
|
+- 解析:`resolveTownByName`、`resolveVillageByTownAndName`、`requireReportVillage`。
|
|
84
|
88
|
|
|
85
|
|
-### 2.3 可选月份
|
|
|
89
|
+### 2.4 可选年份 / 月份
|
|
86
|
90
|
|
|
87
|
|
-`YakHerdInventoryMonthSupport.resolveMonthOptions()` 返回 **1~12**;`validateStatPeriod(year, month)` 校验年份在 **§2.2** 范围内、月份合法且**非未来月**。
|
|
|
91
|
+- `YakHerdInventoryYearSupport`:当前年起向前 5 年,共 6 个。
|
|
|
92
|
+- `YakHerdInventoryMonthSupport.resolveMonthOptions()`:1~12;`validateStatPeriod` 拒绝未来月。
|
|
88
|
93
|
|
|
89
|
94
|
---
|
|
90
|
95
|
|
|
91
|
96
|
## 3. 接口设计
|
|
92
|
97
|
|
|
93
|
|
-**Base Path**:`/dataModel/yakHerdInventory`
|
|
94
|
|
-
|
|
|
98
|
+**Base Path**:`/dataModel/yakHerdInventory`
|
|
95
|
99
|
**权限前缀**:`dataModel:yakHerdInventory`
|
|
96
|
100
|
|
|
97
|
101
|
| # | 说明 | Method | URI | 权限 |
|
|
|
@@ -102,6 +106,7 @@ for (int y = current; y >= current - 5; y--) { ... }
|
|
102
|
106
|
| 3.4 | 修改 | PUT | `/` | `edit` |
|
|
103
|
107
|
| 3.5 | 删除 | DELETE | `/{ids}` | `remove` |
|
|
104
|
108
|
| 3.6 | 乡镇下拉 | GET | `/townOptions` | `list` |
|
|
|
109
|
+| 3.6.1 | 村树 | GET | `/villageTree` | `list` |
|
|
105
|
110
|
| 3.7 | 年份下拉 | GET | `/yearOptions` | `list` |
|
|
106
|
111
|
| 3.7.1 | 月份下拉 | GET | `/monthOptions` | `list` |
|
|
107
|
112
|
| 3.8 | 导入 | POST | `/importData` | `import` |
|
|
|
@@ -113,123 +118,71 @@ for (int y = current; y >= current - 5; y--) { ... }
|
|
113
|
118
|
| 参数 | 类型 | 说明 |
|
|
114
|
119
|
| --- | --- | --- |
|
|
115
|
120
|
| `pageNum` / `pageSize` | int | 默认 1 / 20 |
|
|
116
|
|
-| `statYear` | int | 所属年份,精确 |
|
|
117
|
|
-| `statMonth` | int | 所属月份(1~12),精确 |
|
|
118
|
|
-| `townDeptId` | long | 所属乡镇 dept_id,精确 |
|
|
119
|
|
-
|
|
120
|
|
-**列表 VO 字段**(列标题与需求 **§5.1** 一致):
|
|
121
|
|
-
|
|
122
|
|
-| 列标题 | 字段 |
|
|
123
|
|
-| --- | --- |
|
|
124
|
|
-| 所属年份 | `statYear` |
|
|
125
|
|
-| 所属月份 | `statMonth` |
|
|
126
|
|
-| 乡镇 | `townName` |
|
|
127
|
|
-| 村居数 | `villageCount` |
|
|
128
|
|
-| 牧户数 | `herdsmanHouseholdCount` |
|
|
129
|
|
-| 存栏数 | `yakTotal` |
|
|
130
|
|
-| 公牛存栏数 | `bullTotal` |
|
|
131
|
|
-| 母牛存栏数 | `cowTotal` |
|
|
132
|
|
-
|
|
133
|
|
-#### 3.2.1 详情
|
|
|
121
|
+| `statYear` / `statMonth` | int | 精确 |
|
|
|
122
|
+| `townDeptId` | long | 乡镇 |
|
|
|
123
|
+| `villageDeptId` | long | 村 |
|
|
134
|
124
|
|
|
135
|
|
-返回 `BizYakHerdInventory` **全字段**(驼峰),含预留村居、分龄母牛、种公牛、阉畜、备注及 `createBy` / `createTime` / `updateBy` / `updateTime` 等。
|
|
|
125
|
+**列表主要字段**:`statYear`、`statMonth`、`townName`、`villageName`、`villageCount`、`herdsmanHouseholdCount`、`yakTotal`、`bullTotal`、`cowTotal`。
|
|
136
|
126
|
|
|
137
|
127
|
#### 3.3.1 新增/修改 Body
|
|
138
|
128
|
|
|
139
|
129
|
| 字段 | 必填 | 校验 |
|
|
140
|
130
|
| --- | --- | --- |
|
|
141
|
|
-| `statYear` | Y | 在 `yearOptions` 范围内 |
|
|
142
|
|
-| `statMonth` | Y | 1~12;不可为未来月 |
|
|
143
|
|
-| `townDeptId` | Y | 须在乡镇字典内 |
|
|
144
|
|
-| `villageDeptId` | N | **预留**;若填写须为有效 `sys_dept.dept_id`,且 `parent_id = townDeptId`(可选校验) |
|
|
145
|
|
-| `villageName` | N | **预留**村居名称 |
|
|
146
|
|
-| 各 `*Count` | N | `>= 0` 整数 |
|
|
|
131
|
+| `statYear` / `statMonth` | Y | 合法且非未来月 |
|
|
|
132
|
+| `villageDeptId` | Y | 合法村;反推乡镇 |
|
|
|
133
|
+| 明细 `*Count` | N | `>= 0` |
|
|
147
|
134
|
| `id` | 修改必填 | — |
|
|
148
|
135
|
|
|
149
|
|
-**唯一性**:`countByYearMonthAndTownExcludeId(statYear, statMonth, townDeptId, excludeId) > 0` 则拒绝(**手工新增/修改**);**导入**走 upsert,不受此限。
|
|
|
136
|
+**唯一性**:`countByYearMonthAndVillageExcludeId(...) > 0` →「该年该月该村已填报」。
|
|
150
|
137
|
|
|
151
|
138
|
#### 3.8 导入
|
|
152
|
139
|
|
|
153
|
|
-**请求**:`multipart/form-data`
|
|
154
|
|
-
|
|
155
|
|
-| 参数 | 必填 | 说明 |
|
|
156
|
|
-| --- | --- | --- |
|
|
157
|
|
-| `file` | Y | `.xlsx`(如 `牦牛存栏数据.xlsx`) |
|
|
158
|
|
-| `statYear` | Y | 填报年份 |
|
|
159
|
|
-| `statMonth` | Y | 填报月份(1~12) |
|
|
160
|
|
-
|
|
161
|
|
-**Upsert 规则**(`BizYakHerdInventoryServiceImpl.upsertImportRow`):
|
|
162
|
|
-
|
|
163
|
|
-| 步骤 | 说明 |
|
|
164
|
|
-| --- | --- |
|
|
165
|
|
-| 1 | 按 `statYear` + `statMonth` + `townDeptId` 查询 `selectByYearMonthAndTown` |
|
|
166
|
|
-| 2 | 无记录 → `insert`;`insertCount++` |
|
|
167
|
|
-| 3 | 有记录 → `updateBizYakHerdInventory` 全字段覆盖;`updateCount++` |
|
|
168
|
|
-
|
|
169
|
|
-同一文件对**同一填报年月**多次导入:各乡镇行均为更新,不产生重复有效记录。
|
|
|
140
|
+**请求**:`multipart/form-data`:`file` + `statYear` + `statMonth`。
|
|
170
|
141
|
|
|
171
|
|
-**响应 `data`**
|
|
|
142
|
+**策略**(`BizYakHerdInventoryServiceImpl.importData`):
|
|
172
|
143
|
|
|
173
|
|
-| 字段 | 说明 |
|
|
174
|
|
-| --- | --- |
|
|
175
|
|
-| `insertCount` | 新增条数 |
|
|
176
|
|
-| `updateCount` | 更新条数 |
|
|
177
|
|
-| `failCount` | 失败条数 |
|
|
178
|
|
-| `failMessages` | 如 `第8行[杂色镇]: 乡镇未识别` |
|
|
179
|
|
-| `warnMessages` | 分龄加总与母牛合计不一致等警告(可选) |
|
|
|
144
|
+1. 解析全部有效数据行;任一行乡镇/村无法匹配或校验失败 → 整体失败,不写库。
|
|
|
145
|
+2. 全部成功 → `deleteByYearMonth(statYear, statMonth)` → 逐行 `insert`。
|
|
|
146
|
+3. Excel 合计列与重算不一致 → 记入 `warnMessages`(非阻断)。
|
|
180
|
147
|
|
|
181
|
|
-#### 3.8.1 Excel 第一个 Sheet 解析约定(`2026年.xlsx`)
|
|
|
148
|
+**响应**:`insertCount`、`failCount`、`failMessages`、`warnMessages`。
|
|
182
|
149
|
|
|
183
|
|
-| 项 | 约定 |
|
|
184
|
|
-| --- | --- |
|
|
185
|
|
-| Sheet | `workbook.getSheetAt(0)` |
|
|
186
|
|
-| 标题行 | 前若干行为「巴青县…畜群结构…统计表」及填表说明,**自动扫描**首列含「序号」且相邻列含「乡镇」的行作为表头行 `headerRow` |
|
|
187
|
|
-| 数据行 | `headerRow + 1` 起至「乡镇」列为空 |
|
|
188
|
|
-| 列映射(默认,实施对照模板微调) | |
|
|
|
150
|
+#### 3.8.1 Excel 列映射(0-based,`YakHerdInventoryExcelParser`)
|
|
189
|
151
|
|
|
190
|
|
-| 列号(0-based) | Excel 列 | 实体字段 |
|
|
|
152
|
+| 列号 | Excel | 用途 |
|
|
191
|
153
|
| --- | --- | --- |
|
|
192
|
|
-| 1 | B | 乡镇(按 `dept_name` 解析 `townDeptId`) |
|
|
193
|
|
-| 2 | C | `villageCount` |
|
|
194
|
|
-| 3 | D | `herdsmanHouseholdCount` |
|
|
195
|
|
-| 4 | E | `yakTotal`(存栏数) |
|
|
196
|
|
-| 5 | F | 与 E 同值(牦牛公母分类合计) |
|
|
197
|
|
-| 6 | G | `bullTotal`(公牛(头)) |
|
|
198
|
|
-| 7 | H | `cowTotal`(牦牛公母分类 — 母牛(头)) |
|
|
199
|
|
-| 8 | I | 与 G 同值(公牛区块合计) |
|
|
200
|
|
-| 9 | J | `breedingBullCount` |
|
|
201
|
|
-| 10 | K | `bullCastratedCount` |
|
|
202
|
|
-| 11 | L | `cowTotal` |
|
|
203
|
|
-| 12 | M | `cowUnder1Count` |
|
|
204
|
|
-| 13 | N | `cow13Count` |
|
|
205
|
|
-| 14 | O | `cow312Count` |
|
|
206
|
|
-| 15 | P | `cowOver12Count` |
|
|
207
|
|
-| 16 | Q | `remark` |
|
|
208
|
|
-
|
|
209
|
|
-> 数据区起始行:`headerRow + 3`(表头行由「序号」「乡镇」自动识别)。模板存在合并单元格,列号以代码常量为准。
|
|
210
|
|
-
|
|
211
|
|
-**导入事务**:逐乡镇独立处理,单乡镇失败不影响其余。
|
|
|
154
|
+| 1 | B 乡镇 | 匹配乡镇 |
|
|
|
155
|
+| 2 | C 村 | 匹配村 |
|
|
|
156
|
+| 3 | D 村居 | `villageCount` |
|
|
|
157
|
+| 4 | E 牧户 | `herdsmanHouseholdCount` |
|
|
|
158
|
+| 5 | F 总合计 | Excel 对照 |
|
|
|
159
|
+| 6~8 | 牦牛公母分类 | Excel 对照 |
|
|
|
160
|
+| 9 | J 保险 | `insuredYakCount` |
|
|
|
161
|
+| 10 | K 公牛合计 | Excel 对照 |
|
|
|
162
|
+| 11 | L 种公牛 | `breedingBullCount` |
|
|
|
163
|
+| 12 | M 阉畜 | `bullCastratedCount` |
|
|
|
164
|
+| 13 | N 母牛合计 | Excel 对照 |
|
|
|
165
|
+| 14 | O 幼畜 | `cowYoungCount` |
|
|
|
166
|
+| 15 | P 成畜 | `cowAdultCount` |
|
|
|
167
|
+| 16 | Q 奶牛合计 | Excel 对照 |
|
|
|
168
|
+| 17 | R 产奶母牛 | `milkingCowCount` |
|
|
|
169
|
+| 18 | S 能繁母牛 | `fertileCowCount` |
|
|
|
170
|
+| 19 | T 羊 | `sheepTotal` |
|
|
|
171
|
+| 20 | U 产奶羊 | `milkingSheepCount` |
|
|
|
172
|
+| 21 | V 总量 | Excel 对照 |
|
|
|
173
|
+
|
|
|
174
|
+数据起始行:`headerRow + 3`(三行表头)。
|
|
212
|
175
|
|
|
213
|
176
|
#### 3.10 按年月导出
|
|
214
|
177
|
|
|
215
|
|
-**请求**:`GET /export?statYear=2026&statMonth=7`
|
|
216
|
|
-
|
|
217
|
|
-| 参数 | 必填 | 说明 |
|
|
218
|
|
-| --- | --- | --- |
|
|
219
|
|
-| `statYear` | Y | 导出年份,须在 `yearOptions` 范围内 |
|
|
220
|
|
-| `statMonth` | Y | 导出月份(1~12);须通过 `validateStatPeriod` |
|
|
221
|
|
-
|
|
222
|
|
-**响应**:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` 文件流;文件名 `{statYear}年{statMonth}月牦牛存栏数据.xlsx`。
|
|
|
178
|
+**请求**:`GET /export?statYear=&statMonth=`。
|
|
223
|
179
|
|
|
224
|
|
-**实现**:`BizYakHerdInventoryServiceImpl.exportByYearMonth` → `YakHerdInventoryExcelExporter.export`:
|
|
|
180
|
+**实现**:查询该年月全部村记录 → `YakHerdInventoryExcelExporter.export`:
|
|
225
|
181
|
|
|
226
|
|
-1. 加载 classpath 模板 `YakHerdInventoryExcelExporter.TEMPLATE_CLASSPATH`
|
|
227
|
|
-2. 替换表头中的四位年份为 `statYear`
|
|
228
|
|
-3. 查询 `stat_year = statYear AND stat_month = statMonth` 的全部记录,按 `town_dept_id` 建 Map
|
|
229
|
|
-4. 遍历 `TownDeptSupport.listReportTowns()`,逐乡镇写行;无数据则仅写乡镇名
|
|
230
|
|
-5. 末行写「合计」,对已填报乡镇数值列求和
|
|
231
|
|
-
|
|
232
|
|
-**与 3.9 区别**:`/importTemplate` 返回空白模板;`/export` 返回填充后的全县报表。
|
|
|
182
|
+1. 替换标题年、月;填表人;填表时间=**导出当日年月**
|
|
|
183
|
+2. 按记录写数据行(含派生合计)
|
|
|
184
|
+3. 末行「合计」:合并列 0~2;自列 3(村居)起对各数值列求和写入
|
|
|
185
|
+4. 删除合计行之后的空行
|
|
233
|
186
|
|
|
234
|
187
|
---
|
|
235
|
188
|
|
|
|
@@ -239,52 +192,36 @@ for (int y = current; y >= current - 5; y--) { ... }
|
|
239
|
192
|
| --- | --- |
|
|
240
|
193
|
| **路径** | `ruoyi-ui/src/views/dataModel/yakHerdInventory/index.vue` |
|
|
241
|
194
|
| **API** | `ruoyi-ui/src/api/dataModel/yakHerdInventory.js` |
|
|
242
|
|
-| **列表** | 年份、**月份**、乡镇筛选;**进入页面不默认年月**;列:所属年份、所属月份、乡镇、村居数、牧户数、存栏数、公牛/母牛存栏数 |
|
|
243
|
|
-| **详情** | 抽屉/对话框只读展示全部字段 |
|
|
244
|
|
-| **表单** | 抽屉或对话框;年份/月份/乡镇下拉;新增默认**当前年月**;数字 `el-input-number` `:min="0"` `:precision="0"` |
|
|
245
|
|
-| **导入** | 先选「填报年份」「填报月份」(默认当前年月)→ 上传 → 展示导入结果摘要 |
|
|
246
|
|
-| **模板下载** | `GET /importTemplate`;空白模板 |
|
|
247
|
|
-| **导出** | 弹窗选年月(默认当前年月)→ `GET /export?statYear=&statMonth=` |
|
|
|
195
|
+| **列表** | 年/月/乡镇/村筛选;列含乡镇、村、存栏等 |
|
|
|
196
|
+| **表单** | 年/月 + Treeselect 选村;仅明细录入字段;无派生合计输入 |
|
|
|
197
|
+| **详情** | 含派生合计只读 |
|
|
|
198
|
+| **导入/导出** | 先选年月 |
|
|
248
|
199
|
|
|
249
|
200
|
---
|
|
250
|
201
|
|
|
251
|
202
|
## 5. 菜单与权限(示例)
|
|
252
|
203
|
|
|
253
|
|
-| 类型 | 名称 | 权限标识 |
|
|
254
|
|
-| --- | --- | --- |
|
|
255
|
|
-| 菜单 | 牦牛存栏数据填报 | `dataModel:yakHerdInventory:list` |
|
|
256
|
|
-| 按钮 | 查询 | `dataModel:yakHerdInventory:query` |
|
|
257
|
|
-| 按钮 | 新增 | `dataModel:yakHerdInventory:add` |
|
|
258
|
|
-| 按钮 | 修改 | `dataModel:yakHerdInventory:edit` |
|
|
259
|
|
-| 按钮 | 删除 | `dataModel:yakHerdInventory:remove` |
|
|
260
|
|
-| 按钮 | 导入 | `dataModel:yakHerdInventory:import` |
|
|
261
|
|
-| 按钮 | 导出 | `dataModel:yakHerdInventory:export` |
|
|
262
|
|
-
|
|
263
|
|
-挂载目录:**产业数据模型及服务**。菜单 SQL 见 `sql/biz_sys_menu_yak_herd_inventory.sql`。
|
|
|
204
|
+同权限标识:`list|query|add|edit|remove|import|export`。菜单 SQL 见 `sql/biz_sys_menu_yak_herd_inventory.sql`。
|
|
264
|
205
|
|
|
265
|
206
|
---
|
|
266
|
207
|
|
|
267
|
208
|
## 6. 与养殖产业数据看板 / 大屏的关系
|
|
268
|
209
|
|
|
269
|
|
-「养殖产业数据」看板、大屏首页产业总览中的**全县存栏合计**、地图乡镇存栏标注,读取 `biz_yak_herd_inventory` 时:
|
|
270
|
|
-
|
|
271
|
210
|
| 场景 | 口径 |
|
|
272
|
211
|
| --- | --- |
|
|
273
|
|
-| 年度全县合计 | `stat_year = 当前自然年 − 1` 且 **`stat_month = 12`**(`YakHerdInventoryRules.YEAR_END_STAT_MONTH`) |
|
|
274
|
|
-| 地图乡镇存栏 | 同上:`herdStatYear = 当前年 − 1`,`herdStatMonth = 12` |
|
|
275
|
|
-
|
|
276
|
|
-避免同一年多个月份重复累加。月度明细在本模块列表按年月筛选查看。
|
|
|
212
|
+| 全县存栏合计 | `biz_yak_herd_inventory` **最近填报年月**全县 `yak_total` / `bull_total` / `cow_total` 等合计(按村汇总) |
|
|
|
213
|
+| 年龄结构 | 两档:`cow_young_count`、`cow_adult_count`;`bandCode`=`COW_YOUNG` / `COW_ADULT` |
|
|
|
214
|
+| 地图乡镇存栏 | 按乡镇聚合该最近年月村记录 |
|
|
277
|
215
|
|
|
278
|
216
|
---
|
|
279
|
217
|
|
|
280
|
218
|
## 7. 交付清单
|
|
281
|
219
|
|
|
282
|
|
-- [x] `sql/biz_yak_herd_inventory.sql`
|
|
283
|
|
-- [x] `BizYakHerdInventory` Domain / Mapper / XML / Service / Controller
|
|
284
|
|
-- [x] `YakHerdInventoryExcelParser` + `YakHerdInventoryExcelExporter`
|
|
285
|
|
-- [x] `TownDeptSupport` 乡镇字典
|
|
286
|
|
-- [x] 前端列表/表单/导入/导出
|
|
287
|
|
-- [x] 单元测试 + 导入/导出集成测试(`yak_herd_inventory_2026.xlsx`)
|
|
|
220
|
+- [x] `sql/biz_yak_herd_inventory.sql`、`sql/biz_yak_herd_inventory_village_uk.sql`
|
|
|
221
|
+- [x] Domain / Mapper / Service / Controller
|
|
|
222
|
+- [x] Parser / Exporter / Validation / TownDeptSupport 村树
|
|
|
223
|
+- [x] 前端列表/表单(Treeselect)/导入/导出
|
|
|
224
|
+- [x] 单元测试与 Excel 样例
|
|
288
|
225
|
|
|
289
|
226
|
---
|
|
290
|
227
|
|
|
|
@@ -292,9 +229,5 @@ for (int y = current; y >= current - 5; y--) { ... }
|
|
292
|
229
|
|
|
293
|
230
|
| 版本 | 说明 |
|
|
294
|
231
|
| --- | --- |
|
|
295
|
|
-| 1.0 | 初稿:表结构、CRUD、导入、sys_dept 乡镇、年份前推 5 年 |
|
|
296
|
|
-| 1.1 | 增加预留字段 `village_dept_id`(非必填) |
|
|
297
|
|
-| 1.2 | 实现按年份导出全县乡镇 Excel;列映射与代码对齐;交付清单勾选 |
|
|
298
|
|
-| 1.3 | 导入 upsert:`selectByYearAndTown` + `updateBizYakHerdInventory`;支持重复导入 |
|
|
299
|
|
-| 1.4 | 取消逻辑删除:无 `del_flag`;`deleteBizYakHerdInventoryByIds` 物理删除;`uk_year_town` 唯一约束 |
|
|
300
|
|
-| 1.5 | 按年月填报:`stat_month`;`uk_year_month_town`;`YakHerdInventoryMonthSupport`;导入/导出/列表/CRUD 支持月份;大屏年度汇总取 12 月 |
|
|
|
232
|
+| 1.0~1.5 | 乡镇粒度、按年月、四档母牛年龄等历史版本 |
|
|
|
233
|
+| 1.6 | 村粒度 `uk_year_month_village`;新模板字段与派生合计;导入全量覆盖;导出合计按列求和;`/villageTree`;大屏年龄两档 |
|