366 lines
7.0 KiB
Markdown
366 lines
7.0 KiB
Markdown
# 接口文档
|
||
|
||
本地 Base URL:
|
||
|
||
```
|
||
http://127.0.0.1:8001
|
||
```
|
||
|
||
自动生成文档:
|
||
|
||
- Swagger UI:`/docs`
|
||
- ReDoc:`/redoc`
|
||
|
||
鉴权说明:
|
||
|
||
- 除 `GET /health`、`POST /auth/login`、`/docs`、`/redoc`、`/openapi.json` 外,其余接口都需要 Bearer Token。
|
||
- 请求头格式:`Authorization: Bearer <access_token>`
|
||
|
||
## 1. 健康检查
|
||
|
||
### `GET /health`
|
||
|
||
用途:
|
||
|
||
- 检查服务是否存活。
|
||
|
||
响应示例:
|
||
|
||
```json
|
||
{
|
||
"status": "ok"
|
||
}
|
||
```
|
||
|
||
## 2. 登录
|
||
|
||
### `POST /auth/login`
|
||
|
||
用途:
|
||
|
||
- 小程序端上传 `wx.login` 返回的一次性 `code`。
|
||
- 服务端调用微信 `code2Session` 换取真实 `openid/unionid`,并签发本地访问令牌。
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"code": "0312abcdEFGHijklMNopqrstUVwxYZ12",
|
||
"nickname": "家长昵称",
|
||
"avatar_url": "https://thirdwx.qlogo.cn/mmopen/xxx/132"
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
- `code`:必填,来自微信 `wx.login` / `Taro.login`
|
||
- `nickname`:可选,仅作为资料字段
|
||
- `avatar_url`:可选,仅作为资料字段
|
||
|
||
成功响应(`200`):
|
||
|
||
```json
|
||
{
|
||
"access_token": "<jwt-token>",
|
||
"token_type": "bearer",
|
||
"expires_in": 3600,
|
||
"user_id": 1
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
- `401`:微信 `code` 无效、已过期或已被使用
|
||
- `422`:请求参数校验失败
|
||
- `502`:微信登录服务不可用或返回异常数据
|
||
- `503`:服务端未配置正确的微信小程序凭证
|
||
|
||
## 3. 发送消息
|
||
|
||
### `POST /messages`
|
||
|
||
用途:
|
||
|
||
- 保存单聊消息。
|
||
- 服务端从 token 中识别发送者,不需要传 `sender_user_id`。
|
||
- 服务端根据“当前用户 + peer_user_id”自动查找或创建会话。
|
||
- `client_msg_id` 用于幂等控制。
|
||
|
||
请求头:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"peer_user_id": 2,
|
||
"client_msg_id": "msg-20260326-0002",
|
||
"content_type": 1,
|
||
"content_text": "hello"
|
||
}
|
||
```
|
||
|
||
字段规则:
|
||
|
||
- `peer_user_id`:`int > 0`,且不能与当前登录用户相同
|
||
- `client_msg_id`:`string`,长度 `1-64`
|
||
- `content_type`:`1=text 2=audio 3=image 4=json`
|
||
- `content_text`:`content_type=1` 时必填
|
||
- `content_json`:`content_type=4` 时必填
|
||
- `media_file_key`:`content_type=2` 或 `3` 时必填
|
||
- `media_duration_ms`:媒体时长(可选,毫秒)
|
||
|
||
成功响应(首次入库,`201`):
|
||
|
||
```json
|
||
{
|
||
"idempotent": false,
|
||
"message": {
|
||
"id": 1008,
|
||
"conversation_id": 1,
|
||
"seq": 7,
|
||
"sender_user_id": 1,
|
||
"role": 1,
|
||
"content_type": 1,
|
||
"content_text": "hello",
|
||
"content_json": null,
|
||
"media_file_key": null,
|
||
"media_duration_ms": null,
|
||
"client_msg_id": "msg-20260326-0002",
|
||
"created_at": "2026-03-26T11:20:00.123000"
|
||
}
|
||
}
|
||
```
|
||
|
||
成功响应(幂等命中,`200`):
|
||
|
||
```json
|
||
{
|
||
"idempotent": true,
|
||
"message": {
|
||
"id": 1008,
|
||
"conversation_id": 1,
|
||
"seq": 7,
|
||
"sender_user_id": 1,
|
||
"role": 1,
|
||
"content_type": 1,
|
||
"content_text": "hello",
|
||
"content_json": null,
|
||
"media_file_key": null,
|
||
"media_duration_ms": null,
|
||
"client_msg_id": "msg-20260326-0002",
|
||
"created_at": "2026-03-26T11:20:00.123000"
|
||
}
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
- `401`:未登录或 token 无效
|
||
- `404`:接收人不存在/不可用
|
||
- `409`:会话不是激活状态
|
||
- `422`:请求参数校验失败
|
||
|
||
## 4. 查询消息
|
||
|
||
### `GET /messages`
|
||
|
||
用途:
|
||
|
||
- 按会话分页读取消息。
|
||
- 返回结果按 `seq` 正序排列。
|
||
- 仅会话参与者可读取。
|
||
|
||
请求头:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
Query 参数:
|
||
|
||
- `conversation_id`(必填):`int > 0`
|
||
- `cursor_seq`(可选):`int >= 1`,用于向前翻页
|
||
- `limit`(可选):默认 `20`,最大 `100`
|
||
|
||
请求示例:
|
||
|
||
```
|
||
GET /messages?conversation_id=1&limit=20
|
||
GET /messages?conversation_id=1&cursor_seq=50&limit=20
|
||
```
|
||
|
||
响应示例:
|
||
|
||
```json
|
||
{
|
||
"conversation_id": 1,
|
||
"has_more": false,
|
||
"next_cursor_seq": null,
|
||
"items": [
|
||
{
|
||
"id": 1001,
|
||
"conversation_id": 1,
|
||
"seq": 1,
|
||
"sender_user_id": 1,
|
||
"role": 1,
|
||
"content_type": 1,
|
||
"content_text": "Hi, did you finish homework?",
|
||
"content_json": {
|
||
"lang": "en"
|
||
},
|
||
"media_file_key": null,
|
||
"media_duration_ms": null,
|
||
"client_msg_id": "c1-m1",
|
||
"created_at": "2026-03-25T10:00:05"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
- `401`:未登录或 token 无效
|
||
- `403`:无权限读取该会话
|
||
- `404`:会话不存在
|
||
- `422`:请求参数校验失败
|
||
|
||
## 5. 家长头像
|
||
|
||
### `POST /parents/me/avatar`
|
||
|
||
用途:
|
||
|
||
- 上传当前登录用户头像到 COS 头像桶。
|
||
- 服务端会将 COS `avatar_file_key` 写入数据库,并在响应中返回可用的 `avatar_url`。
|
||
|
||
请求头:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
Content-Type: multipart/form-data
|
||
```
|
||
|
||
表单字段:
|
||
|
||
- `file`:头像图片文件,支持 `jpg/jpeg/png/webp`
|
||
|
||
成功响应(`200`):
|
||
|
||
```json
|
||
{
|
||
"user_id": 1,
|
||
"openid": "wx_xxx",
|
||
"unionid": null,
|
||
"nickname": "Parent A",
|
||
"avatar_url": "https://ava-1320289366.cos.ap-guangzhou.myqcloud.com/...",
|
||
"phone": null,
|
||
"status": 1
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
- `401`:未登录或 token 无效
|
||
- `404`:当前用户不存在
|
||
- `413`:头像文件过大
|
||
- `415`:头像文件类型不支持
|
||
|
||
### `GET /parents/{user_id}/avatar`
|
||
|
||
用途:
|
||
|
||
- 获取指定用户头像的可访问 URL。
|
||
- 如果数据库里存的是 COS `avatar_file_key`,服务端会返回短时有效的签名 URL。
|
||
- 如果数据库里仍是旧的 `avatar_url`,服务端会直接返回旧 URL。
|
||
|
||
请求头:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
成功响应(`200`):
|
||
|
||
```json
|
||
{
|
||
"avatar_url": "https://ava-1320289366.cos.ap-guangzhou.myqcloud.com/...",
|
||
"expires_in": 86400
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
|
||
- `401`:未登录或 token 无效
|
||
- `404`:用户不存在或未设置头像
|
||
|
||
## 6. 设备绑定列表
|
||
|
||
### `GET /bindings`
|
||
|
||
用途:
|
||
|
||
- 查询当前登录家长名下的全部有效绑定设备。
|
||
- 返回结果包含 `child_name`,可直接用于首页设备卡片展示。
|
||
- 返回结果按最新绑定记录优先排序。
|
||
|
||
请求头:
|
||
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
Query 参数:
|
||
|
||
- `cursor`(可选):`int >= 1`,用于向后翻页
|
||
- `limit`(可选):默认 `20`,最大 `100`
|
||
|
||
请求示例:
|
||
|
||
```
|
||
GET /bindings
|
||
GET /bindings?cursor=120&limit=20
|
||
```
|
||
|
||
成功响应(`200`):
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"device_id": "DEV-002",
|
||
"child_id": null,
|
||
"child_name": null,
|
||
"status": 1,
|
||
"bound_at": "2026-04-16T18:00:00"
|
||
},
|
||
{
|
||
"device_id": "DEV-001",
|
||
"child_id": 10,
|
||
"child_name": "小明",
|
||
"status": 1,
|
||
"bound_at": "2026-04-16T17:30:00"
|
||
}
|
||
],
|
||
"total": 2,
|
||
"next_cursor": null
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
- `device_id`:设备业务标识
|
||
- `child_id`:当前绑定儿童 ID,可为空
|
||
- `child_name`:当前绑定儿童昵称,可为空
|
||
- `status`:绑定状态,当前列表只返回有效绑定
|
||
- `bound_at`:设备绑定时间
|
||
- `next_cursor`:下一页游标,没有更多数据时为 `null`
|
||
|
||
常见错误码:
|
||
|
||
- `401`:未登录或 token 无效
|
||
- `422`:请求参数校验失败
|