签入版本
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# 12.2 分页查询规范
|
||||
|
||||
:::tip 概述
|
||||
必须遵守的查询契约:筛选对齐三件套、分页默认值与上限、导出=所见、排序白名单。机制详解见 [8.3 分页查询规范](../api-spec/pagination)。
|
||||
:::
|
||||
|
||||
## 强制规范(三件套对齐)
|
||||
|
||||
```text
|
||||
1. 前端 querySchemas.ts 每个筛选输入 ↔ XxxPageReq 同名驼峰字段 ↔ spec 声明
|
||||
——三处任一缺失即视为筛选缺陷
|
||||
|
||||
2. 组件类型与后端声明对应:
|
||||
字符串 Input → LikeFields(逐列模糊,列名显式声明)
|
||||
Select/InputNumber → EqFields(零值跳过)
|
||||
KeywordFields(req.keyword 多列 OR)能力保留在基座,模块不声明,需要时再用
|
||||
|
||||
3. 分页:PageReq 内嵌 common.PageReq(pageNo 默认 1;pageSize 默认 10 上限 500)
|
||||
|
||||
4. 导出统一走 xxxSpec.applyFilters 与列表同套筛选(导出=所见,含数据权限)
|
||||
|
||||
5. 排序:前端排序字段仅 OrderableFields 白名单内生效(防注入)
|
||||
|
||||
6. 复杂条件写 Filter 钩子——不重复声明 Like/Eq 已覆盖条件
|
||||
```
|
||||
|
||||
## spec 声明模板(标准形态)
|
||||
|
||||
```go
|
||||
var xxxSpec = ModuleSpec[...]{
|
||||
Model: dao.Xxx.Ctx,
|
||||
LikeFields: []string{"name"}, // 对应 querySchemas 的 Input
|
||||
EqFields: []string{"status", "type"}, // 对应 Select/InputNumber
|
||||
OrderBy: "id DESC",
|
||||
// DataScope: ApplyDataScope("dept_id"), // 有部门列且需行级权限时
|
||||
}
|
||||
```
|
||||
|
||||
## Review 检查项
|
||||
|
||||
```text
|
||||
□ querySchemas 新增输入 → Req 加字段 + spec 加 Like/Eq 声明(三件同步)
|
||||
□ Req 筛选字段命名与表单 field 完全一致(驼峰)
|
||||
□ 导出接口 ExportReq 携带同套筛选字段且走 applyFilters
|
||||
□ 排序字段在白名单内
|
||||
□ 零值语义确认(status=0 为有效筛选时的处理)
|
||||
□ 分页上限未绕过(未自定义 pageSize 无上限)
|
||||
```
|
||||
|
||||
## 反例(禁止)
|
||||
|
||||
```text
|
||||
❌ querySchemas 有输入但 Req 无字段(提交了后端不读)
|
||||
❌ Req 有字段但 spec 未声明(读了不过滤——筛选假生效)
|
||||
❌ 导出另写查询条件(导出 ≠ 所见)
|
||||
❌ Filter 里重复写 LikeFields 已覆盖的条件
|
||||
❌ 前端传 orderField 直通 SQL(必须白名单)
|
||||
❌ 手写 del_flag/tenant_id 条件混入筛选(dao.Ctx 已注入)
|
||||
```
|
||||
|
||||
## 一致性验证方法
|
||||
|
||||
```text
|
||||
1. 页面输入筛选值 → Network 看请求参数
|
||||
2. 对照 Req 字段名(驼峰)是否接收
|
||||
3. 对照 spec 声明过滤是否生效(结果集变化)
|
||||
4. 导出同一筛选 → Excel 行数 = 列表 total
|
||||
```
|
||||
Reference in New Issue
Block a user