对接腾讯云及时通讯总结

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

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

要注意在index.js中导出这么模块
在这里插入图片描述
其余的vue代码不多做描述,到时候直接看源码。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值