界面微调(Web)

最近更新时间:2026-03-27 14:45:03

我的收藏
当你需要根据业务诉求微调 RoomKit 的界面和交互时,可以通过以下三类能力完成:
添加自定义按钮,例如录制、答题器、白板入口、实时数据面板。
隐藏或恢复 SDK 内置按钮,裁剪默认界面。
在用户点击内置按钮后、底层操作执行前插入权限校验或二次确认。


前置条件

安装包@tencentcloud/roomkit-web-vue3
最低版本>=5.4.3
框架依赖:Vue 3+

能力概览

conference.setWidgetVisible()裁剪默认界面。只控制内置按钮是否显示,不限制底层功能是否可被代码调用。
conference.registerWidget()增加业务入口。在工具栏新增自定义按钮,不接管内置按钮。
conference.onWill()点击前做校验。只拦截内置 UI 按钮点击,不拦截主动调用的底层接口。
需求
使用 API
说明
增加业务入口
conference.registerWidget()
在工具栏中新增一个自定义按钮。
裁剪默认界面
conference.setWidgetVisible()
控制内置按钮是否显示。
点击前做校验
conference.onWill()
拦截内置按钮的点击操作。

快速开始

下面示例演示一个完整的界面微调场景:
隐藏邀请按钮。
增加一个答题器按钮。
点击开启摄像头前弹出确认框。
分别对应 setWidgetVisible()registerWidget()onWill() 三类能力。
注意:
sdkAppIduserSig 获取方式请参阅 用户鉴权
import {
conference,
BuiltinWidget,
InterceptorAction,
RoomEvent,
} from '@tencentcloud/roomkit-web-vue3';
import QuizPanel from './QuizPanel.vue';

async function startMeeting() {
await conference.login({
sdkAppId: 12345678,
userId: 'your-user-id',
userSig: 'your-user-sig',
});

// 建议在 start() / join() 前完成所有界面微调,避免按钮闪烁或漏拦截
conference.setWidgetVisible({
[BuiltinWidget.InviteWidget]: false,
});

const cleanups: Array<() => void> = [];

cleanups.push(
conference.registerWidget({
id: 'quiz',
zone: 'bottom-right',
icon: '📝',
label: '答题器',
panel: {
title: '答题器',
component: QuizPanel,
},
}),
);

cleanups.push(
conference.onWill(InterceptorAction.OpenCamera, async (action, proceed, abort) => {
if (window.confirm('确认开启摄像头?')) {
proceed();
} else {
abort();
}
}),
);

const cleanup = () => {
cleanups.forEach(fn => fn());
cleanups.length = 0;
conference.off(RoomEvent.ROOM_LEAVE, cleanup);
conference.off(RoomEvent.ROOM_DISMISS, cleanup);
};

// 两个事件都要监听:
// - ROOM_LEAVE:当前用户主动离开
// - ROOM_DISMISS:主持人解散房间(参会者走此事件)
conference.on(RoomEvent.ROOM_LEAVE, cleanup);
conference.on(RoomEvent.ROOM_DISMISS, cleanup);

const roomId = Date.now().toString();
await conference.start({ roomId });
}

显示/隐藏按钮

默认情况下,所有内置 Widget 在未调用 setWidgetVisible 时,均为显示状态。只需要对需要隐藏的按钮进行配置即可。Webinar 模式下由 RoomKit 根据房间类型和角色自动控制的 Widget 除外。


场景:隐藏内置按钮

import { conference, BuiltinWidget } from '@tencentcloud/roomkit-web-vue3';

conference.setWidgetVisible({
[BuiltinWidget.InviteWidget]: false,
[BuiltinWidget.RoomChatWidget]: false,
});

注意事项

建议在 conference.login() 完成之后、conference.join() / conference.start() 之前调用,避免按钮闪烁。
setWidgetVisible() 只控制按钮是否显示,不会锁定功能本身,如果你的业务代码直接调用 SDK 底层接口,对应功能仍然会执行。
setWidgetVisible() 没有注销函数;如果不同房间有不同显隐策略,请在下一次进房前显式重置。

添加自定义按钮

调用 registerWidget 会返回一个注销函数,调用后可立即从工具栏移除该按钮。


场景一:状态切换按钮(支持响应式)

iconlabel 支持函数形式,函数内部的响应式变量变化时按钮状态会自动更新:
import { ref } from 'vue';
import { conference } from '@tencentcloud/roomkit-web-vue3';

const isRecording = ref(false);

conference.registerWidget({
id: 'recorder',
zone: 'bottom-center',
icon: () => isRecording.value ? '⏹' : '⏺',
label: () => isRecording.value ? '停止录制' : '开始录制',
onClick: async () => {
try {
if (isRecording.value) {
await stopRecording();
} else {
await startRecording();
}
isRecording.value = !isRecording.value;
} catch (e) {
console.error('录制操作失败:', e);
}
},
});

场景二:点击后弹出侧边面板

配置 panel 后,点击按钮会自动展开或收起侧边面板(与“聊天”“成员”等内置面板互斥,同时只能展开一个)。
import { conference } from '@tencentcloud/roomkit-web-vue3';
import QuizPanel from './QuizPanel.vue';

conference.registerWidget({
id: 'quiz',
zone: 'bottom-right',
icon: '📝',
label: '随堂测试',
panel: {
title: '随堂测试',
component: QuizPanel,
props: { courseId: 'xxx' },
},
});

场景三:使用自定义组件

如果内置的图标+文字样式不能满足需求,可以使用传入 component 完全自定义触发器。
import { conference } from '@tencentcloud/roomkit-web-vue3';
import MyCustomTrigger from './MyCustomTrigger.vue';
import MyPanel from './MyPanel.vue';

conference.registerWidget({
id: 'custom-trigger',
zone: 'bottom-right',
component: MyCustomTrigger,
panel: {
title: '数据面板',
component: MyPanel,
},
});
MyCustomTrigger.vue 可通过 togglePanel 控制面板展开和收起:
<script setup lang="ts">
defineProps<{ togglePanel?: () => void }>();
</script>

<template>
<button @click="togglePanel?.()">打开面板</button>
</template>

拦截内置按钮操作

适合在用户点击 SDK 内置按钮时,在底层操作真正执行之前插入你的业务逻辑,例如:
点击摄像头按钮前弹窗确认。
点击屏幕共享按钮前请求服务端校验权限。
点击麦克风按钮前显示自定义提示。


场景一:二次确认

import { conference, InterceptorAction } from '@tencentcloud/roomkit-web-vue3';

conference.onWill(InterceptorAction.OpenCamera, async (action, proceed, abort) => {
if (window.confirm('确认开启摄像头?')) {
proceed();
} else {
abort();
}
});

场景二:异步权限校验

import { conference, InterceptorAction } from '@tencentcloud/roomkit-web-vue3';

conference.onWill(InterceptorAction.StartScreenShare, async (action, proceed, abort) => {
try {
const hasPermission = await checkScreenSharePermission();
if (hasPermission) {
proceed();
} else {
alert('当前会议不允许屏幕共享');
abort();
}
} catch (e) {
console.error('权限校验异常:', e);
abort();
}
});

注意事项

onWill proceed() / abort() 必须二选一调用:漏掉会导致操作链静默终止。
建议在 start() / join() 前注册:这样不会遗漏用户进房瞬间的操作。
生命周期管理:务必同时监听 RoomEvent.ROOM_LEAVERoomEvent.ROOM_DISMISS 并调用注销函数;如果事件监听本身支持解绑,也应一并清理。
隐藏 UI 不等于拦截操作:onWill() 只拦截内置按钮点击路径,不能拦截底层接口调用。

常见问题

按钮注册了但不显示?

最常见原因是没有传 zone,或传入的 zone 与当前设备类型不匹配。PC 和 H5 可分别指定不同区域,例如:
zone: { pc: 'bottom-center', h5: 'top-right' }

多次进出会议后,自定义按钮或拦截器重复生效?

通常是离会时没有调用注销函数。请统一收集 registerWidget()onWill() 返回的注销函数,并在 RoomEvent.ROOM_LEAVERoomEvent.ROOM_DISMISS 中同时清理。

隐藏了按钮,为什么对应功能还能被触发?

这是预期行为。setWidgetVisible() 只负责控制 UI,不限制功能本身。如果你的业务代码直接调用 SDK 底层接口,功能仍然会执行。如果还需要在点击前做权限判断或确认,请使用 onWill()

setWidgetVisible() 可以在会中动态调用吗?

可以,调用后按钮显示状态会立即更新。如果你的应用会复用同一个 conference 实例,请注意在下次进房前按需重置。

点击按钮后功能一直没有响应?

通常是某个 handler 分支没有调用 proceed()abort(),导致操作链静默终止。请检查所有 if / else / catch 分支。

onWill() 能拦截我自己代码里调用的底层接口吗?

不能。onWill() 只拦截 SDK 内置 UI 按钮的点击路径;如果你在业务代码里直接调用底层接口,需要自行补充权限控制。

自定义触发器如何控制面板展开或收起?

配置了 panel 后,SDK 会自动向自定义触发器注入 togglePanel 函数。在组件中通过 defineProps<{ togglePanel?: () => void }>() 接收后,调用 togglePanel() 即可。

附录:类型定义

以下仅列出接入界面微调时最常用的核心类型,便于快速查阅。完整类型定义请参考 RoomKit 源码 type.ts