本例主要介绍在uniapp中使用网易云信IM聊天教程,使用其他IM的可以参考,在对接云信IM聊天的过程中,以下几点请注意:
- IM聊天历史聊天记录查询是以时间段为查询条件
 - 初始化聊天时,离线消息优先级要高于漫游消息
 - 多端登录和多账号切换建议谨慎处理
 
使用示例:
一、下载SDK ,其它端可根据需要选择
NIM_Web_NIM_weixin_v6.9.0.js
NIM_Web_Netcall_weixin_v6.8.0.js(音视频SDK暂不需要)
(微信小程序SDK)
二、创建目录
我的存放位置
components>NIM
config>index,js
// IM 初始化配置
export let config = {
    debug: false,
    appKey: '',//配置自己的appKey
};controller>im.js
//引入配置文件
import NetcallWeixin from '../sdk/NIM_Web_Netcall_weixin_v6.8.0.js'
import NIM from '../sdk/NIM_Web_NIM_weixin_v6.8.0.js'
import store from '@/store/index.js'
import { config } from '../config/index.js'
//创建IM实例
// im实例
class IMController {
    constructor(props) {
        let nim = NIM.getInstance({
            promise: true,
            transports: ['websocket'],
            syncSessionUnread: true, // 同步未读数
            syncFriends: false, // 是否同步好友列表
            autoMarkRead: false,
            ...nimConfig,
            ...props,
            onconnect: this.onConnect,
            onwillreconnect: this.onWillReconnect,
            ondisconnect: this.onDisConnect,
            onerror: this.onError,
            onloginportschange: this.onLoginPortsChange,
            //onsessions: this.onSessions,
            onupdatesession: this.onUpdateSession,
            onmsg: this.onMsg,
            onroamingmsgs: this.onRoamingMsgs // 漫游消息
            onsyncdone:this.onSyncDone, //同步消息完成
        })
        store.commit('setNim', nim)
    }
    // 连接成功
    onConnect(data) {
        const { nim } = store.state.nim
    }
    // 即将重连的回调
    onWillReconnect(data) {
        console.log('即将重连的回调 ===>  ', data)
    }
    // 断开连接后的回调
    onDisConnect(data) {
        console.log('断开连接后的回调 ===>  ', data)
        switch (data.code) {
            case 'kicked':
                console.log('您的账号在别的地方登陆, 是否重新登陆')
                break;
            case '':
                break;
            default:
                break;
        }
    }
    // 发生错误的回调
    onError(error) {
        console.log('发生错误的回调 ===>  ', error)
    }
    // 多端登录状态变化的回调
    onLoginPortsChange(data) {
        console.log('多端登录状态变化的回调 ===>  ', data)
    }
    // 同步最近会话列表回调
    onSessions(data) {
        console.log('同步最近会话列表回调 ===>  ', data)
        if(Object.keys(store.state.nim.rawMessageList).length == 0){
            let list = {
                to:data[0].to,
                msgs:[],
            };
            data.map(item =>{
                list.msgs.push(item.msgs)
            })
        }else{
            data.map(item => {
                item.lastMsg.cntype = 1
                store.commit('addMsgsItem', item.lastMsg)
            })
        }
    }
    // 更新会话的回调
    onUpdateSession(data) {}
    // 同步离线消息的回调
    onofflinemsgs(data) {
        console.log('同步离线消息的回调 ===>  ', data)
        store.commit('addOfflinemsgs', data)
    }
    // 漫游消息
    onRoamingMsgs(data) {
        console.log('漫游消息', data)
        store.commit('addRoamingMsgs', data);
    }
    // 收到消息的回调
    onMsg(data) {
        console.log(data,'00000')
        data.cntype = 2
        store.commit('addMsgsItem', data)
    }
    onSyncDone(){
        console.log('同步完成,跳转聊天界面')
        uni.navigateTo({
            url:'/pages/doctor/chat/chat',
        })
    }
export default IMControllersdk(sdk存放位置)
store>nim>index.js (供参考)
export default {
  state: {
    isInit:‘’,
    nim: {},
    messageList: [], // 所有的聊天,
    nmsgs:[],//初始化后的所有聊天
  },
  getters: {},
  actions: {},
  mutations: {
    // 设置Nim实例
    setNim: function(state, value) {
      state.nim = value
    },
    //添加离线消息
    addOfflinemsgs:function(state,props){
        props.msgs.map(item=>{
            state.messageList.push(item)
        })
    },
    //添加漫游消息
    addRoamingMsgs:function(state,props){
        props.msgs.map(item=>{
            state.messageList.push(item)
        })
    },
    //添加消息
    addMsgsItem:function(state,msg){
        state.messageList.push(msg)
    },
  },
}初始化聊天
在需要的位置添加(App.vue OnLaunch() 或者在切换账号的位置添加)
_init(account){
    this.$store.state.nim.nmsgs = []; //清空消息记录
    uni.showLoading({
        title:'正在初始化聊天,请稍等',
        icon:'none',
    })
    //此处需要请求后台接口初始化聊天信息
    let data = responseData; //假设data为接口返回信息,具体可参考云信官方文档,此处主要获取accid和token
    // 初始化im聊天
    new IMController({
        account: data.accid,
        token: data.token
    });
    this.$store.state.nim.isInit = account // 保存聊天初始化情况
},聊天界面,可以使用插件市场上的聊天组件也可以选择自己封装一套
如果使用scroll-view处理聊天内容,web界面下不会自动向上滚动,小程序和app没问题
初始化时动态设置聊天窗口大小
const res = uni.getSystemInfoSync();
this.style.pageHeight = res.windowHeight;
this.style.contentViewHeight = res.windowHeight - res.screenWidth / 750 * (100);自动化滚动到底部代码
// 滚动至聊天底部
scrollToBottom() {
    let that = this
    let query = uni.createSelectorQuery()
    query.select('#scrollview').boundingClientRect()
    query.select('#content').boundingClientRect() //聊天组件外部框
    query.exec((res) => {
        console.log(res)
        if(res[0] !=null && res[1] !=null){
        that.scrollTop = res[1].height
        }
    })
},如果使用第三方,可以直接跳过
聊天消息信息渲染(根据不同的type类型渲染聊天界面,参考消息发送)
computed: {
    ...mapState({ messageList:state => state.nim.messageList })
},
watch:{
    messageList: function(val,nval){
        let len = this.messageList.length;
        if(this.messageList[len-1].type == 'custom'){
            this.messageList[len-1].content = JSON.parse(this.messageList[len-1].content)
        }
        this.msgs.push(this.messageList[len-1])
        this.scrollToBottom()
    },
},
onLoad(){
    let messageList = this.messageList;
    let mmsgs = this.mmsgs;
    for(let i in messageList){
        if(messageList[i].from == this.account){
            mmsgs.push(messageList[i])
        }
    }
    console.log('初始化后的消息',mmsgs)
    //合并消息
    this.scrollToBottom()//数据加载完成之后滚动到底部
}消息收发(建议参考官方文档)
//获取历史消息
nim.getHistoryMsgs({
    to:self.account,
    scene: 'p2p',
    beginTime:start, //开始时间
    endTime:end,//结束时间
    reverse: true,
    done: (err, list) => {
        if(list.msgs.length>0){
            let data = list.msgs.reverse();
            self.hmsgs = data
        }
    }
})
//文字消息
nim.sendText({
    scene: 'p2p',
    to: account,
    text: text,
    isHistoryable:true,
    done: (err, msg) => {
        _this.$store.commit('addMsgsItem', msg);//添加消息
        _this.text = '';
    }
})
//图片消息
nim.sendFile({
    type: 'image',
    scene:'p2p',
    to: account,
    filePath:tempFilePaths[i],
    //wxFilePath: tempFilePaths[i],
    done: (err, msg) => {
        self.$store.commit('addMsgsItem', msg);
    }
})
//音频消息
nim.sendFile({
    scene: 'p2p',
    to: account,
    type: 'audio',
    filePath:res.tempFilePath,
    //blob:res.tempFilePath,
    //wxFilePath: res.tempFilePath,
    done: (err,msg) => {
        self.$store.commit('addMsgsItem', msg);
    }
});
//自定义
nim.sendCustomMsg({
    scene: 'p2p',
    to: account,
    content: JSON.stringify('测试'),
    done: (err, msg) => {
        self.$store.commit('addMsgsItem', msg);
    }
});