房间管理(Web)

最近更新时间:2026-05-20 17:34:30

我的收藏
本篇文档旨在指导开发者如何利用无 UI SDK 的 useRoomState 处理 Web 端房间的全生命周期。通过响应式状态管理,您可以灵活实现房间的创建、加入、信息同步及销毁逻辑,并精准捕获各类房间事件。
以下时序图展示了房间从创建到销毁的主要流程。




前提条件

用户已经通过 useLoginState 完成登录鉴权,请参考 接入概览
注意:
异步性: login 方法为异步执行。在单页应用中,建议通过监听 loginUserInfo.value?.userId 的变化来确保登录就绪,严禁在未确认登录状态时抢跑调用房间管理方法。
单例约束: useRoomState 采用单例设计,同一用户同一时刻仅支持存在于一个房间内。

实现房间管理

步骤1:导入 useRoomState

import { useRoomState } from 'tuikit-atomicx-vue3/room';

const {
createAndJoinRoom,
joinRoom,
updateRoomInfo,
leaveRoom,
endRoom,
currentRoom,
} = useRoomState();

步骤2:创建房间

请根据您的业务场景,选择适合的创建房间方式。
注意:
创建房间时指定的 roomId 建议由业务后台生成并下发,以确保同一场会议在您的业务系统中具备稳定且唯一的标识。

场景一:客户端发起快速会议

适用场景:用户在客户端点击“快速会议”,需要立即发起并进入一个房间,例如临时沟通、IM 会话内发起会议。
实现方式:调用 createAndJoinRoom 创建并进入房间。
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { createAndJoinRoom } = useRoomState();

await createAndJoinRoom({
roomId: 'YOUR_ROOM_ID', // 必填:建议由业务后台生成的唯一标识
options: {
roomName: '项目进度周会', // 选填:房间展示名称
},
});
如果您需要限制入会范围,也可以在快速会议场景下创建密码房间。
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { createAndJoinRoom } = useRoomState();

await createAndJoinRoom({
roomId: 'YOUR_ROOM_ID', // 必填:建议由业务后台生成的唯一标识
options: {
roomName: '项目进度周会', // 选填:房间展示名称
password: '123', // 选填:开启密码入会模式
},
});
说明:
创建者在调用 createAndJoinRoom 时会自动加入房间,无需额外输入密码。

场景二:客户端预约会议

适用场景:适用于需要在未来特定时间召开的会议(例如团队周会、线上培训等)。用户可在客户端提前设定会议标题、时间及受邀参会成员。
实现方式:由客户端生成或向业务后台申请一个唯一的房间号,并配合会议时间等参数调用 scheduleRoom 接口提交预定。预定成功后,会议信息将同步至参与者的会议列表中。更多客户端预订会议能力请参考 无 UI 集成 > 预订房间
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { scheduleRoom } = useRoomState();

const createSchedule = async () => {
try {
// roomId 限制:字符串类型,必传参数,建议由业务后台生成保证 roomId 唯一性。
const roomId = '123456';
// 注意:时间戳单位必须为 **秒** (Date.getTime() 获取的是毫秒,需除以 1000)
const startTime = Math.floor(new Date().getTime() / 1000) + 3600; // 1小时后开始
const duration = 1800; // 30分钟

const options = {
roomName: '产品需求评审会',
scheduleStartTime: startTime, // 单位:秒
scheduleEndTime: startTime + duration, // 单位:秒
scheduleAttendees: ['userA', 'userB'], // 邀请参会成员ID列表
password: '123', // 可选:设置入会密码
};

await scheduleRoom({ roomId, options });
} catch (error) {
console.error('预定失败', error);
}
};

场景三:服务端创建会议

适用场景:政务、医疗、大型企业 OA 等强管控场景。
实现方式:会议的创建动作完全由您的业务服务端发起,调用腾讯云的 服务端 REST API 创建房间
POST /v4/room_engine_http_srv/create_room
{
"roomId": "your-room-id",
"roomName": "会议名称",
"startTime": 1710000000,
"endTime": 1710003600,
"invitees": ["userId1", "userId2"]
}

步骤3:加入房间

请根据您是否确定房间已经存在,选择不同的加入方式。

场景一:确定房间已经存在

适用场景:
用户从房间列表进入会议。
用户通过会议邀请链接进入会议。
房间已经由发起人或服务端创建完成。
实现方式:直接调用 joinRoom
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { joinRoom } = useRoomState();

await joinRoom({
roomId: 'YOUR_ROOM_ID',
});
如果房间开启了密码保护,调用 joinRoom 时可能返回以下错误码:
TUIErrorCode.ERR_NEED_PASSWORD:表示该房间需要密码。建议由业务侧弹出密码输入框,用户输入后再次调用 joinRoom
TUIErrorCode.ERR_WRONG_PASSWORD:表示密码错误。建议提示用户重新输入密码,再次调用 joinRoom
在无 UI 接入场景下,密码输入弹窗和错误提示需由业务层自行实现。

场景二:只知道 roomId,但不确定房间是否已经存在

适用场景:双向对等发起的场景,例如在线问诊、视频面试、1v1 视频客服等,双方只知道同一个 roomId,但无法预先确定谁会先进入。
实现方式:直接调用 createAndJoinRoom
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { createAndJoinRoom } = useRoomState();

await createAndJoinRoom({
roomId: 'YOUR_ROOM_ID',
options: {
roomName: '业务沟通房间',
},
});
说明:
createAndJoinRoom 支持“房间不存在则创建,房间已存在则加入”的进房方式,适合无法预先判断房间状态的业务场景。

步骤4:更新房间信息

房主可以在进入房间后调用 updateRoomInfo 更新房间名称和密码。
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { updateRoomInfo } = useRoomState();

await updateRoomInfo({
roomId: 'YOUR_ROOM_ID',
options: {
roomName: '新的房间名称',
password: '234567',
},
});
说明:
房主必须已经在房间内才能调用 updateRoomInfo。如果房主已经离开房间,需要先重新加入房间。

步骤5:离开房间与解散房间

房间内的退出操作分为“离开房间”和“解散房间”两种,请根据业务目标选择合适的接口。

场景一:离开房间

适用场景:当前用户仅需退出房间,不影响其他成员继续留在房间内。
实现方式:调用 leaveRoom
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { currentRoom, leaveRoom } = useRoomState();

if (!currentRoom.value) {
return;
}

await leaveRoom();

场景二:解散房间

适用场景:房主需要结束当前会议,并使所有成员退出房间。
实现方式:调用 endRoom
import { useRoomState } from 'tuikit-atomicx-vue3/room';

const { currentRoom, endRoom } = useRoomState();

if (!currentRoom.value) {
return;
}

await endRoom();
说明:
leaveRoom 适用于“当前用户退出”,不会销毁房间。
endRoom 仅房主可调用,用于结束当前房间。
如果房主离开房间但未调用 endRoom,房间将继续存在,直到满足自动回收条件(连续 6 小时无用户)。
房主可以通过 transferOwner 将房主身份转移给其他用户。

步骤6:处理房间状态事件变更

在房间生命周期中,业务层通常需要处理房间被解散、用户被踢出等事件。建议在组件挂载时注册事件监听,在组件销毁时移除监听。

处理房间被解散事件

普通用户可通过监听 RoomEvent.onRoomEnded 处理房间被房主解散后的业务交互。
import { onMounted, onUnmounted } from 'vue';
import { useRoomState, RoomEvent } from 'tuikit-atomicx-vue3/room';
import { TUIMessageBox } from '@tencentcloud/uikit-base-component-vue3';

const { subscribeEvent, unsubscribeEvent } = useRoomState();

function onRoomEnded() {
TUIMessageBox.alert({
title: '通知',
content: '房主已解散房间',
});
}

onMounted(() => {
subscribeEvent(RoomEvent.onRoomEnded, onRoomEnded);
});

onUnmounted(() => {
unsubscribeEvent(RoomEvent.onRoomEnded, onRoomEnded);
});

处理用户被踢出房间事件

普通用户可通过监听 RoomParticipantEvent.onKickedFromRoom 处理用户被踢出房间后的业务交互。
import { onMounted, onUnmounted } from 'vue';
import {
useRoomParticipantState,
RoomParticipantEvent,
KickedOutOfRoomReason,
} from 'tuikit-atomicx-vue3/room';
import { TUIMessageBox } from '@tencentcloud/uikit-base-component-vue3';

const { subscribeEvent, unsubscribeEvent } = useRoomParticipantState();

function onKickedFromRoom({
reason,
}: {
reason: KickedOutOfRoomReason;
message: string;
}) {
let notice = '';

switch (reason) {
case KickedOutOfRoomReason.KickedByAdmin:
notice = '您已被房主移出房间';
break;
case KickedOutOfRoomReason.ReplacedByAnotherDevice:
notice = '您的账号已在其他设备登录';
break;
case KickedOutOfRoomReason.KickedByServer:
notice = '您已被服务器移出房间';
break;
case KickedOutOfRoomReason.ConnectionTimeout:
notice = '网络连接超时,正在退出房间';
break;
case KickedOutOfRoomReason.InvalidStatusOnReconnect:
notice = '房间已解散或您在离线期间已被移出';
break;
case KickedOutOfRoomReason.RoomLimitExceeded:
notice = '房间人数已达上限,无法加入';
break;
default:
notice = '您已被移出房间';
break;
}

TUIMessageBox.alert({
title: '通知',
content: notice,
});
}

onMounted(() => {
subscribeEvent(RoomParticipantEvent.onKickedFromRoom, onKickedFromRoom);
});

onUnmounted(() => {
unsubscribeEvent(RoomParticipantEvent.onKickedFromRoom, onKickedFromRoom);
});

场景最佳实践

下表总结了不同业务场景下的推荐接入方式。
业务场景
推荐做法
推荐接口/方式
临时沟通、即时会议
由发起人在客户端直接创建并进入房间,其他参会人拿到 roomId 后加入
发起人使用 createAndJoinRoom,参会人使用 joinRoom
团队周会、培训、定期例会
由客户端提前预约会议,会议开始前在会议列表或详情页展示,开始后再入会
创建阶段参考 预定房间,入会阶段使用 joinRoom
在线教育、医疗、政务、企业 OA 等由业务系统统一创建会议的场景
由业务系统提前分配 roomId,调用服务端接口创建房间,客户端在指定页面获取 roomId 调用 joinRoom 入会
由业务系统提前创建会议房间,客户端使用 joinRoom
在线问诊、视频面试、1v1 客服
双方使用同一个业务标识作为 roomId,任意一方进入时都可直接尝试进房
使用 createAndJoinRoom

错误码速查

在无 UI SDK 接入场景下,建议您通过 try/catch 统一处理创建房间和加入房间时的常见错误。
TUIErrorCode 可从 tuikit-atomicx-vue3 导入:
import { TUIErrorCode } from 'tuikit-atomicx-vue3';
错误码名称
错误码值
常见触发场景
建议处理方式
TUIErrorCode.ERR_NEED_PASSWORD
100018
进入密码房间但未传入密码
由业务侧弹出密码输入框,用户输入后再次调用 joinRoom
TUIErrorCode.ERR_WRONG_PASSWORD
100019
进入密码房间时传入的密码错误
提示用户密码错误,允许重新输入后再次调用 joinRoom
TUIErrorCode.ERR_ROOM_ID_NOT_EXIST
100004
调用 joinRoom 时房间不存在
提示房间不存在;若属于双向发起场景,建议直接改用 createAndJoinRoom
TUIErrorCode.ERR_ROOM_USER_FULL
100008
房间人数已达上限
提示房间人数已满,并引导用户稍后重试或联系房主
TUIErrorCode.ERR_ROOM_ID_OCCUPIED
100003
创建房间时使用的 roomId 已被占用
检查 roomId 生成策略;若业务允许“房间已存在则直接进入”,建议使用 createAndJoinRoom

常见问题

房间内已经没有用户但房间未被解散,房间是否会一直存在?

房间内连续 6 小时无用户进入时,后台将尝试回收房间。

房间内已经没有用户但房间未被解散,是否会产生费用消耗?

没有用户但是未被解散的房间仅占用套餐群组数,不产生分钟数消耗和额外费用消耗。

一个用户可以同时加入多个房间吗?

useRoomState 为单例接口,仅支持用户同时加入一个房间。

最多支持多少人同时加入房间?

房间内用户数量上限和您的套餐包相关,具体请查看 TUIRoomKit 套餐包说明