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

164 lines
6.5 KiB
Markdown
Raw 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 对接
## 1. 接口职责
个人信息页通过本接口判断被查看用户当前是否占用语音房麦位,并取得可直接交给统一进房入口的房间信息。
- 上麦事实只来自 `room-service` 当前 Room Cell 快照不要用用户是否为房主、房间搜索结果、IM 本地状态或历史缓存推断。
- 接口返回的是带时间戳的瞬时快照;点击 Live 后仍以 `POST /api/v1/rooms/join` 的实时校验为准。
- 当前接口仅用于客态个人信息页。请求中包含当前登录用户本人时,该项固定返回 `not_on_mic`
## 2. 请求
```http
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_id``app_code``request_id` 由 gateway 从登录态和请求上下文注入,客户端不能提交。
- 接口要求有效登录态且用户已完成资料。
## 3. 成功响应
```json
{
"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_mic``not_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_id``owner_user_id` 一致。
- `locked=true` 表示密码房;点击后继续复用现有密码输入和进房流程,不能在个人页自行索取或缓存密码。
## 4. Flutter 展示和刷新规则
只有下面四个条件全部成立时显示 Live
```dart
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页面其他内容继续展示 |
示例:
```json
{
"code": "INVALID_USER_IDS",
"message": "invalid user ids",
"request_id": "req_xxx"
}
```
排障日志只记录接口路径、目标 ID 数量、响应业务码和 `request_id`;不要记录 access token 或密码房密码。
## 7. 联调清单
- 未进房、只在房内未上麦:不显示 Live。
- 在自己的房间或其他人的房间实际占麦:显示 Live并返回实际所在房间。
- `pending_publish``publishing`:都显示 Live。
- 下麦、离房、被踢或关房后重新请求:返回 `not_on_mic`
- 密码房:显示 Live点击后进入既有密码流程。
- viewer 被目标房间封禁、跨 App、查询本人不返回房间定位。
- 一批中混合上麦、未上麦和重复用户:每个去重用户一条结果,顺序稳定。
- 查询成功后立即下麦:点击仍以正式进房接口结果为准。