hyapp-server/docs/flutter对接/个人信息页用户上麦状态Flutter对接.md
2026-07-17 16:55:22 +08:00

6.5 KiB
Raw Blame History

个人信息页用户上麦状态 Flutter 对接

1. 接口职责

个人信息页通过本接口判断被查看用户当前是否占用语音房麦位,并取得可直接交给统一进房入口的房间信息。

  • 上麦事实只来自 room-service 当前 Room Cell 快照不要用用户是否为房主、房间搜索结果、IM 本地状态或历史缓存推断。
  • 接口返回的是带时间戳的瞬时快照;点击 Live 后仍以 POST /api/v1/rooms/join 的实时校验为准。
  • 当前接口仅用于客态个人信息页。请求中包含当前登录用户本人时,该项固定返回 not_on_mic

2. 请求

GET /api/v1/users/voice-room-presence:batch?user_ids=163020,163021
Authorization: Bearer {access_token}
参数 类型 必填 说明
user_ids string 逗号分隔的系统 user_id,不接受展示短号

约束:

  • 去重后最多 100 个 ID响应顺序按请求中第一次出现的顺序返回。
  • 空值、非数字、0、负数、空分段或超过上限都会整批返回 INVALID_USER_IDS
  • viewer_user_idapp_coderequest_id 由 gateway 从登录态和请求上下文注入,客户端不能提交。
  • 接口要求有效登录态且用户已完成资料。

3. 成功响应

{
  "code": "OK",
  "message": "ok",
  "request_id": "req_xxx",
  "data": {
    "items": [
      {
        "user_id": "163020",
        "state": "on_mic",
        "seat_no": 3,
        "joinable": true,
        "observed_at_ms": 1784265600000,
        "room": {
          "room_id": "100086",
          "im_group_id": "100086",
          "rtc_room_id": "100086",
          "room_short_id": "886688",
          "title": "Room name",
          "owner_user_id": "12001",
          "host_user_id": "12001",
          "mode": "voice",
          "cover_url": "https://cdn.example.com/room-cover.png",
          "background_url": "https://cdn.example.com/room-bg.png",
          "online_count": 56,
          "seat_count": 10,
          "locked": true
        }
      },
      {
        "user_id": "163021",
        "state": "not_on_mic",
        "seat_no": 0,
        "joinable": false,
        "observed_at_ms": 1784265600000,
        "room": null
      }
    ],
    "server_time_ms": 1784265600123
  }
}

字段说明:

字段 类型 说明
items[].user_id string 系统用户 IDJSON 中按字符串返回
items[].state string on_micnot_on_mic
items[].seat_no int 当前麦位编号;未上麦为 0
items[].joinable bool 当前 viewer 是否允许通过该入口尝试进房
items[].observed_at_ms int64 本批状态完成判定时的 UTC epoch ms
items[].room object/null on_mic && joinable 时非空
server_time_ms int64 服务端本批响应时间UTC epoch ms

房间字段可以直接构造现有 VoiceRoomEntryArgs

  • room_id 是业务房间主键。
  • im_group_id 当前等于 room_id
  • rtc_room_id 当前使用 TRTC string room ID等于 room_id
  • 当前房间模型没有独立主持人字段,host_user_idowner_user_id 一致。
  • locked=true 表示密码房;点击后继续复用现有密码输入和进房流程,不能在个人页自行索取或缓存密码。

4. Flutter 展示和刷新规则

只有下面四个条件全部成立时显示 Live

final showLive = item.state == 'on_mic' &&
    item.joinable &&
    item.room != null &&
    item.room!.roomId.isNotEmpty;

点击时:

  1. 调用现有 VoiceRoomNavigation.open()
  2. room 构造 VoiceRoomEntryArgs
  3. entrySource 使用 profile_card_live_badge
  4. 正常调用 POST /api/v1/rooms/join;如果用户已经下麦但房间仍允许进入,可以正常进入。
  5. 进房返回房间关闭、封禁、密码错误等业务错误时,移除当前 Live 状态并按现有错误规则提示。

刷新时机:

  • 首次进入客态个人信息页。
  • App 从后台回到前台且个人信息页仍可见。
  • 从语音房返回个人信息页。
  • 用户手动刷新个人信息页。

不要轮询、持久化或使用上一次成功结果兜底。接口失败时只隐藏 Live不影响个人信息页其他资料。

5. 后端状态边界

  • on_mic 表示房间仍为 active、目标用户仍在房间在线集合中,并且占用一个当前有效麦位。MicUp 后的 pending_publish 和 RTC 已确认的 publishing 都属于已占麦。
  • 房主或管理员只有实际占用麦位时才算上麦;身份本身不算。
  • 同一 App 的 room_user_presence 使用 (app_code, user_id) 主键定位候选房间,最终状态再由 Room Cell 快照确认。
  • app_code 房间不会返回。
  • viewer 被目标房间封禁、房间已关闭、presence 已滞后或快照事实不完整时,统一返回 not_on_mic + room:null,不泄露旧房间 ID。
  • 密码房允许展示 Live返回 locked=true,正式进房仍校验密码。
  • 当前房间产品模型没有“隐藏房/隐身上麦”字段用户关系也没有资料位置黑名单能力本版不做不存在的状态推断。以后增加此类产品能力时必须在后端权限判断中收敛后再返回Flutter 不得自行判断。

6. 错误响应

HTTP code 处理方式
400 INVALID_USER_IDS 修正参数;不要重试同一请求
401 UNAUTHORIZED / ACCESS_TOKEN_EXPIRED 走现有登录或刷新 token 流程
403 PROFILE_REQUIRED 先完成用户资料
503 VOICE_ROOM_PRESENCE_UNAVAILABLE 隐藏 Live页面其他内容继续展示

示例:

{
  "code": "INVALID_USER_IDS",
  "message": "invalid user ids",
  "request_id": "req_xxx"
}

排障日志只记录接口路径、目标 ID 数量、响应业务码和 request_id;不要记录 access token 或密码房密码。

7. 联调清单

  • 未进房、只在房内未上麦:不显示 Live。
  • 在自己的房间或其他人的房间实际占麦:显示 Live并返回实际所在房间。
  • pending_publishpublishing:都显示 Live。
  • 下麦、离房、被踢或关房后重新请求:返回 not_on_mic
  • 密码房:显示 Live点击后进入既有密码流程。
  • viewer 被目标房间封禁、跨 App、查询本人不返回房间定位。
  • 一批中混合上麦、未上麦和重复用户:每个去重用户一条结果,顺序稳定。
  • 查询成功后立即下麦:点击仍以正式进房接口结果为准。