目录
关于腾讯 IM SDK Demo
范例运行环境
设计思路
服务端生成地址
IM 服务端接收
IM 客户端程序
小结
关于腾讯 IM SDK Demo
腾讯云即时通信 IM SDK 提供了单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕等功能,并提供完备的 App 接入及管理接口。目前的下载链接请参照如下:
https://cloud.tencent.com/document/product/269/36887
我们下载的是 Windows SDK Web 版本的源码,其结构如下:
下载后感觉目录里的文件有些随意,因此围绕打包编译后的目录 dist 展开研究,运行 index.html 似乎能够出来一些效果,但实际的使用中肯定与自己的需求有出入,由于本人比较懒,仅通过跟踪终端显示呈现效果,直接暴力修改混淆代码,主要解决如下一些问题:
1、结合已有系统,通过令牌机制验证对首页登录的访问
2、成功访问登录页后生成访问用户的 UserSig ,UserSig 是用户登录即时通信 IM 的密码,其本质是对 UserID 等信息加密后得到的密文,如何生成 UserSig 请参照我的文章《C# 生成腾讯云 IM 之 TLSSigAPIv2 UserSig》
3、修改 Toast.js 的信息提示程序
4、根据判断手机微信和PC不同终端进入不同的运行环境样式
5、重写左侧分页提示消息(如我的消息、我的通讯录)
6、重写获取好友列表
7、重写左侧操作面板样式
8、重写了更新个人资料的昵称和头像功能
9、增加获取成员信息的功能
10、增加了禁言用户和解禁用户的功能
11、重写了初始化左侧好友列表、消息状态及显示的功能
12、修改了视频通话只能显示帐户名,改为可以显示昵称的功能
13、增加了视频通话云端混录的功能
14、增加了群组管理员禁言用户及获取禁言用户列表的功能
15、增加对左侧控制面板的显示配置
16、增加聊天面板的选项配置
范例运行环境
操作系统: Windows Server 2019 DataCenter
.net版本: .netFramework4.0 或以上
开发工具:VS2019 C#
设计思路
服务端生成地址
服务端设计一个登录页面用于如客服登录或普通登录。(也可以集成在应用中直接使用Session用户帐户登录),通过建立 IM 备份帐户表,检验登录 ,表大致设计如下:
序号 | 字段名 | 基础类型 | 说明 |
---|---|---|---|
1 | AppUID | nvarchar | 应用系统可能集成的用户帐户 |
2 | Account | nvarchar | 腾讯IM账户 |
3 | APWD | nvarchar | 应用系统集成的加密密码 |
4 | avatarUrl | nvarchar | 应用系统集成的头像地址 |
5 | nickName | nvarchar | 应用系统集成的昵称 |
6 | sex | nvarchar | 应用系统集成的性别 |
7 | AppClass | nvarchar | App平台名称 |
8 | AppName | nvarchar | 应用分类名称 |
9 | AppSubName | nvarchar | 应用二类分类名称 |
10 | AppIDN | nvarchar | 账户类型(如客服、考生、个人、企业等等) |
登录通过后根据用户生成 IM 用链接,地址为 /webim/dist/index.aspx,并传递相关参数值,见下表:
序号 | 参数 | 类型 | 说明 |
---|---|---|---|
1 | at | string | 传递的即时令牌值,接收端页面检验成功后即失效,用于页面安全访问 |
2 | scene | string | 场景配置参数。配置参数形式如下:{0}_{1}_{2}_{3} {0}:表示登录帐号 {1}:表示对方帐号(比如添加好友,这里可以默认为空) {2}:左侧控制面板配置,用6个数字连接,依次表示为显示控制列表、会话、群组、好友、黑名单、默认进入类型的对应四个图标(1234),除最后一个数字为1到4的值外,其它均为1和0,1代表显示,0代表隐藏 如110102,代表显示控制列表,显示会话,隐藏群组,显示好友、隐藏黑名单、进入第二个图标 {3}:聊天面板配置,用4个数字连接,依次表示发送图片、视频、文件、视频通话。 如1110,则表示关闭视频通话功能,其它图标都显示 |
综上所述,生成的拼接地址如下示例:
/webim/dist/index.aspx?at=令牌值&scene=user1_user2_110102_1110
IM 服务端接收
IM 服务端接收,只要实现令牌值的合法校验,即是否可以访问本页,成功后进行客户端用的参数赋值,并生成 UserSig,示例代码如下:
<%@ Page Language="C#" ResponseEncoding="utf-8" ValidateRequest="false" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.UI" %>
<%@ Import Namespace="System.Web.UI.WebControls" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Web.Services"%>
<%@ Import Namespace="System.Web.Script.Services"%>
<script language="C#" runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == true)
{
return;
}
Security.CraneOfficeCloud cc = new Security.CraneOfficeCloud();
ViewState["access_token"] = cc.getToken("");
ViewState["apiurl"] = System.Configuration.ConfigurationManager.AppSettings["apiurl"];
ViewState["userId"] = "";
ViewState["reomteUserId"] = "";
ViewState["cfg_showlist"] = "0";
ViewState["cfg_clist"] = "0";
ViewState["cfg_glist"] = "0";
ViewState["cfg_flist"] = "0";
ViewState["cfg_blist"] = "0";
ViewState["cfg_dlist"] = "1";
ViewState["cfg_spic"] = "0";
ViewState["cfg_svideo"] = "0";
ViewState["cfg_sfile"] = "0";
ViewState["cfg_videocall"] = "0";
ViewState["userSig"] ="";
string _at = (Request.QueryString["at"] == null ? "" : Request.QueryString["at"].ToString());
bool validresult = cc.validImToken(_at);
if (validresult == false)
{
Response.Redirect("end.aspx");
return;
}
string reqPara = sec.CoDecode(Request.QueryString["scene"].ToString(), "michaeln");
string[] paras = reqPara.Split('_');
ViewState["userId"] = paras[0];
ViewState["reomteUserId"] = paras[1];
string cfg = paras[2];
ViewState["cfg_showlist"] = cfg.Substring(0, 1);
ViewState["cfg_clist"] = cfg.Substring(1, 1);
ViewState["cfg_glist"] = cfg.Substring(2, 1);
ViewState["cfg_flist"] = cfg.Substring(3, 1);
ViewState["cfg_blist"] = cfg.Substring(4, 1);
ViewState["cfg_dlist"] = cfg.Substring(5, 1);
string cfg2 = paras[3];
ViewState["cfg_spic"] = cfg2.Substring(0, 1);
ViewState["cfg_svideo"] = cfg2.Substring(1, 1);
ViewState["cfg_sfile"] = cfg2.Substring(2, 1);
ViewState["cfg_videocall"] = cfg2.Substring(3, 1);
TLSSigAPIv2 sig = new TLSSigAPIv2(1400,"6b7ec2a8fd");
string _sig = sig.GenSig(ViewState["userId"].ToString());
ViewState["userSig"] = _sig;
}
</script>
IM 客户端程序
客户端程序主要用于接收服务端生成的参数,并通过 JS 外围控制与改变 IM SDK 的核心JS,客户端的示例代码如下:
<html>
<head>
<meta charset="utf-8"/><meta name="renderer" content="webkit"/><meta name="force-rendering" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<title>craneoffice TIM</title>
<style type="text/css">
.fbbtn
{
cursor:pointer;
background-color:White;
color:Gray;
width:100px;
-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
border-style:solid;
border-width:1px;
}
.fbbtn2
{
cursor:pointer;
background-color:White;
width:100px;
color:Gray;
-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
border-style:solid;
border-width:1px;
}
.fblist
{
width:120px;
font-size:9pt;
font-family:微软雅黑;
}
.rfbtn
{
width:35px;
font-size:9pt;
font-family:微软雅黑;
}
.friend-list-container
{
margin-top:80px;
margin-left:10px;
}
.friend-item-container
{
cursor:pointer;
margin-top:10px;
}
.friend-name
{
margin-top:10px;
margin-left:0px;
color:White;
}
</style>
<script language="javascript" type="text/javascript">
var app_apiurl = '<%=ViewState["apiurl"].ToString()%>';
var app_at = '<%=ViewState["access_token"].ToString()%>';
var app_userId = '<%=ViewState["userId"].ToString()%>';
var app_remote_userId = '<%=ViewState["reomteUserId"].ToString()%>';
var app_showlist = '<%=ViewState["cfg_showlist"].ToString()%>';
var app_clist = '<%=ViewState["cfg_clist"].ToString()%>';
var app_glist = '<%=ViewState["cfg_glist"].ToString()%>';
var app_flist = '<%=ViewState["cfg_flist"].ToString()%>';
var app_blist = '<%=ViewState["cfg_blist"].ToString()%>';
var app_dlist = '<%=ViewState["cfg_dlist"].ToString()%>';
var app_sig = '<%=ViewState["userSig"].ToString()%>';
var app_spic = '<%=ViewState["cfg_spic"].ToString()%>';
var app_svideo = '<%=ViewState["cfg_svideo"].ToString()%>';
var app_sfile = '<%=ViewState["cfg_sfile"].ToString()%>';
var app_videocall = '<%=ViewState["cfg_videocall"].ToString()%>';
var app_roomid = '';
var app_groupid = '';
var app_groupMsgUserId = '';
var app_groupMsgUserRole = '';
var app_frameId = window.frameElement && window.frameElement.id || '';
var app_e = null;
var app_nickname = "";
var app_faceurl = "";
if (window.parent != null) {
app_nickname=(window.parent.document.getElementById('imnickname').value);
app_faceurl=(window.parent.document.getElementById('imfaceurl').value);
}
</script>
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link href="css/chunk-vendors.c7922a7e.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="stylesheet" />
<link href="css/app.16310f51.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="Stylesheet" />
<link rel="stylesheet" href="css/toastify.min.css" />
</head>
<body>
<div id="app"></div>
<script src="js/toastify.js"></script>
<script src="./debug/GenerateTestUserSig.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="./debug/lib-generate-test-usersig.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/chunk-vendors.f90981cb.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/app.430352d1.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/jquery-3.2.1.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/utils.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<asp:Label ID="inittip" runat="server" Width="300px" Height="70px" Text="<br>正在配置请稍候..." style="text-align:center; display:none;position:absolute;left:100px;top:100px;-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.9);box-shadow:0 5px 10px 0 rgba(0,0,0,.9)" ForeColor="white" ></asp:Label>
<asp:Label ID="exTitle" runat="server" Text="" style="position:absolute;left:100px;top:20px;" ForeColor="#a5b5c1" ></asp:Label>
<input type="button" ID="rfbtn" runat="server" style="display:none" onclick="getGroupShuttedList()" value="刷新" class="rfbtn" />
<select id="shlist" class="fblist" onchange="muteRefUser(this.value)" style="display:none"></select>
<input type="button" ID="Button1" runat="server" style="display:none" onclick="changeArea(1)" value="刷新" class="rfbtn" />
<input type="button" ID="Button2" runat="server" style="display:none" onclick="changeArea(2)" value="刷新" class="rfbtn" />
</body>
</html>
<script language="javascript" type="text/javascript">
var app_groupmemberlist=null;
function is_weixin(){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
return true;
} else {
return false;
}
}
var vtitle='';
if(is_weixin()==true){
vtitle='IM 微信版';
document.getElementById('exTitle').style.display=vtitle;
}else{
vtitle='IM PC版';
document.getElementById('exTitle').style.display=vtitle;
}
Toast.info('正在配置启动 CO '+vtitle+',请稍候...');
function getmemberlist(){
var promise = tim.getGroupMemberList({ groupID: app_groupid, count: 30, offset:0 }); // 从0开始拉取30个群成员
promise.then(function(imResponse) {
alert(JSON.stringify(imResponse.data.memberList)); // 群成员列表
}).catch(function(imError) {
alert(imError);
});
}
async function test() {
await sleep(10000);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function setTitleEx(etype){
var title='';
if(etype==1){
title='我的消息';
}else if(etype==2){
title='我的通讯录';
}
document.getElementById('exTitle').innerHTML=title;
}
app_gfl=new Array();
function gfl(){
var promise =tim.getFriendList();
promise.then(function(imResponse) {
for(var i=0;i<imResponse.data.length;i++){
app_gfl.push(imResponse.data[i]);
}
}).catch(function(imError) {
Toast.error(imError);
});
}
function handleFriendClickEx(e){
e.querySelector('.friend-name').click();
}
function changeArea(paneltype){
var ol=30;
if(is_weixin()==true){
document.getElementById('exTitle').style.display='none';
}
if(paneltype==1){
if(is_weixin()==true){
document.querySelector(".bar-right").style.display = 'none';
document.querySelector(".current-conversation-wrapper").style.display='';
document.querySelector(".current-conversation-wrapper").style.width = (window.frameElement.offsetWidth-ol)+'px';
document.querySelector(".current-conversation-wrapper").style.position = 'absolute';
document.querySelector(".current-conversation-wrapper").style.left = ol+'px';
}
}else if(paneltype==2){
document.getElementById('exTitle').style.display='';
if(is_weixin()==true){
document.querySelector(".current-conversation-wrapper").style.display='none';
document.querySelector(".bar-right").style.display = '';
document.querySelector(".bar-right").style.position = 'absolute';
document.querySelector(".bar-right").style.left = ol+'px';
document.querySelector(".bar-right").style.width = (window.frameElement.offsetWidth-ol)+'px';
}
}
}
function updateProfile(){
if(app_nickname==""||app_faceurl==""){
return;
}
let promise = tim.updateMyProfile({
nick: app_nickname,
avatar: app_faceurl
});
promise.then(function(imResponse) {
}).catch(function(imError) {
alert('updateMyProfile error:'+ imError); // 更新资料失败的相关信息
});
}
function getNick(userid){
for(var i=0;i<app_gfl.length;i++){
if(app_gfl[i].profile.userID==userid){
return app_gfl[i].profile.nick;
}
}
return userid;
}
function getNick2(userid){
let promise = tim.getUserProfile({
userIDList: [userid] // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']
});
promise.then(function(imResponse) {
app_e=imResponse.data[0].nick;
if(imResponse.data[0].nick!=undefined){
return imResponse.data[0].nick;
}
}).catch(function(imError) {
return userid; // 获取其他用户资料失败的相关信息
});
var e=app_e;
alert(e.$store);
e.$store.dispatch("checkoutConversation","CC20210506102216154");
}
function getmemberinfo(){
Toast.info('信息提取中,如某些选项未显示请重新点击再试...');
if(app_groupMsgUserId==app_userId){
app_groupMsgUserRole='';
Toast.notify('提取用户信息完成');
return;
}
var promise = tim.getGroupMemberProfile({
groupID: app_groupid,
userIDList: [app_userId]
});
promise.then(function(imResponse) {
if(imResponse.data.memberList.length>0){
var ml=imResponse.data.memberList[0];
app_groupMsgUserRole=ml.role;
Toast.notify('提取用户信息完成。');
}
}).catch(function(imError) {
Toast.error(imError);
});
}
function reposx(x){
if(x+230+100>$(window).width()){
x=$(window).width()-230-100;
}
return x;
}
function reposy(y){
if(y+271+70>$(window).height()){
y=$(window).height()-271-70;
}
return y;
}
function muteRefUser(userid){
if(userid=='') return;
if(confirm('是否解禁用户'+userid)==false){
return;
}
app_groupMsgUserId=userid;
muteUser(0);
}
function muteUser(seconds) {
var promise = tim.setGroupMemberMuteTime({
groupID: app_groupid,
userID: app_groupMsgUserId,
muteTime: seconds // 禁言10分钟;设为0,则表示取消禁言
});
promise.then(function(imResponse) {
var tip=(seconds==0?"已取消禁言该用户":'用户'+app_groupMsgUserId+'已被禁言'+timetip(seconds));
Toast.notify(tip);
rfbtn.click();
}).catch(function(imError) {
Toast.error(imError);
});
}
function timetip(off) {
var x=parseInt(off/3600,10);
var htip=x==0?"":x+'小时';
off=off-x*3600;
var z = parseInt(off / 60, 10);
var y = off % 60;
var mtip='';
var stip='';
if(z==0&&y!=0){
stip=y+'秒';
} else if (z != 0 && y == 0) {
mtip = z +'分钟';
} else if (z != 0 && y != 0) {
mtip = z + '分';
stip = y + '秒';
}
return htip+mtip+stip;
}
function onl() {
if (app_showlist == 1) {
}
window.setTimeout(async function () {
document.getElementById('inittip').style.display = 'none';
var f = false;
var fi = 0;
for (var i = 0; i < document.getElementsByTagName('div').length; i++) {
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'side-bar-wrapper') {
// document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth+'px';
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-right') {
// document.getElementsByTagName('div')[i].style.display = 'none';
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-left') {
// document.getElementsByTagName('div')[i].style.display = 'none';
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'current-conversation-wrapper' && app_showlist == 0) {
if (app_frameId != "") {
document.getElementsByTagName('div')[i].style.width = (window.frameElement.offsetWidth - 44) + 'px';
document.getElementsByTagName('div')[i].style.height = '99vh';
document.getElementsByTagName('div')[i].style.left = '31px';
document.getElementsByTagName('div')[i].style.top = '0px';
document.getElementsByTagName('div')[i].style.position = 'absolute';
}
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'content') {
// alert(document.getElementsByTagName('div')[i].innerHTML);
// document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth + 'px';
// document.getElementsByTagName('div')[i].style.height = window.frameElement.offsetHeight + 'px';
// document.getElementsByTagName('div')[i].style.position = 'absolute';
}
// group - list
if (document.getElementsByTagName('div')[i].getAttribute('id') == 'group-list' && app_dlist == 2) {
document.getElementsByTagName('div')[i].click();
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'header-bar') {
if (document.getElementsByTagName('div')[i].innerHTML.indexOf('创建群组') != -1) {
document.getElementsByTagName('div')[i].innerHTML = '';
shlist.style.display='none';
rfbtn.style.display='none';
document.getElementsByTagName('div')[i].appendChild(shlist);
document.getElementsByTagName('div')[i].appendChild(rfbtn);
}
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' && app_dlist == 1) {
f = true;
fi = i;
// break;
}
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'group-item' && app_dlist == 2) {
f = true;
fi = i;
// break;
}
}
if (f == true) {
document.getElementsByTagName('div')[fi].click();
if(app_dlist==2){
await sleep(1500);
getmemberinfo();
await sleep(1500);
if(app_groupMsgUserRole=='Owner'||app_groupMsgUserRole=='Admin'){
rfbtn.click();
shlist.style.display='';
rfbtn.style.display='';
}
}
}
updateProfile();
document.getElementById('friend-list').click();
await sleep(1000);
gfl();
document.getElementById('conversation-list').click();
}, 3000);
}
function iconClick() {
setTitleEx(1);
window.setTimeout(async function () {
var f = false;
var fi = 0;
for (var i = 0; i < document.getElementsByTagName('div').length; i++) {
if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' ) {
f = true;
fi = i;
break;
}
}
if (f == true&&is_weixin()==false){
document.getElementsByTagName('div')[fi].click();
}
window.parent.layer.closeAll();
}, 1000);
}
window.onload = function () {
if (document.getElementsByTagName('button').length == 1) {
document.getElementsByTagName('button')[0].click();
}
}
function setonline(_user1, _user2) {
$.ajax({
type: "Post",
url: app_apiurl,
contentType: "application/x-www-form-urlencoded;charset=utf-8",
data: {
gettype: 'getRoomIdForMixRecord',
at: app_at,
user1: encodeURIComponent(_user1),
user2: encodeURIComponent(_user2)
},
dataType: "json",
success: function (res) {
//JSON.stringify
alert(res.roomid);
if (res.roomid != "") {
app_roomid = res.roomid;
requestMixRecord("request", "turing", app_roomid, "ARP120102197701243273", "ARI20200401");
}
},
error: function (err) {
alert(JSON.stringify(err));
}
});
}
function requestMixRecord(_mixtype, _companyName, _roomid, _userid1, _userid2) {
$.ajax({
type: "Post",
url: app_apiurl,
contentType: "application/x-www-form-urlencoded;charset=utf-8",
data: {
gettype: 'MixRecord',
at: app_at,
mixtype: encodeURIComponent(_mixtype),
companyName: encodeURIComponent(_companyName),
roomid: encodeURIComponent(_roomid),
userid1: encodeURIComponent(_userid1),
userid2: encodeURIComponent(_userid2)
},
dataType: "json",
success: function (res) {
//返回的数据用data.d获取内容
if (res.code == '0') {
// Toast.notify(_mixtype + ' record ok');
} else {
// Toast.notify(' record '+res.code);
}
// alert(JSON.stringify(res));
},
error: function (err) {
Toast.error(err);
}
});
} //mixrecord
function delGroupMsg() {
$.ajax({
type: "Post",
url: app_apiurl,
contentType: "application/x-www-form-urlencoded;charset=utf-8",
data: {
gettype: 'im_deleteGroupMsg',
at: app_at,
groupid: encodeURIComponent(app_groupid),
account: encodeURIComponent(app_groupMsgUserId)
},
dataType: "json",
success: function (res) {
//返回的数据用data.d获取内容
// alert(JSON.stringify(res));
if(res.ErrorCode=='0'){
Toast.notify('删除消息成功,缓存的消息可能还会显示。');
}else{
Toast.error('删除消息失败。');
}
},
error: function (err) {
Toast.error(JSON.stringify(err));
}
});
} //mixrecord
function getGroupShuttedList() {
$.ajax({
type: "Post",
url: app_apiurl,
contentType: "application/x-www-form-urlencoded;charset=utf-8",
data: {
gettype: 'im_getGroupShuttedList',
at: app_at,
groupid: encodeURIComponent(app_groupid)
},
dataType: "json",
success: function (res) {
if(res.ErrorCode=='0'){
if(res.ShuttedUinList.length>0){
Toast.notify('获取禁言列表成功,共'+res.ShuttedUinList.length+'个用户');
shlist.length=0;
shlist.options.add(new Option('选择取消禁言用户',''));
for(var i=0;i<res.ShuttedUinList.length;i++){
var userid=res.ShuttedUinList[i].Member_Account;
shlist.options.add(new Option(userid,userid));
}
}else{
shlist.length=0;
shlist.options.add(new Option('没有被禁言的用户',''));
}
}else{
// Toast.error('获取禁言列表失败。');
}
},
error: function (err) {
alert('error'+JSON.stringify(err));
// Toast.notify(_mixtype + ' record fail');
}
});
} //mixrecord
</script>
小结
暴改的腾讯 IM SDK Demo 请下载我的资源:
https://download.csdn.net/download/michaelline/89356543
本文代码代码示例仅供您参考使用,示例中使用到了视频通话的云端混录功能,有关云端混录功能请参考我的文章《C# 实现腾讯云多路直播流的云端混合录制》,请根据实际的应用取舍,另外一些 WebAPI 如设置用户在线状态、群组管理,也可根据实际需要进行修改。
感谢您的阅读,希望本文能够对您有所帮助。