leniu-dev 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/mysql-config.json +34 -0
- package/.claude/skills/jenkins-deploy/SKILL.md +21 -5
- package/.claude/skills/jenkins-deploy/assets/jk_build.py +29 -14
- package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.claude/skills/leniu-java-export/SKILL.md +570 -0
- package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.claude/skills/leniu-java-total-line/SKILL.md +196 -0
- package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
- package/.claude/skills/leniu-report-customization/SKILL.md +415 -0
- package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +391 -0
- package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.claude/skills/loki-log-query/SKILL.md +25 -55
- package/.claude/skills/loki-log-query/environments.json +45 -0
- package/.claude/skills/mysql-debug/SKILL.md +6 -12
- package/.codex/skills/jenkins-deploy/SKILL.md +21 -5
- package/.codex/skills/jenkins-deploy/assets/env_param.template.json +51 -0
- package/.codex/skills/jenkins-deploy/assets/jk_build.py +415 -0
- package/.codex/skills/leniu-java-export/SKILL.md +570 -0
- package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.codex/skills/leniu-java-total-line/SKILL.md +196 -0
- package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
- package/.codex/skills/leniu-report-customization/SKILL.md +415 -0
- package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +391 -0
- package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.codex/skills/loki-log-query/SKILL.md +25 -55
- package/.codex/skills/mysql-debug/SKILL.md +6 -12
- package/.cursor/skills/jenkins-deploy/SKILL.md +21 -5
- package/.cursor/skills/jenkins-deploy/assets/env_param.template.json +51 -0
- package/.cursor/skills/jenkins-deploy/assets/jk_build.py +415 -0
- package/.cursor/skills/leniu-java-export/SKILL.md +570 -0
- package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.cursor/skills/leniu-java-total-line/SKILL.md +196 -0
- package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
- package/.cursor/skills/leniu-report-customization/SKILL.md +415 -0
- package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +391 -0
- package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.cursor/skills/loki-log-query/SKILL.md +25 -55
- package/.cursor/skills/mysql-debug/SKILL.md +6 -12
- package/bin/index.js +59 -15
- package/package.json +1 -1
- package/src/skills/jenkins-deploy/SKILL.md +150 -0
- package/src/skills/jenkins-deploy/assets/env_param.template.json +51 -0
- package/src/skills/jenkins-deploy/assets/jk_build.py +415 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: leniu-java-report-query-param
|
|
3
|
+
description: |
|
|
4
|
+
leniu-tengyun-core / leniu-yunshitang 项目报表查询入参规范。当创建报表Controller接口的查询入参Param类时使用此skill。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 创建报表查询入参Param类(分页、时间范围、组织筛选)
|
|
8
|
+
- 设计报表接口的基类继承结构
|
|
9
|
+
- 配置导出列开关(exportColumns)
|
|
10
|
+
- 报表查询参数标准化
|
|
11
|
+
|
|
12
|
+
适用项目:
|
|
13
|
+
- leniu-tengyun-core:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun-core
|
|
14
|
+
- leniu-yunshitang:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun/leniu-yunshitang
|
|
15
|
+
|
|
16
|
+
触发词:报表查询入参、Param类、分页参数、时间范围查询、ReportBaseParam、exportCols
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# leniu-tengyun-core 报表查询入参规范
|
|
20
|
+
|
|
21
|
+
## 项目特征
|
|
22
|
+
|
|
23
|
+
| 特征 | 说明 |
|
|
24
|
+
|------|------|
|
|
25
|
+
| **包名前缀** | `net.xnzn.core.*` |
|
|
26
|
+
| **JDK 版本** | 21 |
|
|
27
|
+
| **请求封装** | `LeRequest<T>` |
|
|
28
|
+
| **分页参数** | `PageDTO` |
|
|
29
|
+
| **基类** | `ReportBaseParam` |
|
|
30
|
+
| **校验框架** | Jakarta Validation |
|
|
31
|
+
|
|
32
|
+
## 核心结构
|
|
33
|
+
|
|
34
|
+
### 1. Controller层接收入参
|
|
35
|
+
|
|
36
|
+
```java
|
|
37
|
+
import com.pig4cloud.pigx.common.core.util.LeRequest;
|
|
38
|
+
|
|
39
|
+
@PostMapping("/page")
|
|
40
|
+
public ReportBaseTotalVO<XxxVO> pageXxxSummary(@RequestBody LeRequest<XxxParam> request) {
|
|
41
|
+
XxxParam param = request.getContent();
|
|
42
|
+
return xxxService.pageSummary(param);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Param类基类继承
|
|
47
|
+
|
|
48
|
+
报表查询Param类**必须继承** `ReportBaseParam`:
|
|
49
|
+
|
|
50
|
+
```java
|
|
51
|
+
import lombok.Data;
|
|
52
|
+
import lombok.EqualsAndHashCode;
|
|
53
|
+
import io.swagger.annotations.ApiModel;
|
|
54
|
+
import io.swagger.annotations.ApiModelProperty;
|
|
55
|
+
import net.xnzn.core.common.page.PageDTO;
|
|
56
|
+
import net.xnzn.core.common.param.ReportBaseParam;
|
|
57
|
+
|
|
58
|
+
import java.time.LocalDate;
|
|
59
|
+
import java.util.List;
|
|
60
|
+
|
|
61
|
+
@Data
|
|
62
|
+
@EqualsAndHashCode(callSuper = true)
|
|
63
|
+
@ApiModel(value = "XXX查询入参")
|
|
64
|
+
public class XxxParam extends ReportBaseParam {
|
|
65
|
+
|
|
66
|
+
@ApiModelProperty("关键字")
|
|
67
|
+
private String keyword;
|
|
68
|
+
|
|
69
|
+
@ApiModelProperty("状态")
|
|
70
|
+
private Integer status;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. ReportBaseParam 提供的通用字段
|
|
75
|
+
|
|
76
|
+
| 字段名 | 类型 | 说明 |
|
|
77
|
+
|--------|------|------|
|
|
78
|
+
| `page` | `PageDTO` | 分页参数 |
|
|
79
|
+
| `startDate` | `LocalDate` | 开始时间 |
|
|
80
|
+
| `endDate` | `LocalDate` | 结束时间 |
|
|
81
|
+
| `exportCols` | `List<String>` | 需要导出的列 |
|
|
82
|
+
| `sumType` | `Integer` | 汇总类型 |
|
|
83
|
+
| `sumDimension` | `Integer` | 统计维度 |
|
|
84
|
+
|
|
85
|
+
## 常用查询字段模式
|
|
86
|
+
|
|
87
|
+
### 时间范围查询
|
|
88
|
+
|
|
89
|
+
```java
|
|
90
|
+
@Data
|
|
91
|
+
@EqualsAndHashCode(callSuper = true)
|
|
92
|
+
@ApiModel("订单报表查询参数")
|
|
93
|
+
public class OrderReportParam extends ReportBaseParam {
|
|
94
|
+
|
|
95
|
+
// 基类已有 startDate, endDate
|
|
96
|
+
|
|
97
|
+
@ApiModelProperty("开始时间(精确到秒)")
|
|
98
|
+
private LocalDateTime startTime;
|
|
99
|
+
|
|
100
|
+
@ApiModelProperty("结束时间(精确到秒)")
|
|
101
|
+
private LocalDateTime endTime;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 组织筛选
|
|
106
|
+
|
|
107
|
+
```java
|
|
108
|
+
@Data
|
|
109
|
+
@EqualsAndHashCode(callSuper = true)
|
|
110
|
+
@ApiModel("组织报表查询参数")
|
|
111
|
+
public class OrgReportParam extends ReportBaseParam {
|
|
112
|
+
|
|
113
|
+
@ApiModelProperty("组织ID")
|
|
114
|
+
private Long orgId;
|
|
115
|
+
|
|
116
|
+
@ApiModelProperty("组织ID列表")
|
|
117
|
+
private List<Long> orgIds;
|
|
118
|
+
|
|
119
|
+
@ApiModelProperty("食堂ID")
|
|
120
|
+
private Long canteenId;
|
|
121
|
+
|
|
122
|
+
@ApiModelProperty("食堂ID列表")
|
|
123
|
+
private List<Long> canteenIds;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 餐次筛选
|
|
128
|
+
|
|
129
|
+
```java
|
|
130
|
+
@Data
|
|
131
|
+
@EqualsAndHashCode(callSuper = true)
|
|
132
|
+
@ApiModel("餐次报表查询参数")
|
|
133
|
+
public class MealtimeReportParam extends ReportBaseParam {
|
|
134
|
+
|
|
135
|
+
@ApiModelProperty("餐次类型列表")
|
|
136
|
+
private List<Integer> mealtimeTypes;
|
|
137
|
+
|
|
138
|
+
@ApiModelProperty("是否只查正餐")
|
|
139
|
+
private Boolean onlyMainMeal;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 金额范围
|
|
144
|
+
|
|
145
|
+
```java
|
|
146
|
+
@Data
|
|
147
|
+
@EqualsAndHashCode(callSuper = true)
|
|
148
|
+
@ApiModel("金额报表查询参数")
|
|
149
|
+
public class AmountReportParam extends ReportBaseParam {
|
|
150
|
+
|
|
151
|
+
@ApiModelProperty("最小金额(分)")
|
|
152
|
+
private Long minAmount;
|
|
153
|
+
|
|
154
|
+
@ApiModelProperty("最大金额(分)")
|
|
155
|
+
private Long maxAmount;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## PageDTO 结构
|
|
160
|
+
|
|
161
|
+
```java
|
|
162
|
+
@Data
|
|
163
|
+
@ApiModel("分页参数")
|
|
164
|
+
public class PageDTO {
|
|
165
|
+
|
|
166
|
+
@ApiModelProperty("当前页码")
|
|
167
|
+
private Integer current = 1;
|
|
168
|
+
|
|
169
|
+
@ApiModelProperty("每页条数")
|
|
170
|
+
private Integer size = 10;
|
|
171
|
+
|
|
172
|
+
@ApiModelProperty("是否查询总数")
|
|
173
|
+
private Boolean ifCount = true;
|
|
174
|
+
|
|
175
|
+
@ApiModelProperty("页数为0时的处理")
|
|
176
|
+
private Boolean ifPageSizeZero = false;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## 完整示例
|
|
181
|
+
|
|
182
|
+
```java
|
|
183
|
+
@Data
|
|
184
|
+
@EqualsAndHashCode(callSuper = true)
|
|
185
|
+
@ApiModel("销售报表查询参数")
|
|
186
|
+
public class SalesReportParam extends ReportBaseParam {
|
|
187
|
+
|
|
188
|
+
@ApiModelProperty(value = "关键字")
|
|
189
|
+
private String keyword;
|
|
190
|
+
|
|
191
|
+
@ApiModelProperty(value = "组织ID列表")
|
|
192
|
+
private List<Long> orgIds;
|
|
193
|
+
|
|
194
|
+
@ApiModelProperty(value = "食堂ID列表")
|
|
195
|
+
private List<Long> canteenIds;
|
|
196
|
+
|
|
197
|
+
@ApiModelProperty(value = "餐次类型列表")
|
|
198
|
+
private List<Integer> mealtimeTypes;
|
|
199
|
+
|
|
200
|
+
@ApiModelProperty(value = "支付方式列表")
|
|
201
|
+
private List<Integer> payTypes;
|
|
202
|
+
|
|
203
|
+
@ApiModelProperty(value = "最小金额(分)")
|
|
204
|
+
private Long minAmount;
|
|
205
|
+
|
|
206
|
+
@ApiModelProperty(value = "最大金额(分)")
|
|
207
|
+
private Long maxAmount;
|
|
208
|
+
|
|
209
|
+
@ApiModelProperty(value = "是否查询合计行")
|
|
210
|
+
private Boolean ifQueryTotal = true;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 两层继承结构(实际生产代码模式)
|
|
215
|
+
|
|
216
|
+
报表 Param 存在两层继承结构,以订单分析报表为例:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
ReportAnalysisParam(大类基类:订单分析类报表通用字段)
|
|
220
|
+
└── ReportAnalysisTurnoverParam(具体报表 Param,加业务字段)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### ReportAnalysisParam(中间基类)
|
|
224
|
+
|
|
225
|
+
```java
|
|
226
|
+
import lombok.Data;
|
|
227
|
+
import net.xnzn.core.common.page.PageDTO;
|
|
228
|
+
|
|
229
|
+
import java.time.LocalDate;
|
|
230
|
+
import java.util.List;
|
|
231
|
+
|
|
232
|
+
@Data
|
|
233
|
+
public class ReportAnalysisParam {
|
|
234
|
+
|
|
235
|
+
/** 分页参数 */
|
|
236
|
+
private PageDTO page;
|
|
237
|
+
|
|
238
|
+
/** 开始日期 */
|
|
239
|
+
private LocalDate startDate;
|
|
240
|
+
|
|
241
|
+
/** 结束日期 */
|
|
242
|
+
private LocalDate endDate;
|
|
243
|
+
|
|
244
|
+
/** 日期维度:1=按月 2=按日 */
|
|
245
|
+
private Integer dateType;
|
|
246
|
+
|
|
247
|
+
/** 食堂摊位ID列表(多选) */
|
|
248
|
+
private List<Long> canteenStallIds;
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### ReportAnalysisTurnoverParam(具体 Param,继承中间基类)
|
|
253
|
+
|
|
254
|
+
```java
|
|
255
|
+
import lombok.Data;
|
|
256
|
+
import lombok.EqualsAndHashCode;
|
|
257
|
+
|
|
258
|
+
import java.util.List;
|
|
259
|
+
|
|
260
|
+
@Data
|
|
261
|
+
@EqualsAndHashCode(callSuper = true)
|
|
262
|
+
public class ReportAnalysisTurnoverParam extends ReportAnalysisParam {
|
|
263
|
+
|
|
264
|
+
/** 餐次类型(单选) */
|
|
265
|
+
private Integer mealtimeType;
|
|
266
|
+
|
|
267
|
+
/** 餐次类型列表(多选) */
|
|
268
|
+
private List<Integer> mealtimeTypeList;
|
|
269
|
+
|
|
270
|
+
/** 排序类型:1=按金额降序(默认) */
|
|
271
|
+
private Integer sortType = 1;
|
|
272
|
+
|
|
273
|
+
/** 食堂ID(单选) */
|
|
274
|
+
private Long canteenId;
|
|
275
|
+
|
|
276
|
+
/** 摊位ID(单选) */
|
|
277
|
+
private Long stallId;
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**选择继承层级的判断依据**:
|
|
282
|
+
- 若报表是"订单分析"大类报表 → 继承 `ReportAnalysisParam`(含 `dateType`)
|
|
283
|
+
- 若是通用报表 → 直接继承 `ReportBaseParam`(含 `page/startDate/endDate/exportCols`)
|
|
284
|
+
|
|
285
|
+
## 注意事项
|
|
286
|
+
|
|
287
|
+
- 报表Param类必须继承 `ReportBaseParam` 或其子类(如 `ReportAnalysisParam`)
|
|
288
|
+
- 时间字段使用 `LocalDate` 或 `LocalDateTime`
|
|
289
|
+
- `dateType` 字段含义:1=按月汇总,2=按日汇总
|
|
290
|
+
- 金额查询参数类型与业务域保持一致:钱包/账户用 `Long`(分),订单用 `BigDecimal`(分);见 leniu-java-amount-handling
|
|
291
|
+
- 导出时通过 `exportCols` 控制导出列
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: leniu-java-total-line
|
|
3
|
+
description: |
|
|
4
|
+
leniu-tengyun-core / leniu-yunshitang 项目合计行查询规范。当实现报表分页查询需要合计行功能时使用此skill。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 实现报表分页查询合计行(Service层合计查询)
|
|
8
|
+
- 编写Mapper XML合计SQL(只返回数值字段)
|
|
9
|
+
- Controller层合计行数据组装
|
|
10
|
+
- 合计查询开关控制
|
|
11
|
+
|
|
12
|
+
适用项目:
|
|
13
|
+
- leniu-tengyun-core:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun-core
|
|
14
|
+
- leniu-yunshitang:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun/leniu-yunshitang
|
|
15
|
+
|
|
16
|
+
触发词:合计行、totalLine、报表合计、SUM合计、ReportBaseTotalVO、合计查询
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# leniu-tengyun-core 合计行(Total Line)规范
|
|
20
|
+
|
|
21
|
+
## 项目特征
|
|
22
|
+
|
|
23
|
+
| 特征 | 说明 |
|
|
24
|
+
|------|------|
|
|
25
|
+
| **包名前缀** | `net.xnzn.core.*` |
|
|
26
|
+
| **JDK 版本** | 21 |
|
|
27
|
+
| **双库切换** | 默认商户库,`Executors.doInSystem()` 切换系统库 |
|
|
28
|
+
| **分页工具** | `PageMethod.startPage()` |
|
|
29
|
+
| **结果封装** | `ReportBaseTotalVO<T>` |
|
|
30
|
+
| **分页封装** | `PageVO.of()` |
|
|
31
|
+
|
|
32
|
+
## 核心原则
|
|
33
|
+
|
|
34
|
+
**合计行SQL只返回需要合计的数值字段**,不返回非数值字段(如日期、名称、ID等)。
|
|
35
|
+
|
|
36
|
+
## Service层实现
|
|
37
|
+
|
|
38
|
+
### 带合计行的分页查询
|
|
39
|
+
|
|
40
|
+
```java
|
|
41
|
+
import net.xnzn.core.common.page.PageMethod;
|
|
42
|
+
import net.xnzn.core.common.page.PageVO;
|
|
43
|
+
import net.xnzn.core.common.vo.ReportBaseTotalVO;
|
|
44
|
+
import cn.hutool.core.collection.CollUtil;
|
|
45
|
+
|
|
46
|
+
// ⚠️ 系统默认在商户库执行,业务查询无需 Executors.readInSystem()
|
|
47
|
+
// Executors.readInSystem() 仅用于需要访问系统库的场景(如全局配置、商户管理)
|
|
48
|
+
|
|
49
|
+
public ReportBaseTotalVO<XxxVO> pageWithTotal(XxxPageParam param) {
|
|
50
|
+
ReportBaseTotalVO<XxxVO> result = new ReportBaseTotalVO<>();
|
|
51
|
+
|
|
52
|
+
// 1. 导出时不查询合计行(避免不必要的性能开销)
|
|
53
|
+
if (CollUtil.isEmpty(param.getExportCols())) {
|
|
54
|
+
XxxVO totalLine = mapper.getSummaryTotal(param);
|
|
55
|
+
result.setTotalLine(totalLine);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 2. 开启分页
|
|
59
|
+
PageMethod.startPage(param.getPage());
|
|
60
|
+
|
|
61
|
+
// 3. 查询数据
|
|
62
|
+
List<XxxVO> list = mapper.getSummaryList(param);
|
|
63
|
+
|
|
64
|
+
// 4. 封装分页结果
|
|
65
|
+
result.setResultPage(PageVO.of(list));
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 单独的合计行查询方法
|
|
71
|
+
|
|
72
|
+
```java
|
|
73
|
+
public XxxVO getSummaryTotal(XxxPageParam param) {
|
|
74
|
+
// 默认在商户库执行,无需 Executors 包装
|
|
75
|
+
return mapper.getSummaryTotal(param);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Mapper XML规范
|
|
80
|
+
|
|
81
|
+
### 错误示例:返回非数值字段
|
|
82
|
+
|
|
83
|
+
```xml
|
|
84
|
+
<!-- ❌ 不要这样做 -->
|
|
85
|
+
<select id="getSummaryTotal" resultType="XxxVO">
|
|
86
|
+
SELECT
|
|
87
|
+
'合计' AS dateMonth, <!-- ❌ 不要返回字符串 -->
|
|
88
|
+
NULL AS schoolId, <!-- ❌ 不要返回ID -->
|
|
89
|
+
NULL AS schoolName, <!-- ❌ 不要返回名称 -->
|
|
90
|
+
SUM(staffCount) AS staffCount,
|
|
91
|
+
SUM(amount) AS amount
|
|
92
|
+
FROM xxx_table
|
|
93
|
+
</select>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 正确示例:只返回数值字段
|
|
97
|
+
|
|
98
|
+
```xml
|
|
99
|
+
<!-- ✅ 正确做法 -->
|
|
100
|
+
<select id="getSummaryTotal" resultType="XxxVO">
|
|
101
|
+
SELECT
|
|
102
|
+
SUM(staff_count) AS staffCount,
|
|
103
|
+
SUM(basic_salary) AS basicSalary,
|
|
104
|
+
SUM(overtime_salary) AS overtimeSalary,
|
|
105
|
+
SUM(personal_actual_amount) AS personalActualAmount,
|
|
106
|
+
CASE
|
|
107
|
+
WHEN SUM(staff_count) = 0 THEN 0
|
|
108
|
+
ELSE SUM(avg_salary) / COUNT(DISTINCT tenant_id)
|
|
109
|
+
END AS avgSalary
|
|
110
|
+
FROM xxx_table
|
|
111
|
+
<where>
|
|
112
|
+
del_flag = 2
|
|
113
|
+
<if test="startDate != null">
|
|
114
|
+
AND crtime >= #{startDate}
|
|
115
|
+
</if>
|
|
116
|
+
<if test="endDate != null">
|
|
117
|
+
AND crtime <= #{endDate}
|
|
118
|
+
</if>
|
|
119
|
+
</where>
|
|
120
|
+
</select>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 常见合计字段类型
|
|
124
|
+
|
|
125
|
+
| 字段类型 | 示例 | 合计方式 |
|
|
126
|
+
|---------|------|---------|
|
|
127
|
+
| 数量 | `staff_count`, `order_count` | `SUM()` |
|
|
128
|
+
| 金额 | `amount`, `salary` | `SUM()` |
|
|
129
|
+
| 百分比 | `discount_rate` | `AVG()` 或 `SUM() / COUNT()` |
|
|
130
|
+
| 计数 | `COUNT(DISTINCT id)` | 直接使用 |
|
|
131
|
+
|
|
132
|
+
## 特殊处理:平均值
|
|
133
|
+
|
|
134
|
+
```xml
|
|
135
|
+
<!-- 简单平均值 -->
|
|
136
|
+
SELECT AVG(amount) AS avgAmount
|
|
137
|
+
|
|
138
|
+
<!-- 加权平均值 -->
|
|
139
|
+
SELECT
|
|
140
|
+
CASE
|
|
141
|
+
WHEN SUM(count) = 0 THEN 0
|
|
142
|
+
ELSE SUM(amount * count) / SUM(count)
|
|
143
|
+
END AS weightedAvgAmount
|
|
144
|
+
|
|
145
|
+
<!-- 按维度平均 -->
|
|
146
|
+
SELECT
|
|
147
|
+
CASE
|
|
148
|
+
WHEN COUNT(DISTINCT tenant_id) = 0 THEN 0
|
|
149
|
+
ELSE SUM(total_amount) / COUNT(DISTINCT tenant_id)
|
|
150
|
+
END AS avgByTenant
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Controller层实现
|
|
154
|
+
|
|
155
|
+
```java
|
|
156
|
+
@PostMapping("/page")
|
|
157
|
+
@ApiOperation("分页查询(带合计)")
|
|
158
|
+
@RequiresAuthentication
|
|
159
|
+
public ReportBaseTotalVO<XxxVO> page(@RequestBody LeRequest<XxxParam> request) {
|
|
160
|
+
XxxParam param = request.getContent();
|
|
161
|
+
return xxxService.pageWithTotal(param);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@GetMapping("/total")
|
|
165
|
+
@ApiOperation("单独查询合计行")
|
|
166
|
+
@RequiresAuthentication
|
|
167
|
+
public XxxVO getTotal(XxxParam param) {
|
|
168
|
+
return xxxService.getSummaryTotal(param);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 导出时合计行处理
|
|
173
|
+
|
|
174
|
+
```java
|
|
175
|
+
public void exportExcel(XxxParam param, HttpServletResponse response) {
|
|
176
|
+
// 导出时需要查询合计行
|
|
177
|
+
XxxVO totalLine = mapper.getSummaryTotal(param);
|
|
178
|
+
|
|
179
|
+
// 分页查询所有数据(不分页)
|
|
180
|
+
param.getPage().setSize(Integer.MAX_VALUE);
|
|
181
|
+
List<XxxVO> list = mapper.getSummaryList(param);
|
|
182
|
+
|
|
183
|
+
// 将合计行添加到列表末尾
|
|
184
|
+
list.add(totalLine);
|
|
185
|
+
|
|
186
|
+
// 导出
|
|
187
|
+
exportService.export(list, response);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 注意事项
|
|
192
|
+
|
|
193
|
+
- 合计SQL只返回数值字段,不返回字符串、ID、名称等
|
|
194
|
+
- 业务查询默认在商户库执行,无需 `Executors` 包装;仅访问系统库数据时才使用 `Executors.doInSystem()`
|
|
195
|
+
- 导出时通过 `exportCols` 判断是否需要合计行
|
|
196
|
+
- 金额字段类型与 Entity 保持一致:订单模块用 `BigDecimal`,钱包模块用 `Long`(详见 leniu-java-amount-handling)
|