分页设计:让数据展示更轻量、更流畅
在智评 Code+ 中,用户提交记录、题目列表、题目提交情况等数据可能会迅速增长。为了防止前端一次性加载全部数据导致卡顿、接口耗时过长,我引入了通用分页查询设计,确保平台在数据量变大时依然响应快速、体验流畅。
为什么要分页?
分页是 Web 开发中非常经典的优化手段,尤其适用于:
-
用户提交记录多时;
-
某个题目提交用户多时;
-
后台数据管理页面展示长列表时。
通过分页,我们可以:
-
避免一次性查询大数据量导致内存占用高;
-
降低 API 响应时间;
-
支持前端 “无限滚动加载” 体验。
分页参数设计
我采用了常规 RESTful 分页参数约定:
参数 | 含义 | 示例 |
---|---|---|
page | 页码(从 1 开始) | /submissions?page=2 |
limit | 每页数量(最大值限制) | /submissions?limit=20 |
并通过 DefaultQuery 提供默认值:
page := c.DefaultQuery("page", "1")
limit := c.DefaultQuery("limit", "10")
GORM 实现分页查询
使用 GORM 实现分页非常自然,只需配合 .Offset() 与 .Limit() 方法即可:
utils.DB.Model(&models.Submission{}).
Where("problem_id = ?", problemID).
Count(&total).
Order("submit_time desc").
Offset((pageInt - 1) * limitInt).
Limit(limitInt).
Find(&submissions)
其中:
-
Count() 用于前端分页控件展示总数;
-
Offset() 计算偏移量;
-
Limit() 控制每页条数;
-
Order() 保证按时间排序展示。
这套结构也应用在其他接口中,例如 /auth/submissions 用于当前用户历史提交分页查看。
返回结构设计
分页接口统一返回以下结构:
{
"total": 54,
"page": 2,
"limit": 10,
"submissions": [ ... ]
}
-
前端可以根据 total 和 limit 计算出总页数;
-
可用于无限滚动加载 / 页码切换;
-
保持接口一致性,便于通用组件调用。
可扩展点
分页设计简单但灵活,后续可拓展功能包括:
拓展 | 说明 |
---|---|
条件过滤 | 按用户、语言、评测结果等条件组合过滤 |
排序字段切换 | 默认按提交时间,也可支持按结果、耗时排序 |
前后端统一分页组件 | 提供统一的前端分页控件和接口协议 |
Cursor 分页 | 对高并发下偏移量不准确问题提供更优解 |
总结
分页系统虽然只是系统中的一个小模块,但它是数据展示与接口性能之间的「平衡器」。在智评 Code+ 中,通过灵活的分页参数设计与统一的返回结构,我让各类记录展示既清晰又高效,未来也便于进一步功能拓展。