1. 程式人生 > 其它 >對接騰訊雲及時通訊總結

對接騰訊雲及時通訊總結

1.在騰訊雲官網上建立應用,獲取到相應的SDKAppID和相應的祕鑰資訊。
2.可以下載官方的即時通訊例子參考官方demo進行開發。
3.使用npm安裝SDK檔案:
(1)像uni-app開發的小程式在專案之前沒有用到npm管理依賴(專案根目錄下無package.json檔案),現在專案根目錄執行命令初始化npm工程:

npm init -y

(2)安裝SDK
web專案使用命令:

// IM Web SDK
npm install tim-js-sdk --save
// 傳送圖片、檔案等訊息需要的 COS SDK
npm install cos-js-sdk-v5 --save

小程式專案使用命令:

// IM 小程式 SDK
npm install tim-wx-sdk --save
// 傳送圖片、檔案等訊息需要的 COS SDK
npm install cos-wx-sdk-v5 --save

4.在main.js中引入

import TIM from 'tim-js-sdk';
// import TIM from 'tim-wx-sdk'; // 微信小程式環境請取消本行註釋,並註釋掉 import TIM from 'tim-js-sdk';
import COS from 'cos-js-sdk-v5';
// import COS from 'cos-wx-sdk-v5'; // 微信小程式環境請取消本行註釋,並註釋掉 import COS from 'cos-js-sdk-v5';

// 建立 SDK 例項,TIM.create() 方法對於同一個 SDKAppID 只會返回同一份例項
let options = {
SDKAppID: 0 // 接入時需要將0替換為您的即時通訊應用的 SDKAppID
};
let tim = TIM.create(options); // SDK 例項通常用 tim 表示
// 設定 SDK 日誌輸出級別,詳細分級請參見 setLogLevel 介面的說明
tim.setLogLevel(0); // 普通級別,日誌量較多,接入時建議使用
// tim.setLogLevel(1); // release級別,SDK 輸出關鍵資訊,生產環境時建議使用

// 將騰訊雲物件儲存服務 SDK (以下簡稱 COS SDK)註冊為外掛,IM SDK 傳送檔案、圖片等訊息時,需要用到騰訊雲的 COS 服務
wx.$app = tim
wx.$app.registerPlugin({'cos-wx-sdk': COS})
wx.store = store
wx.TIM = TIM
wx.dayjs = dayjs
dayjs.locale('zh-cn')
let $bus = new Vue()
Vue.prototype.TIM = TIM
Vue.prototype.$type = TYPES
Vue.prototype.$store = store
Vue.prototype.$bus = $bus
// 監聽事件 收到離線訊息和會話列表同步完畢通知
tim.on(TIM.EVENT.SDK_READY, onReadyStateUpdate, this)
// 收到SDK進入not ready狀態通知,此時SDK無法正常工作
tim.on(TIM.EVENT.SDK_NOT_READY, onReadyStateUpdate, this)
// 收到被踢下線通知
tim.on(TIM.EVENT.KICKED_OUT, kickOut, this)
// 出錯統一處理
tim.on(TIM.EVENT.ERROR, onError, this)
// 收到推送的訊息,遍歷event.data獲取訊息列表資料並渲染到頁面
tim.on(TIM.EVENT.MESSAGE_RECEIVED, messageReceived, this)
// 更新會話列表
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, convListUpdate, this)
// 更新群組列表
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, groupListUpdate, this)
// 更新黑名單
tim.on(TIM.EVENT.BLACKLIST_UPDATED, blackListUpdate, this)
// 網路狀態變化
tim.on(TIM.EVENT.NET_STATE_CHANGE, netStateChange, this)
function onReadyStateUpdate ({ name }) {
const isSDKReady = (name === TIM.EVENT.SDK_READY)
if (isSDKReady) {
//使用者資訊
wx.$app.getMyProfile().then(res => {
store.commit('updateMyInfo', res.data)
uni.setStorageSync('name', res.data.nick);
console.log(name,'updateMyInfo');
})
//黑名單列表,存入vuex中
wx.$app.getBlacklist().then(res => {
store.commit('setBlacklist', res.data)
})
}
store.commit('setSdkReady', isSDKReady)
}
//被踢下線函式,被踢下線之後需要設定重新登入
function kickOut (event) {
store.dispatch('resetStore')
wx.showToast({
title: '你已被踢下線',
icon: 'none',
duration: 1500
})
setTimeout(() => {
wx.reLaunch({
url: '../account/login'
})
}, 500)
}
function onError (event) {
// 網路錯誤不彈toast && sdk未初始化完全報錯
if (event.data.message && event.data.code && event.data.code !== 2800 && event.data.code !== 2999) {
store.commit('showToast', {
title: event.data.message,
duration: 2000
})
}
}
//
function checkoutNetState (state) {
switch (state) {
case TIM.TYPES.NET_STATE_CONNECTED:
return { title: '已接入網路', duration: 2000 }
case TIM.TYPES.NET_STATE_CONNECTING:
return { title: '當前網路不穩定', duration: 2000 }
case TIM.TYPES.NET_STATE_DISCONNECTED:
return { title: '當前網路不可用', duration: 2000 }
default:
return ''
}
}
//網路狀態變化函式
function netStateChange (event) {
console.log(event.data.state)
store.commit('showToast', checkoutNetState(event.data.state))
}
//訊息收發
function messageReceived (event) {
console.log(event,'main.js');
for (let i = 0; i < event.data.length; i++) {
let item = event.data[i]
if (item.type === TYPES.MSG_GRP_TIP) {
if (item.payload.operationType) {
$bus.$emit('groupNameUpdate', item.payload)
}
}
if (item.type === TYPES.MSG_CUSTOM) {
if (isJSON(item.payload.data)) {
const videoCustom = JSON.parse(item.payload.data)
console.log(item,'首頁資訊')
if (videoCustom.version === 3) {
switch (videoCustom.action) {
// 對方呼叫我
case 0:
if (!store.getters.isCalling) {
let url = `call?args=${item.payload.data}&&from=${item.from}&&to=${item.to}&&name=`+uni.getStorageSync('name')+'&&nick='+'';
console.log(url,'url')
wx.navigateTo({url})
} else {
$bus.$emit('isCalling', item)
}
break
// 對方取消
case 1:
wx.navigateBack({
delta: 1
})
break
// 對方拒絕
case 2:
$bus.$emit('onRefuse')
break
// 對方不接1min
case 3:
wx.navigateBack({
delta: 1
})
break
// 對方接聽
case 4:
$bus.$emit('onCall', videoCustom)
break
// 對方結束通話
case 5:
$bus.$emit('onClose')
break
// 對方正在通話中
case 6:
$bus.$emit('onBusy')
break
default:
break
}
}
}
}
}
store.dispatch('onMessageEvent', event)
}
function convListUpdate (event) {
store.commit('updateAllConversation', event.data)
}

function groupListUpdate (event) {
store.commit('updateGroupList', event.data)
}

function blackListUpdate (event) {
store.commit('updateBlacklist', event.data)
}


5.在store檔案中匯入conversation.js和user.js,global.js用於快取更新會話和使用者資訊
conversation.js檔案:

import {
formatTime
} from '../../utils/index'
import {
decodeElement
} from '../../utils/decodeElement'
import TIM from 'tim-wx-sdk'

const conversationModules = {
state: {
allConversation: [], // 所有的conversation
currentConversationID: '', // 當前聊天對話ID
currentConversation: {}, // 當前聊天對話資訊
currentMessageList: [], // 當前聊天訊息列表
nextReqMessageID: '', // 下一條訊息標誌
isCompleted: false, // 當前會話訊息是否已經請求完畢
isLoading: false // 是否正在請求
},
getters: {
allConversation: state => state.allConversation,
// 當前聊天物件的ID
toAccount: state => {
if (state.currentConversationID.indexOf('C2C') === 0) {
return state.currentConversationID.substring(3)
} else if (state.currentConversationID.indexOf('GROUP') === 0) {
return state.currentConversationID.substring(5)
}
},
// 當前聊天物件的暱稱
toName: state => {
if (state.currentConversation.type === 'C2C') {
return state.currentConversation.userProfile.userID
} else if (state.currentConversation.type === 'GROUP') {
return state.currentConversation.groupProfile.name
}
},
// 當前聊天對話的Type
currentConversationType: state => {
if (state.currentConversationID.indexOf('C2C') === 0) {
return 'C2C'
}
if (state.currentConversationID.indexOf('GROUP') === 0) {
return 'GROUP'
}
return ''
},
currentConversation: state => state.currentConversation,
currentMessageList: state => state.currentMessageList,
totalUnreadCount: state => {
const result = state.allConversation.reduce((count, {
unreadCount
}) => count + unreadCount, 0)
if (result === 0) {
wx.removeTabBarBadge({
index: 1 //用於設定未讀訊息的tabbar
})
} else {
wx.setTabBarBadge({
index: 1,
text: result > 99 ? '99+' : String(result)
})
}
return result
}
},
mutations: {
// 歷史頭插訊息列表
// 小程式問題,在渲染的時候模板引擎不能處理函式,所以只能在渲染前處理好message的展示問題
unshiftMessageList(state, messageList) {
let list = [...messageList]
for (let i = 0; i < list.length; i++) {
let message = list[i]
list[i].virtualDom = decodeElement(message)
let date = new Date(message.time * 1000)
list[i].newtime = formatTime(date)
}
state.currentMessageList = [...list, ...state.currentMessageList]
},
// 收到
receiveMessage(state, messageList) {
let list = [...messageList]
for (let i = 0; i < list.length; i++) {
let message = list[i]
list[i].virtualDom = decodeElement(message)
let date = new Date(message.time * 1000)
list[i].newtime = formatTime(date)
}
state.currentMessageList = [...state.currentMessageList, ...list]
},
sendMessage(state, message) {
message.virtualDom = decodeElement(message)
let date = new Date(message.time * 1000)
message.newtime = formatTime(date)
state.currentMessageList.push(message)
setTimeout(() => {
wx.pageScrollTo({
scrollTop: 99999
})
}, 800)
},
// 更新當前的會話
updateCurrentConversation(state, conversation) {
state.currentConversation = conversation
state.currentConversationID = conversation.conversationID
},
// 更新當前所有會話列表
updateAllConversation(state, list) {
for (let i = 0; i < list.length; i++) {
if (list[i].lastMessage && (typeof list[i].lastMessage.lastTime === 'number')) {
let date = new Date(list[i].lastMessage.lastTime * 1000)
list[i].lastMessage._lastTime = formatTime(date)
}
}
state.allConversation = list //allConversation是所有的會話資訊
console.log(list, '會話快取')
},
// 重置當前會話
resetCurrentConversation(state) {
state.currentConversationID = '' // 當前聊天對話ID
state.currentConversation = {} // 當前聊天對話資訊
state.currentMessageList = [] // 當前聊天訊息列表
state.nextReqMessageID = '' // 下一條訊息標誌
state.isCompleted = false // 當前會話訊息是否已經請求完畢
state.isLoading = false // 是否正在請求
},
resetAllConversation(state) {
state.allConversation = []
},
removeMessage(state, message) {
state.currentMessageList.splice(state.currentMessageList.findIndex(item => item.ID === message.ID), 1)
},
changeMessageStatus(state, index) {
state.currentMessageList[index].status = 'fail'
}
},
actions: {
// 訊息事件
onMessageEvent(context, event) {
if (event.name === 'onMessageReceived') {
let id = context.state.currentConversationID
if (!id) {
return
}
let list = []
event.data.forEach(item => {
if (item.conversationID === id) {
list.push(item)
}
})
context.commit('receiveMessage', list)
}
},
// 獲取訊息列表
getMessageList(context) {
const {
currentConversationID,
nextReqMessageID
} = context.state
// 判斷是否拉完了,isCompleted 的話要報一下沒有更多了
if (!context.state.isCompleted) {
// 如果請求還沒回來,又拉,此時做一下防禦
if (!context.state.isLoading) {
context.state.isLoading = true
wx.$app.getMessageList({
conversationID: currentConversationID,
nextReqMessageID: nextReqMessageID,
count: 15
}).then(res => {
context.state.nextReqMessageID = res.data.nextReqMessageID
context.commit('unshiftMessageList', res.data.messageList)
if (res.data.isCompleted) {
context.state.isCompleted = true
}
context.state.isLoading = false
}).catch(err => {
console.log(err)
})
} else {
wx.showToast({
title: '你拉的太快了',
icon: 'none',
duration: 500
})
}
} else {
wx.showToast({
title: '沒有更多啦',
icon: 'none',
duration: 1500
})
}
},
checkoutConversation(context, conversationID) {
context.commit('resetCurrentConversation')
wx.$app.setMessageRead({
conversationID
})
return wx.$app.getConversationProfile(conversationID)
.then(({
data: {
conversation
}
}) => {
context.commit('updateCurrentConversation', conversation)
context.dispatch('getMessageList')
let name = ''
switch (conversation.type) {
case TIM.TYPES.CONV_C2C:
name = conversation.userProfile.nick || conversation.userProfile.userID
break
case TIM.TYPES.CONV_GROUP:
name = conversation.groupProfile.name || conversation.groupProfile.groupID
break
default:
name = '系統通知'
}
wx.navigateTo({
url: `chat?toAccount=${name}&type=${conversation.type}`
})
return Promise.resolve()
})
},
checkoutConversationOther(context, conversationID) {
context.commit('resetCurrentConversation')
wx.$app.setMessageRead({
conversationID
})
return wx.$app.getConversationProfile(conversationID)
.then(({
data: {
conversation
}
}) => {
context.commit('updateCurrentConversation', conversation)
context.dispatch('getMessageList')
let name = ''
switch (conversation.type) {
case TIM.TYPES.CONV_C2C:
name = conversation.userProfile.nick || conversation.userProfile.userID
break
case TIM.TYPES.CONV_GROUP:
name = conversation.groupProfile.name || conversation.groupProfile.groupID
break
default:
name = '系統通知'
}
//跳轉到訊息聊天介面,傳遞引數聊天物件和聊天型別
wx.navigateTo({
url: `../../news/chat?toAccount=${name}&type=${conversation.type}`
})
return Promise.resolve()
})

}

}
}

export default conversationModules


global.js檔案
主要用到監聽sdk的狀態

const globalModules = {
state: {
isSdkReady: false,
isCalling: false,
systemInfo: null
},
getters: {
isSdkReady: state => state.isSdkReady,
isCalling: state => state.isCalling,
isIphoneX: state => state.systemInfo && state.systemInfo.model.indexOf('iPhone X') > -1
},
mutations: {
showToast (state, payload) {
wx.showToast({
title: payload.title,
icon: payload.icon || 'none',
duration: payload.duration || 800
})
},
setSdkReady (state, payload) {
state.isSdkReady = payload
},
setCalling (state, payload) {
state.isCalling = payload
},
setSystemInfo (state, payload) {
state.systemInfo = payload
}
},
actions: {
resetStore (context) {
context.commit('resetGroup')
context.commit('resetUser')
context.commit('resetCurrentConversation')
context.commit('resetAllConversation')
}
}
}

export default globalModules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
user.js用於存放使用者資訊

const userModules = {
state: {
myInfo: {},
userProfile: {},
blacklist: []
},
getters: {
myInfo: state => state.myInfo,
userProfile: state => state.userProfile
},
mutations: {
updateMyInfo (state, myInfo) {
state.myInfo = myInfo
},
updateUserProfile (state, userProfile) {
state.userProfile = userProfile
},
setBlacklist (state, blacklist) {
state.blacklist = blacklist
},
updateBlacklist (state, blacklist) {
state.blacklist.push(blacklist)
},
resetUser (state) {
state.blacklist = []
state.userProfile = {}
state.myInfo = {}
}
}
}

export default userModules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
要注意在index.js中匯出這麼模組

其餘的vue程式碼不多做描述,到時候直接看原始碼。
————————————————

原文連結:https://blog.csdn.net/weixin_45442630/article/details/107819821