@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.
- package/LICENSE +21 -0
- package/README.md +172 -0
- package/README.zh.md +173 -0
- package/bin/cli.js +434 -0
- package/knowledge-base/index.yaml +454 -0
- package/knowledge-base/platform-slice-template.md +233 -0
- package/knowledge-base/scenario-spec.md +350 -0
- package/knowledge-base/scenarios/conference/base/general-conference.md +365 -0
- package/knowledge-base/scenarios/conference/base/webinar-conference.md +130 -0
- package/knowledge-base/scenarios/conference/medical/1v1-video-consultation.md +145 -0
- package/knowledge-base/scenarios/conference/medical/medical-multidoctor-consultation.md +113 -0
- package/knowledge-base/scenarios/live/entertainment-live-room.md +118 -0
- package/knowledge-base/slice-spec.md +546 -0
- package/knowledge-base/slices/conference/web/ai-tools.md +225 -0
- package/knowledge-base/slices/conference/web/beauty-effects.md +188 -0
- package/knowledge-base/slices/conference/web/device-control.md +338 -0
- package/knowledge-base/slices/conference/web/login-auth.md +261 -0
- package/knowledge-base/slices/conference/web/network-quality.md +190 -0
- package/knowledge-base/slices/conference/web/official-roomkit-api.md +298 -0
- package/knowledge-base/slices/conference/web/official-roomkit-login-ui.md +246 -0
- package/knowledge-base/slices/conference/web/participant-list.md +238 -0
- package/knowledge-base/slices/conference/web/participant-management.md +718 -0
- package/knowledge-base/slices/conference/web/prejoin-check.md +293 -0
- package/knowledge-base/slices/conference/web/room-call.md +213 -0
- package/knowledge-base/slices/conference/web/room-chat.md +426 -0
- package/knowledge-base/slices/conference/web/room-lifecycle.md +534 -0
- package/knowledge-base/slices/conference/web/room-schedule.md +281 -0
- package/knowledge-base/slices/conference/web/screen-share.md +211 -0
- package/knowledge-base/slices/conference/web/video-layout.md +675 -0
- package/knowledge-base/slices/conference/web/virtual-background.md +197 -0
- package/knowledge-base/slices/conference/web/webinar-interaction.md +206 -0
- package/knowledge-base/slices/live/anchor-lifecycle.md +122 -0
- package/knowledge-base/slices/live/anchor-preview.md +90 -0
- package/knowledge-base/slices/live/anchor-room-config.md +104 -0
- package/knowledge-base/slices/live/audience-list.md +86 -0
- package/knowledge-base/slices/live/audience-manage.md +92 -0
- package/knowledge-base/slices/live/audience-watch.md +85 -0
- package/knowledge-base/slices/live/audio.md +116 -0
- package/knowledge-base/slices/live/barrage.md +88 -0
- package/knowledge-base/slices/live/beauty.md +99 -0
- package/knowledge-base/slices/live/coguest-apply.md +105 -0
- package/knowledge-base/slices/live/device-control.md +91 -0
- package/knowledge-base/slices/live/error-codes.md +167 -0
- package/knowledge-base/slices/live/gift.md +84 -0
- package/knowledge-base/slices/live/ios/.gitkeep +0 -0
- package/knowledge-base/slices/live/ios/anchor-lifecycle.md +313 -0
- package/knowledge-base/slices/live/ios/anchor-preview.md +228 -0
- package/knowledge-base/slices/live/ios/anchor-room-config.md +257 -0
- package/knowledge-base/slices/live/ios/audience-list.md +353 -0
- package/knowledge-base/slices/live/ios/audience-manage.md +381 -0
- package/knowledge-base/slices/live/ios/audience-watch.md +286 -0
- package/knowledge-base/slices/live/ios/audio.md +373 -0
- package/knowledge-base/slices/live/ios/barrage.md +285 -0
- package/knowledge-base/slices/live/ios/beauty.md +323 -0
- package/knowledge-base/slices/live/ios/coguest-apply.md +506 -0
- package/knowledge-base/slices/live/ios/device-control.md +286 -0
- package/knowledge-base/slices/live/ios/error-codes.md +270 -0
- package/knowledge-base/slices/live/ios/gift.md +315 -0
- package/knowledge-base/slices/live/ios/live-list.md +269 -0
- package/knowledge-base/slices/live/ios/login-auth.md +247 -0
- package/knowledge-base/slices/live/live-list.md +82 -0
- package/knowledge-base/slices/live/login-auth.md +78 -0
- package/package.json +34 -0
- package/skills/trtc/SKILL.md +326 -0
- package/skills/trtc/room-builder/SKILL.md +138 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/README.md +108 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/backend-contract.zh-CN.md +162 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/integration.zh-CN.md +154 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/docs/theme.zh-CN.md +78 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/index.html +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/package.json +28 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/postcss.config.js +5 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/App.vue +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/ConsultationManagePanel.vue +838 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LanguageSwitch.vue +102 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/LoadingSpinner.vue +6 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalAlert.vue +34 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalBusinessPanel.vue +148 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalButton.vue +49 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalConfirmDialog.vue +68 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalDataPanel.vue +196 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/MedicalRecordPanel.vue +270 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/components/PrescriptionPanel.vue +363 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/basic-info-config.ts +29 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.d.ts +4 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/lib-generate-test-usersig-es.min.js +2 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/config/runtime-config.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/env.d.ts +32 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationChatPanel.vue +123 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationMembersPanel.vue +230 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationTranscriptionPanel.vue +135 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/ConsultationVideoStage.vue +113 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/InviteDoctorDialog.vue +132 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/components/KickMemberConfirmDialog.vue +50 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/types.ts +77 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationChat.ts +97 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationDevices.ts +48 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationParticipants.ts +121 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/useConsultationPermissions.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/features/consultation/utils.ts +70 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/en-US/index.ts +553 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/index.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/medicalTranslate.ts +85 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/state.ts +49 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/i18n/zh-CN/index.ts +463 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/main.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/appointments.ts +96 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/mock/users.ts +79 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/router/index.ts +63 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/index.ts +25 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/appointmentService.ts +77 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/authService.ts +38 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/launchContext.ts +31 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/integration/userService.ts +35 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/appointmentService.ts +43 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/authService.ts +33 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/mock/userService.ts +43 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/services/adapters/types.ts +135 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/shared/icons.ts +53 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/index.css +106 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/tailwind.css +3 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/styles/theme.css +209 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/auth.ts +50 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/format.ts +24 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/navigation.ts +12 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/utils/session.ts +28 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorConsultationView.vue +777 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/DoctorDashboardView.vue +678 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/LoginView.vue +441 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationFinishedView.vue +185 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientConsultationView.vue +1003 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientSelectDoctorView.vue +317 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/src/views/PatientWaitingView.vue +454 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.json +21 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/tsconfig.node.json +8 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation/vite.config.ts +17 -0
- package/skills/trtc/room-builder/templates/scenarios/medical-consultation//346/216/245/345/205/245/350/257/264/346/230/216.md +6 -0
- package/skills/trtc/room-builder/tools/render_ai_instructions.py +226 -0
- package/skills/trtc-apply/SKILL.md +97 -0
- package/skills/trtc-apply/guardrails/apply_lib/__init__.py +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/__pycache__/rule_parser.cpython-313.pyc +0 -0
- package/skills/trtc-apply/guardrails/apply_lib/rule_parser.py +268 -0
- package/skills/trtc-docs/SKILL.md +207 -0
- package/skills/trtc-onboarding/SKILL.md +839 -0
- package/skills/trtc-onboarding/reference/path-a1-demo.md +103 -0
- package/skills/trtc-onboarding/reference/path-a2-integrate.md +693 -0
- package/skills/trtc-onboarding/reference/path-b-troubleshoot.md +115 -0
- package/skills/trtc-onboarding/reference/path-c-expand.md +43 -0
- package/skills/trtc-onboarding/reference/reporting-protocol.md +174 -0
- package/skills/trtc-onboarding/reference/supported-matrix.md +100 -0
- package/skills/trtc-onboarding/reference/usersig-handling.md +140 -0
- package/skills/trtc-search/SKILL.md +221 -0
- package/skills/trtc-topic/SKILL.md +638 -0
- package/skills/trtc-topic/guardrails/__pycache__/gate_slice_read.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/__pycache__/gate_slice_write.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/__pycache__/stop_require_apply_evidence.cpython-313.pyc +0 -0
- package/skills/trtc-topic/guardrails/gate_slice_read.py +133 -0
- package/skills/trtc-topic/guardrails/gate_slice_write.py +169 -0
- package/skills/trtc-topic/guardrails/stop_require_apply_evidence.py +97 -0
- package/skills/trtc-topic/references/execution-units.yaml +58 -0
- package/skills/trtc-topic/runtime/README.md +50 -0
- package/skills/trtc-topic/runtime/RUNTIME.md +128 -0
- package/skills/trtc-topic/runtime/lib/__init__.py +0 -0
- package/skills/trtc-topic/runtime/lib/platforms.py +194 -0
- package/skills/trtc-topic/runtime/package-lock.json +1211 -0
- package/skills/trtc-topic/runtime/package.json +13 -0
- package/skills/trtc-topic/runtime/telemetry-bridge.mjs +339 -0
- package/skills/trtc-topic/runtime/telemetry_collector.py +293 -0
- package/skills/trtc-topic/scripts/STATE-MACHINE-GUIDE.md +186 -0
- package/skills/trtc-topic/scripts/__pycache__/apply.cpython-313.pyc +0 -0
- package/skills/trtc-topic/scripts/apply.py +581 -0
- package/skills/trtc-topic/scripts/finalize_session.py +113 -0
- package/skills/trtc-topic/scripts/init_slice_queue.py +96 -0
- package/skills/trtc-topic/scripts/lib/__pycache__/state_machine.cpython-313.pyc +0 -0
- package/skills/trtc-topic/scripts/lib/state_machine.py +328 -0
- package/skills/trtc-topic/scripts/next_slice.py +137 -0
- package/skills/trtc-topic/tests/README.md +70 -0
- package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_apply_cli.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_end_to_end.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_finalize_session.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_gates.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_session_resolver.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_state_machine.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_stop_require_apply.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.2.pyc +0 -0
- package/skills/trtc-topic/tests/__pycache__/test_topic_skill_invariants.cpython-313-pytest-9.0.3.pyc +0 -0
- package/skills/trtc-topic/tests/conftest.py +72 -0
- package/skills/trtc-topic/tests/test_apply_cli.py +480 -0
- package/skills/trtc-topic/tests/test_end_to_end.py +305 -0
- package/skills/trtc-topic/tests/test_finalize_session.py +51 -0
- package/skills/trtc-topic/tests/test_gates.py +316 -0
- package/skills/trtc-topic/tests/test_session_resolver.py +260 -0
- package/skills/trtc-topic/tests/test_state_machine.py +414 -0
- package/skills/trtc-topic/tests/test_stop_require_apply.py +99 -0
- package/skills/trtc-topic/tests/test_topic_skill_invariants.py +130 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: conference/room-lifecycle
|
|
3
|
+
name: 房间创建、加入、离开与结束
|
|
4
|
+
product: conference
|
|
5
|
+
platform: web
|
|
6
|
+
tags: [room, lifecycle, create, join, leave, end]
|
|
7
|
+
platforms: [web]
|
|
8
|
+
related: [conference/login-auth, conference/participant-list, conference/room-schedule, conference/room-call]
|
|
9
|
+
api_docs:
|
|
10
|
+
- title: 房间管理
|
|
11
|
+
url: https://cloud.tencent.com/document/product/647/126919
|
|
12
|
+
business_decisions:
|
|
13
|
+
- key: roomid_origin
|
|
14
|
+
tier: blocking
|
|
15
|
+
question: "会议的房间号从哪儿来?建议 onboarding 分两步渐进引导:先问“会议怎么发起”(自己开新会 / 由后台统一管理 / 只能受邀入会),选“后台统一管理”后再追问一句“房间号是后台早建好的,还是进会时现向后台要一个”,据此落到下面四个 value 之一。"
|
|
16
|
+
options:
|
|
17
|
+
- { label: "用户自己开新会 —— 谁发起谁建房,系统当场生成房间号", value: "frontend" }
|
|
18
|
+
- { label: "后台早就建好了 —— 前端拿现成的房间号直接进", value: "backend-precreated" }
|
|
19
|
+
- { label: "后台临时分配 —— 进会时向后台要一个房间号再进", value: "backend-allocated" }
|
|
20
|
+
- { label: "只进别人的会,自己从不建房 —— 比如纯听课/纯参会", value: "join-only" }
|
|
21
|
+
- key: creation_pattern
|
|
22
|
+
tier: blocking
|
|
23
|
+
question: "你的会议是随开随用,还是需要提前预约?(本维度与 roomid_origin 正交:号从哪来 ≠ 现在开还是约将来,两者不要合并)"
|
|
24
|
+
options:
|
|
25
|
+
- { label: "随开随用 —— 点一下马上开会", value: "instant" }
|
|
26
|
+
- { label: "提前预约 —— 先订好时间,到点再进", value: "scheduled" }
|
|
27
|
+
- { label: "两种都要", value: "both" }
|
|
28
|
+
- key: passive_exit_target
|
|
29
|
+
tier: deferrable
|
|
30
|
+
default: lobby
|
|
31
|
+
question: "用户被动离开会议(被请出、会议结束、网络断开重连失败)后,页面默认跳去哪?注意:异地登录顶替(KickedOutOfRoomReason.ReplacedByAnotherDevice)身份态已失效,强制跳登录页,不受此项影响。"
|
|
32
|
+
options:
|
|
33
|
+
- { label: "回会议列表/大厅 —— 方便再进别的会(推荐默认;仅当应用确有大厅/列表页可回时才适用)", value: "lobby" }
|
|
34
|
+
- { label: "回登录页", value: "login" }
|
|
35
|
+
- { label: "弹提示,让用户在【重新入会 / 回首页】之间自己决定", value: "prompt-user" }
|
|
36
|
+
decision_constraints:
|
|
37
|
+
- when: { roomid_origin: join-only }
|
|
38
|
+
forbid: { creation_pattern: both }
|
|
39
|
+
reason: "“只进别人的会”意味着前端不具备建房能力,无法支撑“即时+预约都要”;onboarding 选到此组合时应校验拦截,提示改选 instant 或调整 roomid_origin。"
|
|
40
|
+
- when: { roomid_origin: join-only }
|
|
41
|
+
adjust: { passive_exit_target: { disable_option: lobby, prefer: [login, prompt-user] } }
|
|
42
|
+
reason: "纯受邀/链接入会的应用通常没有大厅或会议列表页可回,lobby 不可达;此场景应灰掉 lobby 选项,默认推 login 或 prompt-user。"
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# 房间创建、加入、离开与结束
|
|
46
|
+
|
|
47
|
+
## 功能说明
|
|
48
|
+
|
|
49
|
+
房间生命周期负责一场 Conference 通用会议从"被创建"到"被结束"的主链路,覆盖即时会议发起、加入已有房间、在无法确认房间是否已存在时直接创建并加入、主动离房、房主结束会议以及被动退房后的状态收口。它是会议产品的主干流程,服务端预创建房间或代解散房间时,前端仍需通过同一套生命周期能力完成真实入会和退场。
|
|
50
|
+
|
|
51
|
+
创建时可通过 `options` 传入房间名称(`roomName`)、密码(`password`)和默认入会规则(`isAllMicrophoneDisabled` 等),这些配置决定了成员进入房间后的初始受限状态。房主在会中也可通过 `updateRoomInfo()` 修改房间名称和密码。
|
|
52
|
+
|
|
53
|
+
## 核心概念
|
|
54
|
+
|
|
55
|
+
### 角色与操作
|
|
56
|
+
|
|
57
|
+
| 角色 | 关键操作 | 说明 |
|
|
58
|
+
|------|----------|------|
|
|
59
|
+
| 房主 / 发起人 | 创建并加入房间、结束房间 | 房主通常拥有会议生命周期中的最高控制权 |
|
|
60
|
+
| 普通参会人 | 加入已有房间、主动离房 | 普通成员可以进入和离开会议,但不能结束整个房间 |
|
|
61
|
+
| 服务端业务系统 | 预创建 / 销毁房间 | 可通过服务端能力提前准备会议,但前端仍负责真正入会与状态收口 |
|
|
62
|
+
| 客户端应用 | 监听生命周期变化 | 负责处理房间结束、被踢、异常断开、重进等状态变化 |
|
|
63
|
+
|
|
64
|
+
### 事件流
|
|
65
|
+
|
|
66
|
+
| 阶段 | 参与方 | 关键动作 |
|
|
67
|
+
|------|--------|----------|
|
|
68
|
+
| 登录就绪 | 用户 → 客户端 | 完成登录,确认当前用户已具备可调用房间能力的身份态 |
|
|
69
|
+
| 创建或加入 | 客户端 | 已知房间存在时发起 `joinRoom`;若只知道 `roomId` 但不确定房间是否存在,可直接发起 `createAndJoinRoom` |
|
|
70
|
+
| 会议建立 | 房间状态 | `currentRoom` 建立,参会人列表和布局开始同步 |
|
|
71
|
+
| 退出会议 | 用户 / 系统 | 发生主动离房、房主结束、被踢出、网络异常断开等事件 |
|
|
72
|
+
| 状态清理 | 客户端 | 清理房间上下文、会中状态和界面残留,恢复到可再次入会的初始态 |
|
|
73
|
+
|
|
74
|
+
### 状态与数据
|
|
75
|
+
|
|
76
|
+
| 数据 / 状态 | 说明 |
|
|
77
|
+
|-------------|------|
|
|
78
|
+
| `roomId` | 当前房间唯一标识,创建和加入都会围绕它展开 |
|
|
79
|
+
| `currentRoom` | 当前房间的核心响应式状态入口 |
|
|
80
|
+
| 登录就绪状态 | 决定当前是否已经可以安全发起创建、加入、离房或结束动作 |
|
|
81
|
+
| 生命周期状态 | 表示当前处于创建中、加入中、会中、离房中或已结束 |
|
|
82
|
+
| 房主信息 | 决定谁有权结束会议以及执行部分管理能力 |
|
|
83
|
+
| 单用户单房间约束 | 同一用户同一时刻通常只能维持一个有效房间上下文 |
|
|
84
|
+
| 被动退房原因 | 用于区分房间结束、被踢、网络异常等不同退出来源 |
|
|
85
|
+
|
|
86
|
+
### 状态机
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
idle
|
|
90
|
+
→ creating / joining
|
|
91
|
+
→ joined
|
|
92
|
+
→ leaving / ending
|
|
93
|
+
→ idle
|
|
94
|
+
|
|
95
|
+
joined
|
|
96
|
+
→ kicked-out
|
|
97
|
+
→ room-ended
|
|
98
|
+
→ reconnecting
|
|
99
|
+
→ idle
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 典型接入场景
|
|
103
|
+
|
|
104
|
+
| 场景 | 推荐主路径 | 说明 |
|
|
105
|
+
|------|------------|------|
|
|
106
|
+
| 临时沟通 / 即时会议 | 发起人 `createAndJoinRoom`,其他成员 `joinRoom` | 适合 IM 会话内快速开会或临时拉会 |
|
|
107
|
+
| 预约会议到点入会 | 先通过 `room-schedule` 完成预约,真正开会时回到 `joinRoom` 或 `createAndJoinRoom` | 预约成功不等于已经进入会议 |
|
|
108
|
+
| 服务端统一创建会议 | 服务端预先生成并维护 `roomId`,客户端在指定入口 `joinRoom` | 适合政务、医疗、企业 OA 等强管控场景 |
|
|
109
|
+
| 双向对等发起 | 直接使用 `createAndJoinRoom` | 适合在线问诊、视频面试、1v1 客服等无法预判谁先入会的场景 |
|
|
110
|
+
| 邀请链接 / 会议列表入会 | `joinRoom` | 前提是房间已经由发起人、预约系统或服务端准备好 |
|
|
111
|
+
|
|
112
|
+
### 被动退房与失败分流
|
|
113
|
+
|
|
114
|
+
| 类型 | 常见来源 | 处理重点 |
|
|
115
|
+
|------|----------|----------|
|
|
116
|
+
| 房间被结束 | 房主调用结束会议 | 提示会议已结束,并立即收口会中 UI 与状态 |
|
|
117
|
+
| 成员被移出 | 房主 / 管理员移出成员 | 给出明确原因提示,不要只停留在旧页面 |
|
|
118
|
+
| 账号被顶替 / 异地登录 | 同账号在其他设备进入会议 | 提示当前设备已失效,并回到安全的可重入状态 |
|
|
119
|
+
| 断线或重连失败 | 网络超时、离线期间房间状态已变化 | 区分临时重连与最终退房,避免页面假在线 |
|
|
120
|
+
| 房间不存在 | 对不存在的房间调用 `joinRoom` | 提示房间不存在;若属于双向对等发起场景,可改走 `createAndJoinRoom` |
|
|
121
|
+
| 房间人数已满 | 房间达到成员上限 | 给出明确失败提示,并引导稍后重试或联系房主 |
|
|
122
|
+
| `roomId` 已占用 | 创建时使用了已被占用的 `roomId` | 回查 `roomId` 生成策略;若允许“存在则加入”,可改走 `createAndJoinRoom` |
|
|
123
|
+
|
|
124
|
+
## 前置条件
|
|
125
|
+
**通用依赖**:见 [login-auth 平台 slice](login-auth.md)。
|
|
126
|
+
|
|
127
|
+
**额外依赖**:
|
|
128
|
+
- 已安装 `tuikit-atomicx-vue3@latest`
|
|
129
|
+
|
|
130
|
+
**前置状态**:
|
|
131
|
+
- 已阅读 `conference/room-lifecycle`,明确当前能力的产品边界。
|
|
132
|
+
- 已完成 `conference/login-auth`,确保当前页面具备稳定登录态。
|
|
133
|
+
- 已根据业务流程接入会议上下文;需要房间状态时,优先通过当前 slice 统一承接。
|
|
134
|
+
|
|
135
|
+
## 最佳实践
|
|
136
|
+
|
|
137
|
+
### ✅ ALWAYS
|
|
138
|
+
|
|
139
|
+
1. **把创建、加入、离开、结束视为同一条生命周期链路** —— 不要只写“进房成功”的快乐路径,退场和异常分支同样是主流程的一部分。
|
|
140
|
+
2. **登录真正就绪后再触发房间生命周期动作** —— 未确认登录态时抢跑调用,很容易导致入房失败或状态漂移。
|
|
141
|
+
3. **根据是否确定房间已存在选择 `joinRoom` 或 `createAndJoinRoom`** —— 已知房间存在就直接加入;无法确认存在性时再走“存在则加入,不存在则创建”的路径。
|
|
142
|
+
4. **把服务端预创建房间与端上即时入会统一收口到前端生命周期管理** —— 即使房间由服务端准备,前端仍要显式处理入房与离房状态。
|
|
143
|
+
5. **对被动退房做明确原因区分** —— 房间结束、被踢、网络断连需要不同的 UI 提示与状态恢复方式。
|
|
144
|
+
6. **离房或结束后立即清理会中上下文** —— 包括当前房间状态、局部面板、聊天上下文和布局焦点,避免残留到下一场会议。
|
|
145
|
+
7. **让 `options` 模型集中维护房间配置,让生命周期负责流程切换** —— `roomName`、`password`、默认规则属于配置语义,建议收口到一个 `baseRoomOptions` 对象;创建 / 加入 / 离开 / 结束才属于生命周期语义。
|
|
146
|
+
|
|
147
|
+
### ❌ NEVER
|
|
148
|
+
|
|
149
|
+
1. **不要把接受邀请等同于已经入会** —— 邀请只是前置信令,真正进入会议仍应回到房间生命周期执行。
|
|
150
|
+
2. **不要只处理主动离房,不处理被动退房** —— 房间主链路必须覆盖被踢、被结束、重连失败等异常分支。
|
|
151
|
+
3. **不要在旧房间状态未清理前直接复用下一场会议上下文** —— 很容易造成房间号错乱、成员状态串场或 UI 残留。
|
|
152
|
+
4. **不要在 `room-lifecycle` 里把预约时间、参会人等排期字段当成房间配置主语义** —— 这些是 `room-schedule` 的时间维度能力。
|
|
153
|
+
|
|
154
|
+
## 代码示例
|
|
155
|
+
### 场景一:房主 / 发起人直接创建并进入快速会议
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
159
|
+
|
|
160
|
+
const { createAndJoinRoom, currentRoom } = useRoomState();
|
|
161
|
+
|
|
162
|
+
await createAndJoinRoom({
|
|
163
|
+
roomId: 'demo_room',
|
|
164
|
+
options: { roomName: '演示会议' },
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
console.log(currentRoom.value?.roomId);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 场景二:已知房间已经存在,直接加入
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
174
|
+
|
|
175
|
+
const { joinRoom, currentRoom } = useRoomState();
|
|
176
|
+
|
|
177
|
+
await joinRoom({
|
|
178
|
+
roomId: 'demo_room',
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
console.log(currentRoom.value?.roomId);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 场景三:只知道 `roomId`,但不确定房间是否已经存在
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
188
|
+
|
|
189
|
+
const { createAndJoinRoom, currentRoom } = useRoomState();
|
|
190
|
+
|
|
191
|
+
await createAndJoinRoom({
|
|
192
|
+
roomId: 'demo_room',
|
|
193
|
+
options: { roomName: '业务沟通房间' },
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
console.log(currentRoom.value?.roomId);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 场景四:会议结束前正确收口
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
203
|
+
|
|
204
|
+
const { leaveRoom, endRoom } = useRoomState();
|
|
205
|
+
|
|
206
|
+
await leaveRoom();
|
|
207
|
+
// 房主结束会议:await endRoom();
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 场景五:创建带配置的会议(房间名称、密码、默认规则)
|
|
211
|
+
|
|
212
|
+
创建会议时可通过 `options` 传入房间名称、密码和默认入会规则(全员禁麦/禁画/禁共享/禁消息),这些配置会决定成员进入房间后的初始受限状态。
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import { reactive, computed } from 'vue';
|
|
216
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
217
|
+
|
|
218
|
+
const { createAndJoinRoom } = useRoomState();
|
|
219
|
+
|
|
220
|
+
const roomDraft = reactive({
|
|
221
|
+
roomId: 'room_20260507_001',
|
|
222
|
+
roomName: '产品评审会',
|
|
223
|
+
password: '123456',
|
|
224
|
+
isAllMicrophoneDisabled: true,
|
|
225
|
+
isAllCameraDisabled: true,
|
|
226
|
+
isAllScreenShareDisabled: true,
|
|
227
|
+
isAllMessageDisabled: true,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const baseRoomOptions = computed(() => ({
|
|
231
|
+
roomName: roomDraft.roomName.trim(),
|
|
232
|
+
password: roomDraft.password || undefined,
|
|
233
|
+
isAllMicrophoneDisabled: roomDraft.isAllMicrophoneDisabled,
|
|
234
|
+
isAllCameraDisabled: roomDraft.isAllCameraDisabled,
|
|
235
|
+
isAllScreenShareDisabled: roomDraft.isAllScreenShareDisabled,
|
|
236
|
+
isAllMessageDisabled: roomDraft.isAllMessageDisabled,
|
|
237
|
+
}));
|
|
238
|
+
|
|
239
|
+
async function createConfiguredRoom() {
|
|
240
|
+
await createAndJoinRoom({
|
|
241
|
+
roomId: roomDraft.roomId,
|
|
242
|
+
options: baseRoomOptions.value,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
> **说明:**
|
|
248
|
+
> - `baseRoomOptions` 可以在即时会议和预约会议中复用;预约会议时额外补充 `scheduleStartTime`、`scheduleEndTime`、`scheduleAttendees` 等字段(由 `room-schedule` 承接)。
|
|
249
|
+
> - 默认规则字段映射(Web):`isAllMicrophoneDisabled` / `isAllCameraDisabled` / `isAllScreenShareDisabled` / `isAllMessageDisabled`,对应全员禁麦、禁画、禁共享、禁消息。
|
|
250
|
+
> - 当默认规则为 `true` 时,前端不应只在接口侧生效,还应同步让对应按钮切到禁用图标和禁用提示态(见下方 UI 状态派生)。
|
|
251
|
+
|
|
252
|
+
### 默认规则驱动 UI 状态派生
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
const toolbarUiState = computed(() => ({
|
|
256
|
+
microphone: {
|
|
257
|
+
disabled: baseRoomOptions.value.isAllMicrophoneDisabled,
|
|
258
|
+
icon: baseRoomOptions.value.isAllMicrophoneDisabled ? 'mic-off-disabled' : 'mic-on',
|
|
259
|
+
tooltip: baseRoomOptions.value.isAllMicrophoneDisabled ? '房主已开启全员静音' : '打开麦克风',
|
|
260
|
+
},
|
|
261
|
+
camera: {
|
|
262
|
+
disabled: baseRoomOptions.value.isAllCameraDisabled,
|
|
263
|
+
icon: baseRoomOptions.value.isAllCameraDisabled ? 'cam-off-disabled' : 'cam-on',
|
|
264
|
+
tooltip: baseRoomOptions.value.isAllCameraDisabled ? '房主已禁用摄像头' : '打开摄像头',
|
|
265
|
+
},
|
|
266
|
+
}));
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 场景六:会中修改房间名称或密码
|
|
270
|
+
|
|
271
|
+
房主在会议中可调用 `updateRoomInfo()` 修改房间基础信息,但必须确认仍在当前房间内。
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import { useRoomState } from 'tuikit-atomicx-vue3/room';
|
|
275
|
+
|
|
276
|
+
const { updateRoomInfo, currentRoom } = useRoomState();
|
|
277
|
+
|
|
278
|
+
async function updateRoomNameOrPassword(newName: string, newPassword?: string) {
|
|
279
|
+
if (!currentRoom.value) {
|
|
280
|
+
console.warn('当前不在任何房间内,不能更新房间信息');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
await updateRoomInfo({
|
|
285
|
+
roomId: currentRoom.value.roomId,
|
|
286
|
+
options: {
|
|
287
|
+
roomName: newName.trim(),
|
|
288
|
+
password: newPassword || undefined,
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 处理房间结束与被动退房:监听房间被解散、被踢和异常退出
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import { onMounted, onUnmounted } from 'vue';
|
|
298
|
+
import {
|
|
299
|
+
useRoomParticipantState,
|
|
300
|
+
useRoomState,
|
|
301
|
+
RoomEvent,
|
|
302
|
+
RoomParticipantEvent,
|
|
303
|
+
KickedOutOfRoomReason,
|
|
304
|
+
} from 'tuikit-atomicx-vue3/room';
|
|
305
|
+
|
|
306
|
+
const { subscribeEvent, unsubscribeEvent } = useRoomState();
|
|
307
|
+
const {
|
|
308
|
+
subscribeEvent: subscribeParticipantEvent,
|
|
309
|
+
unsubscribeEvent: unsubscribeParticipantEvent,
|
|
310
|
+
} = useRoomParticipantState();
|
|
311
|
+
|
|
312
|
+
// passive_exit_target 决定“被动离开后默认跳哪”:'lobby' | 'login' | 'prompt-user'
|
|
313
|
+
// 由 business_decisions 注入;这里以 'lobby' 为例
|
|
314
|
+
const passiveExitTarget: 'lobby' | 'login' | 'prompt-user' = 'lobby';
|
|
315
|
+
|
|
316
|
+
// 关键:跳转前必须先清理会中上下文,否则下一场会议会串场(聊天/布局/成员残留)
|
|
317
|
+
function cleanupRoomContext() {
|
|
318
|
+
// 清理 currentRoom 派生状态、聊天上下文、布局焦点、局部面板等
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function routeAfterPassiveExit(target: 'lobby' | 'login' | 'prompt-user') {
|
|
322
|
+
cleanupRoomContext();
|
|
323
|
+
switch (target) {
|
|
324
|
+
case 'login':
|
|
325
|
+
// router.replace('/login')
|
|
326
|
+
break;
|
|
327
|
+
case 'prompt-user':
|
|
328
|
+
// 弹窗,提供【重新入会 / 回首页】两个动作,由用户决定
|
|
329
|
+
break;
|
|
330
|
+
case 'lobby':
|
|
331
|
+
default:
|
|
332
|
+
// router.replace('/meeting/lobby') —— 前提是应用确有大厅/列表页
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function onRoomEnded() {
|
|
338
|
+
console.log('房主已结束会议');
|
|
339
|
+
routeAfterPassiveExit(passiveExitTarget);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function onKickedFromRoom({ reason }: { reason: KickedOutOfRoomReason; message: string }) {
|
|
343
|
+
switch (reason) {
|
|
344
|
+
case KickedOutOfRoomReason.KickedByAdmin:
|
|
345
|
+
console.log('当前用户被房主或管理员移出房间');
|
|
346
|
+
routeAfterPassiveExit(passiveExitTarget);
|
|
347
|
+
break;
|
|
348
|
+
case KickedOutOfRoomReason.ReplacedByAnotherDevice:
|
|
349
|
+
// 异地登录顶替:当前设备身份态已失效,强制回登录页,覆盖 passiveExitTarget
|
|
350
|
+
console.log('当前账号已在其他设备进入会议');
|
|
351
|
+
routeAfterPassiveExit('login');
|
|
352
|
+
break;
|
|
353
|
+
case KickedOutOfRoomReason.ConnectionTimeout:
|
|
354
|
+
console.log('网络连接超时,当前会议状态需要重新确认');
|
|
355
|
+
routeAfterPassiveExit(passiveExitTarget);
|
|
356
|
+
break;
|
|
357
|
+
default:
|
|
358
|
+
console.log('当前用户已退出房间');
|
|
359
|
+
routeAfterPassiveExit(passiveExitTarget);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
onMounted(() => {
|
|
365
|
+
subscribeEvent(RoomEvent.onRoomEnded, onRoomEnded);
|
|
366
|
+
subscribeParticipantEvent(RoomParticipantEvent.onKickedFromRoom, onKickedFromRoom);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
onUnmounted(() => {
|
|
370
|
+
unsubscribeEvent(RoomEvent.onRoomEnded, onRoomEnded);
|
|
371
|
+
unsubscribeParticipantEvent(RoomParticipantEvent.onKickedFromRoom, onKickedFromRoom);
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## 调用时序
|
|
376
|
+
```
|
|
377
|
+
完成 login-auth
|
|
378
|
+
│
|
|
379
|
+
▼
|
|
380
|
+
决定当前路径:创建会议 或 加入已有会议
|
|
381
|
+
│
|
|
382
|
+
├─ 房主端 → createAndJoinRoom({ roomId, options })
|
|
383
|
+
└─ 成员端 → joinRoom({ roomId })
|
|
384
|
+
│
|
|
385
|
+
▼
|
|
386
|
+
以 currentRoom 作为会议内真实状态来源
|
|
387
|
+
│
|
|
388
|
+
├─ 普通离开 → leaveRoom()
|
|
389
|
+
├─ 房主结束 → endRoom()
|
|
390
|
+
└─ 会议被结束 → 通过事件和 currentRoom 变化收口 UI
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## 平台特有注意事项
|
|
394
|
+
### 1. 登录真正就绪后再调用房间生命周期接口
|
|
395
|
+
`login()` 是异步动作。单页应用里更适合监听 `loginUserInfo.value?.userId` 或等价登录完成信号,确认用户身份已就绪后再调用 `createAndJoinRoom()`、`joinRoom()`、`leaveRoom()`、`endRoom()`。
|
|
396
|
+
|
|
397
|
+
### 2. `useRoomState` 是单例,同一时刻只承接一个房间上下文
|
|
398
|
+
同一用户同一时间通常只能处于一个有效房间内。切房前应先完成上一场会议的离房或结束收口,避免多个房间状态并存。
|
|
399
|
+
|
|
400
|
+
### 3. 按业务目标区分 `createAndJoinRoom()` 与 `joinRoom()`
|
|
401
|
+
如果当前用户就是房主 / 发起人,需要立即创建并进入一场新会议,应使用 `createAndJoinRoom()`;如果房间已经由发起人、会议列表、预约系统或服务端预先创建好,应使用 `joinRoom()`;如果双方只知道同一个 `roomId`,但无法预先判断房间是否存在,也更适合使用 `createAndJoinRoom()` 承接“存在则加入,不存在则创建”的场景。
|
|
402
|
+
|
|
403
|
+
调用 `joinRoom()` 时只需要传入 `roomId`;如果是密码房,再额外传入顶层 `password` 字段,例如 `joinRoom({ roomId, password })`。不要把密码或空对象包进 `options`,当前 Web API 的加入房间签名并不接收 `options`。
|
|
404
|
+
|
|
405
|
+
### 4. `leaveRoom()` 与 `endRoom()` 是两类不同动作
|
|
406
|
+
普通成员离开会议应调用 `leaveRoom()`;房主若要真正解散会议,需要调用 `endRoom()`,两者语义不能混用。
|
|
407
|
+
|
|
408
|
+
### 5. `currentRoom` 是会中真实状态源
|
|
409
|
+
即使房间由服务端预创建、预销毁或通过其他链路调度,前端仍要以 `currentRoom` 和实际入会流程作为最终真实状态来源。
|
|
410
|
+
|
|
411
|
+
### 6. 密码房和入会错误需要业务侧自行承接
|
|
412
|
+
加入密码房时,要准备好对 `ERR_NEED_PASSWORD`、`ERR_WRONG_PASSWORD` 等结果做输入与重试处理;若出现房间不存在、人数已满等错误,也应给出明确反馈,而不是只在控制台报错。
|
|
413
|
+
|
|
414
|
+
### 7. 被动退房最好通过事件与页面收口统一处理
|
|
415
|
+
房主结束会议、成员被踢、异地登录顶替、网络超时等情况,本质上都属于“被动离开当前房间”。业务层最好统一监听房间事件并收口页面,而不是分别在多个组件里零散兜底。
|
|
416
|
+
|
|
417
|
+
被动退房后的跳转目标由 `passive_exit_target` 决策驱动,但**跳转目标不是一刀切**,要按退出原因分层:
|
|
418
|
+
|
|
419
|
+
| 退出原因 | 来源 | 跳转目标 |
|
|
420
|
+
|----------|------|----------|
|
|
421
|
+
| 房主结束 / 被移出 / 重连失败 | `onRoomEnded`、`KickedByAdmin`、`ConnectionTimeout` | 用 `passive_exit_target` 的选择(`lobby` / `login` / `prompt-user`) |
|
|
422
|
+
| 异地登录顶替 | `KickedOutOfRoomReason.ReplacedByAnotherDevice` | **强制 `login`**,覆盖 `passive_exit_target` —— 当前设备身份态已失效,跳大厅会立刻再次失败 |
|
|
423
|
+
|
|
424
|
+
两条额外约束:
|
|
425
|
+
|
|
426
|
+
- **跳转前必须先清理会中上下文**(`currentRoom` 派生状态、聊天、布局、局部面板),否则跳回大厅再进下一场会议会串场。
|
|
427
|
+
- **`lobby` 可达性依赖应用形态**:纯受邀 / 邀请链接直接入会(`roomid_origin = join-only`)的应用通常没有大厅或会议列表页,此时 `lobby` 不可达,应在 onboarding 灰掉该选项,默认推 `login` 或 `prompt-user`。
|
|
428
|
+
- **`prompt-user` 必须定义弹窗动作集合**:约定提供【重新入会 / 回首页】两个动作,否则生成代码时无从决定按钮。
|
|
429
|
+
|
|
430
|
+
### 8. `roomId` 应由业务侧保证唯一性
|
|
431
|
+
建议由业务后端生成全局唯一 `roomId`,避免测试环境与正式环境、不同会议之间发生 ID 冲突或复用歧义。
|
|
432
|
+
|
|
433
|
+
### 9. 建房时把配置收口到一个 `baseRoomOptions` 对象
|
|
434
|
+
`roomName`、`password`、默认规则等字段的维护与解释,建议收口到一个 `baseRoomOptions` / `roomDraft` 对象,避免散落在多个分支里。默认规则字段在 Web 侧对应 `isAllMicrophoneDisabled`、`isAllCameraDisabled`、`isAllScreenShareDisabled`、`isAllMessageDisabled`,它们同时决定了按钮图标、禁用态和提示文案。
|
|
435
|
+
|
|
436
|
+
### 10. 默认规则生效后,按钮图标和禁用态也要同步
|
|
437
|
+
例如 `isAllMicrophoneDisabled` 为 `true` 时,麦克风按钮不应继续显示为"可开麦"图标;更合理的做法是同步切换到禁用态图标、禁用点击并展示"房主已开启全员静音"之类的提示。`isAllCameraDisabled`、`isAllScreenShareDisabled`、`isAllMessageDisabled` 也应同理映射到对应入口的禁用态。
|
|
438
|
+
|
|
439
|
+
### 11. `updateRoomInfo()` 仅适合房主在会中执行
|
|
440
|
+
更新房间名称或密码前,应确认操作者仍在当前房间内;如果房主已经离房,通常需要重新入会后再修改。
|
|
441
|
+
|
|
442
|
+
### 12. 创建期默认规则与会中动态治理要分层
|
|
443
|
+
默认禁麦、禁画、禁共享、禁消息等规则适合在 `options` 中一次性声明。会中临时禁言、关闭单成员设备等动作仍应由 `conference/participant-management` 承接。
|
|
444
|
+
|
|
445
|
+
### 13. 密码字段属于配置语义,但密码交互属于入会流程语义
|
|
446
|
+
创建时写入 `password`;加入密码房时,密码输入、错误提示和重试逻辑,应由本 slice 的加入流程承接。
|
|
447
|
+
|
|
448
|
+
## 常见错误与场景对照
|
|
449
|
+
|
|
450
|
+
| 错误 / 场景 | 常见触发时机 | 建议处理方式 |
|
|
451
|
+
|-------------|--------------|--------------|
|
|
452
|
+
| `ERR_NEED_PASSWORD` | 加入密码房但未传密码 | 弹出密码输入框,输入后再次调用 `joinRoom({ roomId, password })` |
|
|
453
|
+
| `ERR_WRONG_PASSWORD` | 输入的入会密码错误 | 提示密码错误,并允许用户修正顶层 `password` 后重试 |
|
|
454
|
+
| `ERR_ROOM_ID_NOT_EXIST` | 对不存在的房间调用 `joinRoom({ roomId })` | 提示房间不存在;若属于对等发起场景可改走 `createAndJoinRoom()` |
|
|
455
|
+
| `ERR_ROOM_USER_FULL` | 房间人数达到上限 | 提示房间已满,引导稍后重试或联系房主 |
|
|
456
|
+
| `ERR_ROOM_ID_OCCUPIED` | 创建时 `roomId` 已被占用 | 检查 `roomId` 生成策略;若允许“存在则加入”,优先使用 `createAndJoinRoom()` |
|
|
457
|
+
| `RoomEvent.onRoomEnded` | 房主结束当前会议 | 提示会议已结束,并退出会中页面 |
|
|
458
|
+
| `RoomParticipantEvent.onKickedFromRoom` | 当前用户被移出、被顶替或重连失败 | 根据 `reason` 区分提示文案,并回收当前会中状态 |
|
|
459
|
+
|
|
460
|
+
## 代码生成约束
|
|
461
|
+
### 编译必要条件
|
|
462
|
+
- **通用条件**:见 [login-auth 平台 slice](login-auth.md)。
|
|
463
|
+
- **额外导入**:至少需要导入 `useRoomState`。
|
|
464
|
+
- **运行前提**:页面已具备有效登录态,且拿到可用的 `roomId`。
|
|
465
|
+
|
|
466
|
+
### 生成规则
|
|
467
|
+
#### MUST(生成时必须包含)
|
|
468
|
+
|
|
469
|
+
1. **通过 `useRoomState` 承接创建、加入、离开和结束会议的主链路** — 才能让状态与 UI 从同一来源收口。
|
|
470
|
+
**Verify**: 检查是否存在 `useRoomState()` 与生命周期 API 调用。
|
|
471
|
+
2. **在登录真正就绪后再触发房间生命周期动作** — 未确认登录完成时抢跑调用很容易导致状态异常。
|
|
472
|
+
**Verify**: 检查是否存在登录完成判断,例如监听 `loginUserInfo.value?.userId` 或等价登录完成信号。
|
|
473
|
+
3. **按业务目标选择 `createAndJoinRoom()` 或 `joinRoom()`** — 房主快速创建并入会、以及无法确认房间是否存在时,都更适合 `createAndJoinRoom()`;只有已知房间已存在时才直接使用 `joinRoom()`。
|
|
474
|
+
**Verify**: 检查是否把“房主创建并入会”“已知房间存在直接加入”“存在性未知时尝试进入”这三类路径明确区分。
|
|
475
|
+
4. **把 `currentRoom` 作为会中状态锚点** — 能避免页面层与房间真实状态漂移。
|
|
476
|
+
**Verify**: 检查是否读取 `currentRoom` 或围绕其变化更新页面。
|
|
477
|
+
5. **为密码房和常见入会错误预留业务反馈** — 无 UI 接入时,密码输入、重试和错误提示都需要页面自行承接。
|
|
478
|
+
**Verify**: 检查加入流程是否处理 `ERR_NEED_PASSWORD`、`ERR_WRONG_PASSWORD` 或等价失败提示。
|
|
479
|
+
6. **被动退房后按 `passive_exit_target` 决策收口路由,且跳转前先清理会中上下文** — 房主结束、被移出、重连失败走该决策选定目标;`ReplacedByAnotherDevice` 强制跳登录页,覆盖该决策。
|
|
480
|
+
**Verify**: 检查 `onRoomEnded` / `onKickedFromRoom` 中是否存在按 `reason` 分层的跳转,且跳转前调用了上下文清理;`creation_pattern` / `roomid_origin` 的代码分支与决策值一致。
|
|
481
|
+
|
|
482
|
+
#### MUST NOT(生成时绝不能出现)
|
|
483
|
+
|
|
484
|
+
1. **不要把 `leaveRoom()` 当成解散会议** — 会导致房主离开后房间仍在。
|
|
485
|
+
**Verify**: 检查房主结束逻辑是否明确调用 `endRoom()`。
|
|
486
|
+
2. **不要只信任服务端预创建结果而跳过前端真实入会状态判断** — 页面可能显示“已在会中”但底层并未入房。
|
|
487
|
+
**Verify**: 检查是否仍通过 `joinRoom()` / `createAndJoinRoom()` 与 `currentRoom` 收口。
|
|
488
|
+
|
|
489
|
+
### 集成检查点
|
|
490
|
+
- 当前 slice 是 `conference/web` 大多数能力的房间状态基座。
|
|
491
|
+
- 集成方式通常是新增页面路由状态或 ViewModel,不需要改 SDK 底层。
|
|
492
|
+
- 若业务同时存在预约会议、呼叫入会或服务端预创建房间,需要统一约定 `roomId` 和入会入口。
|
|
493
|
+
|
|
494
|
+
## 验证矩阵
|
|
495
|
+
| 层级 | 检查项 | 验证手段 | 预期结果 |
|
|
496
|
+
|------|--------|----------|---------|
|
|
497
|
+
| 1. 编译级 | 已导入 `useRoomState` | 检查 `import` 语句 | 房间生命周期 Hook 可解析 |
|
|
498
|
+
| 2. 静态规则级 | 进房路径、离开与结束动作分层明确 | 搜索 `joinRoom` / `createAndJoinRoom` / `leaveRoom` / `endRoom` | 进入、离开、结束职责清晰 |
|
|
499
|
+
| 3. 运行时级 | 创建 / 加入会议后 `currentRoom` 可用 | 进房并查看调试状态 | 可读取有效 `roomId` |
|
|
500
|
+
| 4. 业务行为级 | 密码房与错误提示、离开与结束后的页面状态正确收口 | 分别测试密码入会、离会与结束会议 | UI 与房间真实状态一致,失败时有明确反馈 |
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
> **official-roomkit 模式用户注意**:如果 `ui_mode = official-roomkit`,
|
|
505
|
+
> 房间操作通过 `conference` 对象而非直接 composable。
|
|
506
|
+
> 完整的 `conference` API 签名、枚举定义和代码示例见
|
|
507
|
+
> **[`conference/web/official-roomkit-api.md`](./official-roomkit-api.md)**。
|
|
508
|
+
|
|
509
|
+
## 排障指南
|
|
510
|
+
|
|
511
|
+
### 常见问题
|
|
512
|
+
|
|
513
|
+
| 问题 | 表现 | 处理建议 |
|
|
514
|
+
|------|------|----------|
|
|
515
|
+
| 进房失败 | 创建或加入调用后未能进入会中态 | 先检查登录是否完成,再确认房间配置参数、房间号和调用时机是否正确 |
|
|
516
|
+
| 房间已结束但 UI 未退出 | 房主结束会议后,部分参会人页面仍停留在会中 | 检查是否监听并处理了房间结束、被动退房与清理逻辑 |
|
|
517
|
+
| 离房后状态残留 | 再次入会时看到上一场会议的聊天、布局或成员数据 | 检查离房和结束路径是否统一清理 `currentRoom` 及相关派生状态 |
|
|
518
|
+
|
|
519
|
+
### 排障流程
|
|
520
|
+
|
|
521
|
+
```text
|
|
522
|
+
发现 房间创建、加入、离开与结束 相关问题
|
|
523
|
+
├── 第 1 步:确认登录是否已完成,并且 roomId / roomName / options 使用的是当前会议上下文
|
|
524
|
+
├── 第 2 步:检查当前流程属于创建、加入、主动离房还是被动退房,不要混淆处理分支
|
|
525
|
+
├── 第 3 步:确认 currentRoom 建立与销毁时,参会人列表、布局、聊天等派生状态是否同步收口
|
|
526
|
+
└── 第 4 步:若仍异常,再回查 login-auth / participant-list / room-schedule 的衔接是否正确
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## 关联知识
|
|
530
|
+
|
|
531
|
+
- **[conference/login-auth](login-auth.md)** —— 房间生命周期开始前的统一身份鉴权入口。
|
|
532
|
+
- **[conference/room-schedule](room-schedule.md)** —— 预约会议复用房间配置模型,并补充时间与参会人维度。
|
|
533
|
+
- **[conference/room-call](room-call.md)** —— 会中呼叫房外用户入会,呼叫接受后仍需回到本 slice 执行入房。
|
|
534
|
+
- **[conference/participant-list](participant-list.md)** —— 进房成功后开始同步的成员读模型与状态展示。
|