Skip to content

8.3 分页查询规范 ​

概述

所有分页接口遵循统一的参数命名和返回结构。分页由 BaseController::_index() → BaseLogic::pageList() 实现,前端只需传标准参数即可获得分页数据。

请求参数 ​

参数类型默认值说明
pageNonumber1页码(最小为 1)
pageSizenumber20每页条数(1~100)
orderFieldstring-排序字段(camelCase,如 createTime)
orderTypestringdesc排序方向(asc / desc)
fieldsstring-返回字段(逗号分隔,如 id,username,realname)
其他参数--按 Logic 中配置的 pageLikeFields / pageEqFields 自动匹配

分页参数边界限制 ​

参数最小值最大值默认值超出处理
pageNo1-1小于 1 时强制为 1
pageSize110020超出范围时限制在 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
    }
}

返回字段 ​

字段类型说明
recordsarray当前页数据列表
totalnumber总记录数
sizenumber每页条数
currentnumber当前页码
pagesnumber总页数(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:

前端参数转换后说明
pageNopageNo不转换(排除项)
pageSizepageSize不转换(排除项)
orderFieldorderField不转换(排除项)
orderTypeorderType不转换(排除项)
fieldsfields不转换(排除项)
categoryIdcategory_id自动转换
createTimecreate_time自动转换
userNameuser_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)作为第二排序条件。

小蚂蚁云团队 · 提供技术支持