library-picturebook-activity/docs/api/device-api.md
En 98e9ad1d28 feat(前端): 测试环境登录框支持自动填充测试账号
通过 VITE_AUTO_FILL_TEST 环境变量控制,在 .env.test 中启用,
使测试环境构建后登录框也能自动填充测试账号,方便测试人员使用。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 17:03:22 +08:00

407 lines
10 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.

# 终端设备接口文档
> **基础地址**: `http://{服务器IP}:8580/api`
> **认证方式**: Bearer TokenJWT
> **数据格式**: JSON
> **字符编码**: UTF-8
---
## 目录
1. [发送短信验证码](#1-发送短信验证码)
2. [手机验证码登录](#2-手机验证码登录)
3. [用户作品列表](#3-用户作品列表)
4. [作品详情](#4-作品详情)
5. [通用错误码](#5-通用错误码)
---
## 接口详情
### 1. 发送短信验证码
向指定手机号发送6位数字验证码验证码有效期 **5分钟**
```
POST /device/auth/sms/send
```
**请求头**
| 参数 | 值 |
|------|------|
| Content-Type | application/json |
**请求参数Body**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| phone | string | 是 | 手机号11位 |
**请求示例**
```json
{
"phone": "13800138000"
}
```
**响应参数**
| 字段 | 类型 | 说明 |
|------|------|------|
| code | int | 状态码200=成功 |
| message | string | 描述信息 |
| data | null | 无数据返回 |
**响应示例**
```json
{
"code": 200,
"message": "success",
"data": null,
"timestamp": "2026-04-11T12:00:00",
"path": "/api/device/auth/sms/send"
}
```
**注意事项**
- 同一手机号 **60秒内** 只能发送一次
- 同一手机号每天最多发送 **15次**
- 验证码 **5分钟** 内有效,仅可使用一次
---
### 2. 手机验证码登录
使用手机号 + 短信验证码登录,成功返回 JWT Token 和用户信息。
```
POST /device/auth/login/sms
```
**请求头**
| 参数 | 值 |
|------|------|
| Content-Type | application/json |
**请求参数Body**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| phone | string | 是 | 手机号11位 |
| smsCode | string | 是 | 6位数字验证码 |
**请求示例**
```json
{
"phone": "13800138000",
"smsCode": "406436"
}
```
**响应参数**
| 字段 | 类型 | 说明 |
|------|------|------|
| code | int | 状态码200=成功 |
| message | string | 描述信息 |
| data | object | 登录数据 |
| data.token | string | JWT Token后续接口需携带 |
| data.userId | long | 用户ID |
| data.username | string | 用户名 |
| data.nickname | string | 昵称 |
| data.avatar | string | 头像URL可为 null |
| data.phone | string | 手机号(脱敏,如 138****8000 |
**响应示例**
```json
{
"code": 200,
"message": "success",
"data": {
"token": "eyJhbGciOiJIUzM4NCJ9.eyJ0ZW5hbnRJZCI6OCwidXNlcm5hbWUiOiJkZW1vIiwic3ViIjoiOSIsImlhdCI6MTc3NTg4MjgwNywiZXhwIjoxNzc2NDg3NjA3fQ.xxx",
"userId": 9,
"username": "demo",
"nickname": "小明",
"avatar": "https://example.com/avatar.png",
"phone": "137****9302"
},
"timestamp": "2026-04-11T12:00:00",
"path": "/api/device/auth/login/sms"
}
```
**错误情况**
| code | 说明 |
|------|------|
| 404 | 该手机号未注册 |
| 403 | 账号已被禁用 |
| 400 | 验证码错误 |
| 400 | 验证码已过期 |
| 400 | 验证码不能为空 |
---
### 3. 用户作品列表
获取当前登录用户的创作作品列表(分页)。
```
GET /device/works
```
**请求头**
| 参数 | 值 | 必填 | 说明 |
|------|------|------|------|
| Authorization | Bearer {token} | 是 | 登录接口返回的 Token |
**请求参数Query**
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| page | int | 否 | 1 | 页码从1开始 |
| pageSize | int | 否 | 10 | 每页条数 |
| status | string | 否 | - | 筛选状态:`draft`/`unpublished`/`pending_review`/`published`/`rejected` |
| keyword | string | 否 | - | 标题关键词搜索 |
**请求示例**
```
GET /api/device/works?page=1&pageSize=10&status=unpublished&keyword=测试
```
**响应参数**
| 字段 | 类型 | 说明 |
|------|------|------|
| code | int | 状态码200=成功 |
| data | object | 分页数据 |
| data.list | array | 作品列表 |
| data.total | long | 总记录数 |
| data.page | long | 当前页码 |
| data.pageSize | long | 每页条数 |
**list 数组项字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | long | 作品ID |
| title | string | 作品标题 |
| coverUrl | string | 封面图URL可为 null |
| description | string | 作品描述,可为 null |
| status | string | 状态:`draft`(草稿)/ `unpublished`(待发布)/ `pending_review`(审核中)/ `published`(已发布)/ `rejected`(已拒绝) |
| authorName | string | 作者名称 |
| leaiStatus | int | AI创作进度`-1`=失败, `0`=初始化, `1`=排队中, `2`=处理中, `3`=完成, `4`=已编目, `5`=已配音 |
| pageCount | int | 绘本页数,可为 null |
| createTime | string | 创建时间,格式 `yyyy-MM-ddTHH:mm:ss` |
| modifyTime | string | 修改时间,格式 `yyyy-MM-ddTHH:mm:ss` |
**响应示例**
```json
{
"code": 200,
"message": "success",
"data": {
"list": [
{
"id": 38,
"title": "我的绘本",
"coverUrl": "https://oss.example.com/cover.png",
"description": "一个有趣的故事",
"status": "unpublished",
"authorName": "小明",
"leaiStatus": 5,
"pageCount": 6,
"createTime": "2026-04-10T17:07:00",
"modifyTime": "2026-04-10T17:10:53"
},
{
"id": 37,
"title": "春天的故事",
"coverUrl": "https://oss.example.com/cover2.png",
"description": null,
"status": "published",
"authorName": "小红",
"leaiStatus": 5,
"pageCount": 6,
"createTime": "2026-04-10T16:53:17",
"modifyTime": "2026-04-10T16:58:54"
}
],
"total": 15,
"page": 1,
"pageSize": 10
}
}
```
---
### 4. 作品详情
获取指定作品的完整信息,包含所有页面内容(图片、文字、音频)。
```
GET /device/works/{id}
```
**请求头**
| 参数 | 值 | 必填 | 说明 |
|------|------|------|------|
| Authorization | Bearer {token} | 是 | 登录接口返回的 Token |
**路径参数**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | long | 是 | 作品ID |
**请求示例**
```
GET /api/device/works/38
```
**响应参数**
| 字段 | 类型 | 说明 |
|------|------|------|
| code | int | 状态码200=成功 |
| data | object | 作品详情 |
| data.id | long | 作品ID |
| data.title | string | 作品标题 |
| data.authorName | string | 作者名称 |
| data.coverUrl | string | 封面图URL |
| data.description | string | 作品描述,可为 null |
| data.status | string | 状态 |
| data.visibility | string | 可见范围:`public`/`designated`/`internal`/`private` |
| data.createTime | string | 创建时间 |
| data.modifyTime | string | 修改时间 |
| data.pages | array | 页面列表,按页码升序排列 |
**pages 数组项字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| pageNo | int | 页码从1开始 |
| imageUrl | string | 页面图片URL |
| text | string | 页面文字内容,可为 null |
| audioUrl | string | 页面音频URL可为 null |
**响应示例**
```json
{
"code": 200,
"message": "success",
"data": {
"id": 38,
"title": "我的绘本",
"authorName": "小明",
"coverUrl": "https://oss.example.com/cover.png",
"description": "一个有趣的故事",
"status": "unpublished",
"visibility": "private",
"createTime": "2026-04-10T17:07:00",
"modifyTime": "2026-04-10T17:10:53",
"pages": [
{
"pageNo": 1,
"imageUrl": "https://oss.example.com/page_0.png",
"text": "从前有一座山",
"audioUrl": "https://oss.example.com/page_0.mp3"
},
{
"pageNo": 2,
"imageUrl": "https://oss.example.com/page_1.png",
"text": "山里有一座庙",
"audioUrl": "https://oss.example.com/page_1.mp3"
},
{
"pageNo": 3,
"imageUrl": "https://oss.example.com/page_2.png",
"text": "庙里有一个老和尚",
"audioUrl": null
}
]
}
}
```
**错误情况**
| code | 说明 |
|------|------|
| 404 | 作品不存在 |
| 403 | 无权访问该作品(非本人作品) |
---
## 5. 通用错误码
所有接口统一响应格式:
```json
{
"code": 401,
"message": "未登录或 Token 已过期",
"timestamp": "2026-04-11T12:00:00",
"path": "/api/device/works"
}
```
| code | 说明 |
|------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未登录或 Token 已过期 |
| 403 | 无权限访问 |
| 404 | 资源不存在 |
| 429 | 请求过于频繁(触发限流) |
| 500 | 服务器内部错误 |
---
## 调用流程
```
┌─────────────────────────────────────────────────────────┐
│ 终端设备调用流程 │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. 发送验证码 POST /device/auth/sms/send │
│ └─ 参数: { phone } │
│ │
│ 2. 验证码登录 POST /device/auth/login/sms │
│ └─ 参数: { phone, smsCode } │
│ └─ 返回: token ← 保存到本地 │
│ │
│ 3. 作品列表 GET /device/works │
│ └─ Header: Authorization: Bearer {token} │
│ └─ 参数: page, pageSize, status(可选), keyword(可选) │
│ │
│ 4. 作品详情 GET /device/works/{id} │
│ └─ Header: Authorization: Bearer {token} │
│ └─ 返回: 完整页面数据(图片+文字+音频) │
│ │
└─────────────────────────────────────────────────────────┘
```
**Token 有效期**: 7天604800秒过期后需重新登录获取。
**建议**:
- Token 存储在设备本地,每次启动时检查是否过期
- 过期后重新走 发送验证码 → 登录 流程
- 音频和图片资源使用返回的 URL 直接访问 OSS无需经过本服务