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

8.8 KiB
Raw Permalink Blame History

房内贡献榜 Flutter 对接

本文描述语音房内 day/week/month 三个 tab 的贡献榜接口。客户端按当前 tab 独立请求,不再从进房、心跳或送礼接口里复用同一份榜单数据。

接口地址

本地开发地址:

http://127.0.0.1:13000
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 榜单周期。可选值:dayweekmonth
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)

请求示例:

GET /api/v1/rooms/room_123/contribution-rank?period=week&limit=20
Authorization: Bearer <access_token>
X-App-Code: lalu

返回值

统一外壳:

{
  "code": "OK",
  "message": "ok",
  "request_id": "req_xxx",
  "data": {}
}

成功返回示例:

{
  "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 服务端归一化后的周期:dayweekmonth
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/monthlimit<=0 或不是数字。
401 UNAUTHORIZED 未登录或 token 无效。
403 PROFILE_REQUIRED 登录用户未完成资料流程gateway profile gate 拦截。
403 PERMISSION_DENIED viewer 当前不在该房间,不能读取房内贡献榜。
502 UPSTREAM_ERROR room-service 或 user-service 调用失败。

失败返回示例:

{
  "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 切换或送礼后重拉榜单快照。