vue+elementUI 集成融云 实现IM即时通讯

本文主要是介绍vue+elementUI 集成融云 实现IM即时通讯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这几天有个需求,做一个im,有app端和web端,能发文字、语音、图片、视频、视频、emoji,能看聊天记录,最终敲定融云。但融云没有现成的web端的UI,给的web端demo对我这个纯后端来说,看不太懂,所以准备自己写个简单点的,代码如下,token需要从后端获取,比较简单所以就不贴了,只贴一下效果图和前端代码。
在这里插入图片描述
在这里插入图片描述

<template><div class="whole-wrapper"><!-- 左边的聊天列表 --><div class="left_whole_wrapper"><!-- 搜索框 --><div class="search"><el-input placeholder="搜索联系人" suffix-icon="el-icon-search" v-model="find" @input="searchChange"></el-input></div><!-- 聊天列表 --><div class="left_wrapper" style="overflow-y:auto;" v-if="chatList"><div class="left-item" v-for="(item,index) in chatList" :key="index" @click="clickItem(item,index)" :class="{active:targetId==item.targetId}"><div class="left-item-left"><div class="left-item-head"><img :src="item.head"></div><div class="left-item-info"><div class="left-item-info_title">{{item.name}}</div><div class="left-item-info_content">{{item.info}}</div></div></div><div class="left-item-time"><div class="left-item-time-time">{{item.time}}</div><div class="left-item-time-number" v-if="item.number">{{item.number}}</div></div></div></div></div><!-- 中间的对话--><div class="center_whole_wrapper" v-if="dialogueInfo"><div class="center_wrapper"><!-- 上面的表头 --><div class="center_wrapper_top"><div class="center_wrapper_top_name">{{dialogueInfo.name}}</div><div class="center_wrapper_top_number">{{dialogueInfo.phone}}</div></div><!-- 中间的聊天框,尝试模拟数据 --><div class="center_wrapper_center" style="overflow-y:auto;" ref="dialogue_box"><div class="item loading">{{loadText}}<span>{{"第" + pageNum + "页"}}</span></div><div v-for="(item,index) in dialogueInfo.dialogueList" :key="index" :class="item.other?center_wrapper_center_item:center_wrapper_center_item_reserve"><div class="left-item-head"><img :src="item.head"></div><!-- 文字 --><div class="center-item-info_wrapper" v-if="item.text"><div class="center-item-tip"><div class="center-item-info">{{item.text}}</div><div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div></div><div class="center-item-time">{{item.date}}</div></div><!-- 图片 --><div class="center-item-info_wrapper" v-if="item.img"><div class="center-item-tip"><div class="center-item-info_img"><el-image :src="item.img" :preview-src-list="item.srcList" :fit="contain" v-loading="item.loading"></el-image></div><div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div></div><div class="center-item-time">{{item.date}}</div></div><!-- 音频 --><div class="center-item-info_wrapper" v-if="item.audio"><div class="center-item-tip"><audio :src="item.audio" controls></audio><div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div></div><div class="center-item-time">{{item.date}}</div></div><!-- 视频 --><div class="center-item-info_wrapper" v-if="item.video"><div class="center-item-tip"><video :src="item.video" controls></video><div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div></div><strong></strong><div class="center-item-time">{{item.date}}</div></div></div></div><!-- 下面的输入框,发送 --><div class="center_wrapper_right"><div class="icon-list"><!-- 表情 --><div class="icon-item" title="表情"><el-popover placement="top" width="450" trigger="click"><div style="width: 100%;height: 280px;display: flex;flex-wrap: wrap;overflow-y:auto;"><div class="emoji_icon" style="width: 5%;padding: 10px;" v-for="(item,index) in emojiList" :key="index"@click="clickEmoji(item.emoji)">{{item.emoji}}</div></div><el-button slot="reference" style="border: none;padding:0;"><img class="icon-item-img" src="../../../public/img/bg/emoji.png"></el-button></el-popover></div><!-- 上传文件 --><div class="icon-item"><el-upload class="avatar-uploader" action="/api/blade-app/filemgr/upload" :show-file-list="false":before-upload="beforeAvatarUpload" :on-success="handleAvatarSuccess"><div class="icon-item" title="发送文件"><img class="icon-item-img" src="../../../public/img/bg/photo.png"></div></el-upload></div><!-- 聊天记录 --><div class="icon-item" title="聊天记录" @click="clickHistory"><img class="icon-item-img" src="../../../public/img/bg/record.png"></div><!-- 模拟消息提醒弹框 --><!-- <el-buttonplain@click="notifyByOrder">使用 HTML 片段</el-button> --></div><el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="textarea" @keyup.enter.native="sendTextarea"></el-input><el-button type="primary" @click="sendTextarea">发送</el-button></div></div></div><!-- 右边的聊天记录 --><div class="center_whole_wrapper right_whole_wrapper"><div class="center_wrapper right_wrapper" v-if="showHistory"><div class="center_wrapper_center right_wrapper_center" style="overflow-y:auto;" ref="dialogue_record"><div class="item loading">{{loadText1}}<span>{{"第" + pageNum1 + "页"}}</span></div><div v-for="(item,index) in dialogueInfo.dialogueList" :key="index" :class="isOther?center_wrapper_center_item:center_wrapper_center_item_reserve"><div class="left-item-head"><img :src="item.head"></div><!-- 文字 --><div class="center-item-info_wrapper" v-if="item.text"><div class="center-item-name">{{item.name}}</div><div class="center-item-info">{{item.text}}</div><div class="center-item-time">{{item.date}}</div></div><!-- 图片 --><div class="center-item-info_wrapper" v-if="item.img"><div class="center-item-name">{{item.name}}</div><div class="center-item-info_img"><el-image :src="item.img" :preview-src-list="item.srcList" :fit="contain"></el-image></div><div class="center-item-time">{{item.date}}</div></div><!-- 音频 --><div class="center-item-info_wrapper" v-if="item.audio"><div class="center-item-name">{{item.name}}</div><audio :src="item.audio" controls></audio><div class="center-item-time">{{item.date}}</div></div><!-- 视频 --><div class="center-item-info_wrapper" v-if="item.video"><div class="center-item-name">{{item.name}}</div><video :src="item.video" controls></video><div class="center-item-time">{{item.date}}</div></div></div></div></div></div></div>
</template>
<script>import {getToken,getChatList} from "@/api/app/chat";import {dateFormat} from "@/util/date.js";var RongIMLib = window.RongIMLib;var RongIMClient = RongIMLib.RongIMClient;var RongIMEmoji = RongIMLib.RongIMEmoji;export default {data() {return {chatList: [// {//   "targetId": "1123598821738675201",//   "head": "https://gitee.com/uploads/61/632261_smallweigit.jpg",//   "name": "济南亨达通汽修厂1",//   "info": "转账了,麻烦下午尽快发货。转账了,麻烦下午尽快发货。转账了,麻烦下午尽快发货。",//   "time": "17:45",//   "phone": "18888888888",//   "number": "3"// }],//存储条件查询时 原来的数组findList: [],// 搜索联系人find: '',// 发送文字textarea: '',// 模拟对话dialogueInfo: {index: 0,hasMsg: true,targetId: "", //对方的idname: "", //对方的名字phone: "", //对方的手机号head: "https://gitee.com/uploads/61/632261_smallweigit.jpg", //对方的头像dialogueList: [//   {//   // 判断是对方//   other: true,//   head: "https://gitee.com/uploads/61/632261_smallweigit.jpg",//   text: "在吗?我发询价了(右后减震器、左后减震器防尘套)需要原厂件请尽快报价。",//   // img: "http://124.128.226.225:8083/upload/1301812392719626241.png",//   // audio: "https://www.w3school.com.cn/i/horse.ogg",//   // video: "https://www.w3school.com.cn/i/movie.ogg",//   date: "2019-07-17 9:25:15",//   send: false,//   name: "济南亨达通汽修厂1"// },],},// 右边的聊天记录,用于判断是对方说的,ture,选择样式1isOther: true,center_wrapper_center_item: "center_wrapper_center_item",center_wrapper_center_item_reserve: "center_wrapper_center_item_reserve",// 判断是否显示聊天记录showHistory: false,// 点击的子项targetId: "",//我的targetIdmytargetId: "",//我的头像myhead: '',//我的名字myname: '',// 上传文件fileList: [],imageUrl: '',// 新增上滚方法scrollHeight: 0,list: [],loadText: "加载中...",pageNum: 1,loadText1: "加载中...",pageNum1: 1,// 模拟图片放大url: 'http://gudian-qpc.oss-cn-hangzhou.aliyuncs.com/2020/1329338563854811138.png',srcList: ['http://gudian-qpc.oss-cn-hangzhou.aliyuncs.com/2020/1329338563854811138.png',],loading: false,// 表情包列表emojiList: []}},created() {this.loadComments();getToken().then(res => {var appkey = 'vnroth0kvb2mo'var token = res.data.data;this.init(appkey, token)// 默认是当前对话this.targetId = this.dialogueInfo.targetId});// this.notifyByOrder();},// 将滚动条定位到底部updated() {// 中间的聊天框const dialogue_box = this.$refs.dialogue_box;dialogue_box.scrollTop = dialogue_box.scrollHeight;// 右边的聊天记录if (this.$refs.dialogue_record) {const dialogue_record = this.$refs.dialogue_record;dialogue_record.scrollTop = dialogue_record.scrollHeight;this.handleRightScroll();}},mounted() {this.handleCenterScroll();},methods: {//初始化个人信息loadComments() {var info = JSON.parse(localStorage.getItem("saber-userInfo"));this.myhead = info.content.avatar;this.myname = info.content.nick_name;},//初始化链接方法init: function(appkey, token) {var _this = this;var params = {appkey: appkey,token: token}RongIMEmoji.init();this.emojiList = RongIMLib.RongIMEmoji.list;RongIMClient.init(appkey, null, params);RongIMClient.setConnectionStatusListener({onChanged: function(status) {switch (status) {case RongIMLib.ConnectionStatus['CONNECTED']:case 0:console.log('连接成功')_this.$store.commit("SET_LINK_STATE", 1);breakcase RongIMLib.ConnectionStatus['CONNECTING']:case 1:console.log('连接中')breakcase RongIMLib.ConnectionStatus['DISCONNECTED']:case 2:console.log('当前用户主动断开链接')breakcase RongIMLib.ConnectionStatus['NETWORK_UNAVAILABLE']:case 3:console.log('网络不可用')breakcase RongIMLib.ConnectionStatus['CONNECTION_CLOSED']:case 4:console.log('未知原因,连接关闭')breakcase RongIMLib.ConnectionStatus['KICKED_OFFLINE_BY_OTHER_CLIENT']:case 6:console.log('用户账户在其他设备登录,本机被踢掉线')breakcase RongIMLib.ConnectionStatus['DOMAIN_INCORRECT']:case 12:console.log('当前运行域名错误,请检查安全域名配置')break}}})RongIMClient.setOnReceiveMessageListener({// 接收到的消息onReceived: function(message) {// 判断消息类型switch (message.messageType) {case RongIMClient.MessageType.TextMessage:_this.handleGetTxt(message);break;case RongIMClient.MessageType.ImageMessage:_this.handleGetImg(message);break;case RongIMClient.MessageType.VoiceMessage:_this.handleGetVoice(message);break;}}})RongIMClient.connect(token, {onSuccess: function(userId) {console.log('链接成功,id:' + userId)_this.mytargetId = userId_this.getChatList(true);},onTokenIncorrect: function() {console.log('token无效')},onError: function(errorCode) {switch (errorCode) {case RongIMLib.ErrorCode.TIMEOUT:console.log('超时')break;case RongIMLib.ConnectionState.UNACCEPTABLE_PAROTOCOL_VERSION:console.log('不可接受的协议版本')break;case RongIMLib.ConnectionState.IDENTIFIER_REJECTED:console.log('appkey不正确')break;case RongIMLib.ConnectionState.SERVER_UNAVAILABLE:console.log('服务器不可用')break;}}}, null)},//处理接收到的文字消息handleGetTxt: function(message) {var info = {text: RongIMEmoji.symbolToEmoji(message.content.content),date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),send: false}if (message.senderUserId == this.mytargetId) {//我发出去的(比如app端发出去的,pc端会收到)info.other = false;info.head = this.myheadinfo.name = this.mynamethis.chatList[this.dialogueInfo.index].info = RongIMEmoji.symbolToEmoji(message.content.content);this.dialogueInfo.dialogueList.push(info)} else if (message.senderUserId == this.dialogueInfo.targetId) {//对方发出去的info.other = true;info.head = this.dialogueInfo.headinfo.name = this.dialogueInfo.namethis.chatList[this.dialogueInfo.index].info = RongIMEmoji.symbolToEmoji(message.content.content);this.dialogueInfo.dialogueList.push(info)} else {//聊天列表其他人发出去的(不是现在聊天的人)var flag = false;for (var i = 0; i < this.chatList.length; i++) {if (this.chatList[i].targetId == message.senderUserId) {flag = true;this.chatList[i].info = RongIMEmoji.symbolToEmoji(message.content.content);if (this.chatList[i].number == '') {this.chatList[i].number = '1'} else {this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();}break;}}if (!flag) {this.getChatList(false)}}// console.log('新消息 ' + message.targetId + ':' + JSON.stringify(message))},//处理图片方法handleGetImg: function(message) {var info = {srcList: [message.content.imageUri],img: message.content.imageUri,date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),send: false}if (message.senderUserId == this.mytargetId) {//我发出去的(比如app端发出去的,pc端会收到)info.other = false;info.head = this.myheadinfo.name = this.mynamethis.chatList[this.dialogueInfo.index].info = '[图片]';this.dialogueInfo.dialogueList.push(info)} else if (message.senderUserId == this.dialogueInfo.targetId) {//对方发出去的info.other = true;info.head = this.dialogueInfo.headinfo.name = this.dialogueInfo.namethis.chatList[this.dialogueInfo.index].info = '[图片]';this.dialogueInfo.dialogueList.push(info)} else {//聊天列表其他人发出去的(不是现在聊天的人)var flag = false;for (var i = 0; i < this.chatList.length; i++) {if (this.chatList[i].targetId == message.senderUserId) {flag = true;this.chatList[i].info = '[图片]';if (this.chatList[i].number == '') {this.chatList[i].number = '1'} else {this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();}break;}}if (!flag) {this.getChatList(false)}}},//处理语音方法handleGetVoice: function(message) {var info = {video: message.content.remoteUrl,date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),send: false}if (message.senderUserId == this.mytargetId) {//我发出去的(比如app端发出去的,pc端会收到)info.other = false;info.head = this.myheadinfo.name = this.mynamethis.chatList[this.dialogueInfo.index].info = '[语音]';this.dialogueInfo.dialogueList.push(info)} else if (message.senderUserId == this.dialogueInfo.targetId) {//对方发出去的info.other = true;info.head = this.dialogueInfo.headinfo.name = this.dialogueInfo.namethis.chatList[this.dialogueInfo.index].info = '[语音]';this.dialogueInfo.dialogueList.push(info)} else {//聊天列表其他人发出去的(不是现在聊天的人)var flag = false;for (var i = 0; i < this.chatList.length; i++) {if (this.chatList[i].targetId == message.senderUserId) {flag = true;this.chatList[i].info = '[语音]';if (this.chatList[i].number == '') {this.chatList[i].number = '1'} else {this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();}break;}}if (!flag) {this.getChatList(false)}}},//获取左侧聊天列表方法getChatList: function(flag) {var _this = this;RongIMClient.getInstance().getConversationList({onSuccess: function(list) {//处理一下图片和语音list.forEach((item) => {switch (item.latestMessage.messageType) {case "ImageMessage":item.latestMessage.content.content = '[图片]'break;case "HQVoiceMessage":item.latestMessage.content.content = '[语音]'break;}})getChatList(JSON.stringify(list)).then(res => {var chatList = res.data.datachatList.forEach((item) => {item.info = RongIMEmoji.symbolToEmoji(item.info)if (item.time > new Date(new Date().toLocaleDateString()).getTime()) {item.time = dateFormat(new Date(item.time), 'hh:mm')} else if (item.time > (new Date(new Date().toLocaleDateString()).getTime() -86400000)) {item.time = '昨天'} else {item.time = dateFormat(new Date(item.time), 'MM-dd')}})_this.chatList = chatListif (flag && _this.chatList.length > 0) {_this.clickItem(_this.chatList[0], 0)}});},onError: function(error) {console(error)}}, null);},//清除未读方法(聊天列表左侧角标)clearCount: function(item) {var conversationType = RongIMLib.ConversationType.PRIVATE;var targetId = item.targetId;RongIMClient.getInstance().clearUnreadCount(conversationType, targetId, {onSuccess: function() {},onError: function(error) {}});item.number = ''},//获取聊天记录getDialogueInfo: function(targetId, flag) {var _this = this;var conversationType = RongIMLib.ConversationType.PRIVATE;var targetId = targetId; // 想获取自己和谁的历史消息,targetId 赋值为对方的 Idvar timestrap = flag ? 0 : null; // 默认传 null,若从头开始获取历史消息,请赋值为 0, timestrap = 0;var count = 20; // 每次获取的历史消息条数,范围 0-20 条,可以多次获取var data = [];RongIMLib.RongIMClient.getInstance().getHistoryMessages(conversationType, targetId, timestrap, count, {onSuccess: function(list, hasMsg) {_this.dialogueInfo.hasMsg = hasMsg;list.forEach((item) => {var info = {date: dateFormat(new Date(item.sentTime), 'yyyy-MM-dd hh:mm:ss'),send: false}switch (item.messageType) {case 'TextMessage':info.text = RongIMEmoji.symbolToEmoji(item.content.content);break;case 'ImageMessage':info.srcList = [item.content.imageUri];info.img = item.content.imageUri;break;case 'HQVoiceMessage':info.video = item.content.remoteUrl;break;}if (item.senderUserId == _this.mytargetId) {info.other = false;info.head = _this.myheadinfo.name = _this.myname} else {info.other = true;info.head = _this.dialogueInfo.headinfo.name = _this.dialogueInfo.name}data.push(info)})_this.dialogueInfo.dialogueList = [...data, ..._this.dialogueInfo.dialogueList]},onError: function(error) {console.log('GetHistoryMessages, errorcode:' + error);}});},//发送文字方法sendTxt: function(txt) {var msg = new RongIMLib.TextMessage({content: txt});var conversationType = RongIMLib.ConversationType.PRIVATE; // 单聊, 其他会话选择相应的会话类型即可var targetId = this.dialogueInfo.targetId; // 目标 Idvar _this = this;var param = {other: false,head: _this.myhead,text: _this.textarea,send: false,date: dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'),name: "我"}RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {onSuccess: function(message) {_this.dialogueInfo.dialogueList.push(param)},onError: function(errorCode, message) {param.send = true;_this.dialogueInfo.dialogueList.push(param);console.log('发送失败: ' + info + errorCode);},});},// 点击聊天列表的某一项clickItem(item, index) {this.dialogueInfo.index = index;this.dialogueInfo.targetId = item.targetId;this.dialogueInfo.name = item.name;this.dialogueInfo.head = item.head;this.dialogueInfo.phone = item.phone;this.dialogueInfo.hasMsg = true;// 设置选中的 targetIdthis.targetId = item.targetId;this.clearCount(item);this.dialogueInfo.dialogueList = [];//从头获取聊天记录this.getDialogueInfo(item.targetId, true);this.dialogueInfo.hasMsg = true;this.pageNum = 1;this.pageNum1 = 1;},getMore() {this.getDialogueInfo(this.dialogueInfo.targetId, false);this.pageNum++;this.pageNum1++;},// 搜索框变化searchChange() {//初始化的时候,给findList赋值if (this.findList.length == 0 && this.chatList.length != 0) {this.findList = this.chatList;}if (this.find == null || this.find == '') {this.chatList = this.findList;this.findList = [];} else {var list = [];this.findList.forEach((item) => {if (item.name.indexOf(this.find) != -1) {list.push(item)}})this.chatList = list}},// 点击发送sendTextarea() {if (this.textarea != '' && this.textarea != null) {this.sendTxt(this.textarea);this.chatList[this.dialogueInfo.index].info = this.textarea;this.chatList[this.dialogueInfo.index].time = dateFormat(new Date(), 'hh:mm')this.textarea = '';}},// 点击出现聊天记录clickHistory() {this.showHistory = !this.showHistory;},// 上传前校验beforeAvatarUpload(file) {const isImage = file.type.includes("image");const isLt2M = file.size / 1024 / 1024 < 20;if (!isImage) {this.$message.error("上传文件类型必须是图片!");}if (!isLt2M) {this.$message.error('上传头像图片大小不能超过 2MB!');}return isImage && isLt2M;},// 上传成功handleAvatarSuccess(res, file) {var url = res.data.url;var info = {srcList: [url],loading: true,img: URL.createObjectURL(file.raw),date: dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'),send: false,other: false,head: this.myhead,name: this.myname,}this.chatList[this.dialogueInfo.index].info = '[图片]';this.chatList[this.dialogueInfo.index].time = dateFormat(new Date(), 'hh:mm');this.dialogueInfo.dialogueList.push(info);var index = this.dialogueInfo.dialogueList.length;var a = 150;var base64 = "";var canvas = document.createElement("canvas");var ctx = canvas.getContext('2d');var Img = new Image();Img.setAttribute("crossOrigin", 'anonymous')Img.src = url;Img.onload = function() {var width = ""var height = ""if (Img.width > Img.height) {width = a;height = a * Img.height / Img.width;} else {width = a * Img.width / Img.height;height = a;}canvas.width = width;canvas.height = height;ctx.drawImage(Img, 0, 0, width, height)base64 = canvas.toDataURL('image/jpeg')};var msg = new RongIMLib.ImageMessage({content: base64,imageUri: url});var conversationType = RongIMLib.ConversationType.PRIVATE; // 单聊, 其他会话选择相应的会话类型即可var targetId = this.dialogueInfo.targetId; // 目标 Idvar _this = this;RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {onSuccess: function(message) {if (_this.dialogueInfo.dialogueList.length >= index) {_this.dialogueInfo.dialogueList[index - 1].loading = false;}},onError: function(errorCode, message) {console.log('发送失败:' + info + errorCode);}});},// 中间聊天框的上滚事件handleCenterScroll() {// this.getMore();const dialogue_box = this.$refs.dialogue_box;//这里的定时是为了列表首次渲染后获取scrollHeight并滑动到底部setTimeout(() => {this.scrollHeight = dialogue_box.scrollHeight;dialogue_box.scrollTo(0, this.scrollHeight);}, 10);dialogue_box.addEventListener('scroll', (e) => {//这里的2秒钟定时是为了避免滑动频繁,节流setTimeout(() => {if (!this.dialogueInfo.hasMsg) {this.loadText = "加载完成";return;}//滑到顶部时触发下次数据加载if (e.target.scrollTop == 0) {//将scrollTop置为10以便下次滑到顶部e.target.scrollTop = 10;//加载数据this.getMore();setTimeout(() => {e.target.scrollTo(0, this.scrollHeight - 30); //-30是为了露出最新加载的一行数据}, 100);}}, 2000);});},// 右边聊天记录的上滚事件handleRightScroll() {// this.getMore();const dialogue_record = this.$refs.dialogue_record;//这里的定时是为了列表首次渲染后获取scrollHeight并滑动到底部// setTimeout(() => {//   this.scrollHeight = dialogue_record.scrollHeight;//   dialogue_record.scrollTo(0, this.scrollHeight);// }, 10);dialogue_record.addEventListener('scroll', (e) => {//这里的2秒钟定时是为了避免滑动频繁,节流setTimeout(() => {if (!this.dialogueInfo.hasMsg) {// this.loadText = "加载完成";this.loadText1 = "加载完成";return;}//滑到顶部时触发下次数据加载if (e.target.scrollTop == 0) {//将scrollTop置为10以便下次滑到顶部e.target.scrollTop = 10;//加载数据this.getMore();//这里的定时是为了在列表渲染之后才使用scrollTo。setTimeout(() => {e.target.scrollTo(0, this.scrollHeight - 30); //-30是为了露出最新加载的一行数据}, 100);}}, 2000);});},// 点击单个表情包clickEmoji(emoji) {this.textarea += emoji},}}
</script><style scoped>.whole-wrapper {display: flex;background: #fff;/* height: 700px; */height: 90%;}/* 左边部分 */.left_whole_wrapper {display: flex;flex-direction: column;width: 24%;}.left_wrapper {flex: 1;}.left-item {display: flex;justify-content: space-between;padding: 18px 24px;}.active {background: #ebebeb;}.left-item-left {display: flex;}.left-item-head>img {width: 48px;height: 48px;border-radius: 50%;}.left-item-info {margin-left: 12px;max-width: 220px;display: flex;flex-direction: column;justify-content: space-around;}.left-item-info_title {font-size: 14px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: left;color: #292929;/* 文字超出处理 */white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}.left-item-info_content {font-size: 14px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: left;color: #909090;margin-top: 4px;/* 文字超出处理 */white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}.left-item-time {display: flex;flex-direction: column;text-align: right;align-items: flex-end;margin-left: 20px;}.left-item-time-time {font-size: 14px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: right;color: #909090;}.left-item-time-number {width: 20px;height: 20px;line-height: 20px;border-radius: 50%;background: #ff4949;color: #ffffff;text-align: center;font-size: 12px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;margin-top: 5px;}.search {padding: 36px 24px;height: 5%;}/* 中间部分*/.center_whole_wrapper {flex: 1;background: #f8f8f8;}.center_wrapper {height: 100%;display: flex;flex-direction: column;}.center_wrapper_top {display: flex;align-items: center;padding: 30px 24px;flex: 1;}.center_wrapper_top_name {font-size: 18px;font-family: PingFang SC, PingFang SC-Bold;font-weight: 700;text-align: left;color: #292929;}.center_wrapper_top_number {font-size: 14px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: left;color: #292929;margin-left: 12px;}.center_wrapper_center {flex: 10;padding: 30px 24px 0px 24px;border-top: 1px solid #c7c7c7;border-bottom: 1px solid #c7c7c7;}.center_wrapper_center_item {display: flex;margin-bottom: 32px;}.center_wrapper_right {flex: 4;padding: 20px 20px;position: relative;}.center-item-info_wrapper {margin: 0px 16px;}.center-item-tip {display: flex;align-items: center;}.error-tip>img {width: 20px;margin: 0 10px;}.center-item-info {max-width: 336px;font-size: 14px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: left;color: #909090;line-height: 22px;background: #f1f1f1;padding: 16px;}.center-item-time {font-size: 12px;font-family: PingFang SC, PingFang SC-Regular;font-weight: 400;text-align: left;color: #909090;line-height: 22px;margin-top: 12px;}/* 反向样式开始*/.center_wrapper_center_item_reserve {display: flex;flex-direction: row-reverse;margin-bottom: 32px;}.center_wrapper_center_item_reserve .center-item-time {text-align: right;}.center_wrapper_center_item_reserve {display: flex;flex-direction: row-reverse;margin-bottom: 32px;}.center_wrapper_center_item_reserve .center-item-tip {display: flex;flex-direction: row-reverse;align-items: center;}.center_wrapper_center_item_reserve .error-tip>img {width: 20px;margin: 0 10px;}/* 反向样式结束*//* 右边样式 */.right_whole_wrapper {background: #fff;}.right_wrapper {flex: 1;}.right_wrapper_center {border: none;color: #909090;}.center-item-name {font-size: 12px;}.center-item-info {margin-top: 10px;}.center-item-info_img {width: 150px;/* height: 100px; */}.center-item-info_img>img {width: 100%;height: 100%;}/* 几个图标 */.icon-list {display: flex;}.icon-list>div:not(:first-child) {margin-left: 15px;}.icon-item-img {width: 25px;}/* 修改组件样式 */.whole-wrapper>>>.el-input__inner {border-radius: 30px;}.whole-wrapper>>>.el-textarea__inner {min-height: 80px;resize: none;border: none;background: #f8f8f8;padding: 5px 0px;}.whole-wrapper>>>.el-button--primary {width: 100px;height: 40px;position: absolute;bottom: 20px;right: 20px;}.loading {text-align: center;color: #909090;}.loading span {margin-left: 10px;}
</style>

这篇关于vue+elementUI 集成融云 实现IM即时通讯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/621829

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount