@tencentcloud/sdk-mcp 1.3.1 → 1.3.3

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 (90) hide show
  1. package/index.js +5 -1
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/resource/doc/chatuikit/faq/web_sdk/faq.md +117 -0
  5. package/resource/doc/chatuikit/flutter/client_api_Flutter.md +100 -179
  6. package/resource/doc/chatuikit/flutter/faq.md +17 -112
  7. package/resource/doc/chatuikit/flutter/integrate_tuikit_Flutter.md +272 -1281
  8. package/resource/doc/livekit/live/android/live-audience-list.md +335 -0
  9. package/resource/doc/livekit/live/android/live-audio-effect.md +384 -0
  10. package/resource/doc/livekit/live/android/live-barrage.md +569 -0
  11. package/resource/doc/livekit/live/android/live-base-beauty.md +265 -0
  12. package/resource/doc/livekit/live/android/live-co-guest-interaction.md +600 -0
  13. package/resource/doc/livekit/live/android/live-gift.md +833 -0
  14. package/resource/doc/livekit/live/android/live-host-interaction.md +810 -0
  15. package/resource/doc/livekit/live/android/live-integration.md +883 -0
  16. package/resource/doc/livekit/live/android/live-live-list.md +657 -0
  17. package/resource/doc/livekit/live/android/workflow.md +189 -0
  18. package/resource/doc/roomkit/vue/features/call-user-to-room.md +256 -0
  19. package/resource/doc/roomkit/vue/features/device-detection.md +388 -0
  20. package/resource/doc/roomkit/vue/features/device-state.md +480 -0
  21. package/resource/doc/roomkit/vue/features/free-beauty-panel.md +238 -0
  22. package/resource/doc/roomkit/vue/features/room-chat.md +427 -0
  23. package/resource/doc/roomkit/vue/features/room-participant-state.md +407 -0
  24. package/resource/doc/roomkit/vue/features/room-state.md +291 -0
  25. package/resource/doc/roomkit/vue/features/room-view.md +338 -0
  26. package/resource/doc/roomkit/vue/features/schedule-room.md +349 -0
  27. package/resource/doc/roomkit/vue/features/screen-share.md +333 -0
  28. package/resource/doc/roomkit/vue/features/virtual-background.md +281 -0
  29. package/resource/doc/roomkit/vue/features/workflow.md +553 -0
  30. package/resource/doc/roomkit/vue/integration.md +479 -0
  31. package/resource/doc/roomkit/vue/workflow.md +487 -0
  32. package/resource/doc/tuicallkit/react/api.md +16 -0
  33. package/resource/doc/tuicallkit/vue/api.md +16 -0
  34. package/tools/common/record-prompt.js +2 -2
  35. package/tools/common/record-prompt.js.map +1 -1
  36. package/tools/definitions/get_native_live_extra_features_def.js +109 -0
  37. package/tools/definitions/get_native_live_extra_features_def.js.map +1 -0
  38. package/tools/definitions/get_native_live_interaction_def.js +115 -0
  39. package/tools/definitions/get_native_live_interaction_def.js.map +1 -0
  40. package/tools/definitions/get_native_live_uikit_integration_def.js +50 -0
  41. package/tools/definitions/get_native_live_uikit_integration_def.js.map +1 -0
  42. package/tools/definitions/get_web_live_uikit_integration_def.js +1 -1
  43. package/tools/definitions/get_web_room_feature_detail_def.js +95 -0
  44. package/tools/definitions/get_web_room_feature_detail_def.js.map +1 -0
  45. package/tools/definitions/get_web_room_uikit_integration_def.js +44 -0
  46. package/tools/definitions/get_web_room_uikit_integration_def.js.map +1 -0
  47. package/tools/definitions/record_prompt_def.js +1 -1
  48. package/tools/definitions/record_prompt_def.js.map +1 -1
  49. package/tools/index.js +10 -2
  50. package/tools/index.js.map +1 -1
  51. package/tools/live/get-native-live-uikit-integration.js +101 -0
  52. package/tools/live/get-native-live-uikit-integration.js.map +1 -0
  53. package/tools/live/get-web-live-component-detail.js +1 -1
  54. package/tools/live/get-web-live-component-detail.js.map +1 -1
  55. package/tools/live/get-web-live-state-detail.js +1 -1
  56. package/tools/live/get-web-live-state-detail.js.map +1 -1
  57. package/tools/live/get-web-live-uikit-integration.js +6 -6
  58. package/tools/live/get-web-live-uikit-integration.js.map +1 -1
  59. package/tools/live/get_native_live_extra_features.js +105 -0
  60. package/tools/live/get_native_live_extra_features.js.map +1 -0
  61. package/tools/live/get_native_live_interaction.js +101 -0
  62. package/tools/live/get_native_live_interaction.js.map +1 -0
  63. package/tools/room/get-web-room-feature-detail.js +68 -0
  64. package/tools/room/get-web-room-feature-detail.js.map +1 -0
  65. package/tools/room/get-web-room-integration.js +43 -0
  66. package/tools/room/get-web-room-integration.js.map +1 -0
  67. package/utils/generate-structured-result.js +1 -1
  68. package/utils/report-cls-client.js +1 -1
  69. package/utils/report-es-client.js +1 -1
  70. package/resource/doc/roomkit/vue/states/device-state.md +0 -316
  71. package/resource/doc/roomkit/vue/states/login-state.md +0 -51
  72. package/resource/doc/roomkit/vue/states/room-list-state.md +0 -287
  73. package/resource/doc/roomkit/vue/states/room-participant-state.md +0 -307
  74. package/tools/definitions/get_web_room_state_detail_def.js +0 -19
  75. package/tools/definitions/get_web_room_state_detail_def.js.map +0 -1
  76. package/tools/room/get-web-room-state-detail.js +0 -31
  77. package/tools/room/get-web-room-state-detail.js.map +0 -1
  78. /package/resource/doc/livekit/{vue → live/vue}/components/barrage.md +0 -0
  79. /package/resource/doc/livekit/{vue → live/vue}/components/co-guest-panel.md +0 -0
  80. /package/resource/doc/livekit/{vue → live/vue}/components/live-audience-list.md +0 -0
  81. /package/resource/doc/livekit/{vue → live/vue}/components/live-scene-panel.md +0 -0
  82. /package/resource/doc/livekit/{vue → live/vue}/components/live-view.md +0 -0
  83. /package/resource/doc/livekit/{vue → live/vue}/components/stream-mixer.md +0 -0
  84. /package/resource/doc/livekit/{vue → live/vue}/faq.md +0 -0
  85. /package/resource/doc/livekit/{vue → live/vue}/live-list-integration.md +0 -0
  86. /package/resource/doc/livekit/{vue → live/vue}/live-player-desk-integration.md +0 -0
  87. /package/resource/doc/livekit/{vue → live/vue}/live-player-h5-integration.md +0 -0
  88. /package/resource/doc/livekit/{vue → live/vue}/live-pusher-integration.md +0 -0
  89. /package/resource/doc/livekit/{vue → live/vue}/states/live-state.md +0 -0
  90. /package/resource/doc/livekit/{vue → live/vue}/workflow.md +0 -0
@@ -0,0 +1,189 @@
1
+ # Native Live AtomicXCore 代码生成工作流指令 (Android)
2
+
3
+ ## 🚨 核心原则(最高优先级)
4
+
5
+ **Agent 必须确保生成的代码可以成功编译运行,严禁将无法编译的代码交付给用户!**
6
+
7
+ ### ⚠️ 强制编译验证
8
+ **每次生成/修改代码后,必须执行完整 Gradle 编译**:
9
+ ```bash
10
+ ./gradlew assembleDebug --stacktrace
11
+ ```
12
+
13
+ **禁止行为**:
14
+ - ❌ 禁止只用 `read_lints` 检查就认为代码正确
15
+ - ❌ 禁止用 `grep` 过滤编译输出(可能遗漏关键错误)
16
+
17
+ **编译错误分类与处理**:
18
+ | 错误类型 | 示例 | 处理方式 |
19
+ |---------|------|---------|
20
+ | 依赖解析失败 | `Could not find xxx` | 检查仓库配置(JitPack/Maven) |
21
+ | 依赖缺失 | `Unresolved reference` | 添加缺失依赖到 build.gradle |
22
+ | Import 缺失 | `Unresolved reference: xxx` | 添加 import 语句 |
23
+ | 资源缺失 | `cannot find symbol R.xxx` | 创建对应资源文件 |
24
+ | Manifest 缺失 | `Activity not found` | 注册到 AndroidManifest.xml |
25
+
26
+ **验证流程**:
27
+ 1. 执行 `./gradlew assembleDebug`(完整输出,不过滤)
28
+ 2. 如果失败 → 分析完整错误 → 修复 → 重新编译
29
+ 3. 循环直到 `BUILD SUCCESSFUL`
30
+ ```
31
+
32
+ **关键点**:强调 `read_lints ≠ 完整编译验证`,Gradle 依赖/配置错误只有完整编译才能发现。
33
+ ```
34
+
35
+ **处理流程**:
36
+ 1. **编译成功 (BUILD SUCCESSFUL)** → 交付代码。
37
+ 2. **编译失败** → 分析错误 → **自动修复** → 重新编译。
38
+ * ✅ **可自动修复**:依赖缺失、Import 缺失、AndroidManifest 权限缺失。
39
+ * ❌ **不可修复**:SDK 内部错误、网络环境问题(需提示用户)。
40
+
41
+ ---
42
+
43
+ ## 📋 指令目的与架构
44
+
45
+ 为 Agent 提供实现 Native (Android) Live AtomicXCore 核心功能的**代码生成蓝图**。
46
+
47
+ **核心架构**:
48
+ * **容器**:`LiveCoreView` (视图层)
49
+ * **状态**:`Store` (数据驱动)
50
+ * **事件**:`Listener` (回调处理)
51
+
52
+ **功能依赖逻辑(重要)**:
53
+ 1. **基础先行**:必须先使用本工具(`get_native_live_uikit_integration`)完成基础直播(开播/观看/列表)。
54
+ 2. **互动叠加**:如果用户需求包含“连麦”、“PK”、“观众列表”,必须**在基础功能完成后**,再调用互动工具(`get_native_live_interaction`)。
55
+ 3. **空项目处理**:若用户在空项目中直接请求互动功能,Agent **必须先实现基础功能**,再添加互动能力。
56
+
57
+ ---
58
+
59
+ ## ⚙️ 自动化工作流步骤
60
+
61
+ ### 步骤 0: 前置准备(自动化)
62
+ 1. **生成凭证**:调用 `get_usersig` 工具生成测试凭证。
63
+ * 主播: `anchor001`, `anchor002`, `anchor003`
64
+ * 观众: `user001`, `user002`, `user003`
65
+ 2. **环境检查**:检查 `build.gradle`,若缺失以下依赖则自动添加:
66
+ ```gradle
67
+ api 'io.trtc.uikit:atomicx-core:latest.release'
68
+ api "io.trtc.uikit:rtc_room_engine:latest.release"
69
+ api "com.tencent.liteav:LiteAVSDK_Professional:latest.release"
70
+ api "com.tencent.imsdk:imsdk-plus:latest.release"
71
+ ```
72
+ 3. **权限注入**:在 `AndroidManifest.xml` 中添加摄像头、麦克风、网络权限。
73
+
74
+ ### 步骤 1: 获取与生成
75
+ **必须优先且唯一**使用本工具返回的**实时文档内容**生成代码。
76
+ * **仅主播**:生成 `AnchorActivity`
77
+ * **仅观众**:生成 `AudienceActivity`
78
+ * **主播+观众**:生成 `MainActivity` (入口选择) + `AnchorActivity` + `AudienceActivity`
79
+
80
+ ### 步骤 2: 验证与交付
81
+ 执行 `./gradlew assembleDebug`,确保无误后交付。
82
+
83
+ ---
84
+
85
+ ## 🚫 代码生成约束(严格遵守)
86
+
87
+ ### 1. 通用代码约束
88
+ * **严禁修改 Import**:文档中的 import 路径经过验证,绝对不可修改。
89
+ * **严禁臆造 API**:如果文档没写,绝对不能自己发明方法名或参数名。
90
+ * **必须查阅 API 文档**:涉及数据模型字段(如 `LiveInfo`),必须查看文档确认字段名(例如确认是 `liveOwner.userName` 而不是 `name`)。
91
+
92
+ ### 2. 🧩 Store 与 Listener 管理约束(生命周期安全)
93
+ **核心原因**:SDK 的 `Store.create(liveId)` 通常返回单例或复用实例。使用匿名内部类会导致监听器实例重复注册或被覆盖,引发“主播端不显示”或“仅首次生效”的 Bug。
94
+
95
+ * **唯一实例原则**:所有 Listener(如 `GiftListener`, `CoGuestListener`, `BarrageListener`)**必须声明为 Activity/Fragment 的成员变量**。
96
+ * **严禁匿名内部类**:禁止直接在 `addXXXListener(object : ...)` 中写匿名对象。
97
+ * **成对原则**:在 `onCreate/onStart` 调用 `addListener`,则**必须**在 `onDestroy/onStop` 调用 `removeListener`,防止内存泄漏和监听失效。
98
+
99
+ ### 3. ⏱️ 超时时间限制(关键技术点)
100
+ **必须严格遵守以下参数限制,优先使用文档示例中的值:**
101
+
102
+ #### A. 观众连麦 (`CoGuestStore`)
103
+ * **规则**:
104
+ * 可选参数,不填则不检查超时。
105
+ * 若填写,范围必须在 **5 - 1800 秒**之间。
106
+ * **正确示例**:
107
+ ```kotlin
108
+ // ✅ 推荐:跟随文档示例(如 30秒)
109
+ applyForSeat(seatIndex = -1, timeout = 30, ...)
110
+ // ✅ 合法:不检查超时
111
+ applyForSeat(seatIndex = -1, timeout = 0, ...)
112
+ ```
113
+ * **错误示例**:❌ `timeout = 3` (太短),❌ `timeout = 2000` (太长)。
114
+
115
+ #### B. 主播连线/PK (`CoHostStore`)
116
+ * **规则**:
117
+ * **最大值 30 秒**(后台硬限制)。
118
+ * **正确示例**:
119
+ ```kotlin
120
+ // ✅ 推荐:使用最大值
121
+ requestHostConnection(..., timeout = 30, ...)
122
+ ```
123
+ * **错误示例**:❌ `timeout = 60` (会导致请求失败)。
124
+
125
+ ### 3. 🎨 扩展功能约束(美颜/音效/UI)
126
+
127
+ #### A. 音效 (Audio Effect)
128
+ * **变声枚举 (`AudioChangerType`)**:
129
+ * ✅ **允许**:`CHILD, LITTLE_GIRL, MAN, ETHEREAL` 等标准枚举。
130
+ * ❌ **禁止**:`UNCLE, LOLI, GIRL, BOY` (这些是旧版或错误的枚举)。
131
+ * **混响枚举 (`AudioReverbType`)**:
132
+ * ✅ **允许**:`KTV, SMALL_ROOM, METALLIC` 等。
133
+ * ❌ **禁止**:`ROOM, HALL, LOW`。
134
+
135
+ #### B. 美颜 (Beauty)
136
+ * **参数范围**:**0.0 - 9.0** (Float)。
137
+ * ❌ 不是 0-1 (Float),也不是 0-100 (Int)。
138
+ * **UI 映射公式**:`progress / 100.0f * 9.0f`。
139
+
140
+ #### C. 弹幕、礼物与布局 (Barrage, Gift & UI)
141
+ * **层级要求**:弹幕列表和全屏礼物动画必须使用 `FrameLayout` 或 `RelativeLayout` 覆盖在视频层**之上**。
142
+ * **禁止分割**:严禁将屏幕分割为“上视频、下弹幕”,必须是叠加模式。
143
+ * **键盘适配**:必须在 Manifest 中设置 `android:windowSoftInputMode="adjustNothing"` 或 `adjustPan`,**防止键盘弹起时视频画面变形或上移**。
144
+ * **礼物弹幕 (Gift Barrage)**:**如果用户需要集成礼物弹幕**,`onReceiveGift` 事件触发时,**主播端和观众端**都必须在弹幕列表(Message List)中插入礼物消息。严禁仅在观众端显示礼物文本。
145
+ * **全屏礼物 (Full-screen Gift)**:**如果用户需要集成全屏礼物**,收到礼物回调后,**主播端和观众端**都必须在视频顶层播放全屏动画。严禁只在观众端播放动画,主播也必须能看到观众送出的礼物特效。
146
+ ---
147
+
148
+ ## 🎯 功能实现细节
149
+
150
+ ### 1. 主播开播 (`host_streaming`)
151
+ * **核心**:`LiveCoreView(viewType = PUSH_VIEW)`
152
+ * **流程**:`LiveListStore.createLive()`
153
+ * **销毁**:`onDestroy` 中必须调用 `endLive()`。
154
+
155
+ ### 2. 观众观看 (`audience_streaming`)
156
+ * **核心**:`LiveCoreView(viewType = PLAY_VIEW)`
157
+ * **流程**:`LiveListStore.joinLive()`
158
+ * **销毁**:`onDestroy` 中必须调用 `leaveLive()`。
159
+
160
+ ### 3. 直播列表 (`live_list`)
161
+ * **核心**:`LiveListStore.fetchLiveList()` + `RecyclerView`
162
+ * **数据**:订阅 `liveState.liveList`。
163
+ * **跳转**:点击列表项跳转观众页,传递 `liveID`。
164
+
165
+ ---
166
+
167
+ ## 📋 Agent 最终检查清单
168
+
169
+ - [ ] **编译验证**:已执行 `./gradlew assembleDebug` 且结果为 SUCCESS。
170
+ - [ ] **API 准确性**:未修改 Import,未臆造 API,已核对 `LiveInfo` 字段名。
171
+ - [ ] **超时合规**:连麦超时 5-1800s,连线超时 ≤30s。
172
+ - [ ] **扩展合规**:音效枚举正确,美颜范围 0-9,弹幕布局覆盖且键盘适配。
173
+ - [ ] **礼物合规**:主播和观众端均实现了全屏礼物动画显示。
174
+ - [ ] **凭证注入**:已自动注入测试 UserSig。
175
+ - [ ] **依赖完整**:已检查并修复 `build.gradle` 和权限。
176
+
177
+ ---
178
+
179
+ ## 🚨 安全提醒(代码注释模板)
180
+
181
+ ```kotlin
182
+ /**
183
+ * ⚠️ 测试凭证说明
184
+ * - 当前 userSig 由开发工具自动生成,有效期 7 天
185
+ * - ❌ 生产环境严禁在客户端生成 userSig
186
+ * - ✅ 正式上线前必须在后端服务生成
187
+ * - 参考: https://cloud.tencent.com/document/product/647/17275
188
+ */
189
+ ```
@@ -0,0 +1,256 @@
1
+ 会中呼叫功能允许会议内的用户(邀请者)向房间外的其他用户(被邀请者)发送实时入会邀请。该功能基于 `Atomicx State Hooks` 实现,能够帮助开发者快速构建具有主动邀约能力的互动场景。
2
+
3
+ ## 适用场景
4
+ - **协同办公:**在进行远程会议时,若涉及跨部门决策,可一键呼叫外部专家快速入会,缩短沟通链路。
5
+
6
+ - **直播教学:**老师在授课过程中,若发现部分学生缺席,可直接邀请其加入课堂。
7
+
8
+ - **互联网医疗会诊:**首诊医生在病历分析过程中,通过呼叫功能邀请上级医生进入虚拟诊室进行多方会诊,或者医生呼叫在等候室的患者进行问诊。
9
+
10
+
11
+ ## 前提条件
12
+
13
+ 在接入功能前,请确保满足以下条件:
14
+ - **邀请者 (User A):**用户已经通过 `useLoginState` 完成登录鉴权,参考 [接入概览](https://write.woa.com/document/197379797539790848),并已作为一个房间的房主或成员在房间内,参考 [房间周期](https://write.woa.com/document/197379861957083136)。
15
+
16
+ - **被邀请者 (User B):**用户已经通过 `useLoginState` 完成登录鉴权,参考 [接入概览](https://write.woa.com/document/197379797539790848),以便接收信令事件。
17
+
18
+ - **环境依赖:**项目已正确安装并引入 `tuikit-atomicx-vue3`。
19
+
20
+
21
+ ## 实现会中呼叫功能
22
+
23
+ 实现会中呼叫的核心流程如下:
24
+
25
+ ![会中呼叫时序图](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100027160512/82ba8603dee611f0a4f35254007c27c5.png)
26
+
27
+ 会中呼叫时序图
28
+
29
+
30
+ ### 步骤1:发起呼叫(邀请者)
31
+
32
+ 邀请者调用 [callUserToRoom](https://web.sdk.qcloud.com/trtc/live/web/doc/zh/index.html#callUserToRoom) 接口发起邀请。请确保邀请者当前已在房间内(即 [currentRoom](https://web.sdk.qcloud.com/trtc/live/web/doc/zh/index.html#currentRoom) 不为空),否则无法发起呼叫。
33
+ ``` typescript
34
+ import { useRoomState } from 'tuikit-atomicx-vue3/room';
35
+
36
+ const { currentRoom, callUserToRoom } = useRoomState();
37
+
38
+ const inviteUser = async () => {
39
+ // 会中呼叫必须关联一个已存在的 roomId,因此需先校验当前用户的进房状态
40
+ if (!currentRoom.value) {
41
+ console.warn('请先进入房间再发起邀请');
42
+ return;
43
+ }
44
+
45
+ try {
46
+ const resultMap = await callUserToRoom({
47
+ roomId: currentRoom.value.roomId, // 被邀请者将要加入的房间 ID
48
+ userIdList: ['user1', 'user2'], // 目标用户 ID 数组,支持单人或多人
49
+ timeout: 60, // 邀请有效时长(秒),超时后双方会触发 onCallTimeout
50
+ // extensionInfo 可用于传递业务自定义数据,例如邀请类型、附加消息等
51
+ extensionInfo: JSON.stringify({ type: 'emergency', priority: 'high' })
52
+ });
53
+
54
+ // resultMap 返回每个 userId 对应的状态,例如 Success、AlreadyInRoom (已在房) 或 AlreadyInCalling (通话中)
55
+ console.log('邀请发送完成,详情状态映射:', resultMap);
56
+ } catch (error) {
57
+ console.error('呼叫请求发送失败,请检查网络或登录状态:', error);
58
+ }
59
+ };
60
+ ```
61
+
62
+ ### 步骤2:监听呼叫事件(被邀请者)
63
+
64
+ 被邀请者需要监听 `onCallReceived` 事件。建议在例如 `App.vue`等长驻组件中实现,以确保无论用户在哪个页面都能响应。
65
+ ``` typescript
66
+ import { ref, onMounted, onUnmounted } from 'vue';
67
+ import { useRoomState, RoomEvent } from 'tuikit-atomicx-vue3/room';
68
+
69
+ const {
70
+ subscribeEvent,
71
+ unsubscribeEvent,
72
+ acceptCall,
73
+ rejectCall,
74
+ joinRoom,
75
+ currentRoom
76
+ } = useRoomState();
77
+
78
+ const showInviteDialog = ref(false); // 控制 UI 弹窗显隐
79
+ const currentCallInfo = ref(null); // 缓存收到的邀请上下文
80
+
81
+ const handleCallReceived = async ({ roomInfo, call, extensionInfo }) => {
82
+ // 冲突处理:如果用户当前已经在会议中,根据业务策略通常应直接拒绝新邀请,防止干扰
83
+ if (currentRoom.value?.roomId) {
84
+ await rejectCall({ roomId: roomInfo.roomId });
85
+ return;
86
+ }
87
+
88
+ // 记录邀请详情,用于在 UI 上展示邀请者名称或业务透传数据
89
+ currentCallInfo.value = { roomInfo, call };
90
+ showInviteDialog.value = true;
91
+ };
92
+
93
+ // 接受邀请逻辑
94
+ const onUserAccept = async () => {
95
+ if (!currentCallInfo.value) return;
96
+ const { roomId } = currentCallInfo.value.roomInfo;
97
+
98
+ try {
99
+ // 关键流程 A:响应信令。告知邀请者已接受,使其能更新 UI(例如显示“对方已接听”)
100
+ await acceptCall({ roomId });
101
+
102
+ // 关键流程 B:执行进房。只有调用 joinRoom 才会真正开启音视频推拉流链路
103
+ await joinRoom({ roomId });
104
+ } catch (error) {
105
+ console.error('接受呼叫后的进房操作失败:', error);
106
+ } finally {
107
+ closeDialog();
108
+ }
109
+ };
110
+
111
+ // 拒绝邀请逻辑
112
+ const onUserReject = async () => {
113
+ if (currentCallInfo.value) {
114
+ // 告知邀请者已拒绝,邀请者会收到 onCallRejected 事件
115
+ await rejectCall({ roomId: currentCallInfo.value.roomInfo.roomId });
116
+ }
117
+ closeDialog();
118
+ };
119
+
120
+ const closeDialog = () => {
121
+ showInviteDialog.value = false;
122
+ currentCallInfo.value = null;
123
+ };
124
+
125
+ // 事件全生命周期管理:确保在组件挂载时监听,销毁时移除,防止事件溢出
126
+ onMounted(() => {
127
+ subscribeEvent(RoomEvent.onCallReceived, handleCallReceived);
128
+
129
+ // 监听导致邀请结束的各种异常/同步事件,确保 UI 弹窗能及时闭合
130
+ subscribeEvent(RoomEvent.onCallCancelled, closeDialog); // 邀请者取消了呼叫
131
+ subscribeEvent(RoomEvent.onCallTimeout, closeDialog); // 呼叫超时未响应
132
+ subscribeEvent(RoomEvent.onCallHandledByOtherDevice, closeDialog); // 用户在其他设备已处理该呼叫
133
+ });
134
+
135
+ onUnmounted(() => {
136
+ // 移除所有监听器,避免在组件销毁后继续执行 handleCallReceived 导致内存泄漏或报错
137
+ unsubscribeEvent(RoomEvent.onCallReceived, handleCallReceived);
138
+ unsubscribeEvent(RoomEvent.onCallCancelled, closeDialog);
139
+ unsubscribeEvent(RoomEvent.onCallTimeout, closeDialog);
140
+ unsubscribeEvent(RoomEvent.onCallHandledByOtherDevice, closeDialog);
141
+ });
142
+ ```
143
+
144
+ ## 实践教程:提升呼叫接通率
145
+
146
+ 为了在业务中获得更高的呼叫接通率,除了基础功能的实现外,建议参考以下策略优化用户体验:
147
+
148
+ ### 1. 增强呼叫感知(避免用户遗漏)
149
+
150
+ 由于 Web 端特性,浏览器静音或页面处于后台运行状态可能导致用户遗漏呼叫。
151
+ - **视觉提醒**:利用 [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) 检测页面可见性状态。若页面处于后台,可通过循环修改 `document.title` 实现标题栏闪烁提示(例如:“【新邀请】UserA 邀请您入会...”),以吸引用户注意。
152
+
153
+ - **听觉提醒**:在 `onCallReceived` 事件触发时播放高优先级的提示铃声。注意:需遵循浏览器的 [自动播放策略](https://developer.mozilla.org/zh-CN/docs/Web/Media/Guides/Autoplay),大部分浏览器在缺乏用户交互(例如点击、触摸或按键)的情况下会限制音频自动播放。
154
+
155
+
156
+ ### 2. 丰富邀请上下文(提升接听意愿)
157
+
158
+ 缺乏明确意图的邀请容易被用户拒绝。建议充分利用 `extensionInfo` 字段传递关键业务信息,以提升用户的接听意愿。
159
+ - **传递业务上下文**:利用 `extensionInfo` 透传如 `reason`(例如:“项目紧急评审”)、`level`(例如:“P0故障排查”)等业务字段,告知用户呼叫的紧迫性和重要性。
160
+
161
+
162
+ ### 3. 多通道触达兜底(确保消息可达)
163
+
164
+ 受限于 Web 端机制,浏览器进程结束将无法接收实时信令。建议采取以下替代方案以确保触达:
165
+ - **浏览器系统通知**:引导用户授权 [Web Notification API](https://developer.mozilla.org/en-US/docs/Web/API/Notification)。只要浏览器进程未关闭(包括最小化或在后台标签页),即可触发操作系统级别的弹窗通知,有效提醒用户。
166
+
167
+ - **多通道触达**:建议结合业务后端逻辑,在检测到用户不在线或超时未响应时,通过**短信**、**邮件**或**企业微信**等外部渠道发送入会链接,实现全方位触达。
168
+
169
+
170
+ ### 4. 智能重试机制(解决“接受邀请后进房失败”)
171
+
172
+ 在弱网或其他不稳定环境下,用户点击接受邀请后调用 `joinRoom` 可能会出现偶发性失败。
173
+ - **自动重试**:建议在 `onUserAccept` 的异常处理逻辑(`catch`)中引入 2-3 次自动重试机制(推荐结合指数退避策略),以最大程度确保用户点击“接受”后能成功加入会议。
174
+
175
+
176
+ ## 开发注意事项
177
+ 1. **接受邀请不等于进房**
178
+
179
+
180
+ `acceptCall` 仅仅是信令层面的回复(告知对方已接听)。用户必须在调用 `acceptCall` 后紧接着手动调用 `await joinRoom({ roomId })` 才能真正进入音视频房间。
181
+
182
+ 2. **生命周期管理**
183
+
184
+
185
+ 请务必在组件销毁周期(`onUnmounted`)调用 `unsubscribeEvent`。如果不清理监听器,当用户切换页面时,旧页面的监听器会残留在内存中,导致一次邀请弹出多个窗口或逻辑重复执行。
186
+
187
+ 3. **超时设置**
188
+
189
+
190
+ 如果不设置 `timeout` 参数,在某些网络异常或程序崩溃情况下,邀请可能长期处于挂起状态,导致无法再次对该用户发起呼叫。建议设置为 30-60 秒。
191
+
192
+
193
+ ## 常见问题
194
+ 1. **如何在呼叫时带上自定义参数(如“来自XX的紧急会议”)?**
195
+
196
+
197
+ 使用 `callUserToRoom` 的 `extensionInfo` 参数传递 JSON 字符串。被邀请者可以在 `onCallReceived` 事件的 `extensionInfo` 字段中解析该字符串获取业务信息。
198
+
199
+ 2. **被邀请者如果不在线,上线后能收到邀请吗?**
200
+
201
+
202
+ 不可以。邀请事件是一个瞬时信令动作,SDK 目前不会补发离线期间收到的呼叫通知。
203
+
204
+ 3. **可以取消已发出的邀请吗?**
205
+
206
+
207
+ 可以。调用 `cancelCall({ roomId, userIdList })` 即可撤销。此时被邀请者会收到 `onCallCancelled` 事件,您需要监听此事件来关闭被邀请端的 UI 弹窗。
208
+
209
+ 4. **接受后进房失败怎么办?**
210
+
211
+
212
+ 检查是否已登录 `TUIRoomEngine`,重试 `joinRoom({ roomId })` 并捕获错误提示用户;必要时在 UI 上提供“重试”按钮。
213
+
214
+ 5. **对方忙线或已在其他房间如何提示?**
215
+
216
+
217
+ `callUserToRoom` 的返回值 `resultMap` 中若出现 `AlreadyInRoom` / `AlreadyInCalling`,应在邀请者 UI 提示“对方忙线/已在会中”,并决定是否稍后重试。
218
+
219
+ 6. **超时/取消后弹窗不关闭?**
220
+
221
+
222
+ 确保监听 `onCallTimeout`、`onCallCancelled`、`onCallHandledByOtherDevice`,统一在回调里关闭弹窗、清理当前邀请数据。
223
+
224
+ 7. **多设备同时响铃如何处理?**
225
+
226
+
227
+ 在任意设备接受/拒绝后,其余设备会收到 `onCallHandledByOtherDevice`,需关闭其他端弹窗避免重复处理。
228
+
229
+ 8. **extensionInfo 该怎么约定?**
230
+
231
+
232
+ 建议使用 JSON 字符串并约定字段(例如 `type`、`priority`、`from`),在 `handleCallReceived` 时解析后展示友好文案(例如“来自XX的紧急会议”)。
233
+
234
+
235
+ ## **示例项目**
236
+
237
+ 腾讯云在 GitHub 上提供了示例项目 [atomicx-vite-vue3-ts](https://github.com/Tencent-RTC/TUIRoomKit/tree/main/Web/example/atomicx-vite-vue3-ts) ,您可以参考以实现完整的 RoomKit 功能。
238
+
239
+ ## API 文档
240
+ <table>
241
+ <tr>
242
+ <td rowspan="1" colSpan="1" >**State/Component**</td>
243
+
244
+ <td rowspan="1" colSpan="1" >**功能描述**</td>
245
+
246
+ <td rowspan="1" colSpan="1" >**API 文档**</td>
247
+ </tr>
248
+
249
+ <tr>
250
+ <td rowspan="1" colSpan="1" >**useRoomState**</td>
251
+
252
+ <td rowspan="1" colSpan="1" >房间状态管理(创建、加入、预约等)</td>
253
+
254
+ <td rowspan="1" colSpan="1" >[API 文档](https://web.sdk.qcloud.com/trtc/live/web/doc/zh/index.html#module-RoomState)</td>
255
+ </tr>
256
+ </table>