# 终端设备接口文档 > **基础地址**: `http://{服务器IP}:8580/api` > **认证方式**: Bearer Token(JWT) > **数据格式**: 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,无需经过本服务