由于有同窗问了我下融云怎么写聊天的问题,我才了解到有融云这么个东西,尝试着学了下。主要介绍了vue中使用vue-cli接入融云实现即时通讯的相关资料,本文经过实例代码给你们介绍的很是详细,具备必定的参考借鉴价值,须要的朋友能够参考下... 我的博客javascript
本文章 Demo 源码 star 哦 拿下来能够直接跑css
Flutter 项目 star 哦 这是本人打算长期更新的一个项目html
在写代码以前咱们首先要 注册融云,注册融云后拿到 appkey 和融云提供的 tokenvue
拿到 appkey 和 token 后记得保存下来java
能够使用下列任一命令安装这个新的包:git
$ npm install -g @vue/cli
# OR
$ yarn global add @vue/cli
复制代码
运行如下命令来建立一个新项目:github
$ vue create hello-world
# OR
$ vue ui // UI 界面建立项目
复制代码
你会被提示选取一个 prese 由于咱们这个项目用到了 VUEX 因此咱们选择手动选择特性来选取须要的特性来避免后续的的麻烦web
除了默认选项 咱们须要选择 Router
和 Vuex
vuex
等项目建立完毕后大概是这个样子vue-cli
首先咱们进入根目录的 public
目录下的 index.html
这个位置引入融云 SDK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>im</title>
</head>
<body>
<noscript>
<strong>We're sorry but im doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="https://cdn.ronghub.com/RongIMLib-2.5.0.min.js"></script>
<!-- built files will be auto injected -->
</body>
</html>
复制代码
src
下建立几个文件 名字随意你们能够自行建立utils.js
scss
目录 在此目录建立一个 utils.scss
(这个文件并不重要只是为了自适应)scr
目录下建立 init.vue
src
目录下建立 RongCloud.vue
src
目录下建立 Message.vue
utils.js
此文件是对融云的初始化操做
export const init = (params, addPromptInfo) => {
var appkey = params.appkey
var token = params.token
RongIMClient.init(appkey)
RongIMClient.setConnectionStatusListener({
onChanged: function (status) {
switch (status) {
case RongIMLib.ConnectionStatus['CONNECTED']:
case 0:
addPromptInfo('链接成功')
break
case RongIMLib.ConnectionStatus['CONNECTING']:
case 1:
addPromptInfo('正在链接中')
break
case RongIMLib.ConnectionStatus['DISCONNECTED']:
case 2:
addPromptInfo('当前用户主动断开连接')
break
case RongIMLib.ConnectionStatus['NETWORK_UNAVAILABLE']:
case 3:
addPromptInfo('网络不可用')
break
case RongIMLib.ConnectionStatus['CONNECTION_CLOSED']:
case 4:
addPromptInfo('未知缘由,链接关闭')
break
case RongIMLib.ConnectionStatus['KICKED_OFFLINE_BY_OTHER_CLIENT']:
case 6:
addPromptInfo('用户帐户在其余设备登陆,本机会被踢掉线')
break
case RongIMLib.ConnectionStatus['DOMAIN_INCORRECT']:
case 12:
addPromptInfo('当前运行域名错误,请检查安全域名配置')
break
}
}
})
// 消息监听器
RongIMClient.setOnReceiveMessageListener({
// 接收到的消息
onReceived: function (message) {
// 判断消息类型
switch (message.messageType) {
case RongIMClient.MessageType.TextMessage:
// message.content.content => 文字内容
addPromptInfo('新消息 ' + message.targetId + ':' + JSON.stringify(message))
break
case RongIMClient.MessageType.VoiceMessage:
// message.content.content => 格式为 AMR 的音频 base64
break
case RongIMClient.MessageType.ImageMessage:
// message.content.content => 图片缩略图 base64
// message.content.imageUri => 原图 URL
break
case RongIMClient.MessageType.LocationMessage:
// message.content.latiude => 纬度
// message.content.longitude => 经度
// message.content.content => 位置图片 base64
break
case RongIMClient.MessageType.RichContentMessage:
// message.content.content => 文本消息内容
// message.content.imageUri => 图片 base64
// message.content.url => 原图 URL
break
case RongIMClient.MessageType.InformationNotificationMessage:
// do something
break
case RongIMClient.MessageType.ContactNotificationMessage:
// do something
break
case RongIMClient.MessageType.ProfileNotificationMessage:
// do something
break
case RongIMClient.MessageType.CommandNotificationMessage:
// do something
break
case RongIMClient.MessageType.CommandMessage:
// do something
break
case RongIMClient.MessageType.UnknownMessage:
// do something
break
default:
// do something
}
}
})
RongIMClient.connect(token, {
onSuccess: function (userId) {
addPromptInfo('链接成功,用户id:' + userId, userId)
},
onTokenIncorrect: function () {
addPromptInfo('token无效')
},
onError: function (errorCode) {
switch (errorCode) {
case RongIMLib.ErrorCode.TIMEOUT:
addPromptInfo('超时')
//连接超时进行从新的连接start
var callback = {
onSuccess: function (userId) {
console.log("Reconnect successfully." + userId);
},
onTokenIncorrect: function () {
console.log('token无效');
},
onError: function (errorCode) {
console.log(errorcode);
}
};
var config = {
// 默认 false, true 启用自动重连,启用则为必选参数
auto: true,
// 重试频率 [100, 1000, 3000, 6000, 10000, 18000] 单位为毫秒,可选
url: 'cdn.ronghub.com/RongIMLib-2.5.0.min.js',
rate: [100, 1000, 3000, 6000, 10000]
};
RongIMClient.reconnect(callback, config);
//连接超时进行从新连接end
break;
case RongIMLib.ErrorCode.UNKNOWN_ERROR:
addPromptInfo('未知错误')
break;
case RongIMLib.ErrorCode.UNACCEPTABLE_PaROTOCOL_VERSION:
addPromptInfo('不可接受的协议版本')
break;
case RongIMLib.ErrorCode.IDENTIFIER_REJECTED:
console.log('ddd')
addPromptInfo('appkey不正确')
break;
case RongIMLib.ErrorCode.SERVER_UNAVAILABLE:
addPromptInfo('服务器不可用')
break;
}
addPromptInfo(errorCode)
}
}, null)
}
复制代码
utils.scss
这个文件很简单
@function vw ($px) {
@return $px / 750px * 100vw;
}
复制代码
init.vue
经过用户输入的信息来进行初始化链接
<template>
<div class="init">
<van-nav-bar title="链接融云" />
<van-cell-group>
<van-field v-model="appkey" required label="appkey" placeholder="请输入您的 appkey" />
<van-field v-model="token" label="token" placeholder="请输入您的 token" required />
<van-field v-model="targetId" label="targetId" placeholder="请输入 targetId" required />
</van-cell-group>
<van-button class="init-button" type="info" @click="initRongCloud">初始化链接</van-button>
<div class="rong-show-box">
<p v-for="data in showDatas" v-bind:key="data">
{{data}}
</p>
</div>
</div>
</template>
<script> import { init } from '@/utils.js' export default { data () { return { appkey: '', // 这是咱们以前保存的 appkey *重要 token: '', // token 能够屡次生成 以前也有介绍过 targetId: '', // 你要给谁发送消息 目标ID showDatas: [], // 初始化信息 } }, methods: { addPromptInfo (prompt, userId = null) { const _this = this const avatarList = [ 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4100987808,2324741924&fm=26&gp=0.jpg', 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2988245209,2476612762&fm=26&gp=0.jpg', 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4259300811,497831842&fm=26&gp=0.jpg', 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3684587473,1286660191&fm=26&gp=0.jpg', 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2884107401,3797902000&fm=26&gp=0.jpg' ] // 真实环境是经过登陆 后台接口返回的 token 拿到的用户信息 我在这为为了模拟 因此给初始化后的用户随机生成一个头像 const avatar = avatarList[Math.floor(Math.random() * (3 + 1))] _this.showDatas.push(prompt) const timer = setInterval(() => { if (userId) { clearInterval(timer) // 路由跳转后销毁定时器 _this.$store.commit('SET_MEMBER', { // 保存用户信息 userId: userId, avatar: avatar }) _this.$store.commit('SET_TARGETID', _this.targetId) // 保存目标ID _this.$router.push({ name: 'RongCloud' }) } }, 500) }, initRongCloud () { var appkey = this.appkey var token = this.token if (!appkey || !token) { alert('appkey 和 token 不能为空') } else { // 这个init 是咱们以前撸的 `utils.js` init({ appkey: appkey, token: token }, this.addPromptInfo) } } } } </script>
<style lang="scss" scoped> @import "~@/scss/utils"; .init-button { position: fixed !important; bottom: vw(30px); left: 50%; transform: translateX(-50%); } .rong-show-box { margin-top: vw(100px); text-align: center; } </style>
复制代码
RongCloud.vue
发送消息
<template>
<div id='rongcloud'>
<van-nav-bar title="融云聊天" fixed left-text="返回" left-arrow @click-left="onClickLeft" />
<div class="wrapper">
<Message v-for="(item, index) in answer" :key="index" :data='item' />
</div>
<div class="send-message">
<van-field v-model="say" class="message-textarea" type="textarea" placeholder="请输入..." />
<van-button class="send-button" type="info" size="small" @click="sendMessage">发送</van-button>
</div>
</div>
</template>
<script> import { mapState } from 'vuex' import Message from './Message' export default { components: { Message }, data () { return { say: '' // 消息 } }, created () { this.$nextTick(() => { const list = document.getElementById('rongcloud') document.documentElement.scrollTop = list.scrollHeight //如不行,请尝试-> list.scrollTop = list.scrollHeight }) }, watch: { answer () { this.$nextTick(() => { const list = document.getElementById('rongcloud') document.documentElement.scrollTop = list.scrollHeight //如不行,请尝试-> list.scrollTop = list.scrollHeight }) } }, computed: { ...mapState({ answer: 'answer', // 消息列表 memberInfo: 'memberInfo', // 用户信息 targetId: 'targetId' // 目标ID }) }, methods: { onClickLeft () { this.$router.go(-1) }, sendMessage () { const _this = this var msg = new RongIMLib.TextMessage({ content: _this.say, extra: _this.memberInfo.avatar }); var conversationType = RongIMLib.ConversationType.PRIVATE // 单聊, 其余会话选择相应的消息类型便可 var targetId = this.targetId // 目标 Id RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, { onSuccess: function (message) { // message 为发送的消息对象而且包含服务器返回的消息惟一 Id 和发送消息时间戳 const say = { css: 'right', txt: message.content.content, headImg: _this.memberInfo.avatar } _this.answer.push(say) _this.say = '' }, onError: function (errorCode, message) { var info = '' switch (errorCode) { case RongIMLib.ErrorCode.TIMEOUT: info = '超时' break case RongIMLib.ErrorCode.UNKNOWN: info = '未知错误' break case RongIMLib.ErrorCode.REJECTED_BY_BLACKLIST: info = '在黑名单中,没法向对方发送消息' break case RongIMLib.ErrorCode.NOT_IN_DISCUSSION: info = '不在讨论组中' break case RongIMLib.ErrorCode.NOT_IN_GROUP: info = '不在群组中' break case RongIMLib.ErrorCode.NOT_IN_CHATROOM: info = '不在聊天室中' break } console.log('发送失败: ' + info + errorCode) } }) } } } </script>
<style lang="scss" scoped> @import "~@/scss/utils"; .wrapper { padding-top: vw(92px); padding-bottom: vw(200px); } .send-message { width: 100vw; height: vw(200px); position: fixed !important; bottom: 0; left: 0; .message-textarea { height: 100%; } .send-button { position: fixed; right: vw(30px); bottom: vw(30px); } } </style>
复制代码
Message.vue
显示消息 逻辑比较简单就不讲了
<template>
<div>
<div v-if="data.css === 'left'">
<div class="message left">
<van-image round fit="cover" width="2rem" height="2rem" :src="data.headImg" />
<span>{{data.txt}}</span>
</div>
</div>
<div v-if="data.css === 'right'">
<div class="message right">
<span>{{data.txt}}</span>
<van-image round fit="cover" width="2rem" height="2rem" :src="data.headImg" />
</div>
</div>
</div>
</template>
<script> export default { props: ['data'] } </script>
<style lang="scss" scoped> @import "~@/scss/utils"; .message { display: flex; align-items: center; padding: vw(10px); } .left { justify-content: flex-start; span { margin-left: vw(20px); } } .right { justify-content: flex-end; span { margin-right: vw(20px); } } </style>
复制代码
store.js
此demo的一些状态管理数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
memberInfo: undefined, // 用户信息
targetId: undefined, // 目标ID
answer: [] // 消息列表
}
const mutations = {
SET_MEMBER (state, memberInfo) {
state.memberInfo = memberInfo
},
SET_TARGETID (state, targetId) {
state.targetId = targetId
},
SET_ANSWER (state, playload) {
let say = {
css: 'left', // css 样式
txt: playload.content, // 文本内容
headImg: playload.extra // 头像
}
state.answer.push(say)
},
};
export default new Vuex.Store({
state,
mutations,
actions
})
复制代码
utils.js
文件中引入store 保存发送的消息到 answer
import store from './store'
export const init = (params, addPromptInfo) => {
...
// 消息监听器
RongIMClient.setOnReceiveMessageListener({
// 接收到的消息
onReceived: function (message) {
// 判断消息类型
switch (message.messageType) {
case RongIMClient.MessageType.TextMessage:
// message.content.content => 文字内容
store.commit('SET_ANSWER', message.content)
...
}
}
})
...
}
复制代码
我的博客 本 demo 是给你们实现一个基本思路,只是实现了一个一对一聊天的功能。如需更多功能,请自行深刻了解,谢谢