微信的聊天功能很完善了,但在某些特殊需求的时候很难找到想要的群聊
最近社群裂变什么的很火啊,就想着顺便制作一个即时通讯的小程序练练手,于是就有了下面这个半成品。
没打算上线,就几个内部的人用作交流用,写下一点对接极光IM开发的一点坑,给过路的人一些提示。
废话不多说,先上截图看效果
一共4个Tap
首页:首页其实是一些大的分类做个展示,外加一个搜索功能
信息:类似于论坛,里面是各个模块的帖子
消息:主要功能在这里,分为私聊,群聊,好友和公开聊天室
我的:基本照抄ColorUI的界面,没时间改
今天是即时通讯篇,主要讲讲消息模块的开发内容。
极光IM的文档做得还是可以的,就是有时候通讯质量堪忧,可能是我用的免费的原因吧
第一个判断是否登陆与极光是否初始化
initPage: function (page) {
var vm = this
if (!vm.globalData.isJMLogin) {
let jim = vm.globalData.jim
if (!jim.isInit()) {
vm.initJim()
}
// 判断是用户数据是否获取
// 获取用户信息
// 系统登陆
}
}
定义了一个全局函数和全局的jim对象,只要需要用到极光IM的页面就调用initPage方法查看是否初始化jim。因为小程序并不一直保持常显状态,长时间微操作或者进入后台可能导致jim对象过期。
第二步如果极光没有初始化,那就去初始化了
initJim() {
let vm = this
let jim = vm.globalData.jim
let random = vm.randomString()
let time = new Date().getTime()
jim.init({
"appkey": "你自己的appkey",
"random_str": random,
"signature": crypt.MD5("appkey=你自己的appkey×tamp=" + time + "&random_str=" + random + "&key=你自己的key"),
"timestamp": time
}).onSuccess(function (data) {
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
if (res.code) {
// 发起网络请求
wx.request({
url: vm.globalData.url + '/wx/session',
data: {
code: res.code,
system: vm.globalData.system
},
header: {
"Content-Type": "application/json; charset=UTF-8"
},
method: 'POST',
success: res => {
if (res.data && res.data.openid) {
vm.globalData.openId = res.data.openid
vm.globalData.sessionKey = res.data.session_key
if (vm.openIdReadyCallback) {
vm.openIdReadyCallback(res.data.openid)
}
}
}
})
}
}
})
}).onFail(function (data) {
vm.initJim()
})
}
这里有个问题,就是openId可能还没有获取到,页面就加载完了,这个时候页面调用onload里的openId就会报错,所以用了openIdReadyCallback做了个回调
每个页面Onload方法高度一致调用isLoginTodo来判断是否登陆,参数是每个页面对象和回调函数
app.isLoginTodo(this, function () {
//业务代码
})
isLoginTodo(page, callBack) {
var vm = this
var time
wx.showLoading({
title: "Loding...",
// mask: true,
success: function () {
if (!vm.globalData.isJMLogin) {
vm.initPage(page)
time = setInterval(function () {
if (vm.globalData.isJMLogin) {
callBack()
wx.hideLoading()
clearInterval(time)
}
}, 500)
} else {
callBack()
wx.hideLoading()
}
}
})
}
除了极光登陆,还有小程序的系统登陆,这个就不放上来了,每个系统自己去做设计就好
私聊群聊的列表需要获取对话记录,还有监听消息
monitor() {
var vm = this
let jim = app.globalData.jim
jim.onEventNotification(function (data) {
console.log("EventNotification", data)
if (data.event_type == 5 && data.description == 'yes') {
vm.loadFriends()
} else if (data.event_type == 5 && data.description == 'no') {
vm.loadFriends()
} else if (data.event_type == 5 && data.description != 'yes') {
vm.data.addFriends.push(data)
vm.setData({
addFriends: vm.data.addFriends
})
wx.setStorageSync("receive_add_friend_msg", vm.data.addFriends)
} else if (data.event_type == 6) {
vm.loadFriends()
}
})
jim.onSyncEvent(function (data) {
console.log("SyncEvent", data)
})
jim.onSyncConversation(function (data) {
console.log("SyncConversation", data)
})
jim.onTransMsgRec(function (data) {
console.log("SyncConversation", data)
})
jim.onTransMsgRec(function (data) {
console.log("TransMsgRec", data)
})
}
因为极光的好友申请是一个事件监听,所以需要在收到消息之后先缓存起来,不然之后就找不到好友申请了
而且极光的好友申请是这样的流程
A申请B好友,B收到消息,B同意好友请求(但实际上是B发送了一个好友请求给A),AB成为好友
注意括号里的那句话,所以其实只要AB互发了好友请求就会成为好友,在这个基础上你就需要验证收到的消息是好友请求还是同意好友请求,这个地方有点绕,不然你会把同意好友请求当作好友申请显示到列表上,这就很尴尬了
还有一个要注意的地方是消息界面,极光的图片是需要通过消息返回的地址用jim.getResource获取资源,所以需要用到Promise做同步,如下,传入promise数组对象
asyncImages: function (promises, item, jim) {
var vm = this
if (item.msg_type === 'image' && (item.from_id === vm.data.fromId || item.target_id === vm.data.fromId)) {
var promise = new Promise(function (resolve, reject) {
jim.getResource({
media_id: item.msg_body.media_id
}).onSuccess(function (data) {
resolve(data.url)
}).onFail(function (data) {
reject()
})
})
promises.push(
promise.then(url => {
item.image_url = url
}).catch(res => {
item.image_url = ''
})
)
}
}
然后
Promise.all(promises).then(() => {
vm.setData({
messages: tempMessages
}, () => {
vm.pageScrollToBottom()
})
})
至于其他的,加载消息,发送消息,参考官方文档就好了,这个也没什么好说的,最后实现了文字,图片,表情,文件这些基础功能。