本例主要介绍在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 IMController
sdk(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);
}
});