@tencent-rtc/trtc-agent-skills 0.1.0

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 (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/README.zh.md +173 -0
  4. package/bin/cli.js +434 -0
  5. package/knowledge-base/index.yaml +454 -0
  6. package/knowledge-base/platform-slice-template.md +233 -0
  7. package/knowledge-base/scenario-spec.md +350 -0
  8. package/knowledge-base/scenarios/conference/base/general-conference.md +365 -0
  9. package/knowledge-base/scenarios/conference/base/webinar-conference.md +130 -0
  10. package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +145 -0
  11. package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +113 -0
  12. package/knowledge-base/scenarios/live/entertainment-live-room.md +118 -0
  13. package/knowledge-base/slice-spec.md +546 -0
  14. package/knowledge-base/slices/conference/web/ai-tools.md +225 -0
  15. package/knowledge-base/slices/conference/web/beauty-effects.md +188 -0
  16. package/knowledge-base/slices/conference/web/device-control.md +338 -0
  17. package/knowledge-base/slices/conference/web/login-auth.md +261 -0
  18. package/knowledge-base/slices/conference/web/network-quality.md +190 -0
  19. package/knowledge-base/slices/conference/web/official-roomkit-api.md +298 -0
  20. package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +246 -0
  21. package/knowledge-base/slices/conference/web/participant-list.md +238 -0
  22. package/knowledge-base/slices/conference/web/participant-management.md +718 -0
  23. package/knowledge-base/slices/conference/web/prejoin-check.md +293 -0
  24. package/knowledge-base/slices/conference/web/room-call.md +213 -0
  25. package/knowledge-base/slices/conference/web/room-chat.md +426 -0
  26. package/knowledge-base/slices/conference/web/room-lifecycle.md +534 -0
  27. package/knowledge-base/slices/conference/web/room-schedule.md +281 -0
  28. package/knowledge-base/slices/conference/web/screen-share.md +211 -0
  29. package/knowledge-base/slices/conference/web/video-layout.md +675 -0
  30. package/knowledge-base/slices/conference/web/virtual-background.md +197 -0
  31. package/knowledge-base/slices/conference/web/webinar-interaction.md +206 -0
  32. package/knowledge-base/slices/live/anchor-lifecycle.md +122 -0
  33. package/knowledge-base/slices/live/anchor-preview.md +90 -0
  34. package/knowledge-base/slices/live/anchor-room-config.md +104 -0
  35. package/knowledge-base/slices/live/audience-list.md +86 -0
  36. package/knowledge-base/slices/live/audience-manage.md +92 -0
  37. package/knowledge-base/slices/live/audience-watch.md +85 -0
  38. package/knowledge-base/slices/live/audio.md +116 -0
  39. package/knowledge-base/slices/live/barrage.md +88 -0
  40. package/knowledge-base/slices/live/beauty.md +99 -0
  41. package/knowledge-base/slices/live/coguest-apply.md +105 -0
  42. package/knowledge-base/slices/live/device-control.md +91 -0
  43. package/knowledge-base/slices/live/error-codes.md +167 -0
  44. package/knowledge-base/slices/live/gift.md +84 -0
  45. package/knowledge-base/slices/live/ios/.gitkeep +0 -0
  46. package/knowledge-base/slices/live/ios/anchor-lifecycle.md +313 -0
  47. package/knowledge-base/slices/live/ios/anchor-preview.md +228 -0
  48. package/knowledge-base/slices/live/ios/anchor-room-config.md +257 -0
  49. package/knowledge-base/slices/live/ios/audience-list.md +353 -0
  50. package/knowledge-base/slices/live/ios/audience-manage.md +381 -0
  51. package/knowledge-base/slices/live/ios/audience-watch.md +286 -0
  52. package/knowledge-base/slices/live/ios/audio.md +373 -0
  53. package/knowledge-base/slices/live/ios/barrage.md +285 -0
  54. package/knowledge-base/slices/live/ios/beauty.md +323 -0
  55. package/knowledge-base/slices/live/ios/coguest-apply.md +506 -0
  56. package/knowledge-base/slices/live/ios/device-control.md +286 -0
  57. package/knowledge-base/slices/live/ios/error-codes.md +270 -0
  58. package/knowledge-base/slices/live/ios/gift.md +315 -0
  59. package/knowledge-base/slices/live/ios/live-list.md +269 -0
  60. package/knowledge-base/slices/live/ios/login-auth.md +247 -0
  61. package/knowledge-base/slices/live/live-list.md +82 -0
  62. package/knowledge-base/slices/live/login-auth.md +78 -0
  63. package/package.json +34 -0
  64. package/skills/trtc/SKILL.md +326 -0
  65. package/skills/trtc/room-builder/SKILL.md +138 -0
  66. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +108 -0
  67. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/backend-contract.zh-CN.md +162 -0
  68. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/integration.zh-CN.md +154 -0
  69. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/theme.zh-CN.md +78 -0
  70. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/index.html +12 -0
  71. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/package.json +28 -0
  72. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/postcss.config.js +5 -0
  73. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/App.vue +25 -0
  74. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/ConsultationManagePanel.vue +838 -0
  75. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LanguageSwitch.vue +102 -0
  76. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LoadingSpinner.vue +6 -0
  77. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalAlert.vue +34 -0
  78. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalBusinessPanel.vue +148 -0
  79. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalButton.vue +49 -0
  80. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalConfirmDialog.vue +68 -0
  81. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalDataPanel.vue +196 -0
  82. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalRecordPanel.vue +270 -0
  83. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/PrescriptionPanel.vue +363 -0
  84. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/basic-info-config.ts +29 -0
  85. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
  86. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
  87. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/runtime-config.ts +12 -0
  88. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/env.d.ts +32 -0
  89. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +123 -0
  90. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +230 -0
  91. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +135 -0
  92. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +113 -0
  93. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +132 -0
  94. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +50 -0
  95. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/types.ts +77 -0
  96. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationChat.ts +97 -0
  97. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationDevices.ts +48 -0
  98. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationParticipants.ts +121 -0
  99. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationPermissions.ts +25 -0
  100. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/utils.ts +70 -0
  101. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/en-US/index.ts +553 -0
  102. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/index.ts +25 -0
  103. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/medicalTranslate.ts +85 -0
  104. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/state.ts +49 -0
  105. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/zh-CN/index.ts +463 -0
  106. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/main.ts +12 -0
  107. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/appointments.ts +96 -0
  108. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/users.ts +79 -0
  109. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/router/index.ts +63 -0
  110. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/index.ts +25 -0
  111. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/appointmentService.ts +77 -0
  112. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/authService.ts +38 -0
  113. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/launchContext.ts +31 -0
  114. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/userService.ts +35 -0
  115. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/appointmentService.ts +43 -0
  116. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/authService.ts +33 -0
  117. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/userService.ts +43 -0
  118. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/types.ts +135 -0
  119. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/shared/icons.ts +53 -0
  120. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/index.css +106 -0
  121. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/tailwind.css +3 -0
  122. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/theme.css +209 -0
  123. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/auth.ts +50 -0
  124. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/format.ts +24 -0
  125. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/navigation.ts +12 -0
  126. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/session.ts +28 -0
  127. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorConsultationView.vue +777 -0
  128. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorDashboardView.vue +678 -0
  129. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/LoginView.vue +441 -0
  130. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationFinishedView.vue +185 -0
  131. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationView.vue +1003 -0
  132. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientSelectDoctorView.vue +317 -0
  133. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientWaitingView.vue +454 -0
  134. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.json +21 -0
  135. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.node.json +8 -0
  136. package/skills/trtc/room-builder/templates/scenarios/medical-consultation/vite.config.ts +17 -0
  137. package/skills/trtc/room-builder/templates/scenarios/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md +6 -0
  138. package/skills/trtc/room-builder/tools/render_ai_instructions.py +226 -0
  139. package/skills/trtc-apply/SKILL.md +97 -0
  140. package/skills/trtc-apply/guardrails/apply_lib/__init__.py +0 -0
  141. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
  142. package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
  143. package/skills/trtc-apply/guardrails/apply_lib/rule_parser.py +268 -0
  144. package/skills/trtc-docs/SKILL.md +207 -0
  145. package/skills/trtc-onboarding/SKILL.md +839 -0
  146. package/skills/trtc-onboarding/reference/path-a1-demo.md +103 -0
  147. package/skills/trtc-onboarding/reference/path-a2-integrate.md +693 -0
  148. package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +115 -0
  149. package/skills/trtc-onboarding/reference/path-c-expand.md +43 -0
  150. package/skills/trtc-onboarding/reference/reporting-protocol.md +174 -0
  151. package/skills/trtc-onboarding/reference/supported-matrix.md +100 -0
  152. package/skills/trtc-onboarding/reference/usersig-handling.md +140 -0
  153. package/skills/trtc-search/SKILL.md +221 -0
  154. package/skills/trtc-topic/SKILL.md +638 -0
  155. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
  156. package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
  157. package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
  158. package/skills/trtc-topic/guardrails/gate_slice_read.py +133 -0
  159. package/skills/trtc-topic/guardrails/gate_slice_write.py +169 -0
  160. package/skills/trtc-topic/guardrails/stop_require_apply_evidence.py +97 -0
  161. package/skills/trtc-topic/references/execution-units.yaml +58 -0
  162. package/skills/trtc-topic/runtime/README.md +50 -0
  163. package/skills/trtc-topic/runtime/RUNTIME.md +128 -0
  164. package/skills/trtc-topic/runtime/lib/__init__.py +0 -0
  165. package/skills/trtc-topic/runtime/lib/platforms.py +194 -0
  166. package/skills/trtc-topic/runtime/package-lock.json +1211 -0
  167. package/skills/trtc-topic/runtime/package.json +13 -0
  168. package/skills/trtc-topic/runtime/telemetry-bridge.mjs +339 -0
  169. package/skills/trtc-topic/runtime/telemetry_collector.py +293 -0
  170. package/skills/trtc-topic/scripts/STATE-MACHINE-GUIDE.md +186 -0
  171. package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
  172. package/skills/trtc-topic/scripts/apply.py +581 -0
  173. package/skills/trtc-topic/scripts/finalize_session.py +113 -0
  174. package/skills/trtc-topic/scripts/init_slice_queue.py +96 -0
  175. package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
  176. package/skills/trtc-topic/scripts/lib/state_machine.py +328 -0
  177. package/skills/trtc-topic/scripts/next_slice.py +137 -0
  178. package/skills/trtc-topic/tests/README.md +70 -0
  179. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  180. package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  181. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
  182. package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
  183. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
  184. package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
  185. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
  186. package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
  187. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
  188. package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
  189. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
  190. package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
  191. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
  192. package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
  193. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
  194. package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
  195. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
  196. package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
  197. package/skills/trtc-topic/tests/conftest.py +72 -0
  198. package/skills/trtc-topic/tests/test_apply_cli.py +480 -0
  199. package/skills/trtc-topic/tests/test_end_to_end.py +305 -0
  200. package/skills/trtc-topic/tests/test_finalize_session.py +51 -0
  201. package/skills/trtc-topic/tests/test_gates.py +316 -0
  202. package/skills/trtc-topic/tests/test_session_resolver.py +260 -0
  203. package/skills/trtc-topic/tests/test_state_machine.py +414 -0
  204. package/skills/trtc-topic/tests/test_stop_require_apply.py +99 -0
  205. package/skills/trtc-topic/tests/test_topic_skill_invariants.py +130 -0
@@ -0,0 +1,338 @@
1
+ ---
2
+ id: conference/device-control
3
+ name: 设备控制
4
+ product: conference
5
+ platform: web
6
+ tags: [device, camera, microphone, speaker, resolution, mirror]
7
+ platforms: [web]
8
+ related: [conference/prejoin-check, conference/participant-management, conference/network-quality, conference/video-layout]
9
+ api_docs:
10
+ - title: 设备及网络
11
+ url: https://cloud.tencent.com/document/product/647/126923
12
+ ---
13
+
14
+ # 设备控制
15
+
16
+ ## 功能说明
17
+
18
+ 设备控制负责会议中的本地音视频设备使用与设置,覆盖摄像头、麦克风、扬声器的打开关闭、设备切换、音量调节、视频分辨率、本地镜像,以及权限拒绝、设备占用、无设备可用、受会中规则限制等异常处理。它解决的是“本机设备如何被正确使用”“当前为什么不能使用”“当前终端支持哪些设置项”“当前是否需要先做局部检查或预览”这类问题。入会前的完整设备检查主流程归属 `prejoin-check`;而会中设置面板、工具栏或异常恢复场景下的局部摄像头预览、麦克风音量检测、扬声器测试,也属于当前 slice 的能力范围。会中的全体禁用、成员设备关闭、设备申请和设备邀请等约束则与 `participant-management` 联动。
19
+
20
+ ## 核心概念
21
+
22
+ ### 角色与操作
23
+
24
+ | 角色 | 关键操作 | 说明 |
25
+ |------|----------|------|
26
+ | 当前参会人 | 开关设备、调整设置并执行局部检查 | 控制自己的摄像头、麦克风、扬声器,以及音量、分辨率、镜像等设置;也可在需要时做局部预览、音量检测和扬声器测试;设备受限时可发起申请或响应邀请 |
27
+ | 会控模块 | 限制或恢复设备能力 | 可通过全体禁用、关闭成员设备、设备申请和设备邀请等规则影响本地设备可用态 |
28
+ | 浏览器 / 系统 | 提供设备与权限能力 | 决定设备能否被访问,以及是否支持设备枚举、扬声器切换、音量调整、局部预览和测试等能力 |
29
+ | 设备设置界面 | 展示设备列表、设置项与能力边界 | 应根据当前终端能力裁剪设置项;能力完整的终端可提供更完整的音频和视频设置,能力受限的终端应只保留核心入口,并同步展示异常和受限原因 |
30
+ | 布局模块 | 感知设备开关结果 | 摄像头、麦克风和共享相关状态会进一步影响画面编排和挂件展示 |
31
+
32
+ ### 事件流
33
+
34
+ | 阶段 | 参与方 | 关键动作 |
35
+ |------|--------|----------|
36
+ | 设备准备 | 浏览器 / 客户端 | 枚举摄像头、麦克风、扬声器等设备,并确认当前终端支持哪些设置项 |
37
+ | 局部检查 | 当前参会人 / 浏览器 | 在会前页或会中设置面板进行摄像头预览、麦克风音量检测或扬声器测试 |
38
+ | 权限与约束判断 | 浏览器 / 会控状态 | 判断是否具备浏览器权限、是否受会中规则限制,以及是否需要先申请或等待邀请 |
39
+ | 会中控制 | 当前参会人 | 开关、切换和调整设备设置;设备受限时发起申请或响应邀请 |
40
+ | 状态同步 | UI / 会控 / 布局 | 设备状态、受限原因和处理结果同步到工具栏、设置面板和画面展示 |
41
+ | 异常收口 | 浏览器 / 客户端 | 处理权限拒绝、设备占用、无设备可用、切换失败、不支持等场景 |
42
+
43
+ ### 状态与数据
44
+
45
+ | 数据 / 状态 | 说明 |
46
+ |-------------|------|
47
+ | 摄像头 / 麦克风 / 扬声器列表 | 当前终端可选择的本地设备集合 |
48
+ | 当前设备选择 | 当前实际使用的摄像头、麦克风、扬声器标识 |
49
+ | 设备能力边界 | 表示当前终端是否支持设备切换、扬声器选择、音量调节、镜像或分辨率设置 |
50
+ | 本地设备开关状态 | 表示摄像头和麦克风当前是否处于开启状态 |
51
+ | 麦克风采集与发言状态 | 用于区分“设备已经开始采集”与“当前是否正在向房间发送音频”,也可支撑闭麦说话提醒 |
52
+ | 局部检查状态 | 包括摄像头预览状态、麦克风电平检测状态和扬声器测试状态 |
53
+ | 音频设置项 | 包括麦克风选择、扬声器选择、采集音量、播放音量和实时音量反馈 |
54
+ | 视频设置项 | 包括摄像头选择、前后置切换、视频分辨率、本地镜像和局部预览 |
55
+ | 分辨率档位策略 | 用于按弱网、多人成会、默认会议体验或高清场景提供不同清晰度选项 |
56
+ | 会中限制状态 | 表示是否被全体禁用、被管理员关闭,或需要先申请开启 |
57
+ | 设备异常状态 | 包括权限拒绝、占用冲突、设备不存在、浏览器不支持、切换失败等结果 |
58
+
59
+ ### 状态机
60
+
61
+ ```text
62
+ idle
63
+ → enumerating-devices
64
+ → ready
65
+ → opening-device
66
+ → active
67
+
68
+ active
69
+ → changing-settings
70
+ → muted-but-capturing
71
+ → active
72
+
73
+ opening-device / changing-settings
74
+ → restricted
75
+ → blocked
76
+ → failed
77
+ → ready
78
+ ```
79
+
80
+ ## 前置条件
81
+ **通用依赖**:见 [login-auth 平台 slice](login-auth.md)。
82
+
83
+ **额外依赖**:
84
+ - 已安装 `tuikit-atomicx-vue3@latest`
85
+
86
+ **前置状态**:
87
+ - 已阅读 `conference/device-control`,明确当前能力的产品边界。
88
+ - 已完成 `conference/login-auth`,确保当前页面具备稳定登录态。
89
+ - 已根据业务流程接入会议上下文;需要房间状态时,优先通过 `conference/room-lifecycle` 统一承接。
90
+ - 当前能力涉及媒体采集、渲染或浏览器权限时,请在 `HTTPS` 或 `localhost` 安全上下文下调试。
91
+
92
+ ## 最佳实践
93
+
94
+ ### ✅ ALWAYS
95
+
96
+ 1. **把会前完整检查流程和会中设备控制拆成两段主链路** —— 会前主流程负责入会准备;会中仍可在设置面板、工具栏或异常恢复时做局部检查、预览和测试。
97
+ 2. **区分麦克风采集状态和发言状态** —— 会议场景更推荐在用户成功进房后先完成本地麦克风采集准备,并默认保持静音;之后“开麦 / 闭麦”主要控制音频是否上行,而不是频繁打开和关闭物理麦克风采集。这样既能减少开麦时重新处理设备采集带来的延迟,也便于结合实时音量反馈实现闭麦说话提醒。
98
+ 3. **根据当前终端能力裁剪设备设置项** —— 能力完整的终端可提供设备列表、扬声器切换、音量、分辨率和镜像设置;能力受限的终端只保留开关、前后置切换和少量分辨率等核心入口。
99
+ 4. **按音频设置和视频设置组织面板** —— 音频侧重点是设备选择、音量和音量反馈;视频侧重点是摄像头选择、分辨率、镜像和局部预览。
100
+ 5. **把设备列表、当前选择和工具栏状态放在同一份状态里维护** —— 切换设备、调节音量或修改分辨率后,设置面板和会中入口应看到一致结果;切换失败时应保留原设备并给出提示。
101
+ 6. **按场景提供清晰度档位** —— 弱网、多人成会或小窗场景可优先低档位;默认会议体验可使用中高档位;高清主讲场景再提供更高分辨率选项。
102
+ 7. **把设备受限原因和恢复路径一起展示** —— 当设备因 `disableAllDevices` 触发的房间级禁用而不可开时,这类限制通常只作用于普通成员;设备 icon 应表现为 disabled,并在用户点击时按产品需要提供申请开启入口。若设备只是被房主或管理员单独关闭,则应通过 toast 等方式明确告知结果,但只要没有房间级禁用,成员仍可再次主动开启本地设备。
103
+ 8. **把设备异常直接映射成可执行提示** —— 权限拒绝、设备占用、无设备可用、浏览器不支持、切换失败等情况都应告诉用户下一步该怎么做。
104
+
105
+ ### ❌ NEVER
106
+
107
+ 1. **不要把会中的“开麦 / 闭麦”直接等同于频繁开关物理麦克风** —— 释放物理设备更适合离房、结束会议或明确需要停止采集的场景。
108
+ 2. **不要在能力受限的终端强行展示完整设备设置** —— 麦克风列表、扬声器切换或复杂设置项在部分终端上可能并不成立。
109
+ 3. **不要把“打不开设备”一律解释成浏览器或系统问题** —— 还应排查是否被全体禁用、被管理员关闭,或需要先发起设备申请。
110
+ 4. **不要假设设备列表和设备切换永远可用** —— 浏览器兼容性、热插拔、系统限制和切换失败都需要单独收口。
111
+ 5. **不要把网络波动、设备异常和会控限制混成同一类问题** —— 设备权限、设备状态和网络质量应分别判断,避免误导排障方向。
112
+ 6. **不要在离房、结束会议或页面销毁后遗留采集状态** —— 避免摄像头常亮、麦克风仍被占用或下一场会议沿用脏状态。
113
+
114
+ ### 会议中的麦克风控制推荐采用"进房后预静音 + 建立采集"
115
+ - 用户成功进入房间后,先调用 `muteMicrophone()`,先把本地音频上行状态收口为静音。
116
+ - 随后调用 `openLocalMicrophone()` 建立本地麦克风采集,保持本地已采集但默认不向远端发送音频。
117
+ - 用户点击"打开麦克风"时,调用 `unmuteMicrophone()` 恢复音频上行。
118
+ - 用户点击"关闭麦克风"时,调用 `muteMicrophone()` 停止音频上行。
119
+ - 只有在离房、结束会议或明确要释放设备时,再调用 `closeLocalMicrophone()`。
120
+
121
+ 这里要特别区分:**麦克风需要把"是否采集"和"是否上行"拆开处理,但摄像头通常不需要照搬这套模型。**
122
+ - 摄像头在大多数会议产品里,直接用 `openLocalCamera()` / `closeLocalCamera()` 控制开启与关闭即可。
123
+ - 如果业务要求"入会默认不开摄",应明确调用 `closeLocalCamera()` 收口摄像头关闭状态;当用户点击开摄时再调用 `openLocalCamera()`。
124
+ - 如果用户点击关摄,直接调用 `closeLocalCamera()` 释放本地摄像头采集即可,不需要类比成 `muteMicrophone()` / `unmuteMicrophone()` 这类"保留采集但停止上行"的用法。
125
+ - 只有在客户明确要求"摄像头预热但默认不展示 / 不上屏"这类特殊策略时,才需要单独评估是否做更复杂的摄像头状态编排;默认文档口径不要把摄像头推断成和麦克风同一套控制链路。
126
+
127
+ 这样设计有两个直接收益:
128
+ - 用户开麦时无需重新处理物理设备采集,响应速度更快。
129
+ - 业务层可以持续结合 `currentMicVolume` 检测闭麦说话,并在合适时提示"您正在说话,是否打开麦克风?"。
130
+
131
+ ## 代码示例
132
+ ### 基础接入:打开摄像头、切换设备并在离场前关闭
133
+
134
+ ```ts
135
+ import { useDeviceState, DeviceStatus } from 'tuikit-atomicx-vue3/room';
136
+
137
+ const {
138
+ cameraStatus,
139
+ openLocalCamera,
140
+ closeLocalCamera,
141
+ getCameraList,
142
+ setCurrentCamera,
143
+ } = useDeviceState();
144
+
145
+ if (cameraStatus.value !== DeviceStatus.On) await openLocalCamera();
146
+ await getCameraList();
147
+ await setCurrentCamera({ deviceId: 'camera_device_id' });
148
+ await closeLocalCamera();
149
+ ```
150
+
151
+ ### 会议推荐:用 `cameraStatus` 驱动摄像头开关按钮
152
+
153
+ > ⚠️ 重要:`localParticipant.isCameraDisabled` 是管理员/会控禁用状态,**不**反映本地设备的实际开关。会中摄像头开关按钮状态必须来自 `cameraStatus`。
154
+
155
+ ```ts
156
+ import { computed } from 'vue';
157
+ import { useDeviceState, useRoomParticipantState, DeviceStatus } from 'tuikit-atomicx-vue3/room';
158
+
159
+ const { cameraStatus, openLocalCamera, closeLocalCamera } = useDeviceState();
160
+
161
+ // ✅ 正确:用 cameraStatus 反映本地设备实际开关状态
162
+ const isCameraOff = computed(() => cameraStatus.value !== DeviceStatus.On);
163
+
164
+ // ❌ 错误示例(切勿使用):
165
+ // const { localParticipant } = useRoomParticipantState();
166
+ // const isCameraOff = computed(() => Boolean(localParticipant.value?.isCameraDisabled));
167
+ // → isCameraDisabled 是管理员远程禁用标志,不跟随 openLocalCamera/closeLocalCamera 更新
168
+
169
+ export async function toggleCamera() {
170
+ if (isCameraOff.value) {
171
+ await openLocalCamera(); // 重新开启摄像头采集
172
+ } else {
173
+ await closeLocalCamera(); // 停止摄像头采集(离场时也应调用)
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### 会议推荐:进房后先静音,再建立麦克风采集
179
+
180
+ ```ts
181
+ import { computed } from 'vue';
182
+ import { DeviceStatus, useDeviceState, useRoomParticipantState } from 'tuikit-atomicx-vue3/room';
183
+
184
+ const { microphoneStatus, openLocalMicrophone, currentMicVolume } = useDeviceState();
185
+ const { muteMicrophone, unmuteMicrophone } = useRoomParticipantState();
186
+
187
+ const isMicrophoneOn = computed(() => microphoneStatus.value === DeviceStatus.On);
188
+
189
+ export async function prepareMicrophoneAfterJoin() {
190
+ await muteMicrophone();
191
+ await openLocalMicrophone();
192
+ }
193
+
194
+ export async function handleClickOpenMicrophone() {
195
+ await unmuteMicrophone();
196
+ }
197
+
198
+ export async function handleClickCloseMicrophone() {
199
+ await muteMicrophone();
200
+ }
201
+
202
+ export function shouldPromptSpeakingWhileMuted() {
203
+ return !isMicrophoneOn.value && currentMicVolume.value > 30;
204
+ }
205
+ ```
206
+
207
+ ## 调用时序
208
+ ```
209
+ 完成 login-auth 并进入会议
210
+
211
+
212
+ 根据页面状态初始化本地设备
213
+
214
+ ├─ 摄像头需要开启 → openLocalCamera()
215
+ ├─ 麦克风需要预采集 → muteMicrophone() → openLocalMicrophone()
216
+ ├─ 需切换设备 → getCameraList() / getMicrophoneList() → setCurrent*(...)
217
+ └─ 权限失败 → 展示错误并提示检查浏览器授权
218
+
219
+
220
+ 用户点击"开麦" → unmuteMicrophone()
221
+
222
+ ├─ 检测到闭麦说话 → 可结合 currentMicVolume 给出提醒
223
+ └─ 用户点击"闭麦" → muteMicrophone()
224
+
225
+
226
+ 离场或明确释放设备时调用 closeLocalCamera() / closeLocalMicrophone()
227
+ ```
228
+
229
+ ## 平台特有注意事项
230
+ ### 1. Web 采集设备必须运行在安全上下文
231
+ 线上环境未启用 `HTTPS` 时,浏览器会直接拦截摄像头和麦克风采集;本地联调可使用 `localhost`。
232
+
233
+ ### 2. 设备切换属于异步动作
234
+ 切换摄像头、麦克风或扬声器时,建议在 UI 层提供 loading 或"切换中"反馈,避免用户连续点击造成状态错乱。
235
+
236
+ ### 3. 设备错误应直接投射到 UI
237
+ 摄像头或麦克风异常时,应把 `cameraLastError`、`microphoneLastError` 等状态及时映射成提示,而不是只在控制台打印。
238
+
239
+ ### 4. 工具栏状态应以 AtomicX 状态为准
240
+ 麦克风按钮应直接用 `useDeviceState().microphoneStatus === DeviceStatus.On` 判断当前是否开麦,再分别调用 `muteMicrophone()` / `unmuteMicrophone()`。自定义工具栏不要额外维护一个容易漂移的本地 `isMuted` 作为唯一事实源;如果业务需要本地 UI 状态,也应从 `microphoneStatus` 派生。
241
+
242
+ > ⚠️ **注意**:上述规则仅适用于**正式入会后**的会中场景。会前检测页(prejoin)使用的是 `startCameraTest` / `startMicrophoneTest`,这些测试模式 API **不会**更新 `cameraStatus` / `microphoneStatus`,因此预检页的设备 UI 状态必须用本地 `ref` 管理。详见 `conference/prejoin-check`。
243
+
244
+ ### 5. `useDeviceState()` 在业务 composable 中必须保持单例
245
+ 如果项目将设备操作封装为统一的 composable(如 `useConferenceDevice`),内部的 `useDeviceState()` 必须在模块级缓存为单例,**不能**在每次 composable 调用时重复执行 `useDeviceState()`。
246
+
247
+ **原因**:`useDeviceState()` 每次调用返回一组独立的响应式引用;如果在不同组件中通过 composable 各自创建了不同实例,`startMicrophoneTest` 更新的 `currentMicVolume` 只会写入调用发起方的实例,其他实例的 `currentMicVolume` 始终为 0。
248
+
249
+ **正确模式**:
250
+ ```ts
251
+ let _state: ReturnType<typeof useDeviceState> | null = null;
252
+ function getDeviceState() {
253
+ if (!_state) _state = useDeviceState();
254
+ return _state;
255
+ }
256
+ export function useConferenceDevice() {
257
+ const { currentMicVolume, cameraStatus, ... } = getDeviceState();
258
+ // 所有消费方共享同一个响应式实例
259
+ }
260
+ ```
261
+
262
+ ### 5. 设备入口要区分"房间级禁用"和"成员级关闭"
263
+ 如果当前是 `disableAllDevices` 触发的房间级禁用,这类限制通常只作用于普通成员;普通成员的设备 icon 应表现为 disabled,并在点击时通过 toast 或等价提示说明原因。是否继续允许用户通过 `requestToOpenDevice()` 申请开启,需要结合客户需求决定。若只是被房主或管理员单独关闭设备,则更适合提示"设备已被管理员关闭",并允许用户在没有房间级禁用的前提下再次调用 `openLocalCamera()` 或 `unmuteMicrophone()` 主动恢复。
264
+
265
+ ### 6. `iframe` 集成要显式放开媒体权限
266
+ 如果会议页面运行在 `iframe` 内,宿主页面需要通过 `allow` 放开麦克风、摄像头、屏幕共享和全屏权限;否则即使业务代码正确,浏览器也可能直接拦截媒体采集或共享能力。
267
+
268
+ ## 代码生成约束
269
+ ### 编译必要条件
270
+ - **通用条件**:见 [login-auth 平台 slice](login-auth.md)。
271
+ - **额外导入**:至少需要从 `tuikit-atomicx-vue3/room` 导入 `useDeviceState`,按需导入 `DeviceStatus`、`DeviceError`。
272
+ - **运行前提**:浏览器具备设备权限,页面处于安全上下文。
273
+
274
+ ### 生成规则
275
+ #### MUST(生成时必须包含)
276
+
277
+ 1. **通过 `useDeviceState` 承接本地设备状态与操作** — 这样设备列表、状态与异常才能保持同源。
278
+ **Verify**: 检查是否存在 `useDeviceState()`。
279
+ 2. **在切换设备前先获取设备列表或当前状态** — 否则 UI 容易对不存在的设备执行切换。
280
+ **Verify**: 检查是否存在 `getCameraList()` / `getMicrophoneList()` / 状态读取逻辑。
281
+ 3. **会议场景下把"麦克风采集"与"音频上行"拆开处理,但不要把这套规则直接套到摄像头上** — 推荐进房后先 `muteMicrophone()`,再 `openLocalMicrophone()`;后续通过 `unmuteMicrophone()` / `muteMicrophone()` 响应开麦与闭麦。摄像头统一按 `openLocalCamera()` / `closeLocalCamera()` 直接控制开关。
282
+ **Verify**: 检查会议工具栏或入会初始化逻辑中,麦克风是否存在上述调用链,同时摄像头是否统一使用 `openLocalCamera()` / `closeLocalCamera()` 控制。
283
+
284
+ #### MUST NOT(生成时绝不能出现)
285
+
286
+ 1. **不要在不满足安全上下文时默认开启媒体采集** — 浏览器会直接拒绝访问。
287
+ **Verify**: 检查代码或说明中是否明确 `HTTPS` / `localhost` 前提。
288
+ 2. **不要只改 UI 开关,不调用真实设备接口** — 会出现按钮已开但本地流未变化的假状态。
289
+ **Verify**: 检查交互处理函数中是否实际调用 `open*` / `close*` / `setCurrent*`。
290
+ 3. **不要把会中的"开麦 / 闭麦"实现成反复 `openLocalMicrophone()` / `closeLocalMicrophone()`** — 这样会增加重新采集延迟,也不利于闭麦说话提醒。
291
+ **Verify**: 检查工具栏开关逻辑是否优先使用 `muteMicrophone()` / `unmuteMicrophone()`。
292
+ 4. **不要在封装 composable 时多次调用 `useDeviceState()` 创建独立实例** — 多实例会导致 `currentMicVolume`、`cameraStatus` 等响应式数据在组件间断链、无法同步。
293
+ **Verify**: 检查 composable 是否将 `useDeviceState()` 返回值缓存为模块级单例。
294
+ 5. **不要在预检页(prejoin)用 `cameraStatus` / `microphoneStatus` 判断设备是否开启** — 会前测试 API 不更新这些字段。
295
+ **Verify**: 预检页组件中的设备 UI 状态是否来自独立的本地 `ref`。
296
+
297
+ ### 集成检查点
298
+ - 当前 slice 常与 `conference/prejoin-check`、`conference/screen-share`、`conference/beauty-effects` 联动。
299
+ - 一般只需要新增设备面板或工具栏逻辑,不应侵入 SDK 内部采集实现。
300
+ - 如果业务已存在独立媒体层,需要明确由哪一层负责最终设备开关,避免双写状态。
301
+
302
+ ## 验证矩阵
303
+ | 层级 | 检查项 | 验证手段 | 预期结果 |
304
+ |------|--------|----------|---------|
305
+ | 1. 编译级 | 已导入 `useDeviceState` | 检查 `import` 语句 | 可正常解析设备 Hook |
306
+ | 2. 静态规则级 | UI 操作真实调用设备接口 | 搜索 `openLocalCamera` / `openLocalMicrophone` / `muteMicrophone` / `unmuteMicrophone` / `setCurrentCamera` | 至少一条真实设备调用链存在 |
307
+ | 3. 运行时级 | 设备开关与切换可执行 | 在浏览器授权后触发操作 | 摄像头状态可切换,麦克风可在静音与上行之间切换 |
308
+ | 4. 业务行为级 | 用户能感知权限、切换与闭麦说话提醒 | 在设置面板或工具栏执行操作 | UI 与实际设备状态保持一致,必要时可提示闭麦说话 |
309
+
310
+ ## 排障指南
311
+
312
+ ### 常见问题
313
+
314
+ | 问题 | 表现 | 处理建议 |
315
+ |------|------|----------|
316
+ | 麦克风已打开但别人听不到 | 本地看起来已开麦,但远端没有声音 | 检查当前是“已采集但未上行”还是设备根本未开启,并确认是否受会中禁言或设备限制 |
317
+ | 权限正常但设备仍打不开 | 浏览器已授权,按钮仍不可用或开启后立即失败 | 检查是否被全体禁用、被管理员关闭,或是否需要先发起设备申请 |
318
+ | 切换设备不生效 | 设置面板已选中新设备,但实际采集仍来自旧设备 | 检查当前设备选择是否真正更新,并确认切换失败时是否保留原设备和提示用户 |
319
+ | 扬声器测试或切换无效 | 听不到测试音,或切换输出设备后播放路径未变化 | 检查当前浏览器是否支持扬声器列表与切换;不支持时应引导用户使用系统声音设置 |
320
+ | 某些设置项缺失或不可用 | 看不到扬声器切换、完整设备列表或高级设置 | 先确认这是当前终端的能力边界,避免把兼容性差异误判为功能异常 |
321
+ | 离房后设备仍在运行 | 会议退出后摄像头灯仍亮或麦克风仍被占用 | 检查离房、结束房间和页面销毁路径是否统一关闭本地采集 |
322
+
323
+ ### 排障流程
324
+
325
+ ```text
326
+ 发现 设备控制 相关问题
327
+ ├── 第 1 步:确认问题属于会中设备控制或会中局部检查,而不是独立的会前检查主流程
328
+ ├── 第 2 步:检查浏览器权限、设备可用性以及当前终端是否支持对应设置项
329
+ ├── 第 3 步:确认当前是否存在全体禁用、管理员关闭、设备申请或设备邀请等会中限制
330
+ └── 第 4 步:若仍异常,再回查 prejoin-check / participant-management / network-quality / video-layout 的衔接是否正确
331
+ ```
332
+
333
+ ## 关联知识
334
+
335
+ - **[conference/prejoin-check](prejoin-check.md)** —— 入会前的完整设备检查主流程在这里定义;会中也可能存在局部检查和预览。
336
+ - **[conference/participant-management](participant-management.md)** —— 设备按钮可用态、管理员关闭设备和申请开启链路由这里约束。
337
+ - **[conference/network-quality](network-quality.md)** —— 网络问题和设备问题常被用户混淆,需要分层排查。
338
+ - **[conference/video-layout](video-layout.md)** —— 摄像头开关结果最终会影响画面布局和成员挂件展示。
@@ -0,0 +1,261 @@
1
+ ---
2
+ id: conference/login-auth
3
+ name: 登录与鉴权
4
+ product: conference
5
+ platform: web
6
+ tags: [login, auth, sdkappid, usersig, useLoginState]
7
+ platforms: [web]
8
+ related: [conference/room-lifecycle, conference/device-control, conference/prejoin-check]
9
+ api_docs:
10
+ - title: 接入概览
11
+ url: https://cloud.tencent.com/document/product/647/126917
12
+ business_decisions:
13
+ - key: usersig_source
14
+ tier: blocking
15
+ question: "您的项目当前处于哪个阶段?这决定鉴权凭证(UserSig)的生成方式。"
16
+ options:
17
+ - { label: "本地开发 / 调试 —— 控制台临时签发,几分钟即可跑通;有有效期、不能用于生产", value: "console" }
18
+ - { label: "生产环境(上线)—— 由您的后端接口签发,安全合规(推荐)", value: "backend" }
19
+ - key: userid_strategy
20
+ tier: blocking
21
+ question: "参会用户的身份需要绑定您现有的账号体系吗?"
22
+ options:
23
+ - { label: "需要,直接使用现有账号的用户 ID —— 最常见,如员工工号、手机号等", value: "direct" }
24
+ - { label: "需要,但不能暴露真实 ID —— 转换为会议专用身份,后台维护映射关系", value: "uuid-mapping" }
25
+ - { label: "不需要,允许无账号匿名入会 —— 生成临时 ID,用完即弃", value: "anonymous" }
26
+ - key: on_session_lost
27
+ tier: deferrable
28
+ default: redirect-login
29
+ question: "如果用户登录态失效了(凭证过期,或在别处登录把这台顶下线),页面应如何处理?"
30
+ options:
31
+ - { label: "跳回登录页,让用户重新登录 —— 最稳妥(推荐默认)", value: "redirect-login" }
32
+ - { label: "后台静默换新凭证、自动重连 —— 用户无感,但需后端配合", value: "auto-refresh" }
33
+ - { label: "弹窗提示,由用户决定重连或退出", value: "prompt-user" }
34
+ ---
35
+
36
+ # 登录与鉴权
37
+
38
+ ## 功能说明
39
+
40
+ 登录与鉴权是 Conference 通用会议所有能力的共同入口,负责把业务身份映射成可被 Room UIKit 使用的登录态。它解决“用户是谁、凭什么入会、资料如何同步”这三个基础问题;创建房间、加入房间、采集设备、会中聊天等后续能力都应建立在稳定登录态之上。
41
+
42
+ ## 核心概念
43
+
44
+ ### 角色与操作
45
+
46
+ | 角色 | 关键操作 | 说明 |
47
+ |------|----------|------|
48
+ | 业务后端 | 签发 `UserSig` | 正式环境下由服务端签发登录凭证,不在前端硬编码长期有效凭证 |
49
+ | 客户端应用 | 调用 `login` | 使用 `SDKAppID / userId / userSig` 建立会议登录态 |
50
+ | 当前用户 | 设置资料 | 通过 `setSelfInfo` 同步昵称、头像等会中展示信息 |
51
+ | 后续会议能力 | 消费登录态 | `room-lifecycle`、`device-control`、`prejoin-check` 等能力都依赖已登录状态 |
52
+
53
+ ### 事件流
54
+
55
+ | 阶段 | 参与方 | 关键动作 |
56
+ |------|--------|----------|
57
+ | 凭证准备 | 后端 → 客户端 | 后端根据业务身份生成 `userSig` 并下发给客户端 |
58
+ | 登录建链 | 客户端 | 客户端调用登录接口,建立 SDK 登录态 |
59
+ | 资料同步 | 客户端 | 登录成功后补充昵称、头像等用户展示信息 |
60
+ | 能力放行 | 客户端 → 会议能力 | 只有登录完成后,房间、设备、聊天等能力才开始工作 |
61
+ | 退出登录 | 客户端 | 登出或切换用户时清理旧会话,避免把旧状态带入下一场会议 |
62
+
63
+ ### 状态与数据
64
+
65
+ | 数据 / 状态 | 说明 |
66
+ |-------------|------|
67
+ | `sdkAppId` | 当前会议应用的 SDK 应用标识 |
68
+ | `userId` | 当前登录用户的唯一身份标识 |
69
+ | `userSig` | 用于完成鉴权的动态签名,正式环境应由服务端签发 |
70
+ | `selfInfo` | 当前用户昵称、头像等会中展示信息 |
71
+ | 登录态 | 表示当前用户是否已可安全执行房间与设备相关操作 |
72
+
73
+ ### 状态机
74
+
75
+ ```text
76
+ idle
77
+ → credential-ready
78
+ → logging-in
79
+ → logged-in
80
+ → profile-synced
81
+ → logged-out
82
+
83
+ logging-in
84
+ → login-failed
85
+ → credential-ready
86
+ ```
87
+
88
+ ## 前置条件
89
+ **通用依赖**:已准备 `SDKAppID / UserID / UserSig`,并确认正式环境的 `UserSig` 由业务后端签发。
90
+
91
+ **额外依赖**:
92
+ - 已安装 `tuikit-atomicx-vue3@latest`
93
+
94
+ **前置状态**:
95
+ - 已阅读 `conference/login-auth`,明确当前能力的产品边界。
96
+ - 若后续需要采集摄像头、麦克风或屏幕,请直接在 `HTTPS` 或 `localhost` 环境联调。
97
+
98
+ ## 最佳实践
99
+
100
+ ### ✅ ALWAYS
101
+
102
+ 1. **由业务后端签发正式环境 `UserSig`** —— 前端只负责消费凭证,不负责生成生产可用签名。
103
+ 2. **把登录放在应用启动或进入会议主流程之前完成** —— 避免房间创建、设备采集、聊天绑定与登录竞态交错。
104
+ 3. **登录成功后立即同步用户资料** —— 参会人列表、聊天头像、会控面板都依赖一致的用户展示信息。
105
+ 4. **在切换账号或退出会议体系时显式清理旧登录态** —— 防止上一位用户的资料和房间上下文泄漏到下一次会话。
106
+
107
+ ### ❌ NEVER
108
+
109
+ 1. **不要在前端硬编码长期有效的生产 `UserSig`** —— 这会破坏鉴权边界,也不利于后续风控和吊销。
110
+ 2. **不要在未登录完成前直接创建或加入房间** —— 很容易出现入房失败、资料缺失或后续状态无法收口的问题。
111
+ 3. **不要让多个页面各自重复触发登录** —— 登录应尽量收敛到统一入口,避免并发登录与状态覆盖。
112
+
113
+ ## 代码示例
114
+ ### 基础接入:启动时完成登录并写入用户资料
115
+
116
+ ```ts
117
+ import { onMounted } from 'vue';
118
+ import { useLoginState } from 'tuikit-atomicx-vue3/room';
119
+
120
+ const { login, setSelfInfo } = useLoginState();
121
+
122
+ onMounted(async () => {
123
+ await login({
124
+ sdkAppId: 1400000000,
125
+ userId: 'user_001',
126
+ userSig: 'YOUR_USERSIG',
127
+ scene: 5001,
128
+ });
129
+ await setSelfInfo({ userName: 'Alice', avatarUrl: '' });
130
+ });
131
+ ```
132
+
133
+ ### 事件处理:登录过期与被强制下线后收口登录态
134
+
135
+ ```ts
136
+ import { LoginEvent, useLoginState } from 'tuikit-atomicx-vue3';
137
+
138
+ const { subscribeEvent } = useLoginState();
139
+
140
+ subscribeEvent(LoginEvent.onLoginExpired, () => {
141
+ console.log('登录已过期,请重新登录');
142
+ // 跳转到登录页面或刷新 userSig
143
+ });
144
+
145
+ subscribeEvent(LoginEvent.onKickedOffline, () => {
146
+ console.log('账号在其他设备登录,已被强制下线');
147
+ // 提示用户重新登录
148
+ });
149
+ ```
150
+
151
+ ## 调用时序
152
+ ```
153
+ 应用启动
154
+
155
+
156
+ 准备 SDKAppID / UserID / UserSig
157
+
158
+
159
+ 初始化全局上下文提供者
160
+
161
+
162
+ 调用 login(...)
163
+
164
+ ├─ 失败 → 提示鉴权或签名错误,停止后续房间 / 设备初始化
165
+
166
+ └─ 成功
167
+
168
+
169
+ 调用 setSelfInfo(...)
170
+
171
+
172
+ 订阅 LoginEvent.onLoginExpired / LoginEvent.onKickedOffline
173
+
174
+ ├─ 触发过期事件 → 跳转登录页或刷新 userSig 后重新登录
175
+
176
+ ├─ 触发被踢下线事件 → 提示账号异地登录并收口当前登录态
177
+
178
+
179
+ 再进入 room-lifecycle / device-control / room-chat 等后续能力
180
+ ```
181
+
182
+ ## 平台特有注意事项
183
+ ### 1. `userSig` 只能由业务后端在正式环境签发
184
+ 开发联调时可以临时生成 `userSig`,但线上不能把签名逻辑放在前端,否则会直接破坏账号安全边界。
185
+
186
+ ### 2. 登录应早于房间与设备能力初始化
187
+ `room-lifecycle`、`device-control`、`room-chat` 等能力都依赖稳定登录态;未登录就先调房间或聊天接口,通常会导致调用失败或状态异常。
188
+
189
+ ### 3. 需要显式处理登录过期与被强制下线事件
190
+ 当登录凭证过期时,会触发 `LoginEvent.onLoginExpired`;收到此事件后应立即跳转登录页,或先刷新 `userSig` 再重新执行登录流程,不能只在控制台打印日志。
191
+
192
+ 当账号在其他设备登录导致当前设备被强制下线时,会触发 `LoginEvent.onKickedOffline`;收到此事件后应立即提示用户当前登录态已失效,并引导重新登录,避免页面继续停留在失效会中状态。
193
+
194
+ ### 4. Web 端媒体能力依赖安全上下文
195
+ 如果页面后续需要摄像头、麦克风、屏幕共享或本地特效,部署环境必须满足 `HTTPS`、`localhost` 或浏览器认可的其他安全上下文条件。
196
+
197
+ ## 代码生成约束
198
+ ### 编译必要条件
199
+ - **通用条件**:当前 slice 是 Web 会议所有后续能力的统一登录入口。
200
+ - **额外导入**:至少需要从 `tuikit-atomicx-vue3/room` 导入 `useLoginState`;若需订阅登录事件,还应从 `tuikit-atomicx-vue3` 导入 `LoginEvent`。
201
+ - **运行前提**:页面必须能拿到有效的 `SDKAppID / UserID / UserSig`;若要承接 UI Kit 组件,还需在根节点挂载全局上下文。
202
+
203
+ ### 生成规则
204
+ #### MUST(生成时必须包含)
205
+
206
+ 1. **先完成 `login()`,再初始化其他会议能力** — 否则后续 room / device / chat 调用缺少基础登录态。
207
+ **Verify**: 检查代码中是否存在 `await login(`,且后续房间或设备逻辑位于其后。
208
+ 2. **登录参数必须包含 `scene: 5001`** — 用于标识由 skill 生成的场景接入来源,所有 useLoginState().login 生成代码都必须带上该参数。
209
+ **Verify**: 检查 `login(` 参数对象中是否包含 `scene: 5001`。
210
+ 3. **把用户资料写入 `setSelfInfo()` 或等价链路** — 否则远端成员列表与会中 UI 可能只显示默认 ID。
211
+ **Verify**: 检查是否存在 `setSelfInfo(` 或明确的资料同步逻辑。
212
+ 4. **订阅登录过期与被强制下线事件并收口恢复逻辑** — 登录成功后仍要处理 `LoginEvent.onLoginExpired` 与 `LoginEvent.onKickedOffline`,避免后续房间与聊天状态静默失效。
213
+ **Verify**: 检查是否存在 `subscribeEvent(LoginEvent.onLoginExpired, ...)`、`subscribeEvent(LoginEvent.onKickedOffline, ...)` 或等价恢复逻辑。
214
+
215
+ #### MUST NOT(生成时绝不能出现)
216
+
217
+ 1. **不要把正式环境 `UserSig` 生成逻辑写在前端** — 会直接泄露签名能力。
218
+ **Verify**: 搜索是否存在前端本地生成正式 `UserSig` 的实现。
219
+ 2. **不要在未登录态下直接调用房间、聊天或设备接口** — 会造成初始化顺序错误。
220
+ **Verify**: 检查房间 / 设备 / 聊天逻辑是否依赖已完成登录的状态。
221
+ 3. **不要在收到登录过期或被强制下线事件后只打印日志、不做恢复处理** — 这会让后续能力停留在失效登录态。
222
+ **Verify**: 检查 `onLoginExpired` 与 `onKickedOffline` 处理逻辑是否真正跳转登录页、刷新 `userSig` 或提示用户重新登录。
223
+
224
+ ### 集成检查点
225
+ - 当前 slice 是 `conference/web` 目录下其他所有能力 slice 的公共前置条件。
226
+ - 集成方式通常是新增启动逻辑或根级状态管理,不应修改 SDK 内部实现。
227
+ - 若业务项目已有独立账号体系,应把用户登录与 TRTC/IM 登录桥接清楚,而不是直接复用匿名测试账号。
228
+
229
+ ## 验证矩阵
230
+ | 层级 | 检查项 | 验证手段 | 预期结果 |
231
+ |------|--------|----------|---------|
232
+ | 1. 编译级 | 已正确导入 `useLoginState`、`LoginEvent` 与登录事件相关依赖 | 检查 `import` 语句 | 可解析登录 Hook 与 `LoginEvent` |
233
+ | 2. 静态规则级 | 登录先于其他会议能力初始化,登录参数包含 `scene: 5001`,且已监听过期与被踢下线事件 | 搜索 `await login(`、`scene: 5001`、`setSelfInfo(`、`subscribeEvent(LoginEvent.onLoginExpired`、`subscribeEvent(LoginEvent.onKickedOffline` | 先登录、写入资料,并具备完整的登录态恢复入口 |
234
+ | 3. 运行时级 | 登录成功后可继续设置资料,并能响应过期或被强制下线事件 | 触发启动流程并观察日志或调试状态 | 登录成功且用户资料更新完成;过期时进入重登或刷新票据流程;被踢下线时提示重新登录 |
235
+ | 4. 业务行为级 | 后续会议能力可正常承接 | 完成登录后继续进入会议页面,并模拟异地登录顶替场景 | 房间、设备、聊天入口不再因未登录失败;登录过期或被强制下线后都能被及时收口 |
236
+
237
+ ## 排障指南
238
+
239
+ ### 常见问题
240
+
241
+ | 问题 | 表现 | 处理建议 |
242
+ |------|------|----------|
243
+ | 登录失败 | 调用登录后报错,后续房间与设备能力都无法使用 | 检查 `sdkAppId`、`userId`、`userSig` 是否匹配,确认 `UserSig` 未过期且由正确环境签发 |
244
+ | 用户资料未同步 | 已登录,但参会人列表或聊天区域昵称、头像不对 | 确认登录成功后已调用资料同步接口,并检查是否被旧本地缓存覆盖 |
245
+ | 后续能力报未鉴权 | 创建房间、设备采集或聊天初始化时报未登录 | 检查业务流程是否在登录完成前提前触发了 `room-lifecycle` 或 `device-control` |
246
+
247
+ ### 排障流程
248
+
249
+ ```text
250
+ 发现 登录与鉴权 相关问题
251
+ ├── 第 1 步:确认当前使用的 sdkAppId / userId / userSig 是否同属一个环境
252
+ ├── 第 2 步:检查 userSig 是否过期、是否由后端按当前 userId 重新签发
253
+ ├── 第 3 步:确认登录成功后是否立即同步了昵称、头像等 selfInfo
254
+ └── 第 4 步:若房间或设备能力仍异常,再回查 room-lifecycle / device-control 是否在登录前被提前触发
255
+ ```
256
+
257
+ ## 关联知识
258
+
259
+ - **[conference/room-lifecycle](room-lifecycle.md)** —— 登录完成后,真正承接创建房间、加入房间、离房和结束会议。
260
+ - **[conference/device-control](device-control.md)** —— 摄像头、麦克风等本地设备能力依赖稳定登录态。
261
+ - **[conference/prejoin-check](prejoin-check.md)** —— 会前检测通常在登录完成后进入,确保设备信息可被统一管理。