hyapp-server/docs/flutter对接/房内贡献榜Flutter对接.md
2026-07-06 12:53:36 +08:00

278 lines
8.8 KiB
Markdown
Raw Permalink 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.

# 房内贡献榜 Flutter 对接
本文描述语音房内 day/week/month 三个 tab 的贡献榜接口。客户端按当前 tab 独立请求,不再从进房、心跳或送礼接口里复用同一份榜单数据。
## 接口地址
本地开发地址:
```text
http://127.0.0.1:13000
```
```http
GET /api/v1/rooms/{room_id}/contribution-rank?period=day&limit=20
Authorization: Bearer <access_token>
X-App-Code: lalu
```
说明:
| 项 | 说明 |
| --- | --- |
| 鉴权 | 必须登录。gateway 使用 token 里的 `user_id` 作为 viewer。 |
| 房间校验 | viewer 必须仍在当前房间内;不在房间时返回 403。 |
| 响应外壳 | 统一使用 `{code,message,request_id,data}`。 |
| 时间单位 | 所有 `*_ms` 都是 Unix epoch milliseconds统计窗口按 UTC 计算。 |
## 参数
Path 参数:
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `room_id` | string | 是 | 房间 ID。只支持字母、数字、下划线和中横线最长 48 位。 |
Query 参数:
| 字段 | 类型 | 必填 | 默认 | 说明 |
| --- | --- | --- | --- | --- |
| `period` | string | 否 | `day` | 榜单周期。可选值:`day``week``month`。 |
| `limit` | int32 | 否 | `20` | 返回条数。必须大于 0服务端最大返回 `100`。 |
周期含义:
| `period` | 统计窗口 |
| --- | --- |
| `day` | UTC 当日 00:00:00 到次日 00:00:00区间为 `[start_at_ms, end_at_ms)`。 |
| `week` | UTC 自然周,周一 00:00:00 到下周一 00:00:00区间为 `[start_at_ms, end_at_ms)`。 |
| `month` | UTC 自然月1 日 00:00:00 到下月 1 日 00:00:00区间为 `[start_at_ms, end_at_ms)`。 |
请求示例:
```http
GET /api/v1/rooms/room_123/contribution-rank?period=week&limit=20
Authorization: Bearer <access_token>
X-App-Code: lalu
```
## 返回值
统一外壳:
```json
{
"code": "OK",
"message": "ok",
"request_id": "req_xxx",
"data": {}
}
```
成功返回示例:
```json
{
"code": "OK",
"message": "ok",
"request_id": "req_room_rank",
"data": {
"room_id": "room_123",
"period": "week",
"start_at_ms": 1780329600000,
"end_at_ms": 1780934400000,
"total": 2,
"contribution_rank": [
{
"rank": 1,
"user_id": "43",
"score": 900,
"gift_value": 900,
"updated_at_ms": 1780400001000,
"profile": {
"user_id": "43",
"username": "Luna",
"avatar": "https://cdn.example/avatar/43.png",
"display_user_id": "10043",
"pretty_id": "888888",
"pretty_display_user_id": "888888",
"gender": "female",
"age": 22,
"country": "US",
"country_name": "United States",
"country_display_name": "United States",
"country_flag": "https://cdn.example/flags/us.png",
"vip": {},
"level": {},
"level_badges": {},
"badges": [],
"avatar_frame": {},
"profile_card": {},
"vehicle": {},
"mic_seat_animation": {},
"charm": 0
}
},
{
"rank": 2,
"user_id": "44",
"score": 520,
"gift_value": 520,
"updated_at_ms": 1780390001000,
"profile": {
"user_id": "44",
"username": "Mia",
"avatar": "https://cdn.example/avatar/44.png",
"display_user_id": "10044",
"gender": "",
"age": 0,
"country": "",
"country_name": "",
"country_display_name": "",
"country_flag": "",
"vip": {},
"level": {},
"level_badges": {},
"badges": [],
"avatar_frame": {},
"profile_card": {},
"vehicle": {},
"mic_seat_animation": {},
"charm": 0
}
}
],
"profiles": [
{
"user_id": "43",
"username": "Luna",
"avatar": "https://cdn.example/avatar/43.png",
"display_user_id": "10043",
"gender": "female",
"age": 22,
"country": "US",
"country_name": "United States",
"country_display_name": "United States",
"country_flag": "https://cdn.example/flags/us.png",
"vip": {},
"level": {},
"level_badges": {},
"badges": [],
"avatar_frame": {},
"profile_card": {},
"vehicle": {},
"mic_seat_animation": {},
"charm": 0
},
{
"user_id": "44",
"username": "Mia",
"avatar": "https://cdn.example/avatar/44.png",
"display_user_id": "10044",
"gender": "",
"age": 0,
"country": "",
"country_name": "",
"country_display_name": "",
"country_flag": "",
"vip": {},
"level": {},
"level_badges": {},
"badges": [],
"avatar_frame": {},
"profile_card": {},
"vehicle": {},
"mic_seat_animation": {},
"charm": 0
}
],
"server_time_ms": 1780400005000
}
}
```
`data` 字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `room_id` | string | 房间 ID。 |
| `period` | string | 服务端归一化后的周期:`day``week``month`。 |
| `start_at_ms` | int64 | 本次榜单统计窗口开始时间UTC。 |
| `end_at_ms` | int64 | 本次榜单统计窗口结束时间UTC。 |
| `total` | int64 | 当前房间、当前周期内有贡献的总用户数。 |
| `contribution_rank` | array | 当前页榜单项。空数组表示当前周期暂无贡献数据。 |
| `profiles` | array | 榜单用户的展示资料列表,顺序和 `contribution_rank` 一致。 |
| `server_time_ms` | int64 | 服务端当前时间,可用于展示更新时间。 |
`contribution_rank[]` 字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `rank` | int64 | 排名,从 1 开始。 |
| `user_id` | string | 上榜用户 IDHTTP JSON 固定按字符串解析。 |
| `score` | int64 | 榜单分值;当前等于 `gift_value`。 |
| `gift_value` | int64 | 统计窗口内该用户在本房间送礼贡献总值。 |
| `updated_at_ms` | int64 | 该用户本周期贡献记录更新时间。 |
| `profile` | object? | 当前用户展示资料。资料服务异常或用户资料缺失时可能为空。 |
`profile` / `profiles[]` 字段:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `user_id` | string | 用户长 ID。 |
| `username` | string | 昵称。 |
| `avatar` | string | 头像 URL。 |
| `display_user_id` | string | 展示 ID。 |
| `pretty_id` | string | 靓号 ID没有时为空或不返回。 |
| `pretty_display_user_id` | string | 靓号展示 ID没有时为空或不返回。 |
| `gender` | string | 性别展示值。 |
| `age` | int32 | 年龄。 |
| `country` | string | 国家码。 |
| `country_name` | string | 国家名称。 |
| `country_display_name` | string | 国家展示名。 |
| `country_flag` | string | 国家旗帜。 |
| `vip` | object | VIP 展示资料。 |
| `level` | object | 等级展示资料。 |
| `level_badges` | object | 等级徽章资料。 |
| `badges` | array | 当前佩戴徽章。 |
| `avatar_frame` | object | 当前佩戴头像框。 |
| `profile_card` | object | 当前佩戴资料卡。 |
| `vehicle` | object | 当前佩戴座驾。 |
| `mic_seat_animation` | object | 当前佩戴麦位动画。 |
| `charm` | int64 | 魅力值。 |
## 错误码
| HTTP | `code` | 场景 |
| --- | --- | --- |
| 400 | `INVALID_ARGUMENT` | `room_id` 格式错误、`period` 不是 `day/week/month``limit<=0` 或不是数字。 |
| 401 | `UNAUTHORIZED` | 未登录或 token 无效。 |
| 403 | `PROFILE_REQUIRED` | 登录用户未完成资料流程gateway profile gate 拦截。 |
| 403 | `PERMISSION_DENIED` | viewer 当前不在该房间,不能读取房内贡献榜。 |
| 502 | `UPSTREAM_ERROR` | room-service 或 user-service 调用失败。 |
失败返回示例:
```json
{
"code": "INVALID_ARGUMENT",
"message": "invalid argument",
"request_id": "req_bad_period"
}
```
## Flutter 调用规则
| 场景 | 处理 |
| --- | --- |
| 进入房间后首次展示 | `POST /api/v1/rooms/join` 成功、房间页建立后,请求当前默认 tab例如 `period=day`。 |
| tab 切换 | 按 `room_id + period` 单独请求本接口;不要把 day 的数据复制给 week/month。 |
| 送礼成功后 | 刷新当前展示的 `period`,或收到本地送礼成功事件后延迟刷新;不要依赖送礼接口返回榜单。 |
| 心跳 | `POST /api/v1/rooms/heartbeat` 只维护在线状态,不用它刷新榜单。 |
| 进房首包 | 新版进房继续传 `response_mode=lite`;贡献榜由本接口独立拉取。 |
| 空榜 | `contribution_rank=[]``profiles=[]``total=0` 时展示空状态。 |
## 相关 IM
本接口没有独立 IM 消息。房间内送礼动效、公屏礼物消息仍按现有送礼链路和房间 IM 事件处理;本接口只用于 Flutter 在面板打开、tab 切换或送礼后重拉榜单快照。