• 对接腾讯云及时通讯总结


    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

  • 相关阅读:
    大数据概述
    递归下降语法分析
    消除左递归c语言文法
    自动转换机
    简单的C语言文法
    实验报告一 词法分析程序
    组合数据类型练习
    Python绘制五星红旗
    熟悉常用Linux操作
    大数据概述
  • 原文地址:https://www.cnblogs.com/shxd/p/16249264.html
Copyright © 2020-2023  润新知