网易信im对接web端!

概述

最近跟朋友做了一个小程序项目,用到了即时通讯,选择了网易信Im即时通讯,不得不说,网易信的文档写的相当不友好,文档链接:https://dev.yunxin.163.com/docs/product/IM%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/%E6%96%B0%E6%89%8B%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97

谁看谁懵逼。。。

长话短说,进入正题。

介绍:这里对接是小程序sdk版本

第一步
先去注册网易信账号建立应用,拿到appKey ,appSecret。理解为小程序的appid就OK,应用唯一标识码

const appKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const appSecret = "xxxxxxxxxxxx"

export default {
    appKey,
    appSecret
}

第二步
先把demo拷贝下来,看看代码,这个真的要看看,很有帮助,地址:https://dev.yunxin.163.com/docs/product/IM%E5%8D%B3%E6%97%B6%E9%80%9A%E8%AE%AF/SDK%E5%BC%80%E5%8F%91%E9%9B%86%E6%88%90/Web%E5%BC%80%E5%8F%91%E9%9B%86%E6%88%90/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F

第三步
把文档过一遍,不理解跟着我往下看

第四步
去控制台打开自己的账号建立几个IM账户,注意这里是纯前端实现,IM用户体系来自网易信数据库,不通过我们自己的服务端后台,记住账户和密码用来测试的
然后跟我写下面代码试试

import config from '@/im/config.js'
let orderCounter=1

class IMController {
    constructor(headers) {
        this.onConnect = this.onConnect.bind(this)

        /* 初始化SDk */
        app.globalData.nim = NIM.getInstance({
            // debug: true,
            db: false, // 小程序不支持数据库
            syncSessionUnread: true, // 同步会话的未读数
            autoMarkRead: false, // 不开启自动标记消息已读 此时服务器下推的所有离线消息算未读,漫游消息算已读
            appKey: config.appKey, // 在云信管理后台查看应用的 appKey
            token: headers.token, // 帐号的唯一标识, 用于建立连接
            account: headers.account, // 帐号, 应用内唯一
            onconnect: this.onConnect, // 连接成功
        })
    }
    /** 1 abnormal closure
     * 连接成功
     */
    onConnect() {
        console.log(orderCounter++, '连接成功: ')
        console.log(app.globalData.nim)
    }
}

const appNim=new IMController({
    token: '测试账号密码',
    account: ‘测试账号’
})

//下面是一段发送消息的方法
// 他人account
let to = this.otherParam.account
let text='测试消息'
appNim.sendText({
  scene: 'p2p',
  to,
  text,
  done: (err, msg) => {
    console.log('发送文本消息回调')
    console.log(err)
    console.log(msg)
  }
})

这样一个Im账号登录连接就成功了,你可以把im类放在全局对象上以便使用,请继续看下代码,它只是一个消息Mock

// 这里我只介绍几个重点的字段及状态,
/*
* @param {string} flow  发送方 (‘out’=>自己)  and (‘in’ =>他人)
* @param {string} fromNick 目标名称
* @param {string} scene 聊天类型 ‘p2p’ 点对点
* @param {string} to 发送者账户
* @param {string} sessionId 会话id
* @param {number} time 发送时间
* 
*/
export default {
    cc: true,
    flow: "out",
    from: "19b82a32aa30c50fc4c943ff398dfcae",
    fromClientType: "Web",
    fromDeviceId: "f1cbf57270cfe916c270a842085ce75a",
    fromNick: "woshichunlogn",
    idClient: "0376a3107b0d200744be4c87523b7838",
    idServer: "306034218126",
    isHistoryable: true,
    isLocal: false,
    isOfflinable: true,
    isPushable: true,
    isReplyMsg: true,
    isRoamingable: true,
    isSyncable: true,
    isUnreadable: true,
    needMsgReceipt: false,
    needPushNick: true,
    resend: false,
    scene: "p2p",
    sessionId: "p2p-dc46c6ede64c2c7595f0246e8cd146a7",
    status: "success",
    target: "dc46c6ede64c2c7595f0246e8cd146a7",
    text: "fasf",
    time: 1566653977065,
    to: "dc46c6ede64c2c7595f0246e8cd146a7",
    type: "text",
    userUpdateTime: 1566543003373,
}

看了各项字段应该已经猜到对应的什么了吧,如text消息文案,time发送时间,scene点对点,等等,也可以自己去看看文档。
这里我要讲重点

离线消息与漫游消息

离线消息只能拿到他人的消息列,漫游消息需要在后台管理开启漫游,不然我们是拿不到漫游消息的,漫游消息指的是自己最近发送的消息列,当然会有本地库存储的,但是小程序里是不支持本地数据库的,当然我也是第一次对接,现在我的理解是这样,如有错误请指出。

会话

会话指的是你最近跟某个用户产生的一次对话,他是有消息输出的,如QQ会话列表,千万不要把会话跟消息弄混淆了,会话包括消息或多个消息

第五步
看到这里,你也大概了解这个流程是怎么建立的,你现在首要的任务是,写好UI界面,然后把我上面登录的方法调通,然后用实例发送一个消息,看看真实的数据,在把官方给的demo模板里的回调方法一个一个抽出来,我把我的例子放出来如下,有些方法和模块搜不到你不用管,因为这个都是逻辑层,自己懂了之后,每个人才会有自己的实现方式,当然我用的uni.app里的vuex....

import NIM from '@/vendors/NIM_Web_NIM_weixin_v6.7.0.js'
import NetcallController from './netcall.js'
import config from '@/im/config.js'
import store from '@/api/request/store/home.js' // 删除本地缓存
import common from '@/common/common.js'
import { hexMD5, utf8 } from '@/utils/md5-utf8'

let app = getApp()

let orderCounter = 1
export default class IMController {
    constructor(headers) {
        // vuex对象赋给im类
        this.store = headers.$store

        this.onConnect = this.onConnect.bind(this)
        this.onSessions = this.onSessions.bind(this)
        this.onMsg = this.onMsg.bind(this)
        this.onRoamingMsgs = this.onRoamingMsgs.bind(this)
        this.onUpdateSession = this.onUpdateSession.bind(this)
        this.onOfflineMsgs = this.onOfflineMsgs.bind(this)
        this.onMyInfo = this.onMyInfo.bind(this)

        /* 初始化SDk */
        app.globalData.nim = NIM.getInstance({
            // debug: true,
            db: false, // 小程序不支持数据库
            syncSessionUnread: true, // 同步会话的未读数
            autoMarkRead: false, // 不开启自动标记消息已读 此时服务器下推的所有离线消息算未读,漫游消息算已读
            appKey: config.appKey, // 在云信管理后台查看应用的 appKey
            token: headers.token, // 帐号的唯一标识, 用于建立连接
            account: headers.account, // 帐号, 应用内唯一
            onconnect: this.onConnect, // 连接成功
            onwillreconnect: this.onWillReconnect, // 断开重连
            ondisconnect: this.onDisconnect, // 丢失连接
            onerror: this.onError, // onError
            /* 收到onconnect后,链接已经建立(登录成功), SDK会开始同步数据, 在收到onsyncdone回调后表示SDK完成了数据同步工作, 此时开发者可以进行渲染 UI 等操作了。*/
            onsyncdone: this.onSyncDone,
            // 用户名片
            onmyinfo: this.onMyInfo, // 同步登录用户资料的回调, 会传入用户资料
            // onupdatemyinfo: this.onUpdateMyInfo, // 当前登录用户在其它端修改自己的个人名片之后的回调, 会传入用户资料
            onusers: this.onUsers, //  同步好友用户资料的回调, 会传入用户资料数组 此回调是增量回调, 可以调用nim.mergeUsers来合并数据
            // onupdateuser: this.onUpdateUser, //  用户资料更新后的回调, 会传入用户资料,请参考用户资料更新时机
            // // 机器人列表的回调
            // onrobots: this.onRobots, // 机器人列表事件
            // // 会话
            onsessions: this.onSessions, // 同步最近会话列表回调, 会传入会话列表, 按时间正序排列, 即最近聊过天的放在列表的最后面 此回调是增量回调, 可以调用nim.mergeSessions来合并数据
            onupdatesession: this.onUpdateSession, // 更新会话的回调, 会传入会话对象, 以下情况会收到此回调 收到消息 发送消息 设置当前会话 重置会话未读数
            // // 消息
            onroamingmsgs: this.onRoamingMsgs, // 漫游消息, 对应回调
            onofflinemsgs: this.onOfflineMsgs, // 离线消息, 对应回调 
            onmsg: this.onMsg, // 收到消息
            // // 系统通知
            // onofflinesysmsgs: this.onOfflineSysMsgs, // 同步离线系统通知的回调, 会传入系统通知数组
            // onsysmsg: this.onSysMsg, // 收到系统通知的回调, 会传入系统通知
            // onsysmsgunread: this.onSysMsgUnread, // 收到系统通知未读数的回调
            // onupdatesysmsgunread: this.onUpdateSysMsgUnread, // 更新系统通知未读数的回调
            // onofflinecustomsysmsgs: this.onOfflineCustomSysMsgs, //  同步离线自定义系统通知的回调, 会传入系统通知数组
            // oncustomsysmsg: this.onCustomSysMsg, // 收到自定义系统通知的回调, 会传入系统通知
            // // 收到广播消息
            // onbroadcastmsg: this.onBroadcastMsg,
            // onbroadcastmsgs: this.onBroadcastMsgs,
            // // 事件订阅
            // onpushevents: this.onPushEvents,
        })
        // 发送消息开始登陆
        // store.dispatch({
        //  type: 'Login_StartLogin'
        // })
    }
    /** 1 abnormal closure
     * 连接成功
     */
    onConnect() {
        console.log(orderCounter++, '连接成功: ')
        console.log(app.globalData.nim)
        app.globalData.netcallController = new NetcallController({
            // debug: false,
            debug: true,
            nim: app.globalData.nim,
            store: this.store
        })
    }
    /**
     * 连接出错
     */
    onError(error) {
        console.log('连接出错')
        common.msgHint()

        toLogin()
    }
    /**
     * 此时说明 SDK 处于断开状态, 开发者此时应该根据错误码提示相应的错误信息, 并且跳转到登录页面
     */
    onDisconnect(error) {
        console.log('丢失连接');
        if (error) {
            switch (error.code) {
                // 账号或者密码错误, 请跳转到登录页面并提示错误
                case 302:
                    common.msgHint({
                        title: 'im的账户或密码错误,需重新登录'
                    })
                    toLogin()
                    break;
                    // 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误
                case 417:
                    common.msgHint({
                        title: '已经在其它端登录了'
                    })

                    toLogin()
                    break;
                    // 被踢, 请提示错误后跳转到登录页面
                case 'kicked':
                    common.msgHint({
                        title: '你被一名用户踢了'
                    })

                    toLogin()
                    break;
                default:
                    break;
            }
        }
    }
    /** 1 abnormal closure
     * 断线重连
     */
    onWillReconnect(obj) {
        // 此时说明 SDK 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
        console.log('断线重连');
        common.msgHint({
            title: '断线重连中,请稍后!',
            duration: 3000
        })
    }
    /** 6
     * 个人名片:存储个人信息到全局数据
     */
    onMyInfo(user) {
        console.log(orderCounter++, ' 个人信息: ')
        console.log(user)
        if (user) {
            this.store.commit('setMyImData', user)
        }
    }
    /** 7
     * 包含名片的好友信息(可能某些字段不全),[{account,avatar,birth,createTime,email,gender,nick,sign,updateTime}]
     */
    onUsers(friends) {
        console.log(orderCounter++, ' 好友信息: ')
        console.log(friends)
    }
    /** 9
     * 同步完成
     */
    onSyncDone() {
        console.log(orderCounter++, '同步完成')
    }
    /**会话
     * [ {id:"p2p-liuxuanlin",lastMsg:{from:'wujie',text:'222',to:"liuxuanlin"}} ]
     */
    onSessions(session) {
        console.log('会话: ')
        console.log(session)
        if (session) {
            // 会话列表
            let chatList = JSON.parse(JSON.stringify(this.store.state.chatList || []))
            // 合并会话列表
            let list = app.globalData.nim.mergeSessions(chatList, session);
        }
    }
    /**
     * 会话更新:收到消息、发送消息、设置当前会话、重置会话未读数 触发
     * {id:'p2p-zys2',lastMsg:{},scene,to,unread,updateTime}
     * {id:'team-1389946935',lastMsg:{attach:{accounts,team},type,users},scene,to,from,type,unread,updateTime}
     */
    onUpdateSession(session) {
        console.log('会话更新: ', session)
        if (session) {
            // 更新会话列表
            app.globalData.netcallController.mergeChatList(session)
        }
    }
    /**
     * 收到消息
     * {cc,flow:"in",from,fromClientType:"Web",fromDeviceId,fromNick,idClient,idServer:"9680840912",isHistoryable:true,isLocal,isMuted, isOfflinable,isPushable,isRoamingable,isSyncable,isUnreadable,needPushNick,resend,scene:"p2p",sessionId:"p2p-zys2",status:"success",target:"zys2",text:"[呕吐]",time,to:"wujie",type:"text",userUpdateTime}
     */
    onMsg(msg) {
        console.log('收到消息', msg.scene, msg.type);
        console.log(msg);
        if (msg) {
            // 更新消息列表
            app.globalData.netcallController.mergeMsg(msg)
        }
    }
    /**
     * 漫游消息:会多次收到,每次只会收到指定人的漫游消息
      // {scene:"p2p",sessionId:"p2p-cs4",timetag:1513153729257,to:"cs4",msg:[{from:'wujie',text:'222',to:'cs4'}]}
      // {scene:"team",sessionId:"team-3944051",timetag:1513153729257,to:"3944051",msg:[{from:'wujie',text:'222',to:'cs4'}]}
     */
    onRoamingMsgs(session) {
        console.log(orderCounter++, ' 漫游消息')
        console.log(session)

        if (session) {
            // 合并漫游消息列表
            app.globalData.netcallController.mergeMsgList(session)
        }
    }
    /**
     * 会话离线消息 拿到每条会话的消息列表
     */
    onOfflineMsgs(session) {
        console.log(orderCounter++, ' 会话离线消息')
        console.log(session)

        if (session) {
            // 合并离线消息列表
            app.globalData.netcallController.mergeMsgList(session)
        }
    }
}


let toLogin = res => {
    setTimeout(() => {
        // 删除本地缓存
        store.clear()
        uni.reLaunch({
            url: '/pages/login/index'
        })
    }, 1000)
}

我是个懒人,~~喜欢把知识放在脑子里,写了这么多累了,有什么需要咨询的可以私信给我哦,bey

你可能感兴趣的:(网易信im对接web端!)