@tencentcloud/sdk-mcp 1.6.6 → 1.6.8
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/knowledge/build-index.js +4 -1
- package/knowledge/content-loader.js +3 -1
- package/knowledge/search/filter-pool.js +12 -4
- package/knowledge/search/query-normalizer.js +76 -0
- package/knowledge/search/search-knowledge.js +104 -5
- package/package.json +1 -1
- package/resource/_schema/feature-aliases.yaml +1 -0
- package/resource/_schema/query-normalization.yaml +9 -0
- package/resource/index/component-slugs.json +1 -0
- package/resource/index/doc-source-urls.json +1 -0
- package/resource/index/manifest.json +1 -0
- package/resource/integration/callkit/preset/android/integration.md +0 -14
- package/resource/integration/callkit/preset/flutter/integration.md +0 -9
- package/resource/integration/callkit/preset/ios/integration.md +2 -15
- package/resource/integration/callkit/preset/react/integration.md +0 -21
- package/resource/integration/callkit/preset/vue/integration.md +0 -27
- package/resource/integration/chat/preset/android/integration.md +3 -10
- package/resource/integration/chat/preset/flutter/integration.md +11 -13
- package/resource/integration/chat/preset/ios/integration.md +9 -16
- package/resource/integration/chat/preset/react/integration.md +1 -9
- package/resource/integration/chat/preset/uni-app/integration.md +0 -9
- package/resource/integration/chat/preset/vue/integration.md +3 -13
- package/resource/integration/livekit/preset/live/android/live-host-integration.md +0 -4
- package/resource/integration/livekit/preset/live/android/prepare-integration.md +8 -21
- package/resource/integration/livekit/preset/live/ios/live-audience-integration.md +0 -1
- package/resource/integration/livekit/preset/live/ios/live-host-integration.md +0 -5
- package/resource/integration/livekit/preset/live/ios/live-list-integration.md +0 -4
- package/resource/integration/livekit/preset/live/ios/prepare-integration.md +0 -9
- package/resource/integration/livekit/preset/live/vue/live-list-integration.md +1 -5
- package/resource/integration/livekit/preset/live/vue/live-player-desk-integration.md +36 -147
- package/resource/integration/livekit/preset/live/vue/live-player-h5-integration.md +1 -6
- package/resource/integration/livekit/preset/live/vue/live-pusher-integration.md +432 -286
- package/resource/integration/roomkit/preset/vue/integration.md +18 -31
- package/resource/knowledge/callkit/core-sdk/android/answer-call.md +1 -20
- package/resource/knowledge/callkit/core-sdk/android/make-call.md +0 -12
- package/resource/knowledge/callkit/core-sdk/android/offline-push.md +1 -12
- package/resource/knowledge/callkit/core-sdk/flutter/answer-call.md +0 -19
- package/resource/knowledge/callkit/core-sdk/flutter/make-call.md +0 -13
- package/resource/knowledge/callkit/core-sdk/flutter/offline-push.md +1 -17
- package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +0 -13
- package/resource/knowledge/callkit/core-sdk/ios/make-call.md +0 -13
- package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +0 -12
- package/resource/knowledge/callkit/core-sdk/miniprogram/call-engine.md +0 -1
- package/resource/knowledge/callkit/core-sdk/miniprogram/call-event.md +0 -2
- package/resource/knowledge/callkit/core-sdk/uni-app/answer-call.md +0 -15
- package/resource/knowledge/callkit/core-sdk/uni-app/make-call.md +0 -15
- package/resource/knowledge/callkit/core-sdk/web/call-engine.md +0 -1
- package/resource/knowledge/callkit/core-sdk/web/call-event.md +0 -1
- package/resource/knowledge/callkit/core-sdk/web/callengine-api-overview.md +0 -1
- package/resource/knowledge/callkit/faq/android.md +5 -15
- package/resource/knowledge/callkit/faq/common.md +0 -1
- package/resource/knowledge/callkit/faq/ios.md +1 -4
- package/resource/knowledge/callkit/faq/uniapp-app.md +0 -2
- package/resource/knowledge/callkit/faq/uniapp-miniprogram.md +0 -5
- package/resource/knowledge/callkit/faq/web.md +1 -5
- package/resource/knowledge/callkit/preset/android/api.md +0 -6
- package/resource/knowledge/callkit/preset/ios/api.md +0 -4
- package/resource/knowledge/callkit/preset/miniprogram/api.md +0 -2
- package/resource/knowledge/callkit/preset/react/api.md +2 -4
- package/resource/knowledge/callkit/preset/react/uikit-api-reference.md +2 -8
- package/resource/knowledge/callkit/preset/vue/api.md +2 -4
- package/resource/knowledge/callkit/preset/vue/uikit-api-reference.md +2 -8
- package/resource/knowledge/chat/preset/android/features/chat-setting.md +1 -4
- package/resource/knowledge/chat/preset/android/features/contact-list.md +0 -5
- package/resource/knowledge/chat/preset/android/features/conversation-list.md +1 -10
- package/resource/knowledge/chat/preset/android/features/language.md +1 -12
- package/resource/knowledge/chat/preset/android/features/message-input.md +1 -9
- package/resource/knowledge/chat/preset/android/features/message-list.md +1 -11
- package/resource/knowledge/chat/preset/android/features/search.md +0 -7
- package/resource/knowledge/chat/preset/android/features/theme.md +0 -6
- package/resource/knowledge/chat/preset/android-view/integration.md +3 -5
- package/resource/knowledge/chat/preset/flutter/features/chat-setting.md +1 -4
- package/resource/knowledge/chat/preset/flutter/features/contact-list.md +1 -6
- package/resource/knowledge/chat/preset/flutter/features/conversation-list.md +1 -10
- package/resource/knowledge/chat/preset/flutter/features/language.md +0 -3
- package/resource/knowledge/chat/preset/flutter/features/message-input.md +1 -9
- package/resource/knowledge/chat/preset/flutter/features/message-list.md +1 -11
- package/resource/knowledge/chat/preset/flutter/features/search.md +0 -7
- package/resource/knowledge/chat/preset/flutter/features/theme.md +0 -6
- package/resource/knowledge/chat/preset/ios/features/chat-setting.md +1 -4
- package/resource/knowledge/chat/preset/ios/features/contact-list.md +1 -8
- package/resource/knowledge/chat/preset/ios/features/conversation-list.md +1 -10
- package/resource/knowledge/chat/preset/ios/features/language.md +0 -11
- package/resource/knowledge/chat/preset/ios/features/message-input.md +1 -9
- package/resource/knowledge/chat/preset/ios/features/message-list.md +1 -11
- package/resource/knowledge/chat/preset/ios/features/search.md +0 -5
- package/resource/knowledge/chat/preset/ios/features/theme.md +0 -6
- package/resource/knowledge/chat/preset/ios-uikit/integration.md +5 -17
- package/resource/knowledge/chat/preset/react/features/chat-setting.md +0 -2
- package/resource/knowledge/chat/preset/react/features/contact-list.md +0 -23
- package/resource/knowledge/chat/preset/react/features/conversation-actions.md +2 -11
- package/resource/knowledge/chat/preset/react/features/conversation-list.md +2 -23
- package/resource/knowledge/chat/preset/react/features/conversation-preview.md +0 -6
- package/resource/knowledge/chat/preset/react/features/search.md +0 -1
- package/resource/knowledge/chat/preset/vue/features/chat-header.md +1 -3
- package/resource/knowledge/chat/preset/vue/features/chat-setting.md +3 -5
- package/resource/knowledge/chat/preset/vue/features/contact-list.md +3 -9
- package/resource/knowledge/chat/preset/vue/features/conversation-actions.md +0 -3
- package/resource/knowledge/chat/preset/vue/features/conversation-list.md +2 -13
- package/resource/knowledge/chat/preset/vue/features/conversation-preview.md +2 -5
- package/resource/knowledge/chat/preset/vue/features/conversation-search.md +1 -0
- package/resource/knowledge/chat/preset/vue/features/message-input.md +2 -4
- package/resource/knowledge/chat/preset/vue/features/message-list.md +2 -4
- package/resource/knowledge/chat/preset/vue/features/search.md +4 -1
- package/resource/knowledge/chat/preset/vue/features/theme.md +4 -6
- package/resource/knowledge/livekit/core-sdk/api-reference/android/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CameraView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LoginStore.md +1 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BaseBeautyStore.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LoginStore.md +1 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BaseBeautyStore.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LoginStore.md +1 -3
- package/resource/knowledge/livekit/core-sdk/features/android/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/android/audio-effect.md +1 -3
- package/resource/knowledge/livekit/core-sdk/features/android/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/android/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/android/gift.md +2 -7
- package/resource/knowledge/livekit/core-sdk/features/android/live-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/audio-effect.md +0 -4
- package/resource/knowledge/livekit/core-sdk/features/flutter/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/gift.md +3 -7
- package/resource/knowledge/livekit/core-sdk/features/flutter/live-list.md +3 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/audio-effect.md +1 -3
- package/resource/knowledge/livekit/core-sdk/features/ios/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/gift.md +2 -7
- package/resource/knowledge/livekit/core-sdk/features/ios/live-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/audio-effect.md +1 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/uni-app/gift.md +4 -8
- package/resource/knowledge/livekit/core-sdk/features/uni-app/live-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/live/android/co-guest-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/live/android/host-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/android/integration.md +0 -7
- package/resource/knowledge/livekit/core-sdk/live/flutter/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/flutter/host-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/flutter/integration.md +1 -7
- package/resource/knowledge/livekit/core-sdk/live/ios/co-guest-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/live/ios/host-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/ios/integration.md +0 -7
- package/resource/knowledge/livekit/core-sdk/live/uni-app/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/uni-app/host-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/live/uni-app/integration.md +0 -5
- package/resource/knowledge/livekit/core-sdk/voice/android/co-guest-interaction.md +1 -3
- package/resource/knowledge/livekit/core-sdk/voice/android/host-interaction.md +4 -13
- package/resource/knowledge/livekit/core-sdk/voice/android/integration.md +5 -5
- package/resource/knowledge/livekit/core-sdk/voice/flutter/co-guest-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/voice/flutter/integration.md +18 -21
- package/resource/knowledge/livekit/core-sdk/voice/ios/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/ios/host-interaction.md +2 -11
- package/resource/knowledge/livekit/core-sdk/voice/ios/integration.md +8 -8
- package/resource/knowledge/livekit/core-sdk/voice/uni-app/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/uni-app/integration.md +1 -4
- package/resource/knowledge/livekit/faq/error-code.md +1 -1
- package/resource/knowledge/livekit/preset/live/vue/features/barrage.md +0 -5
- package/resource/knowledge/livekit/preset/live/vue/features/live-audience-list.md +1 -1
- package/resource/knowledge/livekit/preset/live/vue/features/live-view.md +0 -3
- package/resource/knowledge/push/api-reference/donut.md +1 -6
- package/resource/knowledge/push/api-reference/harmonyos.md +0 -2
- package/resource/knowledge/push/api-reference/react-native.md +0 -3
- package/resource/knowledge/push/api-reference/uni-app.md +3 -5
- package/resource/knowledge/push/api-reference/unity.md +0 -1
- package/resource/knowledge/push/api-reference/unreal-engine.md +0 -1
- package/resource/knowledge/push/config/android/fcm.md +0 -6
- package/resource/knowledge/push/config/android/honor.md +1 -7
- package/resource/knowledge/push/config/android/huawei.md +1 -9
- package/resource/knowledge/push/config/android/meizu.md +1 -7
- package/resource/knowledge/push/config/android/oppo.md +1 -3
- package/resource/knowledge/push/config/android/vivo.md +1 -12
- package/resource/knowledge/push/config/android/xiaomi.md +0 -5
- package/resource/knowledge/push/config/donut.md +0 -12
- package/resource/knowledge/push/config/harmonyos.md +18 -7
- package/resource/knowledge/push/config/ios.md +26 -33
- package/resource/knowledge/push/config/react-native.md +0 -31
- package/resource/knowledge/push/config/unity.md +0 -31
- package/resource/knowledge/push/config/unreal-engine.md +0 -31
- package/resource/knowledge/push/integration/android.md +137 -46
- package/resource/knowledge/push/integration/donut.md +5 -21
- package/resource/knowledge/push/integration/flutter.md +1 -3
- package/resource/knowledge/push/integration/harmonyos.md +17 -16
- package/resource/knowledge/push/integration/ios.md +27 -15
- package/resource/knowledge/push/integration/react-native.md +9 -59
- package/resource/knowledge/push/integration/uni-app.md +3 -25
- package/resource/knowledge/push/integration/unity.md +8 -77
- package/resource/knowledge/push/integration/unreal-engine.md +37 -96
- package/resource/knowledge/roomkit/core-sdk/android/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/android/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/android/room-state.md +3 -5
- package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +4 -6
- package/resource/knowledge/roomkit/core-sdk/flutter/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/flutter/room-state.md +2 -4
- package/resource/knowledge/roomkit/core-sdk/flutter/schedule-room.md +4 -6
- package/resource/knowledge/roomkit/core-sdk/ios/call-user-to-room.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/room-participant-state.md +0 -2
- package/resource/knowledge/roomkit/core-sdk/ios/room-state.md +3 -5
- package/resource/knowledge/roomkit/core-sdk/ios/schedule-room.md +4 -6
- package/resource/knowledge/roomkit/core-sdk/vue/device-state.md +0 -5
- package/resource/knowledge/roomkit/core-sdk/vue/free-beauty-panel.md +0 -3
- package/resource/knowledge/roomkit/core-sdk/vue/room-chat.md +0 -5
- package/resource/knowledge/roomkit/core-sdk/vue/room-participant-state.md +0 -3
- package/resource/knowledge/roomkit/core-sdk/vue/room-state.md +1 -7
- package/resource/knowledge/roomkit/core-sdk/vue/room-view.md +1 -2
- package/resource/knowledge/roomkit/core-sdk/vue/screen-share.md +0 -1
- package/resource/knowledge/roomkit/core-sdk/vue/virtual-background.md +0 -3
- package/resource/knowledge/roomkit/preset/android/integration.md +202 -6
- package/resource/knowledge/roomkit/preset/flutter/integration.md +1 -16
- package/resource/knowledge/roomkit/preset/ios/integration.md +201 -7
- package/resource/knowledge/roomkit/preset/react/integration.md +205 -4
- package/resource/knowledge/rtcengine/web/api.md +0 -2
- package/resource/knowledge/rtcengine/web/plugin/22-advanced-audio-mixer.md +2 -2
- package/resource/knowledge/rtcengine/web/plugin/23-advanced-support-detection.md +3 -3
- package/resource/knowledge/rtcengine/web/plugin/28-advanced-beauty.md +1 -1
- package/resource/knowledge/rtcengine/web/plugin/36-advanced-virtual-background.md +0 -4
- package/resource/knowledge/share/userSig.md +2 -2
- package/resource/knowledge/trtc/android/TRTCCloud.md +16 -16
- package/resource/knowledge/trtc/android/TRTCCloudDef.md +5 -5
- package/resource/knowledge/trtc/android/TRTCCloudListener.md +3 -3
- package/resource/knowledge/trtc/android/TXAudioEffectManager.md +2 -2
- package/resource/knowledge/trtc/android/TXDeviceManager.md +1 -1
- package/resource/knowledge/trtc/c++/ITRTCCloud.md +14 -14
- package/resource/knowledge/trtc/c++/ITXAudioEffectManager.md +2 -2
- package/resource/knowledge/trtc/c++/ITXDeviceManager.md +4 -4
- package/resource/knowledge/trtc/c++/TRTCCloudCallback.md +3 -3
- package/resource/knowledge/trtc/c++/TRTCTypeDef.md +5 -5
- package/resource/knowledge/trtc/ios/TRTCCloud.md +14 -14
- package/resource/knowledge/trtc/ios/TRTCCloudDelegate.md +3 -3
- package/resource/knowledge/trtc/ios/TXAudioEffectManager.md +2 -2
- package/resource/knowledge/trtc/ios/TXDeviceManager.md +4 -4
- package/resource/knowledge/trtc/ios/TXLiveSDKTypeDef.md +5 -5
- package/server.js +1 -1
- package/tools/common/search_trtc_knowledge.js +2 -0
- package/tools/definitions/search_trtc_knowledge_def.js +1 -0
- package/utils/report-cls-client.js +3 -3
- package/utils/report-es-client.js +1 -1
|
@@ -3,15 +3,20 @@
|
|
|
3
3
|
|
|
4
4
|
- 极高的灵活度:支持原子化拆解以及丰富的 UI 属性定制。
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
> **集成提示:**
|
|
7
|
+
>
|
|
8
|
+
> 本文档介绍基于 **UI 组件** 的开播方式(含完整交互 UI)。若您需通过无 UI 的 **Core SDK** 自行搭建主播端界面,请参考 主播开播 (Core SDK)。
|
|
9
|
+
>
|
|
9
10
|
|
|
10
11
|
## 快速接入
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
### 前提条件
|
|
14
|
+
|
|
15
|
+
请您先阅读准备工作,请确保集成对应组件并实现登录。
|
|
16
|
+
|
|
17
|
+
### 集成主播开播页面
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
新建`live-pusher.vue`,作为开播页面的入口,负责**整体布局**、**开播 / 停播**、**登录初始化**,并按需引入底部控制栏的各功能模块。将以下代码复制到该文件即可:
|
|
15
20
|
``` typescript
|
|
16
21
|
<template>
|
|
17
22
|
<UIKitProvider language="zh-CN" theme="dark">
|
|
@@ -38,39 +43,11 @@
|
|
|
38
43
|
<StreamMixer />
|
|
39
44
|
</div>
|
|
40
45
|
<div class="live-controls">
|
|
41
|
-
<!-- 底部控制面板(已集成高级功能) -->
|
|
42
46
|
<div class="bottom-panel">
|
|
43
|
-
<!--
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<TUISlider v-model="microphoneVolume" class="device-slider" :min="0" :max="100" :disabled="!microphoneIsOn" @change="handleMicrophoneVolumeChange" />
|
|
48
|
-
</div>
|
|
49
|
-
<div class="device-setting">
|
|
50
|
-
<TUIIcon class="device-icon" :icon="speakerIsOn ? IconSpeakerOn : IconSpeakerOff" :size="20" @click="switchSpeaker(!speakerIsOn)" />
|
|
51
|
-
<TUISlider v-model="speakerVolume" class="device-slider" :min="0" :max="100" :disabled="!speakerIsOn" @change="handleSpeakerVolumeChange" />
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<!-- 2. CoGuestButton 观众连麦设置 -->
|
|
56
|
-
<div class="custom-icon-container" :class="{ disabled: coGuestDisabled }" @click="handleCoGuest">
|
|
57
|
-
<span v-if="applicants.length > 0" class="unread-count">{{ applicants.length }}</span>
|
|
58
|
-
<IconCoGuest class="custom-icon" />
|
|
59
|
-
<span class="custom-text co-guest-text">{{ t('CoGuest') }}</span>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<!-- 3. OrientationSwitch 横竖屏推流设置 -->
|
|
63
|
-
<div class="custom-icon-container" :class="{ disabled: currentLive?.liveId }" @click="handleOrientationSwitch">
|
|
64
|
-
<IconHorizontalMode v-if="currentOrientation === LiveOrientation.Landscape" class="custom-icon" />
|
|
65
|
-
<IconPortrait v-else class="custom-icon" />
|
|
66
|
-
<span class="custom-text co-guest-text">{{ currentOrientation === LiveOrientation.Portrait ? t('Portrait') : t('Landscape') }}</span>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<!-- 4. LayoutSwitch 布局设置 -->
|
|
70
|
-
<div class="custom-icon-container" :class="{ 'disabled': layoutSwitchDisabled }" @click="handleSwitchLayout">
|
|
71
|
-
<IconLayoutTemplate class="custom-icon" />
|
|
72
|
-
<span class="custom-text setting-text">{{ t('Layout Settings') }}</span>
|
|
73
|
-
</div>
|
|
47
|
+
<!-- <MediaDeviceSetting />// 媒体设置能力请参考本文高级功能集成部分
|
|
48
|
+
<CoGuestButton /> // 连麦观众能力请参考本文高级功能集成部分
|
|
49
|
+
<OrientationSwitch /> // 布局设置请参考本文高级功能集成部分
|
|
50
|
+
<LayoutSwitch /> // 横竖屏推流能力请参考本文高级功能集成部分 -->
|
|
74
51
|
</div>
|
|
75
52
|
<TUIButton type="primary" v-if="!currentLive?.liveId" @click="handleStartLive">开始直播</TUIButton>
|
|
76
53
|
<TUIButton color="red" v-else @click="handleStopLive">停止直播</TUIButton>
|
|
@@ -89,88 +66,51 @@
|
|
|
89
66
|
<BarrageInput />
|
|
90
67
|
</div>
|
|
91
68
|
</div>
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
69
|
|
|
95
|
-
<!-- 弹窗:连麦观众面板 -->
|
|
96
|
-
<TUIDialog :title="t('CoGuest')" :visible="coGuestPanelVisible" :custom-classes="['co-guest-dialog']" @close="coGuestPanelVisible = false" @confirm="coGuestPanelVisible = false" @cancel="coGuestPanelVisible = false">
|
|
97
|
-
<CoGuestPanel class="co-guest-panel" />
|
|
98
|
-
<template #footer><div /></template>
|
|
99
|
-
</TUIDialog>
|
|
100
|
-
|
|
101
|
-
<!-- 弹窗:布局模板设置面板 -->
|
|
102
|
-
<TUIDialog :customClasses="['layout-dialog']" :title="t('Layout Settings')" :visible="layoutSwitchVisible" @close="handleCancel" @confirm="handleConfirm" @cancel="handleCancel" appendTo="body">
|
|
103
|
-
<div class="layout-label">{{ t('Audience Layout') }}</div>
|
|
104
|
-
<div class="template-options">
|
|
105
|
-
<div class="options-grid">
|
|
106
|
-
<template v-for="template in layoutOptions" :key="template.id">
|
|
107
|
-
<div class="option-card" :class="{ active: selectedTemplate === template.templateId }" @click="selectTemplate(template.templateId)">
|
|
108
|
-
<div class="option-info">
|
|
109
|
-
<component :is="template.icon" v-if="template.icon" class="option-icon" />
|
|
110
|
-
<h4>{{ template.label }}</h4>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</template>
|
|
114
|
-
</div>
|
|
115
70
|
</div>
|
|
116
|
-
</
|
|
117
|
-
|
|
71
|
+
</div>
|
|
118
72
|
</UIKitProvider>
|
|
119
73
|
</template>
|
|
120
74
|
|
|
121
75
|
<script setup lang="ts">
|
|
122
|
-
import { onMounted
|
|
123
|
-
import {
|
|
124
|
-
import {
|
|
125
|
-
|
|
126
|
-
IconSpeakerOn, IconSpeakerOff, IconAudioOpen, IconAudioClose, IconPortrait, IconHorizontalMode,
|
|
127
|
-
IconCoGuest, IconLayoutTemplate
|
|
128
|
-
} from '@tencentcloud/uikit-base-component-vue3';
|
|
129
|
-
import {
|
|
130
|
-
LiveScenePanel, StreamMixer, LiveAudienceList, BarrageList, BarrageInput, CoGuestPanel,
|
|
131
|
-
CoHostStatus, LiveOrientation, useLiveListState, useLiveAudienceState, useLoginState,
|
|
132
|
-
useDeviceState, useCoGuestState, useCoHostState
|
|
133
|
-
} from 'tuikit-atomicx-vue3';
|
|
134
|
-
|
|
135
|
-
// ================= 全局定义与基础状态 =================
|
|
136
|
-
const { t } = useUIKit();
|
|
76
|
+
import { onMounted } from 'vue';
|
|
77
|
+
import { UIKitProvider, TUIButton } from '@tencentcloud/uikit-base-component-vue3';
|
|
78
|
+
import { LiveScenePanel, StreamMixer, LiveAudienceList, BarrageList, BarrageInput, useLiveListState, useLiveAudienceState, useLoginState } from 'tuikit-atomicx-vue3';
|
|
79
|
+
|
|
137
80
|
const { login, setSelfInfo } = useLoginState();
|
|
138
|
-
const {
|
|
81
|
+
const { startLive, currentLive, endLive } = useLiveListState();
|
|
139
82
|
const { audienceCount } = useLiveAudienceState();
|
|
140
|
-
const { coHostStatus } = useCoHostState();
|
|
141
|
-
|
|
142
83
|
const liveName = '我的直播间';
|
|
143
84
|
|
|
144
|
-
enum TUISeatLayoutTemplate {
|
|
145
|
-
LandscapeDynamic_1v3 = 200,
|
|
146
|
-
PortraitDynamic_Grid9 = 600,
|
|
147
|
-
PortraitDynamic_1v6 = 601,
|
|
148
|
-
PortraitFixed_Grid9 = 800,
|
|
149
|
-
PortraitFixed_1v6 = 801,
|
|
150
|
-
PortraitFixed_6v6 = 802,
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// 基础开播控制
|
|
154
85
|
const handleStartLive = async () => {
|
|
86
|
+
// 开始直播
|
|
155
87
|
await startLive({
|
|
156
|
-
liveId: 'my-live-room',
|
|
157
|
-
liveName: liveName,
|
|
158
|
-
coverUrl: '',
|
|
159
|
-
isPublicVisible: true,
|
|
160
|
-
seatLayoutTemplateId:
|
|
88
|
+
liveId: 'my-live-room', // 直播间 ID
|
|
89
|
+
liveName: liveName, // 直播间名称
|
|
90
|
+
coverUrl: '', // 直播间封面 URL
|
|
91
|
+
isPublicVisible: true, // 是否公开可见
|
|
92
|
+
seatLayoutTemplateId: 600, // 麦位布局模板 ID
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// 设置个人信息
|
|
96
|
+
await setSelfInfo({
|
|
97
|
+
userName: '我的名字/昵称', // 用户名
|
|
98
|
+
avatarUrl: '', // 头像 URL 地址
|
|
161
99
|
});
|
|
162
|
-
await setSelfInfo({ userName: '我的名字/昵称', avatarUrl: '' });
|
|
163
100
|
};
|
|
164
101
|
|
|
102
|
+
// 结束直播
|
|
165
103
|
const handleStopLive = async () => {
|
|
166
104
|
await endLive();
|
|
167
105
|
};
|
|
168
106
|
|
|
169
|
-
// 如果您已参考准备工作实现过登陆,则可跳过本部分
|
|
170
107
|
async function initLogin() {
|
|
171
108
|
try {
|
|
172
|
-
|
|
173
|
-
|
|
109
|
+
await login({
|
|
110
|
+
sdkAppId: 0, // SDKAppID, 可以参考准备工作进行获取
|
|
111
|
+
userId: '', // UserID, 可以参考准备工作进行获取
|
|
112
|
+
userSig: '', // userSig, 可以参考准备工作进行获取
|
|
113
|
+
});
|
|
174
114
|
} catch (error) {
|
|
175
115
|
console.error('登录失败:', error);
|
|
176
116
|
}
|
|
@@ -180,8 +120,63 @@ onMounted(async () => {
|
|
|
180
120
|
await initLogin();
|
|
181
121
|
});
|
|
182
122
|
|
|
183
|
-
|
|
184
|
-
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<style>html,body,#app{height:100%;width:100%;margin:0;padding:0}</style>
|
|
126
|
+
<style scoped>.custom-live-pusher,.left-panel{flex-direction:column;display:flex}.custom-live-pusher,.live-title{color:var(--text-color-primary)}.live-controls,.tools-section,.top-controls{backdrop-filter:blur(10px)}*{box-sizing:border-box;margin:0;padding:0}:global(::before){box-sizing:border-box;margin:0;padding:0}.layout-label,.template-options{margin-bottom:16px}:global(body){line-height:1.6;color:var(--text-color-primary);background:var(--bg-color-default)}.custom-live-pusher{height:100vh;width:100vw;background:linear-gradient(135deg,var(--bg-color-default) 0,var(--bg-color-function) 100%);overflow:hidden}.top-controls{display:flex;justify-content:space-between;align-items:center;padding:12px 20px;background:var(--bg-color-operate);border-bottom:1px solid var(--stroke-color-primary);z-index:100;min-height:60px}.live-title{font-size:18px;font-weight:600;text-shadow:0 2px 4px var(--shadow-color)}.audience-count{font-size:14px;color:var(--text-color-error);background:var(--uikit-color-red-1);padding:6px 12px;border-radius:20px;border:1px solid var(--uikit-color-red-3)}.live-controls,.tools-section{background:var(--bg-color-operate)}.main-content{display:flex;flex:1;height:calc(100vh - 60px);gap:16px;padding:16px;overflow:hidden}.left-panel{width:320px;gap:16px;flex-shrink:0}.panel-title{font-size:16px;font-weight:600;color:var(--text-color-primary);margin-bottom:12px;text-align:left}.audience-section,.message-section,.scene-section{display:flex;flex-direction:column;background:var(--bg-color-operate);border-radius:12px;border:1px solid var(--stroke-color-primary);padding:16px;overflow:hidden}.scene-section{flex:1;min-height:0}.message-section{flex:1;min-height:0}.message-section :deep(input),.message-section :deep(textarea){text-align:left}.tools-section{border-radius:12px;padding:16px;border:1px solid var(--stroke-color-primary)}.center-panel{display:flex;flex-direction:column;flex:1;gap:16px;min-width:0}.stream-section{display:flex;flex-direction:column;flex:1;min-height:0;background:var(--bg-color-operate);border-radius:12px;border:1px solid var(--stroke-color-primary);overflow:hidden}.stream-header{display:flex;justify-content:space-between;align-items:center;padding:22px;border-bottom:1px solid var(--stroke-color-primary)}.stream-title{display:flex;align-items:center;gap:8px;font-size:18px;font-weight:500;color:var(--text-color-primary)}.stream-audience{font-size:14px;color:var(--text-color-primary)}.live-controls{display:flex;justify-content:space-between;align-items:center;padding:16px;border-radius:12px;border:1px solid var(--stroke-color-primary);gap:16px}.live-controls button{padding:18px 20px}.right-panel{display:flex;flex-direction:column;width:320px;gap:16px;flex-shrink:0}.center-panel>.live-controls,.left-panel>*,.right-panel>*{background:var(--bg-color-operate);border-radius:12px;border:1px solid var(--stroke-color-primary);overflow:hidden}.left-panel>*{padding:16px}.left-panel>.panel-title,.scene-section>.panel-title,.audience-section>.panel-title,.message-section>.panel-title{padding:0;background:transparent;border:none;border-radius:0}.custom-icon-container,.device-setting{padding:8px 12px;background:var(--bg-color-function)}.stream-section :deep(>*:last-child){flex:1;min-height:300px}.bottom-panel,.device-setting{align-items:center;display:flex}.custom-icon-container:hover,.option-card:hover{border-color:var(--stroke-color-primary);background:var(--list-color-hover)}.bottom-panel{gap:16px;flex:1}.device-setting{gap:8px;border-radius:8px;border:1px solid var(--stroke-color-secondary)}.device-icon{cursor:pointer;color:var(--text-color-primary);transition:color .2s}.device-icon:hover{color:var(--text-color-link)}.device-slider{width:80px}.custom-icon-container{display:flex;align-items:center;gap:6px;border-radius:8px;border:1px solid var(--stroke-color-secondary);cursor:pointer;transition:.2s;position:relative}.custom-icon-container.disabled{opacity:.5;cursor:not-allowed}.custom-icon-container.disabled:hover{background:var(--bg-color-function);border-color:var(--stroke-color-secondary)}.custom-icon{width:16px;height:16px;display:inline-block;background-size:contain;background-repeat:no-repeat;background-position:center}.custom-text{font-size:12px;color:var(--text-color-secondary);white-space:nowrap}.unread-count{position:absolute;top:-4px;right:-4px;background:var(--text-color-error);color:var(--text-color-button);border-radius:10px;padding:2px 6px;font-size:10px;font-weight:600;min-width:16px;text-align:center;line-height:1}.layout-label,.option-info h4{color:var(--text-color-primary)}.layout-dialog{max-width:600px}.layout-label{font-size:16px;font-weight:600}.options-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:12px}.option-card{padding:16px;background:var(--bg-color-function);border:2px solid var(--stroke-color-secondary);border-radius:8px;cursor:pointer;transition:.2s;text-align:center}.option-card.active{border-color:var(--text-color-link);background:var(--bg-color-operate)}.option-info h4{margin:8px 0 0;font-size:12px}.option-icon{width:32px;height:32px;margin:0 auto;color:var(--text-color-secondary)}.co-guest-dialog{max-width:500px}.co-guest-panel{min-height:300px}</style>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 启动并运行示例
|
|
130
|
+
|
|
131
|
+
执行 `npm run dev` 成功后,在浏览器地址栏输入本地访问地址(例如`https://localhost:5173/live-pusher`,具体端口号可能因项目配置不同而有所差异),即可看到开播页面,添加媒体源素材点击开始直播即可开启您的直播。
|
|
132
|
+
``` bash
|
|
133
|
+
npm run dev
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
> **观看直播的两种方式:**
|
|
137
|
+
>
|
|
138
|
+
> 开播成功后,可通过以下任一方式观看直播间效果:
|
|
139
|
+
>
|
|
140
|
+
> - 在线观看网站:打开[在线观看网站](https://web.sdk.qcloud.com/trtc/livekit/player/index.html#/),输入对应 **sdkAppId** 等信息,在直播列表中找到并进入你的直播间。
|
|
141
|
+
> - 集成观看页面:在您的项目中接入 观众观看(Web 桌面浏览器)或者 观众观看(H5 移动端浏览器)组件观看。
|
|
142
|
+
> ⚠️ 观看请使用与开播端不同的用户 ID,否则先登录的设备会被强制下线。
|
|
143
|
+
>
|
|
144
|
+
|
|
145
|
+
## 功能模块
|
|
146
|
+
|
|
147
|
+
以下模块均为可独立复制的组件,需要先通过集成主播开播页面,然后根据您的业务需求将下列各个模块的代码直接粘贴进对应的注释部分去即可。
|
|
148
|
+
|
|
149
|
+
### 支持媒体设置能力
|
|
150
|
+
|
|
151
|
+
MediaDeviceSetting 媒体设备设置
|
|
152
|
+
``` typescript
|
|
153
|
+
<template>
|
|
154
|
+
<div class="media-device-container">
|
|
155
|
+
<!-- MicVolumeSetting 麦克风设置 -->
|
|
156
|
+
<div class="device-setting">
|
|
157
|
+
<TUIIcon class="device-icon" :icon="microphoneIsOn ? IconAudioOpen : IconAudioClose" :size="20" @click="switchMicrophoneStatus" />
|
|
158
|
+
<TUISlider v-model="microphoneVolume" class="device-slider" :min="0" :max="100" :disabled="!microphoneIsOn" @change="handleMicrophoneVolumeChange" />
|
|
159
|
+
</div>
|
|
160
|
+
<!-- SpeakerVolumeSetting 扬声器设置 -->
|
|
161
|
+
<div class="device-setting">
|
|
162
|
+
<TUIIcon class="device-icon" :icon="speakerIsOn ? IconSpeakerOn : IconSpeakerOff" :size="20" @click="switchSpeaker(!speakerIsOn)" />
|
|
163
|
+
<TUISlider v-model="speakerVolume" class="device-slider" :min="0" :max="100" :disabled="!speakerIsOn" @change="handleSpeakerVolumeChange" />
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</template>
|
|
167
|
+
|
|
168
|
+
<script lang="ts" setup>
|
|
169
|
+
import { ref, watch } from 'vue';
|
|
170
|
+
import { TUIIcon, TUISlider, IconSpeakerOn, IconSpeakerOff, IconAudioOpen, IconAudioClose } from '@tencentcloud/uikit-base-component-vue3';
|
|
171
|
+
import { useDeviceState } from 'tuikit-atomicx-vue3';
|
|
172
|
+
|
|
173
|
+
const {
|
|
174
|
+
captureVolume,
|
|
175
|
+
setCaptureVolume,
|
|
176
|
+
openLocalMicrophone,
|
|
177
|
+
closeLocalMicrophone,
|
|
178
|
+
} = useDeviceState();
|
|
179
|
+
const { outputVolume, setOutputVolume } = useDeviceState();
|
|
185
180
|
const microphoneVolume = ref(captureVolume.value);
|
|
186
181
|
const speakerVolume = ref(outputVolume.value);
|
|
187
182
|
const microphoneIsOn = ref(true);
|
|
@@ -190,8 +185,11 @@ const templateSpeakerVolume = ref(outputVolume.value);
|
|
|
190
185
|
const templateMicrophoneVolume = ref(captureVolume.value);
|
|
191
186
|
|
|
192
187
|
const handleMicrophoneVolumeChange = (value: number) => {
|
|
193
|
-
if (value !== captureVolume.value)
|
|
188
|
+
if (value !== captureVolume.value) {
|
|
189
|
+
setCaptureVolume(value);
|
|
190
|
+
}
|
|
194
191
|
};
|
|
192
|
+
|
|
195
193
|
const switchMicrophoneStatus = () => {
|
|
196
194
|
microphoneIsOn.value = !microphoneIsOn.value;
|
|
197
195
|
if (!microphoneIsOn.value) {
|
|
@@ -202,6 +200,7 @@ const switchMicrophoneStatus = () => {
|
|
|
202
200
|
setCaptureVolume(templateMicrophoneVolume.value);
|
|
203
201
|
}
|
|
204
202
|
};
|
|
203
|
+
|
|
205
204
|
const switchSpeaker = (open: boolean) => {
|
|
206
205
|
speakerIsOn.value = open;
|
|
207
206
|
if (!open) {
|
|
@@ -211,15 +210,69 @@ const switchSpeaker = (open: boolean) => {
|
|
|
211
210
|
setOutputVolume(templateSpeakerVolume.value);
|
|
212
211
|
}
|
|
213
212
|
};
|
|
213
|
+
|
|
214
214
|
const handleSpeakerVolumeChange = (value: number) => {
|
|
215
|
-
if (value !== outputVolume.value)
|
|
215
|
+
if (value !== outputVolume.value) {
|
|
216
|
+
setOutputVolume(value);
|
|
217
|
+
}
|
|
216
218
|
};
|
|
217
219
|
|
|
218
|
-
watch(captureVolume, (newVal) => {
|
|
219
|
-
|
|
220
|
+
watch(captureVolume, (newVal) => {
|
|
221
|
+
microphoneVolume.value = newVal;
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
watch(outputVolume, (newVal) => {
|
|
225
|
+
speakerVolume.value = newVal;
|
|
226
|
+
});
|
|
227
|
+
</script>
|
|
228
|
+
|
|
229
|
+
<style scoped>.media-device-container{display:flex;align-items:center;gap:12px}.device-setting{display:flex;align-items:center;gap:8px;padding:12px 16px;background:var(--bg-color-function);border-radius:8px;border:1px solid var(--stroke-color-secondary)}.device-slider{width:100px}.device-icon{cursor:pointer;color:var(--text-color-primary);transition:color .2s}.device-icon:hover{color:var(--text-color-link)}</style>
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 支持横竖屏推流能力
|
|
220
234
|
|
|
221
|
-
|
|
235
|
+
LayoutSwitch 横竖屏推流设置
|
|
236
|
+
``` typescript
|
|
237
|
+
<template>
|
|
238
|
+
<div
|
|
239
|
+
class="custom-icon-container"
|
|
240
|
+
:class="{ disabled: currentLive?.liveId }"
|
|
241
|
+
@click="handleOrientationSwitch"
|
|
242
|
+
>
|
|
243
|
+
<IconHorizontalMode
|
|
244
|
+
v-if="currentOrientation === LiveOrientation.Landscape"
|
|
245
|
+
class="custom-icon"
|
|
246
|
+
/>
|
|
247
|
+
<IconPortrait
|
|
248
|
+
v-else
|
|
249
|
+
class="custom-icon"
|
|
250
|
+
/>
|
|
251
|
+
<span class="custom-text co-guest-text">{{
|
|
252
|
+
currentOrientation === LiveOrientation.Portrait ? t('Portrait') : t('Landscape')
|
|
253
|
+
}}</span>
|
|
254
|
+
</div>
|
|
255
|
+
</template>
|
|
256
|
+
|
|
257
|
+
<script setup lang="ts">
|
|
258
|
+
import { ref, watch } from 'vue';
|
|
259
|
+
import { useUIKit, TUIToast, TOAST_TYPE, IconPortrait, IconHorizontalMode } from '@tencentcloud/uikit-base-component-vue3';
|
|
260
|
+
import { useLiveListState, LiveOrientation } from 'tuikit-atomicx-vue3';
|
|
261
|
+
|
|
262
|
+
const { t } = useUIKit();
|
|
263
|
+
|
|
264
|
+
enum TUISeatLayoutTemplate {
|
|
265
|
+
LandscapeDynamic_1v3 = 200,
|
|
266
|
+
PortraitDynamic_Grid9 = 600,
|
|
267
|
+
PortraitDynamic_1v6 = 601,
|
|
268
|
+
PortraitFixed_Grid9 = 800,
|
|
269
|
+
PortraitFixed_1v6 = 801,
|
|
270
|
+
PortraitFixed_6v6 = 802,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const { currentLive, updateLiveInfo } = useLiveListState();
|
|
222
274
|
const currentOrientation = ref(LiveOrientation.Portrait);
|
|
275
|
+
|
|
223
276
|
watch(
|
|
224
277
|
() => currentLive.value?.layoutTemplate,
|
|
225
278
|
newVal => {
|
|
@@ -234,7 +287,10 @@ watch(
|
|
|
234
287
|
|
|
235
288
|
const handleOrientationSwitch = () => {
|
|
236
289
|
if (currentLive.value?.liveId) {
|
|
237
|
-
TUIToast({
|
|
290
|
+
TUIToast({
|
|
291
|
+
message: t('Cannot switch orientation during live streaming'),
|
|
292
|
+
type: TOAST_TYPE.ERROR,
|
|
293
|
+
});
|
|
238
294
|
return;
|
|
239
295
|
}
|
|
240
296
|
if (currentOrientation.value === LiveOrientation.Portrait) {
|
|
@@ -243,61 +299,209 @@ const handleOrientationSwitch = () => {
|
|
|
243
299
|
updateLiveInfo({ layoutTemplate: TUISeatLayoutTemplate.PortraitDynamic_Grid9 });
|
|
244
300
|
}
|
|
245
301
|
};
|
|
302
|
+
</script>
|
|
246
303
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const coGuestDisabled = computed(() => !currentLive.value?.liveId || coHostStatus.value !== CoHostStatus.Disconnected);
|
|
250
|
-
const coGuestPanelVisible = ref(false);
|
|
304
|
+
<style scoped>.custom-icon-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:56px;height:56px;cursor:pointer;color:var(--text-color-primary);border-radius:12px;position:relative}.custom-icon{width:24px;height:24px;background:transparent}.custom-text{font-size:12px}.custom-icon-container:not(.disabled):hover{box-shadow:0 0 10px 0 var(--bg-color-mask)}.custom-icon-container:not(.disabled):hover .custom-icon,.custom-icon-container:not(.disabled):hover .custom-text{color:var(--text-color-link)}.custom-icon-container.disabled{cursor:not-allowed;opacity:.5;color:var(--text-color-secondary)}.custom-icon-container.disabled .custom-icon,.custom-icon-container.disabled .custom-text{color:var(--text-color-secondary);cursor:not-allowed}</style>
|
|
305
|
+
```
|
|
251
306
|
|
|
252
|
-
|
|
253
|
-
if (coGuestDisabled.value) {
|
|
254
|
-
const message = !currentLive.value?.liveId
|
|
255
|
-
? t('Cannot use co-guest before live starts')
|
|
256
|
-
: t('Cannot enable audience co-hosting while co-hosting with other hosts');
|
|
257
|
-
TUIToast({ type: TOAST_TYPE.ERROR, message });
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
coGuestPanelVisible.value = true;
|
|
261
|
-
};
|
|
262
|
-
watch(coGuestDisabled, () => { if (coGuestDisabled.value) coGuestPanelVisible.value = false; });
|
|
307
|
+
TUILiveKit 支持横屏和竖屏两种推流模式,您可根据直播场景选择合适的推流方向:
|
|
263
308
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
309
|
+
|**推流模式**|**适用场景**|**说明**|
|
|
310
|
+
|---------|---------|---------|
|
|
311
|
+
|竖屏推流|秀场直播、电商带货、聊天互动|默认模式,适合移动端观看,画面比例为 9:16。|
|
|
312
|
+
|横屏推流|游戏直播、在线教育、会议直播|适合 PC 端观看,画面比例为 16:9。|
|
|
313
|
+
|
|
314
|
+
> **注意:**
|
|
315
|
+
> 横竖屏切换必须在开播前进行设置,直播过程中无法切换推流方向。
|
|
316
|
+
>
|
|
317
|
+
|
|
318
|
+
#### 通过 UI 交互切换横竖屏
|
|
319
|
+
|
|
320
|
+
在主播开播页的底部控制栏,点击横屏 / 竖屏按钮即可切换推流方向:
|
|
321
|
+
- 显示竖屏时,当前为竖屏推流模式;
|
|
322
|
+
|
|
323
|
+
- 显示横屏时,当前为横屏推流模式。
|
|
324
|
+
|
|
325
|
+
#### 通过代码设置横竖屏
|
|
326
|
+
|
|
327
|
+
您也可以通过调用 `updateLiveInfo` 方法,在代码中设置推流方向:
|
|
328
|
+
``` typescript
|
|
329
|
+
import { useLiveListState } from 'tuikit-atomicx-vue3';
|
|
330
|
+
|
|
331
|
+
const { updateLiveInfo } = useLiveListState();
|
|
332
|
+
|
|
333
|
+
// 切换为横屏模式(模板 ID: 200)
|
|
334
|
+
updateLiveInfo({ layoutTemplate: 200 });
|
|
335
|
+
|
|
336
|
+
// 切换为竖屏模式(模板 ID: 600)
|
|
337
|
+
updateLiveInfo({ layoutTemplate: 600 });
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
> **说明:**
|
|
341
|
+
> - 横屏模式对应的布局模板 ID 范围为 200-599,默认使用 200(横屏浮动布局)。
|
|
342
|
+
> - 竖屏模式对应的布局模板 ID 范围为 600-899,默认使用 600(动态宫格布局)。
|
|
343
|
+
> - 切换横竖屏时,系统会自动切换到对应方向的默认布局模板。
|
|
344
|
+
|
|
345
|
+
### 支持布局设置能力
|
|
346
|
+
|
|
347
|
+
若您需要支持视频流切换布局能力,包括设置**动态宫格布局、静态宫格布局、静态小窗布局、浮动小窗布局**等内容。
|
|
348
|
+
|
|
349
|
+
OrientationSwitch 布局设置
|
|
350
|
+
``` typescript
|
|
351
|
+
<template>
|
|
352
|
+
<div
|
|
353
|
+
class="custom-icon-container"
|
|
354
|
+
:class="{ 'disabled': disabled }"
|
|
355
|
+
@click="handleSwitchLayout"
|
|
356
|
+
>
|
|
357
|
+
<IconLayoutTemplate class="custom-icon" />
|
|
358
|
+
<span class="custom-text setting-text">{{ t('Layout Settings') }}</span>
|
|
359
|
+
</div>
|
|
360
|
+
<TUIDialog
|
|
361
|
+
:customClasses="['layout-dialog']"
|
|
362
|
+
:title="t('Layout Settings')"
|
|
363
|
+
:visible="layoutSwitchVisible"
|
|
364
|
+
@close="handleCancel"
|
|
365
|
+
@confirm="handleConfirm"
|
|
366
|
+
@cancel="handleCancel"
|
|
367
|
+
appendTo="body"
|
|
368
|
+
>
|
|
369
|
+
<div class="layout-label">
|
|
370
|
+
{{ t('Audience Layout') }}
|
|
371
|
+
</div>
|
|
372
|
+
<div class="template-options">
|
|
373
|
+
<div class="options-grid">
|
|
374
|
+
<template
|
|
375
|
+
v-for="template in layoutOptions"
|
|
376
|
+
:key="template.id"
|
|
377
|
+
>
|
|
378
|
+
<div
|
|
379
|
+
class="option-card"
|
|
380
|
+
:class="{ active: selectedTemplate === template.templateId }"
|
|
381
|
+
@click="selectTemplate(template.templateId)"
|
|
382
|
+
>
|
|
383
|
+
<div class="option-info">
|
|
384
|
+
<component
|
|
385
|
+
:is="template.icon"
|
|
386
|
+
v-if="template.icon"
|
|
387
|
+
class="option-icon"
|
|
388
|
+
/>
|
|
389
|
+
<h4>{{ template.label }}</h4>
|
|
390
|
+
</div>
|
|
391
|
+
</div>
|
|
392
|
+
</template>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
</TUIDialog>
|
|
396
|
+
</template>
|
|
397
|
+
|
|
398
|
+
<script lang="ts" setup>
|
|
399
|
+
import { ref, computed, watch, h, defineComponent } from 'vue';
|
|
400
|
+
import { TUIErrorCode } from '@tencentcloud/tuiroom-engine-js';
|
|
401
|
+
import { useUIKit, TUIDialog, TUIToast, TOAST_TYPE, IconLayoutTemplate } from '@tencentcloud/uikit-base-component-vue3';
|
|
402
|
+
import { useLiveListState, useCoHostState, CoHostStatus } from 'tuikit-atomicx-vue3';
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* 直播间麦位排版模板
|
|
406
|
+
*/
|
|
407
|
+
enum TUISeatLayoutTemplate {
|
|
408
|
+
LandscapeDynamic_1v3 = 200,
|
|
409
|
+
PortraitDynamic_Grid9 = 600,
|
|
410
|
+
PortraitDynamic_1v6 = 601,
|
|
411
|
+
PortraitFixed_Grid9 = 800,
|
|
412
|
+
PortraitFixed_1v6 = 801,
|
|
413
|
+
PortraitFixed_6v6 = 802,
|
|
414
|
+
}
|
|
268
415
|
|
|
269
416
|
const createSvgIcon = (pathD: string) => defineComponent({
|
|
270
417
|
render: () => h('svg', { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', fill: 'currentColor', width: '24', height: '24' }, [h('path', { d: pathD })])
|
|
271
418
|
});
|
|
419
|
+
|
|
272
420
|
const Dynamic1v6 = createSvgIcon('M3 3h7v7H3V3zm11 0h7v4h-7V3zm0 6h7v4h-7V9zm0 6h7v6h-7v-6zM3 12h7v9H3v-9z');
|
|
273
421
|
const DynamicGrid9 = createSvgIcon('M3 3h5v5H3V3zm7 0h4v5h-4V3zm6 0h5v5h-5V3zM3 10h5v4H3v-4zm7 0h4v4h-4v-4zm6 0h5v4h-5v-4zM3 16h5v5H3v-5zm7 0h4v5h-4v-5zm6 0h5v5h-5v-5z');
|
|
274
422
|
const Fixed1v6 = createSvgIcon('M2 2h9v9H2V2zm11 0h9v4h-9V2zm0 5h9v4h-9V7zm0 5h9v4h-9v-4zm0 5h9v5h-9v-5zM2 13h9v9H2v-9z');
|
|
275
423
|
const FixedGrid9 = createSvgIcon('M2 2h6v6H2V2zm7 0h6v6H9V2zm7 0h6v6h-6V2zM2 9h6v6H2V9zm7 0h6v6H9V9zm7 0h6v6h-6V9zM2 16h6v6H2v-6zm7 0h6v6H9v-6zm7 0h6v6h-6v-6z');
|
|
276
424
|
const HorizontalFloat = createSvgIcon('M2 4h20v12H2V4zm3 14h4v2H5v-2zm6 0h4v2h-4v-2zm6 0h4v2h-4v-2z');
|
|
277
425
|
|
|
426
|
+
const { t } = useUIKit();
|
|
427
|
+
const { currentLive, updateLiveInfo } = useLiveListState();
|
|
428
|
+
const { coHostStatus } = useCoHostState();
|
|
429
|
+
const disabled = computed(() => coHostStatus.value === CoHostStatus.Connected);
|
|
430
|
+
|
|
431
|
+
watch(
|
|
432
|
+
() => currentLive.value?.liveId,
|
|
433
|
+
(liveId) => {
|
|
434
|
+
if (!liveId) {
|
|
435
|
+
updateLiveInfo({ layoutTemplate: TUISeatLayoutTemplate.PortraitDynamic_Grid9 });
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
{ immediate: true },
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const layoutSwitchVisible = ref(false);
|
|
442
|
+
|
|
443
|
+
const handleSwitchLayout = () => {
|
|
444
|
+
if (disabled.value) {
|
|
445
|
+
TUIToast({ type: TOAST_TYPE.ERROR, message: t('Layout switching is not available during co-hosting') });
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
layoutSwitchVisible.value = true;
|
|
449
|
+
};
|
|
450
|
+
|
|
278
451
|
const portraitLayoutOptions = computed(() => [
|
|
279
|
-
{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
452
|
+
{
|
|
453
|
+
id: 'PortraitDynamic_Grid9',
|
|
454
|
+
icon: DynamicGrid9,
|
|
455
|
+
templateId: TUISeatLayoutTemplate.PortraitDynamic_Grid9,
|
|
456
|
+
label: t('Dynamic Grid9 Layout'),
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
id: 'PortraitFixed_1v6',
|
|
460
|
+
icon: Fixed1v6,
|
|
461
|
+
templateId: TUISeatLayoutTemplate.PortraitFixed_1v6,
|
|
462
|
+
label: t('Fixed 1v6 Layout'),
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
id: 'PortraitFixed_Grid9',
|
|
466
|
+
icon: FixedGrid9,
|
|
467
|
+
templateId: TUISeatLayoutTemplate.PortraitFixed_Grid9,
|
|
468
|
+
label: t('Fixed Grid9 Layout'),
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
id: 'PortraitDynamic_1v6',
|
|
472
|
+
icon: Dynamic1v6,
|
|
473
|
+
templateId: TUISeatLayoutTemplate.PortraitDynamic_1v6,
|
|
474
|
+
label: t('Dynamic 1v6 Layout'),
|
|
475
|
+
},
|
|
283
476
|
]);
|
|
477
|
+
|
|
284
478
|
const horizontalLayoutOptions = computed(() => [
|
|
285
|
-
{
|
|
479
|
+
{
|
|
480
|
+
id: 'LandscapeDynamic_1v3',
|
|
481
|
+
icon: HorizontalFloat,
|
|
482
|
+
templateId: TUISeatLayoutTemplate.LandscapeDynamic_1v3,
|
|
483
|
+
label: t('Landscape Template'),
|
|
484
|
+
},
|
|
286
485
|
]);
|
|
486
|
+
|
|
287
487
|
const layoutOptions = computed(() => {
|
|
288
|
-
if (currentLive.value && currentLive.value?.layoutTemplate >= 200 && currentLive.value?.layoutTemplate <= 599)
|
|
488
|
+
if (currentLive.value && currentLive.value?.layoutTemplate >= 200 && currentLive.value?.layoutTemplate <= 599) {
|
|
489
|
+
return horizontalLayoutOptions.value;
|
|
490
|
+
}
|
|
289
491
|
return portraitLayoutOptions.value;
|
|
290
492
|
});
|
|
291
493
|
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
494
|
+
const selectedTemplate = ref<TUISeatLayoutTemplate | null>(currentLive.value?.layoutTemplate ?? null);
|
|
495
|
+
|
|
496
|
+
function selectTemplate(template: TUISeatLayoutTemplate) {
|
|
497
|
+
selectedTemplate.value = template;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
watch(() => currentLive.value?.layoutTemplate, (newVal) => {
|
|
501
|
+
if (newVal) {
|
|
502
|
+
selectedTemplate.value = newVal;
|
|
296
503
|
}
|
|
297
|
-
|
|
298
|
-
};
|
|
299
|
-
function selectTemplate(template: TUISeatLayoutTemplate) { selectedTemplate.value = template; }
|
|
300
|
-
watch(() => currentLive.value?.layoutTemplate, (newVal) => { if (newVal) selectedTemplate.value = newVal; });
|
|
504
|
+
});
|
|
301
505
|
|
|
302
506
|
async function handleConfirm() {
|
|
303
507
|
if (selectedTemplate.value) {
|
|
@@ -306,169 +510,50 @@ async function handleConfirm() {
|
|
|
306
510
|
layoutSwitchVisible.value = false;
|
|
307
511
|
} catch (error: any) {
|
|
308
512
|
let errorMessage = t('Layout switch failed');
|
|
309
|
-
if (error.code === TUIErrorCode.ERR_FREQ_LIMIT)
|
|
513
|
+
if (error.code === TUIErrorCode.ERR_FREQ_LIMIT) {
|
|
514
|
+
errorMessage = t('Operation too frequent, please try again later');
|
|
515
|
+
}
|
|
310
516
|
TUIToast({ type: TOAST_TYPE.ERROR, message: errorMessage });
|
|
311
517
|
}
|
|
312
518
|
} else {
|
|
313
519
|
layoutSwitchVisible.value = false;
|
|
314
520
|
}
|
|
315
521
|
}
|
|
522
|
+
|
|
316
523
|
function handleCancel() {
|
|
317
524
|
selectedTemplate.value = currentLive.value?.layoutTemplate ?? null;
|
|
318
525
|
layoutSwitchVisible.value = false;
|
|
319
526
|
}
|
|
320
|
-
watch(
|
|
321
|
-
() => currentLive.value?.liveId,
|
|
322
|
-
(liveId) => { if (!liveId) updateLiveInfo({ layoutTemplate: TUISeatLayoutTemplate.PortraitDynamic_Grid9 }); },
|
|
323
|
-
{ immediate: true },
|
|
324
|
-
);
|
|
325
527
|
</script>
|
|
326
528
|
|
|
327
|
-
<style>
|
|
328
|
-
/* 全局样式 */
|
|
329
|
-
html, body, #app { height: 100%; width: 100%; margin: 0; padding: 0; }
|
|
330
|
-
body { line-height: 1.6; color: var(--text-color-primary); background: var(--bg-color-default); }
|
|
331
|
-
:global(::before), * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
332
|
-
</style>
|
|
333
|
-
|
|
334
529
|
<style scoped>
|
|
335
|
-
|
|
336
|
-
.custom-live-pusher { height: 100vh; width: 100vw; background: linear-gradient(135deg, var(--bg-color-default) 0, var(--bg-color-function) 100%); overflow: hidden; display: flex; flex-direction: column; color: var(--text-color-primary); }
|
|
337
|
-
.main-content { display: flex; flex: 1; height: calc(100vh - 60px); gap: 16px; padding: 16px; overflow: hidden; }
|
|
338
|
-
|
|
339
|
-
/* 左右面板通用 */
|
|
340
|
-
.left-panel, .right-panel { display: flex; flex-direction: column; width: 320px; gap: 16px; flex-shrink: 0; }
|
|
341
|
-
.left-panel > *, .right-panel > * { background: var(--bg-color-operate); border-radius: 12px; border: 1px solid var(--stroke-color-primary); overflow: hidden; }
|
|
342
|
-
.scene-section, .audience-section, .message-section { display: flex; flex-direction: column; padding: 16px; overflow: hidden; }
|
|
343
|
-
.scene-section, .message-section { flex: 1; min-height: 0; }
|
|
344
|
-
.panel-title { font-size: 16px; font-weight: 600; color: var(--text-color-primary); margin-bottom: 12px; text-align: left; }
|
|
345
|
-
.message-section :deep(input), .message-section :deep(textarea) { text-align: left; }
|
|
346
|
-
|
|
347
|
-
/* 中央面板结构 */
|
|
348
|
-
.center-panel { display: flex; flex-direction: column; flex: 1; gap: 16px; min-width: 0; }
|
|
349
|
-
.stream-section { display: flex; flex-direction: column; flex: 1; min-height: 0; background: var(--bg-color-operate); border-radius: 12px; border: 1px solid var(--stroke-color-primary); overflow: hidden; }
|
|
350
|
-
.stream-header { display: flex; justify-content: space-between; align-items: center; padding: 22px; border-bottom: 1px solid var(--stroke-color-primary); }
|
|
351
|
-
.stream-title { display: flex; align-items: center; gap: 8px; font-size: 18px; font-weight: 500; color: var(--text-color-primary); }
|
|
352
|
-
.stream-audience { font-size: 14px; color: var(--text-color-primary); }
|
|
353
|
-
.stream-section :deep(>*:last-child) { flex: 1; min-height: 300px; }
|
|
354
|
-
|
|
355
|
-
/* 底部操作区集成 */
|
|
356
|
-
.live-controls { display: flex; justify-content: space-between; align-items: center; padding: 16px; border-radius: 12px; border: 1px solid var(--stroke-color-primary); gap: 16px; background: var(--bg-color-operate); backdrop-filter: blur(10px); }
|
|
357
|
-
.live-controls button { padding: 18px 20px; }
|
|
358
|
-
.bottom-panel { display: flex; align-items: center; gap: 16px; flex: 1; }
|
|
359
|
-
|
|
360
|
-
/* 高级功能:媒体设备设置 */
|
|
361
|
-
.media-device-container { display: flex; align-items: center; gap: 12px; }
|
|
362
|
-
.device-setting { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--bg-color-function); border-radius: 8px; border: 1px solid var(--stroke-color-secondary); }
|
|
363
|
-
.device-slider { width: 80px; }
|
|
364
|
-
.device-icon { cursor: pointer; color: var(--text-color-primary); transition: color .2s; }
|
|
365
|
-
.device-icon:hover { color: var(--text-color-link); }
|
|
366
|
-
|
|
367
|
-
/* 高级功能:图标操作按钮 (横竖屏、连麦、布局通用) */
|
|
368
|
-
.custom-icon-container { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; width: 56px; height: 56px; cursor: pointer; color: var(--text-color-primary); border-radius: 12px; position: relative; border: 1px solid transparent; transition: 0.2s; background: var(--bg-color-function); }
|
|
369
|
-
.custom-icon { display: inline-block; width: 24px; height: 24px; background: transparent; }
|
|
370
|
-
.custom-text { font-size: 12px; font-weight: 400; color: var(--text-color-secondary); white-space: nowrap; }
|
|
371
|
-
.custom-icon-container:not(.disabled):hover { box-shadow: 0 0 10px 0 var(--bg-color-mask); border-color: var(--stroke-color-primary); background: var(--list-color-hover); }
|
|
372
|
-
.custom-icon-container:not(.disabled):hover .custom-icon, .custom-icon-container:not(.disabled):hover .custom-text { color: var(--text-color-link); }
|
|
373
|
-
.custom-icon-container.disabled { cursor: not-allowed; opacity: 0.5; }
|
|
374
|
-
.custom-icon-container.disabled:hover { background: var(--bg-color-function); border-color: transparent; }
|
|
375
|
-
.custom-icon-container.disabled .custom-icon, .custom-icon-container.disabled .custom-text { color: var(--text-color-secondary); cursor: not-allowed; }
|
|
376
|
-
.unread-count { position: absolute; top: 0px; right: 0px; background: var(--text-color-error); color: var(--text-color-button); border-radius: 10px; padding: 2px 6px; font-size: 10px; font-weight: 600; min-width: 16px; text-align: center; line-height: 1; }
|
|
377
|
-
|
|
378
|
-
/* 弹窗:连麦面板 */
|
|
379
|
-
:deep(.co-guest-dialog) { width: 520px; }
|
|
380
|
-
.co-guest-panel { height: 560px; min-height: 300px; }
|
|
381
|
-
|
|
382
|
-
/* 弹窗:布局面板 */
|
|
383
|
-
:deep(.layout-dialog) { padding: 24px; width: 480px; max-width: 600px; }
|
|
384
|
-
:deep(.layout-dialog) .dialog-body { flex-wrap: wrap; }
|
|
385
|
-
:deep(.layout-dialog) .dialog-footer { padding-top: 32px; }
|
|
386
|
-
.layout-label { font-size: 16px; font-weight: 600; color: var(--text-color-primary); margin-bottom: 16px; }
|
|
387
|
-
.template-options { width: 100%; height: 100%; overflow: auto; margin-bottom: 16px; }
|
|
388
|
-
.options-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; }
|
|
389
|
-
.option-card { padding: 16px; background: var(--bg-color-function); border: 2px solid var(--stroke-color-secondary); border-radius: 8px; cursor: pointer; transition: 0.2s; text-align: center; }
|
|
390
|
-
.option-card:hover { border-color: var(--stroke-color-primary); background: var(--list-color-hover); }
|
|
391
|
-
.option-card.active { border-color: var(--text-color-link); background: var(--bg-color-operate); }
|
|
392
|
-
.option-info { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; }
|
|
393
|
-
.option-icon { width: 32px; height: 32px; margin: 0 auto; color: var(--text-color-secondary); }
|
|
394
|
-
.option-info h4 { margin: 8px 0 0; font-size: 12px; color: var(--text-color-primary); transition: color 0.2s; }
|
|
395
|
-
.option-card.active .option-info h4 { color: var(--text-color-link); }
|
|
530
|
+
.custom-icon-container { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; width: 56px; height: 56px; cursor: pointer; color: var(--text-color-primary); border-radius: 12px; position: relative; } .custom-icon-container .custom-icon { display: inline-block; width: 24px; height: 24px; background: transparent; } .custom-icon-container .custom-text { font-size: 12px; font-weight: 400; } .custom-icon-container:not(.disabled):hover { box-shadow: 0 0 10px 0 var(--bg-color-mask); } .custom-icon-container:not(.disabled):hover .custom-icon { color: var(--text-color-link); } .custom-icon-container:not(.disabled):hover .custom-text { color: var(--text-color-link); } .custom-icon-container.disabled { cursor: not-allowed; opacity: 0.5; color: var(--text-color-tertiary); } .custom-icon-container.disabled .custom-icon { color: var(--text-color-tertiary); cursor: not-allowed; } .custom-icon-container.disabled .custom-text { color: var(--text-color-tertiary); } :deep(.layout-dialog) { padding: 24px; width: 480px; } :deep(.layout-dialog) .dialog-body { flex-wrap: wrap; } :deep(.layout-dialog) .dialog-footer { padding-top: 32px; } .layout-label { font-size: 14px; font-weight: 400; color: var(--text-color-primary, #ffffff); margin: 4px 0px 16px 0px; } .template-options { width: 100%; height: 100%; overflow: auto; } .template-options .options-grid { display: flex; flex-wrap: wrap; gap: 16px; justify-content: flex-start; } .template-options .options-grid .option-card { box-sizing: border-box; padding: 12px 13px; width: 208px; background: #3a3a3a; border: 2px solid transparent; border-radius: 12px; cursor: pointer; transition: all 0.2s ease; text-align: center; } .template-options .options-grid .option-card:hover { background: #4a4a4a; border-color: #5a5a5a; } .template-options .options-grid .option-card.active { border: 2px solid var(--text-color-link-hover, #2B6AD6); background: var(--list-color-focused, #243047); } .template-options .options-grid .option-card.active .option-info h4 { color: #ffffff; } .template-options .options-grid .option-card .option-info { display: flex; align-items: center; justify-content: flex-start; gap: 8px; } .template-options .options-grid .option-card .option-info .option-icon { width: 24px; height: 24px; } .template-options .options-grid .option-card .option-info h4 { margin: 0; font-size: 14px; font-weight: 600; color: #ffffff; transition: color 0.2s ease; }
|
|
396
531
|
</style>
|
|
397
532
|
```
|
|
398
533
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
执行 `npm run dev` 成功后,在浏览器地址栏输入本地访问地址(例如`http://localhost:5173/live-pusher`,具体端口号可能因项目配置不同而有所差异),即可看到开播页面,开启您的第一场直播,效果如图所示。
|
|
402
|
-
``` bash
|
|
403
|
-
npm run dev
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
## 开播核心功能配置
|
|
407
|
-
|
|
408
|
-
### 横竖屏推流设置
|
|
409
|
-
|
|
410
|
-
TUILiveKit 支持横屏和竖屏两种推流模式,您可根据直播场景选择合适的推流方向:
|
|
411
|
-
| <strong>推流模式</strong> | <strong>适用场景</strong> | <strong>说明</strong> |
|
|
412
|
-
| --- | --- | --- |
|
|
413
|
-
| <strong>竖屏推流</strong> | 秀场直播、电商带货、聊天互动 | 默认模式,适合移动端观看,画面比例为 9:16。 |
|
|
414
|
-
| <strong>横屏推流</strong> | 游戏直播、在线教育、会议直播 | 适合 PC 端观看,画面比例为 16:9。 |
|
|
415
|
-
|
|
416
|
-
> **注意:**
|
|
417
|
-
>
|
|
418
|
-
> 横竖屏切换必须在开播前进行设置,直播过程中无法切换推流方向。
|
|
419
|
-
>
|
|
420
|
-
|
|
421
|
-
#### 通过 UI 交互切换横竖屏
|
|
422
|
-
|
|
423
|
-
在主播开播页的底部控制栏,点击横屏 / 竖屏按钮即可切换推流方向:
|
|
424
|
-
- 显示竖屏时,当前为竖屏推流模式;
|
|
425
|
-
|
|
426
|
-
- 显示横屏时,当前为横屏推流模式。
|
|
427
|
-
|
|
428
|
-
#### 通过代码设置横竖屏
|
|
429
|
-
|
|
430
|
-
您也可以通过调用 `updateLiveInfo` 方法,在代码中设置推流方向:
|
|
431
|
-
``` typescript
|
|
432
|
-
import { useLiveListState } from 'tuikit-atomicx-vue3';
|
|
433
|
-
|
|
434
|
-
const { updateLiveInfo } = useLiveListState();
|
|
435
|
-
|
|
436
|
-
// 切换为横屏模式(模板 ID: 200)
|
|
437
|
-
updateLiveInfo({ layoutTemplate: 200 });
|
|
438
|
-
|
|
439
|
-
// 切换为竖屏模式(模板 ID: 600)
|
|
440
|
-
updateLiveInfo({ layoutTemplate: 600 });
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
> **说明:**
|
|
444
|
-
>
|
|
445
|
-
> - 横屏模式对应的布局模板 ID 范围为 200-599,默认使用 200(横屏浮动布局)。
|
|
446
|
-
> - 竖屏模式对应的布局模板 ID 范围为 600-899,默认使用 600(动态宫格布局)。
|
|
447
|
-
> - 切换横竖屏时,系统会自动切换到对应方向的默认布局模板。
|
|
448
|
-
|
|
449
|
-
### 直播布局模板
|
|
534
|
+
#### 直播布局模板介绍
|
|
450
535
|
|
|
451
536
|
`TUILiveKit` 在横屏布局和竖屏布局下分别提供多种直播布局模板,用于控制主播与连麦嘉宾的画面排列方式。您可在开播页的布局设置中选择合适模板。
|
|
452
537
|
|
|
453
|
-
#### 布局模板介绍
|
|
454
|
-
|
|
455
538
|
(1)竖屏模式布局模板
|
|
456
539
|
|
|
457
540
|
竖屏模式下提供 **4** 种布局模板,较适用于**秀场直播、电商带货**等场景:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
541
|
+
|
|
542
|
+
|**名称**|**动态宫格布局**|**动态 1V6 布局**|**静态宫格布局**|**静态小窗布局**|
|
|
543
|
+
|---------|---------|---------|---------|---------|
|
|
544
|
+
|模板 ID|600|601|800|801|
|
|
545
|
+
|描述|默认布局,根据连麦人数动态调整宫格大小,画面自适应填充。|主播画面居中大窗显示,连麦嘉宾以浮动小窗形式环绕在主播周围。|固定 9 宫格布局,每个嘉宾占据一个固定大小的宫格位置。|主播画面全屏显示,连麦嘉宾以固定小窗形式显示在画面边缘。|
|
|
546
|
+
|适用场景|通用场景,连麦人数不固定。|主播为主、嘉宾为辅的互动场景。|多人连麦、语音聊天室等固定人数场景。|主播全屏展示、嘉宾辅助的场景。|
|
|
463
547
|
|
|
464
548
|
(2)横屏模式布局模板
|
|
465
549
|
|
|
466
550
|
横屏模式下提供 **2** 种布局模板,适用于**游戏直播、在线教育**等场景:
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
551
|
+
|
|
552
|
+
|**名称**|**横屏浮动布局**|**横屏1v1 连麦布局**|
|
|
553
|
+
|---------|---------|---------|
|
|
554
|
+
|模板 ID|200|400|
|
|
555
|
+
|描述|主播画面全屏显示,连麦嘉宾以浮动小窗形式显示在画面底部|主播与 1 位连线/PK 嘉宾以固定位置、左右各占一半的形式并排显示在横屏画面中,麦位位置固定|
|
|
556
|
+
|适用场景|游戏直播、屏幕分享、在线教育等需要横屏展示的场景|横屏方向下的双人连线与主播 PK 对战场景|
|
|
472
557
|
|
|
473
558
|
#### 通过代码设置布局模板
|
|
474
559
|
|
|
@@ -498,19 +583,67 @@ updateLiveInfo({ layoutTemplate: 200 });
|
|
|
498
583
|
updateLiveInfo({ layoutTemplate: 400 });
|
|
499
584
|
```
|
|
500
585
|
|
|
501
|
-
###
|
|
586
|
+
### 支持连观众能力
|
|
587
|
+
|
|
588
|
+
CoGuestButton 观众连麦设置
|
|
589
|
+
``` typescript
|
|
590
|
+
<template>
|
|
591
|
+
<div class="custom-icon-container" :class="{ disabled: disabled }" @click="handleCoGuest">
|
|
592
|
+
<span v-if="applicants.length > 0" class="unread-count">{{ applicants.length }}</span>
|
|
593
|
+
<IconCoGuest class="custom-icon" />
|
|
594
|
+
<span class="custom-text co-guest-text">{{ t('CoGuest') }}</span>
|
|
595
|
+
</div>
|
|
596
|
+
<TUIDialog :title="t('CoGuest')" :visible="coGuestPanelVisible" :custom-classes="['co-guest-dialog']" @close="coGuestPanelVisible = false" @confirm="coGuestPanelVisible = false" @cancel="coGuestPanelVisible = false">
|
|
597
|
+
<CoGuestPanel class="co-guest-panel" />
|
|
598
|
+
<template #footer>
|
|
599
|
+
<div />
|
|
600
|
+
</template>
|
|
601
|
+
</TUIDialog>
|
|
602
|
+
</template>
|
|
603
|
+
|
|
604
|
+
<script lang="ts" setup>
|
|
605
|
+
import { computed, ref, watch } from 'vue';
|
|
606
|
+
import { useUIKit, TUIDialog, TUIToast, TOAST_TYPE, IconCoGuest } from '@tencentcloud/uikit-base-component-vue3';
|
|
607
|
+
import { CoGuestPanel, CoHostStatus, useCoGuestState, useCoHostState, useLiveListState } from 'tuikit-atomicx-vue3';
|
|
608
|
+
|
|
609
|
+
const { t } = useUIKit();
|
|
610
|
+
const { applicants } = useCoGuestState();
|
|
611
|
+
const { currentLive } = useLiveListState();
|
|
612
|
+
const { coHostStatus } = useCoHostState();
|
|
613
|
+
const disabled = computed(() => !currentLive.value?.liveId || coHostStatus.value !== CoHostStatus.Disconnected);
|
|
614
|
+
|
|
615
|
+
const coGuestPanelVisible = ref(false);
|
|
616
|
+
|
|
617
|
+
const handleCoGuest = () => {
|
|
618
|
+
if (disabled.value) {
|
|
619
|
+
const message = !currentLive.value?.liveId
|
|
620
|
+
? t('Cannot use co-guest before live starts')
|
|
621
|
+
: t('Cannot enable audience co-hosting while co-hosting with other hosts');
|
|
622
|
+
TUIToast({ type: TOAST_TYPE.ERROR, message });
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
coGuestPanelVisible.value = true;
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
watch(disabled, () => {
|
|
629
|
+
if (disabled.value) {
|
|
630
|
+
coGuestPanelVisible.value = false;
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
</script>
|
|
502
634
|
|
|
503
|
-
|
|
635
|
+
<style scoped>.custom-icon-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:56px;height:56px;cursor:pointer;color:var(--text-color-primary);border-radius:12px;position:relative}.unread-count{position:absolute;top:0;right:0;background-color:var(--text-color-error);border-radius:50%;width:16px;height:16px;display:flex;align-items:center;justify-content:center;font-size:12px}.custom-icon{width:24px;height:24px;background:transparent}.custom-text{font-size:12px}.custom-icon-container:not(.disabled):hover{box-shadow:0 0 10px 0 var(--bg-color-mask)}.custom-icon-container:not(.disabled):hover .custom-icon,.custom-icon-container:not(.disabled):hover .custom-text{color:var(--text-color-link)}.custom-icon-container.disabled{cursor:not-allowed;opacity:.5;color:var(--text-color-secondary)}.custom-icon-container.disabled .custom-icon{cursor:not-allowed}.custom-icon-container.disabled .custom-text{color:var(--text-color-secondary)}.co-guest-panel{height:560px}:deep(.co-guest-dialog){width:520px}</style>
|
|
636
|
+
```
|
|
504
637
|
|
|
505
|
-
##
|
|
638
|
+
## 自由定制
|
|
506
639
|
|
|
507
|
-
###
|
|
640
|
+
### 配置皮肤主题及语言
|
|
508
641
|
|
|
509
|
-
|
|
642
|
+
通过配置 `App.vue` 中 `UIKitProvider` 的入参,修改主题及语言的默认值。
|
|
510
643
|
| <strong>UIKitProvider 参数</strong> | <strong>可选值</strong> | <strong>默认值</strong> |
|
|
511
644
|
| --- | --- | --- |
|
|
512
|
-
|
|
|
513
|
-
|
|
|
645
|
+
| theme | "light" \\| "dark" | "light" |
|
|
646
|
+
| language | "zh-CN" \\| "en-US" | "en-US" |
|
|
514
647
|
|
|
515
648
|
``` typescript
|
|
516
649
|
<UIKitProvider theme="light">
|
|
@@ -522,6 +655,19 @@ import { UIKitProvider } from '@tencentcloud/uikit-base-component-vue3';
|
|
|
522
655
|
</script>
|
|
523
656
|
```
|
|
524
657
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
658
|
+
我们支持您根据项目需求对观众观看页面进行 UI 定制——除页面布局调整外,还可对**颜色主题、字体、圆角、输入框、弹框**等内容进行增删改;若需新增或替换按钮(Button)、图标(Icon)等控件,也可找到对应控件的指定位置源码,直接进行增加、删除、替换等操作,满足您的 UI 定制需要。
|
|
659
|
+
| <strong>类别</strong> | <strong>功能</strong> | <strong>描述</strong> | <strong>组件详细定制指引</strong> |
|
|
660
|
+
| --- | --- | --- | --- |
|
|
661
|
+
| <strong>素材管理</strong> | 自定义素材管理区域展示 | <strong>支持:</strong><br>- <strong>调整展示 Icon 的大小、颜色或对 Icon 进行替换。</strong> | <a href="https://cloud.tencent.com/document/product/647/123838">媒体源配置面板</a> |
|
|
662
|
+
| <strong>在线观众</strong> | 自定义观众信息展示 | <strong>支持:</strong><br>- <strong>展示/隐藏观众等级。</strong><br>- <strong>观众信息字体、颜色 UI 自定义设置。</strong><br>- <strong>替换为您需要的 Icon 风格。</strong> | <a href="https://cloud.tencent.com/document/product/647/123834">视频源编辑画板</a> |
|
|
663
|
+
| <strong>消息列表</strong> | 自定义消息弹幕区域展示 | <strong>支持:</strong><br>- <strong>展示/隐藏聊天输入区域。</strong><br>- <strong>支持 UI 定制聊天气泡风格、定制观众等级等内容。</strong> | <a href="https://cloud.tencent.com/document/product/647/123836">聊天弹幕组件</a> |
|
|
664
|
+
|
|
665
|
+
## 下一步
|
|
666
|
+
|
|
667
|
+
恭喜您,现在您已经成功集成了**主播开播页面** 。接下来,您可以实现**观众观看页**、**直播列表页**和 **UI 自定义**等内容,可参考下表:
|
|
668
|
+
| <strong>功能</strong> | <strong>描述</strong> | <strong>集成指引</strong> |
|
|
669
|
+
| --- | --- | --- |
|
|
670
|
+
| <strong>观众观看</strong> | 实现观众进入主播的直播间后观看直播,实现观众连麦 、直播间信息、在线观众、弹幕显示等功能。 | 观众观看 |
|
|
671
|
+
| <strong>直播列表</strong> | 展示直播列表界面和功能,包含直播列表,房间信息展示功能。 | 直播列表 |
|
|
672
|
+
|
|
673
|
+
###
|