一、核心原理:定制化开发的运作逻辑
互动课堂的各端界面(Web、Electron、Web 内核的 iOS/Android),底层都是基于网页(Web)实现的。
定制化开发的核心逻辑是:
不修改 SDK 内核源码,通过注入自定义 JS/CSS 文件,借助 SDK 开放的全局对象 TCIC.SDK.instance,在课堂生命周期的对应节点,实现界面样式修改、业务逻辑扩展、功能权限管控,最终实现全端统一的自定义效果。
定制化原理
二、通过定制化能实现什么?
通过注入自定义的 JS 和 CSS,你可以修改所有端的界面并补充业务逻辑。常见场景如下:
| 业务方向 | 具体场景举例 |
| 界面与样式 | 文案替换:将页面上的“课堂”字样全部替换为“会议”等行业专有词。布局调整:修改摄像头/麦克风图标样式、调整弹窗按钮行为、自定义虚拟背景等。 |
| 功能与权限 | 屏蔽功能:隐藏头像区域、隐藏在线人数等无关业务。权限配置:针对不同角色(老师/学生)配置白板权限、设置下课倒计时提醒等。 |
| 数据与事件 | 事件监听:当特定事件发生时(如进入房间、开关麦克风),触发业务弹窗,或将状态上报给你的业务后台。 |
三、快速开始:本地开发与调试
无论你是使用模板还是从零开发,调试的核心步骤都是启动本地服务 > 拼接课堂 URL > 注入代码。
四、步骤1:准备本地 JS/CSS 文件
你可以选择以下两种方式之一来准备代码:
方式一:使用 Demo方式二:自己从零搭建我们提供了常用的自定义示例代码,开箱即用:git clone https://github.com/InteractiveClassroom/tcic-custom-demo.gitpnpm icd ./demos/{SOME_DEMO} # 选择一个你需要的 demo 目录pnpm dev # 默认会在 localhost:3000 启动服务如果你熟悉前端开发,可以直接在本地搭建一个静态服务器(假设运行在 8080 端口),并在根目录创建 test.js 和 test.css。注意:如果使用 Vue/React 开发,请自行创建 div 节点插入 DOM,不要直接挂载到课堂原有的 #app 节点上。
五、步骤2:在课堂中注入并调试
1. 进入 课堂演示登录页,依次单击创建课堂 > 立即进入。
2. 进入课堂后,复制浏览器地址栏中的 URL。
3. 在 URL 末尾拼接你的本地文件地址:
·拼接 JS:&debugjs=http://localhost:3000/custom.js
·拼接 CSS:&debugcss=http://localhost:3000/custom.css
·完整示例:https://class.qcloudclass.com/…&debugjs=http://localhost:3000/custom.js&debugcss=http://localhost:3000/custom.css
4. 敲击回车键重新加载页面。打开开发者工具(F12)的 Network 面板,如果看到你的本地 JS/CSS 文件被成功加载,说明环境准备完毕,可以开始写代码了。
六、步骤3:发布到生产环境
当你在本地(localhost)调试完毕,确认功能无误后,就可以发布上线了:
1. 在本地项目中运行打包命令(如 npm run build),生成最终的 JS 和 CSS 文件,并发布到你的生产环境,使外网能访问到。
2. 登录腾讯云控制台,进入自定义场景配置页面,详见 场景配置。
3. 配置你打包好的 JS 和 CSS URL,并生成一个“场景名称”。
4. 以后在进入课堂的时候,传入这个“场景名称”,该课堂就会自动加载你的定制化代码。
Web/H5安卓(Web 内核)iOS(Web 内核)Electron参考 Web 及 H5 快速接入 在拼接进入课堂的时候,带上参数 scene={场景名称},示例:https://${课堂域名}/latest/class.html?scene=${scene}&schoolid=${schoolid}&classid=${classid}&userid=${userid}&token=${token}参考文档 Web 内核(Android)快速接入在进入课堂时,传参 scene,示例:// 1. 构建配置对象TCICClassConfig initConfig = new TCICClassConfig.Builder() .schoolId(schoolId) // 应用 ID .classId(classId) // 课堂 ID .userId(userId) // 用户 ID .token(token) // 鉴权 Token .scene(scene) // 场景名称 .build();参考 Web 内核(iOS)快速接入 在进入课堂时,传参 scene,示例:TCICClassConfig *roomConfig = [[TCICClassConfig alloc] init];// 必填参数roomConfig.schoolId = 123456; // 学校/应用 IDroomConfig.userId = "test_user"; // 用户 IDroomConfig.token = "test_token"; // 鉴权 TokenroomConfig.classId = 654321; // 课堂 ID// 可选参数配置[roomConfig setValue:@"en" forKey:@"language"]; // 设置语言[roomConfig setValue:@"scene_name" forKey:@"scene"]; // 设置场景参考 Electron 快速接入 在进入课堂的时候,带上参数 scene={场景名称}。示例一:URL 唤起方式,需要拼接 URL。tcic://${课堂域名}/latest/class.html?scene=${scene}&classid=${classId}&userid=${userId}&token=${token}示例二:SDK 集成方式,在初始化时传入 scene。const TCIC = require('tcic-electron-sdk');TCIC.initialize({ // 核心鉴权参数 classId: '368507569', userId: '123456', token: 'yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…', // 务必动态获取 // 可选:自定义参数 (透传至 Web 端) customParams: { key: 'value', scene: 'scene_name', //自定义场景名称 }, …})
七、基本概念与 API
在你的自定义 JS 文件中,主要通过操作状态(State)、事件(Event)和功能开关(Feature)来实现业务逻辑。
八、1. 课堂生命周期与状态
课堂的加载是一个按顺序进行的过程。绝大多数自定义逻辑,都必须等课堂加载到特定状态后才能执行,否则会报错。
课堂生命周期
关键状态节点:
| 含义 | 状态名 | 类型 | 备注 |
| 学校信息已获取 | TCIC.TMainState.School_Info_Ready | Boolean | 自定义 js/css 地址是从获取学校信息接口中获取,js/css 加载完成后,School_Info_Ready 状态会变成 true。 |
| 课堂信息已获取 | TCIC.TMainState.Class_Info_Ready | Boolean | 获取到课堂信息后,会处理布局和文案相关内容。注意:除了 替换关键文案 等少量自定义需求需要在 Class_Info_Ready 前执行外,自定义代码的逻辑都应该在 Class_Info_Ready 状态之后再执行。 |
| 加入 TRTC 房间 | TCIC.TMainState.Joined_TRTC | Boolean | 在该状态改变后,用户才能使用 TRTC 房间相关功能,例如开启麦克风或者打开视频。 |
| 是否进行设备检测 | TCICUI.Constant.TStateDeviceDetect | Boolean | 需要连麦视频的用户完成设备检测再进入房间可以减少连麦异常的情况。 |
注意:说明:
注意:历史原因状态值有两类,挂载在 TCIC.TMainState 和 TCICUI.Constant 对象,具体参考 TCIC-SDK API 文档。
如何使用状态代码:
我们强烈推荐使用 promiseState 方法,它能确保当状态满足条件时,安全地执行你的代码。
// 设置状态值TCIC.SDK.instance.setState(name ,val)// 示例:promiseState可以确保当前状态满足条件的时候立即执行一次。TCIC.SDK.instance.promiseState(name,val)// 示例:获取状态值TCIC.SDK.instance.getState(name)// 示例:当“学校信息已获取”时,打印学校信息TCIC.SDK.instance .promiseState(TCIC.TMainState.School_Info_Ready, true) .then(() => { console.log("学校信息:", TCIC.SDK.instance.getSchoolInfo()); });// 示例:强制关闭进入课堂前的“设备检测”环节TCIC.SDK.instance.setState(TCICUI.Constant.TStateDeviceDetect, false);
九、2. 课堂事件监听
除了状态,课堂还会不断抛出各种事件(例如有人进房、收到消息等)。你可以通过 on 和 off 来监听或取消监听。
常用事件举例:
·TCIC.TMainEvent.Show_Msg_Box:弹窗出现时触发,使用示例可以参考 修改下课按钮行为。
·TCIC.TMainEvent.Member_Join:有人加入课堂时触发。
·TCIC.TIMEvent.Recv_Msg:收到聊天消息时触发。
事件可以在 TCIC.TMainEvent/TCIC.TIMEvent 里找到。
// 示例:监听事件TCIC.SDK.instance.on(eventname, callback);// 示例:取消监听事件TCIC.SDK.instance.off(eventname, callback);// 示例:监听收到消息事件TCIC.SDK.instance.on(TCIC.TIMEvent.Recv_Msg, (msg) => { console.log("收到新消息:", msg);});
注意:说明:
注意:在课堂控制台过滤 Tevent:: 可以观察到所有实时触发的事件行为。
十、3. 功能开关配置
针对不同的角色,你可能需要开启或关闭某些特定功能。这可以通过 setFeatureAvailable 来实现。此操作应在课堂信息加载完成 (Class_Status) 之后进行。
常用白板开关:
·WhiteBoardList:是否允许新增/切换白板(默认 true)。
·WhiteBoardPPT:是否允许课件翻页(默认 true)。
·WhiteBoardPPT.WheelPaging:是否支持用户使用鼠标滚轮对课件翻页(默认 false)。
// 示例:如果是学生,则限制其白板操作权限TCIC.SDK.instance .promiseState(TCIC.TMainState.Class_Status, TCIC.TClassStatus.Already_Start) .then(() => { if (TCIC.SDK.instance.isStudent()) { TCIC.SDK.instance.setFeatureAvailable("WhiteBoardList", true); // 允许添加白板 TCIC.SDK.instance.setFeatureAvailable("WhiteBoardPPT", false); // 禁止翻页 TCIC.SDK.instance.setFeatureAvailable("WhiteBoardPPT.WheelPaging", false); // 禁止滚轮翻页 } });
十一、更多参考资料
这篇仅介绍了最核心的定制化原理和常用 API。如需查阅完整的状态枚举、事件列表和方法详情,请参见 TCIC-SDK API 产品文档。