需要添加直播接口
This commit is contained in:
253
uni_modules/tuikit-atomic-x/state/AudioEffectState.ts
Normal file
253
uni_modules/tuikit-atomic-x/state/AudioEffectState.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* @module AudioEffectState
|
||||
* @module_description
|
||||
* 音效设置管理模块
|
||||
* 核心功能:提供变声、混响、耳返等高级音效功能,支持多种音效效果和实时音效调节。
|
||||
* 技术特点:基于音频处理算法,支持实时音效处理、低延迟音频传输、音质优化等高级技术。
|
||||
* 业务价值:为直播平台提供差异化的音效体验,增强用户参与度和直播趣味性。
|
||||
* 应用场景:变声直播、K歌直播、音效娱乐、专业音效等需要音频处理的场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
SetAudioChangerTypeOptions, SetAudioReverbTypeOptions, SetVoiceEarMonitorEnableOptions,
|
||||
VolumeOptions, AudioChangerTypeParam, AudioReverbTypeParam
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 变声器类型映射表
|
||||
* @internal
|
||||
*/
|
||||
const CHANGER_TYPE_MAP: Record<number, AudioChangerTypeParam> = {
|
||||
0: 'NONE',
|
||||
1: 'CHILD',
|
||||
2: 'LITTLE_GIRL',
|
||||
3: 'MAN',
|
||||
4: 'HEAVY_METAL',
|
||||
5: 'COLD',
|
||||
6: 'FOREIGNER',
|
||||
7: 'TRAPPED_BEAST',
|
||||
8: 'FATSO',
|
||||
9: 'STRONG_CURRENT',
|
||||
10: 'HEAVY_MACHINERY',
|
||||
11: 'ETHEREAL',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 混响类型映射表
|
||||
* @internal
|
||||
*/
|
||||
const REVERB_TYPE_MAP: Record<number, AudioReverbTypeParam> = {
|
||||
0: 'NONE',
|
||||
1: 'KTV',
|
||||
2: 'SMALL_ROOM',
|
||||
3: 'AUDITORIUM',
|
||||
4: 'DEEP',
|
||||
5: 'LOUD',
|
||||
6: 'METALLIC',
|
||||
7: 'MAGNETIC',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 耳返开关状态
|
||||
* @type {Ref<boolean>}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { isEarMonitorOpened } = useAudioEffectState('your_live_id');
|
||||
*
|
||||
* // 监听耳返开关状态变化
|
||||
* watch(isEarMonitorOpened, (newStatus) => {
|
||||
* console.log('耳返开关状态:', newStatus);
|
||||
* });
|
||||
*
|
||||
* // 获取当前耳返开关状态
|
||||
* const isOpen = isEarMonitorOpened.value;
|
||||
* console.log('当前耳返状态:', isOpen);
|
||||
*/
|
||||
const isEarMonitorOpened = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 耳返音量大小
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { earMonitorVolume } = useAudioEffectState('your_live_id');
|
||||
*
|
||||
* // 监听耳返音量变化
|
||||
* watch(earMonitorVolume, (newVolume) => {
|
||||
* console.log('耳返音量:', newVolume);
|
||||
* });
|
||||
*
|
||||
* // 获取当前耳返音量
|
||||
* const volume = earMonitorVolume.value;
|
||||
* console.log('当前耳返音量:', volume);
|
||||
*/
|
||||
const earMonitorVolume = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 变声状态
|
||||
* @type {Ref<AudioChangerTypeParam>}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { audioChangerType } = useAudioEffectState('your_live_id');
|
||||
*
|
||||
* // 监听变声类型变化
|
||||
* watch(audioChangerType, (newType) => {
|
||||
* console.log('变声类型:', newType);
|
||||
* });
|
||||
*
|
||||
* // 获取当前变声类型
|
||||
* const type = audioChangerType.value;
|
||||
* console.log('当前变声类型:', type);
|
||||
*/
|
||||
const audioChangerType = ref<AudioChangerTypeParam>('NONE');
|
||||
|
||||
/**
|
||||
* 混响状态
|
||||
* @type {Ref<AudioReverbTypeParam>}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { audioReverbType } = useAudioEffectState('your_live_id');
|
||||
*
|
||||
* // 监听混响类型变化
|
||||
* watch(audioReverbType, (newType) => {
|
||||
* console.log('混响类型:', newType);
|
||||
* });
|
||||
*
|
||||
* // 获取当前混响类型
|
||||
* const type = audioReverbType.value;
|
||||
* console.log('当前混响类型:', type);
|
||||
*/
|
||||
const audioReverbType = ref<AudioReverbTypeParam>('NONE');
|
||||
|
||||
/**
|
||||
* 设置变声效果
|
||||
* @param {SetAudioChangerTypeOptions} params - 变声效果参数
|
||||
* @returns {void}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { setAudioChangerType } = useAudioEffectState("your_live_id");
|
||||
* setAudioChangerType({ changerType: 'MAN' });
|
||||
*/
|
||||
function setAudioChangerType(params: SetAudioChangerTypeOptions): void {
|
||||
callUTSFunction("setAudioChangerType", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置混响效果
|
||||
* @param {SetAudioReverbTypeOptions} params - 混响效果参数
|
||||
* @returns {void}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { setAudioReverbType } = useAudioEffectState("your_live_id");
|
||||
* setAudioReverbType({ reverbType: 'KTV' });
|
||||
*/
|
||||
function setAudioReverbType(params: SetAudioReverbTypeOptions): void {
|
||||
callUTSFunction("setAudioReverbType", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置耳返开关状态
|
||||
* @param {SetVoiceEarMonitorEnableOptions} params - 耳返开关参数
|
||||
* @returns {void}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { setVoiceEarMonitorEnable } = useAudioEffectState("your_live_id");
|
||||
* setVoiceEarMonitorEnable({ enable: true });
|
||||
*/
|
||||
function setVoiceEarMonitorEnable(params: SetVoiceEarMonitorEnableOptions): void {
|
||||
callUTSFunction("setVoiceEarMonitorEnable", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置耳返音量大小
|
||||
* @param {VolumeOptions} params - 耳返音量参数
|
||||
* @returns {void}
|
||||
* @memberof module:AudioEffectState
|
||||
* @example
|
||||
* import { useAudioEffectState } from '@/uni_modules/tuikit-atomic-x/state/AudioEffectState';
|
||||
* const { setVoiceEarMonitorVolume } = useAudioEffectState("your_live_id");
|
||||
* setVoiceEarMonitorVolume({ volume: 50 });
|
||||
*/
|
||||
function setVoiceEarMonitorVolume(params: VolumeOptions): void {
|
||||
callUTSFunction("setVoiceEarMonitorVolume", params);
|
||||
}
|
||||
|
||||
const onAudioEffectStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "isEarMonitorOpened") {
|
||||
const data = safeJsonParse<boolean>(res, false);
|
||||
isEarMonitorOpened.value = data;
|
||||
} else if (eventName === "earMonitorVolume") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
earMonitorVolume.value = data;
|
||||
} else if (eventName === "audioChangerType") {
|
||||
const typeCode = safeJsonParse<number>(res, -1);
|
||||
const type = mapChangerTypeCodeToChangerType(typeCode);
|
||||
|
||||
if (type) {
|
||||
audioChangerType.value = type;
|
||||
} else {
|
||||
console.error(`Invalid changer type code received: ${typeCode}`);
|
||||
}
|
||||
} else if (eventName === "audioReverbType") {
|
||||
const typeCode = safeJsonParse<number>(res, -1);
|
||||
const type = mapReverbTypeCodeToReverbType(typeCode);
|
||||
|
||||
if (type) {
|
||||
audioReverbType.value = type;
|
||||
} else {
|
||||
console.error(`Invalid reverb type code received: ${typeCode}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onAudioEffectStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
function mapChangerTypeCodeToChangerType(typeCode: number): AudioChangerTypeParam | null {
|
||||
const mappedType = CHANGER_TYPE_MAP[typeCode];
|
||||
if (mappedType === undefined) {
|
||||
console.warn(`Unknown changer type code: ${typeCode}`);
|
||||
return null;
|
||||
}
|
||||
return mappedType;
|
||||
}
|
||||
|
||||
function mapReverbTypeCodeToReverbType(typeCode: number): AudioReverbTypeParam | null {
|
||||
const mappedType = REVERB_TYPE_MAP[typeCode];
|
||||
if (mappedType === undefined) {
|
||||
console.warn(`Unknown reverb type code: ${typeCode}`);
|
||||
return null;
|
||||
}
|
||||
return mappedType;
|
||||
}
|
||||
|
||||
function bindEvent(liveID: string): void {
|
||||
getRTCRoomEngineManager().on("audioEffectStoreChanged", onAudioEffectStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useAudioEffectState(liveID: string) {
|
||||
bindEvent(liveID);
|
||||
|
||||
return {
|
||||
audioChangerType, // 变声状态
|
||||
audioReverbType, // 混响状态
|
||||
isEarMonitorOpened, // 耳返开关状态
|
||||
earMonitorVolume, // 耳返音量大小
|
||||
|
||||
setAudioChangerType, // 设置变声效果
|
||||
setAudioReverbType, // 设置混响效果
|
||||
setVoiceEarMonitorEnable, // 设置耳返开关
|
||||
setVoiceEarMonitorVolume, // 设置耳返音量
|
||||
};
|
||||
}
|
||||
|
||||
export default useAudioEffectState;
|
||||
136
uni_modules/tuikit-atomic-x/state/BarrageState.ts
Normal file
136
uni_modules/tuikit-atomic-x/state/BarrageState.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @module BarrageState
|
||||
* 弹幕管理管理模块
|
||||
* @module_description
|
||||
* 核心功能:处理直播间内的文本消息、自定义消息等弹幕功能,支持弹幕发送、消息状态同步等。
|
||||
* 技术特点:支持高并发消息处理、实时消息同步、消息过滤、表情包支持等高级功能。
|
||||
* 业务价值:为直播平台提供核心的互动能力,增强用户参与度和直播氛围。
|
||||
* 应用场景:弹幕互动、消息管理、表情包、聊天室等社交互动场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
SendTextMessageOptions, SendCustomMessageOptions, BarrageParam, AppendLocalTipOptions
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
|
||||
/**
|
||||
* 当前房间的弹幕消息列表
|
||||
* @type {Ref<BarrageParam[]>}
|
||||
* @memberof module:BarrageState
|
||||
* @example
|
||||
* import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
|
||||
* const { messageList } = useBarrageState('your_live_id');
|
||||
*
|
||||
* // 监听弹幕消息列表变化
|
||||
* watch(messageList, (newMessages) => {
|
||||
* if (newMessages && newMessages.length > 0) {
|
||||
* console.log('弹幕消息列表更新:', newMessages);
|
||||
* newMessages.forEach(msg => {
|
||||
* console.log('消息内容:', msg.content);
|
||||
* console.log('发送者:', msg.sender);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前弹幕列表
|
||||
* const messages = messageList.value;
|
||||
* console.log('当前弹幕数量:', messages.length);
|
||||
*/
|
||||
const messageList = ref<BarrageParam[]>([]);
|
||||
|
||||
/**
|
||||
* 是否允许发送消息
|
||||
* @type {Ref<boolean>}
|
||||
* @memberof module:BarrageState
|
||||
* @example
|
||||
* import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
|
||||
* const { allowSendMessage } = useBarrageState('your_live_id');
|
||||
*
|
||||
* // 监听消息发送权限变化
|
||||
* watch(allowSendMessage, (newAllow) => {
|
||||
* console.log('是否允许发送消息:', newAllow);
|
||||
* });
|
||||
*
|
||||
* // 检查当前是否允许发送消息
|
||||
* const allowSend = allowSendMessage.value;
|
||||
* if (allowSend) {
|
||||
* console.log('已启用消息发送功能');
|
||||
* }
|
||||
*/
|
||||
const allowSendMessage = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
* 发送文本类型弹幕。
|
||||
* @param {SendTextMessageOptions} params - 发送文本弹幕参数
|
||||
* @returns {void}
|
||||
* @memberof module:BarrageState
|
||||
* @example
|
||||
* import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
|
||||
* const { sendTextMessage } = useBarrageState('your_live_id');
|
||||
* sendTextMessage({ liveID: "your_live_id", text: 'Hello World' });
|
||||
*/
|
||||
function sendTextMessage(params : SendTextMessageOptions) : void {
|
||||
callUTSFunction("sendTextMessage", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加本地提示消息。
|
||||
* @param {AppendLocalTipOptions} params - 添加本地提示消息参数
|
||||
* @returns {void}
|
||||
* @memberof module:BarrageState
|
||||
* @example
|
||||
* import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
|
||||
* const { appendLocalTip } = useBarrageState('your_live_id');
|
||||
* appendLocalTip({ liveID: "your_live_id", message: { text: 'Hello World' } });
|
||||
*/
|
||||
function appendLocalTip(params : AppendLocalTipOptions) : void {
|
||||
getRTCRoomEngineManager()["appendLocalTip"](params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送自定义类型弹幕。
|
||||
* @param {SendCustomMessageOptions} params - 发送自定义类型弹幕参数
|
||||
* @returns {void}
|
||||
* @memberof module:BarrageState
|
||||
* @example
|
||||
* import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
|
||||
* const { sendCustomMessage } = useBarrageState('your_live_id');
|
||||
* sendCustomMessage({ liveID: "your_live_id", businessID: "livekit", data: JSON.stringify("my custom message"});
|
||||
*/
|
||||
function sendCustomMessage(params : SendCustomMessageOptions) : void {
|
||||
callUTSFunction("sendCustomMessage", params);
|
||||
}
|
||||
|
||||
const onBarrageStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "messageList") {
|
||||
const data = safeJsonParse<BarrageParam[]>(res, []);
|
||||
messageList.value = data;
|
||||
} else if (eventName === "allowSendMessage") {
|
||||
const data = safeJsonParse<boolean>(res, false);
|
||||
allowSendMessage.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onBarrageStoreChanged JSON parse error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID : string) {
|
||||
getRTCRoomEngineManager().on("barrageStoreChanged", onBarrageStoreChanged, liveID);
|
||||
}
|
||||
export function useBarrageState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
messageList, // 当前房间的弹幕消息列表
|
||||
|
||||
// allowSendMessage, // 是否允许发送消息 TODO:待支持
|
||||
sendTextMessage, // 发送文本消息方法
|
||||
sendCustomMessage, // 发送自定义消息方法
|
||||
appendLocalTip // 添加本地提示消息方法
|
||||
};
|
||||
}
|
||||
|
||||
export default useBarrageState;
|
||||
173
uni_modules/tuikit-atomic-x/state/BaseBeautyState.ts
Normal file
173
uni_modules/tuikit-atomic-x/state/BaseBeautyState.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @module BaseBeautyState
|
||||
* @module_description
|
||||
* 基础美颜管理模块
|
||||
* 核心功能:提供磨皮、美白、红润等基础美颜效果调节,支持实时美颜参数调整。
|
||||
* 技术特点:支持实时美颜处理、参数平滑调节、性能优化等高级技术。
|
||||
* 业务价值:为直播平台提供基础的美颜能力,提升用户形象和直播质量。
|
||||
* 应用场景:美颜直播、形象优化、美颜调节、直播美化等需要美颜功能的场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { SetSmoothLevelOptions, SetWhitenessLevelOptions, SetRuddyLevelOptions } from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 磨皮级别 取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { smoothLevel } = useBaseBeautyState('your_live_id');
|
||||
*
|
||||
* // 监听磨皮级别变化
|
||||
* watch(smoothLevel, (newLevel) => {
|
||||
* console.log('磨皮级别:', newLevel);
|
||||
* });
|
||||
*
|
||||
* // 获取当前磨皮级别
|
||||
* const level = smoothLevel.value;
|
||||
* console.log('当前磨皮级别:', level);
|
||||
*/
|
||||
const smoothLevel = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 美白级别 取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { whitenessLevel } = useBaseBeautyState('your_live_id');
|
||||
*
|
||||
* // 监听美白级别变化
|
||||
* watch(whitenessLevel, (newLevel) => {
|
||||
* console.log('美白级别:', newLevel);
|
||||
* });
|
||||
*
|
||||
* // 获取当前美白级别
|
||||
* const level = whitenessLevel.value;
|
||||
* console.log('当前美白级别:', level);
|
||||
*/
|
||||
const whitenessLevel = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 红润级别 取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { ruddyLevel } = useBaseBeautyState('your_live_id');
|
||||
*
|
||||
* // 监听红润级别变化
|
||||
* watch(ruddyLevel, (newLevel) => {
|
||||
* console.log('红润级别:', newLevel);
|
||||
* });
|
||||
*
|
||||
* // 获取当前红润级别
|
||||
* const level = ruddyLevel.value;
|
||||
* console.log('当前红润级别:', level);
|
||||
*/
|
||||
const ruddyLevel = ref<number>(0);
|
||||
|
||||
const realUiValues = ref({
|
||||
whiteness: 0,
|
||||
smooth: 0,
|
||||
ruddy: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* 设置磨皮级别
|
||||
* @param {SetSmoothLevelOptions} params - 磨皮参数,取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @returns {void}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { setSmoothLevel } = useBaseBeautyState('your_live_id');
|
||||
* setSmoothLevel({ smoothLevel: 5 });
|
||||
*/
|
||||
function setSmoothLevel(params: SetSmoothLevelOptions): void {
|
||||
callUTSFunction("setSmoothLevel", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置美白级别
|
||||
* @param {SetWhitenessLevelOptions} params - 美白参数,取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @returns {void}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { setWhitenessLevel } = useBaseBeautyState('your_live_id');
|
||||
* setWhitenessLevel({ whitenessLevel: 6 });
|
||||
*/
|
||||
function setWhitenessLevel(params: SetWhitenessLevelOptions): void {
|
||||
callUTSFunction("setWhitenessLevel", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置红润级别
|
||||
* @param {SetRuddyLevelOptions} params - 红润参数,取值范围[0,9]: 0 表示关闭,9 表示效果最明显
|
||||
* @returns {void}
|
||||
* @memberof module:BaseBeautyState
|
||||
* @example
|
||||
* import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState';
|
||||
* const { setRuddyLevel } = useBaseBeautyState('your_live_id');
|
||||
* setRuddyLevel({ ruddyLevel: 4 });
|
||||
*/
|
||||
function setRuddyLevel(params: SetRuddyLevelOptions): void {
|
||||
callUTSFunction("setRuddyLevel", params);
|
||||
}
|
||||
|
||||
function setRealUiValue(type: 'whiteness' | 'smooth' | 'ruddy', value: number): void {
|
||||
realUiValues.value[type] = value;
|
||||
}
|
||||
|
||||
function getRealUiValue(type: 'whiteness' | 'smooth' | 'ruddy'): number {
|
||||
return realUiValues.value[type];
|
||||
}
|
||||
|
||||
function resetRealUiValues(): void {
|
||||
realUiValues.value.whiteness = 0;
|
||||
realUiValues.value.smooth = 0;
|
||||
realUiValues.value.ruddy = 0;
|
||||
}
|
||||
|
||||
const onBeautyStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "smoothLevel") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
smoothLevel.value = data;
|
||||
} else if (eventName === "whitenessLevel") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
whitenessLevel.value = data;
|
||||
} else if (eventName === "ruddyLevel") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
ruddyLevel.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onBeautyStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID: string): void {
|
||||
getRTCRoomEngineManager().on("beautyStoreChanged", onBeautyStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useBaseBeautyState(liveID: string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
smoothLevel, // 磨皮级别状态
|
||||
whitenessLevel, // 美白级别状态
|
||||
ruddyLevel, // 红润级别状态
|
||||
|
||||
setSmoothLevel, // 设置磨皮级别方法
|
||||
setWhitenessLevel, // 设置美白级别方法
|
||||
setRuddyLevel, // 设置红润级别方法
|
||||
|
||||
realUiValues,
|
||||
setRealUiValue,
|
||||
getRealUiValue,
|
||||
resetRealUiValues,
|
||||
};
|
||||
}
|
||||
|
||||
export default useBaseBeautyState;
|
||||
274
uni_modules/tuikit-atomic-x/state/BattleState.ts
Normal file
274
uni_modules/tuikit-atomic-x/state/BattleState.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @module BattleState
|
||||
* @module_description
|
||||
* 直播 PK 管理模块
|
||||
* 核心功能:处理主播间的PK对战流程,包括PK请求、接受、拒绝、退出等完整的PK管理功能。
|
||||
* 技术特点:支持实时PK状态同步、分数统计、PK时长控制、结果计算等高级功能。
|
||||
* 业务价值:为直播平台提供丰富的互动玩法,增加主播收益和用户粘性。
|
||||
* 应用场景:主播PK、对战直播、分数统计、互动游戏等娱乐互动场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { ILiveListener, RequestBattleOptions, CancelBattleRequestOptions, AcceptBattleOptions, RejectBattleOptions, ExitBattleOptions, BattleInfoParam, SeatUserInfoParam } from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 当前 PK 信息
|
||||
* @type {Ref<BattleInfoParam | null>}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { currentBattleInfo } = useBattleState('your_live_id');
|
||||
*
|
||||
* // 监听当前 PK 信息变化
|
||||
* watch(currentBattleInfo, (newBattle) => {
|
||||
* if (newBattle) {
|
||||
* console.log(' PK 已开始:', newBattle.battleID);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前 PK 信息
|
||||
* const battle = currentBattleInfo.value;
|
||||
*/
|
||||
const currentBattleInfo = ref<BattleInfoParam | null>(null);
|
||||
|
||||
/**
|
||||
* PK 用户列表
|
||||
* @type {Ref<SeatUserInfoParam[]>}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { battleUsers } = useBattleState('your_live_id');
|
||||
*
|
||||
* // 监听当前 PK 用户列表变化
|
||||
* watch(battleUsers, (newUsers) => {
|
||||
* console.log('PK 用户列表更新:', newUsers);
|
||||
* });
|
||||
*
|
||||
* // 获取当前 PK 用户列表
|
||||
* const users = battleUsers.value;
|
||||
* console.log('PK 用户列表更新:', users);
|
||||
*/
|
||||
const battleUsers = ref<SeatUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* PK 分数映射
|
||||
* @type {Ref<Map<string, number>> | null}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { battleScore } = useBattleState('your_live_id');
|
||||
*
|
||||
* // 监听当前 PK 分数变化
|
||||
* watch(battleScore, (newScore) => {
|
||||
* console.log('PK 分数更新:', newScore);
|
||||
* });
|
||||
*
|
||||
* // 获取当前 PK 分数
|
||||
* const score = battleScore.value;
|
||||
* console.log('当前 PK 分数:', score);
|
||||
*/
|
||||
const battleScore = ref<Map<string, number> | null>(null);
|
||||
|
||||
/**
|
||||
* 请求 PK
|
||||
* @param {RequestBattleOptions} params - 请求 PK 参数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { requestBattle } = useBattleState("your_live_id");
|
||||
* requestBattle({
|
||||
* liveID: "your_live_id",
|
||||
* userIDList: ["target_user_id"],
|
||||
* timeout: 10,
|
||||
* config: {
|
||||
* duration: 300,
|
||||
* needResponse: true,
|
||||
* extensionInfo: "{"\"type\":\"standard\""}"
|
||||
* },
|
||||
* success: (battleInfo, result) => {
|
||||
* console.log(' PK 请求成功:', battleInfo, result);
|
||||
* },
|
||||
* fail: (code, desc) => {
|
||||
* console.error(' PK 请求失败:', code, desc);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function requestBattle(params : RequestBattleOptions) : void {
|
||||
callUTSFunction("requestBattle", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消 PK 请求
|
||||
* @param {CancelBattleRequestOptions} params - 取消 PK 请求参数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { cancelBattleRequest } = useBattleState("your_live_id");
|
||||
* cancelBattleRequest({
|
||||
* liveID: "your_live_id",
|
||||
* battleID: "battle_id",
|
||||
* userIDList: ["target_user_id"],
|
||||
* success: () => {
|
||||
* console.log('取消 PK 请求成功');
|
||||
* },
|
||||
* fail: (code, desc) => {
|
||||
* console.error('取消 PK 请求失败:', code, desc);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function cancelBattleRequest(params : CancelBattleRequestOptions) : void {
|
||||
callUTSFunction("cancelBattleRequest", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受 PK
|
||||
* @param {AcceptBattleOptions} params - 接受 PK 参数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { acceptBattle } = useBattleState("your_live_id");
|
||||
* acceptBattle({
|
||||
* liveID: "your_live_id",
|
||||
* battleID: "battle_id",
|
||||
* success: () => {
|
||||
* console.log('接受 PK 成功');
|
||||
* },
|
||||
* fail: (code, desc) => {
|
||||
* console.error('接受 PK 失败:', code, desc);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function acceptBattle(params : AcceptBattleOptions) : void {
|
||||
callUTSFunction("acceptBattle", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝 PK
|
||||
* @param {RejectBattleOptions} params - 拒绝 PK 参数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { rejectBattle } = useBattleState("your_live_id");
|
||||
* rejectBattle({
|
||||
* liveID: "your_live_id",
|
||||
* battleID: "battle_id",
|
||||
* success: () => {
|
||||
* console.log('拒绝 PK 成功');
|
||||
* },
|
||||
* fail: (code, desc) => {
|
||||
* console.error('拒绝 PK 失败:', code, desc);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function rejectBattle(params : RejectBattleOptions) : void {
|
||||
callUTSFunction("rejectBattle", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出 PK
|
||||
* @param {ExitBattleOptions} params - 退出 PK 参数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { exitBattle } = useBattleState("your_live_id");
|
||||
* exitBattle({
|
||||
* liveID: "your_live_id",
|
||||
* battleID: "battle_id",
|
||||
* success: () => {
|
||||
* console.log('退出 PK 成功');
|
||||
* },
|
||||
* fail: (code, desc) => {
|
||||
* console.error('退出 PK 失败:', code, desc);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function exitBattle(params : ExitBattleOptions) : void {
|
||||
callUTSFunction("exitBattle", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 PK 事件监听器
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onBattleStarted'( PK 开始)<br>'onBattleEnded'( PK 结束)<br>'onUserJoinBattle'(当前有用户加入 PK 对战)<br>'onUserExitBattle'(当前有用户退出 PK 对战)<br>'onBattleRequestReceived'(收到 PK 请求)<br>'onBattleRequestCancelled'(取消 PK 请求)<br>'onBattleRequestTimeout'(当前 PK 对战请求超时)<br>'onBattleRequestAccept'(当前 PK 对战请求被接受)<br>'onBattleRequestReject'(当前 PK 对战请求被拒绝)
|
||||
* @param {ILiveListener} listener - 事件处理函数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { addBattleListener } = useBattleState('your_live_id');
|
||||
* addBattleListener('your_live_id', 'onBattleStarted', {
|
||||
* callback: (params) => {
|
||||
* console.log(' PK 已开始:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addBattleListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().addBattleListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除 PK 事件监听器
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onBattleStarted'( PK 开始)<br>'onBattleEnded'( PK 结束)<br>'onUserJoinBattle'(当前有用户加入 PK 对战)<br>'onUserExitBattle'(当前有用户退出 PK 对战)<br>'onBattleRequestReceived'(收到 PK 请求)<br>'onBattleRequestCancelled'(取消 PK 请求)<br>'onBattleRequestTimeout'(当前 PK 对战请求超时)<br>'onBattleRequestAccept'(当前 PK 对战请求被接受)<br>'onBattleRequestReject'(当前 PK 对战请求被拒绝)
|
||||
* @param {ILiveListener} listener - 事件处理函数
|
||||
* @returns {void}
|
||||
* @memberof module:BattleState
|
||||
* @example
|
||||
* import { useBattleState } from '@/uni_modules/tuikit-atomic-x/state/BattleState';
|
||||
* const { removeBattleListener } = useBattleState('your_live_id');
|
||||
* removeBattleListener('your_live_id', 'onBattleStarted', battleListener);
|
||||
*/
|
||||
function removeBattleListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().removeBattleListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onBattleStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
switch (eventName) {
|
||||
case "currentBattleInfo":
|
||||
const battleData = safeJsonParse<BattleInfoParam | null>(res, null);
|
||||
currentBattleInfo.value = battleData;
|
||||
break;
|
||||
case "battleUsers":
|
||||
const requestsData = safeJsonParse<SeatUserInfoParam[]>(res, []);
|
||||
battleUsers.value = requestsData;
|
||||
break;
|
||||
case "battleScore":
|
||||
const scoreData = safeJsonParse<Map<string, number> | null>(res, null);
|
||||
battleScore.value = scoreData;
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onBattleStoreChanged JSON parse error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID : string) : void {
|
||||
getRTCRoomEngineManager().on("battleStoreChanged", onBattleStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useBattleState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
currentBattleInfo, // 当前 PK 信息
|
||||
battleUsers, // PK 用户列表
|
||||
battleScore, // PK 分数映射
|
||||
|
||||
requestBattle, // 请求 PK
|
||||
cancelBattleRequest, // 取消 PK 请求
|
||||
acceptBattle, // 接受 PK
|
||||
rejectBattle, // 拒绝 PK
|
||||
exitBattle, // 退出 PK
|
||||
|
||||
addBattleListener, // 添加 PK 事件监听
|
||||
removeBattleListener // 移除 PK 事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useBattleState;
|
||||
367
uni_modules/tuikit-atomic-x/state/CoGuestState.ts
Normal file
367
uni_modules/tuikit-atomic-x/state/CoGuestState.ts
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* @module CoGuestState
|
||||
* @module_description
|
||||
* 直播连麦管理相关接口
|
||||
* 核心功能:处理观众与主播之间的连麦互动,管理连麦申请、邀请、接受、拒绝等完整的连麦流程。
|
||||
* 技术特点:基于音视频技术,支持连麦状态实时同步、音视频质量自适应、网络状况监控等高级功能。
|
||||
* 业务价值:为直播平台提供观众参与互动的核心能力,增强用户粘性和直播趣味性。
|
||||
* 应用场景:观众连麦、互动问答、在线K歌、游戏直播等需要观众参与的互动场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
ApplyForSeatOptions, CancelApplicationOptions, AcceptApplicationOptions, RejectApplicationOptions,
|
||||
InviteToSeatOptions, CancelInvitationOptions, AcceptInvitationOptions, RejectInvitationOptions, DisconnectOptions,
|
||||
LiveUserInfoParam, SeatUserInfoParam, ILiveListener,
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 已连接的连麦嘉宾列表
|
||||
* @type {Ref<SeatUserInfoParam[]>}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { connected } = useCoGuestState('your_live_id');
|
||||
*
|
||||
* // 监听已连接的连麦嘉宾列表变化
|
||||
* watch(connected, (newConnected) => {
|
||||
* if (newConnected && newConnected.length > 0) {
|
||||
* console.log('连麦嘉宾列表更新:', newConnected);
|
||||
* newConnected.forEach(guest => {
|
||||
* console.log('嘉宾用户ID:', guest.userID);
|
||||
* console.log('嘉宾昵称:', guest.nickname);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前连麦嘉宾列表
|
||||
* const guests = connected.value;
|
||||
* console.log('当前连麦嘉宾数量:', guests.length);
|
||||
*/
|
||||
const connected = ref<SeatUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 被邀请上麦的用户列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { invitees } = useCoGuestState('your_live_id');
|
||||
*
|
||||
* // 监听被邀请用户列表变化
|
||||
* watch(invitees, (newInvitees) => {
|
||||
* if (newInvitees && newInvitees.length > 0) {
|
||||
* console.log('被邀请用户列表更新:', newInvitees);
|
||||
* newInvitees.forEach(user => {
|
||||
* console.log('被邀请用户ID:', user.userID);
|
||||
* console.log('被邀请用户昵称:', user.nickname);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前被邀请用户列表
|
||||
* const invitedUsers = invitees.value;
|
||||
* console.log('当前被邀请用户数量:', invitedUsers.length);
|
||||
*/
|
||||
const invitees = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 申请上麦的用户列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { applicants } = useCoGuestState('your_live_id');
|
||||
*
|
||||
* // 监听申请上麦用户列表变化
|
||||
* watch(applicants, (newApplicants) => {
|
||||
* if (newApplicants && newApplicants.length > 0) {
|
||||
* console.log('申请上麦用户列表更新:', newApplicants);
|
||||
* newApplicants.forEach(user => {
|
||||
* console.log('申请用户ID:', user.userID);
|
||||
* console.log('申请用户昵称:', user.nickname);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前申请上麦用户列表
|
||||
* const applyingUsers = applicants.value;
|
||||
* console.log('当前申请用户数量:', applyingUsers.length);
|
||||
*/
|
||||
const applicants = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 可邀请上麦的候选用户列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { candidates } = useCoGuestState('your_live_id');
|
||||
*
|
||||
* // 监听候选用户列表变化
|
||||
* watch(candidates, (newCandidates) => {
|
||||
* if (newCandidates && newCandidates.length > 0) {
|
||||
* console.log('候选用户列表更新:', newCandidates);
|
||||
* newCandidates.forEach(user => {
|
||||
* console.log('候选用户ID:', user.userID);
|
||||
* console.log('候选用户昵称:', user.nickname);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前候选用户列表
|
||||
* const candidateUsers = candidates.value;
|
||||
* console.log('当前候选用户数量:', candidateUsers.length);
|
||||
*/
|
||||
const candidates = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 申请连麦座位
|
||||
* @param {ApplyForSeatOptions} params - 申请连麦座位参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { applyForSeat } = useCoGuestState("your_live_id");
|
||||
* applyForSeat({ seatIndex: 2, timeout: 10 , extension: 'extra info'});
|
||||
*/
|
||||
function applyForSeat(params: ApplyForSeatOptions): void {
|
||||
callUTSFunction("applyForSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消申请
|
||||
* @param {CancelApplicationOptions} params - 取消申请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { cancelApplication } = useCoGuestState("your_live_id");
|
||||
* cancelApplication({});
|
||||
*/
|
||||
function cancelApplication(params: CancelApplicationOptions): void {
|
||||
callUTSFunction("cancelApplication", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受申请
|
||||
* @param {AcceptApplicationOptions} params - 接受申请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { acceptApplication } = useCoGuestState("your_live_id");
|
||||
* acceptApplication({ userID: 'user123', seatIndex: 0 });
|
||||
*/
|
||||
function acceptApplication(params: AcceptApplicationOptions): void {
|
||||
callUTSFunction("acceptApplication", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝申请
|
||||
* @param {RejectApplicationOptions} params - 拒绝申请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { rejectApplication } = useCoGuestState("your_live_id");
|
||||
* rejectApplication({ userID: 'user123' });
|
||||
*/
|
||||
function rejectApplication(params: RejectApplicationOptions): void {
|
||||
callUTSFunction("rejectApplication", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请上麦
|
||||
* @param {InviteToSeatOptions} params - 邀请上麦参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { inviteToSeat } = useCoGuestState("your_live_id");
|
||||
* inviteToSeat({ userID: 'user123', seatIndex: 2, timeout: 10 , extension: 'extra info'});
|
||||
*/
|
||||
function inviteToSeat(params: InviteToSeatOptions): void {
|
||||
callUTSFunction("inviteToSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消邀请
|
||||
* @param {CancelInvitationOptions} params - 取消邀请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { cancelInvitation } = useCoGuestState("your_live_id");
|
||||
* cancelInvitation({ inviteeID: 'user123' });
|
||||
*/
|
||||
function cancelInvitation(params: CancelInvitationOptions): void {
|
||||
callUTSFunction("cancelInvitation", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受邀请
|
||||
* @param {AcceptInvitationOptions} params - 接受邀请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { acceptInvitation } = useCoGuestState("your_live_id");
|
||||
* acceptInvitation({ inviterID: 'user123' });
|
||||
*/
|
||||
function acceptInvitation(params: AcceptInvitationOptions): void {
|
||||
callUTSFunction("acceptInvitation", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝邀请
|
||||
* @param {RejectInvitationOptions} params - 拒绝邀请参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { rejectInvitation } = useCoGuestState("your_live_id");
|
||||
* rejectInvitation({ inviterID: 'user123'});
|
||||
*/
|
||||
function rejectInvitation(params: RejectInvitationOptions): void {
|
||||
callUTSFunction("rejectInvitation", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开连麦连接
|
||||
* @param {DisconnectOptions} params - 断开连接参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { disconnect } = useCoGuestState("your_live_id");
|
||||
* disconnect();
|
||||
*/
|
||||
function disconnect(params: DisconnectOptions): void {
|
||||
callUTSFunction("disconnect", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连麦嘉宾侧事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onHostInvitationReceived'(收到主播邀请)<br>'onHostInvitationCancelled'(主播取消邀请)<br>'onGuestApplicationResponded'(嘉宾申请响应)<br>'onGuestApplicationNoResponse'(嘉宾申请无响应)<br>'onKickedOffSeat'(被踢下座位)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { addCoGuestGuestListener } = useCoGuestState("your_live_id");
|
||||
* addCoGuestGuestListener('your_live_id', 'onHostInvitationReceived', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addCoGuestGuestListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().addCoGuestGuestListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连麦嘉宾侧事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onHostInvitationReceived'(收到主播邀请)<br>'onHostInvitationCancelled'(主播取消邀请)<br>'onGuestApplicationResponded'(嘉宾申请响应)<br>'onGuestApplicationNoResponse'(嘉宾申请无响应)<br>'onKickedOffSeat'(被踢下座位)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { removeCoGuestGuestListener } = useCoGuestState("your_live_id");
|
||||
* removeCoGuestGuestListener('your_live_id', 'onHostInvitationReceived', guestListener);
|
||||
*/
|
||||
function removeCoGuestGuestListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().removeCoGuestGuestListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连麦主播侧事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onGuestApplicationReceived'(收到嘉宾申请)<br>'onGuestApplicationCancelled'(嘉宾取消申请)<br>'onGuestApplicationProcessedByOtherHost'(嘉宾申请被其他主播处理)<br>'onHostInvitationResponded'(主播邀请得到回应)<br>'onHostInvitationNoResponse'(主播邀请无响应)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { addCoGuestHostListener } = useCoGuestState("your_live_id");
|
||||
* addCoGuestHostListener('your_live_id', 'onGuestApplicationReceived', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addCoGuestHostListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().addCoGuestHostListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连麦主播侧事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onGuestApplicationReceived'(收到嘉宾申请)<br>'onGuestApplicationCancelled'(嘉宾取消申请)<br>'onGuestApplicationProcessedByOtherHost'(嘉宾申请被其他主播处理)<br>'onHostInvitationResponded'(主播邀请得到回应)<br>'onHostInvitationNoResponse'(主播邀请无响应)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoGuestState
|
||||
* @example
|
||||
* import { useCoGuestState } from '@/uni_modules/tuikit-atomic-x/state/CoGuestState';
|
||||
* const { removeCoGuestHostListener } = useCoGuestState("your_live_id");
|
||||
* removeCoGuestHostListener('your_live_id', 'onGuestApplicationReceived', hostListener);
|
||||
*/
|
||||
function removeCoGuestHostListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().removeCoGuestHostListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onCoGuestStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "connected") {
|
||||
const data = safeJsonParse<SeatUserInfoParam[]>(res, []);
|
||||
connected.value = data;
|
||||
} else if (eventName === "invitees") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
invitees.value = data;
|
||||
} else if (eventName === "applicants") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
applicants.value = data;
|
||||
} else if (eventName === "candidates") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
candidates.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onCoGuestStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID: string): void {
|
||||
getRTCRoomEngineManager().on("coGuestStoreChanged", onCoGuestStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useCoGuestState(liveID: string) {
|
||||
bindEvent(liveID);
|
||||
|
||||
return {
|
||||
connected, // 已连接的连麦嘉宾列表
|
||||
invitees, // 被邀请上麦的用户列表
|
||||
applicants, // 申请上麦的用户列表
|
||||
candidates, // 可邀请上麦的候选用户列表
|
||||
|
||||
applyForSeat, // 申请连麦座位
|
||||
cancelApplication, // 取消申请
|
||||
acceptApplication, // 接受申请
|
||||
rejectApplication, // 拒绝申请
|
||||
inviteToSeat, // 邀请上麦
|
||||
cancelInvitation, // 取消邀请
|
||||
acceptInvitation, // 接受邀请
|
||||
rejectInvitation, // 拒绝邀请
|
||||
disconnect, // 断开连麦连接
|
||||
|
||||
addCoGuestGuestListener, // 添加嘉宾侧事件监听
|
||||
removeCoGuestGuestListener,// 移除嘉宾侧事件监听
|
||||
addCoGuestHostListener, // 添加主播侧事件监听
|
||||
removeCoGuestHostListener, // 移除主播侧事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useCoGuestState;
|
||||
277
uni_modules/tuikit-atomic-x/state/CoHostState.ts
Normal file
277
uni_modules/tuikit-atomic-x/state/CoHostState.ts
Normal file
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* @module CoHostState
|
||||
* @module_description
|
||||
* 连线主播管理模块
|
||||
* 核心功能:实现主播间的连线功能,支持主播邀请、连线申请、连线状态管理等主播间互动功能。
|
||||
* 技术特点:支持多主播音视频同步、画中画显示、音视频质量优化等高级技术,确保连线体验的流畅性。
|
||||
* 业务价值:为直播平台提供主播间协作的核心能力,支持PK、合作直播等高级业务场景。
|
||||
* 应用场景:主播连线、合作直播、跨平台连线、主播互动等高级直播场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
LiveUserInfoParam,
|
||||
RequestHostConnectionOptions, CancelHostConnectionOptions, AcceptHostConnectionOptions,
|
||||
RejectHostConnectionOptions, ExitHostConnectionOptions, ILiveListener
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 已连接的连线主播列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { connected } = useCoHostState('your_live_id');
|
||||
*
|
||||
* // 监听已连接的连线主播列表变化
|
||||
* watch(connected, (newConnected) => {
|
||||
* if (newConnected && newConnected.length > 0) {
|
||||
* console.log('已连接的主播列表:', newConnected);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前已连接的连线主播数量
|
||||
* const coHosts = connected.value;
|
||||
* console.log('已连接的主播数:', coHosts.length);
|
||||
*/
|
||||
const connected = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 被邀请连线的主播列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { invitees } = useCoHostState('your_live_id');
|
||||
*
|
||||
* // 监听被邀请的主播列表变化
|
||||
* watch(invitees, (newInvitees) => {
|
||||
* if (newInvitees && newInvitees.length > 0) {
|
||||
* console.log('被邀请的主播列表:', newInvitees);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前被邀请的主播列表
|
||||
* const invitedHosts = invitees.value;
|
||||
* console.log('被邀请的主播数:', invitedHosts.length);
|
||||
*/
|
||||
const invitees = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 当前申请连线的主播信息
|
||||
* @type {Ref<LiveUserInfoParam | undefined>}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { applicant } = useCoHostState('your_live_id');
|
||||
*
|
||||
* // 监听申请连线的主播信息变化
|
||||
* watch(applicant, (newApplicant) => {
|
||||
* if (newApplicant) {
|
||||
* console.log('申请主播:', newApplicant.userID);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前申请连线的主播信息
|
||||
* const currentApplicant = applicant.value;
|
||||
* if (currentApplicant) {
|
||||
* console.log('当前申请连线的主播:', currentApplicant.nickname);
|
||||
* }
|
||||
*/
|
||||
const applicant = ref<LiveUserInfoParam | undefined>();
|
||||
|
||||
/**
|
||||
* 可邀请连线的候选主播列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { candidates } = useCoHostState('your_live_id');
|
||||
*
|
||||
* // 监听候选主播列表变化
|
||||
* watch(candidates, (newCandidates) => {
|
||||
* if (newCandidates && newCandidates.length > 0) {
|
||||
* console.log('候选主播列表:', newCandidates);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前候选主播列表
|
||||
* const candidateHosts = candidates.value;
|
||||
* console.log('候选主播数:', candidateHosts.length);
|
||||
*/
|
||||
const candidates = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 当前连线状态
|
||||
* @type {Ref<string>}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { coHostStatus } = useCoHostState('your_live_id');
|
||||
*
|
||||
* // 监听连线状态变化
|
||||
* watch(coHostStatus, (newStatus) => {
|
||||
* console.log('连线状态:', newStatus);
|
||||
* });
|
||||
*
|
||||
* // 获取当前连线状态
|
||||
* const status = coHostStatus.value;
|
||||
* console.log('当前连线状态:', status);
|
||||
*/
|
||||
const coHostStatus = ref<string>('')
|
||||
|
||||
/**
|
||||
* 请求连线
|
||||
* @param {RequestHostConnectionOptions} params - 请求连线参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { requestHostConnection } = useCoHostState("your_live_id");
|
||||
* requestHostConnection({});
|
||||
*/
|
||||
function requestHostConnection(params: RequestHostConnectionOptions): void {
|
||||
callUTSFunction("requestHostConnection", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消连线请求
|
||||
* @param {CancelHostConnectionOptions} params - 取消连线请求参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { cancelHostConnection } = useCoHostState(“your_live_id”);
|
||||
* cancelHostConnection({ toHostLiveID : "target_live_id" });
|
||||
*/
|
||||
function cancelHostConnection(params: CancelHostConnectionOptions): void {
|
||||
callUTSFunction("cancelHostConnection", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受连线请求
|
||||
* @param {AcceptHostConnectionOptions} params - 接受连线请求参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { acceptHostConnection } = useCoHostState(“your_live_id”);
|
||||
* acceptHostConnection({ fromHostLiveID: "from_live_id" });
|
||||
*/
|
||||
function acceptHostConnection(params: AcceptHostConnectionOptions): void {
|
||||
callUTSFunction("acceptHostConnection", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝连线请求
|
||||
* @param {RejectHostConnectionOptions} params - 拒绝连线请求参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { rejectHostConnection } = useCoHostState(“your_live_id”);
|
||||
* rejectHostConnection({ fromHostLiveID: "from_live_id" });
|
||||
*/
|
||||
function rejectHostConnection(params: RejectHostConnectionOptions): void {
|
||||
callUTSFunction("rejectHostConnection", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出连线
|
||||
* @param {ExitHostConnectionOptions} params - 退出连线参数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { exitHostConnection } = useCoHostState(“your_live_id”);
|
||||
* exitHostConnection({});
|
||||
*/
|
||||
function exitHostConnection(params: ExitHostConnectionOptions): void {
|
||||
callUTSFunction("exitHostConnection", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加连线主播事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onCoHostRequestReceived'(收到连线请求)<br>'onCoHostRequestCancelled'(连线请求被取消)<br>'onCoHostRequestAccepted'(连线请求被接受)<br>'onCoHostRequestRejected'(连线请求被拒绝)<br>'onCoHostRequestTimeout'(连线请求超时)<br>'onCoHostUserJoined'(连线用户加入)<br>'onCoHostUserLeft'(连线用户离开)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { addCoHostListener } = useCoHostState("your_live_id");
|
||||
* addCoHostListener('your_live_id', 'onCoHostRequestReceived', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addCoHostListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().addCoHostListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除连线主播事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onCoHostRequestReceived'(收到连线请求)<br>'onCoHostRequestCancelled'(连线请求被取消)<br>'onCoHostRequestAccepted'(连线请求被接受)<br>'onCoHostRequestRejected'(连线请求被拒绝)<br>'onCoHostRequestTimeout'(连线请求超时)<br>'onCoHostUserJoined'(连线用户加入)<br>'onCoHostUserLeft'(连线用户离开)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:CoHostState
|
||||
* @example
|
||||
* import { useCoHostState } from '@/uni_modules/tuikit-atomic-x/state/CoHostState';
|
||||
* const { removeCoHostListener } = useCoHostState("your_live_id");
|
||||
* removeCoHostListener('your_live_id', 'onCoHostRequestReceived', hostListener);
|
||||
*/
|
||||
function removeCoHostListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().removeCoHostListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onCoHostStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "connected") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
connected.value = data;
|
||||
} else if (eventName === "invitees") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
invitees.value = data;
|
||||
} else if (eventName === "applicant") {
|
||||
const data = safeJsonParse<LiveUserInfoParam | null>(res, null);
|
||||
applicant.value = data;
|
||||
} else if (eventName === "candidates") {
|
||||
const data = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
candidates.value = data;
|
||||
} else if (eventName === "coHostStatus") {
|
||||
coHostStatus.value = JSON.parse(res);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onCoHostStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID: string): void {
|
||||
getRTCRoomEngineManager().on("coHostStoreChanged", onCoHostStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useCoHostState(liveID: string) {
|
||||
bindEvent(liveID);
|
||||
|
||||
return {
|
||||
coHostStatus, // 当前连线状态
|
||||
connected, // 已连接的连线主播列表
|
||||
invitees, // 被邀请连线的主播列表
|
||||
applicant, // 当前申请连线的主播信息
|
||||
// candidates, // 可邀请连线的候选主播列表: TODO:待支持
|
||||
|
||||
requestHostConnection, // 请求连线
|
||||
cancelHostConnection, // 取消连线请求
|
||||
acceptHostConnection, // 接受连线请求
|
||||
rejectHostConnection, // 拒绝连线请求
|
||||
exitHostConnection, // 退出连线
|
||||
|
||||
addCoHostListener, // 添加连线事件监听
|
||||
removeCoHostListener, // 移除连线事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useCoHostState;
|
||||
625
uni_modules/tuikit-atomic-x/state/DeviceState.ts
Normal file
625
uni_modules/tuikit-atomic-x/state/DeviceState.ts
Normal file
@@ -0,0 +1,625 @@
|
||||
/**
|
||||
* @module DeviceState
|
||||
* @module_description
|
||||
* 设备状态管理模块
|
||||
* 核心功能:管理摄像头、麦克风等音视频设备的控制,提供设备状态监控、权限检查等基础设备服务。
|
||||
* 技术特点:支持多设备管理、设备状态实时监控、权限动态检查、设备故障自动恢复等高级功能。
|
||||
* 业务价值:为直播系统提供稳定的设备基础,确保音视频采集的可靠性和用户体验。
|
||||
* 应用场景:设备管理、权限控制、音视频采集、设备故障处理等基础技术场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
OpenLocalMicrophoneOptions, SetAudioRouteOptions, OpenLocalCameraOptions, SwitchCameraOptions,
|
||||
UpdateVideoQualityOptions, SwitchMirrorOptions, VolumeOptions,
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import permission from "../utils/permission";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
export const DeviceStatusCode = {
|
||||
OFF: 0,
|
||||
ON: 1,
|
||||
} as const;
|
||||
|
||||
export type DeviceStatusCodeType =
|
||||
(typeof DeviceStatusCode)[keyof typeof DeviceStatusCode];
|
||||
|
||||
export const DeviceStatus = {
|
||||
OFF: "OFF",
|
||||
ON: "ON",
|
||||
} as const;
|
||||
|
||||
|
||||
export type DeviceStatusType = (typeof DeviceStatus)[keyof typeof DeviceStatus];
|
||||
|
||||
export const DeviceErrorCode = {
|
||||
NO_ERROR: 0,
|
||||
NO_DEVICE_DETECTED: 1,
|
||||
NO_SYSTEM_PERMISSION: 2,
|
||||
NOT_SUPPORT_CAPTURE: 3,
|
||||
OCCUPIED_ERROR: 4,
|
||||
UNKNOWN_ERROR: 5,
|
||||
} as const;
|
||||
|
||||
export type DeviceErrorCodeType =
|
||||
(typeof DeviceErrorCode)[keyof typeof DeviceErrorCode];
|
||||
|
||||
export const DeviceErrorEnum = {
|
||||
NO_ERROR: "NO_ERROR",
|
||||
NO_DEVICE_DETECTED: "NO_DEVICE_DETECTED",
|
||||
NO_SYSTEM_PERMISSION: "NO_SYSTEM_PERMISSION",
|
||||
NOT_SUPPORT_CAPTURE: "NOT_SUPPORT_CAPTURE",
|
||||
OCCUPIED_ERROR: "OCCUPIED_ERROR",
|
||||
UNKNOWN_ERROR: "UNKNOWN_ERROR",
|
||||
} as const;
|
||||
|
||||
export type DeviceErrorType = (typeof DeviceErrorEnum)[keyof typeof DeviceErrorEnum];
|
||||
|
||||
export const AudioOutput = {
|
||||
SPEAKERPHONE: "SPEAKERPHONE",
|
||||
EARPIECE: "EARPIECE",
|
||||
} as const;
|
||||
|
||||
export type AudioOutputType = (typeof AudioOutput)[keyof typeof AudioOutput];
|
||||
|
||||
const DEVICE_STATUS_MAP: Record<DeviceStatusCodeType, DeviceStatusType> = {
|
||||
[DeviceStatusCode.OFF]: DeviceStatus.OFF,
|
||||
[DeviceStatusCode.ON]: DeviceStatus.ON,
|
||||
} as const;
|
||||
|
||||
const DEVICE_ERROR_MAP: Record<DeviceErrorCodeType, DeviceErrorType> = {
|
||||
[DeviceErrorCode.NO_ERROR]: DeviceErrorEnum.NO_ERROR,
|
||||
[DeviceErrorCode.NO_DEVICE_DETECTED]: DeviceErrorEnum.NO_DEVICE_DETECTED,
|
||||
[DeviceErrorCode.NO_SYSTEM_PERMISSION]: DeviceErrorEnum.NO_SYSTEM_PERMISSION,
|
||||
[DeviceErrorCode.NOT_SUPPORT_CAPTURE]: DeviceErrorEnum.NOT_SUPPORT_CAPTURE,
|
||||
[DeviceErrorCode.OCCUPIED_ERROR]: DeviceErrorEnum.OCCUPIED_ERROR,
|
||||
[DeviceErrorCode.UNKNOWN_ERROR]: DeviceErrorEnum.UNKNOWN_ERROR,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 麦克风开启状态
|
||||
* @type {Ref<DeviceStatusType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { microphoneStatus } = useDeviceState();
|
||||
*
|
||||
* // 监听麦克风状态变化
|
||||
* watch(microphoneStatus, (newStatus) => {
|
||||
* console.log('麦克风状态:', newStatus);
|
||||
* if (newStatus === 'ON') {
|
||||
* console.log('麦克风已打开');
|
||||
* } else if (newStatus === 'OFF') {
|
||||
* console.log('麦克风已关闭');
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const microphoneStatus = ref<DeviceStatusType>();
|
||||
|
||||
/**
|
||||
* 麦克风最后一次错误状态
|
||||
* @type {Ref<DeviceErrorType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { microphoneLastError } = useDeviceState();
|
||||
*
|
||||
* // 监听麦克风错误状态
|
||||
* watch(microphoneLastError, (newError) => {
|
||||
* if (newError && newError !== 'NO_ERROR') {
|
||||
* console.log('麦克风错误:', newError);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const microphoneLastError = ref<DeviceErrorType>();
|
||||
|
||||
/**
|
||||
* 是否有音频发布权限
|
||||
* @type {Ref<boolean>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { hasPublishAudioPermission } = useDeviceState();
|
||||
*
|
||||
* // 检查是否有音频发布权限
|
||||
* const hasPermission = hasPublishAudioPermission.value;
|
||||
* if (!hasPermission) {
|
||||
* console.log('没有音频发布权限');
|
||||
* }
|
||||
*/
|
||||
const hasPublishAudioPermission = ref<boolean>(true);
|
||||
|
||||
/**
|
||||
* 采集音量大小(0-100)
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { captureVolume } = useDeviceState();
|
||||
*
|
||||
* // 监听采集音量变化
|
||||
* watch(captureVolume, (newVolume) => {
|
||||
* console.log('采集音量:', newVolume);
|
||||
* });
|
||||
*/
|
||||
const captureVolume = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 当前麦克风音量(0-100)
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { currentMicVolume } = useDeviceState();
|
||||
*
|
||||
* // 监听麦克风音量变化
|
||||
* watch(currentMicVolume, (newVolume) => {
|
||||
* console.log('当前麦克风音量:', newVolume);
|
||||
* });
|
||||
*/
|
||||
const currentMicVolume = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 输出音量大小(0-100)
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { outputVolume } = useDeviceState();
|
||||
*
|
||||
* // 监听输出音量变化
|
||||
* watch(outputVolume, (newVolume) => {
|
||||
* console.log('输出音量:', newVolume);
|
||||
* });
|
||||
*/
|
||||
const outputVolume = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 摄像头开启状态
|
||||
* @type {Ref<DeviceStatusType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { cameraStatus } = useDeviceState();
|
||||
*
|
||||
* // 监听摄像头状态变化
|
||||
* watch(cameraStatus, (newStatus) => {
|
||||
* console.log('摄像头状态:', newStatus);
|
||||
* if (newStatus === 'ON') {
|
||||
* console.log('摄像头已打开');
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const cameraStatus = ref<DeviceStatusType>();
|
||||
|
||||
/**
|
||||
* 摄像头最后一次错误状态
|
||||
* @type {Ref<DeviceErrorType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { cameraLastError } = useDeviceState();
|
||||
*
|
||||
* // 监听摄像头错误状态
|
||||
* watch(cameraLastError, (newError) => {
|
||||
* if (newError && newError !== 'NO_ERROR') {
|
||||
* console.log('摄像头错误:', newError);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const cameraLastError = ref<DeviceErrorType>();
|
||||
|
||||
/**
|
||||
* 是否为前置摄像头
|
||||
* @type {Ref<boolean>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { isFrontCamera } = useDeviceState();
|
||||
*
|
||||
* // 检查当前是否为前置摄像头
|
||||
* const isFront = isFrontCamera.value;
|
||||
* if (isFront) {
|
||||
* console.log('当前使用前置摄像头');
|
||||
* }
|
||||
*/
|
||||
const isFrontCamera = ref<boolean>();
|
||||
|
||||
/**
|
||||
* 本地镜像类型
|
||||
* @type {Ref<string>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { localMirrorType } = useDeviceState();
|
||||
*
|
||||
* // 获取本地镜像类型
|
||||
* const mirrorType = localMirrorType.value;
|
||||
* console.log('本地镜像类型:', mirrorType);
|
||||
*/
|
||||
const localMirrorType = ref<string>('');
|
||||
|
||||
/**
|
||||
* 本地视频质量设置
|
||||
* @type {Ref<any>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { localVideoQuality } = useDeviceState();
|
||||
*
|
||||
* // 获取本地视频质量设置
|
||||
* const quality = localVideoQuality.value;
|
||||
* console.log('本地视频质量:', quality);
|
||||
*/
|
||||
const localVideoQuality = ref<any>();
|
||||
|
||||
/**
|
||||
* 当前音频输出路由(扬声器/耳机)
|
||||
* @type {Ref<AudioOutputType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { currentAudioRoute } = useDeviceState();
|
||||
*
|
||||
* // 监听音频输出路由变化
|
||||
* watch(currentAudioRoute, (newRoute) => {
|
||||
* console.log('音频输出路由:', newRoute);
|
||||
* if (newRoute === 'SPEAKERPHONE') {
|
||||
* console.log('使用扬声器');
|
||||
* } else if (newRoute === 'EARPIECE') {
|
||||
* console.log('使用耳机');
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const currentAudioRoute = ref<AudioOutputType>();
|
||||
|
||||
/**
|
||||
* 屏幕共享状态
|
||||
* @type {Ref<DeviceStatusType>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { screenStatus } = useDeviceState();
|
||||
*
|
||||
* // 监听屏幕共享状态
|
||||
* watch(screenStatus, (newStatus) => {
|
||||
* console.log('屏幕共享状态:', newStatus);
|
||||
* if (newStatus === 'ON') {
|
||||
* console.log('屏幕共享已开启');
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
const screenStatus = ref<DeviceStatusType>();
|
||||
|
||||
/**
|
||||
* 网络信息状态
|
||||
* @type {Ref<any>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { networkInfo } = useDeviceState();
|
||||
*
|
||||
* // 获取网络信息
|
||||
* const info = networkInfo.value;
|
||||
* console.log('网络信息:', info);
|
||||
*/
|
||||
const networkInfo = ref<any>();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function mapStatusCodeToDeviceStatus(
|
||||
statusCode: number
|
||||
): DeviceStatusType | null {
|
||||
const mappedStatus = DEVICE_STATUS_MAP[statusCode as DeviceStatusCodeType];
|
||||
if (!mappedStatus) {
|
||||
console.warn(`Unknown device status code: ${statusCode}`);
|
||||
return null;
|
||||
}
|
||||
return mappedStatus;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function mapErrorCodeToDeviceError(errorCode: number): DeviceErrorType | null {
|
||||
const mappedError = DEVICE_ERROR_MAP[errorCode as DeviceErrorCodeType];
|
||||
if (!mappedError) {
|
||||
console.warn(`Unknown device error code: ${errorCode}`);
|
||||
return null;
|
||||
}
|
||||
return mappedError;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开本地麦克风
|
||||
* @param {OpenLocalMicrophoneOptions} [params] - 麦克风参数
|
||||
* @returns {Promise<void>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { openLocalMicrophone } = useDeviceState();
|
||||
* openLocalMicrophone({})
|
||||
*/
|
||||
async function openLocalMicrophone(params?: OpenLocalMicrophoneOptions): Promise<void> {
|
||||
// @ts-ignore
|
||||
if (uni.getSystemInfoSync().platform === "android") {
|
||||
await permission.requestAndroidPermission(
|
||||
"android.permission.RECORD_AUDIO"
|
||||
);
|
||||
}
|
||||
callUTSFunction("openLocalMicrophone", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭本地麦克风
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { closeLocalMicrophone } = useDeviceState();
|
||||
* closeLocalMicrophone()
|
||||
*/
|
||||
function closeLocalMicrophone(): void {
|
||||
callUTSFunction("closeLocalMicrophone");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置采集音量
|
||||
* @param {VolumeOptions} params - 音量参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { setCaptureVolume } = useDeviceState();
|
||||
* setCaptureVolume({ volume: 80 })
|
||||
*/
|
||||
function setCaptureVolume(params: VolumeOptions): void {
|
||||
callUTSFunction("setCaptureVolume", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置输出音量
|
||||
* @param {VolumeOptions} params - 音量参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { setOutputVolume } = useDeviceState();
|
||||
* setOutputVolume({ volume: 90 })
|
||||
*/
|
||||
function setOutputVolume(params: VolumeOptions): void {
|
||||
callUTSFunction("setOutputVolume", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置音频路由
|
||||
* @param {SetAudioRouteOptions} params - 音频路由参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* // 设置为扬声器
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { setAudioRoute } = useDeviceState();
|
||||
* setAudioRoute({ route: 'SPEAKERPHONE' })
|
||||
*/
|
||||
function setAudioRoute(params: SetAudioRouteOptions): void {
|
||||
callUTSFunction("setAudioRoute", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开本地摄像头
|
||||
* @param {OpenLocalCameraOptions} [params] - 摄像头参数
|
||||
* @returns {Promise<void>}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { openLocalCamera } = useDeviceState();
|
||||
* openLocalCamera({ isFront: true })
|
||||
*/
|
||||
async function openLocalCamera(params?: OpenLocalCameraOptions): Promise<void> {
|
||||
// @ts-ignore
|
||||
if (uni.getSystemInfoSync().platform === "android") {
|
||||
await permission.requestAndroidPermission("android.permission.CAMERA");
|
||||
}
|
||||
callUTSFunction("openLocalCamera", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭本地摄像头
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { closeLocalCamera } = useDeviceState();
|
||||
* closeLocalCamera()
|
||||
*/
|
||||
function closeLocalCamera(): void {
|
||||
callUTSFunction("closeLocalCamera");
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换摄像头前后置
|
||||
* @param {SwitchCameraOptions} params - 切换参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* // 切换到前置摄像头
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { switchCamera } = useDeviceState();
|
||||
* switchCamera({ isFront: true })
|
||||
*/
|
||||
function switchCamera(params: SwitchCameraOptions): void {
|
||||
callUTSFunction("switchCamera", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换镜像
|
||||
* @param {SwitchMirrorOptions} params - 镜像参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* // 设置自动镜像
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { switchMirror } = useDeviceState();
|
||||
* switchMirror({ mirrorType: 'AUTO' })
|
||||
*/
|
||||
function switchMirror(params: SwitchMirrorOptions): void {
|
||||
callUTSFunction("switchMirror", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新视频质量
|
||||
* @param {UpdateVideoQualityOptions} params - 视频质量参数
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { updateVideoQuality } = useDeviceState();
|
||||
* updateVideoQuality({ quality: 'VIDEOQUALITY_1080P' })
|
||||
*/
|
||||
function updateVideoQuality(params: UpdateVideoQualityOptions): void {
|
||||
callUTSFunction("updateVideoQuality", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始屏幕共享
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { startScreenShare } = useDeviceState();
|
||||
* startScreenShare()
|
||||
*/
|
||||
function startScreenShare(): void {
|
||||
callUTSFunction("startScreenShare");
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止屏幕共享
|
||||
* @returns {void}
|
||||
* @memberof module:DeviceState
|
||||
* @example
|
||||
* import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';
|
||||
* const { stopScreenShare } = useDeviceState();
|
||||
* stopScreenShare()
|
||||
*/
|
||||
function stopScreenShare(): void {
|
||||
callUTSFunction("stopScreenShare");
|
||||
}
|
||||
|
||||
const onDeviceStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "microphoneStatus") {
|
||||
const statusCode = safeJsonParse<number>(res, -1);
|
||||
const status = mapStatusCodeToDeviceStatus(statusCode);
|
||||
if (status) {
|
||||
microphoneStatus.value = status;
|
||||
} else {
|
||||
console.error(`Invalid microphone status code received: ${statusCode}`);
|
||||
}
|
||||
} else if (eventName === "microphoneLastError") {
|
||||
const errorCode = safeJsonParse<number>(res, -1);
|
||||
const error = mapErrorCodeToDeviceError(errorCode);
|
||||
if (error) {
|
||||
microphoneLastError.value = error;
|
||||
} else {
|
||||
console.error(`Invalid microphone error code received: ${errorCode}`);
|
||||
}
|
||||
} else if (eventName === "captureVolume") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
captureVolume.value = data;
|
||||
} else if (eventName === "currentMicVolume") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
currentMicVolume.value = data;
|
||||
}
|
||||
else if (eventName === "outputVolume") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
outputVolume.value = data;
|
||||
}
|
||||
|
||||
else if (eventName === "cameraStatus") {
|
||||
const statusCode = safeJsonParse<number>(res, -1);
|
||||
const status = mapStatusCodeToDeviceStatus(statusCode);
|
||||
if (status) {
|
||||
cameraStatus.value = status;
|
||||
} else {
|
||||
console.error(`Invalid camera status code received: ${statusCode}`);
|
||||
}
|
||||
} else if (eventName === "cameraLastError") {
|
||||
const errorCode = safeJsonParse<number>(res, -1);
|
||||
const error = mapErrorCodeToDeviceError(errorCode);
|
||||
if (error) {
|
||||
cameraLastError.value = error;
|
||||
} else {
|
||||
console.error(`Invalid camera error code received: ${errorCode}`);
|
||||
}
|
||||
} else if (eventName === "isFrontCamera") {
|
||||
const data = safeJsonParse<boolean>(res, true);
|
||||
isFrontCamera.value = data;
|
||||
} else if (eventName === "localMirrorType") {
|
||||
localMirrorType.value = JSON.parse(res);
|
||||
} else if (eventName === "localVideoQuality") {
|
||||
const data = safeJsonParse<boolean>(res, false);
|
||||
localVideoQuality.value = data;
|
||||
}
|
||||
else if (eventName === "currentAudioRoute") {
|
||||
const data = safeJsonParse<AudioOutputType>(res, AudioOutput.SPEAKERPHONE);
|
||||
currentAudioRoute.value = data;
|
||||
} else if (eventName === "screenStatus") {
|
||||
const statusCode = safeJsonParse<number>(res, -1);
|
||||
const status = mapStatusCodeToDeviceStatus(statusCode);
|
||||
if (status) {
|
||||
screenStatus.value = status;
|
||||
} else {
|
||||
console.error(`Invalid screen status code received: ${statusCode}`);
|
||||
}
|
||||
} else if (eventName === "networkInfo") {
|
||||
networkInfo.value = safeJsonParse<any>(res, {});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onDeviceStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(): void {
|
||||
getRTCRoomEngineManager().on("deviceStoreChanged", onDeviceStoreChanged, "");
|
||||
}
|
||||
|
||||
export function useDeviceState() {
|
||||
bindEvent();
|
||||
|
||||
return {
|
||||
microphoneStatus, // 麦克风开启状态
|
||||
microphoneLastError, // 麦克风最后一次错误状态
|
||||
hasPublishAudioPermission,// 是否有音频发布权限
|
||||
captureVolume, // 采集音量大小
|
||||
currentMicVolume, // 当前麦克风音量
|
||||
outputVolume, // 输出音量大小
|
||||
|
||||
cameraStatus, // 摄像头开启状态
|
||||
cameraLastError, // 摄像头最后一次错误状态
|
||||
isFrontCamera, // 是否为前置摄像头
|
||||
localMirrorType, // 本地镜像类型
|
||||
localVideoQuality, // 本地视频质量设置
|
||||
currentAudioRoute, // 当前音频输出路由
|
||||
screenStatus, // 屏幕共享状态
|
||||
networkInfo, // 网络信息状态
|
||||
|
||||
openLocalMicrophone, // 打开本地麦克风
|
||||
closeLocalMicrophone, // 关闭本地麦克风
|
||||
setCaptureVolume, // 设置采集音量
|
||||
setOutputVolume, // 设置输出音量
|
||||
setAudioRoute, // 设置音频路由
|
||||
|
||||
openLocalCamera, // 打开本地摄像头
|
||||
closeLocalCamera, // 关闭本地摄像头
|
||||
switchCamera, // 切换摄像头
|
||||
switchMirror, // 切换镜像
|
||||
updateVideoQuality, // 更新视频质量
|
||||
|
||||
startScreenShare, // 开始屏幕共享
|
||||
stopScreenShare, // 停止屏幕共享
|
||||
};
|
||||
}
|
||||
|
||||
export default useDeviceState;
|
||||
188
uni_modules/tuikit-atomic-x/state/GiftState.ts
Normal file
188
uni_modules/tuikit-atomic-x/state/GiftState.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @module GiftState
|
||||
* @module_description
|
||||
* 礼物系统管理模块
|
||||
* 核心功能:处理礼物的发送、接收、礼物列表管理等功能,支持礼物分类、礼物动画、礼物统计等完整礼物经济系统。
|
||||
* 技术特点:支持礼物动画渲染、礼物特效处理、礼物统计、礼物排行榜等高级功能。
|
||||
* 业务价值:为直播平台提供核心的变现能力,支持礼物经济、虚拟货币等商业模式。
|
||||
* 应用场景:礼物打赏、虚拟货币、礼物特效、礼物统计等商业化场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { ILiveListener, RefreshUsableGiftsOptions, SendGiftOptions, SetLanguageOptions } from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 礼物参数类型定义
|
||||
* @typedef {Object} GiftParam
|
||||
* @property {String} giftID - 礼物唯一标识
|
||||
* @property {String} name - 礼物名称
|
||||
* @property {String} desc - 礼物描述
|
||||
* @property {String} iconURL - 礼物图标URL
|
||||
* @property {String} resourceURL - 礼物动画资源URL
|
||||
* @property {number} level - 礼物等级
|
||||
* @property {number} coins - 礼物价格(金币)
|
||||
* @property {Map<String, String>} extensionInfo - 扩展信息
|
||||
* @memberof module:GiftState
|
||||
*/
|
||||
export type GiftParam = {
|
||||
giftID : String;
|
||||
name : String;
|
||||
desc : String;
|
||||
iconURL : String;
|
||||
resourceURL : String;
|
||||
level : number;
|
||||
coins : number;
|
||||
extensionInfo : Map<String, String>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 礼物分类参数类型定义
|
||||
* @typedef {Object} GiftCategoryParam
|
||||
* @property {string} [categoryID] - 分类ID
|
||||
* @property {string} [name] - 分类名称
|
||||
* @property {string} [desc] - 分类描述
|
||||
* @property {Map<string, string>} [extensionInfo] - 扩展信息
|
||||
* @property {GiftParam[]} [giftList] - 分类下的礼物列表
|
||||
* @memberof module:GiftState
|
||||
*/
|
||||
export type GiftCategoryParam = {
|
||||
categoryID ?: string;
|
||||
name ?: string;
|
||||
desc ?: string;
|
||||
extensionInfo ?: Map<string, string>;
|
||||
giftList ?: GiftParam[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 可用礼物列表
|
||||
* @type {Ref<GiftCategoryParam[]>}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { usableGifts } = useGiftState('your_live_id');
|
||||
*
|
||||
* // 监听可用礼物列表变化
|
||||
* watch(usableGifts, (newGifts) => {
|
||||
* if (newGifts && newGifts.length > 0) {
|
||||
* console.log('可用礼物更新:', newGifts);
|
||||
* newGifts.forEach(gift => {
|
||||
* console.log('礼物ID:', gift.giftID);
|
||||
* console.log('礼物名称:', gift.name);
|
||||
* console.log('礼物价格:', gift.coins);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前可用礼物列表
|
||||
* const gifts = usableGifts.value;
|
||||
* console.log('当前可用礼物数量:', gifts.length);
|
||||
*/
|
||||
const usableGifts = ref<GiftCategoryParam[]>([]);
|
||||
|
||||
/**
|
||||
* 刷新可用礼物列表
|
||||
* @param {RefreshUsableGiftsOptions} params - 刷新礼物列表参数
|
||||
* @returns {void}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { refreshUsableGifts } = useGiftState("your_live_id");
|
||||
* refreshUsableGifts({});
|
||||
*/
|
||||
function refreshUsableGifts(params : RefreshUsableGiftsOptions) : void {
|
||||
callUTSFunction("refreshUsableGifts", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送礼物
|
||||
* @param {SendGiftOptions} params - 发送礼物参数
|
||||
* @returns {void}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { sendGift } = useGiftState("your_live_id")
|
||||
* sendGift({ liveID: 'xxx', giftID: "gift001", count: 1 });
|
||||
*/
|
||||
function sendGift(params : SendGiftOptions) : void {
|
||||
callUTSFunction("sendGift", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置礼物语言
|
||||
* @param {SetLanguageOptions} params - 设置礼物语言参数
|
||||
* @returns {void}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { setLanguage } = useGiftState("your_live_id")
|
||||
* setLanguage({ liveID: 'xxx', language: "zh-CN",});
|
||||
*/
|
||||
function setLanguage(params : SetLanguageOptions) : void {
|
||||
callUTSFunction("setLanguage", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加礼物事件监听器
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onReceiveGift'(收到礼物)
|
||||
* @param {ILiveListener} listener - 事件监听器函数
|
||||
* @returns {void}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { addGiftListener } = useGiftState("your_live_id")
|
||||
* addGiftListener('your_live_id', 'onReceiveGift', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addGiftListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().addGiftListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除礼物事件监听器
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onReceiveGift'(收到礼物)
|
||||
* @param {ILiveListener} listener - 事件监听器函数
|
||||
* @returns {void}
|
||||
* @memberof module:GiftState
|
||||
* @example
|
||||
* import { useGiftState } from '@/uni_modules/tuikit-atomic-x/state/GiftState';
|
||||
* const { removeGiftListener } = useGiftState("your_live_id")
|
||||
* removeGiftListener('your_live_id', 'onReceiveGift', giftListener);
|
||||
*/
|
||||
function removeGiftListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().removeGiftListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onGiftStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "usableGifts") {
|
||||
const data = safeJsonParse<GiftCategoryParam[]>(res, []);
|
||||
usableGifts.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onGiftStoreChanged JSON parse error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID : string) : void {
|
||||
getRTCRoomEngineManager().on("giftStoreChanged", onGiftStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useGiftState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
usableGifts, // 可用礼物列表
|
||||
|
||||
refreshUsableGifts, // 刷新可用礼物列表
|
||||
sendGift, // 发送礼物
|
||||
setLanguage, // 设置礼物语言
|
||||
addGiftListener, // 添加礼物事件监听
|
||||
removeGiftListener // 移除礼物事件监听
|
||||
};
|
||||
}
|
||||
export default useGiftState;
|
||||
108
uni_modules/tuikit-atomic-x/state/LikeState.ts
Normal file
108
uni_modules/tuikit-atomic-x/state/LikeState.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @module LikeState
|
||||
* @module_description
|
||||
* 点赞互动管理模块
|
||||
* 核心功能:处理直播间的点赞功能,支持点赞发送、点赞统计、点赞事件监听等互动功能。
|
||||
* 技术特点:支持高并发点赞处理、实时点赞统计、点赞动画效果、点赞排行榜等高级功能。
|
||||
* 业务价值:为直播平台提供基础的互动能力,增强用户参与度和直播氛围。
|
||||
* 应用场景:点赞互动、人气统计、互动效果、用户参与等基础互动场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { ILiveListener, SendLikeOptions } from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 总点赞数量
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:LikeState
|
||||
* @example
|
||||
* import { useLikeState } from '@/uni_modules/tuikit-atomic-x/state/LikeState';
|
||||
* const { totalLikeCount } = useLikeState('your_live_id');
|
||||
*
|
||||
* // 监听总点赞数量变化
|
||||
* watch(totalLikeCount, (newCount) => {
|
||||
* console.log('总点赞数量:', newCount);
|
||||
* });
|
||||
*
|
||||
* // 获取当前总点赞数量
|
||||
* const likeCount = totalLikeCount.value;
|
||||
* console.log('当前获赞数:', likeCount);
|
||||
*/
|
||||
const totalLikeCount = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 发送点赞
|
||||
* @param {SendLikeOptions} params - 点赞参数
|
||||
* @returns {void}
|
||||
* @memberof module:LikeState
|
||||
* @example
|
||||
* import { useLikeState } from '@/uni_modules/tuikit-atomic-x/state/LikeState';
|
||||
* const { sendLike } = useLikeState("your_live_id");
|
||||
* sendLike({ count: 1 });
|
||||
*/
|
||||
function sendLike(params: SendLikeOptions): void {
|
||||
callUTSFunction("sendLike", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加点赞事件监听
|
||||
* @param {string} liveID - 直播ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onReceiveLikesMessage'(收到点赞消息)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LikeState
|
||||
* @example
|
||||
* import { useLikeState } from '@/uni_modules/tuikit-atomic-x/state/LikeState';
|
||||
* const { addLikeListener } = useLikeState("your_live_id");
|
||||
* addLikeListener('your_live_id', 'onReceiveLikesMessage', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addLikeListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().addLikeListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除点赞事件监听
|
||||
* @param {string} liveID - 直播ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onReceiveLikesMessage'(收到点赞消息)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LikeState
|
||||
* @example
|
||||
* import { useLikeState } from '@/uni_modules/tuikit-atomic-x/state/LikeState';
|
||||
* const { removeLikeListener } = useLikeState("your_live_id");
|
||||
* removeLikeListener('your_live_id', 'onReceiveLikesMessage', likeListener);
|
||||
*/
|
||||
function removeLikeListener(liveID: string, eventName: string, listener: ILiveListener): void {
|
||||
getRTCRoomEngineManager().removeLikeListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onLikeStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "totalLikeCount") {
|
||||
const data = safeJsonParse<number>(res, 0);
|
||||
totalLikeCount.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLikeStoreChanged JSON parse error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID: string): void {
|
||||
getRTCRoomEngineManager().on("likeStoreChanged", onLikeStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useLikeState(liveID: string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
totalLikeCount, // 总点赞数量
|
||||
sendLike, // 发送点赞
|
||||
addLikeListener, // 添加点赞事件监听
|
||||
removeLikeListener, // 移除点赞事件监听
|
||||
};
|
||||
}
|
||||
export default useLikeState;
|
||||
204
uni_modules/tuikit-atomic-x/state/LiveAudienceState.ts
Normal file
204
uni_modules/tuikit-atomic-x/state/LiveAudienceState.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* @module LiveAudienceState
|
||||
* @module_description
|
||||
* 直播间观众状态管理模块
|
||||
* 核心功能:管理直播间观众列表,提供观众权限控制、管理员设置等直播间秩序维护功能。
|
||||
* 技术特点:支持实时观众列表更新、权限分级管理、批量操作等高级功能,确保直播间秩序和用户体验。
|
||||
* 业务价值:为直播平台提供完整的观众管理解决方案,支持大规模观众场景下的秩序维护。
|
||||
* 应用场景:观众管理、权限控制、直播间秩序维护、观众互动管理等核心业务场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
FetchAudienceListOptions, SetAdministratorOptions, RevokeAdministratorOptions, KickUserOutOfRoomOptions,
|
||||
DisableSendMessageOptions, LiveUserInfoParam, ILiveListener
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 直播间观众列表
|
||||
* @type {Ref<LiveUserInfoParam[]>}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { audienceList } = useLiveAudienceState('your_live_id');
|
||||
*
|
||||
* // 监听观众列表变化
|
||||
* watch(audienceList, (newAudienceList) => {
|
||||
* if (newAudienceList && newAudienceList.length > 0) {
|
||||
* console.log('观众列表更新:', newAudienceList);
|
||||
* newAudienceList.forEach(audience => {
|
||||
* console.log('观众ID:', audience.userID);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前观众列表
|
||||
* const audiences = audienceList.value;
|
||||
* console.log('当前观众数:', audiences.length);
|
||||
*/
|
||||
const audienceList = ref<LiveUserInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 直播间观众数量
|
||||
* @type {Ref<number>}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { audienceCount } = useLiveAudienceState('your_live_id');
|
||||
*
|
||||
* // 监听观众数量变化
|
||||
* watch(audienceCount, (newCount) => {
|
||||
* console.log('观众数量更新:', newCount);
|
||||
* // 当观众数量达到某个阈值时可以进行特殊处理
|
||||
* if (newCount >= 100) {
|
||||
* console.log('直播热度很高,观众数超过100');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前观众数量
|
||||
* const count = audienceCount.value;
|
||||
* console.log('当前观众数量:', count);
|
||||
*/
|
||||
const audienceCount = ref<number>(0);
|
||||
|
||||
/**
|
||||
* 获取直播间观众列表
|
||||
* @param {FetchAudienceListOptions} [params] - 获取观众列表参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { fetchAudienceList } = useLiveAudienceState("your_live_id");
|
||||
* fetchAudienceList();
|
||||
*/
|
||||
function fetchAudienceList(params ?: FetchAudienceListOptions) : void {
|
||||
callUTSFunction("fetchAudienceList", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置管理员
|
||||
* @param {SetAdministratorOptions} params - 设置管理员参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { setAdministrator } = useLiveAudienceState("your_live_id");
|
||||
* setAdministrator({ userID: 'user123' });
|
||||
*/
|
||||
function setAdministrator(params : SetAdministratorOptions) : void {
|
||||
callUTSFunction("setAdministrator", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销管理员权限
|
||||
* @param {RevokeAdministratorOptions} params - 撤销管理员参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { revokeAdministrator } = useLiveAudienceState("your_live_id");
|
||||
* revokeAdministrator({ userID: 'user123' });
|
||||
*/
|
||||
function revokeAdministrator(params : RevokeAdministratorOptions) : void {
|
||||
callUTSFunction("revokeAdministrator", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将用户踢出直播间
|
||||
* @param {KickUserOutOfRoomOptions} params - 踢出用户参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { kickUserOutOfRoom } = useLiveAudienceState("your_live_id");
|
||||
* kickUserOutOfRoom({ userID: 'user123' });
|
||||
*/
|
||||
function kickUserOutOfRoom(params : KickUserOutOfRoomOptions) : void {
|
||||
callUTSFunction("kickUserOutOfRoom", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户发送消息
|
||||
* @param {DisableSendMessageOptions} params - 禁用发送消息参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { disableSendMessage } = useLiveAudienceState("your_live_id");
|
||||
* disableSendMessage({ userID: 'user123', disable: true });
|
||||
*/
|
||||
function disableSendMessage(params : DisableSendMessageOptions) : void {
|
||||
callUTSFunction("disableSendMessage", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加观众事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onAudienceJoined'(观众加入)<br>'onAudienceLeft'(观众离开)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { addAudienceListener } = useLiveAudienceState("your_live_id");
|
||||
* addAudienceListener('your_live_id', 'onAudienceJoined', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addAudienceListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().addAudienceListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除观众事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onAudienceJoined'(观众加入)<br>'onAudienceLeft'(观众离开)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveAudienceState
|
||||
* @example
|
||||
* import { useLiveAudienceState } from '@/uni_modules/tuikit-atomic-x/state/LiveAudienceState';
|
||||
* const { removeAudienceListener } = useLiveAudienceState("your_live_id");
|
||||
* removeAudienceListener('your_live_id', 'onAudienceJoined', audienceListener);
|
||||
*/
|
||||
function removeAudienceListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().removeAudienceListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onLiveAudienceStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "audienceList") {
|
||||
audienceList.value = safeJsonParse<LiveUserInfoParam[]>(res, []);
|
||||
} else if (eventName === "audienceCount") {
|
||||
audienceCount.value = safeJsonParse<number>(res, 0);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLiveAudienceStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID : string) : void {
|
||||
getRTCRoomEngineManager().on("liveAudienceStoreChanged", onLiveAudienceStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useLiveAudienceState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
audienceList, // 直播间观众列表
|
||||
audienceCount, // 直播间观众数量
|
||||
|
||||
fetchAudienceList, // 获取观众列表
|
||||
setAdministrator, // 设置管理员
|
||||
revokeAdministrator, // 撤销管理员权限
|
||||
kickUserOutOfRoom, // 将用户踢出直播间
|
||||
disableSendMessage, // 禁用用户发送消息
|
||||
|
||||
addAudienceListener, // 添加观众事件监听
|
||||
removeAudienceListener, // 移除观众事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useLiveAudienceState;
|
||||
281
uni_modules/tuikit-atomic-x/state/LiveListState.ts
Normal file
281
uni_modules/tuikit-atomic-x/state/LiveListState.ts
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* @module LiveListState
|
||||
* @module_description
|
||||
* 直播列表状态管理模块
|
||||
* 核心功能:管理直播间的完整生命周期,包括创建、加入、离开、结束等核心业务流程。
|
||||
* 技术特点:支持分页加载、实时状态同步、直播信息动态更新,采用响应式数据管理,确保UI与数据状态实时同步。
|
||||
* 业务价值:为直播平台提供核心的直播间管理能力,支持大规模并发直播场景,是直播业务的基础设施。
|
||||
* 应用场景:直播列表展示、直播间创建、直播状态管理、直播数据统计等核心业务场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
LiveInfoParam, FetchLiveListOptions, CreateLiveOptions, JoinLiveOptions, LeaveLiveOptions, EndLiveOptions, UpdateLiveInfoOptions, UpdateLiveMetaDataOptions, CallExperimentalAPIOptions, ILiveListener,
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 直播列表数据
|
||||
* @type {Ref<LiveInfoParam[]>}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { liveList } = useLiveListState();
|
||||
*
|
||||
* // 监听直播列表变化
|
||||
* watch(liveList, (newList) => {
|
||||
* if (newList && newList.length > 0) {
|
||||
* console.log('直播列表更新:', newList);
|
||||
* newList.forEach(live => {
|
||||
* console.log('直播ID:', live.liveID);
|
||||
* console.log('直播标题:', live.title);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前直播列表
|
||||
* const currentList = liveList.value;
|
||||
* console.log('当前直播数量:', currentList.length);
|
||||
*/
|
||||
const liveList = ref<LiveInfoParam[]>([]);
|
||||
|
||||
/**
|
||||
* 直播列表游标,用于分页加载
|
||||
* @type {Ref<string>}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { liveListCursor } = useLiveListState();
|
||||
*
|
||||
* // 监听游标变化用于分页加载
|
||||
* watch(liveListCursor, (newCursor) => {
|
||||
* console.log('直播列表游标更新:', newCursor);
|
||||
* // 当游标更新时,可以获取下一页数据
|
||||
* if (newCursor) {
|
||||
* console.log('加载下一页直播列表');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前游标
|
||||
* const cursor = liveListCursor.value;
|
||||
* if (cursor) {
|
||||
* console.log('当前分页游标:', cursor);
|
||||
* }
|
||||
*/
|
||||
const liveListCursor = ref<string>("");
|
||||
|
||||
/**
|
||||
* 当前直播信息
|
||||
* @type {Ref<LiveInfoParam | null>}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { currentLive } = useLiveListState();
|
||||
*
|
||||
* // 监听当前直播信息变化
|
||||
* watch(currentLive, (newLive) => {
|
||||
* if (newLive) {
|
||||
* console.log('当前直播信息更新:', newLive);
|
||||
* console.log('直播ID:', newLive.liveID);
|
||||
* console.log('直播标题:', newLive.title);
|
||||
* console.log('观看人数:', newLive.viewerCount);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前直播信息
|
||||
* const live = currentLive.value;
|
||||
* if (live) {
|
||||
* console.log('当前进入的直播:', live.title);
|
||||
* }
|
||||
*/
|
||||
const currentLive = ref<LiveInfoParam | null>(null);
|
||||
|
||||
/**
|
||||
* 获取直播列表
|
||||
* @param {FetchLiveListOptions} params - 获取参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { fetchLiveList } = useLiveListState();
|
||||
* fetchLiveList({ cursor: "", count: 20 });
|
||||
*/
|
||||
function fetchLiveList(params : FetchLiveListOptions) : void {
|
||||
callUTSFunction("fetchLiveList", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建直播间
|
||||
* @param {CreateLiveOptions} params - 创建参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { createLive } = useLiveListState();
|
||||
* createLive({ title: 'my live', coverUrl: 'https://example.com/cover.jpg'});
|
||||
*/
|
||||
function createLive(params : CreateLiveOptions) : void {
|
||||
callUTSFunction("createLive", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入直播间
|
||||
* @param {JoinLiveOptions} params - 加入参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { joinLive } = useLiveListState();
|
||||
* joinLive({ liveID: 'host_live_id' });
|
||||
*/
|
||||
function joinLive(params : JoinLiveOptions) : void {
|
||||
callUTSFunction("joinLive", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 离开直播间
|
||||
* @param {LeaveLiveOptions} [params] - 离开参数(可选)
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { leaveLive } = useLiveListState();
|
||||
* leaveLive();
|
||||
*/
|
||||
function leaveLive(params ?: LeaveLiveOptions) : void {
|
||||
callUTSFunction("leaveLive", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束直播
|
||||
* @param {EndLiveOptions} [params] - 结束参数(可选)
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { endLive } = useLiveListState();
|
||||
* endLive();
|
||||
*/
|
||||
function endLive(params ?: EndLiveOptions) : void {
|
||||
callUTSFunction("endLive", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新直播信息
|
||||
* @param {UpdateLiveInfoOptions} params - 更新参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { updateLiveInfo } = useLiveListState();
|
||||
* updateLiveInfo({ liveID: 'your_live_id', title: 'new title' });
|
||||
*/
|
||||
function updateLiveInfo(params : UpdateLiveInfoOptions) : void {
|
||||
callUTSFunction("updateLiveInfo", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新直播元数据
|
||||
* @param {UpdateLiveMetaDataOptions} params - 更新直播元数据, 监听 currentLive 获取更新结果
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { updateLiveMetaData } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { updateLiveMetaData } = useLiveListState();
|
||||
* updateLiveMetaData({metaData: '['key': 'value']' });
|
||||
*/
|
||||
function updateLiveMetaData(params : UpdateLiveMetaDataOptions) : void {
|
||||
callUTSFunction("updateLiveMetaData", params);
|
||||
}
|
||||
|
||||
function callExperimentalAPI(params : CallExperimentalAPIOptions) : void {
|
||||
const defaultCallback = {
|
||||
onResponse: (res ?: string) => {
|
||||
console.log("onExperimentalAPIResponse: ", res);
|
||||
},
|
||||
};
|
||||
const finalParams = {
|
||||
...params,
|
||||
onResponse: params.onResponse || defaultCallback.onResponse,
|
||||
};
|
||||
|
||||
console.log("callExperimentalAPI", finalParams);
|
||||
getRTCRoomEngineManager().callExperimentalAPI(finalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加直播列表事件监听
|
||||
* @param {string} eventName - 事件名称,可选值: 'onLiveEnded'(直播结束)<br>'onKickedOutOfLive'(被踢出直播间)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { addLiveListListener } = useLiveListState();
|
||||
* addLiveListListener('onLiveEnded', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addLiveListListener(eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().addLiveListListener(eventName, listener);
|
||||
}
|
||||
/**
|
||||
* 移除直播列表事件监听
|
||||
* @param {string} eventName - 事件名称,可选值: 'onLiveEnded'(直播结束)<br>'onKickedOutOfLive'(被踢出直播间)
|
||||
* @param {ILiveListener} listener - 事件回调函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveListState
|
||||
* @example
|
||||
* import { useLiveListState } from '@/uni_modules/tuikit-atomic-x/state/LiveListState';
|
||||
* const { removeLiveListListener } = useLiveListState();
|
||||
* removeLiveListListener('onLiveEnded', liveEndedListener);
|
||||
*/
|
||||
function removeLiveListListener(eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().removeLiveListListener(eventName, listener);
|
||||
}
|
||||
|
||||
const onLiveStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "liveList") {
|
||||
const data = safeJsonParse<LiveInfoParam[]>(res, []);
|
||||
liveList.value = data;
|
||||
} else if (eventName === "liveListCursor") {
|
||||
const data = safeJsonParse<string>(res, "");
|
||||
liveListCursor.value = data;
|
||||
} else if (eventName === "currentLive") {
|
||||
const data = safeJsonParse<LiveInfoParam | null>(res, null);
|
||||
currentLive.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLiveStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent() : void {
|
||||
getRTCRoomEngineManager().on("liveStoreChanged", onLiveStoreChanged, "");
|
||||
}
|
||||
|
||||
export function useLiveListState() {
|
||||
bindEvent();
|
||||
return {
|
||||
liveList, // 直播列表数据
|
||||
liveListCursor, // 直播列表分页游标
|
||||
currentLive, // 当前直播信息
|
||||
|
||||
fetchLiveList, // 获取直播列表
|
||||
createLive, // 创建直播
|
||||
joinLive, // 加入直播
|
||||
leaveLive, // 离开直播
|
||||
endLive, // 结束直播
|
||||
updateLiveInfo, // 更新直播信息
|
||||
updateLiveMetaData, // 更新直播元数据
|
||||
callExperimentalAPI,
|
||||
|
||||
addLiveListListener, // 添加事件监听
|
||||
removeLiveListListener, // 移除事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useLiveListState;
|
||||
439
uni_modules/tuikit-atomic-x/state/LiveSeatState.ts
Normal file
439
uni_modules/tuikit-atomic-x/state/LiveSeatState.ts
Normal file
@@ -0,0 +1,439 @@
|
||||
/**
|
||||
* @module LiveSeatState
|
||||
* @module_description
|
||||
* 直播间麦位管理模块
|
||||
* 核心功能:实现多人连麦场景下的座位控制,支持复杂的座位状态管理和音视频设备控制。
|
||||
* 技术特点:基于音视频技术,支持多路音视频流管理,提供座位锁定、设备控制、权限管理等高级功能。
|
||||
* 业务价值:为多人互动直播提供核心技术支撑,支持PK、连麦、多人游戏等丰富的互动场景。
|
||||
* 应用场景:多人连麦、主播PK、互动游戏、在线教育、会议直播等需要多人音视频互动的场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
TakeSeatOptions, LeaveSeatOptions, MuteMicrophoneOptions, UnmuteMicrophoneOptions, KickUserOutOfSeatOptions,
|
||||
MoveUserToSeatOptions, UnlockSeatOptions, SeatUserInfoParam, LockSeatOptions,
|
||||
OpenRemoteCameraOptions, CloseRemoteCameraOptions, OpenRemoteMicrophoneOptions, CloseRemoteMicrophoneOptions, ILiveListener,
|
||||
} from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 区域信息参数类型定义
|
||||
* @typedef {Object} RegionInfoParams
|
||||
* @property {number} x X坐标位置
|
||||
* @property {number} y Y坐标位置
|
||||
* @property {number} w 宽度
|
||||
* @property {number} h 高度
|
||||
* @property {number} zorder 层级顺序
|
||||
* @memberof module:LiveSeatState
|
||||
*/
|
||||
export type RegionInfoParams = {
|
||||
x : number;
|
||||
y : number;
|
||||
w : number;
|
||||
h : number;
|
||||
zorder : number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直播画布参数类型定义
|
||||
* @typedef {Object} LiveCanvasParams
|
||||
* @property {number} w 画布宽度
|
||||
* @property {number} h 画布高度
|
||||
* @property {string} [background] 背景色(可选)
|
||||
* @memberof module:LiveSeatState
|
||||
*/
|
||||
export type LiveCanvasParams = {
|
||||
w : number;
|
||||
h : number;
|
||||
background ?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 座位信息类型定义
|
||||
* @typedef {Object} SeatInfo
|
||||
* @property {number} index 座位索引
|
||||
* @property {boolean} isLocked 是否锁定
|
||||
* @property {SeatUserInfoParam} userInfo 座位上用户信息
|
||||
* @property {RegionInfoParams} region 座位区域信息
|
||||
* @memberof module:LiveSeatState
|
||||
*/
|
||||
export type SeatInfo = {
|
||||
index : number;
|
||||
isLocked : boolean;
|
||||
userInfo : SeatUserInfoParam;
|
||||
region : RegionInfoParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 座位列表
|
||||
* @type {Ref<SeatInfo[]>}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { seatList } = useLiveSeatState('your_live_id');
|
||||
*
|
||||
* // 监听座位列表变化
|
||||
* watch(seatList, (newSeatList) => {
|
||||
* if (newSeatList && newSeatList.length > 0) {
|
||||
* console.log('座位列表更新:', newSeatList);
|
||||
* newSeatList.forEach(seat => {
|
||||
* console.log('座位索引:', seat.index);
|
||||
* console.log('座位是否锁定:', seat.isLocked);
|
||||
* if (seat.userInfo) {
|
||||
* console.log('座位上用户ID:', seat.userInfo.userID);
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前座位列表
|
||||
* const seats = seatList.value;
|
||||
* console.log('当前座位数:', seats.length);
|
||||
*/
|
||||
const seatList = ref<SeatInfo[]>([]);
|
||||
|
||||
/**
|
||||
* 画布信息
|
||||
* @type {Ref<LiveCanvasParams | null>}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { canvas } = useLiveSeatState('your_live_id');
|
||||
*
|
||||
* // 监听画布信息变化
|
||||
* watch(canvas, (newCanvas) => {
|
||||
* if (newCanvas) {
|
||||
* console.log('画布信息更新:', newCanvas);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前画布信息
|
||||
* const currentCanvas = canvas.value;
|
||||
* if (currentCanvas) {
|
||||
* console.log('当前画布分辨率:', currentCanvas.w, 'x', currentCanvas.h);
|
||||
* }
|
||||
*/
|
||||
const canvas = ref<LiveCanvasParams | null>(null);
|
||||
|
||||
/**
|
||||
* 正在说话的用户列表
|
||||
* @type {Ref<Map<string, number> | null>}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { speakingUsers } = useLiveSeatState('your_live_id');
|
||||
*
|
||||
* // 监听正在说话的用户列表变化
|
||||
* watch(speakingUsers, (newSpeakingUsers) => {
|
||||
* if (newSpeakingUsers && newSpeakingUsers.size > 0) {
|
||||
* console.log('正在说话的用户更新');
|
||||
* newSpeakingUsers.forEach((volume, userID) => {
|
||||
* console.log('用户ID:', userID);
|
||||
* console.log('音量:', volume);
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前正在说话的用户数量
|
||||
* const users = speakingUsers.value;
|
||||
* if (users) {
|
||||
* console.log('当前说话的用户数:', users.size);
|
||||
* }
|
||||
*/
|
||||
const speakingUsers = ref<Map<string, number> | null>(null);
|
||||
|
||||
/**
|
||||
* 用户上麦
|
||||
* @param {TakeSeatOptions} params - 上麦参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { takeSeat } = useLiveSeatState('your_live_id');
|
||||
* takeSeat({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('上麦成功'),
|
||||
* onError: (error) => console.error('上麦失败:', error)
|
||||
* });
|
||||
*/
|
||||
function takeSeat(params : TakeSeatOptions) : void {
|
||||
callUTSFunction("takeSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户下麦
|
||||
* @param {LeaveSeatOptions} params - 下麦参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { leaveSeat } = useLiveSeatState('your_live_id');
|
||||
* leaveSeat({
|
||||
* onSuccess: () => console.log('下麦成功'),
|
||||
* onError: (error) => console.error('下麦失败:', error)
|
||||
* });
|
||||
*/
|
||||
function leaveSeat(params : LeaveSeatOptions) : void {
|
||||
callUTSFunction("leaveSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静音麦克风
|
||||
* @param {MuteMicrophoneOptions} params - 静音参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { muteMicrophone } = useLiveSeatState('your_live_id');
|
||||
* muteMicrophone({
|
||||
* onSuccess: () => console.log('麦克风静音成功'),
|
||||
* onError: (error) => console.error('麦克风静音失败:', error)
|
||||
* });
|
||||
*/
|
||||
function muteMicrophone(params : MuteMicrophoneOptions) : void {
|
||||
callUTSFunction("muteMicrophone", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消静音麦克风
|
||||
* @param {UnmuteMicrophoneOptions} params - 取消静音参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { unmuteMicrophone } = useLiveSeatState('your_live_id');
|
||||
* unmuteMicrophone({
|
||||
* onSuccess: () => console.log('麦克风取消静音成功'),
|
||||
* onError: (error) => console.error('麦克风取消静音失败:', error)
|
||||
* });
|
||||
*/
|
||||
function unmuteMicrophone(params : UnmuteMicrophoneOptions) : void {
|
||||
callUTSFunction("unmuteMicrophone", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将用户踢出座位
|
||||
* @param {KickUserOutOfSeatOptions} params - 踢出参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { kickUserOutOfSeat } = useLiveSeatState('your_live_id');
|
||||
* kickUserOutOfSeat({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('踢出用户成功'),
|
||||
* onError: (error) => console.error('踢出用户失败:', error)
|
||||
* });
|
||||
*/
|
||||
function kickUserOutOfSeat(params : KickUserOutOfSeatOptions) : void {
|
||||
callUTSFunction("kickUserOutOfSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动用户到指定座位
|
||||
* @param {MoveUserToSeatOptions} params - 移动参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { moveUserToSeat } = useLiveSeatState('your_live_id');
|
||||
* moveUserToSeat({
|
||||
* fromSeatIndex: 1,
|
||||
* toSeatIndex: 3,
|
||||
* onSuccess: () => console.log('用户移动成功'),
|
||||
* onError: (error) => console.error('用户移动失败:', error)
|
||||
* });
|
||||
*/
|
||||
function moveUserToSeat(params : MoveUserToSeatOptions) : void {
|
||||
callUTSFunction("moveUserToSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 锁定座位
|
||||
* @param {LockSeatOptions} params - 锁定参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { lockSeat } = useLiveSeatState('your_live_id');
|
||||
* lockSeat({
|
||||
* seatIndex: 2,
|
||||
* onSuccess: () => console.log('座位锁定成功'),
|
||||
* onError: (error) => console.error('座位锁定失败:', error)
|
||||
* });
|
||||
*/
|
||||
function lockSeat(params : LockSeatOptions) : void {
|
||||
callUTSFunction("lockSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁座位
|
||||
* @param {UnlockSeatOptions} params - 解锁参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { unlockSeat } = useLiveSeatState('your_live_id');
|
||||
* unlockSeat({
|
||||
* seatIndex: 2,
|
||||
* onSuccess: () => console.log('座位解锁成功'),
|
||||
* onError: (error) => console.error('座位解锁失败:', error)
|
||||
* });
|
||||
*/
|
||||
function unlockSeat(params : UnlockSeatOptions) : void {
|
||||
callUTSFunction("unlockSeat", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启远程摄像头
|
||||
* @param {OpenRemoteCameraOptions} params - 开启摄像头参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { openRemoteCamera } = useLiveSeatState('your_live_id');
|
||||
* openRemoteCamera({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('远程摄像头开启成功'),
|
||||
* onError: (error) => console.error('远程摄像头开启失败:', error)
|
||||
* });
|
||||
*/
|
||||
function openRemoteCamera(params : OpenRemoteCameraOptions) : void {
|
||||
callUTSFunction("openRemoteCamera", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程摄像头
|
||||
* @param {CloseRemoteCameraOptions} params - 关闭摄像头参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { closeRemoteCamera } = useLiveSeatState('your_live_id');
|
||||
* closeRemoteCamera({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('远程摄像头关闭成功'),
|
||||
* onError: (error) => console.error('远程摄像头关闭失败:', error)
|
||||
* });
|
||||
*/
|
||||
function closeRemoteCamera(params : CloseRemoteCameraOptions) : void {
|
||||
callUTSFunction("closeRemoteCamera", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启远程麦克风
|
||||
* @param {OpenRemoteMicrophoneOptions} params - 开启麦克风参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { openRemoteMicrophone } = useLiveSeatState('your_live_id');
|
||||
* openRemoteMicrophone({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('远程麦克风开启成功'),
|
||||
* onError: (error) => console.error('远程麦克风开启失败:', error)
|
||||
* });
|
||||
*/
|
||||
function openRemoteMicrophone(params : OpenRemoteMicrophoneOptions) : void {
|
||||
callUTSFunction("openRemoteMicrophone", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭远程麦克风
|
||||
* @param {CloseRemoteMicrophoneOptions} params - 关闭麦克风参数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { closeRemoteMicrophone } = useLiveSeatState('your_live_id');
|
||||
* closeRemoteMicrophone({
|
||||
* seatIndex: 1,
|
||||
* onSuccess: () => console.log('远程麦克风关闭成功'),
|
||||
* onError: (error) => console.error('远程麦克风关闭失败:', error)
|
||||
* });
|
||||
*/
|
||||
function closeRemoteMicrophone(params : CloseRemoteMicrophoneOptions) : void {
|
||||
callUTSFunction("closeRemoteMicrophone", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加座位事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onLocalCameraOpenedByAdmin'(本地摄像头被管理员开启)<br>'onLocalCameraClosedByAdmin'(本地摄像头被管理员关闭)<br>'onLocalMicrophoneOpenedByAdmin'(本地麦克风被管理员开启)<br>'onLocalMicrophoneClosedByAdmin'(本地麦克风被管理员关闭)
|
||||
* @param {ILiveListener} listener - 事件处理函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { addLiveSeatEventListener } = useLiveSeatState('your_live_id');
|
||||
* addLiveSeatEventListener('your_live_id', 'onLocalCameraOpenedByAdmin', {
|
||||
* callback: (params) => {
|
||||
* console.log('result:', params);
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
function addLiveSeatEventListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().addLiveSeatEventListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除座位事件监听
|
||||
* @param {string} liveID - 直播间ID
|
||||
* @param {string} eventName - 事件名称,可选值: 'onLocalCameraOpenedByAdmin'(本地摄像头被管理员开启)<br>'onLocalCameraClosedByAdmin'(本地摄像头被管理员关闭)<br>'onLocalMicrophoneOpenedByAdmin'(本地麦克风被管理员开启)<br>'onLocalMicrophoneClosedByAdmin'(本地麦克风被管理员关闭)
|
||||
* @param {ILiveListener} listener - 事件处理函数
|
||||
* @returns {void}
|
||||
* @memberof module:LiveSeatState
|
||||
* @example
|
||||
* import { useLiveSeatState } from '@/uni_modules/tuikit-atomic-x/state/LiveSeatState';
|
||||
* const { removeLiveSeatEventListener } = useLiveSeatState('your_live_id');
|
||||
* removeLiveSeatEventListener('your_live_id', 'onLocalCameraOpenedByAdmin', seatListener);
|
||||
*/
|
||||
function removeLiveSeatEventListener(liveID : string, eventName : string, listener : ILiveListener) : void {
|
||||
getRTCRoomEngineManager().removeLiveSeatEventListener(liveID, eventName, listener);
|
||||
}
|
||||
|
||||
const onLiveSeatStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "seatList") {
|
||||
seatList.value = safeJsonParse<SeatInfo[]>(res, []);
|
||||
} else if (eventName === "canvas") {
|
||||
canvas.value = safeJsonParse<LiveCanvasParams | null>(res, null);
|
||||
} else if (eventName === "speakingUsers") {
|
||||
speakingUsers.value = safeJsonParse<Map<string, number> | null>(res, null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLiveSeatStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function bindEvent(liveID : string) : void {
|
||||
getRTCRoomEngineManager().on("liveSeatStoreChanged", onLiveSeatStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useLiveSeatState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
seatList, // 座位列表
|
||||
canvas, // 画布信息
|
||||
speakingUsers, // 正在说话的用户列表
|
||||
|
||||
takeSeat, // 用户上麦
|
||||
leaveSeat, // 用户下麦
|
||||
muteMicrophone, // 静音麦克风
|
||||
unmuteMicrophone, // 取消静音麦克风
|
||||
kickUserOutOfSeat, // 将用户踢出座位
|
||||
moveUserToSeat, // 移动用户到指定座位
|
||||
lockSeat, // 锁定座位
|
||||
unlockSeat, // 解锁座位
|
||||
openRemoteCamera, // 开启远程摄像头
|
||||
closeRemoteCamera, // 关闭远程摄像头
|
||||
openRemoteMicrophone, // 开启远程麦克风
|
||||
closeRemoteMicrophone, // 关闭远程麦克风
|
||||
|
||||
addLiveSeatEventListener, // 添加座位事件监听
|
||||
removeLiveSeatEventListener, // 移除座位事件监听
|
||||
};
|
||||
}
|
||||
|
||||
export default useLiveSeatState;
|
||||
58
uni_modules/tuikit-atomic-x/state/LiveSummaryState.ts
Normal file
58
uni_modules/tuikit-atomic-x/state/LiveSummaryState.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @module LiveSummaryState
|
||||
* @module_description
|
||||
* 统计信息状态管理模块
|
||||
* 核心功能:统计和展示直播过程中的关键数据,包括观看人数、点赞数、礼物数等实时统计。
|
||||
* 技术特点:支持实时数据采集、数据聚合、统计分析等功能,提供完整的直播数据视图。
|
||||
* 业务价值:为直播平台提供数据分析能力,支持直播效果评估和优化改进。
|
||||
* 应用场景:直播数据展示、主播分析、流量统计、商业数据报表等数据分析场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
|
||||
/**
|
||||
* 直播间统计信息
|
||||
* @type {Ref<any>}
|
||||
* @memberof module:LiveSummaryState
|
||||
* @example
|
||||
* import { useLiveSummaryState } from '@/uni_modules/tuikit-atomic-x/state/LiveSummaryState';
|
||||
* const { summaryData } = useLiveSummaryState('your_live_id');
|
||||
*
|
||||
* // 监听统计数据变化
|
||||
* watch(summaryData, (newData) => {
|
||||
* if (newData) {
|
||||
* console.log('直播统计数据更新:', newData);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前统计数据
|
||||
* const data = summaryData.value;
|
||||
* if (data) {
|
||||
* console.log('当前直播统计数据:', data);
|
||||
* }
|
||||
*/
|
||||
const summaryData = ref<any>();
|
||||
|
||||
const onLiveSummaryStoreChanged = (eventName : string, res : string) : void => {
|
||||
try {
|
||||
if (eventName === "summaryData") {
|
||||
const data = JSON.parse(res);
|
||||
summaryData.value = data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLiveSummaryStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(liveID : string) : void {
|
||||
getRTCRoomEngineManager().on("liveSummaryStoreChanged", onLiveSummaryStoreChanged, liveID);
|
||||
}
|
||||
|
||||
export function useLiveSummaryState(liveID : string) {
|
||||
bindEvent(liveID);
|
||||
return {
|
||||
summaryData, // 直播间统计信息
|
||||
};
|
||||
}
|
||||
|
||||
export default useLiveSummaryState;
|
||||
146
uni_modules/tuikit-atomic-x/state/LoginState.ts
Normal file
146
uni_modules/tuikit-atomic-x/state/LoginState.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @module LoginState
|
||||
* @module_description
|
||||
* 用户身份认证与登录管理模块
|
||||
* 核心功能:负责用户身份验证、登录状态管理、用户信息维护等基础认证服务。
|
||||
* 技术特点:支持多种认证方式、会话管理、权限验证等高级功能,确保用户身份的安全和有效。
|
||||
* 业务价值:为直播平台提供基础的用户认证能力,是所有其他业务模块的前置条件。
|
||||
* 应用场景:用户登录、身份验证、会话管理、权限控制等基础认证场景。
|
||||
*/
|
||||
import { ref } from "vue";
|
||||
import { UserProfileParam, LoginOptions, LogoutOptions, SetSelfInfoOptions } from "@/uni_modules/tuikit-atomic-x";
|
||||
import { getRTCRoomEngineManager } from "./rtcRoomEngine";
|
||||
import { callUTSFunction, safeJsonParse } from "../utils/utsUtils";
|
||||
|
||||
/**
|
||||
* 当前登录用户信息
|
||||
* @type {Ref<UserProfileParam>}
|
||||
* @memberof module:LoginState
|
||||
* @example
|
||||
* import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState';
|
||||
* const { loginUserInfo } = useLoginState();
|
||||
*
|
||||
* // 监听用户信息变化
|
||||
* watch(loginUserInfo, (newUserInfo) => {
|
||||
* if (newUserInfo) {
|
||||
* console.log('用户信息更新:', newUserInfo);
|
||||
* console.log('用户ID:', newUserInfo.userID);
|
||||
* console.log('用户昵称:', newUserInfo.nickname);
|
||||
* console.log('用户头像:', newUserInfo.avatarURL);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // 获取当前用户信息
|
||||
* const currentUser = loginUserInfo.value;
|
||||
* if (currentUser) {
|
||||
* console.log('当前登录用户:', currentUser.nickname);
|
||||
* }
|
||||
*/
|
||||
const loginUserInfo = ref<UserProfileParam>();
|
||||
|
||||
/**
|
||||
* 当前登录状态
|
||||
* @type {Ref<string>}
|
||||
* @memberof module:LoginState
|
||||
* @example
|
||||
* import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState';
|
||||
* const { logout } = useLoginState();
|
||||
* logout({
|
||||
* onSuccess: () => console.log('登出成功'),
|
||||
* onError: (error) => console.error('登出失败:', error)
|
||||
* });
|
||||
*/
|
||||
const loginStatus = ref<string>();
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
* @param {LoginOptions} params - 登录参数
|
||||
* @returns {void}
|
||||
* @memberof module:LoginState
|
||||
* @example
|
||||
* import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState';
|
||||
* const { login } = useLoginState();
|
||||
* login({
|
||||
* sdkAppID: 1400000000,
|
||||
* userID: 'user123',
|
||||
* userSig: 'eJx1kF1PwzAMhv9KlG...',
|
||||
* onSuccess: () => console.log('登录成功'),
|
||||
* onError: (error) => console.error('登录失败:', error)
|
||||
* });
|
||||
*/
|
||||
function login(params: LoginOptions): void {
|
||||
callUTSFunction("login", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出方法
|
||||
* @param {LogoutOptions} [params] - 登出参数(可选)
|
||||
* @returns {void}
|
||||
* @memberof module:LoginState
|
||||
* @example
|
||||
* import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState';
|
||||
* const { logout } = useLoginState();
|
||||
* logout({
|
||||
* onSuccess: () => console.log('登出成功'),
|
||||
* onError: (error) => console.error('登出失败:', error)
|
||||
* });
|
||||
*/
|
||||
function logout(params?: LogoutOptions): void {
|
||||
callUTSFunction("logout", params || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户信息
|
||||
* @param {SetSelfInfoOptions} userInfo - 用户信息
|
||||
* @returns {void}
|
||||
* @memberof module:LoginState
|
||||
* @example
|
||||
* import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState';
|
||||
* const { setSelfInfo } = useLoginState();
|
||||
* setSelfInfo({
|
||||
* userID: 'user123',
|
||||
* nickname: '张三',
|
||||
* avatarURL: 'https://example.com/avatar.jpg',
|
||||
* onSuccess: () => console.log('用户信息设置成功'),
|
||||
* onError: (error) => console.error('用户信息设置失败:', error)
|
||||
* });
|
||||
*/
|
||||
function setSelfInfo(userInfo: SetSelfInfoOptions): void {
|
||||
callUTSFunction("setSelfInfo", userInfo);
|
||||
}
|
||||
|
||||
function getLoginUserInfo(): UserProfileParam | undefined {
|
||||
return loginUserInfo.value;
|
||||
}
|
||||
|
||||
const onLoginStoreChanged = (eventName: string, res: string): void => {
|
||||
try {
|
||||
if (eventName === "loginUserInfo") {
|
||||
const data = safeJsonParse<UserProfileParam>(res, {});
|
||||
loginUserInfo.value = data;
|
||||
} else if (eventName === "loginStatus") {
|
||||
loginStatus.value = safeJsonParse<string>(res, "");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("onLoginStoreChanged error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function bindEvent(): void {
|
||||
getRTCRoomEngineManager().on("loginStoreChanged", onLoginStoreChanged, '');
|
||||
}
|
||||
|
||||
export function useLoginState() {
|
||||
bindEvent();
|
||||
return {
|
||||
loginUserInfo, // 当前登录用户信息
|
||||
loginStatus, // 当前登录状态
|
||||
|
||||
login, // 登录方法
|
||||
logout, // 登出方法
|
||||
setSelfInfo, // 设置用户信息
|
||||
getLoginUserInfo, // 获取登录用户信息
|
||||
};
|
||||
}
|
||||
|
||||
export default useLoginState;
|
||||
11
uni_modules/tuikit-atomic-x/state/rtcRoomEngine.ts
Normal file
11
uni_modules/tuikit-atomic-x/state/rtcRoomEngine.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { RTCRoomEngineManager } from "@/uni_modules/tuikit-atomic-x";
|
||||
|
||||
let instance : RTCRoomEngineManager | null = null;
|
||||
|
||||
//TODO: 这个文件的命名待讨论,或者直接干掉这个类?
|
||||
export function getRTCRoomEngineManager() : RTCRoomEngineManager {
|
||||
if (!instance) {
|
||||
instance = new RTCRoomEngineManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
Reference in New Issue
Block a user