2023-01-06 关于腾讯im在uniapp的小程序中遇到的一些问题

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 在本人不忙的情况可以协助解决

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 项目源代码地址:https://github.com/Mstian/wanAndroid (求个star)项目简书...
    Mstian阅读 7,519评论 10 22
  • 1 升级/更新 uniapp升级/更新的文档 uni-app资源在线升级/热更新 以及 uni-app 整包升级/...
    司空洛一阅读 4,067评论 0 0
  • 前言 本文会用实例的方式,将iOS各种IM的方案都简单的实现一遍。并且提供一些选型、实现细节以及优化的建议。 注:...
    iOS组委会主任阅读 1,012评论 0 2
  • 前言 本文主要是对iOS各种IM实现方案调研 并且提供一些选型、实现细节以及优化的建议。 注:文中的所有的代码示例...
    LWide阅读 5,311评论 2 36
  • 最近接手了一个小程序开发,从头开始。使用了 uniapp 搭建,以前没有做过小程序开发,着手看文档、查文档。一步一...
    z_hboot阅读 1,959评论 0 1

友情链接更多精彩内容