前言
最近把Vue+Element二次封装持续完善了,然后开始着手处理即时通讯这一块了。
之前的老代码用的是融云2.x版本,现在4.x了,自然要更新下,融云4.x变化还是挺大的,很多API都换掉了,但是相对来讲还是比较简单上手的。
由于没有原型图,我直接边设计办coding,对于这种自己发挥的需求,我仍然保持微笑。(这应该是对我审美的肯定吧!)先整了个样图出来如下
接下来咱们步入正题
分析需求
项目是一个社交APP的后台管理项目,项目中有个模块是关于聊天室的,链接APP内的聊天大厅,如果有用户发布不良信息,可以禁言用户,同时也可以发布公告消息。
任务
- 获取token,链接融云
- 获取历史消息并模拟聊天展示出来
- 发送消息,这个是由后端完成,我发送消息就请求接口
- 可以禁言用户,这个也是由后端来统一完成
关于融云
融云提供的即时通讯服务,不需要在 App 之外建立并行的用户体系,不用同步 App 下用户信息到融云,不影响 App 现有的系统架构与帐号体系,与现有业务体系能够实现完美融合。
兼容说明
Chrome | Firefox | Safari | IE | Edge | QQ 浏览器 | 微信 浏览器 | Android | ✔ | ✔ | ✔ | 9+ | ✔ | ✔ | ✔ | ✔ |
---|
导入 SDK
NPM 引入(推荐)
- 依赖安装
npm install @rongcloud/imlib-v4
- 代码集成
// 非 ESModule
const RongIMLib = require('@rongcloud/imlib-v4')
// ESModule
import * as RongIMLib from '@rongcloud/imlib-v4'
CDN 引入
- 在
index.html
<script src="https://cdn.ronghub.com/RongIMLib-4.3.latest.js"></script>
App Key
App Key
是使用 IMLib 进行即时通讯功能开发的必要条件,也是应用的唯一性标识。在集成使用 IMLib
之前,请务必先通过 融云开发者后台 (opens new window)注册并获取开发者的专属 App Key
。
只有在 App Key 相同的情况下,不同用户之间的消息才有可能互通。
初始化
IMLib 提供的所有能力基于 IMLib 初始化后获取的实例对象,因此在使用 IMLib 的能力之前,必须先调用 IMLib 的初始化接口,且务必保证该接口在应用全生命周期内仅被调用一次。
// 应用初始化以获取 RongIMLib 实例对象,请务必保证此过程只被执行一次
const im = RongIMLib.init({ appkey: '<Your-App-Key>' });
设置监听
初始化完成后,应在建立连接之前对 im 对象添加事件监听器,及时获取相关事件通知。
// 添加事件监听
im.watch({
// 监听会话列表变更事件
conversation (event) {
// 假定存在 getExistedConversationList 方法,以获取当前已存在的会话列表数据
const conversationList = getExistedConversationList()
// 发生变更的会话列表
const updatedConversationList = event.updatedConversationList;
// 通过 im.Conversation.merge 计算最新的会话列表
const latestConversationList = im.Conversation.merge({ conversationList, updatedConversationList })
},
// 监听消息通知
message (event) {
// 新接收到的消息内容
const message = event.message;
},
// 监听 IM 连接状态变化
status (event) {
console.log('connection status:', event.status);
},
// 监听聊天室 KV 数据变更
chatroom (event) {
/**
* 聊天室 KV 存储数据更新
* @example
* [
* {
* "key": "name",
* "value": "我是小融融",
* "timestamp": 1597591258338,
* "chatroomId": "z002",
* "type": 1 // 1: 更新( 含:修改和新增 )、2: 删除
* },
* ]
*/
const updatedEntries = event.updatedEntries
},
expansion (event) {
/**
* 更新的消息拓展数据
* @example {
* expansion: { key: 'value' }, // 设置或更新的扩展值
* messageUId: 'URIT-URIT-ODMF-DURR' // 设置或更新扩展的消息 uid
* }
*/
const updatedExpansion = event.updatedExpansion;
/**
* 删除的消息拓展数据
* @example {
* deletedKeys: ['key1', 'key2'], // 设置或更新的扩展值
* messageUId: 'URIT-URIT-ODMF-DURR' // 设置或更新扩展的消息 uid
* }
*/
const deletedExpansion = event.deletedExpansion;
});
建立 IM 连接
App Key
是应用的唯一性标识,Token
则是用户的唯一性标识,是用户连接融云 IM
服务所必需的身份凭证。Token
一般由开发者的应用服务器调用融云 Server API
获取 Token 接口获取之后,由应用服务器下发到应用客户端。
我的这个token是从后端获取的,然后存储到本地,用的时候看看过期没,过期了就重新获取。相当于前端只进行部分交互。
- 获取token
// 获取token
getIMToken() {
getIMToken().then(res => {
var time = new Date().getTime()
res.time = time
// 将token保存下来
this.gobalToken = res
var tokenStr = JSON.stringify(res)
localStorage.setItem('token', tokenStr)
// 初始化融云
this.linkToRongs(res.data)
})
},
// 判断token是否过期
isToken() {
var now = new Date().getTime()
// 获取上一次存储的token
var oldToken = JSON.parse(localStorage.getItem('token'))
// 判断之前获取的token
if (oldToken) {
var tokenTime = oldToken.time
// 判断时间是否过期了
if (now - tokenTime > 29 * 24 * 60 * 60 * 1000) {
this.getIMToken()
} else {
this.gobalToken = JSON.parse(localStorage.getItem('token'))
this.linkToRongs(this.gobalToken.data)
return
}
}
this.getIMToken()
}
- 建立连接
im.connect({ token: '<Your-Token>' }).then(user => {
console.log('链接成功, 链接用户 id 为: ', user.id);
}).catch(error => {
console.log('链接失败: ', error.code, error.msg);
});
获取会话列表
IMLib
通过会话数据中的 conversationType
与 targetId
两个属性值来标识会话的唯一性,对于两个属性的定义如下:
conversationType
用来标识会话类型(如:单聊、群聊...),其值为RongIMLib.CONVERSATION_TYPE
中的常量定义targetId
用来标识与本端进行对话的人员或群组 Id:
- 当
conversationType
值为 RongIMLib.CONVERSATION_TYPE.PRIVATE,targetId 为对方用户 Id - 当
conversationType
值为 RongIMLib.CONVERSATION_TYPE.GROUP,targetId 为当前群组 Id - 当
conversationType
值为 RongIMLib.CONVERSATION_TYPE.CHATROOM,targetId 为聊天室 Id
// 获取会话列表
im.Conversation.getList().then(conversationList => {
console.log('获取会话列表成功', conversationList);
}).catch(error => {
console.log('获取会话列表失败: ', error.code, error.msg);
});
发送消息
// 获取指定会话的抽象实例,对于会话的操作基于此实例完成
const conversation = im.Conversation.get({
// targetId
targetId: '<TargetId>',
// 会话类型:RongIMLib.CONVERSATION_TYPE.PRIVATE | RongIMLib.CONVERSATION_TYPE.GROUP
type: '<Conversation-Type>'
});
// 向会话内发消息
conversation.send({
// 消息类型,其中 RongIMLib.MESSAGE_TYPE 为 IMLib 内部的内置消息类型常量定义
messageType: RongIMLib.MESSAGE_TYPE.TEXT, // 'RC:TxtMsg'
// 消息内容
content: {
content: 'Hello RongCloud' // 文本内容
}
}).then(function(message){
console.log('发送文字消息成功', message);
}).catch(error => {
console.log('发送文字消息失败', error.code, error.msg);
});
接收消息
当本端作为消息接收的一方,所接收的消息将通过 im.watch()
注册的消息监听向业务层抛出。具体可参考上述 设置监听 部分
获取历史消息
const conversation = im.Conversation.get({
targetId: '<TargetId>',
type: '<Conversation-Type>'
});
const option = {
// 获取历史消息的时间戳,默认为 0,表示从当前时间获取
timestamp: +new Date(),
// 获取条数,有效值 1-20,默认为 20
count: 20,
};
conversation.getMessages(option).then(result => {
const list = result.list; // 获取到的消息列表
const hasMore = result.hasMore; // 是否还有历史消息可获取
console.log('获取历史消息成功', list, hasMore);
}).catch(error => {
console.log('发送文字消息失败', error.code, error.msg);
});
断开连接
im.disconnect().then(() => console.log('断开链接成功'));
实战运用
token拿到手,往前走一走
created() {
this.isToken()
}
methods:{
// 获取token
getIMToken() {
getIMToken().then(res => {
var time = new Date().getTime()
res.time = time
// 将token保存下来
this.gobalToken = res
var tokenStr = JSON.stringify(res)
localStorage.setItem('token', tokenStr)
// 初始化融云
this.linkToRongs(res.data)
})
},
// 判断token是否过期
isToken() {
var now = new Date().getTime()
// 获取上一次存储的token
var oldToken = JSON.parse(localStorage.getItem('token'))
// 判断之前获取的token
if (oldToken) {
var tokenTime = oldToken.time
// 判断时间是否过期了
if (now - tokenTime > 29 * 24 * 60 * 60 * 1000) {
this.getIMToken()
} else {
this.gobalToken = JSON.parse(localStorage.getItem('token'))
this.linkToRongs(this.gobalToken.data)
return
}
}
this.getIMToken()
},
}
init初始化,话话道心好好听
一般测试服一个appkey
,正式服一个appkey
。这个appkey
需要自己去申请
// 链接融云
linkToRongs(token) {
const that = this
let RongClientKey
if (process.env.VUE_APP_BASE_API2 === '') {//测试服
RongClientKey = '4215151sadasas'
} else {//正式服
RongClientKey = 'adsada12asda1a'
}
// 应用初始化以获取 RongIMLib 实例对象,请务必保证此过程只被执行一次
// eslint-disable-next-line no-undef
that.rongyun = RongIMLib.init({ appkey: RongClientKey })
}
监听先行开路,链接随后就到
初始化完成后,应在建立连接之前对 im 对象添加事件监听器,及时获取相关事件通知。
// 链接融云
linkToRongs(token) {
const that = this
let RongClientKey
if (process.env.VUE_APP_BASE_API2 === '') {//测试服
RongClientKey = '4215151sadasas'
} else {//正式服
RongClientKey = 'adsada12asda1a'
}
// 应用初始化以获取 RongIMLib 实例对象,请务必保证此过程只被执行一次
// eslint-disable-next-line no-undef
that.rongyun = RongIMLib.init({ appkey: RongClientKey })
const im = that.rongyun
// 添加事件监听
im.watch({
// 监听会话列表变更事件
conversation(event) {
// 假定存在 getExistedConversationList 方法,以获取当前已存在的会话列表数据
const conversationList = that.getExistedConversationList(im)
// 发生变更的会话列表
const updatedConversationList = event.updatedConversationList
// 通过 im.Conversation.merge 计算最新的会话列表
const latestConversationList = im.Conversation.merge({ conversationList, updatedConversationList })
console.log(latestConversationList)
},
// 监听消息通知
message(event) {
//初始化消息都在这
// 新接收到的消息内容
const message = event.message
console.log(message)
},
// 监听 IM 连接状态变化
status(event) {
console.log('connection status:', event.status)
},
// 监听聊天室 KV 数据变更
chatroom(event) {
const updatedEntries = event.updatedEntries
console.log('聊天室 KV 存储数据更新', updatedEntries)
}
})
}
链接融云先用key,长驱直入无人拦
// 链接融云
linkToRongs(token) {
const that = this
let RongClientKey
if (process.env.VUE_APP_BASE_API2 === '') {//测试服
RongClientKey = '4215151sadasas'
} else {//正式服
RongClientKey = 'adsada12asda1a'
}
// 应用初始化以获取 RongIMLib 实例对象,请务必保证此过程只被执行一次
// eslint-disable-next-line no-undef
that.rongyun = RongIMLib.init({ appkey: RongClientKey })
const im = that.rongyun
// 添加事件监听
im.watch({
// 监听会话列表变更事件
conversation(event) {
// 假定存在 getExistedConversationList 方法,以获取当前已存在的会话列表数据
const conversationList = that.getExistedConversationList(im)
// 发生变更的会话列表
const updatedConversationList = event.updatedConversationList
// 通过 im.Conversation.merge 计算最新的会话列表
const latestConversationList = im.Conversation.merge({ conversationList, updatedConversationList })
console.log(latestConversationList)
},
// 监听消息通知
message(event) {
//初始化消息都在这
// 新接收到的消息内容
const message = event.message
console.log(message)
},
// 监听 IM 连接状态变化
status(event) {
console.log('connection status:', event.status)
},
// 监听聊天室 KV 数据变更
chatroom(event) {
const updatedEntries = event.updatedEntries
console.log('聊天室 KV 存储数据更新', updatedEntries)
}
})
// 建立 IM 连接
const chatRoomId = '627865222'
var count = 50 // 数量
im.connect({ token: token }).then(user => {
this.$message.success('加入聊天室成功')
console.log('链接成功, 链接用户 id 为: ', user.id)
var chatRoom = im.ChatRoom.get({
id: chatRoomId
})
chatRoom.join({
count: count // 进入后, 自动拉取 20 条聊天室最新消息
}).then(function() {
console.log('加入聊天室成功')
chatRoom.getInfo().then(function(result) {
var userCount = result.userCount
var user = that.uniq(that.messageList)
// 刷选用户
user.map(item => {
that.list.push(item.user)
})
that.num = userCount
})
})
}).catch(error => {
this.$message.success('加入聊天室失败')
console.log('链接失败: ', error.code, error.msg)
})
}
最后一步最重要,退出聊天要及时
切换页面时,一定要退出聊天厅,不然下次加入聊天厅无法获取之前的消息。当然你也可以获取历史消息,我尝试获取历史消息一直报错,所以才选择打开页面加入,结束就离开。(不退出的话会一直保持连接)
destroyed() {
var chatRoom = this.rongyun.ChatRoom.get({
id: '聊天室id'
})
chatRoom.quit().then(function() {
console.log('退出聊天室成功')
})
}
结尾
即时通讯这一块做起来还是蛮有意思的,总有一些意料之外的事情发生。
最后把源码放在了github
融云官方文档
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!