ebe191b06d
- 会员改为永久激活方案;云端文件不再拦截非会员;预览弹窗内导出/打印才校验 - 首页最近文件支持本地记录,登录后与云端合并;移除独立会员页与订阅页 - 模板库入库管理:soon_templates 表、Admin 上传 CRUD、/templates 轻量列表与按需下载 Co-authored-by: Cursor <cursoragent@cursor.com>
206 lines
5.8 KiB
Markdown
206 lines
5.8 KiB
Markdown
# 列表分页 API 契约
|
||
|
||
本文描述 `backend-web` 公开端(`/api/v1`)与管理端(`/api/admin`)列表接口的分页约定。实现以仓库内 PHP 控制器为准。
|
||
|
||
## 通用响应包装
|
||
|
||
所有 JSON 接口统一:
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": { }
|
||
}
|
||
```
|
||
|
||
失败时 `ok: false`,含 `error`(机器码)与 `message`(人类可读文案)。
|
||
|
||
## 推荐分页形态(page / size / total)
|
||
|
||
**新接口与前端管理列表优先使用此形态。**
|
||
|
||
### 请求 Query
|
||
|
||
| 参数 | 类型 | 默认 | 上限 | 说明 |
|
||
|------|------|------|------|------|
|
||
| `page` | int | `1` | — | 从 1 开始 |
|
||
| `size` | int | 见各接口 | 见各接口 | 每页条数 |
|
||
|
||
### 响应 `data`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `items` | array | 当前页记录 |
|
||
| `total` | int | 符合条件的总条数(用于算总页数) |
|
||
| `page` | int | 当前页码(回显) |
|
||
| `size` | int | 当前每页条数(回显) |
|
||
|
||
总页数:`ceil(total / size)`,`total === 0` 时视为 0 条、1 页。
|
||
|
||
### 示例
|
||
|
||
```http
|
||
GET /api/admin/users?page=2&size=20&q=test%40local.test
|
||
Authorization: Bearer <admin_token>
|
||
```
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"items": [ { "id": 1, "email": "..." } ],
|
||
"total": 42,
|
||
"page": 2,
|
||
"size": 20
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 管理端分页列表(`/api/admin`)
|
||
|
||
需管理员 JWT(`role=admin`)。默认 `size` 与上限见下表。
|
||
|
||
| 方法 | 路径 | 默认 size | size 上限 | 额外筛选 Query |
|
||
|------|------|-----------|-----------|----------------|
|
||
| GET | `/api/admin/users` | 20 | 200 | `q` 邮箱模糊 |
|
||
| GET | `/api/admin/orders` | 20 | 200 | `q` 订单号或邮箱;`status` pending/paid/cancelled/refunded;`refund_status` none/pending/approved/rejected;`channel` alipay/wechat;`from`/`to` 日期 YYYY-MM-DD |
|
||
| GET | `/api/admin/audits` | 50 | 200 | `q` 操作/目标/管理员邮箱;`action` 精确操作码;`from`/`to` 日期 |
|
||
|
||
实现参考:
|
||
|
||
- `backend-web/src/Admin/Controllers/UsersController.php`
|
||
- `backend-web/src/Admin/Controllers/OrdersController.php`
|
||
- `backend-web/src/Admin/Controllers/AuditsController.php`
|
||
|
||
### 管理端全量列表(无分页)
|
||
|
||
以下接口一次返回全部 `items`,数据量预期较小:
|
||
|
||
| 路径 | 说明 |
|
||
|------|------|
|
||
| `GET /api/admin/plans` | 套餐配置 |
|
||
| `GET/POST /api/admin/templates`、`PUT/DELETE /api/admin/templates/{id}` | 模板库 CRUD |
|
||
| `GET /api/admin/settings` | 系统键值 |
|
||
| `GET /api/admin/payment/status` | PEM 文件元数据 |
|
||
|
||
### 管理端固定条数嵌套列表
|
||
|
||
| 来源 | 条数 | 说明 |
|
||
|------|------|------|
|
||
| `GET /api/admin/stats` → `recent_orders` | 5 | 仪表盘最近订单,非翻页接口 |
|
||
| `GET /api/admin/users/{id}` → `recent_orders` | 5 | 用户详情内嵌 |
|
||
|
||
---
|
||
|
||
## 公开端分页列表(`/api/v1`)
|
||
|
||
需用户 JWT(除 plans 列表可匿名,见各控制器)。
|
||
|
||
| 方法 | 路径 | 默认 size | size 上限 | 分页参数 | 响应 |
|
||
|------|------|-----------|-----------|----------|------|
|
||
| GET | `/api/v1/files` | 50(legacy) | 200 | **推荐** `page`+`size`;**兼容** `limit`+`offset` | 见下文 |
|
||
| GET | `/api/v1/pay/orders` | 8 | 50 | `page`+`size` | page 形态 |
|
||
|
||
实现参考:
|
||
|
||
- `backend-web/src/Controllers/FileController.php`
|
||
- `backend-web/src/Controllers/PayController.php`
|
||
- `backend-web/src/Services/MembershipService.php`(`listOrders`)
|
||
|
||
### `GET /api/v1/files` 双模式
|
||
|
||
**推荐(page 形态)** — 传 `page`≥1 时生效:
|
||
|
||
```http
|
||
GET /api/v1/files?page=1&size=12
|
||
```
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"items": [ { "id": 1, "name": "design.soon", "size": 1024, "version": 1 } ],
|
||
"total": 25,
|
||
"page": 1,
|
||
"size": 12
|
||
}
|
||
}
|
||
```
|
||
|
||
**兼容(offset 形态)** — 未传 `page` 或 `page=0` 时:
|
||
|
||
```http
|
||
GET /api/v1/files?limit=50&offset=0
|
||
```
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"items": [ ],
|
||
"total": 25,
|
||
"limit": 50,
|
||
"offset": 0
|
||
}
|
||
}
|
||
```
|
||
|
||
两种形态均含 `total`。新前端(首页文件列表、管理端)应使用 `page`+`size`。
|
||
|
||
### `GET /api/v1/pay/orders`
|
||
|
||
会员中心订单历史,默认每页 8 条:
|
||
|
||
```http
|
||
GET /api/v1/pay/orders?page=1&size=8
|
||
```
|
||
|
||
### 公开端全量 / 非标准列表
|
||
|
||
| 路径 | 形态 |
|
||
|------|------|
|
||
| `GET /api/v1/plans` | `{ items: [...] }` 全量活跃套餐 |
|
||
| `GET /api/v1/plans/me` | 会员信息 + `recent_orders`(默认 8 条,非翻页) |
|
||
| `GET /api/v1/settings` | 扁平 key-value 对象,非 `items` 数组 |
|
||
| `GET /api/v1/templates` | 首页模板列表(仅 `id/name/type`;缩略图与文件按需拉取) |
|
||
| `GET /api/v1/templates/{id}/thumb` | 模板缩略图(从 `.soon` 内 `frontDisplayPic` 提取) |
|
||
| `GET /api/v1/templates/{id}/file` | 完整 `.soon` JSON(点击使用时再下载) |
|
||
| `GET /api/v1/soon-models` | 兼容别名,同 `GET /api/v1/templates` |
|
||
|
||
---
|
||
|
||
## 前端约定
|
||
|
||
### 管理后台(`frontend-web/pages/admin`)
|
||
|
||
- 分页状态:`AdminState`(`users` / `orders` / `audits` 的 `page`、`size` 及筛选字段)
|
||
- 分页 UI:`AdminPager` + `AdminUi.pagerHtml` / `bindPager`
|
||
- 请求:相对 admin base 的路径,如 `users?page=1&size=20`
|
||
|
||
### 门户 / 会员 / 首页
|
||
|
||
| 页面 | 接口 | 默认 size |
|
||
|------|------|-----------|
|
||
| 会员订单 | `GET /api/v1/pay/orders` | 8 |
|
||
| 首页云端文件 | `GET /api/v1/files?page=&size=` | 12 |
|
||
|
||
---
|
||
|
||
## 新增列表接口检查清单
|
||
|
||
1. 响应是否包含 `items` + `total`?
|
||
2. 是否使用 `page`(从 1)+ `size`,并在 `data` 中回显?
|
||
3. `size` 是否有合理默认值与上限(建议上限 200,管理端;用户订单建议 50)?
|
||
4. 筛选参数是否与分页独立(翻页时保留筛选)?
|
||
5. 是否在本文档「管理端/公开端」表中登记?
|
||
|
||
---
|
||
|
||
## 变更记录
|
||
|
||
| 日期 | 说明 |
|
||
|------|------|
|
||
| 2026-06-08 | 初版:统一 page/size/total;files 兼容 limit/offset;pay/orders 分页 |
|