Files
easygoadmin-wiki/EasyGoAdmin_Iris_AntdVue/zh/api-spec/pagination.md
T
2026-10-20 21:19:44 +08:00

372 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 8.3 分页查询规范
:::tip 概述
所有分页接口遵循统一的参数命名和返回结构。分页由 `BaseController::_index()` → `BaseLogic::pageList()` 实现,前端只需传标准参数即可获得分页数据。
:::
## 请求参数
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `pageNo` | number | 1 | 页码(最小为 1) |
| `pageSize` | number | 20 | 每页条数(1~100) |
| `orderField` | string | - | 排序字段(camelCase,如 `createTime`) |
| `orderType` | string | `desc` | 排序方向(`asc` / `desc`) |
| `fields` | string | - | 返回字段(逗号分隔,如 `id,username,realname`) |
| 其他参数 | - | - | 按 Logic 中配置的 `pageLikeFields` / `pageEqFields` 自动匹配 |
### 分页参数边界限制
| 参数 | 最小值 | 最大值 | 默认值 | 超出处理 |
|------|--------|--------|--------|---------|
| `pageNo` | 1 | - | 1 | 小于 1 时强制为 1 |
| `pageSize` | 1 | 100 | 20 | 超出范围时限制在 1~100 |
## 请求示例
```bash
# 基本分页
GET /api/example/page?pageNo=1&pageSize=10
# 带模糊搜索(LIKE)
GET /api/example/page?pageNo=1&pageSize=10&name=测试
# 带精确过滤(=)
GET /api/example/page?pageNo=1&pageSize=10&status=1&type=2
# 模糊 + 精确组合
GET /api/example/page?pageNo=1&pageSize=10&name=测试&status=1
# 自定义排序
GET /api/example/page?pageNo=1&pageSize=10&orderField=sort&orderType=asc
# 指定返回字段
GET /api/example/page?pageNo=1&pageSize=10&fields=id,name,status
# 多条件组合
GET /api/user/page?pageNo=1&pageSize=20&username=admin&status=1&deptId=3&orderField=id&orderType=desc
```
## 返回结构
```json
{
"code": 0,
"ok": true,
"msg": "操作成功",
"data": {
"records": [
{ "id": 1, "name": "测试", "status": 1, "statusText": "启用", "createTime": "2026-01-01 00:00:00" },
{ "id": 2, "name": "示例", "status": 0, "statusText": "禁用", "createTime": "2026-01-02 00:00:00" }
],
"total": 100,
"size": 10,
"current": 1,
"pages": 10
}
}
```
### 返回字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `records` | array | 当前页数据列表 |
| `total` | number | 总记录数 |
| `size` | number | 每页条数 |
| `current` | number | 当前页码 |
| `pages` | number | 总页数(`ceil(total / size)`) |
## 查询条件匹配
### pageLikeFields — 模糊匹配(LIKE)
在 Logic 中配置的字段,前端传参时自动使用 `LIKE '%值%'` 查询:
```php
class ExampleLogic extends BaseLogic
{
protected array $pageLikeFields = ['name', 'title'];
}
```
```bash
# name 字段自动使用 LIKE 查询
GET /api/example/page?name=测试
# 生成: WHERE name LIKE '%测试%'
```
### pageEqFields — 精确匹配(=)
在 Logic 中配置的字段,前端传参时自动使用 `= 值` 查询:
```php
class ExampleLogic extends BaseLogic
{
protected array $pageEqFields = ['status', 'type', 'category_id'];
}
```
```bash
# status 和 type 字段自动使用 = 查询
GET /api/example/page?status=1&type=2
# 生成: WHERE status = 1 AND type = 2
```
### 条件组合
```bash
# 模糊 + 精确 + 排序 + 分页
GET /api/example/page?pageNo=1&pageSize=20&name=测试&status=1&orderField=sort&orderType=asc
# 生成 SQL:
# SELECT * FROM think_example
# WHERE is_delete = 0
# AND name LIKE '%测试%'
# AND status = 1
# ORDER BY sort ASC
# LIMIT 20 OFFSET 0
```
## 排序
### 前端传参排序
```bash
# 按创建时间倒序
GET /api/example/page?orderField=createTime&orderType=desc
# 按排序字段正序
GET /api/example/page?orderField=sort&orderType=asc
```
### Logic 默认排序
```php
class ExampleLogic extends BaseLogic
{
/**
* 单字段排序
*
* @var array
*/
protected array $pageOrderBy = ['field' => 'sort', 'type' => 'asc'];
/**
* 多字段排序
*
* @var array
*/
protected array $pageOrderBy = [
['field' => 'sort', 'type' => 'asc'],
['field' => 'id', 'type' => 'desc'],
];
}
```
**优先级:** 前端传参 > Logic 默认配置
## 字段过滤
### fields 参数
前端可通过 `fields` 参数指定只需要的字段,减少数据传输量:
```bash
# 只返回 id、name、status 三个字段
GET /api/example/page?fields=id,name,status
```
**响应:**
```json
{
"records": [
{ "id": 1, "name": "测试", "status": 1 },
{ "id": 2, "name": "示例", "status": 0 }
]
}
```
**注意:** `id` 字段始终保留,即使未在 `fields` 中指定。
## 参数转换
前端使用 camelCase,后端自动转换为 snake_case:
| 前端参数 | 转换后 | 说明 |
|---------|--------|------|
| `pageNo` | `pageNo` | 不转换(排除项) |
| `pageSize` | `pageSize` | 不转换(排除项) |
| `orderField` | `orderField` | 不转换(排除项) |
| `orderType` | `orderType` | 不转换(排除项) |
| `fields` | `fields` | 不转换(排除项) |
| `categoryId` | `category_id` | 自动转换 |
| `createTime` | `create_time` | 自动转换 |
| `userName` | `user_name` | 自动转换 |
### 排序字段值也自动转换
```bash
# 前端传入 camelCase
GET /api/example/page?orderField=createTime
# 后端自动转换为 snake_case
ORDER BY create_time DESC
```
## Controller 层实现
### 使用 _index 快捷方法(推荐)
```php
class ExampleController extends BaseController
{
protected ExampleLogic $logic;
protected function initialize(): void
{
$this->logic = new ExampleLogic();
}
#[Permission('sys:example:page', '案例分页')]
public function page(): Json
{
return parent::_index($this->logic);
}
}
```
### 带额外查询条件
```php
#[Permission('sys:user:page', '用户分页')]
public function page(): Json
{
// 额外条件:只查启用状态的用户
return parent::_index($this->logic, ['status' => 1]);
}
```
### 带关联查询
```php
#[Permission('sys:article:page', '文章分页')]
public function page(): Json
{
// 预加载分类关联
return parent::_index($this->logic, [], ['category']);
}
```
## Logic 层实现
```php
class ExampleLogic extends BaseLogic
{
/**
* 关联的模型类
*
* @var string
*/
protected string $modelClass = Example::class;
/**
* LIKE 模糊匹配字段
*
* @var array
*/
protected array $pageLikeFields = ['name', 'title'];
/**
* 精确匹配字段
*
* @var array
*/
protected array $pageEqFields = ['status', 'type', 'category_id'];
/**
* 默认排序规则
*
* @var array
*/
protected array $pageOrderBy = ['field' => 'sort', 'type' => 'asc'];
/**
* 枚举显示名映射
*
* @var array
*/
protected array $serializeMaps = ['status' => 'example_status'];
}
```
## 前端集成
### API 函数
```typescript
// src/api/tool/example.ts
export function getExamplePage(params?) {
return http.request({ url: '/example/page', method: 'GET', params });
}
```
### 组件使用
```vue
<script setup>
import { getExamplePage } from '@/api/tool/example';
const tableData = ref([]);
const pageNo = ref(1);
const pageSize = ref(20);
const total = ref(0);
const searchForm = ref({ name: '', status: '' });
const fetchData = async () => {
const res = await getExamplePage({
pageNo: pageNo.value,
pageSize: pageSize.value,
...searchForm.value,
});
tableData.value = res.records;
total.value = res.total;
};
// 搜索
const handleSearch = () => {
pageNo.value = 1;
fetchData();
};
// 翻页
const handlePageChange = (page) => {
pageNo.value = page;
fetchData();
};
onMounted(() => fetchData());
</script>
```
## 常见问题
### 问题 1:搜索条件不生效
**原因:** 字段名未在 `pageLikeFields` 或 `pageEqFields` 中配置。
**解决:** 在 Logic 中添加对应字段配置。
### 问题 2:排序不生效
**原因:** `orderField` 传了数据库不存在的字段名。
**解决:** 确保 `orderField` 传的是数据库字段名的 camelCase 形式。
### 问题 3:分页数据重复
**原因:** 排序字段值相同,导致数据库返回顺序不确定。
**解决:** 排序字段加上唯一字段(如 id)作为第二排序条件。