Vue集成融云实现即时通信聊天室

前言

最近把Vue+Element二次封装持续完善了,而后开始着手处理即时通信这一块了。html

以前的老代码用的是融云2.x版本,如今4.x了,天然要更新下,融云4.x变化仍是挺大的,不少API都换掉了,可是相对来说仍是比较简单上手的。前端

因为没有原型图,我直接边设计办coding,对于这种本身发挥的需求,我仍然保持微笑。(这应该是对我审美的确定吧!)先整了个样图出来以下git

融云2.png

高处不胜寒,起舞弄清影。github

接下来我们步入正题npm

分析需求

项目是一个社交APP的后台管理项目,项目中有个模块是关于聊天室的,连接APP内的聊天大厅,若是有用户发布不良信息,能够禁言用户,同时也能够发布公告消息。后端

任务

  1. 获取token,连接融云
  2. 获取历史消息并模拟聊天展现出来
  3. 发送消息,这个是由后端完成,我发送消息就请求接口
  4. 能够禁言用户,这个也是由后端来统一完成

关于融云

融云提供的即时通信服务,不须要在 App 以外创建并行的用户体系,不用同步 App 下用户信息到融云,不影响 App 现有的系统架构与账号体系,与现有业务体系可以实现完美融合。浏览器

兼容说明

Chrome Firefox Safari IE Edge QQ 浏览器 微信 浏览器 Android
9+

导入 SDK

融云 4.x 底层使用 Typescript 进行了重构,对 Typescript 的使用者提供了友好的类型化支持,推荐开发者使用 Typescript 进行业务开发以提高代码健壮性及可维护性。服务器

NPM 引入(推荐)

  1. 依赖安装
npm install @rongcloud/imlib-v4
复制代码
  1. 代码集成
// 非 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 相同的状况下,不一样用户之间的消息才有可能互通。markdown

初始化

IMLib 提供的全部能力基于 IMLib 初始化后获取的实例对象,所以在使用 IMLib 的能力以前,必须先调用 IMLib 的初始化接口,且务必保证该接口在应用全生命周期内仅被调用一次。

// 应用初始化以获取 RongIMLib 实例对象,请务必保证此过程只被执行一次
const im = RongIMLib.init({ appkey: '<Your-App-Key>' });
复制代码

后续全部代码示例中的 im 均指经过初始化获取到的 RongIMLib 实例对象

设置监听

初始化完成后,应在创建链接以前对 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);
});
复制代码

获取会话列表

Web 端不具有持久化的数据存储能力,须要开发者开启 IM 商用版 - 单群聊云存储 (opens new window)功能才能生效。 该功能须要在调用 im.connect() 而且创建链接成功以后执行。

IMLib 经过会话数据中的 conversationTypetargetId 两个属性值来标识会话的惟一性,对于两个属性的定义以下:

  1. conversationType 用来标识会话类型(如:单聊、群聊...),其值为 RongIMLib.CONVERSATION_TYPE 中的常量定义
  2. 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);
});

复制代码

发送消息

该功能须要在调用 im.connect() 而且创建链接成功以后执行。 IMLib 内置消息类型可经过 RongIMLib.MESSAGE_TYPE 获取其常量定义

// 获取指定会话的抽象实例,对于会话的操做基于此实例完成
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() 注册的消息监听向业务层抛出。具体可参考上述 设置监听 部分

获取历史消息

Web 端不具有持久化的数据存储能力,须要开发者开启 IM 商用版 - 单群聊云存储 (opens new window)功能才能生效。 该功能须要在调用 im.connect() 而且创建链接成功以后执行。

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);
});

复制代码

断开链接

断开当前用户链接,链接断开后没法接收消息、发送消息、获取历史消息、获取会话列表... 在下次链接融云成功后,会收取上次离线后的消息,离线消息默认保存 7 天。

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

融云官方文档

写在最后

我是凉城a,一个前端,热爱技术也热爱生活。

与你相逢,我很开心。

若是你想了解更多,请点这里,期待你的小⭐⭐

  • 文中若有错误,欢迎在评论区指正,若是这篇文章帮到了你,欢迎点赞和关注😊

  • 本文首发于掘金,未经许可禁止转载💌

相关文章
相关标签/搜索