From b202a62d5d3d6a8fc05761e2091d687b3838b478 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 7 Feb 2022 11:01:36 +0800 Subject: [PATCH] =?UTF-8?q?IM=E9=83=A8=E5=88=86=E7=9A=84=E5=A4=87=E6=B3=A8?= =?UTF-8?q?=EF=BC=8C=E6=B6=88=E6=81=AF=E5=8F=91=E9=80=81=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=88=86=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 1 + pages/im/index.vue | 16 +- pages/im/private/chat.nvue | 831 ++++++++++++++++++------------------- utils/im/index.js | 518 ++++++++++------------- utils/im/message.js | 154 +++++++ 5 files changed, 807 insertions(+), 713 deletions(-) create mode 100644 utils/im/message.js diff --git a/App.vue b/App.vue index 6861729..7b7b95a 100644 --- a/App.vue +++ b/App.vue @@ -5,6 +5,7 @@ export default { onLaunch: function() { im.initIm('lmxuhwaglu76d') + return //#ifdef APP-PLUS // 获取系统版本号 getVersions({ diff --git a/pages/im/index.vue b/pages/im/index.vue index 301c6ee..3871944 100644 --- a/pages/im/index.vue +++ b/pages/im/index.vue @@ -15,9 +15,9 @@ - + @@ -130,14 +130,16 @@ } } }, - methods: { + methods: { + // 隐藏功能菜单 hidePop() { this.showPop = false this.pickedItem = {} setTimeout(() => { this.showShade = false }, 250) - }, + }, + // 点击会话功能菜单 pickerMenu(e) { const index = Number(e.currentTarget.dataset.index) @@ -150,7 +152,8 @@ im.setNotifyBadge() this.getConversationList() this.hidePop() - }, + }, + // 长按会话,展示功能菜单 onLongPress(e) { let [touches, style, item] = [e.touches[0], "", e.currentTarget.dataset.item] @@ -217,7 +220,8 @@ params }) } - }, + }, + // 调起扫码 scanQrCode() { uni.scanCode({ success: (res) => { diff --git a/pages/im/private/chat.nvue b/pages/im/private/chat.nvue index a803811..a026e7b 100644 --- a/pages/im/private/chat.nvue +++ b/pages/im/private/chat.nvue @@ -1,418 +1,417 @@ - - - - - diff --git a/utils/im/index.js b/utils/im/index.js index fdcffef..274c8ab 100644 --- a/utils/im/index.js +++ b/utils/im/index.js @@ -1,292 +1,228 @@ - -import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' -import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index' -import store from '@/store/index.js' -import { - getFriends, - getUserInfo, - getImToken -} from '@/apis/interfaces/im.js' - -const initIm = (KEY) => { - RongIMLib.init(KEY) - CallLib.init() - addListeners() - // 初始化的时候 自动链接 - if (store.getters.getToken !== '') { - getImToken().then(res => { - connect(res.token, res.userInfo, () => {}) - }) - } -} - -const setNotifyBadge = () => { - // 获取未读消息数量 - RongIMLib.getTotalUnreadCount(({ - code, - count - }) => { - if (code === 0) { - // #ifdef APP-PLUS - plus.runtime.setBadgeNumber(count) - // #endif - if (count > 0) { - uni.setTabBarBadge({ - index: 3, - text: String(count > 99 ? '99+' : count) - }) - } else { - uni.removeTabBarBadge({ - index: 3 - }) - } - } - }) -} - -/** - * 连接IM服务 - * @param {string} token token - * @param {object} userInfo {userId: string, name: string, portraitUrl: string} - */ -const connect = (token, userInfo, callback) => { - RongIMLib.connect(token, res => { - console.log('连接结果', res); - - callback(res) - }) - - store.dispatch('setSenderInfo', userInfo) - - setNotifyBadge() - - const model = uni.model.friendModel - - model.find((err, results) => { - console.log('好友列表', results); - results.map(item => { - store.dispatch('updateFriends', item) - }) - }) -} - -/** - * 断开链接 - */ -const disconnect = () => { - RongIMLib.disconnect() - // 移除提醒数量 - // #ifdef APP-PLUS - plus.runtime.setBadgeNumber(0) - // #endif - uni.removeTabBarBadge({ - index: 3 - }) -} - -// 允许通知的消息类型,触发更新消息列表操作 -const notifyMsgTypes = [ - 'RC:TxtMsg', - 'RC:VcMsg', - 'RC:HQVCMsg', - 'RC:ImgMsg', - 'RC:GIFMsg', - 'RC:ImgTextMsg', - 'RC:FileMsg', - 'RC:LBSMsg', - 'RC:SightMsg', - 'RC:ReferenceMsg', - 'RC:CombineMsg', -] - -function inArray(search, array) { - for (var i in array) { - if (array[i] == search) { - return true; - } - } - return false; -} - -const addListeners = () => { - // 添加连接状态监听函数 - RongIMLib.addConnectionStatusListener((res) => { - console.log('连接状态监听', res.data.status); - uni.$emit('onConnectionStatusChange', res.data.status) - }) - // 添加消息监听函数 - RongIMLib.addReceiveMessageListener((res) => { - console.log('收到消息', res.data.message); - const message = res.data.message - if (inArray(message.objectName, notifyMsgTypes)) { - console.log('new Message'); - newMessage(message) - } - }) - // 监听通话呼入 - CallLib.onCallReceived(({ - data - }) => { - console.log('onCallReceived', data) - - uni.navigateTo({ - url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' + - data.mediaType - }) - }) - - // 通话建立成功 - CallLib.onCallConnected(() => { - uni.$emit('onCallConnected'); - }) - - CallLib.onCallOutgoing((res) => { - uni.$emit('onCallOutgoing'); - }) - CallLib.onRemoteUserRinging((res) => { - uni.$emit('onRemoteUserRinging'); - }) - CallLib.onRemoteUserJoined((res) => { - uni.$emit('onRemoteUserJoined'); - }) - CallLib.onCallDisconnected((res) => { - console.log('断开链接', res); - uni.$emit('onCallDisconnected'); - }) - CallLib.onRemoteUserLeft((res) => { - console.log('远端离开', res); - uni.$emit('onRemoteUserLeft'); - }) -} - -// 维护消息列表 -const newMessage = (msg) => { - RongIMLib.getConversationNotificationStatus(msg.conversationType, msg.targetId, ({ - code, - status - }) => { - if (code === 0) { - if (status) { - triTone() - } - } - }); - - setNotifyBadge() - - if (!store.getters.hasUser(msg.targetId)) { - syncUserInfo(msg.targetId) - } - - uni.$emit('onReceiveMessage', msg); - // store.dispatch('newMessage', msg) -} - -function syncUserInfo(targetId) { - getUserInfo(targetId).then(res => { - store.dispatch('updateFriends', res) - }) -} - -// 播放状态 -let tipState = false - -const triTone = () => { - if (tipState == false) { - const innerAudioContext = uni.createInnerAudioContext() - innerAudioContext.autoplay = true - innerAudioContext.src = '/utils/im/sounds/new-msg.mp3' - innerAudioContext.onPlay(() => { - tipState = true - }) - innerAudioContext.onEnded(() => { - tipState = false - }) - } -} - -/** - * 发送消息 - * @param {number} conversationType 消息类型 - * @param {string} targetId 会话id - * @param {string} content 消息内容 - * @param {function} callback 回调函数 - */ -const sendMsg = (conversationType, targetId, content, callback) => { - const msg = { - conversationType: conversationType, - targetId: String(targetId), - content: { - objectName: 'RC:TxtMsg', - content: content, - user: store.getters.sender - } - } - RongIMLib.sendMessage(msg, ({ - code, - messageId - }) => { - if (code === 0) { - callback(messageId) - } else { - uni.showToast({ - icon: 'none', - title: '发送失败' - }) - } - }) -} - -/** - * conversationType 会话类型 - * voiceUrl 本地的录音路径 - * time 录音时长 - */ -const sendVoiceMsg = (conversationType, targetId, voiceUrl, time, callback) => { - console.log('sendVoiceMsg', plus.io.convertLocalFileSystemURL(voiceUrl)); - const msg = { - conversationType: conversationType, - targetId: String(targetId), - content: { - objectName: 'RC:HQVCMsg', - local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl), - duration: time - } - } - RongIMLib.sendMediaMessage(msg, { - success: (messageId) => { - callback(messageId); - }, - progress: (progress, messageId) => { - console.log(messageId); - }, - cancel: (messageId) => { - // 发送取消回调 - }, - error: (errorCode, messageId) => { - console.log(errorCode, messageId); - } - }) -} - -/** - * 同步好友信息,保存头像地址等 - */ -const syncFriends = () => { - getFriends().then(res => { - res.map(item => { - console.log('item', item); - store.dispatch('updateFriends', item) - }) - }) -} - -export default { - initIm, - connect, - sendMsg, - sendVoiceMsg, - setNotifyBadge, - syncFriends, - syncUserInfo +import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' +import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index' +import store from '@/store/index.js' +import message from './message.js' +import { + getFriends, + getUserInfo, + getImToken +} from '@/apis/interfaces/im.js' + +const initIm = (KEY) => { + RongIMLib.init(KEY) + CallLib.init() + addListeners() + // 初始化的时候 自动链接 + if (store.getters.getToken !== '') { + getImToken().then(res => { + connect(res.token, res.userInfo, () => {}) + }) + } +} + +const setNotifyBadge = () => { + // 获取未读消息数量 + RongIMLib.getTotalUnreadCount(({ + code, + count + }) => { + if (code === 0) { + // #ifdef APP-PLUS + plus.runtime.setBadgeNumber(count) + // #endif + if (count > 0) { + uni.setTabBarBadge({ + index: 3, + text: String(count > 99 ? '99+' : count) + }) + } else { + uni.removeTabBarBadge({ + index: 3 + }) + } + } + }) +} + +/** + * 连接IM服务 + * @param {string} token token + * @param {object} userInfo {userId: string, name: string, portraitUrl: string} + */ +const connect = (token, userInfo, callback) => { + RongIMLib.connect(token, res => { + console.log('连接结果', res); + + callback(res) + }) + + store.dispatch('setSenderInfo', userInfo) + + setNotifyBadge() + + const model = uni.model.friendModel + + model.find((err, results) => { + console.log('好友列表', results); + results.map(item => { + store.dispatch('updateFriends', item) + }) + }) +} + +/** + * 断开链接 + */ +const disconnect = () => { + RongIMLib.disconnect() + // 移除提醒数量 + // #ifdef APP-PLUS + plus.runtime.setBadgeNumber(0) + // #endif + uni.removeTabBarBadge({ + index: 3 + }) +} + +// 允许通知的消息类型,触发更新消息列表操作 +const notifyMsgTypes = [ + 'RC:TxtMsg', + 'RC:VcMsg', + 'RC:HQVCMsg', + 'RC:ImgMsg', + 'RC:GIFMsg', + 'RC:ImgTextMsg', + 'RC:FileMsg', + 'RC:LBSMsg', + 'RC:SightMsg', + 'RC:ReferenceMsg', + 'RC:CombineMsg', +] + +function inArray(search, array) { + for (var i in array) { + if (array[i] == search) { + return true; + } + } + return false; +} + +const addListeners = () => { + // 添加连接状态监听函数 + RongIMLib.addConnectionStatusListener((res) => { + console.log('连接状态监听', res.data.status); + uni.$emit('onConnectionStatusChange', res.data.status) + }) + // 添加消息监听函数 + RongIMLib.addReceiveMessageListener((res) => { + console.log('收到消息', res.data.message); + const message = res.data.message + if (inArray(message.objectName, notifyMsgTypes)) { + console.log('new Message'); + newMessage(message) + } + }) + // 音视频通话相关的 + // 监听通话呼入 + CallLib.onCallReceived(({ + data + }) => { + uni.navigateTo({ + url: '/pages/im/private/call?targetId=' + data.targetId + '&mediaType=' + + data.mediaType + }) + }) + // 通话建立成功 + CallLib.onCallConnected(() => { + uni.$emit('onCallConnected'); + }) + // 外呼 + CallLib.onCallOutgoing((res) => { + uni.$emit('onCallOutgoing'); + }) + // 远端响铃 + CallLib.onRemoteUserRinging((res) => { + uni.$emit('onRemoteUserRinging'); + }) + // 远端加入 + CallLib.onRemoteUserJoined((res) => { + uni.$emit('onRemoteUserJoined'); + }) + // 断开链接 + CallLib.onCallDisconnected((res) => { + console.log('断开链接', res); + uni.$emit('onCallDisconnected'); + }) + // 远端挂断 + CallLib.onRemoteUserLeft((res) => { + console.log('远端离开', res); + uni.$emit('onRemoteUserLeft'); + }) +} + +// 维护消息列表,检查是否需要通知声音,设置新消息提醒的数量 +const newMessage = (msg) => { + RongIMLib.getConversationNotificationStatus(msg.conversationType, msg.targetId, ({ + code, + status + }) => { + if (code === 0) { + if (status) { + triTone() + } + } + }); + + setNotifyBadge() + + if (!store.getters.hasUser(msg.targetId)) { + syncUserInfo(msg.targetId) + } + + uni.$emit('onReceiveMessage', msg); +} + +function syncUserInfo(targetId) { + getUserInfo(targetId).then(res => { + store.dispatch('updateFriends', res) + }) +} + +// 播放状态 +let tipState = false + +const triTone = () => { + if (tipState == false) { + const innerAudioContext = uni.createInnerAudioContext() + innerAudioContext.autoplay = true + innerAudioContext.src = '/utils/im/sounds/new-msg.mp3' + innerAudioContext.onPlay(() => { + tipState = true + }) + innerAudioContext.onEnded(() => { + tipState = false + }) + } +} + +/** + * 同步好友信息,保存头像地址等 + */ +const syncFriends = () => { + getFriends().then(res => { + res.map(item => { + console.log('item', item); + store.dispatch('updateFriends', item) + }) + }) +} + +export default { + initIm, + connect, + setNotifyBadge, + syncFriends, + syncUserInfo, + ...message } diff --git a/utils/im/message.js b/utils/im/message.js new file mode 100644 index 0000000..3e22ce4 --- /dev/null +++ b/utils/im/message.js @@ -0,0 +1,154 @@ +import store from '@/store/index.js' +import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index' +/** + * 发送文本消息 + * @param {number} conversationType 消息类型 + * @param {string} targetId 会话id + * @param {string} content 消息内容 + * @param {function} callback 回调函数 + */ +const sentText = (conversationType, targetId, content, callback) => { + console.log('发送'); + const msg = { + conversationType: conversationType, + targetId: String(targetId), + content: { + objectName: 'RC:TxtMsg', + content: content, + user: store.getters.sender + } + } + RongIMLib.sendMessage(msg, ({ + code, + messageId + }) => { + if (code === 0) { + callback(messageId) + } else { + uni.showToast({ + icon: 'none', + title: '发送失败' + }) + } + }) +} + +/** + * 发送消息 + * @param {number} conversationType 消息类型 + * @param {string} targetId 会话id + * @param {string} voiceUrl 录音的本地路径 + * @param {integer} time 录音时长 + * @param {function} callback 录音时长 + */ +const sentVoice = (conversationType, targetId, voiceUrl, time, callback) => { + const msg = { + conversationType: conversationType, + targetId: String(targetId), + content: { + objectName: 'RC:HQVCMsg', + local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl), + duration: time + } + } + RongIMLib.sendMediaMessage(msg, { + success: (messageId) => { + callback(messageId); + }, + progress: (progress, messageId) => { + console.log(messageId); + }, + cancel: (messageId) => { + // 发送取消回调 + }, + error: (errorCode, messageId) => { + console.log(errorCode, messageId); + } + }) +} + +const sentImage = (conversationType, targetId, imageUrl, time, callback) => { + const msg = { + conversationType: conversationType, + targetId: String(targetId), + content: { + objectName: 'RC:ImgMsg', + local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl), + duration: time + } + } + RongIMLib.sendMediaMessage(msg, { + success: (messageId) => { + callback(messageId); + }, + progress: (progress, messageId) => { + console.log(messageId); + }, + cancel: (messageId) => { + // 发送取消回调 + }, + error: (errorCode, messageId) => { + console.log(errorCode, messageId); + } + }) +} + +const sentGif = (conversationType, targetId, gifUrl, time, callback) => { + const msg = { + conversationType: conversationType, + targetId: String(targetId), + content: { + objectName: 'RC:GIFMsg', + local: 'file:///' + plus.io.convertLocalFileSystemURL(gifUrl), + duration: time + } + } + RongIMLib.sendMediaMessage(msg, { + success: (messageId) => { + callback(messageId); + }, + progress: (progress, messageId) => { + console.log(messageId); + }, + cancel: (messageId) => { + // 发送取消回调 + }, + error: (errorCode, messageId) => { + console.log(errorCode, messageId); + } + }) +} + +const sendFile = (conversationType, targetId, fileUrl, time, callback) => { + const msg = { + conversationType: conversationType, + targetId: String(targetId), + content: { + objectName: 'RC:FileMsg', + local: 'file:///' + plus.io.convertLocalFileSystemURL(fileUrl), + duration: time + } + } + RongIMLib.sendMediaMessage(msg, { + success: (messageId) => { + callback(messageId); + }, + progress: (progress, messageId) => { + console.log(messageId); + }, + cancel: (messageId) => { + // 发送取消回调 + }, + error: (errorCode, messageId) => { + console.log(errorCode, messageId); + } + }) +} + +export default { + sentText, + sentVoice, + sentImage, + sentGif, + sendFile +} \ No newline at end of file