1、引入IM必要的包
import TIM from 'tim-wx-sdk'
import COS from 'cos-wx-sdk-v5';
在app.vue内进行初始化的一些操作
const SDKAppID = Config.IM_AppID;
uni.setStorageSync(`TIM_${SDKAppID}_isTUIKit`, true);
// 重点注意: 为了 uni-app 更好地接入使用 tim,快速定位和解决问题,请勿修改 uni.$TUIKit 命名。
// 如果您已经接入 tim ,请将 uni.tim 修改为 uni.$TUIKit。
uni.$TUIKit = TIM.create({
SDKAppID: SDKAppID
});
uni.$TUIKit.registerPlugin({
'cos-wx-sdk': COS
});
// 如果您已创建了 tim,请将 tim 实例挂载在 wx 上,且不可以修改 wx.$TIM(修改变量可能导致 TUICalling 组件无法正常使用), 完成 TUICalling 初始化,
// 如果您没有创建,可以不传
wx.$TIM = uni.$TUIKit;
uni.$TUIKitTIM = TIM;
uni.$TUIKitEvent = TIM.EVENT;
uni.$TUIKitVersion = TIM.VERSION;
uni.$TUIKitTypes = TIM.TYPES; // 监听系统级事件
uni.$resetLoginData = this.resetLoginData();
uni.$TUIKit.on(uni.$TUIKitEvent.SDK_READY, this.onSDKReady);
uni.$TUIKit.on(uni.$TUIKitEvent.SDK_NOT_READY, this.onSdkNotReady);
uni.$TUIKit.on(uni.$TUIKitEvent.KICKED_OUT, this.onKickedOut);
uni.$TUIKit.on(uni.$TUIKitEvent.ERROR, this.onTIMError);
uni.$TUIKit.on(uni.$TUIKitEvent.NET_STATE_CHANGE, this.onNetStateChange);
uni.$TUIKit.on(uni.$TUIKitEvent.SDK_RELOAD, this.onSDKReload);
跟据业务进行登录操作
uni.$TUIKit.login({
userID: userID,
userSig: userSig
}).then(() => {
console.log('im登录成功');
this.imIsLogin = true
}).catch((error) => {
console.log('im登录失败');
this.imIsLogin = false
})
2、音视频的相关内容
由于直接小程序主包体积的问题 如果直接引入官方给的 TUICallKit 会导致主包体积过大
当时困扰了很久
后来的解决方案是把
/wxcomponents/TUICallKit/lib
/wxcomponents/TUICallKit/TUICallEngine
这两个目录的内容全部移到了
/vendors 下面 如下图

image.png
/wxcomponents/TUICallKit/TUICallKit/TUICallKit.js 第一行引入js的地方注释 并且加上4个变量
// import TUICallEngine, {
// EVENT,
// MEDIA_TYPE,
// AUDIO_PLAYBACK_DEVICE,
// STATUS
// } from '/vendors/TUICallEngine/tuicall-engine-wx.js';
const STATUS={"IDLE":"idle","CALLING":"calling","CONNECTED":"connected"}
const MEDIA_TYPE={"AUDIO":1,"VIDEO":2}
const AUDIO_PLAYBACK_DEVICE={"EAR":"ear","SPEAKER":"speaker"}
const EVENT = {"INVITED":"INVITED","GROUP_CALL_INVITEE_LIST_UPDATE":"GROUP_CALL_INVITEE_LIST_UPDATE","USER_ENTER":"USER_ENTER","USER_LEAVE":"USER_LEAVE","USER_ACCEPT":"USER_ACCEPT","USER_UPDATE":"USER_UPDATE","REJECT":"REJECT","NO_RESP":"NO_RESP","LINE_BUSY":"LINE_BUSY","CALLING_CANCEL":"CALLING_CANCEL","CALLING_TIMEOUT":"CALLING_TIMEOUT","CALL_END":"CALL_END","USER_VIDEO_AVAILABLE":"USER_VIDEO_AVAILABLE","USER_AUDIO_AVAILABLE":"USER_AUDIO_AVAILABLE","USER_VOICE_VOLUME":"USER_VOICE_VOLUME","SDK_READY":"SDK_READY","KICKED_OUT":"KICKED_OUT","CALL_MODE":"CALL_MODE","HANG_UP":"HANG_UP","MESSAGE_SENT_BY_ME":"onMessageSentByMe","ERROR":"ERROR"}
// 组件旨在跨终端维护一个通话状态管理机,以事件发布机制驱动上层进行管理,并通过API调用进行状态变更。
// 组件设计思路将UI和状态管理分离。您可以通过修改`component`文件夹下的文件,适配您的业务场景,
// 在UI展示上,您可以通过属性的方式,将上层的用户头像,名称等数据传入组件内部,`static`下的icon和默认头像图片,
// 只是为了展示基础的效果,您需要根据业务场景进行修改。
Component({
properties: {
config: {
type: Object,
value: {
sdkAppID: 0,
userID: '',
userSig: '',
type: 1,
tim: null,
},
},
backgroundMute: {
type: Boolean,
value: false,
},
},
observers: {
},
data: {
callStatus: STATUS.IDLE, // idle、calling、connection
isSponsor: false, // 呼叫者身份 true为呼叫者 false为被叫者
pusher: {}, // TRTC 本地流
playerList: [], // TRTC 远端流
playerProcess: {}, // 经过处理的的远端流(多人通话)
isGroup: false, // 是否为多人通话
remoteUsers: [], // 单人通话远程用户资料(不包含自身)
allUsers: [], // 多人通话用户资料(包含自身)
sponsor: '', // 主叫方
screen: 'pusher', // 视屏通话中,显示大屏幕的流(只限1v1聊天
soundMode: AUDIO_PLAYBACK_DEVICE.SPEAKER, // 声音模式 听筒/扬声器
showToatTime: 0, // 弹窗时长
ownUserId: '',
},
methods: {
resetUI() {
// 收起键盘
wx.hideKeyboard();
},
// 新的邀请回调事件
handleNewInvitationReceived(event) {
this.resetUI();
this.data.config.type = event.data.inviteData.callType;
// 判断是否为多人通话
if (event.data.isFromGroup) {
this.setData({
isGroup: true,
sponsor: event.data.sponsor,
});
// 将主叫方和被叫列表合并在一起 组成全部通话人数
const newList = [...event.data.inviteeList, event.data.sponsor];
// 获取用户信息
this.getUserProfile(newList);
} else {
this.getUserProfile([event.data.sponsor]);
}
this.setData({
config: this.data.config,
callStatus: STATUS.CALLING,
isSponsor: false,
});
console.log('xx看看到这里了没', this.data.config)
},
// 用户接听
handleUserAccept(event) {
// 主叫方则唤起通话页面
if (this.data.isSponsor) {
this.setData({
callStatus: STATUS.CONNECTED,
});
}
},
// 远端用户进入通话
handleUserEnter(res) {
const newList = this.data.allUsers;
// 多人通话
if (this.data.isGroup) {
// 改变远端用户信息中的isEnter属性
for (let i = 0; i < newList.length; i++) {
if (newList[i].userID === res.data.userID) {
newList[i].isEnter = true;
}
}
}
this.setData({
playerList: res.playerList,
allUsers: newList,
});
},
// 远端用户离开通话
handleUserLeave(res) {
// 多人通话
if (this.data.isGroup) {
wx.showToast({
title: `${res.data.userID}离开通话`,
});
this.deleteUsers(this.data.allUsers, res.data.userID);
}
this.setData({
playerList: res.data.playerList,
});
},
// 用户数据更新
handleUserUpdate(res) {
this.handleNetStatus(res.data);
const newplayer = {};
const newres = res.data.playerList;
// 多人通话
if (this.data.isGroup) {
// 处理远端流
for (let i = 0; i < newres.length; i++) {
const {
userID
} = newres[i];
newplayer[userID] = newres[i];
}
};
this.setData({
pusher: res.data.pusher,
playerList: res.data.playerList,
playerProcess: newplayer,
});
},
// 判断网络状态
handleNetStatus(data) {
if (data.pusher.netQualityLevel > 4) {
wx.showToast({
icon: 'none',
title: '您当前网络不佳',
});
}
data.playerList.map((item) => {
if (item.netStatus.netQualityLevel > 4) {
const name = data.playerList.length > 1 ? item.nick : '对方';
wx.showToast({
icon: 'none',
title: `${name}当前网络不佳`,
});
}
return item;
});
},
// 用户拒绝
handleInviteeReject(event) {
if (this.data.isGroup) {
this.deleteUsers(this.data.allUsers, event.data.invitee);
}
wx.showToast({
title: `${event.data.invitee}已拒绝`,
});
},
// 用户不在线
handleNoResponse(event) {
if (this.data.isGroup) {
this.deleteUsers(this.data.allUsers, event.data.timeoutUserList);
}
wx.showToast({
icon: 'none',
title: `${event.data.timeoutUserList}无应答`,
});
},
// 用户忙线
handleLineBusy(event) {
if (this.data.isGroup) {
this.deleteUsers(this.data.allUsers, event.data.invitee);
}
this.showToast(event.data.invitee);
},
showToast(event) {
this.setData({
showToatTime: this.data.showToatTime + 500,
});
setTimeout(() => {
wx.showToast({
title: `${event}忙线中`,
});
}, this.data.showToatTime);
},
// 用户取消
handleCallingCancel(event) {
if (event.data.invitee !== this.data.config.userID) {
wx.showToast({
title: `${event.data.invitee}取消通话`,
});
}
this.reset();
},
// 通话超时未应答
handleCallingTimeout(event) {
if (this.data.isGroup) {
// 若是自身未应答 则不弹窗
if (this.data.config.userID === event.data.timeoutUserList[0]) {
this.reset();
return;
}
const newList = this.deleteUsers(this.data.allUsers, event.data.timeoutUserList);
this.setData({
allUsers: newList,
});
}
if (this.data.playerList.length === 0) {
this.reset();
}
wx.showToast({
title: `${event.data.timeoutUserList[0]}超时无应答`,
});
},
handleCallingUser(userIDList) {
const remoteUsers = [...this.data.remoteUsers];
const userProfile = remoteUsers.filter(item => userIDList.some(userItem => `${userItem}` === item
.userID));
this.setData({
remoteUsers: remoteUsers.filter(item => userIDList.some(userItem => userItem !== item
.userID)),
});
let nick = '';
for (let i = 0; i < userProfile.length; i++) {
nick += `${userProfile[i].nick}、`;
}
return nick.slice(0, -1);
},
// 通话结束
handleCallingEnd(event) {
wx.showToast({
title: '通话结束',
duration: 800,
});
this.reset();
},
// SDK Ready 回调
handleSDKReady() {
// 呼叫需在sdk ready之后
},
// 被踢下线
handleKickedOut() {
wx.showToast({
title: '您已被踢下线',
});
},
// 切换通话模式
handleCallMode(event) {
this.data.config.type = event.data.type;
this.setSoundMode(AUDIO_PLAYBACK_DEVICE.EAR);
this.setData({
config: this.data.config,
});
},
// 删除用户列表操作
deleteUsers(usersList, userID) {
// 若userID不是数组,则将其转换为数组
if (!Array.isArray(userID)) {
userID = [userID];
}
const list = usersList.filter(item => !userID.includes(item.userID));
this.setData({
allUsers: list,
});
},
// 增加用户列表操作
addUsers(usersList, userID) {
// 若userID不是数组,则将其转换为数组
if (!Array.isArray(userID)) {
userID = [userID];
}
const newList = [...usersList, ...userID];
return newList;
},
// 增加 tsignaling 事件监听
_addTSignalingEvent() {
// 被邀请通话
wx.$TUICallEngine.on(EVENT.INVITED, this.handleNewInvitationReceived, this);
// 用户接听
wx.$TUICallEngine.on(EVENT.USER_ACCEPT, this.handleUserAccept, this);
// 用户进入通话
wx.$TUICallEngine.on(EVENT.USER_ENTER, this.handleUserEnter, this);
// 用户离开通话
wx.$TUICallEngine.on(EVENT.USER_LEAVE, this.handleUserLeave, this);
// 用户更新数据
wx.$TUICallEngine.on(EVENT.USER_UPDATE, this.handleUserUpdate, this);
// 用户拒绝通话
wx.$TUICallEngine.on(EVENT.REJECT, this.handleInviteeReject, this);
// 用户无响应
wx.$TUICallEngine.on(EVENT.NO_RESP, this.handleNoResponse, this);
// 用户忙线
wx.$TUICallEngine.on(EVENT.LINE_BUSY, this.handleLineBusy, this);
// 通话被取消
wx.$TUICallEngine.on(EVENT.CALLING_CANCEL, this.handleCallingCancel, this);
// 通话超时未应答
wx.$TUICallEngine.on(EVENT.CALLING_TIMEOUT, this.handleCallingTimeout, this);
// 通话结束
wx.$TUICallEngine.on(EVENT.CALL_END, this.handleCallingEnd, this);
// SDK Ready 回调
wx.$TUICallEngine.on(EVENT.SDK_READY, this.handleSDKReady, this);
// 被踢下线
wx.$TUICallEngine.on(EVENT.KICKED_OUT, this.handleKickedOut, this);
// 切换通话模式
wx.$TUICallEngine.on(EVENT.CALL_MODE, this.handleCallMode, this);
// 自己发送消息
wx.$TUICallEngine.on(EVENT.MESSAGE_SENT_BY_ME, this.messageSentByMe, this);
},
// 取消 tsignaling 事件监听
_removeTSignalingEvent() {
// 被邀请通话
wx.$TUICallEngine.off(EVENT.INVITED, this.handleNewInvitationReceived);
// 用户接听
wx.$TUICallEngine.off(EVENT.USER_ACCEPT, this.handleUserAccept);
// 用户进入通话
wx.$TUICallEngine.off(EVENT.USER_ENTER, this.handleUserEnter);
// 用户离开通话
wx.$TUICallEngine.off(EVENT.USER_LEAVE, this.handleUserLeave);
// 用户更新数据
wx.$TUICallEngine.off(EVENT.USER_UPDATE, this.handleUserUpdate);
// 用户拒绝通话
wx.$TUICallEngine.off(EVENT.REJECT, this.handleInviteeReject);
// 用户无响应
wx.$TUICallEngine.off(EVENT.NO_RESP, this.handleNoResponse);
// 用户忙线
wx.$TUICallEngine.off(EVENT.LINE_BUSY, this.handleLineBusy);
// 通话被取消
wx.$TUICallEngine.off(EVENT.CALLING_CANCEL, this.handleCallingCancel);
// 通话超时未应答
wx.$TUICallEngine.off(EVENT.CALLING_TIMEOUT, this.handleCallingTimeout);
// 通话结束
wx.$TUICallEngine.off(EVENT.CALL_END, this.handleCallingEnd);
// SDK Ready 回调
wx.$TUICallEngine.off(EVENT.SDK_READY, this.handleSDKReady);
// 被踢下线
wx.$TUICallEngine.off(EVENT.KICKED_OUT, this.handleKickedOut);
// 切换通话模式
wx.$TUICallEngine.off(EVENT.CALL_MODE, this.handleCallMode);
// 自己发送消息
wx.$TUICallEngine.off(EVENT.MESSAGE_SENT_BY_ME, this.messageSentByMe);
},
/**
* C2C邀请通话,被邀请方会收到的回调
* 如果当前处于通话中,可以调用该函数以邀请第三方进入通话
*
* @param userID 被邀请方
* @param type 0-为之, 1-语音通话,2-视频通话
*/
async call(params) {
this.resetUI();
if (this.data.callStatus !== STATUS.IDLE) {
return;
}
await wx.$TUICallEngine.call({
userID: params.userID,
type: params.type
}).then((res) => {
this.data.config.type = params.type;
this.getUserProfile([params.userID]);
this.setData({
pusher: res.pusher,
config: this.data.config,
callStatus: STATUS.CALLING,
isSponsor: true,
});
this.setSoundMode(this.data.config.type === MEDIA_TYPE.AUDIO ? AUDIO_PLAYBACK_DEVICE
.EAR : AUDIO_PLAYBACK_DEVICE.SPEAKER);
});
},
/**
* IM群组邀请通话,被邀请方会收到的回调
* 如果当前处于通话中,可以继续调用该函数继续邀请他人进入通话,同时正在通话的用户会收到的回调
*
* @param userIDList 邀请列表
* @param type 1-语音通话,2-视频通话
* @param groupID IM群组ID
*/
async groupCall(params) {
// 判断是否存在groupID
if (!params.groupID) {
wx.showToast({
title: '群ID为空',
});
return;
}
this.resetUI();
if (this.data.callStatus !== STATUS.IDLE) {
return;
}
wx.$TUICallEngine.groupCall({
userIDList: params.userIDList,
type: params.type,
groupID: params.groupID
}).then((res) => {
this.data.config.type = params.type;
this.setData({
pusher: res.pusher,
config: this.data.config,
callStatus: STATUS.CALLING,
isSponsor: true,
isGroup: true,
sponsor: this.data.config.userID,
});
// 将自身的userID插入到邀请列表中,组成完整的用户信息
const list = JSON.parse(JSON.stringify(params.userIDList));
list.unshift(this.data.config.userID);
// 获取用户信息
this.getUserProfile(list);
});
},
/**
* 当您作为被邀请方收到 {@link TRTCCallingDelegate#onInvited } 的回调时,可以调用该函数接听来电
*/
async accept() {
wx.$TUICallEngine.accept().then((res) => {
this.setData({
pusher: res.pusher,
callStatus: STATUS.CONNECTED,
});
// 多人通话需要对自身位置进行修正,将其放到首位
if (this.data.isGroup) {
const newList = this.data.allUsers;
for (let i = 0; i < newList.length; i++) {
if (newList[i].userID === this.data.config.userID) {
newList[i].isEnter = true;
[newList[i], newList[0]] = [newList[0], newList[i]];
}
}
this.setData({
allUsers: newList,
});
}
})
.catch((error) => {
wx.showModal({
icon: 'none',
title: 'error',
content: error.message,
showCancel: false,
});
});
},
/**
* 当您作为被邀请方收到的回调时,可以调用该函数拒绝来电
*/
async reject() {
wx.$TUICallEngine.reject().then((res) => {
this.reset();
});
},
messageSentByMe(event) {
const message = event.data.data;
this.triggerEvent('sendMessage', {
message,
});
},
// xml层,是否开启扬声器
setSoundMode(type) {
this.setData({
soundMode: wx.$TUICallEngine.selectAudioPlaybackDevice(type),
});
},
// xml层,挂断
async _hangUp() {
await wx.$TUICallEngine.hangup();
this.reset();
},
// 切换大小屏 (仅支持1v1聊天)
toggleViewSize(event) {
this.setData({
// FIXME _toggleViewSize 不应该为TUICallEngine的方法 后续修改
screen: wx.$TUICallEngine._toggleViewSize(event),
});
},
// 数据重置
reset() {
this.setData({
callStatus: STATUS.IDLE,
isSponsor: false,
isGroup: false,
soundMode: AUDIO_PLAYBACK_DEVICE.SPEAKER,
pusher: {}, // TRTC 本地流
playerList: [], // TRTC 远端流
showToatTime: 0,
});
},
// 呼叫中的事件处理
handleCallingEvent(data) {
const {
name
} = data.detail;
switch (name) {
case 'accept':
this.setSoundMode(this.data.config.type === MEDIA_TYPE.AUDIO ? AUDIO_PLAYBACK_DEVICE.EAR :
AUDIO_PLAYBACK_DEVICE.SPEAKER);
this.accept();
break;
case 'hangup':
this._hangUp();
break;
case 'reject':
this.reject();
break;
case 'toggleSwitchCamera':
wx.$TUICallEngine.switchCamera();
break;
case 'switchAudioCall':
wx.$TUICallEngine.switchCallMediaType(MEDIA_TYPE.AUDIO).then((res) => {
this.data.config.type = MEDIA_TYPE.AUDIO;
this.setSoundMode(AUDIO_PLAYBACK_DEVICE.EAR);
this.setData({
config: this.data.config,
});
});
break;
default:
break;
}
},
// 通话中的事件处理
handleConnectedEvent(data) {
const {
name,
event
} = data.detail;
switch (name) {
case 'toggleViewSize':
this.toggleViewSize(event);
break;
case 'pusherNetStatus':
wx.$TUICallEngine._pusherNetStatus(event);
break;
case 'playNetStatus':
wx.$TUICallEngine._playNetStatus(event);
break;
case 'pusherStateChangeHandler':
wx.$TUICallEngine._pusherStateChangeHandler(event);
break;
case 'pusherAudioVolumeNotify':
wx.$TUICallEngine._pusherAudioVolumeNotify(event);
break;
case 'playerStateChange':
wx.$TUICallEngine._playerStateChange(event);
break;
case 'playerAudioVolumeNotify':
wx.$TUICallEngine._playerAudioVolumeNotify(event);
break;
case 'pusherAudioHandler':
wx.$TUICallEngine._pusherAudioHandler(event);
break;
case 'hangup':
this._hangUp();
break;
case 'toggleSoundMode':
this.setSoundMode(this.data.soundMode === AUDIO_PLAYBACK_DEVICE.EAR ? AUDIO_PLAYBACK_DEVICE
.SPEAKER : AUDIO_PLAYBACK_DEVICE.EAR);
break;
case 'pusherVideoHandler':
wx.$TUICallEngine._pusherVideoHandler(event);
break;
case 'toggleSwitchCamera':
wx.$TUICallEngine.switchCamera(event);
break;
case 'switchAudioCall':
wx.$TUICallEngine.switchCallMediaType(MEDIA_TYPE.AUDIO).then((res) => {
this.data.config.type = MEDIA_TYPE.AUDIO;
this.setData({
config: this.data.config,
});
this.setSoundMode(AUDIO_PLAYBACK_DEVICE.EAR);
});
break;
default:
break;
}
},
// 设置用户的头像、昵称
setSelfInfo(nickName, avatar) {
return wx.$TUICallEngine.setSelfInfo(nickName, avatar);
},
// 获取用户资料
async getUserProfile(userList) {
const imResponse = await this.getTim().getUserProfile({
userIDList: userList
});
// 修正用户资料
this.modifyUser(imResponse.data);
},
// 修正用户资料
modifyUser(userIDList) {
const {
sponsor
} = this.data;
if (this.data.isGroup) {
// 多人通话需要将呼叫者放到第一位 isEnter的作用是区分用户是否进入房间
for (let i = 0; i < userIDList.length; i++) {
// 主叫方的标志位设置成true
if (userIDList[i].userID === sponsor) {
userIDList[i].isEnter = true;
// 对主叫方位置进行修正 将其放到首位
[userIDList[i], userIDList[0]] = [userIDList[0], userIDList[i]];
} else {
// 其他用户默认未进入房间 设置为false
userIDList[i].isEnter = false;
}
}
this.setData({
allUsers: userIDList,
});
}
this.setData({
remoteUsers: userIDList,
});
},
// 获取 tim 实例
getTim() {
return wx.$TUICallEngine.getTim();
},
// 初始化TRTCCalling
async init(params) {
// 兼容从config和init中传值
const {
sdkAppID,
tim,
userID,
userSig,
SDKAppID
} = {
...this.data.config,
...params
};
this.setData({
ownUserId: userID,
config: {
...this.data.config,
sdkAppID: sdkAppID || SDKAppID,
userID,
userSig,
},
});
// wx.$TUICallEngine = TUICallEngine.createInstance({
// tim,
// sdkAppID: sdkAppID || SDKAppID,
// });
//this._addTSignalingEvent();
// const res = await wx.$TUICallEngine.init({
// userID,
// userSig,
// });
//return res;
},
// 销毁 TUICallEngine
destroyed() {
console.log('销毁了所有了吗')
//this._removeTSignalingEvent();
//TUICallEngine.destroyInstance();
},
},
/**
* 生命周期方法
*/
lifetimes: {
created() {
},
attached() {
},
ready() {
this.reset();
},
detached() {
this.destroyed();
this.reset();
},
error() {},
},
pageLifetimes: {
show() {
},
hide() {},
resize() {},
},
});
在app.vue跟据自行im sdkReady的回调进行初始化 音视频的初始化和业务的监听
1.app-tuicallkit-delegate.js
import TUICallEngine, { EVENT, MEDIA_TYPE, AUDIO_PLAYBACK_DEVICE, STATUS } from '../TUICallEngine/tuicall-engine-wx.js';
var AppTUICallKitDelegate = {
TYPE_INVITE: "invite",
TYPE_CALL: "call",
callPageMethods: null,
init({
tim,
sdkAppId,
userId,
userSig,
callPageMethods
}) {
console.log('初始化音视频开始')
if (wx.$TUICallEngine) {
wx.$TUICallEngine = null
}
//创建TUICallEngine
wx.$TUICallEngine = TUICallEngine.createInstance({
tim: tim,
sdkAppID: sdkAppId,
});
//添加INVITED监听
this.addTUICallEngineEvent();
//监听其它事件
this.callPageMethods = callPageMethods
this.addOtherEvent()
//初始化TUICallEngine
wx.$TUICallEngine.login({
userID: userId,
userSig: userSig,
})
},
eventMethod(event) {
this.callPageMethods(event)
},
addOtherEvent(fun) {
// 用户接听
wx.$TUICallEngine.on(EVENT.USER_ACCEPT, this.eventMethod, this);
// 用户进入通话
wx.$TUICallEngine.on(EVENT.USER_ENTER, this.eventMethod, this);
// 用户离开通话
wx.$TUICallEngine.on(EVENT.USER_LEAVE, this.eventMethod, this);
// 用户更新数据
wx.$TUICallEngine.on(EVENT.USER_UPDATE, this.eventMethod, this);
// 用户拒绝通话
wx.$TUICallEngine.on(EVENT.REJECT, this.eventMethod, this);
// 用户无响应
wx.$TUICallEngine.on(EVENT.NO_RESP, this.eventMethod, this);
// 用户忙线
wx.$TUICallEngine.on(EVENT.LINE_BUSY, this.eventMethod, this);
// 通话被取消
wx.$TUICallEngine.on(EVENT.CALLING_CANCEL, this.eventMethod, this);
// 通话超时未应答
wx.$TUICallEngine.on(EVENT.CALLING_TIMEOUT, this.eventMethod, this);
// 通话结束
wx.$TUICallEngine.on(EVENT.CALL_END, this.eventMethod, this);
// SDK Ready 回调
// wx.$TUICallEngine.on(EVENT.SDK_READY, this.eventMethod, this);
// 被踢下线
wx.$TUICallEngine.on(EVENT.KICKED_OUT, this.eventMethod, this);
// 切换通话模式
wx.$TUICallEngine.on(EVENT.CALL_MODE, this.eventMethod, this);
// 自己发送消息
wx.$TUICallEngine.on(EVENT.MESSAGE_SENT_BY_ME, this.eventMethod, this);
},
addTUICallEngineEvent() {
wx.$TUICallEngine.on('INVITED', this.handleNewInvitationReceived, this);
},
removeTUICallEngineEvent() {
wx.$TUICallEngine.off('INVITED', this.handleNewInvitationReceived, this);
},
/**
* 监听新的邀请
*/
handleNewInvitationReceived(event) {
//this.removeTUICallEngineEvent();
this.navigateTo(this.TYPE_INVITE, event);
},
/**
* 监听主动拨打
*/
handleNewCall(event) {
//this.removeTUICallEngineEvent();
this.navigateTo(this.TYPE_CALL, event);
},
navigateTo(type, event) {
wx.navigateTo({
url: '/pages/call/index?type=' + type + '&event=' + JSON.stringify(event),
})
}
}
export default AppTUICallKitDelegate
2.开始监听
//事件监听处理音视频页面
callPageMethods(event) {
//console.log('获取当前页面',getCurrentPages())
setTimeout(() => {
const curPage = getCurrentPages()
const callPage = curPage[curPage.length - 1]
try {
callPage.$vm.callPageMethods(event)
} catch (err) {
console.log('捕获的错', event)
}
}, 200)
},
onSDKReady({
name
}) {
const isSDKReady = name === uni.$TUIKitEvent.SDK_READY ? true : false
setTimeout(() => {
this.initTuicallkit()
}, 1000)
// uni.$emit('isSDKReady', {
// isSDKReady: true
// });
},
//开始监听音视频了
initTuicallkit() {
AppTuicallkitDelegate.init({
tim: uni.$TUIKit,
userId: this.globalData.userInfo.userID,
sdkAppId: this.globalData.SDKAppID,
userSig: this.globalData.userInfo.userSig,
callPageMethods: this.callPageMethods
})
},
3、/pages/call/index.vue 页面内容
<template>
<view>
<tuicallkit ref="TUICallKit" @callEnd="callEnd"></tuicallkit>
</view>
</template>
<script>
const app = getApp();
//import AppTuicallkitDelegate from '../../wxcomponents/TUICallKit/TUICallEngine/app-tuicallkit-delegate.js';
export default {
data() {
return {
config: {
userID: '',
userSig: '',
type: 1,
tim: uni.$TUIKit,
},
number: 0
}
},
onLoad(option) {
this.init(option)
},
methods: {
init(option) {
this.$nextTick(() => {
this.$refs.TUICallKit.init({
sdkAppID: app.globalData.SDKAppID,
userID: app.globalData.userInfo.userID,
userSig: app.globalData.userInfo.userSig,
tim: uni.$TUIKit
})
const {
type
} = option
let event = JSON.parse(option.event)
if (type == 'invite') {
this.$refs.TUICallKit.handleNewInvitationReceived(event)
} else if (type == 'call') {
this.$refs.TUICallKit.call(event);
}
})
},
callPageMethods(event) {
const type = event.eventCode
switch (type) {
// 用户接听
case 'USER_ACCEPT':
this.$refs.TUICallKit.handleUserAccept(event);
break
// 用户进入通话
case 'USER_ENTER':
this.$refs.TUICallKit.handleUserEnter(event);
break
// 用户离开通话
case 'USER_LEAVE':
this.$refs.TUICallKit.handleUserLeave(event);
break
//用户更新数据
case 'USER_UPDATE':
this.$refs.TUICallKit.handleUserUpdate(event);
break
// 用户拒绝通话
case 'REJECT':
this.$refs.TUICallKit.handleInviteeReject(event);
break
// 用户无响应
case 'NO_RESP':
this.$refs.TUICallKit.handleNoResponse(event);
break
// 用户无响应
case 'NO_RESP':
this.$refs.TUICallKit.handleNoResponse(event);
break
// 用户忙线
case 'LINE_BUSY':
this.$refs.TUICallKit.handleLineBusy(event);
break
// 通话被取消
case 'CALLING_CANCEL':
this.$refs.TUICallKit.handleCallingCancel(event);
this.callEnd()
break
// 通话超时未应答
case 'CALLING_TIMEOUT':
this.$refs.TUICallKit.handleCallingTimeout(event);
break
// 通话结束
case 'CALL_END':
this.$refs.TUICallKit.handleCallingEnd(event);
this.callEnd()
break
// SDK Ready 回调
case 'SDK_READY':
this.$refs.TUICallKit.handleSDKReady(event);
break
//被踢下线
case 'KICKED_OUT':
this.$refs.TUICallKit.handleKickedOut(event);
break
//切换通话模式
case 'CALL_MODE':
this.$refs.TUICallKit.handleCallMode(event);
break
//自己发送消息
case 'MESSAGE_SENT_BY_ME':
this.$refs.TUICallKit.messageSentByMe(event);
break
}
},
callEnd() {
//console.log('关闭了几次')
uni.navigateBack()
},
},
onUnload() {
this.$refs.TUICallKit.destroyed();
// setTimeout(()=>{
// console.log('重新初始化')
// app.initTuicallkit()
// },1000)
}
}
</script>
<style>
</style>
pages.json配置
{
"path": "pages/call/index",
"style": {
"navigationBarTitleText": "音视频",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"usingComponents": {
"tuicallkit": "/wxcomponents/TUICallKit/TUICallKit/TUICallKit"
}
}
}
4、小程序chat页面主动发起音视频 handleCalling这个方法
<template>
<view class="container">
<!-- #ifdef MP-WEIXIN -->
<!-- <tuicalling
ref="TUICalling"
id="TUICalling-component"
:config="config">
</tuicalling> -->
<!-- #endif -->
<view class="tui-chatroom-navigatorbar">
<view class="conversation-title">
<image @tap="goBack" class="tui-chatroom-navigatorbar-back"
src="https://oos-ahwh.ctyunapi.cn/yangzhoudianxin/report/static/static/assets/ic_back_white.svg" />
{{ conversationName }}
</view>
</view>
<view class="group-profile">
<TUI-group-profile v-if="isShow" id="groip-profile" :conversation="conversation" />
</view>
<view class="message-list" @tap="triggerClose" :style="{bottom:bottomVal2 + 'px'}">
<TUI-message-list id="message-list" ref="messageList" :conversation="conversation" />
</view>
<view v-if="videoPlay" class="container-box" @tap.stop="stopVideoHander">
<video v-if="videoPlay" class="video-message" @tap.stop="videoPlay = true"
:src="videoMessage.payload.videoUrl" :poster="videoMessage.payload.thumbUrl" object-fit="cover"
error="videoError" autoplay="true" direction="0" />
</view>
<view v-if="showChat" class="message-input" :style="{bottom:bottomVal + 'px'}">
<TUI-message-input @handleCalling="handleCalling" id="message-input" ref="messageInput"
:conversation="conversation" @sendMessage="sendMessage" @changeBottomVal="changeBottomVal" />
</view>
</view>
</template>
<script>
import AppTuicallkitDelegate from '../../vendors/lib/app-tuicallkit-delegate.js';
import logger from '../../utils/logger';
import TUIMessageList from '../components/tui-chat/message-list/index';
import TUIMessageInput from '../components/tui-chat/message-input/index';
import TUIGroupProfile from '../components/tui-group/group-profile/index';
const app = getApp();
export default {
components: {
TUIMessageList,
TUIMessageInput,
TUIGroupProfile
},
props: {},
data() {
return {
conversationName: '',
conversation: {},
messageList: [],
isShow: false,
showChat: true,
conversationID: '',
videoPlay: false,
videoMessage: {},
config: {
sdkAppID: '',
userID: '',
userSig: '',
type: 1,
tim: null
},
bottomVal: 0,
bottomVal2: 70
};
},
created() {
uni.$on('videoPlayerHandler', value => {
console.log('视频信息-====', value)
this.videoPlay = value.isPlay;
this.videoMessage = value.message;
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// conversationID: C2C、 GROUP
logger.log(` TUI-chat | onLoad | conversationID: ${options.conversationID}`);
const {
conversationID
} = options;
this.setData({
conversationID
});
// #ifdef MP-WEIXIN
// this.config = {
// sdkAppID: app.globalData.SDKAppID,
// userID: app.globalData.userInfo.userID,
// userSig: app.globalData.userInfo.userSig
// }
// logger.log(`TUI-chat | TUICalling-config | config:${JSON.stringify(this.callingConfig)}`);
// // 挂载在 uni 上
// uni.$wxTUICalling = this.$refs.TUICalling;
// this.$nextTick(() => {
// uni.$wxTUICalling.init()
// })
// #endif
uni.$TUIKit
.setMessageRead({
conversationID
})
.then(() => {
logger.log('TUI-chat | setMessageRead | ok');
});
uni.$TUIKit.getConversationProfile(conversationID).then(res => {
const {
conversation
} = res.data;
this.conversation = conversation;
this.setData({
conversationName: this.getConversationName(conversation),
isShow: conversation.type === 'GROUP'
});
});
},
mounted() {},
onUnload() {
// #ifdef MP-WEIXIN
// this.$refs.TUICalling.destroyed();
// // #endif
},
methods: {
// 键盘弹起事件
changeBottomVal(e) {
console.log('弹起的高度====', e)
this.setData({
bottomVal: e,
bottomVal2: e + 70
})
if (e == 0) {
console.log('下去=======')
this.$refs.messageList.scrollToButtomEnd()
} else {
console.log('上来=======')
this.$refs.messageList.scrollToButtom()
}
console.log('输入框盒子的bottom=====', this.bottomVal)
console.log('聊天内容的bottom=====', this.bottomVal2)
},
handleCalling(event) {
AppTuicallkitDelegate.handleNewCall(event);
},
stopVideoHander() {
this.videoPlay = false;
},
getConversationName(conversation) {
if (conversation.type === '@TIM#SYSTEM') {
this.setData({
showChat: false
});
return '系统通知';
}
if (conversation.type === 'C2C') {
return conversation.remark || conversation.userProfile.nick || conversation.userProfile.userID;
}
if (conversation.type === 'GROUP') {
return conversation.groupProfile.name || conversation.groupProfile.groupID;
}
},
sendMessage(event) {
// 将自己发送的消息写进消息列表里面
this.$refs.messageList.updateMessageList(event.detail.message);
},
triggerClose() {
if (this.showChat) {
this.$refs.messageInput.handleClose();
}
},
goBack() {
const pages = getCurrentPages(); // 当前页面栈
console.log('页面======', pages)
console.log('我点击了返回按钮==============')
if (
pages[pages.length - 2].route === 'pages/TUI-Conversation/create-conversation/create' ||
pages[pages.length - 2].route === 'pages/TUI-Group/create-group/create' ||
pages[pages.length - 2].route === 'pages/TUI-Group/join-group/join'
) {
uni.navigateBack({
delta: 2
});
} else {
uni.navigateBack({
delta: 1
});
}
uni.$TUIKit
.setMessageRead({
conversationID: this.conversationID
})
.then(() => {});
}
}
};
</script>
<style>
@import './chat.css';
</style>
如果还有其他问题的话 可以+我QQ 315069146 在本人不忙的情况可以协助解决