即时通信 IM 界面微调(Web)

当你需要根据业务诉求微调 RoomKit 的界面和交互时,可以通过以下三类能力完成。

相关产品
即时通信 IM 产品页,含版本规格、价格与购买入口。

·添加自定义按钮,例如录制、答题器、白板入口、实时数据面板。

·隐藏或恢复 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() 三类能力。

注意:sdkAppId 和 userSig 获取方式请参阅 用户鉴权。

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 会返回一个注销函数,调用后可立即从工具栏移除该按钮。

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

icon 和 label 支持函数形式,函数内部的响应式变量变化时按钮状态会自动更新:

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_LEAVE 和 RoomEvent.ROOM_DISMISS 并调用注销函数;如果事件监听本身支持解绑,也应一并清理。

·隐藏 UI 不等于拦截操作:onWill() 只拦截内置按钮点击路径,不能拦截底层接口调用。

十六、按钮注册了但不显示?

最常见原因是没有传 zone,或传入的 zone 与当前设备类型不匹配。PC 和 H5 可分别指定不同区域,例如:

zone: { pc: 'bottom-center', h5: 'top-right' }

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

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

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

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

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

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

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

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

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

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

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

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

23、附录:类型定义

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

赞 (0)
上一篇 4天前
下一篇 4天前