本人用的是环信
首先要去环信后台里注册测试账号,替换WebIMConfig.js里的地址。
下载环信demo后,将newSDK文件放到根目录下,WebIM.js和WebIMConfig.js本人放到了utils目录下。
在APP.vue文件中,抄案例。 文本消息,自定义消息,会话已读的回调里有未注释的逻辑,先注掉,等到处理消息时再用。
<script>
import { imLogin } from "@/utils/utils.js";
//全局注册一个变量
let WebIM = (wx.WebIM = require("./utils/WebIM")["default"]);
export default {
globalData: {
conn: {
closed: false,
curOpenOpt: {},
open(opt) {
uni.showLoading({
title: "正在初始化客户端..",
mask: true,
});
// debugger
this.curOpenOpt = opt;
this.closed = false;
},
reopen() {
if (this.closed) {
WebIM.conn.open(this.curOpenOpt);
this.closed = false;
}
},
},
},
onShow(){
//切换APP或者息屏再开启,导致im断联,所以要在这里登录一下
console.log("imshow")
this.imLogin()
},
onLaunch() {
WebIM.conn.listen({
onOpened: function() {
}, //连接成功回调
onClosed: function() {
// 不能登录,在此登录可能会陷入循环登录与退出
// that.imLogin()
}, //连接关闭回调
onTextMessage: function(message) {
console.log(message)
if (message) {
store.dispatch("setMsg", message);
console.log(message)
}
}, //收到文本消息
onEmojiMessage: function(message) {}, //收到表情消息
onPictureMessage: function(message) {}, //收到图片消息
onCmdMessage: function(message) {}, //收到命令消息
onAudioMessage: function(message) {}, //收到音频消息
onLocationMessage: function(message) {}, //收到位置消息
onFileMessage: function(message) {}, //收到文件消息
onCustomMessage: function(message) {
store.dispatch("setMsg", message);
console.log(message)
}, //收到自定义消息
onVideoMessage: function(message) {
}, //收到视频消息
onPresence: function(message) {}, //处理“广播”或“发布-订阅”消息,如联系人订阅请求、处理群组、聊天室被踢解散等消息
onRoster: function(message) {}, //处理好友申请
onInviteMessage: function(message) {}, //处理群组邀请
onOnline: function(message) {
console.log(message)
}, //本机网络连接成功
onOffline: function() {
console.log(message)
WebIM.conn.close()
this.imLogin()
}, //本机网络掉线
onError: function(error) {
console.log(error)
}, //失败回调
onBlacklistUpdate: function(list) { //黑名单变动
// 查询黑名单,将好友拉黑,将好友从黑名单移除都会回调这个函数,list则是黑名单现有的所有好友信息
console.log(list);
},
onRecallMessage: function(message) {}, //收到撤回消息回调
onReceivedMessage: function(message) {
console.log(message)
}, //收到消息送达服务器回执
onDeliveredMessage: function(message) {
console.log(message)
}, //收到消息送达客户端回执
onReadMessage: function(message) {}, //收到消息已读回执
onCreateGroup: function(message) {}, //创建群组成功回执(需调用createGroupNew)
onMutedMessage: function(message) {}, //如果用户在A群组被禁言,在A群发消息会走这个回调并且消息不会传递给群其它成员
onChannelMessage: function(message) {
console.log(message)
let msg = {
contentsType:"isRead",
id:message.from
}
store.dispatch("setMsg", msg);
} //收到整个会话已读的回执,在对方发送channel ack时会在这个回调里收到消息
});
}
}
</script>
1.登录
建议封装成函数,因为im会中途断开,后续很多地方需要用到登录。
在APP登录成功之后,调用环信登录
// 环信密码登录
export const imLoginPassword = function imLoginPassword(uid) {
uni.WebIM.conn.open({
appKey: "1122230110163975#inliao",
pwd: "password",
user: uid,
success: (res) => {
const {
access_token
} = res
uni.setStorageSync('imToken', access_token)
}
});
};
// 环信token登录
export const imLogin = function imLogin() {
let uid = uni.getStorageSync('userUuid')
if (uid) {
console.log(uid)
uni.WebIM.conn.open({
appKey: "1122230110163975#inliao",
accessToken: uni.getStorageSync('imToken'),
user: uid,
success: (res) => {
const {
access_token
} = res
uni.setStorageSync('imToken', access_token)
}
});
}
};
2.发消息
测试代码:
//创建消息
let msg = uni.WebIM.message.create({
type: "txt",
// 消息内容。
// msg: this.chatContent,
msg: "11111",
// 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。
to: '123', //测试时可以写死
// 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`,默认为单聊。
chatType: "singleChat",
});
//发送消息
uni.WebIM.conn.send(msg).then((e) => {
console.log("Send message success", e);
})
.catch((e) => {
console.log("send error")
});
发消息时,im可能已经断联,会导致消息发不出去,在catch里监听发送错误码,然后重发。
imSend(msg){
uni.WebIM.conn
.send(msg)
.then((e) => {
console.log("Send message success", e);
})
.catch((e) => {
// 重新登录
if (e.type == 39) {
imLogin()
let timer33 = setTimeout(()=>{
clearTimeout(timer33)
this.imSend(msg,messageList)
},3000)
return
}
// 重新登录 510断开连接
if (e.type == 510) {
console.log(510)
imLogin()
let timer33 = setTimeout(()=>{
clearTimeout(timer33)
this.imSend(msg,messageList)
},3000)
return
}
});
},
3.收消息
思路:app.vue里收到消息后,在vuex里处理:存储的消息内容根据具体情况。只是提供一种处理思路。
state: {
//聊天列表
xiaoxiliebiao: [],
//消息内容(每个人的聊天内容)
xiaoxineirong: [],
},
actions: {
async setMsg({ state }, msg){
//自己的id
let currentUserUuid = uni.getStorageSync("userUuid");
console.log(msg)
//收到消息后,处理消息列表和消息内容
state.xiaoxiliebiao=[]
state.xiaoxineirong=[]
//从本地取聊天列表
if (uni.getStorageSync(currentUserUuid + "msglist").length != 0&&
JSON.parse(uni.getStorageSync(currentUserUuid + "msglist"))[0]!=null) {
state.xiaoxiliebiao = JSON.parse(
uni.getStorageSync(currentUserUuid + "msglist")
);
}
//此处对消息类型判断,做不同的处理,例如文本消息,图片消息,自定义消息
if (msg.contentsType == "TEXT"){
//循环判断本地聊天列表,判断有没有跟这个人聊过天
let isnew = true;
// 如果有,更新列表
state.xiaoxiliebiao.forEach((p) => {
console.log(msg.from , p.userUuid)
if(msg.from == p.id){
p.messageContent: msg.data,
p.time = TimestampFormat(msg.time-0);
p.userHeadPortraitUrl = msg.ext.groupImg;
p.unreadNum +=1
isnew = false;
return;
}
})
// 如果没有,把该用户加入聊天列表
if (isnew == true) {
state.xiaoxiliebiao.unshift({
id: msg.from,
name: msg.ext.groupName, //自定义消息,发送者昵称
time: TimestampFormat(msg.time-0), //消息时间
userUuid: msg.from, //发送者id
userHeadPortraitUrl: msg.ext.groupImg, //自定义消息,发送者头像
isnew: 1, //是否是新消息
unreadNum:1, //有多少未读消息
messageContent: msg.data, //消息内容
isTop: 0, //是否置顶
type: '',//类型:单聊还是群聊
});
}
//把聊天列表存到本地
uni.setStorageSync(
currentUserUuid + msg.from,
JSON.stringify(state.xiaoxineirong)
);
//===================================================================
if (uni.getStorageSync(currentUserUuid + msg.from).length != 0) {
state.xiaoxineirong = JSON.parse(
uni.getStorageSync(currentUserUuid + msg.from)
);
}
let msgLastTime;
if (state.xiaoxineirong.length==0) {
//在第一次聊天时,需要添加时间,所以给0
msgLastTime = 0
} else{
msgLastTime = state.xiaoxineirong[state.xiaoxineirong.length-1].timeline
}
state.lastMsgTime = msg.time;
state.chatTime = new Date().getTime();
// 如果距离上一次聊天已过去三分钟,插入一条时间
if (Math.abs(state.chatTime - msgLastTime) > 180000) {
state.xiaoxineirong.push({
direction: "chatTime",
chatTime: TimestampFormat(state.lastMsgTime-0),
messageUuid: msg.ext.messageUuid + "time",
timeline: state.lastMsgTime,
time: msg.time,
});
}
console.log(customObj)
//把收到的消息存起来
state.xiaoxineirong.push({
direction: "chatLeft", //用来在聊天页判断是发送还是收到
name: msg.ext.userName, //自定义消息,存昵称
fromUserUuid: msg.from, //自定义消息,存发送者昵称
toUserUuid: msg.to, //自定义消息,存接收者昵称
messageUuid: msg.ext.messageUuid,
messageContent: msg.data, //消息内容
customObj: customObj, //存自定义消息
userHeadPortraitUrl: msg.ext.headImg, //自定义消息,存头像
read: 0, //是否已读
time: msg.time, //消息时间
});
//把消息存到本地
uni.setStorageSync(
currentUserUuid + msg.from,
JSON.stringify(state.xiaoxineirong)
);
}
}
}
在聊天页:
正在和某用户聊天,借用computed和watch监听vuex里消息的改变,判断和正在聊天的人是不是同一人,如果是更新聊天列表。 此处还要做消息分页,聊天列表置底,已读回调等操作。
data(){
return {
msgList: [],//消息
}
}
computed: {
msgList2() {
// this.sendIsRead()
console.log(this.$store.state.xiaoxineirong)
return this.$store.state.xiaoxineirong;
},
},
watch: {
msgList2: {
deep: true,
handler(newVal, oldVal) {
console.log(newVal)
//此处判断后台 Websocket接收到的数据是否为本用户,如果是本用户,立即宣染数据
if(this.$store.state.curUserId == this.toUserUuid){
if (uni.getStorageSync(this.currentUserUuid + this.toUserUuid).length !=0) {
list = JSON.parse(
uni.getStorageSync(this.currentUserUuid + this.toUserUuid)
);
}
this.msgList = list
}
}
},