<html lang="cn"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content="陶士涵"> <title>GO-FLY咨询页</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/theme-chalk/index.css"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/index.js"></script> <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script> <!-- Bootstrap core CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <style> html, body { height: 100%; } body { } .chatContext{ background: #fff;padding:0 10px; width: 100%; text-align: left; position: relative; } .chatBox{ max-height: 500px; overflow-y: auto; overflow-x: hidden; margin-bottom: 80px; } .chatBox .el-col{margin:10px 0;} .chatUser{ line-height: 24px; font-size: 12px; white-space: nowrap; color: #999; text-align: left; } .chatContent{ background-color: rgb(166,212,242); color: #000; border: 1px solid rgb(152, 199, 230); padding: 8px 15px; min-height: 35px; word-break: break-all; position: relative; border-radius: 5px; display: inline-block; } .chatContent:after { content: ''; position: absolute; left: -10px; top: 13px; width: 0; height: 0; border-style: dashed; border-color: transparent; overflow: hidden; border-width: 10px; border-top-style: solid; border-top-color: rgb(166,212,242); } .chatBoxMe .chatContent{float: right;background-color: rgb(152,225,101);border: 1px solid rgb(145, 215, 96);} .chatBoxMe .chatContent:after{border-top-color: rgb(152,225,101);} .chatBoxMe .el-col-3{float: right;text-align: right;} .chatBoxMe .chatUser{text-align: right} .chatBoxMe .chatContent:after{left:auto;right: -10px;} .chatArea{margin: 10px 0;} .chatArea .el-textarea__inner{height: 100%;} .chatTitle{height: 30px;line-height: 30px;color: #1989fa} .chatBoxSend{position: fixed;bottom: 0;left: 0;width: 100%;height: 70px;} .chatBoxSendBtn{position: absolute;bottom: 1px;right: 2px;} .chatTime{text-align: center;color: #bbb;margin: 5px 0;font-size: 12px;} .chatTimeHide{display: none;} .clear{clear:both;} </style> </head> <body class="text-center"> <div id="app" style="width:100%"> <template> <!--客服代码--> <div class="chatContext"> <div class="chatBox"> <el-alert style="margin-bottom: 10px;font-size: 12px;" title="公告 : 您好,go-fly目前是即时通讯客服系统方面的小学生,还有很长的路要走,感谢您的使用和支持。" type="success"> </el-alert> <el-alert style="margin-bottom: 10px;" :title="chatTitle" :closable="false" type="success"> </el-alert> <el-row :gutter="2" v-for="v in msgList" v-bind:class="{'chatBoxMe': v.is_kefu==true}"> <el-col :span="3"><el-avatar :size="60" :src="v.avator"></el-avatar></el-col> <el-col :span="21"> <div class="chatUser"><{v.name}></div> <div class="chatContent"><{v.content}></div> </el-col> <div class="clear"></div> <div class="chatTime" v-bind:class="{'chatTimeHide': v.show_time==false}"><{v.time}></div> </el-row> </div> <div class="chatBoxSend"> <el-input type="textarea" class="chatArea" v-model="messageContent" v-on:keyup.enter.native="chatToUser"></el-input> <el-button type="primary" class="chatBoxSendBtn" size="small" v-on:click="chatToUser">发送</el-button> </div> </div> <!--//客服代码--> </template> </div> </body> <script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script src="https://cdn.bootcss.com/reconnecting-websocket/1.0.0/reconnecting-websocket.min.js"></script> <script> var KEFU_ID="{{.KEFU_ID}}"; var guest={}; guest.id = ""; guest.name = typeof(returnCitySN)!="undefined" ?returnCitySN["cip"]+"-"+returnCitySN["cname"]:"小米"; guest.avator = "/static/images/"+Math.floor(Math.random()*(14-0+1)+0)+".jpg"; guest.group = "1"; guest.to_id=KEFU_ID!=""? KEFU_ID:"kefu2"; new Vue({ el: '#app', delimiters:["<{","}>"], data: { window:window, server:"ws://"+window.location.host+"/chat_server", socket:null, msgList:[], messageContent:"", chatTitle:"正在连接...", }, methods: { //初始化websocket initConn() { let socket = new ReconnectingWebSocket(this.server);//创建Socket实例 this.socket = socket this.socket.onmessage = this.OnMessage; this.socket.onopen = this.OnOpen; this.socket.onclose = this.OnClose; }, OnOpen() { this.chatTitle="连接成功! 等待客服接入" //从缓存中取出用户 let userinfo=this.getUserInfo(); let mes = {} mes.type = "userInit"; userinfo.client_ip=returnCitySN["cip"]; userinfo.city=returnCitySN["cname"]; mes.data = userinfo; this.socket.send(JSON.stringify(mes)); }, OnMessage(e) { const redata = JSON.parse(e.data); if (redata.type == "kfOnline") { let msg = redata.data guest.to_id=msg.id; this.chatTitle=msg.name+",正在与您沟通!" } if (redata.type == "message") { let msg = redata.data guest.to_id=msg.id; let content = {} content.avator = msg.avator; content.name = msg.name; content.content = msg.content; content.is_kefu = false; content.time = msg.time; this.msgList.push(content); this.saveHistory(content); this.scrollBottom(); } }, //发送给客户 chatToUser() { if(guest.to_id==""){ this.$message({ message: '暂时没有客服接手', type: 'warning' }); return; } if(this.messageContent==""){ this.$message({ message: '不能发送空白信息', type: 'warning' }); return; } let mes = {}; mes.type = "chatMessage"; guest.content = this.messageContent; mes.data = guest; this.socket.send(JSON.stringify(mes)); this.messageContent = ""; let content = {} content.avator=guest.avator; content.content = guest.content; content.name = guest.name; content.is_kefu = true; content.time = this.getNowDate(); this.msgList.push(content); this.saveHistory(content); this.scrollBottom(); }, OnClose() { this.chatTitle="连接关闭!" }, //获取当前用户信息 getUserInfo(){ let obj=this.getCache("guest"); if(!obj){ guest.id=this.generateUUID(); this.setCache("guest",guest); obj=this.getCache("guest"); } guest=obj; return obj; }, //加载历史 getHistory:function(){ let history=this.getCache("history"); if(history==null){ history=[]; } $.each(history,function(i,val){ history[i]["show_time"]=false; let lastKey=(i+1)>=history.length?i:i+1; let lastTime=new Date(history[lastKey]["time"]).getTime(); let curTime=new Date(val["time"]).getTime(); let diffTime=lastTime-curTime if(diffTime>(1000*60*5)){ history[i]["show_time"]=true; } }); console.log(history); return history; }, //保存历史 saveHistory:function(row){ let history=this.getHistory("history"); history.push(row); this.setCache("history",history); }, //滚动到底部 scrollBottom:function(){ this.$nextTick(() => { $('.chatBox').scrollTop($(".chatBox")[0].scrollHeight); }); }, //获取日期 getNowDate : function() {// 获取日期 var d = new Date(new Date()); return d.getFullYear() + '-' + this.digit(d.getMonth() + 1) + '-' + this.digit(d.getDate()) + ' ' + this.digit(d.getHours()) + ':' + this.digit(d.getMinutes()) + ':' + this.digit(d.getSeconds()); }, //补齐数位 digit : function (num) { return num < 10 ? '0' + (num | 0) : num; }, setCache : function (key,obj){ if(typeof(Storage) !== "undefined"){ localStorage.setItem(key, JSON.stringify(obj)); } },getCache : function (key){ return JSON.parse(localStorage.getItem(key)); }, generateUUID:function () { var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = (d + Math.random()*16)%16 | 0; d = Math.floor(d/16); return (c=='x' ? r : (r&0x3|0x8)).toString(16); }); return uuid; }, //获取自动欢迎语句 getNotice : function (){ let _this=this; $.get("/notice?kefu_id="+guest.to_id,function(res) { console.log(res); if (res.result != null) { let msg = res.result; let content = {} content.avator = msg.avator; content.name = msg.nickname; content.content = msg.content; content.is_kefu = false; content.time = msg.time; setTimeout(function () { _this.msgList.push(content); _this.scrollBottom(); }, 2000); ; } }); }, }, created: function () { this.initConn(); //加载历史记录 this.msgList=this.getHistory(); //滚动底部 this.scrollBottom(); //获取欢迎 this.getNotice(); } }) </script> </html>