@tencentcloud/sdk-mcp 1.3.8 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/package.json +1 -1
  2. package/resource/doc/chatuikit/android/integration.md +466 -484
  3. package/resource/doc/chatuikit/android/workflow.md +713 -0
  4. package/resource/doc/livekit/live/flutter/live-integration.md +208 -167
  5. package/resource/doc/livekit/voice/android/voice-audience-list.md +335 -0
  6. package/resource/doc/livekit/voice/android/voice-audio-effect.md +384 -0
  7. package/resource/doc/livekit/voice/android/voice-barrage.md +569 -0
  8. package/resource/doc/livekit/voice/android/voice-co-guest-interaction.md +748 -0
  9. package/resource/doc/livekit/voice/android/voice-gift.md +833 -0
  10. package/resource/doc/livekit/voice/android/voice-host-interaction.md +728 -0
  11. package/resource/doc/livekit/voice/android/voice-integration.md +886 -0
  12. package/resource/doc/livekit/voice/android/voice-room-list.md +493 -0
  13. package/resource/doc/livekit/voice/android/workflow.md +333 -0
  14. package/resource/doc/livekit/voice/flutter/voice-audience-list.md +337 -0
  15. package/resource/doc/livekit/voice/flutter/voice-audio-effect.md +739 -0
  16. package/resource/doc/livekit/voice/flutter/voice-barrage.md +578 -0
  17. package/resource/doc/livekit/voice/flutter/voice-co-guest-interaction.md +673 -0
  18. package/resource/doc/livekit/voice/flutter/voice-gift.md +812 -0
  19. package/resource/doc/livekit/voice/flutter/voice-integration.md +925 -0
  20. package/resource/doc/livekit/voice/flutter/voice-room-list.md +842 -0
  21. package/resource/doc/livekit/voice/flutter/workflow.md +359 -0
  22. package/resource/doc/livekit/voice/ios/voice-audience-list.md +335 -0
  23. package/resource/doc/livekit/voice/ios/voice-audio-effect.md +373 -0
  24. package/resource/doc/livekit/voice/ios/voice-barrage.md +529 -0
  25. package/resource/doc/livekit/voice/ios/voice-co-guest-interaction.md +701 -0
  26. package/resource/doc/livekit/voice/ios/voice-gift.md +785 -0
  27. package/resource/doc/livekit/voice/ios/voice-host-interaction.md +820 -0
  28. package/resource/doc/livekit/voice/ios/voice-integration.md +853 -0
  29. package/resource/doc/livekit/voice/ios/voice-room-list.md +467 -0
  30. package/resource/doc/livekit/voice/ios/workflow.md +358 -0
  31. package/resource/doc/livekit/voice/uni-app/voice-audience-list.md +264 -0
  32. package/resource/doc/livekit/voice/uni-app/voice-audio-effect.md +332 -0
  33. package/resource/doc/livekit/voice/uni-app/voice-barrage.md +482 -0
  34. package/resource/doc/livekit/voice/uni-app/voice-co-guest-interaction.md +944 -0
  35. package/resource/doc/livekit/voice/uni-app/voice-gift.md +716 -0
  36. package/resource/doc/livekit/voice/uni-app/voice-integration.md +613 -0
  37. package/resource/doc/livekit/voice/uni-app/voice-room-list.md +562 -0
  38. package/resource/doc/livekit/voice/uni-app/workflow.md +369 -0
  39. package/resource/doc/roomkit/vue/integration.md +119 -224
  40. package/resource/doc/roomkit/vue/workflow.md +472 -226
  41. package/resource/doc/tuicallkit/android/integration.md +675 -90
  42. package/resource/doc/tuicallkit/android/workflow.md +432 -0
  43. package/tools/common/present-scenario-choice.js +16 -0
  44. package/tools/common/present-scenario-choice.js.map +1 -0
  45. package/tools/definitions/get_native_call_uikit_integration_def.js +18 -2
  46. package/tools/definitions/get_native_call_uikit_integration_def.js.map +1 -1
  47. package/tools/definitions/get_native_chat_uikit_integration_def.js +29 -7
  48. package/tools/definitions/get_native_chat_uikit_integration_def.js.map +1 -1
  49. package/tools/definitions/get_native_live_uikit_integration_def.js +65 -40
  50. package/tools/definitions/get_native_live_uikit_integration_def.js.map +1 -1
  51. package/tools/definitions/get_native_live_uikit_interaction_def.js +42 -94
  52. package/tools/definitions/get_native_live_uikit_interaction_def.js.map +1 -1
  53. package/tools/definitions/get_web_room_feature_detail_def.js +29 -32
  54. package/tools/definitions/get_web_room_feature_detail_def.js.map +1 -1
  55. package/tools/definitions/get_web_room_uikit_integration_def.js +25 -9
  56. package/tools/definitions/get_web_room_uikit_integration_def.js.map +1 -1
  57. package/tools/definitions/present_scenario_choice_def.js +53 -0
  58. package/tools/definitions/present_scenario_choice_def.js.map +1 -0
  59. package/tools/definitions/record_prompt_def.js +6 -1
  60. package/tools/definitions/record_prompt_def.js.map +1 -1
  61. package/tools/definitions/record_result_def.js +20 -4
  62. package/tools/definitions/record_result_def.js.map +1 -1
  63. package/tools/index.js +2 -0
  64. package/tools/index.js.map +1 -1
  65. package/tools/live/get-native-live-uikit-integration.js +110 -34
  66. package/tools/live/get-native-live-uikit-integration.js.map +1 -1
  67. package/tools/live/get_native_live_uikit_interaction.js +128 -35
  68. package/tools/live/get_native_live_uikit_interaction.js.map +1 -1
  69. package/utils/report-cls-client.js +1 -1
  70. package/utils/report-es-client.js +1 -1
@@ -0,0 +1,358 @@
1
+ # Native 语聊房 AtomicXCore 代码生成工作流指令 (iOS)
2
+
3
+ ## 🚨 核心原则(最高优先级)
4
+
5
+ **Agent 必须确保生成的代码可以成功编译运行,严禁将无法编译的代码交付给用户!**
6
+
7
+ ### ⚠️ 强制编译验证(必须执行,不可省略)
8
+
9
+ **🚫 严禁行为**:
10
+ - ❌ 只用 `read_lints` 检查就认为代码正确
11
+ - ❌ 用 `grep` 过滤编译输出(会导致命令被跳过)
12
+ - ❌ 跳过编译验证直接交付代码
13
+
14
+ **✅ 唯一正确的验证方式**:
15
+
16
+ ```bash
17
+ # 步骤 1: 安装依赖(如需要)
18
+ cd <项目目录> && pod install
19
+
20
+ # 步骤 2: 编译验证(使用 tail 限制输出)
21
+ cd <项目目录> && xcodebuild build \
22
+ -scheme <SchemeName> \
23
+ -workspace <WorkspaceName>.xcworkspace \
24
+ -destination 'generic/platform=iOS' \
25
+ CODE_SIGNING_ALLOWED=NO 2>&1 | tail -150
26
+ ```
27
+
28
+ **判断标准**:
29
+ - ✅ 输出包含 `BUILD SUCCEEDED` → 编译通过,可交付
30
+ - ❌ 输出包含 `BUILD FAILED` 或 `error:` → 必须修复后重新编译
31
+
32
+ **常见错误与修复**:
33
+ | 错误关键字 | 原因 | 修复方式 |
34
+ |-----------|------|---------|
35
+ | `No such module 'xxx'` | Pod 依赖缺失 | 添加到 Podfile 后执行 `pod install` |
36
+ | `Cannot find 'xxx' in scope` | Import 缺失 | 添加 `import xxx` |
37
+ | `Use of unresolved identifier` | API 名称错误 | 查阅文档确认正确 API |
38
+ | `NSMicrophoneUsageDescription` | Info.plist 权限缺失 | 添加权限描述 |
39
+
40
+ **验证循环(必须遵守)**:
41
+ ```
42
+ 执行编译 → 失败 → 分析错误 → 修复代码 → 重新执行编译 → ... → BUILD SUCCEEDED → 交付
43
+ ```
44
+
45
+ ---
46
+
47
+ ## 📋 指令目的与架构
48
+
49
+ 为 Agent 提供实现 Native (iOS) 语聊房 AtomicXCore 核心功能的**代码生成蓝图**。
50
+
51
+ **核心架构**:
52
+ * **麦位管理**:`LiveSeatStore` (麦位数据驱动)
53
+ * **状态**:`LiveSeatState` / `SeatInfo` / `SeatUserInfo`
54
+ * **事件**:`Publisher` (Combine 订阅)
55
+
56
+ **语聊房 vs 视频直播的核心差异**:
57
+ | 特性 | 视频直播 | 语聊房 |
58
+ |------|---------|-------|
59
+ | 核心组件 | `LiveCoreView` | `LiveSeatStore` |
60
+ | 媒体类型 | 音视频流 | 纯音频(麦位) |
61
+ | 画面 | 视频画面 | 麦位头像 + 音浪动画 |
62
+ | 核心概念 | 推流/拉流 | 麦位(seatList) |
63
+
64
+ **功能依赖逻辑(重要)**:
65
+ 1. **基础先行**:必须先使用本工具(`get_native_voice_uikit_integration`)完成基础语聊房(房主开播/观众进房/房间列表)。
66
+ 2. **互动叠加**:如果用户需求包含"上麦"、"连线"、"观众列表",必须**在基础功能完成后**,再调用互动工具(`get_native_voice_uikit_interaction`)。
67
+ 3. **空项目处理**:若用户在空项目中直接请求互动功能,Agent **必须先实现基础功能**,再添加互动能力。
68
+
69
+ ---
70
+
71
+ ## ⚙️ 自动化工作流步骤(必须创建为 TODO 任务)
72
+
73
+ **🚨 Agent 必须将以下步骤创建为 TODO 任务列表,逐一完成并打勾:**
74
+
75
+ ### 步骤 1: 前置准备
76
+ 1. **生成凭证**:调用 `get_usersig` 工具生成测试凭证。
77
+ * 房主: `host001`, `host002`, `host003`
78
+ * 观众: `user001`, `user002`, `user003`
79
+ 2. **环境检查**:检查 `Podfile`,若缺失以下依赖则自动添加:
80
+ ```ruby
81
+ pod 'AtomicXCore'
82
+ ```
83
+ 3. **权限注入**:在 `Info.plist` 中添加麦克风权限描述(语聊房不需要摄像头权限):
84
+ ```xml
85
+ <key>NSMicrophoneUsageDescription</key>
86
+ <string>需要访问您的麦克风权限,开启后才能进行语音互动</string>
87
+ ```
88
+
89
+ ### 步骤 2: 代码生成
90
+ **必须优先且唯一**使用本工具返回的**实时文档内容**生成代码。
91
+ * **仅房主**:生成 `HostViewController`
92
+ * **仅观众**:生成 `AudienceViewController`
93
+ * **房主+观众**:生成 `MainViewController` (入口选择) + `HostViewController` + `AudienceViewController`
94
+
95
+ ### 步骤 3: 🚨 编译验证(强制执行,不可跳过)
96
+ **此步骤必须作为独立 TODO 任务执行,不能省略或合并!**
97
+
98
+ **执行命令**:
99
+ ```bash
100
+ cd <项目目录>/ios && pod install && \
101
+ xcodebuild build -scheme <SchemeName> -workspace <WorkspaceName>.xcworkspace \
102
+ -destination 'platform=iOS Simulator,name=iPhone 16' \
103
+ CODE_SIGNING_ALLOWED=NO 2>&1 | tail -150
104
+ ```
105
+
106
+ **判断与处理**:
107
+ * 输出包含 **BUILD SUCCEEDED** → 进入步骤 4
108
+ * 输出包含 **BUILD FAILED** 或 **error:** → 分析错误 → 修复代码 → **重新执行本命令**,循环直到成功
109
+
110
+ ### 步骤 4: 交付结果
111
+ 确认编译通过后,向用户交付代码。
112
+
113
+ ---
114
+
115
+ ## 🚫 代码生成约束(严格遵守)
116
+
117
+ ### 1. 通用代码约束
118
+ * **严禁修改 Import**:文档中的 import 路径经过验证,绝对不可修改。
119
+ * **严禁臆造 API**:如果文档没写,绝对不能自己发明方法名或参数名。
120
+ * **必须查阅 API 文档**:涉及数据模型字段(如 `SeatInfo`、`SeatUserInfo`),必须查看文档确认字段名(例如确认是 `userInfo.userName` 而不是 `name`)。
121
+
122
+ ### 2. 🧩 Store 与 Publisher 管理约束(生命周期安全)
123
+ **核心原因**:SDK 使用 Combine 的 `Publisher` 进行状态订阅。不正确的生命周期管理会导致监听失效或内存泄漏。
124
+
125
+ * **订阅管理原则**:所有 `AnyCancellable` **必须声明为 ViewController 的成员变量** `cancellableSet`。
126
+ * **严禁忽略返回值**:禁止不存储 `.sink {}` 返回的 `AnyCancellable`。
127
+ * **成对原则**:在 `viewDidLoad` 中设置订阅,订阅会随 `cancellableSet` 在 `deinit` 时自动释放。
128
+
129
+ ### 3. ⏱️ 超时时间限制(关键技术点)
130
+ **必须严格遵守以下参数限制,优先使用文档示例中的值:**
131
+
132
+ #### A. 观众上麦 (`CoGuestStore`)
133
+ * **规则**:
134
+ * 可选参数,不填则不检查超时。
135
+ * 若填写,范围必须在 **5 - 1800 秒**之间。
136
+ * **正确示例**:
137
+ ```swift
138
+ // ✅ 推荐:跟随文档示例(如 30秒)
139
+ CoGuestStore.shared.applyForSeat(seatIndex: -1, timeout: 30) { ... }
140
+ // ✅ 合法:不检查超时
141
+ CoGuestStore.shared.applyForSeat(seatIndex: -1, timeout: 0) { ... }
142
+ ```
143
+ * **错误示例**:❌ `timeout: 3` (太短),❌ `timeout: 2000` (太长)。
144
+
145
+ #### B. 房主连线 (`CoHostStore`)
146
+ * **规则**:
147
+ * **最大值 30 秒**(后台硬限制)。
148
+ * **正确示例**:
149
+ ```swift
150
+ // ✅ 推荐:使用最大值
151
+ CoHostStore.shared.requestHostConnection(..., timeout: 30) { ... }
152
+ ```
153
+ * **错误示例**:❌ `timeout: 60` (会导致请求失败)。
154
+
155
+ ### 4. 🎨 扩展功能约束(音效/弹幕/礼物/UI)
156
+
157
+ #### A. 音效 (Audio Effect)
158
+ * **变声枚举 (`AudioChangerType`)**:
159
+ * ✅ **允许**:`.child, .littleGirl, .man, .ethereal` 等标准枚举。
160
+ * ❌ **禁止**:`.uncle, .loli, .girl, .boy` (这些是旧版或错误的枚举)。
161
+ * **混响枚举 (`AudioReverbType`)**:
162
+ * ✅ **允许**:`.ktv, .smallRoom, .metallic` 等。
163
+ * ❌ **禁止**:`.room, .hall, .low`。
164
+
165
+ #### B. 麦位 UI 布局
166
+ * **布局要求**:麦位使用 `UICollectionView` + `UICollectionViewFlowLayout` 展示,通常 4x2 或 3x3 布局。
167
+ * **麦位状态**:
168
+ * 空麦位:显示占位图标(如 `+` 号)
169
+ * 有人麦位:显示用户头像 + 昵称
170
+ * 正在说话:头像边框高亮或显示音浪动画
171
+ * 麦位锁定:显示锁定图标
172
+ * **音浪动画**:订阅 `LiveSeatState.speakingUsers` 获取正在说话的用户和音量。
173
+
174
+ #### C. 弹幕与礼物布局 (Barrage & Gift)
175
+ * **层级要求**:弹幕列表和全屏礼物动画必须使用 `UIView` 覆盖在麦位区域**之上**。
176
+ * **禁止分割**:严禁将屏幕分割为"上麦位、下弹幕",必须是叠加模式。
177
+
178
+ ##### 弹幕输入框 (Barrage Input)
179
+ * **位置**:固定在屏幕底部左侧,与功能按钮(礼物、申请上麦等)同行。
180
+ * **样式**:半透明圆角背景 + 占位文字「说点什么...」。
181
+ * **键盘适配**:
182
+ * 键盘弹起时,输入框**保持原位置不变**,禁止随键盘上移。
183
+ * 麦位区域约束固定为 `edges.equalToSuperview()`,禁止变形或上移。
184
+ * **严禁**使用 `UIScrollView.contentInsetAdjustmentBehavior` 或自动调整约束。
185
+
186
+ ##### 弹幕显示流 (Barrage Display Flow)
187
+ ```
188
+ 发送弹幕:
189
+ 用户输入 → 点击发送/回车 → BarrageStore.sendTextMessage(text) → 本地立即插入弹幕列表
190
+
191
+ 接收弹幕:
192
+ 订阅 BarrageStore.barrageState.$barrageList → 收到新消息 → 插入弹幕列表 → 滚动到底部
193
+ ```
194
+ * **数据源**:订阅 `BarrageStore.shared.barrageState.$barrageList`。
195
+ * **本地回显**:发送成功后**立即**在本地弹幕列表插入,无需等待服务器回调。
196
+ * **滚动行为**:新消息到达时自动滚动到底部(`scrollToRow(at: lastIndex, animated: true)`)。
197
+ * **消息格式**:`[昵称]: [消息内容]`,昵称使用主题色,内容使用白色。
198
+
199
+ * **礼物弹幕 (Gift Barrage)**:**如果用户需要集成礼物弹幕**,`onReceiveGift` 事件触发时,**房主端和观众端**都必须在弹幕列表(Message List)中插入礼物消息。严禁仅在观众端显示礼物文本。
200
+
201
+ ##### 全屏礼物动画 (Full-screen Gift Animation)
202
+ **⚠️ 必须实现**:礼物功能集成时,全屏礼物动画是**强制要求**,不可省略。
203
+
204
+ * **层级**:全屏礼物动画视图必须覆盖在麦位区域**之上**,使用独立的 `UIView` 容器。
205
+ * **布局**:约束为 `edges.equalToSuperview()`,覆盖整个屏幕。
206
+ * **双端同步**:收到 `GiftStore.onReceiveGift` 回调后,**房主端和观众端**都必须播放全屏动画。严禁只在观众端播放。
207
+
208
+ ### 🎨 默认 UI/UX 设计与交互规范 (仅在用户未指定时生效)
209
+
210
+ **⚠️ 注意:以下规范仅在用户未提供具体 UI 设计图或需求时作为默认标准执行。**
211
+
212
+ ### 1. 全局视觉风格 (Global Aesthetics)
213
+ * **沉浸式暗黑**:语聊房页背景必须为 `.black` 或深色渐变。
214
+ * **安全区域**:所有悬浮 UI 必须约束在 `safeAreaLayoutGuide` 内部,严禁被刘海屏或底部 Home 条遮挡。
215
+ * **文字可读性**:深色背景上的白色文字(如弹幕、ID)必须添加**黑色阴影** (`shadowColor = .black, offset = 0x1`)。
216
+ * **错误提示**:统一使用 **Toast**,禁止使用模态 Alert 打断用户。
217
+
218
+ ### 2. 通用组件规范 (Component Standards)
219
+ * **顶部胶囊 (Glass Capsule)**:
220
+ * **样式**:**磨砂玻璃背景** (`UIBlurEffect.dark`) + **全圆角**。
221
+ * **应用**:仅用于顶部左侧展示"房主头像+ID+在线人数"。
222
+ * **通用按钮 (Flat Buttons)**:
223
+ * **样式**:**"文字 + 圆角矩形背景"**。视觉风格扁平简约,背景色为半透明黑或主题色。
224
+ * **关闭按钮**:特例,使用圆形磨砂玻璃图标。
225
+ * **弹出面板 (Floating Panels)**:
226
+ * **样式**:仅顶部大圆角 (`maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]`)。
227
+ * **禁忌**:底部禁止出现非透明的实色背景块,必须保持悬浮感。
228
+
229
+ ### 3. 语聊房布局蓝图 (Voice Room Layout)
230
+ **⚠️ 动态布局原则:仅渲染用户实际集成的功能按钮。若用户未请求某功能(如礼物/音效),严禁添加对应的空按钮**
231
+
232
+ #### A. 顶部栏 (Top Bar)
233
+ * **左侧 [房间信息]**:使用 **磨砂胶囊** 包裹 [房主头像 | 房主昵称 | 在线人数]。
234
+ * **右侧 [控制区]**:横向排列 [关闭图标(X)]。
235
+
236
+ #### B. 麦位区域 (Seat Area) - 核心展示区
237
+ * **布局方式**:使用 `UICollectionView` + `UICollectionViewFlowLayout`
238
+ * **典型布局**:
239
+ * 8 麦位:4x2 或 2x4
240
+ * 9 麦位:3x3(房主占中心或首位)
241
+ * **麦位状态展示**:
242
+ * 空麦位:圆形占位 + `+` 号图标
243
+ * 有人麦位:用户头像 + 昵称 + 麦克风状态图标
244
+ * 说话中:头像边框高亮(主题色)+ 音浪动画
245
+ * 锁定麦位:锁定图标覆盖
246
+
247
+ #### C. 底部栏 (Bottom Bar) - 根据角色动态切换
248
+ * **房主模式 (Host)**:
249
+ * **左侧**:[弹幕列表(背景透明)] + [聊天输入框]。
250
+ * **右侧**:功能阵列 [音效] [更多(管理麦位)]。
251
+ * **观众模式 (Audience)**:
252
+ * **左侧**:[弹幕列表] + [聊天输入框]。
253
+ * **右侧**:[礼物] [申请上麦]。
254
+ * **麦上用户模式 (On-Seat Audience)**:
255
+ * **左侧**:[弹幕列表] + [聊天输入框]。
256
+ * **右侧**:[礼物] [音效] [下麦]。
257
+
258
+ ### 4. 首页布局与交互 (Home Interaction)
259
+
260
+ #### A. 首页参考布局
261
+ ```
262
+ ┌─────────────────────────────┐
263
+ │ AtomicXCore 语聊房 │
264
+ │ │
265
+ │ 房间 ID │
266
+ │ ┌─────────────────────────┐│
267
+ │ │ voice_room_001 ││ ← 输入框 (带左侧 Padding, 半透明背景)
268
+ │ └─────────────────────────┘│
269
+ │ │
270
+ │ 房主开播 │
271
+ │ (点击即以 host001 登录) │
272
+ │ │
273
+ │ 观众进房 │
274
+ │ (点击即以 user001 登录) │
275
+ │ │
276
+ │ [ 📋 房间列表 ] │
277
+ └─────────────────────────────┘
278
+ ```
279
+
280
+ #### B. 隐式登录流程
281
+ **首页不需要单独的登录按钮**,登录在点击功能按钮时自动完成:
282
+ * 点击「房主开播」→ 使用 `host001` 登录 → 跳转房主页。
283
+ * 点击「观众进房」→ 使用 `user001` 登录 → 跳转观众页。
284
+ * 点击「房间列表」→ 使用 `user001` 登录 → 跳转列表页。
285
+
286
+ ---
287
+
288
+ ## 🎯 功能实现细节
289
+
290
+ ### 1. 房主开播 (`host_streaming`)
291
+ * **核心**:`LiveListStore.shared.createLive()` + `LiveSeatStore`
292
+ * **流程**:
293
+ 1. 创建房间:`LiveListStore.shared.createLive(roomId, roomName, ...)`
294
+ 2. 初始化麦位:`LiveSeatStore.shared`
295
+ 3. 房主自动上 0 号麦位
296
+ * **销毁**:`deinit` 或退出页面时必须调用 `endLive()`。
297
+
298
+ ### 2. 观众进房 (`audience_join`)
299
+ * **核心**:`LiveListStore.shared.joinLive()` + `LiveSeatStore`
300
+ * **流程**:
301
+ 1. 加入房间:`LiveListStore.shared.joinLive(liveId)`
302
+ 2. 订阅麦位:`LiveSeatStore.shared.liveSeatState.$seatList`
303
+ * **销毁**:`deinit` 或退出页面时必须调用 `leaveLive()`。
304
+
305
+ ### 3. 房间列表 (`room_list`)
306
+ * **核心**:`LiveListStore.shared.fetchLiveList()` + `UITableView/UICollectionView`
307
+ * **数据**:订阅 `liveState.liveList`。
308
+ * **跳转**:点击列表项跳转观众页,传递 `liveID`。
309
+
310
+ ### 4. 上麦与麦位管理交互规范 (`co_guest`)
311
+
312
+ #### A. 观众申请上麦(房主被动接收)
313
+ * **房主端 UI**:❌ **严禁**在底部工具栏或任何位置显示「上麦申请」列表按钮。
314
+ * **交互逻辑**:当收到观众上麦申请回调时,直接在屏幕中心弹出对话框(`UIAlertController`):
315
+ * **标题**:上麦申请
316
+ * **内容**:收到观众 [昵称] 的上麦申请,是否接受?
317
+ * **操作**:[拒绝] [接受]
318
+
319
+ #### B. 麦位管理面板(房主点击麦位弹出)
320
+ * **展现形式**:使用底部浮层面板(`UIView` 动画升起)。
321
+ * **功能列表**:
322
+ * 邀请上麦(空麦位)
323
+ * 踢下麦位(有人麦位)
324
+ * 禁言/解禁(有人麦位)
325
+ * 锁定/解锁麦位
326
+
327
+ ---
328
+
329
+ ## 📋 Agent 最终检查清单
330
+
331
+ ### 🚨 必做项(缺一不可)
332
+ - [ ] **🔴 编译验证**:已执行以下命令且输出包含 **BUILD SUCCEEDED**(此项必须在 TODO 任务中明确列出)
333
+ ```bash
334
+ xcodebuild build -scheme <项目名> -workspace <项目名>.xcworkspace -destination 'generic/platform=iOS' CODE_SIGNING_ALLOWED=NO 2>&1 | grep -E "(error:|warning:.*\.swift|BUILD SUCCEEDED|BUILD FAILED)" | head -30
335
+ ```
336
+ - [ ] **凭证注入**:已调用 `get_usersig` 生成测试凭证
337
+ - [ ] **依赖完整**:已检查 `Podfile` 和 Info.plist 权限
338
+
339
+ ### 代码质量检查
340
+ - [ ] **API 准确性**:未修改 Import,未臆造 API,已核对 `SeatInfo`/`SeatUserInfo` 字段名。
341
+ - [ ] **超时合规**:上麦超时 5-1800s,连线超时 ≤30s。
342
+ - [ ] **扩展合规**:音效枚举正确,弹幕布局覆盖且键盘适配。
343
+ - [ ] **礼物合规**:房主和观众端均实现了全屏礼物动画显示。
344
+ - [ ] **麦位合规**:正确订阅 `seatList` 和 `speakingUsers`,实现音浪动画。
345
+
346
+ ---
347
+
348
+ ## 🚨 安全提醒(代码注释模板)
349
+
350
+ ```swift
351
+ /**
352
+ * ⚠️ 测试凭证说明
353
+ * - 当前 userSig 由开发工具自动生成,有效期 7 天
354
+ * - ❌ 生产环境严禁在客户端生成 userSig
355
+ * - ✅ 正式上线前必须在后端服务生成
356
+ * - 参考: https://cloud.tencent.com/document/product/647/17275
357
+ */
358
+ ```
@@ -0,0 +1,264 @@
1
+ `LiveAudienceState` 是 `AtomicXCore` 中专门负责管理语聊房观众信息的模块。通过 `LiveAudienceState`,您可以为您的直播应用构建一套完整的观众列表及管理系统。
2
+
3
+ ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100028028022/ef4d5ed8bbbf11f085a55254007c27c5.png)
4
+
5
+
6
+ ## 核心功能
7
+ - **实时观众列表**:获取并展示当前在语聊房内的所有观众信息。
8
+
9
+ - **观众人数统计**:实时获取当前语聊房的准确观众总数。
10
+
11
+ - **观众动态监听**:通过事件订阅,实时感知观众的加入和离开。
12
+
13
+ - **管理员权限**:主播可以将普通观众设为管理员,或撤销其管理员身份。
14
+
15
+ - **房间管理**:主播或管理员可以将任意普通观众请出(踢出)语聊房。
16
+
17
+
18
+ ## 实现步骤
19
+
20
+ ### 步骤1:组件集成
21
+
22
+ 请参考 [开始直播](https://write.woa.com/document/191127271985012736) 集成 **AtomicXCore**,完成接入。
23
+
24
+ ### 步骤2:初始化并获取观众列表
25
+
26
+ 获取一个与当前语聊房 liveID 绑定的 `LiveAudienceState` 实例,并主动拉取一次当前的观众列表,用于首次展示。
27
+ ``` typescript
28
+ import { useLiveAudienceState } from "@/uni_modules/tuikit-atomic-x/state/LiveAudienceState";
29
+ import { onMounted, watch } from 'vue';
30
+
31
+ // liveID 是语聊房的唯一标识
32
+ const liveID = 'your_live_id'; // 替换为实际的语聊房 liveID
33
+
34
+ // 通过 liveID 获取 LiveAudienceState 的实例
35
+ const { fetchAudienceList, audienceList } = useLiveAudienceState(liveID)
36
+
37
+ onMounted(() => {
38
+ fetchAudienceList({
39
+ liveID: 'xxx', // 当前语聊房的 liveID
40
+ success: () => {
41
+ // 成功后,响应式数据会自动更新
42
+ console.log('首次拉取观众列表成功')
43
+ },
44
+ fail: (error) => {
45
+ console.log('首次拉取观众列表失败', error)
46
+ }
47
+ })
48
+ })
49
+
50
+ // 监听 audienceList 的实时变更,用于驱动 UI 变更
51
+ watch(audienceList, (newVal, oldVal) => {
52
+ console.log(newVal)
53
+ })
54
+
55
+ // ... 后续代码
56
+ ```
57
+
58
+ ### 步骤3:监听观众列表状态与实时动态
59
+
60
+ 订阅和监听 `audienceState` 的 `event` 和 `响应式数据`,用来接收全量列表快照和实时的观众进出事件,从而驱动 UI 更新。
61
+ ``` typescript
62
+ import { useLiveAudienceState } from "@/uni_modules/tuikit-atomic-x/state/LiveAudienceState";
63
+ import { onMounted, watch } from 'vue';
64
+
65
+ const liveID = 'your_live_id'; // 替换为实际的语聊房 liveID
66
+ //通过 liveID 获取 LiveAudienceState 的实例
67
+ const { audienceList, audienceCount, addAudienceListener, removeAudienceListener } = useLiveAudienceState(liveID)
68
+
69
+ // 监听 audienceList 的实时变更,用于驱动 UI 更新
70
+ watch(audienceList, (newVal, oldVal) => {
71
+ console.log(newVal)
72
+ })
73
+
74
+ // 监听 audienceCount 的实时变更,用于驱动 UI 更新
75
+ watch(audienceCount, (newVal, oldVal) => {
76
+ console.log(newVal)
77
+ })
78
+
79
+ onMounted(() => {
80
+ addAudienceListener( liveID, 'onAudienceJoined',
81
+ { callback: (event) => {
82
+ const newAudience = JSON.parse(event)
83
+ console.log("观众 ${newAudience.userName} 加入了语聊房")
84
+ }
85
+ })
86
+
87
+ addAudienceListener( liveID, 'onAudienceLeft',
88
+ { callback: (event) => {
89
+ const departedAudience = JSON.parse(event)
90
+ console.log("观众 ${departedAudience.userName} 离开了语聊房")
91
+ }
92
+ })
93
+ })
94
+ ```
95
+
96
+ ### 步骤4:管理观众(踢人与设置管理员)
97
+
98
+ 作为主播或管理员,对语聊房内的观众进行管理操作。
99
+
100
+ #### 4.1 将观众踢出语聊房
101
+
102
+ 调用 `kickUserOutOfRoom` 接口可以将指定用户请出语聊房。
103
+ ``` typescript
104
+ import { useLiveAudienceState } from "@/uni_modules/tuikit-atomic-x/state/LiveAudienceState";
105
+
106
+ // liveID 是语聊房的唯一标识
107
+ const liveID = 'your_live_id'; // 替换为实际的语聊房 liveID
108
+
109
+ //通过 liveID 获取 LiveAudienceState 的实例
110
+ const { kickUserOutOfRoom } = useLiveAudienceState(liveID)
111
+
112
+ const kickOut = () => {
113
+ kickUserOutOfRoom({
114
+ liveID: 'xxx', // 当前语聊房的 liveID
115
+ userID: 'xxx', // 想要踢出成员的 userID
116
+ success: () => {
117
+ console.log("成功将用户 ${userID} 踢出房间")
118
+ // 踢出成功后,您会收到 onAudienceLeft 事件
119
+ },
120
+ fail: (error) => {
121
+ console.log("将用户 ${userID} 踢出房间失败", error)
122
+ }
123
+ })
124
+ }
125
+ ```
126
+
127
+ #### 4.2 设置/撤销管理员
128
+
129
+ 通过 `setAdministrator` 和 `revokeAdministrator` 接口可以管理用户的管理员身份。
130
+ ``` typescript
131
+ import { useLiveAudienceState } from "@/uni_modules/tuikit-atomic-x/state/LiveAudienceState";
132
+
133
+ // liveID 是语聊房的唯一标识
134
+ const liveID = 'your_live_id'; // 替换为实际的语聊房 liveID
135
+
136
+ //通过 liveID 获取 LiveAudienceState 的实例
137
+ const { setAdministrator, revokeAdministrator } = useLiveAudienceState(liveID)
138
+
139
+ // 将用户设为管理员
140
+ const promoteToAdmin = () => {
141
+ setAdministrator({
142
+ liveID: 'xxx', // 当前语聊房的 liveID
143
+ userID: 'xxx', // 想要设为管理员的 userID
144
+ success: () => {
145
+ console.log("成功将用户 ${userID} 设为管理员")
146
+ },
147
+ fail: (error) => {
148
+ console.log("将用户 ${userID} 设为管理员失败", error)
149
+ }
150
+ })
151
+ }
152
+
153
+ // 撤销用户的管理员身份
154
+ const revokeAdmin = () => {
155
+ revokeAdministrator({
156
+ liveID: 'xxx', // 当前语聊房的 liveID
157
+ userID: 'xxx', // 想要撤销管理员的 userID
158
+ success: () => {
159
+ console.log("成功将用户 ${userID} 的管理员身份撤销")
160
+ },
161
+ fail: (error) => {
162
+ console.log("将用户 ${userID} 设为管理员身份撤销失败", error)
163
+ }
164
+ })
165
+
166
+ }
167
+ ```
168
+
169
+ ## 功能进阶
170
+
171
+ ### 在弹幕区展示观众入场欢迎语
172
+
173
+ 当有新观众进入语聊房时,弹幕/聊天区域会在本地自动显示一条欢迎消息,例如:“欢迎 [用户昵称] 进入语聊房”。
174
+
175
+ #### 实现方式
176
+
177
+ 我们通过订阅 `LiveAudienceState` 的观众加入事件( `'onAudienceJoined'` )来获取新观众加入的实时通知。一旦事件触发,我们便提取出新观众的昵称信息,然后立即调用 `BarrageState` 的本地插入接口 `appendLocalTip`。
178
+ ``` typescript
179
+ import { useLiveAudienceState } from "@/uni_modules/tuikit-atomic-x/state/LiveAudienceState";
180
+ import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
181
+ import { onMounted } from 'vue';
182
+
183
+ // liveID 是语聊房的唯一标识
184
+ const liveID = 'your_live_id'; // 替换为实际的语聊房 liveID
185
+
186
+ //通过 liveID 获取 LiveAudienceState 的实例
187
+ const { addAudienceListener, removeAudienceListener } = useLiveAudienceState(liveID)
188
+ //通过 liveID 获取 BarrageState 的实例
189
+ const { appendLocalTip } = useBarrageState(liveID)
190
+
191
+ onMounted(() => {
192
+ addAudienceListener(liveID, 'onAudienceJoined',
193
+ { callback: (event) => {
194
+ const newAudience = JSON.parse(event)
195
+ // 创建一条本地提示消息
196
+ let welcomeTip = {}
197
+ welcomeTip.liveID = liveID,
198
+ welcomeTip.sender = { userID: 'xxx' },
199
+ welcomeTip.sequence = Date.now(),
200
+ welcomeTip.timestampInSecond = Date.now(),
201
+ welcomeTip.messageType = 'TEXT',
202
+ welcomeTip.textContent = "欢迎 ${newAudience.userName} 进入语聊房!"
203
+ // 调用 BarrageStore 的接口将其插入弹幕列表
204
+ appendLocalTip(welcomeTip)
205
+ console.log("观众 ${newAudience.userName} 加入了语聊房")
206
+ }
207
+ })
208
+ })
209
+ ```
210
+
211
+ ## API 文档
212
+
213
+ 关于 [LiveAudienceState](https://liteav.sdk.qcloud.com/doc/product/tuikit/atomic-x/uni-app/zh/v1.0/api/index.html#module-LiveAudienceState) 及其相关类的所有公开接口、属性和方法的详细信息,请参阅随 [AtomicXCore](https://write.woa.com/document/192223419814899712) 框架的官方 API 文档。本文档使用到的相关 State 如下:
214
+ <table>
215
+ <tr>
216
+ <td rowspan="1" colSpan="1" >**State**</td>
217
+
218
+ <td rowspan="1" colSpan="1" >**功能描述**</td>
219
+
220
+ <td rowspan="1" colSpan="1" >**API 文档**</td>
221
+ </tr>
222
+
223
+ <tr>
224
+ <td rowspan="1" colSpan="1" >LiveAudienceState</td>
225
+
226
+ <td rowspan="1" colSpan="1" >观众管理:获取实时观众列表(ID / 名称 / 头像),统计观众数量,监听观众进出事件。</td>
227
+
228
+ <td rowspan="1" colSpan="1" >[API 文档](https://liteav.sdk.qcloud.com/doc/product/tuikit/atomic-x/uni-app/zh/v1.0/api/index.html#module-LiveAudienceState)</td>
229
+ </tr>
230
+
231
+ <tr>
232
+ <td rowspan="1" colSpan="1" >BarrageState</td>
233
+
234
+ <td rowspan="1" colSpan="1" >弹幕功能:发送文本 / 自定义弹幕,维护弹幕列表,实时监听弹幕状态。</td>
235
+
236
+ <td rowspan="1" colSpan="1" >[API 文档](https://liteav.sdk.qcloud.com/doc/product/tuikit/atomic-x/uni-app/zh/v1.0/api/index.html#module-BarrageState)</td>
237
+ </tr>
238
+ </table>
239
+
240
+
241
+ ## 常见问题
242
+
243
+ ### `LiveAudienceState` 中的在线人数(`audienceCount`)是如何更新的?时机和频率是怎样的?
244
+
245
+ `audienceCount` 的更新并非总是实时的,其机制如下:
246
+ - **主动进出房间**:当用户主动加入或正常退出语聊房时,在线人数的变更通知会即时触发。您会很快在 `LiveAudienceState` 中观察到 `audienceCount` 的变化。
247
+
248
+ - **异常掉线**:当用户因网络问题、应用崩溃等原因异常掉线时,系统需要通过心跳机制来判断其真实状态。只有当该用户连续 90 秒没有心跳后,系统才会判定其为离线,并触发人数变更通知。
249
+
250
+ - **更新机制与频率控制:**
251
+
252
+ - 无论是即时触发还是延迟触发,所有的人数变更通知都是以消息的形式在房间内广播的。
253
+
254
+ - 房间内每秒的消息总量有上限,单房间消息频控是**每秒 40 条消息**。
255
+
256
+ - **关键点:**在“弹幕风暴”或礼物刷屏等消息流量极高的场景下,如果房间内的消息速率超过了 40条/秒 的阈值,为了保证核心消息(例如弹幕)的送达,**人数变更的消息可能会被频控策略丢弃**。
257
+
258
+
259
+ **这对开发者意味着什么?**
260
+
261
+
262
+ `audienceCount` 是一个非常接近实时的**高精度估算值**,但在极端高并发场景下,它可能存在短暂的延迟或数据丢失。因此,我们建议您将其用于 **UI 展示**,而不应作为计费、统计等需要绝对精准场景的唯一依据。
263
+
264
+