<!doctype html> <html> <head> <meta charset="utf-8"> <title> </title> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="format-detection" content="telephone=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <style> html,body{ width: 100%; height: 100%; margin: 0; padding: 0; } input[type="button"],button{ -webkit-appearance: none; } a{ color: #428bca; text-decoration:none; } .cs-box{ width: 100%; height: 100%; margin: 0; padding: 0; display: flex; flex-direction: column; position: relative; overflow: hidden; } .cs-box h4{ text-align: center; height: 30px; line-height: 30px; width: 100%; background: #229ffd; color: rgb(255, 255, 255); margin: 0; } .cs-chat{ overflow-y: auto; padding: 10px; height: 380px; word-wrap: break-word; background-color: #f3f5f7; flex: 1 1 auto; } .cs-submit{ width: 100%; background-color:gainsboro; flex: 0 0 auto; display: flex; justify-content: space-around; padding: 0.266667rem; position: relative; } .txt{ display:flex; -webkit-box-sizing: border-box; box-sizing: border-box; border: 1px solid #d7d7d7; border-radius: 0.16rem; overflow: hidden; position: relative; background:#fcfafa; width: 80%; } .btn{ display: flex; position: relative; } .txt .content{ outline: none; border: none; background: none; width: 95%; min-height: 0.9rem; padding: 0.266667rem 0 0.133333rem 0; line-height: 0.9rem; white-space: pre-wrap; overflow-x: hidden; overflow-y: scroll; font-size: 18px; resize: none; color: #353535; display: inline-block; } .btn input{ padding: 0.25rem 1rem; border-radius: 5px; box-sizing: border-box; background-color: #428bca; color: #fff; text-align: center; vertical-align: middle; border: 1px solid transparent; font-weight: 500; margin-right: 8px; outline: none; } .txt .uploadimg{ width: 2rem; height: 1.9rem; margin:0.1rem; border-radius: 10%; background: url(img/img.png) no-repeat; background-size: contain; text-align: center; box-sizing: border-box; border: 1px solid transparent; display: inline-block; background-color: #eee; } .txt .uploadimg input{ opacity: 0; width: 100%; height: 100%; } .chat-box{ position: relative; width: 100%; margin: 5px 0; } .info{ display: inline-block; width:2.2rem; height:2.2rem; line-height: 2.2rem; overflow: hidden; vertical-align: top; font-size: 13px; background-color: #229ffd; border-radius: 50%; text-align: center; color: #fff; padding: 0.1rem; margin-right:6px; } .chat-text{ display: inline-block; vertical-align: top; position: relative; padding: 0.4rem 0.3rem; max-width: 80%; white-space: pre-wrap; border: 1px solid #DEDEDE; background-color: #fff; border-radius: 4px; box-sizing: border-box; color: #252525; } .service{ text-align: left; } .custom{ text-align: right; } .custom .chat-text{ margin-right:6px; background-color: #A5DE37; color: #fff; } .service-text:before { content: ''; position: absolute; top: 50%; left: -4px; width: 5px; height: 5px; background: #fff; border-top: 1px solid #DEDEDE; border-left: 1px solid #DEDEDE; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } #custom .chat-text:after { content: ''; position: absolute; top: 50%; right: -10px; width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid #A5DE37; -webkit-transform: translate(0, -50%); transform: translate(0, -50%); } .copyright{ width: 100%; height:1rem; line-height: 1rem; background-color:gainsboro; flex: 0 0 auto; display: flex; position: relative; text-align: center; font-size: 10px; color:#353535; } .system{ text-align: center; color:gray; font-size: 13px; margin: 10px 0; } .funbtn{ text-align: center; width: 50%; height: 1.5rem; line-height: 1.5rem; font-size: 15px; margin-left: 25%; text-decoration: underline; color:#229ffd; } .tips{ position: absolute; width: 100%; height: 1.5rem; line-height: 1.5rem; top: -1.5rem; left: 0; font-size: 12px; padding-left: 0.4rem; } .warn{ background:rgba(254,174,27, 0.8); color:#fff; } .error{ background:rgba( 255,67,81, 0.8); color:#fff; } .normal{ background:rgba(27,154,247, 0.8); color:#fff; } .des{ background:rgb(81, 206, 255); color:#fff; } </style> </head> <body> <div class="cs-box"> <h4>客服聊天<span id="state"></span></h4> <div id="cs-chat" class="cs-chat"> <div class="chat-box service" id="help"> <div class="info des">客服</div> <span class="chat-text service-text">您好,有什么需要帮助的吗?</span> </div> </div> <div class="cs-submit"> <div class="txt"> <textarea id="content" class="content" placeholder="请输入您的问题"></textarea> <div class="uploadimg"> <input accept="image/*" type="file" id="img" onchange="uploadimg()" /> </div> </div> <div class="btn"> <input type="button" value="发送" id="send"/> </div> <div class="tips" id="tips" hidden="hidden"></div> </div> <div class="copyright"> </div> <input type="text" hidden="hidden" id="guestid"> </div> <script> var server="https://liveauth.ishuaji.cn"; var cdn="https://app.ixiulive.com/"; var ws; var checkTimer; var sendtime=0; var map = new Map(); var recOk=true; $(function(){ btninit(); params(); }); function params(){ var url = window.location.search; var ua = window.navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i) == 'micromessenger'){ map.set('ua','wechat'); }else{ map.set('ua','other'); } map.set('pkg','wechat'); map.set('cid','wechat'); map.set('gzh','yabo'); // if (url.indexOf("?") != -1) { // var p = url.substr(1); // keys = p.split("&"); // for (i = 0; i < keys.length; i++) { // map.set(keys[i].split("=")[0],keys[i].split("=")[1]); // if("guestid"===keys[i].split("=")[0]){ // setCookie('cs-guestid',keys[i].split("=")[1],3); // } // } // } } function btninit(){ connect(false); $("#send").click(function(){ sendmsg(); }); // $("#img").click(function(){ // var guestid=$("#guestid").val(); // if(null==guestid||guestid==''){ // //连接客服 // system('正在转接客服,请稍等'); // connect(false); // } // }); } function sendmsg(){ var content=$("#content").val(); if(null==content||content==''){ tips("不可以发送空消息","error",5000); return; } if(content.length>120){ tips("内容2超过最大限制","warn",5000); return;2 } var guestid=$("#guestid").val(); if(null==guestid||guestid==''){ //连接客服 system('正在转接客服,请稍等'); connect(true); }else{ send(content,2001) } } function connect(send){ var guestid=getCookie('cs-guestid'); $.ajax({ url:server+"/guest/service", data:{guestid:guestid}, dataType:"json", type:"POST", success:function(data){ if(data.code==1){ guestid=data.guestid; $("#guestid").val(guestid); setCookie('cs-guestid',guestid,3) var list=data.history; if(list!=null&&list.length>0&&sendtime==0){ $("#help").remove(); $.each(list,function(i,msg){ historybulid(msg.mtype,msg.content,msg.fid,msg.mid); if(i==list.length-1){ system('---上次聊到这里('+msg.sendtime+')---'); $("#cs-chat").append('<div class="system">---------------</div>'); } }); } if(data.more){ $("#cs-chat").prepend('<div class="funbtn" onclick="more()">更早的聊天记录</div>'); } WebSocketStart(guestid,send); }else{ system("连接失败("+data.code+")"); } }, error:function(){ system("网络异常"); } }); } function more(){ var guestid=$("#guestid").val(); var index= $("#cs-chat").children(".chat-box").eq(0).attr("data-mid"); $.ajax({ url:server+"/guest/chathistory", data:{guestid:guestid,index:index}, dataType:"json", type:"POST", success:function(data){ if(data.code==1){ $("#cs-chat").find(".funbtn").remove(); var list=data.history; if(list.length>0){ $.each(list,function(i,msg){ historybulid(msg.mtype,msg.content,msg.fid,msg.mid); if(i==list.length-1){ $("#cs-chat").prepend('<div class="funbtn" onclick="more()">更早的聊天记录</div>'); } if(i==0){ $("#cs-chat").prepend('<div class="system">'+msg.sendtime+'</div>'); } }); }else{ $("#cs-chat").prepend('<div class="system">哦豁,没有了</div>'); } }else{ $("#cs-chat").prepend('<div class="system">获取失败('+data.code+')</div>'); } }, error:function(){ $("#cs-chat").prepend('<div class="system">服务出错</div>'); } }); } function system(msg){ var sysmsg='<div class="system">'+msg+'</div>'; var cname= $("#cs-chat").children("div:last-child").attr("class"); if(cname=='system'){ $("#cs-chat").children("div:last-child").text(msg); }else{ var chat=$("#cs-chat"); chat.append(sysmsg); var offset=chat[0].scrollHeight-chat[0].clientHeight; if(offset-chat[0].scrollTop<(500)){ chat.animate({scrollTop: chat.scrollHeight}, 500); }else{ tips("有新的系统消息","normal",3000); } } } function state(msg){ $("#state").text("("+msg+")"); } function tips(msg,type,time){ if(time>0){ $("#tips").removeClass("error warn normal").addClass(type).text(msg).show().delay(time).hide(300); }else{ $("#tips").removeClass("error warn normal").addClass(type).text(msg).show(); } } function removetips(){ $("#tips").hide(); } function msgbulid(type,msg,kf,fid){ var content=""; var size=200; if(fid>0){ if(fid==1){ content+='<div class="chat-box service"><div class="info des">客服</div><span class="chat-text service-text">'; }else{ content+='<div class="chat-box service"><div class="info">客服</div><span class="chat-text service-text">'; } }else{ content+='<div class="chat-box custom"><span class="chat-text ">'; } if(type==1){ content+=msg+'</span></div>'; }else{ if(fid>0){ msg+='?x-oss-process=image/resize,p_95'; }else{ msg+='?x-oss-process=image/resize,l_'+size+',m_mfit'; } content+='<img width="200px" src="'+cdn+msg+'"></span></div>'; } var chat=$("#cs-chat"); chat.append(content); var offset=chat[0].scrollHeight-chat[0].clientHeight; if(offset-chat[0].scrollTop<(chat[0].clientHeight/2)){ chat.animate({scrollTop: chat.scrollHeight}, 1000); }else{ if(fid>0){ tips("收到一条新消息","normal",3000); } } if(type==2){ system('长按图片即可放大或保存到手机查看'); } } function historybulid(type,msg,fid,mid){ var content=""; var size=200; if(fid>0){ content+='<div class="chat-box service" data-mid="'+mid+'"><div class="info des">客服</div><span class="chat-text service-text">'; }else{ content+='<div class="chat-box custom" data-mid="'+mid+'"><span class="chat-text ">'; } if(type==1){ content+=msg+'</span></div>'; }else{ if(fid>0){ msg+='?x-oss-process=image/resize,p_95'; }else{ msg+='?x-oss-process=image/resize,l_'+size+',m_mfit'; } content+='<img width="200px" src="'+cdn+msg+'"></span></div>'; } $("#cs-chat").prepend(content); } function WebSocketStart(guestid,send) { state("连接中"); if(ws!=null&&ws.readyState == WebSocket.OPEN){ system("The socket is opening,please close first!"); return; } if ("WebSocket" in window) { // 打开一个 web socket var url="wss://zhiboweb.ishuaji.cn/yzsocket/ws?guestid="+guestid+"&type=5"; try { ws = new WebSocket(url); }catch(err){ console.error("WebSocket connect error:", err); system("连接失败"); } ws.onopen = function() { recOk=true; state("连接成功"); system("客服已接入"); if(send){ sendmsg(); }else{ $("#guestid").val(guestid); } checkTimer=setInterval("check()",60000); }; ws.onmessage = function (evt) { var msg=JSON.parse(evt.data); if(msg.uid!='0'){ msgbulid(msg.mtype,msg.content,msg.kfName,msg.fid); sendtime=new Date().getTime(); } }; ws.onclose = function(event) { state("连接断开"); $("#guestid").val(''); tips("连接已断开","error",3000); if(recOk){ var guestid=$("#guestid").val(); WebSocketStart(guestid,false) recOk=false; } console.error("WebSocket close observed:", event); }; ws.onerror = function(event) { // 关闭 websocket if(recOk){ var guestid=$("#guestid").val(); WebSocketStart(guestid,false) recOk=false; } state("连接错误"); msgbulid(1,"会话意外断开,发送消息即可联系客服","系统",1); console.error("WebSocket error observed:", event); }; } else{ // 浏览器不支持 WebSocket state("不支持"); } } function check(){ if(sendtime>0){ var min=3; var cut=2; var time=new Date().getTime()-sendtime; if(time>1000*60*min&&time<1000*60*min+1){ var index= $(".chat-box").last().attr("class").indexOf("service"); if(index>-1){ msgbulid(1,"客服还没有等到您的回复,系统将在"+cut+"分钟后关闭会话","系统",1); } } if(new Date().getTime()-sendtime>1000*60*(min+cut)){ var index= $(".chat-box").last().attr("class").indexOf("service"); if(index>-1){ msgbulid(1,"因您长时间未回复,本次会话已经中止,如果还有问题需要咨询,请直接发送消息","系统",1); checkTimer=null; sendtime=-1; recOk=false var guestid=$("#guestid").val(); map.set("guestid",guestid); var msg=new WsMsg(2100,'',JSON.stringify(mapToObj(map))); ws.send(JSON.stringify(msg)); $("#guestid").val(''); ws.close(); } } } } function send(message,cid) { if (!window.WebSocket) { return; } if (ws.readyState == WebSocket.OPEN) { var guestid=$("#guestid").val(); map.set("guestid",guestid); var msg=new WsMsg(cid,message,JSON.stringify(mapToObj(map))); ws.send(JSON.stringify(msg)); if(cid==2001){ msgbulid(1,message,'',0) }else{ msgbulid(2,message,'',0) } $("#content").val(''); sendtime=new Date().getTime(); } else { tips("连接已断开","error",3000); state("连接断开"); } } function mapToObj(strMap){ let obj= Object.create(null); for (let[k,v] of strMap) { obj[k] = v; } return obj; } function WsMsg(cid,content,extend) { this.time = new Date().getTime(); this.msgid=Math.random().toString(36).slice(-8); this.cid = cid; this.content = content; this.extend = extend; this.toUid=2000; } function uploadimg(){ var file=$("#img")[0].files; if(file.length<1){ return; } if(file.length>1){ tips("每次只可选择一个图片","error",3000); return; } if(file[0].size>10485760){ tips("超过限制,最大支持10M的图片","error",5000); return; } var guestid=$("#guestid").val(); var formdata = new FormData(); formdata.append("img",file[0]); formdata.append("guestid",guestid); var url=server+"/guest/upload/img"; var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.open("post", url, true); xhr.onload = function () { if(xhr.status==200){ var result = xhr.responseText; var json = eval("(" + result + ")"); switch (json.code) { case 1: // var path=cdn+; send(json.imgkey,2002); $("#img").val(''); break; default: system(json.msg); $("#img").val(''); break; } }else{ system(xhr.status); tips("上传发生错误"+xhr.status,"error",3000); } }; xhr.onerror = function(e) { tips("上传发生错误"+e,"error",3000); }; xhr.send(formdata); } function uploadProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); tips("上传中("+percentComplete+"%)","normal"); if(percentComplete==100){ tips("上传完成","normal",3000); } } else { tips("上传失败","error",3000); } } function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+d.toUTCString(); document.cookie = cname + "=" + cvalue + "; " + expires; } function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i=0; i<ca.length; i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1); if (c.indexOf(name) != -1) return c.substring(name.length, c.length); } return ""; } function clearCookie(name) { setCookie(name, "", -1); } </script> </body> </html>