2406 lines
115 KiB
HTML
2406 lines
115 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<head>
|
|||
|
<meta charset="utf-8">
|
|||
|
<!--删除苹果默认的工具栏和菜单栏,默认为no显示工具栏和菜单栏。-->
|
|||
|
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
|||
|
<!--QQ强制全屏-->
|
|||
|
<meta name="x5-fullscreen" content="true">
|
|||
|
<!--UC强制全屏-->
|
|||
|
<meta name="fullscreen" content="yes">
|
|||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
|
|||
|
<title>{{.Title}}</title>
|
|||
|
<link rel="stylesheet" href="/static/cdn/element-ui/2.15.1/theme-chalk/index.min.css">
|
|||
|
<script src="/static/cdn/vue/2.6.11/vue.min.js"></script>
|
|||
|
<script src="/static/cdn/element-ui/2.15.1/index.js"></script>
|
|||
|
<script src="/static/cdn/jquery/3.6.0/jquery.min.js"></script>
|
|||
|
|
|||
|
<script src="/static/js/functions.js?v=0.6.9"></script>
|
|||
|
<link rel="stylesheet" href="/static/css/common.css?v=20240618" />
|
|||
|
<link rel="stylesheet" href="/static/css/icon/iconfont.css?v=fgjlgfda"/>
|
|||
|
<link rel="icon" href="/static/images/favicon.ico">
|
|||
|
<style>
|
|||
|
.el-message-box{
|
|||
|
width: auto;
|
|||
|
max-width: 100%;
|
|||
|
max-height: 100%;
|
|||
|
overflow: auto;
|
|||
|
}
|
|||
|
</style>
|
|||
|
</head>
|
|||
|
<body class="visitorBody">
|
|||
|
<div id="app" class="chatCenter">
|
|||
|
<template>
|
|||
|
<!--客服代码-->
|
|||
|
|
|||
|
<div class="chatEntTitle" v-show="!isIframe">
|
|||
|
<el-badge :type="onlineType" is-dot class="item">
|
|||
|
<el-avatar class="chatEntTitleLogo" :size="35" :src="noticeAvatar"></el-avatar>
|
|||
|
</el-badge>
|
|||
|
<div>
|
|||
|
<div><{chatTitle}></div>
|
|||
|
<div class="entIntro" v-show="entIntroduce!=''"><{entIntroduce}></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<div class="chatEntBox">
|
|||
|
<!--公告栏-->
|
|||
|
<div v-show="visitorNotice!=''"
|
|||
|
class="visitorNotice"
|
|||
|
>
|
|||
|
<img src='/static/images/laba.svg'/>
|
|||
|
<span><{visitorNotice}></span>
|
|||
|
<img v-on:click="visitorNotice=''" src="/static/images/cha.png" class="visitorNoticeClose"/>
|
|||
|
</div>
|
|||
|
<!--//公告栏-->
|
|||
|
<!--最小化的语音视频-->
|
|||
|
<div class="minimiCallBox" v-show="isCalling">正在语音或视频通话
|
|||
|
<div>
|
|||
|
<el-button size="mini" type="warning" plain @click="callClose();messageContent='🚫 '+flyLang.cancel;chatToUser()">挂断</el-button>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!--//最小化的语音视频-->
|
|||
|
|
|||
|
<div ref="chatVisitorPage" id="chatVisitorPage" class="chatVisitorPage" v-on:click="showExtendTool=false;showIconBtns=false;showEmojis=false">
|
|||
|
<div class="chatNotice" v-on:click="loadMoreMessages" v-show="showLoadMore">
|
|||
|
<a class="chatNoticeContent"><{flyLang.moremessage}></a>
|
|||
|
</div>
|
|||
|
|
|||
|
<div v-for="v in msgList">
|
|||
|
|
|||
|
<div class="messageBox questionBox" v-if="v.type=='question'">
|
|||
|
<div class="chatTime left" v-bind:class="{'chatTimeHide': v.show_time==false}"><span><{v.time}></span></div>
|
|||
|
<div class="left" v-if="v.is_kefu!=true" style="display: flex;">
|
|||
|
<el-avatar style="margin-right:10px;flex-shrink: 0;" :size="36" :src="v.avator"></el-avatar>
|
|||
|
<div class="chatMsgContent">
|
|||
|
<div class="chatUser" v-if="showKefuName!='off'"><{v.name}></div>
|
|||
|
<div class="chatContent chatContent2 replyContentBtn" v-html="v.content"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!--猜你想问-->
|
|||
|
<div class="messageBox" v-else-if="v.type=='card'" v-show="robotInfo.RobotCard!=''">
|
|||
|
<div class="chatNewRow">
|
|||
|
<el-avatar class="chatNewAvatar" :size="35" :src="noticeAvatar"></el-avatar>
|
|||
|
<div class="chatMsgContent" style="flex: 1">
|
|||
|
<div class="cardBox">
|
|||
|
|
|||
|
<div v-html="robotInfo.RobotCard"></div>
|
|||
|
<div v-show="topQuestionListHtml!=''">
|
|||
|
<div class='visitorReplyTitle'><{flyLang.guess}><a href="javascript:;"><i class='el-icon-refresh-left'></i> <{flyLang.huanyihuan}></a></div>
|
|||
|
<div class="cardBoxContent replyContentBtn" v-html="topQuestionListHtml"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!--//猜你想问-->
|
|||
|
<!--公众号卡片-->
|
|||
|
<div class="wechatTip" v-else-if="v.type=='wechatTip'">
|
|||
|
<img style="width:100px; margin:6px;" :src="VisitorWechatQrcodeUrl">
|
|||
|
扫描或长按左侧二维码关注公众号。<br>可同步聊天消息,防止更换浏览器消息丢失<br>并可及时接收到回复通知
|
|||
|
</div>
|
|||
|
<!--//公众号卡片-->
|
|||
|
<!--提示部分-->
|
|||
|
<div class="chatNotice" v-else-if="v.type=='notice'">
|
|||
|
<div class="chatNoticeContent" v-html="v.content"></div>
|
|||
|
</div>
|
|||
|
<!--//提示部分-->
|
|||
|
<!--询前表单-->
|
|||
|
<div class="cardBox" v-else-if="v.type=='preVisitorForm'" style="margin: 10px">
|
|||
|
您好,为了更高效精准的为您解答,请先填写下面的表单哦 ~,*星号必填,其余选填
|
|||
|
<el-form>
|
|||
|
<el-form-item label="姓名 *">
|
|||
|
<el-input v-model="preVisitorForm.name"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item label="手机">
|
|||
|
<el-input v-model="preVisitorForm.tel"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item label="微信">
|
|||
|
<el-input v-model="preVisitorForm.wechat"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item label="QQ">
|
|||
|
<el-input v-model="preVisitorForm.qq"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item label="邮箱">
|
|||
|
<el-input v-model="preVisitorForm.email"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item label="备注">
|
|||
|
<el-input type="textarea" v-model="preVisitorForm.remark"></el-input>
|
|||
|
</el-form-item>
|
|||
|
<el-form-item>
|
|||
|
<el-button type="primary" size="small" @click="postPreVisitorForm">提交</el-button>
|
|||
|
</el-form-item>
|
|||
|
</el-form>
|
|||
|
</div>
|
|||
|
<!--//询前表单-->
|
|||
|
<!--消息模板-->
|
|||
|
<div class="messageBox" v-else>
|
|||
|
<div class="chatTime left" v-bind:class="{'chatTimeHide': v.show_time==false}"><span><{v.time}></span></div>
|
|||
|
<div class="chatNewRow" v-if="v.is_kefu!=true">
|
|||
|
<el-avatar class="chatNewAvatar" :size="35" :src="v.avator"></el-avatar>
|
|||
|
<div class="chatMsgContent">
|
|||
|
<div class="chatUser" v-if="showKefuName!='off'"><{v.name}></div>
|
|||
|
<div class="chatNewContent replyContentBtn" v-html="v.content"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="chatNewRow chatNewRowMe" v-if="v.is_kefu==true">
|
|||
|
<div class="chatMsgContent">
|
|||
|
<div class="chatNewContent replyContentBtn" v-html="v.content"></div>
|
|||
|
<div class="chatReadStatus" v-show="VisitorReadStatus!='true'"><{v.read_status}></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="clear"></div>
|
|||
|
</div>
|
|||
|
<!--//消息模板-->
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
<!--评价-->
|
|||
|
<div class="commentBox" v-if="comment">
|
|||
|
<div style="font-size: 14px;color: #3e3e3e"><{flyLang.visitorCommentTitle}></div>
|
|||
|
<el-rate v-model="commentScore" style="margin-bottom: 20px"></el-rate>
|
|||
|
<el-input
|
|||
|
style="margin: 10px 0px"
|
|||
|
type="textarea"
|
|||
|
:rows="4"
|
|||
|
v-model="commentContent">
|
|||
|
</el-input>
|
|||
|
<el-button :disabled="commentScore==''" size="mini" type="primary" v-on:click="sendComment()"><{flyLang.sent}></el-button>
|
|||
|
</div>
|
|||
|
<!--//评价-->
|
|||
|
<!--视频-->
|
|||
|
<div class="remoteVideoMask messageBox" id="remoteVideoMask" v-show="isCalling">
|
|||
|
<div class="chatNewRow">
|
|||
|
<div class="chatMsgContent">
|
|||
|
<div class="chatNewContent replyContentBtn">
|
|||
|
远程音视频<br/>
|
|||
|
<video style="max-width: 500px" id="chatRtc" controls autoplay playsinline muted></video>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="chatNewRow chatNewRowMe">
|
|||
|
<div class="chatMsgContent">
|
|||
|
<div class="chatNewContent replyContentBtn">
|
|||
|
本地音视频<br/>
|
|||
|
<video style="max-width: 500px" id="chatLocalRtc" muted controls autoplay></video></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!--视频-->
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<!--热门问题-->
|
|||
|
<div class="hotQuestion" v-if="hotQuestion.length!=0 && !reconnectDialog">
|
|||
|
<a
|
|||
|
class="slideInRightItem"
|
|||
|
v-for="item in hotQuestion"
|
|||
|
v-on:click="messageContent=item;chatToUser($event)">
|
|||
|
<{item}>
|
|||
|
</a>
|
|||
|
</div>
|
|||
|
<!--//热门问题-->
|
|||
|
<!--表情图片-->
|
|||
|
<div class="faceBox visitorFaceBox" v-if="showFaceIcon">
|
|||
|
<ul class="faceBoxList">
|
|||
|
<li v-on:click="faceIconClick(i)" class="faceIcon" v-for="(v,i) in face" :title="v.name"><img :src=v.path></li>
|
|||
|
</ul>
|
|||
|
<div class="clear"></div>
|
|||
|
</div>
|
|||
|
<div class="emojis" v-show="showEmojis">
|
|||
|
<span v-for="item in emojis" @click="messageContent+=item;showEmojis=false"><{item}></span>
|
|||
|
</div>
|
|||
|
<!--//表情图片-->
|
|||
|
<!--搜索建议-->
|
|||
|
<div class="searchList" v-show="searchList.length!=0">
|
|||
|
<div v-on:click="messageContent=item.title;chatToUser();searchList=[]" class="searchItem" v-for="item in searchList" v-html="item.htmlTitle"></div>
|
|||
|
</div>
|
|||
|
<!--//搜索建议-->
|
|||
|
<div class="chatBoxSend" v-show="chatBoxSend">
|
|||
|
<div class="chatBoxSendMask" v-show="reconnectDialog">
|
|||
|
<a @click="location.reload()" href="javascript:void(0);"><{flyLang.socketclose}></a>
|
|||
|
</div>
|
|||
|
<div class="chatSendProduct" v-if="visitorProduct!=null">
|
|||
|
<img :src="visitorProduct.img" class="productImg"/>
|
|||
|
<div class="productInfo">
|
|||
|
<h2 class="productCardTitle" v-html="visitorProduct.title"></h2>
|
|||
|
<div class="productPrice"><{visitorProduct.price}></div>
|
|||
|
</div>
|
|||
|
<div class="productBtns">
|
|||
|
<div class="el-icon-close" @click="visitorProduct=null"></div>
|
|||
|
<el-button size="mini" type="primary" @click="sendProductInfo"><{flyLang.sent}></el-button>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<!--进度条-->
|
|||
|
<div class="progressLine">
|
|||
|
<el-progress :stroke-width="6" :percentage="percentage" v-show="percentage!=0" :text-inside="true"></el-progress>
|
|||
|
</div>
|
|||
|
<!--//进度条-->
|
|||
|
<div class="iconBtns visitorIconBox">
|
|||
|
|
|||
|
<el-tooltip :content="flyLang.emotions" placement="top">
|
|||
|
<div class="iconfont icon-xiaolian visitorIconBtns visitorFaceBtn" v-on:click="showEmojis==true?showEmojis=false:showEmojis=true"></div>
|
|||
|
</el-tooltip>
|
|||
|
<el-tooltip :content="flyLang.photo" placement="top">
|
|||
|
<div v-show="VisitorUploadImgBtn!='true'" :title="flyLang.photo" class="el-icon-picture" id="uploadImg" v-on:click="uploadImg('/uploadimg')" style="font-size: 25px;"></div>
|
|||
|
</el-tooltip>
|
|||
|
<el-tooltip :content="flyLang.recoder" placement="top" v-show="VisitorVoiceBtn!='true'">
|
|||
|
<div class="el-icon-mic" v-on:click="audioDialog=true" style="font-size: 24px;"></div>
|
|||
|
</el-tooltip>
|
|||
|
|
|||
|
|
|||
|
<el-tooltip :content="flyLang.language" placement="top">
|
|||
|
<div @click="flagsDialog='true'" class="iconfont icon-duoyuyan"></div>
|
|||
|
</el-tooltip>
|
|||
|
<el-tooltip :content="flyLang.more" placement="top">
|
|||
|
<div class="iconfont icon-zengjiatianjiajiahao" v-if="VisitorPlusBtn!='true'" @click="showExtendTool==true?showExtendTool=false:showExtendTool=true;"></div>
|
|||
|
</el-tooltip>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="visitorEditor">
|
|||
|
<el-input :placeholder="flyLang.textarea" :maxlength="VisitorMaxLength" :rows="9" :autosize="{ minRows: 4, maxRows: 9 }" type="textarea" resize="none" class="visitorEditorArea" @focus="scrollBottom;showIconBtns=false" @blur="scrollBottom;showIconBtns=false" v-model="messageContent" @keyup.native="inputNextText" v-on:keyup.enter.native="chatToUser($event)">
|
|||
|
</el-input>
|
|||
|
<el-button type="primary" size="small" class="visitorEditorBtn" :disabled="sendDisabled||messageContent==''" v-on:click="chatToUser($event);showIconBtns=false"><{flyLang.sent}></el-button>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="chatExtend" v-show="showExtendTool">
|
|||
|
<div class="iconExtendBtn" id="uploadImg" v-show="VisitorUploadImgBtn!='true'" @click="uploadImg('/uploadimg')">
|
|||
|
<div class="elIcon el-icon-picture"></div>
|
|||
|
<div><{flyLang.photo}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" id="uploadFile" v-show="VisitorUploadFileBtn!='true'" @click="uploadFile('/2/uploadFile')">
|
|||
|
<div class="elIcon el-icon-upload" ></div>
|
|||
|
<div><{flyLang.file}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="window.open('/cutpic.html')">
|
|||
|
<div class="elIcon iconfont icon-jietu" style="font-size: 20px"></div>
|
|||
|
<div><{flyLang.cutpic}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="audioDialog=true">
|
|||
|
<div v-show="VisitorVoiceBtn!='true'" :title="flyLang.recoder" class="elIcon el-icon-microphone" ></div>
|
|||
|
<div><{flyLang.recoder}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="qqMap==true?qqMap=false:qqMap=true;">
|
|||
|
<div v-show="VisitorMapBtn!='true'" class="elIcon el-icon-location" ></div>
|
|||
|
<div><{flyLang.map}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="callPhone()">
|
|||
|
<div class="elIcon el-icon-phone-outline" ></div>
|
|||
|
<div><{flyLang.audio}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="callPeer()">
|
|||
|
<div class="elIcon el-icon-video-camera" >
|
|||
|
</div>
|
|||
|
<div><{flyLang.video}></div>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="iconExtendBtn" @click="window.open(window.location.href.replace('&show_title=no',''))">
|
|||
|
<div class="elIcon el-icon-full-screen" >
|
|||
|
</div>
|
|||
|
<div><{flyLang.expand}></div>
|
|||
|
</div>
|
|||
|
<div class="iconExtendBtn" @click="flagsDialog='true'">
|
|||
|
<div class="elIcon iconfont icon-duoyuyan" >
|
|||
|
</div>
|
|||
|
<div><{flyLang.language}></div>
|
|||
|
</div>
|
|||
|
<div class="clear"></div>
|
|||
|
<div class="footContact">
|
|||
|
<a href="javascript:void(0)">{{.Title}}{{.CopyrightTxt}}</a>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="chatArticle">
|
|||
|
<div style="padding: 8px;" v-if="entInfo.intro_pic"><img style="width: 100%" :src="entInfo.intro_pic" v-if="entInfo.intro_pic" :title="entInfo.username"/></div>
|
|||
|
<div v-html="robotInfo.RobotCard"></div>
|
|||
|
|
|||
|
|
|||
|
<el-tabs class="hotQuestionTab">
|
|||
|
<el-tab-pane :label="item['cat_name']" v-for="item in topQuestionCatResult">
|
|||
|
<ul>
|
|||
|
<li v-on:click="messageContent=title;chatToUser($event)" class="chatArticleItem" v-for="title in item['titles']" ><a><{title}></a></li>
|
|||
|
</ul>
|
|||
|
</el-tab-pane>
|
|||
|
</el-tabs>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="clear"></div>
|
|||
|
|
|||
|
<!--//客服代码-->
|
|||
|
<audio id="chatMessageAudio">
|
|||
|
<source id="chatMessageAudioSource" />
|
|||
|
</audio>
|
|||
|
<audio id="chatMessageSendAudio">
|
|||
|
<source id="chatMessageSendAudioSource" />
|
|||
|
</audio>
|
|||
|
|
|||
|
|
|||
|
<!--图片预览-->
|
|||
|
|
|||
|
<el-image
|
|||
|
style="display: none;"
|
|||
|
ref="preview"
|
|||
|
class="hideImgDiv"
|
|||
|
:src="imgPreviewSrc[0]"
|
|||
|
:preview-src-list="imgPreviewSrc"
|
|||
|
z-index="9999"
|
|||
|
></el-image>
|
|||
|
|
|||
|
<!--地图-->
|
|||
|
<iframe v-if="qqMap" style="position: fixed;top: 0;left: 0;z-index: 999999999" id="mapPage" width="100%" height="100%" frameborder=0
|
|||
|
src="https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=
|
|||
|
3ZPBZ-IDF63-PH33P-YOPSA-LUXIH-UKFVR&referer=kefu">
|
|||
|
</iframe>
|
|||
|
<!--//地图-->
|
|||
|
<el-dialog
|
|||
|
:title="flyLang.leave"
|
|||
|
:visible.sync="allOffline"
|
|||
|
width="100%"
|
|||
|
top="0">
|
|||
|
<el-input style="margin-bottom: 10px;" :placeholder="flyLang.email" v-model="visitorContact.email"></el-input>
|
|||
|
<el-input style="margin-bottom: 10px;" :placeholder="flyLang.wechat" v-model="visitorContact.weixin"></el-input>
|
|||
|
<el-input style="margin-bottom: 10px;" :placeholder="flyLang.realname" v-model="visitorContact.name"></el-input>
|
|||
|
<el-input :placeholder="flyLang.content" type="textarea" v-model="visitorContact.msg"></el-input>
|
|||
|
<span slot="footer" class="dialog-footer">
|
|||
|
<el-button @click="sendEmailMsg"><{flyLang.sent}></el-button>
|
|||
|
<el-button @click="allOffline = false"><{flyLang.cancel}></el-button>
|
|||
|
</span>
|
|||
|
</el-dialog>
|
|||
|
<!--录音-->
|
|||
|
<el-dialog
|
|||
|
:visible.sync="audioDialog"
|
|||
|
width="70%"
|
|||
|
>
|
|||
|
<div class="dialogRecoder">
|
|||
|
<el-progress :color="colors" type="dashboard" :format="recoderFormat" :stroke-width="10" :percentage="recoderSecond"></el-progress>
|
|||
|
<br/>
|
|||
|
<audio v-show="recorderEnd!=null" controls ref="audio" muted="muted" src="" id="audio"></audio>
|
|||
|
<br/>
|
|||
|
<el-button @click="startRecoder()" size="small" type="primary"><{flyLang.start}></el-button>
|
|||
|
<el-button @click="stopRecoder()" size="small" type="warning"><{flyLang.stop}></el-button>
|
|||
|
<el-button @click="cancelRecoder()" size="small" type="danger"><{flyLang.cancel}></el-button>
|
|||
|
<el-button @click="sendRecoder();" size="small" type="success"><{flyLang.sent}></el-button>
|
|||
|
</div>
|
|||
|
|
|||
|
</el-dialog>
|
|||
|
<!--//录音-->
|
|||
|
<!--切换语言-->
|
|||
|
<el-dialog
|
|||
|
:visible.sync="flagsDialog"
|
|||
|
width="90%"
|
|||
|
top="30px">
|
|||
|
<el-button @click="selectLang('zh-CN')" class="flagBtn" type="primary" plain>中文简体</el-button>
|
|||
|
<el-button @click="selectLang('en-US')" class="flagBtn" type="primary" plain>English</el-button>
|
|||
|
<el-button @click="selectLang('ru-RU')" class="flagBtn" type="primary" plain>Русский язык</el-button>
|
|||
|
<el-button @click="selectLang('zh-HK')" class="flagBtn" type="primary" plain>香港繁體</el-button>
|
|||
|
<el-button @click="selectLang('zh-TW')" class="flagBtn" type="primary" plain>台灣繁體</el-button>
|
|||
|
<el-button @click="selectLang('ja-JP')" class="flagBtn" type="primary" plain>日本語</el-button>
|
|||
|
<el-button @click="selectLang('ko-KR')" class="flagBtn" type="primary" plain>한국어</el-button>
|
|||
|
<el-button @click="selectLang('es-ES')" class="flagBtn" type="primary" plain>Español</el-button>
|
|||
|
<el-button @click="selectLang('kk-KZ')" class="flagBtn" type="primary" plain>қазақ тілі</el-button>
|
|||
|
</el-dialog>
|
|||
|
<!--//切换语言-->
|
|||
|
<!--录音-->
|
|||
|
|
|||
|
<!--//录音-->
|
|||
|
<!--关闭-->
|
|||
|
|
|||
|
<div v-if="closeNotice!=''" style="
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
position: fixed;
|
|||
|
z-index: 9999999;
|
|||
|
left: 0px;
|
|||
|
top: 0px;
|
|||
|
background:#f1f5f8;
|
|||
|
">
|
|||
|
<div style="margin:200px auto;background: #fff;width: 88%;padding: 20px 10px;box-shadow: 0 3px 20px rgb(0 20 41 / 6%);">
|
|||
|
<h2 style="text-align: center;word-break: break-all;"><{closeNotice}></h2>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!--//关闭-->
|
|||
|
|
|||
|
</template>
|
|||
|
</div>
|
|||
|
</body>
|
|||
|
<script src="/static/js/xss.js"></script>
|
|||
|
<script src="/static/js/reconnecting-websocket.min.js"></script>
|
|||
|
<script src="/static/js/recoder.js"></script>
|
|||
|
<script src="/static/js/audio.js"></script>
|
|||
|
<!-- 引入markdown-it的库 -->
|
|||
|
<script src="/static/js/markdown-it.min.js"></script>
|
|||
|
<script>
|
|||
|
var KEFU_ID='{{.KEFU_ID}}';
|
|||
|
var REFER=urlDecode('{{.Refer}}');
|
|||
|
var REFER_URL=urlDecode('{{.ReferUrl}}');
|
|||
|
var ENT_ID='{{.ENT_ID}}';
|
|||
|
var IS_TRY='{{.IS_TRY}}';
|
|||
|
var VISITOR_ID='{{.visitorId}}';
|
|||
|
var VISITOR_NAME='{{.visitorName}}';
|
|||
|
var ERR_MSG='{{.errMsg}}';
|
|||
|
var AVATOR='{{.avator}}';
|
|||
|
var LANG=checkLang();
|
|||
|
|
|||
|
var SHOW_KEFU_NAME='{{.ShowKefuName}}';
|
|||
|
var EXTRA='{{.Extra}}';
|
|||
|
</script>
|
|||
|
<script src="/static/js/front-lang.js?v=bys3jhh6hl"></script>
|
|||
|
<script src="/static/js/chat-config.js?v=0.5.1"></script>
|
|||
|
<script src="/static/js/peer.js"></script>
|
|||
|
<script>
|
|||
|
loadJsFile("lang/"+LANG+".js",function () {
|
|||
|
new Vue({
|
|||
|
el: '#app',
|
|||
|
delimiters:["<{","}>"],
|
|||
|
data: {
|
|||
|
window:window,
|
|||
|
server:getWsBaseUrl()+"/ws_visitor",
|
|||
|
socket:null,
|
|||
|
msgList:[],
|
|||
|
imgPreviewSrc:[
|
|||
|
""],
|
|||
|
msgListNum:[],
|
|||
|
messageContent:"",
|
|||
|
chatTitle:KEFU_LANG[LANG]['connecting'],
|
|||
|
visitor:{},
|
|||
|
face:emojiGifsMap(),
|
|||
|
showKfonline:false,
|
|||
|
socketClosed:false,
|
|||
|
focusSendConn:false,
|
|||
|
wsSocketClosed:true,
|
|||
|
timer:null,
|
|||
|
loadingTimer:null,
|
|||
|
sendDisabled:false,
|
|||
|
entLogo:"",
|
|||
|
entName:"",
|
|||
|
peer:null,
|
|||
|
peerjsId:"",
|
|||
|
kefuPeerId:"",
|
|||
|
loading:null,
|
|||
|
localStream:null,
|
|||
|
flyLang:KEFU_LANG[LANG],
|
|||
|
lang:LANG,
|
|||
|
textareaFocused:false,
|
|||
|
replys:[],
|
|||
|
noticeName:"",
|
|||
|
noticeAvatar:"",
|
|||
|
allOffline:false,
|
|||
|
visitorContact:{
|
|||
|
email:"",
|
|||
|
weixin:"",
|
|||
|
name:"",
|
|||
|
msg:"",
|
|||
|
},
|
|||
|
haveUnreadMessage:false,
|
|||
|
audioDialog:false,
|
|||
|
flagsDialog:false,
|
|||
|
recorder:null,
|
|||
|
recorderAudio:null,
|
|||
|
recordeTimer:null,
|
|||
|
recoderSecond:0,
|
|||
|
currentActiveTime:Date.now(),
|
|||
|
timeoutTimer:null,
|
|||
|
timeoutLongTime:20*60*1000,//20分钟没反应
|
|||
|
allTimeouter:[],
|
|||
|
currentPage:1,
|
|||
|
showLoadMore:false,
|
|||
|
loadMoreDisable:false,
|
|||
|
websocketOpenNum:0,//websocket打开次数
|
|||
|
websocketMaxOpenNum:10,//websocket最大打开次数
|
|||
|
recorderEnd:null,
|
|||
|
isMobile:false,
|
|||
|
isIframe:false,
|
|||
|
onlineType:"success",
|
|||
|
reconnectDialog:false,
|
|||
|
showIconBtns:false,
|
|||
|
showFaceIcon:false,
|
|||
|
showKefuName:SHOW_KEFU_NAME,
|
|||
|
comment:false,
|
|||
|
qqMap:false,
|
|||
|
hotQuestion:[],
|
|||
|
topQuestionList:[],
|
|||
|
topQuestionListHtml:"",
|
|||
|
topQuestionCatResult:[],
|
|||
|
topQuestionCount:0,
|
|||
|
topQuestionPage:1,
|
|||
|
topQuestionPagesize:5,
|
|||
|
entIntroduce:"",
|
|||
|
robotSwitch:"",
|
|||
|
robotNoAnswer:"",
|
|||
|
visitorNotice:"",
|
|||
|
autoWelcome:"",
|
|||
|
searchList:[],
|
|||
|
VisitorVoiceBtn:'{{.VisitorVoiceBtn}}',
|
|||
|
VisitorMapBtn:'{{.VisitorMapBtn}}',
|
|||
|
VisitorCommentBtn:'{{.VisitorCommentBtn}}',
|
|||
|
VisitorFaceBtn:'{{.VisitorFaceBtn}}',
|
|||
|
VisitorReadStatus:'{{.VisitorReadStatus}}',
|
|||
|
VisitorPlusBtn:'{{.VisitorPlusBtn}}',
|
|||
|
VisitorUploadImgBtn:'{{.VisitorUploadImgBtn}}',
|
|||
|
VisitorUploadFileBtn:'{{.VisitorUploadFileBtn}}',
|
|||
|
VisitorMaxLength:'{{.VisitorMaxLength}}'==''?100:parseInt('{{.VisitorMaxLength}}'),
|
|||
|
VisitorShowAvator:'{{.VisitorShowAvator}}',
|
|||
|
VisitorWechatQrcodeUrl:'{{.VisitorWechatQrcodeUrl}}',
|
|||
|
closeNotice:'',
|
|||
|
percentage:0,
|
|||
|
visitorMaxNumLimit:false,//客服达到接待上限
|
|||
|
visitorMaxNumNotice:"",//客服达到接待上限文案
|
|||
|
visitorCookie:"",
|
|||
|
scanWechatQrcode:"",
|
|||
|
entConfig:{},//企业配置信息
|
|||
|
colors: [
|
|||
|
{color: '#f56c6c', percentage: 20},
|
|||
|
{color: '#e6a23c', percentage: 40},
|
|||
|
{color: '#5cb87a', percentage: 60},
|
|||
|
{color: '#1989fa', percentage: 80},
|
|||
|
{color: '#6f7ad3', percentage: 100}
|
|||
|
],
|
|||
|
commentScore:0,
|
|||
|
commentContent:"",
|
|||
|
isCalling:false,
|
|||
|
call:null,
|
|||
|
videoElement:null,
|
|||
|
canvasElement:null,
|
|||
|
isVideo:false,
|
|||
|
entInfo:{},
|
|||
|
showExtendTool:false,
|
|||
|
visitorProduct:null,
|
|||
|
robotInfo:{},
|
|||
|
showEmojis:false,
|
|||
|
//固定营销话术
|
|||
|
marketing:[],
|
|||
|
//机器人阶段模式
|
|||
|
isRobotModel:"no",
|
|||
|
//是否有自动回复
|
|||
|
isAutoReply:"yes",
|
|||
|
//是否展示输入框
|
|||
|
chatBoxSend:true,
|
|||
|
markdownIt:null,
|
|||
|
//询前表单
|
|||
|
preVisitorForm:{name:"",wechat:"",qq:"",email:"",remark:"",tel:""},
|
|||
|
emojis:{"smile":"😄","smiley":"😃","grinning":"😀","blush":"😊","wink":"😉","heart_eyes":"😍","kissing_heart":"😘","kissing_closed_eyes":"😚","kissing":"😗","kissing_smiling_eyes":"😙","stuck_out_tongue_winking_eye":"😜","stuck_out_tongue_closed_eyes":"😝","stuck_out_tongue":"😛","flushed":"😳","grin":"😁","pensive":"😔","relieved":"😌","unamused":"😒","disappointed":"😞","persevere":"😣","cry":"😢","joy":"😂","sob":"😭","sleepy":"😪","disappointed_relieved":"😥","cold_sweat":"😰","sweat_smile":"😅","sweat":"😓","weary":"😩","tired_face":"😫","fearful":"😨","scream":"😱","angry":"😠","rage":"😡","triumph":"😤","confounded":"😖","laughing":"😆","yum":"😋","mask":"😷","sunglasses":"😎","sleeping":"😴","dizzy_face":"😵","astonished":"😲","worried":"😟","frowning":"😦","anguished":"😧","imp":"👿","open_mouth":"😮","grimacing":"😬","neutral_face":"😐","confused":"😕","hushed":"😯","smirk":"😏","expressionless":"😑","man_with_gua_pi_mao":"👲","man_with_turban":"👳","cop":"👮","construction_worker":"👷","guardsman":"💂","baby":"👶","boy":"👦","girl":"👧","man":"👨","woman":"👩","older_man":"👴","older_woman":"👵","person_with_blond_hair":"👱","angel":"👼","princess":"👸","smiley_cat":"😺","smile_cat":"😸","heart_eyes_cat":"😻","kissing_cat":"😽","smirk_cat":"😼","scream_cat":"🙀","crying_cat_face":"😿","joy_cat":"😹","pouting_cat":"😾","japanese_ogre":"👹","japanese_goblin":"👺","see_no_evil":"🙈","hear_no_evil":"🙉","speak_no_evil":"🙊","skull":"💀","alien":"👽","hankey":"💩","fire":"🔥","sparkles":"✨","star2":"🌟","dizzy":"💫","boom":"💥","anger":"💢","sweat_drops":"💦","droplet":"💧","zzz":"💤","dash":"💨","ear":"👂","eyes":"👀","nose":"👃","tongue":"👅","lips":"👄","thumbs_up":"👍","-1":"👎","ok_hand":"👌","facepunch":"👊","fist":"✊","wave":"👋","hand":"✋","open_hands":"👐","point_up_2":"👆","point_down":"👇","point_right":"👉","point_left":"👈","raised_hands":"🙌","pray":"🙏","clap":"👏","muscle":"💪","walking":"🚶","runner":"🏃","dancer":"💃","couple":"👫","family":"👪","couplekiss":"💏","couple_with_heart":"💑","dancers":"👯","ok_woman":"🙆","no_good":"🙅","information_desk_person":"💁","raising_hand":"🙋","massage":"💆","haircut":"💇","nail_care":"💅","bride_with_veil":"👰","person_with_pouting_face":"🙎","person_frowning":"🙍","bow":"🙇","tophat":"🎩","crown":"👑","womans_hat":"👒","athletic_shoe":"👟","mans_shoe":"👞","sandal":"👡","high_heel":"👠","boot":"👢","shirt":"👕","necktie":"👔","womans_clothes":"👚","dress":"👗","running_shirt_with_sash":"🎽","jeans":"👖","kimono":"👘","bikini":"👙","briefcase":"💼","handbag":"👜","pouch":"👝","purse":"👛","eyeglasses":"👓","ribbon":"🎀","closed_umbrella":"🌂","lipstick":"💄","yellow_heart":"💛","blue_heart":"💙","purple_heart":"💜","green_heart":"💚","broken_heart":"💔","heartpulse":"💗","heartbeat":"💓","two_hearts":"💕","sparkling_heart":"💖","revolving_hearts":"💞","cupid":"💘","love_letter":"💌","kiss":"💋","ring":"💍","gem":"💎","bust_in_silhouette":"👤","speech_balloon":"💬","footprints":"👣"},
|
|||
|
},
|
|||
|
methods: {
|
|||
|
//初始化websocket
|
|||
|
initConn:function() {
|
|||
|
this.socket = new ReconnectingWebSocket(this.server+"?visitor_id="+this.visitor.visitor_id+"&to_id="+this.visitor.to_id);//创建Socket实例
|
|||
|
this.socket.debug = true;
|
|||
|
this.socket.onmessage = this.OnMessage;
|
|||
|
this.socket.onopen = this.OnOpen;
|
|||
|
this.socket.onerror = this.OnError;
|
|||
|
this.socket.onclose = this.OnClose;
|
|||
|
this.ping();
|
|||
|
},
|
|||
|
OnOpen:function() {
|
|||
|
console.log("ws:onopen");
|
|||
|
//限制最大打开次数
|
|||
|
if(this.websocketOpenNum>=this.websocketMaxOpenNum){
|
|||
|
this.chatTitle=KEFU_LANG[LANG]['refresh'];
|
|||
|
this.socket.close();
|
|||
|
return;
|
|||
|
}
|
|||
|
this.websocketOpenNum++;
|
|||
|
|
|||
|
//获取历史消息
|
|||
|
this.currentPage=1;
|
|||
|
this.msgList=[];
|
|||
|
this.loadMoreMessages();
|
|||
|
|
|||
|
this.chatTitle=this.noticeName;
|
|||
|
this.checkTimeout();
|
|||
|
this.socketClosed=false;
|
|||
|
this.focusSendConn=false;
|
|||
|
this.wsSocketClosed=false;
|
|||
|
this.sendVisitorLogin();
|
|||
|
//this.getExtendInfo();
|
|||
|
//获取产品卡片信息
|
|||
|
this.getUrlExtra();
|
|||
|
this.reconnectDialog=false;
|
|||
|
if(this.onlineType!="danger"){
|
|||
|
this.showTitle(this.entInfo.staffNickname+" "+KEFU_LANG[LANG]['connectok']);
|
|||
|
}
|
|||
|
//this.getNotice();
|
|||
|
|
|||
|
},
|
|||
|
OnMessage:function(e) {
|
|||
|
console.log("ws:onmessage");
|
|||
|
this.socketClosed=false;
|
|||
|
this.focusSendConn=false;
|
|||
|
let _this=this;
|
|||
|
const redata = JSON.parse(e.data);
|
|||
|
if (redata.type == "transfer") {
|
|||
|
var kefuId = redata.data
|
|||
|
if(!kefuId){
|
|||
|
return;
|
|||
|
}
|
|||
|
this.visitor.to_id=kefuId;
|
|||
|
setFakeCookie("kefu_"+ENT_ID,kefuId,24*3600*30);
|
|||
|
}
|
|||
|
if (redata.type == "comment") {
|
|||
|
this.comment=true;
|
|||
|
this.scrollBottom();
|
|||
|
this.socket.close();
|
|||
|
this.socketClosed=true;
|
|||
|
this.reconnectDialog=true;
|
|||
|
}
|
|||
|
if (redata.type == "wechat_notice") {
|
|||
|
this.showTitle(KEFU_LANG[LANG]['wechatNotice']);
|
|||
|
}
|
|||
|
if (redata.type == "notice") {
|
|||
|
let msg = redata.data
|
|||
|
if(!msg){
|
|||
|
return;
|
|||
|
}
|
|||
|
this.showTitle(msg);
|
|||
|
// this.chatTitle=msg
|
|||
|
// $(".chatVisitorPage").append("<div class=\"chatTime\">"+this.chatTitle+"</div>");
|
|||
|
//this.scrollBottom();
|
|||
|
}
|
|||
|
if (redata.type == "accept") {
|
|||
|
let msg = redata.data;
|
|||
|
if(!msg||_this.localStream==null){
|
|||
|
return;
|
|||
|
}
|
|||
|
// this.$confirm('请求与您通话?', '提示', {
|
|||
|
// confirmButtonText: '确定',
|
|||
|
// cancelButtonText: '取消',
|
|||
|
// type: 'warning'
|
|||
|
// }).then(() => {
|
|||
|
_this.kefuPeerId=msg;
|
|||
|
_this.isCalling=true;
|
|||
|
_this.talkPeer();
|
|||
|
// }).catch(() => {
|
|||
|
// });
|
|||
|
|
|||
|
}
|
|||
|
if (redata.type == "callPhone") {
|
|||
|
this.callPhone();
|
|||
|
}
|
|||
|
if (redata.type == "callVideo") {
|
|||
|
this.callPeer();
|
|||
|
}
|
|||
|
if (redata.type == "refuse") {
|
|||
|
this.callClear();
|
|||
|
this.$message({
|
|||
|
message: "已挂断",
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
return;
|
|||
|
}
|
|||
|
if (redata.type == "delete") {
|
|||
|
var msg = redata.data;
|
|||
|
for(var i=0;i<this.msgList.length;i++){
|
|||
|
if(this.msgList[i].msg_id==msg.msg_id){
|
|||
|
this.msgList.splice(i,1);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (redata.type == "read") {
|
|||
|
var msg = redata.data;
|
|||
|
for(var i=0;i<this.msgList.length;i++){
|
|||
|
this.msgList[i].read_status=KEFU_LANG[LANG]['read'];
|
|||
|
}
|
|||
|
}
|
|||
|
if (redata.type == "message") {
|
|||
|
let msg = redata.data
|
|||
|
//this.visitor.to_id=msg.id;
|
|||
|
let content = {}
|
|||
|
content.avator = msg.avator;
|
|||
|
content.name = msg.name;
|
|||
|
content.content =this.markdownHtml(replaceSpecialTag(msg.content));
|
|||
|
content.is_kefu = false;
|
|||
|
content.time = shortTime(msg.time);
|
|||
|
content.is_reply=true;
|
|||
|
content.msg_id = msg.msg_id;
|
|||
|
content.show_time=true;
|
|||
|
let isExist=false;
|
|||
|
for(key in this.msgList){
|
|||
|
if(this.msgList[key].msg_id==msg.msg_id){
|
|||
|
this.$set(this.msgList,key,content);
|
|||
|
this.scrollBottom();
|
|||
|
isExist=true;
|
|||
|
}
|
|||
|
}
|
|||
|
if(isExist) return;
|
|||
|
this.msgList.push(content);
|
|||
|
setTimeout(function () {
|
|||
|
_this.scrollBottom();
|
|||
|
},200);
|
|||
|
|
|||
|
notify(msg.name, {
|
|||
|
body: msg.content,
|
|||
|
icon: msg.avator
|
|||
|
},function(notification) {
|
|||
|
window.focus();
|
|||
|
notification.close();
|
|||
|
});
|
|||
|
flashTitle();//标题闪烁
|
|||
|
//clearInterval(this.timer);
|
|||
|
this.cleanAllTimeout();
|
|||
|
this.alertSound('/static/images/alert4.mp3');//提示音
|
|||
|
this.haveUnreadMessage=true;
|
|||
|
}
|
|||
|
if (redata.type == "close") {
|
|||
|
this.showTitle(KEFU_LANG[LANG]['closemes']);
|
|||
|
this.scrollBottom();
|
|||
|
this.socket.close();
|
|||
|
//this.socketClosed=true;
|
|||
|
this.focusSendConn=true;
|
|||
|
this.reconnectDialog=true;
|
|||
|
}
|
|||
|
if (redata.type == "force_close") {
|
|||
|
this.showTitle(KEFU_LANG[LANG]['forceclosemes']);
|
|||
|
this.scrollBottom();
|
|||
|
this.socket.close();
|
|||
|
this.socketClosed=true;
|
|||
|
this.reconnectDialog=true;
|
|||
|
}
|
|||
|
if (redata.type == "auto_close") {
|
|||
|
this.showTitle(KEFU_LANG[LANG]['autoclosemes']);
|
|||
|
this.scrollBottom();
|
|||
|
this.socket.close();
|
|||
|
this.socketClosed=true;
|
|||
|
this.reconnectDialog=true;
|
|||
|
}
|
|||
|
if (redata.type == "change_id") {
|
|||
|
var openId = redata.data;
|
|||
|
setFakeCookie("visitor_"+ENT_ID,openId,this.visitorCookie);
|
|||
|
location.reload();
|
|||
|
}
|
|||
|
window.parent.postMessage(redata,"*");
|
|||
|
},
|
|||
|
//发送给客户
|
|||
|
chatToUser:function(e) {
|
|||
|
this.searchList=[];
|
|||
|
if(this.sendDisabled){
|
|||
|
return;
|
|||
|
}
|
|||
|
//用户点击了ctrl+enter触发
|
|||
|
if(e && e.ctrlKey && e.keyCode==13) {
|
|||
|
this.messageContent += '\n';
|
|||
|
return;
|
|||
|
}
|
|||
|
let messageContent=filterXSS(trim(this.messageContent.replace(/\r\n|\n/g,"<br>"),"<br>"));
|
|||
|
if(messageContent==""){
|
|||
|
this.messageContent="";
|
|||
|
return;
|
|||
|
}
|
|||
|
this.messageContent="";
|
|||
|
this.currentActiveTime=Date.now();
|
|||
|
if(this.socketClosed){
|
|||
|
this.initConn();
|
|||
|
// this.$message({
|
|||
|
// message: '连接关闭!请重新打开页面',
|
|||
|
// type: 'warning'
|
|||
|
// });
|
|||
|
//return;
|
|||
|
}
|
|||
|
this.sendDisabled=true;
|
|||
|
let _this=this;
|
|||
|
|
|||
|
let content = {}
|
|||
|
content.avator=_this.visitor.avator;
|
|||
|
content.content = replaceSpecialTag(messageContent);
|
|||
|
content.name = _this.visitor.name;
|
|||
|
content.is_kefu = true;
|
|||
|
//content.time = _this.getNowDate();
|
|||
|
content.show_time=false;
|
|||
|
content.read_status = KEFU_LANG[LANG]['unread'];
|
|||
|
_this.msgList.push(content);
|
|||
|
_this.scrollBottom();
|
|||
|
|
|||
|
let mes = {};
|
|||
|
// mes.type = "visitor";
|
|||
|
mes.content = messageContent;
|
|||
|
mes.from_id = this.visitor.visitor_id;
|
|||
|
mes.to_id = this.visitor.to_id;
|
|||
|
|
|||
|
//营销话术
|
|||
|
_this.sendMarketing(messageContent);
|
|||
|
|
|||
|
//机器人回答
|
|||
|
if(this.turnToMan && this.turnToMan.includes(messageContent)) {
|
|||
|
//用户输入了转人工的关键词
|
|||
|
this.isAutoReply = "no";
|
|||
|
}
|
|||
|
if(this.robotSwitch=="true" && this.robotToMessage(messageContent)){
|
|||
|
return;
|
|||
|
}
|
|||
|
mes.is_autoreply=this.isAutoReply;
|
|||
|
|
|||
|
//发送人工消息
|
|||
|
$.post("/2/message?lang="+getQuery("lang"),mes,function(res){
|
|||
|
_this.sendDisabled=false;
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
if(res.code==401){
|
|||
|
setTimeout(function(){
|
|||
|
window.location.reload();
|
|||
|
},2000);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
var result=res.result
|
|||
|
if(result.isBlack){
|
|||
|
_this.msgList.pop();
|
|||
|
content.content=result.content;
|
|||
|
_this.msgList.push(content);
|
|||
|
}
|
|||
|
|
|||
|
_this.messageContent = "";
|
|||
|
_this.cleanAllTimeout();
|
|||
|
_this.sendSound();
|
|||
|
_this.sendDisabled=false;
|
|||
|
});
|
|||
|
|
|||
|
},
|
|||
|
//机器人模式回复
|
|||
|
robotToMessage(userContent){
|
|||
|
let _this=this;
|
|||
|
this.sendDisabled=false;
|
|||
|
this.messageContent="";
|
|||
|
//转接人工
|
|||
|
if(this.turnToMan && this.turnToMan.includes(userContent)){
|
|||
|
//转接人工
|
|||
|
this.isAutoReply="no";
|
|||
|
//正在排队
|
|||
|
if(this.visitorMaxNumLimit){
|
|||
|
this.showTitle(this.visitorMaxNumNotice);
|
|||
|
return true;
|
|||
|
}
|
|||
|
this.initConn();
|
|||
|
this.robotSwitch="";
|
|||
|
this.isRobotModel="no";
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
sendAjax("/2/robotMessage","post",{
|
|||
|
ent_id:ENT_ID,
|
|||
|
content:userContent,
|
|||
|
visitor_id:this.visitor.visitor_id,
|
|||
|
},function(result){
|
|||
|
let msg=result.result;
|
|||
|
let code=result.code;
|
|||
|
if (code!="20000"||(msg.content=="" && _this.robotNoAnswer=="")){
|
|||
|
// _this.msgList.pop();
|
|||
|
return;
|
|||
|
}
|
|||
|
if(msg.content==""){
|
|||
|
msg.content=_this.robotNoAnswer;
|
|||
|
}
|
|||
|
|
|||
|
let content = {}
|
|||
|
content.avator=_this.noticeAvatar;
|
|||
|
content.content = replaceSpecialTag(msg.content);
|
|||
|
content.name = _this.noticeName;
|
|||
|
content.is_kefu = false;
|
|||
|
content.read_status = KEFU_LANG[LANG]['read'];
|
|||
|
content.time = _this.getNowDate();
|
|||
|
content.show_time=false;
|
|||
|
_this.msgList.push(content);
|
|||
|
// _this.msgList[_this.msgList.length-1].content=replaceSpecialTag(msg.content);
|
|||
|
_this.scrollBottom();
|
|||
|
});
|
|||
|
return true;
|
|||
|
},
|
|||
|
//正在输入
|
|||
|
inputNextText:function(){
|
|||
|
var _this=this;
|
|||
|
this.sendInputingStrNow(this.messageContent);
|
|||
|
//是否进行搜索
|
|||
|
if(this.robotSwitch!="true"){
|
|||
|
return;
|
|||
|
}
|
|||
|
this.sendAjax("/2/searchQuestion","get",{ent_id:ENT_ID,content:this.messageContent},function(result){
|
|||
|
if(!result){
|
|||
|
return;
|
|||
|
}
|
|||
|
for(key in result){
|
|||
|
let title=result[key].title.split(",")[0];
|
|||
|
result[key].title=title;
|
|||
|
let str= title.replace(_this.messageContent,"<span>"+_this.messageContent+"</span>");
|
|||
|
result[key].htmlTitle=str;
|
|||
|
}
|
|||
|
_this.searchList=result;
|
|||
|
});
|
|||
|
},
|
|||
|
sendInputingStrNow:function(str){
|
|||
|
if(this.socketClosed||!this.socket||this.wsSocketClosed){
|
|||
|
return;
|
|||
|
}
|
|||
|
var message = {}
|
|||
|
message.type = "inputing";
|
|||
|
message.data = {
|
|||
|
from : this.visitor.visitor_id,
|
|||
|
to : this.visitor.to_id,
|
|||
|
content:str
|
|||
|
};
|
|||
|
this.socket.send(JSON.stringify(message));
|
|||
|
},
|
|||
|
sendVisitorLogin:function(){
|
|||
|
var _this=this;
|
|||
|
setTimeout(function(){
|
|||
|
if(_this.socketClosed||!_this.socket||_this.wsSocketClosed){
|
|||
|
return;
|
|||
|
}
|
|||
|
var message = {}
|
|||
|
message.type = "visitor_login";
|
|||
|
message.data = {
|
|||
|
from : _this.visitor.visitor_id,
|
|||
|
to : _this.visitor.to_id,
|
|||
|
};
|
|||
|
_this.socket.send(JSON.stringify(message));
|
|||
|
}, 3000);
|
|||
|
},
|
|||
|
OnClose:function(event) {
|
|||
|
console.log("ws:onclose",event);
|
|||
|
this.focusSendConn=true;
|
|||
|
this.wsSocketClosed=true;
|
|||
|
this.closeTimeoutTimer();
|
|||
|
},
|
|||
|
OnError:function(event) {
|
|||
|
console.log("ws:onerror",event);
|
|||
|
this.closeTimeoutTimer();
|
|||
|
},
|
|||
|
//访客初始化
|
|||
|
getUserInfo:function(){
|
|||
|
let _this=this;
|
|||
|
let visitor_id=getFakeCookie("visitor_"+ENT_ID);
|
|||
|
let to_id=KEFU_ID;
|
|||
|
let preKefuId=getFakeCookie("kefu_"+ENT_ID);
|
|||
|
if(preKefuId!="") to_id=preKefuId;
|
|||
|
let extra=EXTRA;
|
|||
|
//var url=getQuery("url");
|
|||
|
let paramVisitorId=VISITOR_ID;
|
|||
|
if(paramVisitorId!=""){
|
|||
|
visitor_id=paramVisitorId;
|
|||
|
}
|
|||
|
let visitorName=VISITOR_NAME;
|
|||
|
let avator=AVATOR;
|
|||
|
|
|||
|
if(extra==""){
|
|||
|
let ext={};
|
|||
|
let refer=document.referrer?document.referrer:"-";
|
|||
|
ext.refer=refer;
|
|||
|
ext.host=document.location.href;
|
|||
|
extra=utf8ToB64(JSON.stringify(ext));
|
|||
|
}else{
|
|||
|
try{
|
|||
|
let jsonStr=b64ToUtf8(extra)
|
|||
|
let extJson=JSON.parse(jsonStr)
|
|||
|
if(extJson.refer){
|
|||
|
if(REFER=="") REFER=extJson.refer;
|
|||
|
if(REFER_URL=="") REFER_URL=extJson.refer;
|
|||
|
}
|
|||
|
}catch (e) {}
|
|||
|
|
|||
|
}
|
|||
|
if(REFER_URL==""){
|
|||
|
REFER_URL=document.referrer;
|
|||
|
}
|
|||
|
if(REFER==""){
|
|||
|
REFER=document.title;
|
|||
|
}
|
|||
|
//发送消息
|
|||
|
$.ajax({
|
|||
|
type: "post",
|
|||
|
url: "/visitor_login",
|
|||
|
data:{visitor_id:visitor_id,
|
|||
|
visitor_name:visitorName,
|
|||
|
avator:avator,
|
|||
|
refer:REFER,
|
|||
|
to_id:to_id,
|
|||
|
extra:extra,
|
|||
|
ent_id:ENT_ID,
|
|||
|
url:document.location.href,
|
|||
|
refer_url:REFER_URL,
|
|||
|
title:document.title,
|
|||
|
language:window.navigator.language,//浏览器的语言。
|
|||
|
},
|
|||
|
error:function(res){
|
|||
|
let data=JSON.parse(res.responseText);
|
|||
|
_this.$message({
|
|||
|
message: data.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
},
|
|||
|
success: function(res) {
|
|||
|
_this.getTopQuestion();
|
|||
|
|
|||
|
//判断同时接待访客数
|
|||
|
if(res.code==40018){
|
|||
|
_this.visitorMaxNumLimit=true;
|
|||
|
_this.visitor=res.result;
|
|||
|
_this.robotSwitch="true";
|
|||
|
_this.chatTitle=res.kefu.username;
|
|||
|
_this.turnToMan=res.turnToMan.split(",");
|
|||
|
var visitorMaxNumNotice=res.visitorMaxNumNotice;
|
|||
|
if(visitorMaxNumNotice==""){
|
|||
|
visitorMaxNumNotice="当前有"+res.visitorMaxNum+"位访客正在排队咨询,请稍等一会再尝试 <a href='javascript:window.location.reload();'>刷新</a>";
|
|||
|
}
|
|||
|
_this.visitorMaxNumNotice=visitorMaxNumNotice;
|
|||
|
if (_this.isRobotModel!="yes") _this.showTitle(visitorMaxNumNotice);
|
|||
|
//_this.sendDisabled=true;
|
|||
|
return;
|
|||
|
}
|
|||
|
//提示错误信息
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
_this.reconnectDialog=true;
|
|||
|
_this.chatTitle=res.msg;
|
|||
|
_this.sendDisabled=true;
|
|||
|
return;
|
|||
|
}
|
|||
|
_this.entInfo=res.kefu;
|
|||
|
_this.noticeName=res.kefu.username;
|
|||
|
_this.noticeAvatar=res.kefu.avatar;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if(res.alloffline){
|
|||
|
_this.onlineType="danger";
|
|||
|
_this.showTitle(_this.flyLang.offline);
|
|||
|
}else{
|
|||
|
_this.onlineType="success";
|
|||
|
}
|
|||
|
// if(KEFU_CONFIG.SHOW_OFFLINE_PAGE){
|
|||
|
// _this.allOffline=res.alloffline;
|
|||
|
// }
|
|||
|
_this.sendDisabled=false;
|
|||
|
_this.visitor=res.result;
|
|||
|
// _this.noticeName=res.kefu.username;
|
|||
|
// _this.noticeAvatar=res.kefu.avatar;
|
|||
|
_this.entIntroduce=res.entIntroduce;
|
|||
|
_this.robotSwitch=res.robotSwitch;
|
|||
|
_this.turnToMan=res.turnToMan.split(",");
|
|||
|
_this.chatTitle=_this.noticeName;
|
|||
|
_this.visitorNotice=res.visitorNotice;
|
|||
|
_this.autoWelcome=res.autoWelcome;
|
|||
|
_this.visitorCookie=res.visitorCookie;
|
|||
|
_this.scanWechatQrcode=res.scanWechatQrcode;
|
|||
|
_this.closeNotice=res.closeNotice;
|
|||
|
_this.robotInfo=res.robot;
|
|||
|
document.title=res.kefu.username;
|
|||
|
if(!getFakeCookie("visitor_"+ENT_ID)){
|
|||
|
setFakeCookie("visitor_"+ENT_ID,_this.visitor.visitor_id,res.visitorCookie);
|
|||
|
}
|
|||
|
setFakeCookie("kefu_"+ENT_ID,_this.visitor.to_id,res.visitorCookie);
|
|||
|
//_this.loadMoreMessages();
|
|||
|
_this.showWechatTip();
|
|||
|
//展示固定营销
|
|||
|
_this.sendMarketing();
|
|||
|
if(_this.robotSwitch!="true"){
|
|||
|
_this.initConn();
|
|||
|
_this.getNotice();
|
|||
|
}else{
|
|||
|
//展示机器人
|
|||
|
// _this.msgList.push({type:"card"});
|
|||
|
// _this.displayHide();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
//获取信息列表
|
|||
|
sendEmailMsg:function(){
|
|||
|
let _this=this;
|
|||
|
_this.visitorContact.ent_id=ENT_ID;
|
|||
|
$.ajax({
|
|||
|
type:"post",
|
|||
|
url:"/ent/email_message",
|
|||
|
data:_this.visitorContact,
|
|||
|
success: function(data) {
|
|||
|
if(data.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: data.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else{
|
|||
|
_this.allOffline=false;
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
//滚动到底部
|
|||
|
scrollBottom:function(){
|
|||
|
var _this=this;
|
|||
|
//$('.chatVisitorPage').animate({scrollTop:'99999999999999'},"slow");
|
|||
|
this.$nextTick(function(){
|
|||
|
var container = _this.$el.querySelector(".chatVisitorPage");
|
|||
|
container.scrollTop = 999999;
|
|||
|
//alert(1);
|
|||
|
//$('.chatVisitorPage').animate({scrollTop:'99999999999999'},'99999999');
|
|||
|
// $('.chatVisitorPage').scrollTop(9999999999999999999);
|
|||
|
});
|
|||
|
},
|
|||
|
//软键盘问题
|
|||
|
textareaFocus:function(){
|
|||
|
// if(/Android|webOS|iPhone|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
|||
|
// //$(".chatContext").css("margin-bottom","0");
|
|||
|
// //$(".chatBoxSend").css("position","static");
|
|||
|
// this.textareaFocused=true;
|
|||
|
// }
|
|||
|
this.scrollBottom();
|
|||
|
},
|
|||
|
textareaBlur:function(){
|
|||
|
// if(this.textareaFocused&&/Android|webOS|iPhone|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
|||
|
// var chatBoxSendObj=$(".chatBoxSend");
|
|||
|
// var chatContextObj=$(".chatContext");
|
|||
|
// if(this.textareaFocused&&chatBoxSendObj.css("position")!="fixed"){
|
|||
|
// //chatContextObj.css("margin-bottom","105px");
|
|||
|
// //chatBoxSendObj.css("position","fixed");
|
|||
|
// this.textareaFocused=false;
|
|||
|
// }
|
|||
|
//
|
|||
|
// }
|
|||
|
this.scrollBottom();
|
|||
|
},
|
|||
|
|
|||
|
//获取日期
|
|||
|
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;
|
|||
|
},
|
|||
|
setNoticeWelcome(list){
|
|||
|
var _this=this;
|
|||
|
var msgs = list;
|
|||
|
var delaySecond=2;
|
|||
|
for(let i in msgs){
|
|||
|
var msg=msgs[i];
|
|||
|
if(msg.delay_second){
|
|||
|
delaySecond+=msg.delay_second;
|
|||
|
}else{
|
|||
|
delaySecond+=4;
|
|||
|
}
|
|||
|
var timer = setTimeout(function (msg) {
|
|||
|
msg.time=shortTime(getNowDate());
|
|||
|
msg.show_time=false;
|
|||
|
msg.content = replaceSpecialTag(msg.content);
|
|||
|
|
|||
|
//判断类型
|
|||
|
if(msg.content.includes("[询前表单]")){
|
|||
|
if (getFakeCookie("preVisitorForm_"+ENT_ID)) return
|
|||
|
_this.chatBoxSend=false;
|
|||
|
msg.type="preVisitorForm";
|
|||
|
}
|
|||
|
|
|||
|
_this.msgList.push(msg);
|
|||
|
_this.scrollBottom();
|
|||
|
_this.alertSound('/static/images/notification.mp3');
|
|||
|
var redata={
|
|||
|
type:"message",
|
|||
|
data:msg
|
|||
|
}
|
|||
|
|
|||
|
window.parent.postMessage(redata,"*");
|
|||
|
},1000*delaySecond,msg);
|
|||
|
_this.allTimeouter.push(timer);
|
|||
|
}
|
|||
|
},
|
|||
|
//获取自动欢迎语句
|
|||
|
getNotice : function (){
|
|||
|
var _this=this;
|
|||
|
var oldNotice=getFakeCookie("noticed_"+ENT_ID);
|
|||
|
if(oldNotice && _this.autoWelcome=="on"){
|
|||
|
return;
|
|||
|
}
|
|||
|
$.get("/2/notices?visitor_id="+this.visitor.visitor_id+"&ent_id="+ENT_ID+"&kefu_name="+this.visitor.to_id,function(res) {
|
|||
|
_this.entConfig=res.result.ent_config;
|
|||
|
if (res.result.welcome != null) {
|
|||
|
setFakeCookie("noticed_"+ENT_ID,res.result.welcome,7*3600*24);
|
|||
|
_this.setNoticeWelcome(res.result.welcome);
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
initCss:function(){
|
|||
|
|
|||
|
|
|||
|
var _this=this;
|
|||
|
$(function () {
|
|||
|
//手机端的样式问题
|
|||
|
if(_this.isMobile){
|
|||
|
$(".chatVisitorPage").css("height","calc(100% - 100px)");
|
|||
|
}
|
|||
|
|
|||
|
$("body").on("click",".cardBox a,.chatNewContent a",function() {
|
|||
|
var txt=$(this).text();
|
|||
|
var href=$(this).attr("href");
|
|||
|
if(href=="#"||!href){
|
|||
|
_this.messageContent=txt;
|
|||
|
_this.chatToUser();
|
|||
|
return false;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
//var windheight = $(window).height();
|
|||
|
$(window).resize(function(){
|
|||
|
//var docheight = $(window).height(); /*唤起键盘时当前窗口高度*/
|
|||
|
//_this.scrollBottom();
|
|||
|
_this.visitorPageHeight();
|
|||
|
// if(docheight < windheight){ /*当唤起键盘高度小于未唤起键盘高度时执行*/
|
|||
|
// $(".chatBoxSend").css("position","static");
|
|||
|
// }else{
|
|||
|
// $(".chatBoxSend").css("position","fixed");
|
|||
|
// }
|
|||
|
//_this.visitorPageHeight();
|
|||
|
//document.getElementById('chatVisitorPage').style.height = (document.documentElement.clientHeight - 71) + 'px';
|
|||
|
});
|
|||
|
if(isMobile()){
|
|||
|
_this.visitorPageHeight();
|
|||
|
//document.getElementById('chatVisitorPage').style.height = (document.documentElement.clientHeight - 71) + 'px';
|
|||
|
}
|
|||
|
//自动问答
|
|||
|
$("body").on("click",".visitorReplyContent",function() {
|
|||
|
var txt=$(this).find("span").text();
|
|||
|
_this.messageContent=txt;
|
|||
|
_this.chatToUser();
|
|||
|
});
|
|||
|
//自动问答换一换
|
|||
|
$("body").on("click",".visitorReplyTitle a",function() {
|
|||
|
++_this.topQuestionPage;
|
|||
|
if(_this.topQuestionPage>_this.topQuestionCount){
|
|||
|
_this.topQuestionPage=1;
|
|||
|
}
|
|||
|
var result=pagination(_this.topQuestionPage,_this.topQuestionPagesize,_this.topQuestionList);
|
|||
|
_this.makeReplyItem(result,true);
|
|||
|
});
|
|||
|
|
|||
|
});
|
|||
|
},
|
|||
|
//展开收起效果
|
|||
|
// displayHide:function(){
|
|||
|
// setTimeout(function(){
|
|||
|
// //展开和收起效果
|
|||
|
// let cardBoxArticle=$(".cardBoxArticle");
|
|||
|
// cardBoxArticle.after(`<a class="cardBoxToggle" href="javascript:;">展开</a>`);
|
|||
|
// let cardBoxToggle=$(".cardBoxToggle");
|
|||
|
// let height=cardBoxArticle.height();
|
|||
|
// if(height>70){
|
|||
|
// cardBoxToggle.text("展开").show();
|
|||
|
// cardBoxArticle.css({
|
|||
|
// "height":"70px",
|
|||
|
// "overflow":"hidden",
|
|||
|
// });
|
|||
|
// }else{
|
|||
|
// cardBoxToggle.hide();
|
|||
|
// }
|
|||
|
// $("body").on("click",".cardBoxToggle",function() {
|
|||
|
// height=cardBoxArticle.height();
|
|||
|
// if(height>70){
|
|||
|
// cardBoxToggle.text("展开");
|
|||
|
// cardBoxArticle.css({
|
|||
|
// "height":"70px",
|
|||
|
// "overflow":"hidden",
|
|||
|
// });
|
|||
|
// }else{
|
|||
|
// cardBoxArticle.css({
|
|||
|
// "height":"auto",
|
|||
|
// "overflow":"auto",
|
|||
|
// });
|
|||
|
// cardBoxToggle.text("收起");
|
|||
|
// }
|
|||
|
// });
|
|||
|
// },100);
|
|||
|
// },
|
|||
|
//心跳
|
|||
|
ping:function(){
|
|||
|
let _this=this;
|
|||
|
let mes = {}
|
|||
|
mes.type = "ping";
|
|||
|
mes.data = "visitor:"+_this.visitor.visitor_id;
|
|||
|
setInterval(function () {
|
|||
|
if(_this.socket!=null&&!_this.wsSocketClosed){
|
|||
|
_this.socket.send(JSON.stringify(mes));
|
|||
|
}
|
|||
|
},10000);
|
|||
|
},
|
|||
|
//初始化
|
|||
|
init:function(){
|
|||
|
var _this=this;
|
|||
|
_this.isMobile=isMobile();
|
|||
|
|
|||
|
this.initCss();
|
|||
|
//已读消息
|
|||
|
var ms= 1000*2;
|
|||
|
var lastClick = Date.now() - ms;
|
|||
|
$("body").mouseover(function(){
|
|||
|
if(!_this.haveUnreadMessage){
|
|||
|
return;
|
|||
|
}
|
|||
|
if (Date.now() - lastClick >= ms) {
|
|||
|
lastClick = Date.now();
|
|||
|
//如果有未读消息,调用已读接口
|
|||
|
_this.sendAjax("/2/messages_read","post",{"visitor_id":_this.visitor.visitor_id,"kefu":_this.visitor.to_id},function(data){
|
|||
|
_this.haveUnreadMessage=false;
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
$('body').click(function(){
|
|||
|
clearFlashTitle();
|
|||
|
window.parent.postMessage({type:"focus"},"*");
|
|||
|
//$('.faceBox').hide();
|
|||
|
//剪贴板
|
|||
|
try{
|
|||
|
var selecter = window.getSelection().toString();
|
|||
|
if (selecter != null && selecter.trim() != ""){
|
|||
|
var str=selecter.trim();
|
|||
|
_this.sendInputingStrNow(str);
|
|||
|
}
|
|||
|
} catch (err){
|
|||
|
var selecter = document.selection.createRange();
|
|||
|
var s = selecter.text;
|
|||
|
if (s != null && s.trim() != ""){
|
|||
|
var str=s.trim();
|
|||
|
_this.sendInputingStrNow(str);
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$("body").on("click",".chatNewContent img",function() {
|
|||
|
var url=$(this).attr("data-src");
|
|||
|
if(!url){
|
|||
|
url=$(this).attr("src");
|
|||
|
}
|
|||
|
_this.imgPreviewSrc=[url];
|
|||
|
_this.$refs.preview.clickHandler();
|
|||
|
//new PinchZoom.default($(this)[0], {});
|
|||
|
// _this.$alert("<img src='"+url+"'/>", "", {
|
|||
|
// dangerouslyUseHTMLString: true
|
|||
|
// });
|
|||
|
return false;
|
|||
|
});
|
|||
|
// window.onfocus = function () {
|
|||
|
// //_this.focusHandle();
|
|||
|
// }
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//判断当前是否在iframe中
|
|||
|
if(getQuery("show_title")=='no'){
|
|||
|
_this.isIframe=true;
|
|||
|
}
|
|||
|
//判断微信环境
|
|||
|
_this.checkWechatEnvironmentAndShowImage();
|
|||
|
|
|||
|
this.markdownIt=window.markdownit({
|
|||
|
html: true,
|
|||
|
linkify: true,
|
|||
|
typographer: true,
|
|||
|
});
|
|||
|
},
|
|||
|
//表情点击事件
|
|||
|
faceIconClick:function(index){
|
|||
|
this.showFaceIcon=false;
|
|||
|
this.messageContent+="face"+this.face[index].name;
|
|||
|
},
|
|||
|
//上传图片
|
|||
|
uploadImg:function (url){
|
|||
|
let _this=this;
|
|||
|
$('#uploadImg').after('<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" id="uploadImgFile" name="file" style="display:none" >');
|
|||
|
$("#uploadImgFile").click();
|
|||
|
$("#uploadImgFile").change(function (e) {
|
|||
|
var formData = new FormData();
|
|||
|
var file = $("#uploadImgFile")[0].files[0];
|
|||
|
formData.append("imgfile",file); //传给后台的file的key值是可以自己定义的
|
|||
|
filter(file) && $.ajax({
|
|||
|
url: url || '',
|
|||
|
type: "post",
|
|||
|
data: formData,
|
|||
|
contentType: false,
|
|||
|
processData: false,
|
|||
|
dataType: 'JSON',
|
|||
|
mimeType: "multipart/form-data",
|
|||
|
//添加自定义属性,监听上下文的进度
|
|||
|
xhr: function() {
|
|||
|
//创建原生的ajax请求对象
|
|||
|
var xhr = $.ajaxSettings.xhr();
|
|||
|
//监听进度的一个事件
|
|||
|
xhr.upload.onprogress = function(e) {
|
|||
|
console.log(e.total); //文件大小
|
|||
|
console.log(e.loaded); //上传多少
|
|||
|
var w = parseInt((e.loaded / e.total) * 100)
|
|||
|
console.log(w);
|
|||
|
_this.percentage=w;
|
|||
|
if(w>=100){
|
|||
|
_this.percentage=0;
|
|||
|
}
|
|||
|
}
|
|||
|
return xhr
|
|||
|
},
|
|||
|
success: function (res) {
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else{
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadSuccess'],
|
|||
|
type: 'success'
|
|||
|
});
|
|||
|
_this.messageContent+='img[' + res.result.path + ']';
|
|||
|
_this.chatToUser();
|
|||
|
setTimeout(function () {
|
|||
|
_this.scrollBottom();
|
|||
|
},2000);
|
|||
|
}
|
|||
|
},
|
|||
|
error: function (data) {
|
|||
|
console.log(data);
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadFailed']+data.responseText,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
},
|
|||
|
//上传文件
|
|||
|
uploadFile:function (url){
|
|||
|
let _this=this;
|
|||
|
$('#uploadFile').after('<input type="file" id="uploadRealFile" name="file2" style="display:none" >');
|
|||
|
$("#uploadRealFile").click();
|
|||
|
$("#uploadRealFile").change(function (e) {
|
|||
|
var formData = new FormData();
|
|||
|
var file = $("#uploadRealFile")[0].files[0];
|
|||
|
formData.append("realfile",file); //传给后台的file的key值是可以自己定义的
|
|||
|
console.log(formData);
|
|||
|
$.ajax({
|
|||
|
url: url || '',
|
|||
|
type: "post",
|
|||
|
data: formData,
|
|||
|
contentType: false,
|
|||
|
processData: false,
|
|||
|
dataType: 'JSON',
|
|||
|
mimeType: "multipart/form-data",
|
|||
|
//添加自定义属性,监听上下文的进度
|
|||
|
xhr: function() {
|
|||
|
//创建原生的ajax请求对象
|
|||
|
var xhr = $.ajaxSettings.xhr();
|
|||
|
//监听进度的一个事件
|
|||
|
xhr.upload.onprogress = function(e) {
|
|||
|
console.log(e.total); //文件大小
|
|||
|
console.log(e.loaded); //上传多少
|
|||
|
var w = parseInt((e.loaded / e.total) * 100)
|
|||
|
console.log(w);
|
|||
|
_this.percentage=w;
|
|||
|
if(w>=100){
|
|||
|
_this.percentage=0;
|
|||
|
}
|
|||
|
}
|
|||
|
return xhr
|
|||
|
},
|
|||
|
success: function (res) {
|
|||
|
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else{
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadSuccess'],
|
|||
|
type: 'success'
|
|||
|
});
|
|||
|
//_this.messageContent+='file[' + res.result.path + ']';
|
|||
|
var data=JSON.stringify({
|
|||
|
name:res.result.name,
|
|||
|
ext:res.result.ext,
|
|||
|
size:res.result.size,
|
|||
|
path:res.result.path,
|
|||
|
})
|
|||
|
_this.messageContent+='mutiFile[' + data+ ']';
|
|||
|
_this.chatToUser();
|
|||
|
}
|
|||
|
},
|
|||
|
error: function (data) {
|
|||
|
console.log(data);
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadFailed']+data.responseText,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
},
|
|||
|
//粘贴上传图片
|
|||
|
onPasteUpload:function(event){
|
|||
|
let items = event.clipboardData && event.clipboardData.items;
|
|||
|
let file = null
|
|||
|
if (items && items.length) {
|
|||
|
// 检索剪切板items
|
|||
|
for (var i = 0; i < items.length; i++) {
|
|||
|
if (items[i].type.indexOf('image') !== -1) {
|
|||
|
file = items[i].getAsFile()
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (!file) {
|
|||
|
return;
|
|||
|
}
|
|||
|
let _this=this;
|
|||
|
var formData = new FormData();
|
|||
|
formData.append('imgfile', file);
|
|||
|
$.ajax({
|
|||
|
url: '/uploadimg',
|
|||
|
type: "post",
|
|||
|
data: formData,
|
|||
|
contentType: false,
|
|||
|
processData: false,
|
|||
|
dataType: 'JSON',
|
|||
|
mimeType: "multipart/form-data",
|
|||
|
//添加自定义属性,监听上下文的进度
|
|||
|
xhr: function() {
|
|||
|
//创建原生的ajax请求对象
|
|||
|
var xhr = $.ajaxSettings.xhr();
|
|||
|
//监听进度的一个事件
|
|||
|
xhr.upload.onprogress = function(e) {
|
|||
|
console.log(e.total); //文件大小
|
|||
|
console.log(e.loaded); //上传多少
|
|||
|
var w = parseInt((e.loaded / e.total) * 100)
|
|||
|
console.log(w);
|
|||
|
_this.percentage=w;
|
|||
|
if(w>=100){
|
|||
|
_this.percentage=0;
|
|||
|
}
|
|||
|
}
|
|||
|
return xhr
|
|||
|
},
|
|||
|
success: function (res) {
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else{
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadSuccess'],
|
|||
|
type: 'success'
|
|||
|
});
|
|||
|
_this.messageContent+='img[' + res.result.path + ']';
|
|||
|
_this.chatToUser();
|
|||
|
setTimeout(function () {
|
|||
|
_this.scrollBottom();
|
|||
|
},2000);
|
|||
|
}
|
|||
|
},
|
|||
|
error: function (data) {
|
|||
|
console.log(data);
|
|||
|
_this.$message({
|
|||
|
message: KEFU_LANG[LANG]['uploadFailed']+data.responseText,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
//自动
|
|||
|
getTopQuestion:function(){
|
|||
|
var _this=this;
|
|||
|
$.get("/other/getTopQuestion?ent_id="+ENT_ID,function(res) {
|
|||
|
if(res.code!=200||!res.result){
|
|||
|
return;
|
|||
|
}
|
|||
|
var hotQuestion=res.result.hotQuestion;
|
|||
|
if(hotQuestion!=""){
|
|||
|
_this.hotQuestion=hotQuestion.split(",");
|
|||
|
}
|
|||
|
|
|||
|
var questionList=res.result.questionList;
|
|||
|
if(questionList.length==0){
|
|||
|
return;
|
|||
|
}
|
|||
|
for(var i=0;i<questionList.length;i++){
|
|||
|
var item=questionList[i].split(",")[0];
|
|||
|
questionList[i]=item;
|
|||
|
}
|
|||
|
//多选项卡
|
|||
|
let catResult=res.result.catResult;
|
|||
|
for(let catName in catResult){
|
|||
|
let arr={};
|
|||
|
arr['cat_name']=catName;
|
|||
|
arr['titles']=catResult[catName];
|
|||
|
_this.topQuestionCatResult.push(arr);
|
|||
|
}
|
|||
|
|
|||
|
_this.topQuestionList=questionList;
|
|||
|
_this.topQuestionCount=sumPage(_this.topQuestionPagesize,questionList);
|
|||
|
var result=pagination(1,_this.topQuestionPagesize,questionList);
|
|||
|
_this.makeReplyItem(result);
|
|||
|
});
|
|||
|
},
|
|||
|
makeReplyItem:function(result,isPage){
|
|||
|
var i=1;
|
|||
|
let content="";
|
|||
|
for(key in result){
|
|||
|
content+="<p>"+i+". <a href='#'>"+result[key]+"</a></p>";
|
|||
|
i++;
|
|||
|
}
|
|||
|
this.topQuestionListHtml=content;
|
|||
|
},
|
|||
|
|
|||
|
//提示音
|
|||
|
alertSound:function(soundUrl){
|
|||
|
var b = document.getElementById("chatMessageAudio");
|
|||
|
if (b.canPlayType('audio/ogg; codecs="vorbis"')) {
|
|||
|
b.type= 'audio/mpeg';
|
|||
|
b.src=soundUrl ;
|
|||
|
var p = b.play();
|
|||
|
p && p.then(function () {
|
|||
|
}).catch(function (e) {
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
sendSound:function(){
|
|||
|
var b = document.getElementById("chatMessageSendAudio");
|
|||
|
if (b.canPlayType('audio/ogg; codecs="vorbis"')) {
|
|||
|
b.type= 'audio/mpeg';
|
|||
|
b.src= '/static/images/sent.ogg';
|
|||
|
var p = b.play();
|
|||
|
p && p.then(function(){}).catch(function(e){});
|
|||
|
}
|
|||
|
},
|
|||
|
initPeerjs:function(){
|
|||
|
var peer = new Peer();
|
|||
|
this.peer=peer;
|
|||
|
var _this=this;
|
|||
|
|
|||
|
peer.on('open', function(id) {
|
|||
|
console.log('My peer ID is: ' + id);
|
|||
|
_this.peerjsId=id;
|
|||
|
});
|
|||
|
peer.on('close', function() {
|
|||
|
console.log('My peer close');
|
|||
|
if(_this.loading!=null){
|
|||
|
_this.loading.close();
|
|||
|
}
|
|||
|
});
|
|||
|
peer.on('disconnected', function() {
|
|||
|
console.log('My peer disconnected');
|
|||
|
if(_this.loading!=null){
|
|||
|
_this.loading.close();
|
|||
|
}
|
|||
|
});
|
|||
|
peer.on('error', function() {
|
|||
|
console.log('My peer error');
|
|||
|
if(_this.loading!=null){
|
|||
|
_this.loading.close();
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
//打电话
|
|||
|
callPhone:function(){
|
|||
|
var _this=this;
|
|||
|
var media=(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia);
|
|||
|
if(!media){
|
|||
|
_this.$message({
|
|||
|
type: 'error',
|
|||
|
message: "not support"
|
|||
|
});
|
|||
|
return ;
|
|||
|
}
|
|||
|
var getUserMedia = media.bind(navigator);
|
|||
|
this.$confirm(this.flyLang.videoAudio, this.flyLang.tips, {
|
|||
|
confirmButtonText: this.flyLang.audio,
|
|||
|
cancelButtonText: this.flyLang.cancel,
|
|||
|
type: 'warning'
|
|||
|
}).then(() => {
|
|||
|
|
|||
|
// _this.loading = _this.$loading({
|
|||
|
// lock: true,
|
|||
|
// text: _this.flyLang.connecting,
|
|||
|
// spinner: 'el-icon-phone-outline',
|
|||
|
// background: 'rgba(0, 0, 0, 0.7)'
|
|||
|
// });
|
|||
|
|
|||
|
_this.initPeerjs();//初始化peerjs
|
|||
|
_this.loadingTimerTimeoutClose();
|
|||
|
_this.isVideo=false;
|
|||
|
getUserMedia({video:false, audio: {
|
|||
|
noiseSuppression: true,
|
|||
|
echoCancellation: true,
|
|||
|
}}, function(stream) {
|
|||
|
_this.$message({
|
|||
|
type: 'success',
|
|||
|
message: "语音通话请求已发出,等待客服回复..."
|
|||
|
});
|
|||
|
_this.messageContent="📞"+_this.flyLang.audioCall;
|
|||
|
_this.chatToUser();
|
|||
|
_this.localStream=stream;
|
|||
|
_this.sendAjax("/2/callKefu","post",{"action":"callpeer",kefu_id:_this.visitor.to_id,visitor_id:_this.visitor.visitor_id},function(result){
|
|||
|
});
|
|||
|
}, function(err) {
|
|||
|
_this.$message({
|
|||
|
type: 'error',
|
|||
|
message: err
|
|||
|
});
|
|||
|
if(_this.loading) _this.loading.close();
|
|||
|
});
|
|||
|
}).catch(() => {
|
|||
|
});
|
|||
|
},
|
|||
|
callPeer:function(){
|
|||
|
var _this=this;
|
|||
|
var media=(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia);
|
|||
|
if(!media){
|
|||
|
_this.$message({
|
|||
|
type: 'error',
|
|||
|
message: "not support"
|
|||
|
});
|
|||
|
return ;
|
|||
|
}
|
|||
|
var getUserMedia = media.bind(navigator);
|
|||
|
this.$confirm(this.flyLang.videoAudio, this.flyLang.tips, {
|
|||
|
confirmButtonText: this.flyLang.video,
|
|||
|
cancelButtonText: this.flyLang.cancel,
|
|||
|
type: 'warning'
|
|||
|
}).then(() => {
|
|||
|
|
|||
|
// this.loading = this.$loading({
|
|||
|
// lock: true,
|
|||
|
// text: _this.flyLang.connecting,
|
|||
|
// spinner: 'el-icon-video-camera',
|
|||
|
// background: 'rgba(0, 0, 0, 0.5)'
|
|||
|
// });
|
|||
|
|
|||
|
_this.loadingTimerTimeoutClose();
|
|||
|
this.isVideo=true;
|
|||
|
//初始化peerjs
|
|||
|
this.initPeerjs();
|
|||
|
getUserMedia({video:true, audio: {
|
|||
|
noiseSuppression: true,
|
|||
|
echoCancellation: true,
|
|||
|
}}, function(stream) {
|
|||
|
_this.$message({
|
|||
|
type: 'success',
|
|||
|
message: "视频通话请求已发出,等待客服回复..."
|
|||
|
});
|
|||
|
_this.messageContent="🎥 "+_this.flyLang.videoCall;
|
|||
|
_this.chatToUser();
|
|||
|
_this.localStream=stream;
|
|||
|
|
|||
|
_this.sendAjax("/2/callKefu","post",{"action":"callpeer",kefu_id:_this.visitor.to_id,visitor_id:_this.visitor.visitor_id},function(result){
|
|||
|
});
|
|||
|
}, function(err) {
|
|||
|
_this.$message({
|
|||
|
type: 'error',
|
|||
|
message: err
|
|||
|
});
|
|||
|
if(_this.loading) _this.loading.close();
|
|||
|
});
|
|||
|
}).catch(() => {
|
|||
|
});
|
|||
|
},
|
|||
|
talkPeer:function(){
|
|||
|
var _this=this;
|
|||
|
if(this.loading!=null){
|
|||
|
this.loading.close();
|
|||
|
}
|
|||
|
clearTimeout(this.loadingTimer);
|
|||
|
this.$message({
|
|||
|
message: '正在通话...',
|
|||
|
type: 'success'
|
|||
|
});
|
|||
|
if(_this.kefuPeerId==""||_this.localStream==null){
|
|||
|
return;
|
|||
|
}
|
|||
|
//本人摄像头
|
|||
|
// if(_this.isVideo){
|
|||
|
// var localVideo=document.querySelector("#chatLocalRtc");
|
|||
|
// localVideo.srcObject = _this.localStream;
|
|||
|
// localVideo.autoplay=true;
|
|||
|
// }
|
|||
|
|
|||
|
//localVideo.autoplay = true;
|
|||
|
|
|||
|
_this.call = _this.peer.call(_this.kefuPeerId, _this.localStream);
|
|||
|
_this.call.on('stream', function(remoteStream) {
|
|||
|
console.log(remoteStream);
|
|||
|
var videoTracks = remoteStream.getVideoTracks();
|
|||
|
var audioTracks = remoteStream.getAudioTracks();
|
|||
|
|
|||
|
var remoteVideo = document.getElementById("chatRtc");
|
|||
|
let localVideo = document.getElementById("chatLocalRtc");
|
|||
|
|
|||
|
remoteVideo.srcObject = remoteStream;
|
|||
|
remoteVideo.autoplay = true;
|
|||
|
remoteVideo.play();
|
|||
|
//视频流
|
|||
|
if (videoTracks.length > 0) {
|
|||
|
remoteVideo.style.display = "block";
|
|||
|
remoteVideo.muted=false;
|
|||
|
localVideo.srcObject = _this.localStream;
|
|||
|
localVideo.autoplay = true;
|
|||
|
localVideo.style.display="block";
|
|||
|
|
|||
|
}else if (audioTracks.length > 0) {
|
|||
|
//音频流
|
|||
|
//remoteVideo.style.display = "none";
|
|||
|
remoteVideo.muted=false;
|
|||
|
remoteVideo.autoplay = true;
|
|||
|
localVideo.style.display = "none";
|
|||
|
}
|
|||
|
});
|
|||
|
_this.call.on('close', function() {
|
|||
|
console.log("call close");
|
|||
|
_this.callClear();
|
|||
|
});
|
|||
|
_this.call.on('error', function(err) {
|
|||
|
console.log(err);
|
|||
|
_this.callClear();
|
|||
|
});
|
|||
|
|
|||
|
},
|
|||
|
callClose(){
|
|||
|
var _this=this;
|
|||
|
_this.sendAjax("/2/callKefu","post",{"action":"callCancel",kefu_id:_this.visitor.to_id,visitor_id:_this.visitor.visitor_id},function(result){
|
|||
|
});
|
|||
|
_this.callClear();
|
|||
|
},
|
|||
|
getExtendInfo:function(){
|
|||
|
var _this=this;
|
|||
|
var extra=getQuery("extra");
|
|||
|
if(extra==""){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try{
|
|||
|
var extraString=b64ToUtf8(extra);
|
|||
|
var extra=JSON.parse(extraString);
|
|||
|
if (typeof extra=="string"){
|
|||
|
extra=JSON.parse(extra);
|
|||
|
}
|
|||
|
|
|||
|
for(var key in extra){
|
|||
|
if(extra[key]==""){
|
|||
|
extra[key]="无";
|
|||
|
}
|
|||
|
// if(key=="visitorProduct"){
|
|||
|
// _this.messageContent="product["+JSON.stringify(extra[key])+"]";
|
|||
|
// _this.chatToUser();
|
|||
|
// _this.setCache("extra",extraString);
|
|||
|
// };
|
|||
|
}
|
|||
|
}catch (e) {
|
|||
|
}
|
|||
|
},
|
|||
|
sendAjax:function(url,method,params,callback){
|
|||
|
let _this=this;
|
|||
|
$.ajax({
|
|||
|
type: method,
|
|||
|
url: url,
|
|||
|
data:params,
|
|||
|
headers:{
|
|||
|
"lang":getQuery("lang"),
|
|||
|
},
|
|||
|
error:function(res){
|
|||
|
var data=JSON.parse(res.responseText);
|
|||
|
console.log(data);
|
|||
|
if(data.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: data.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
success: function(data) {
|
|||
|
if(data.code!=200 && data.code!=20000){
|
|||
|
_this.$message({
|
|||
|
message: data.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else if(data.result!=null){
|
|||
|
callback(data.result);
|
|||
|
}else{
|
|||
|
callback([]);
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
showTitle:function(title){
|
|||
|
//this.chatTitle=title;
|
|||
|
title=filterXSS(title);
|
|||
|
this.msgList.push({
|
|||
|
type:"notice",
|
|||
|
content:title,
|
|||
|
});
|
|||
|
//$(".chatVisitorPage").append("<div class=\"chatNotice\"><div class='chatNoticeContent'>"+title+"</div></div>");
|
|||
|
this.scrollBottom();
|
|||
|
},
|
|||
|
//开始录音
|
|||
|
startRecoder:function(){
|
|||
|
if(this.recorder){
|
|||
|
this.recorder.destroy();
|
|||
|
this.recorder=null;
|
|||
|
}
|
|||
|
var _this=this;
|
|||
|
Recorder.getPermission().then(function() {
|
|||
|
_this.recorder = new Recorder();
|
|||
|
_this.recorderAudio = document.querySelector('#audio');
|
|||
|
_this.recorder.start();
|
|||
|
_this.recorder.onprogress = function (params) {
|
|||
|
_this.recoderSecond = parseInt(params.duration);
|
|||
|
if(_this.recoderSecond>=60) _this.stopRecoder();
|
|||
|
}
|
|||
|
}, function(error){
|
|||
|
_this.$message({
|
|||
|
message: error,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
return;
|
|||
|
});
|
|||
|
},
|
|||
|
stopRecoder:function(){
|
|||
|
if(!this.recorder){
|
|||
|
return;
|
|||
|
}
|
|||
|
var blob=this.recorder.getWAVBlob();
|
|||
|
this.recorderAudio.src = URL.createObjectURL(blob);
|
|||
|
this.recorderAudio.controls = true;
|
|||
|
this.recorderEnd=blob;
|
|||
|
this.recorder.destroy();
|
|||
|
this.recorder=null;
|
|||
|
},
|
|||
|
sendRecoder:function(){
|
|||
|
this.stopRecoder()
|
|||
|
if(!this.recorderEnd) return;
|
|||
|
|
|||
|
var formdata = new FormData(); // form 表单 {key:value}
|
|||
|
formdata.append("realfile", this.recorderEnd); // form input type="file"
|
|||
|
var _this=this;
|
|||
|
this.loading = this.$loading({
|
|||
|
background: 'rgba(0, 0, 0, 0.5)'
|
|||
|
});
|
|||
|
$.ajax({
|
|||
|
url: "/2/uploadAudio",
|
|||
|
type: 'post',
|
|||
|
processData: false,
|
|||
|
contentType: false,
|
|||
|
data: formdata,
|
|||
|
dataType: 'JSON',
|
|||
|
mimeType: "multipart/form-data",
|
|||
|
success: function (res) {
|
|||
|
_this.loading.close();
|
|||
|
if(res.code!=200){
|
|||
|
_this.$message({
|
|||
|
message: res.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
}else{
|
|||
|
_this.cancelRecoder();
|
|||
|
_this.messageContent+='audio[' + res.result.path + ']';
|
|||
|
_this.chatToUser();
|
|||
|
_this.recorderEnd=null;
|
|||
|
_this.recoderSecond=0;
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
},
|
|||
|
cancelRecoder:function(){
|
|||
|
this.audioDialog=false;
|
|||
|
if(!this.recorder){
|
|||
|
return;
|
|||
|
}
|
|||
|
this.recorder.destroy();
|
|||
|
this.recorder=null;
|
|||
|
this.recoderSecond=0;
|
|||
|
},
|
|||
|
recoderFormat:function(percentage){
|
|||
|
return percentage+"s";
|
|||
|
},
|
|||
|
openNewWindow:function(){
|
|||
|
var features = "height=800px, width=960px, top=0, left=0, toolbar=no, menubar=no,scrollbars=no,resizable=no, location=no, status=no"; //设置新窗口的特性
|
|||
|
var me = window.open(location.href, "newW", features);
|
|||
|
},
|
|||
|
//超时关闭
|
|||
|
checkTimeout:function(){
|
|||
|
var _this=this;
|
|||
|
this.timeoutTimer=setInterval(function(){
|
|||
|
if (Date.now() - _this.currentActiveTime >= _this.timeoutLongTime) {
|
|||
|
if(_this.VisitorCommentBtn!="true"){
|
|||
|
_this.comment=true;
|
|||
|
_this.scrollBottom();
|
|||
|
}
|
|||
|
console.log("长时间无操作");
|
|||
|
if(_this.socket!=null){
|
|||
|
_this.reconnectDialog=true;
|
|||
|
_this.showTitle(KEFU_LANG[LANG]['autoclosemes']);
|
|||
|
_this.socket.close();
|
|||
|
_this.socket=null;
|
|||
|
}
|
|||
|
window.parent.postMessage({"type":"force_close"},"*");
|
|||
|
}
|
|||
|
},10000);
|
|||
|
},
|
|||
|
closeTimeoutTimer:function(){
|
|||
|
clearInterval(this.timeoutTimer);
|
|||
|
},
|
|||
|
cleanAllTimeout:function(){
|
|||
|
for(var i in this.allTimeouter){
|
|||
|
clearTimeout(this.allTimeouter[i]);
|
|||
|
}
|
|||
|
},
|
|||
|
loadMoreMessages:function(){
|
|||
|
var _this=this;
|
|||
|
var pagesize=5;
|
|||
|
// if(this.currentPage>1){
|
|||
|
// this.replys=[];
|
|||
|
// }
|
|||
|
if(_this.loadMoreDisable){
|
|||
|
return;
|
|||
|
}
|
|||
|
var moreMessage=KEFU_LANG[LANG]['moremessage'];
|
|||
|
this.flyLang.moremessage=this.flyLang.loading;
|
|||
|
this.loadMoreDisable=true;
|
|||
|
var hasUnread=false;
|
|||
|
this.sendAjax("/2/messages_page","get",{pagesize:pagesize,ent_id:ENT_ID,page:this.currentPage,visitor_id:_this.visitor.visitor_id},function(result){
|
|||
|
let msgList=result.list;
|
|||
|
if(msgList.length>=pagesize){
|
|||
|
_this.showLoadMore=true;
|
|||
|
}else{
|
|||
|
_this.showLoadMore=false;
|
|||
|
}
|
|||
|
// if(result.list.length!=0){
|
|||
|
// if(len<pagesize){
|
|||
|
// _this.showLoadMore=false;
|
|||
|
// }else{
|
|||
|
// _this.showLoadMore=true;
|
|||
|
// }
|
|||
|
for(let i=0;i<msgList.length;i++) {
|
|||
|
let visitorMes = msgList[i];
|
|||
|
let content = {}
|
|||
|
if (visitorMes["mes_type"] == "kefu") {
|
|||
|
content.is_kefu = false;
|
|||
|
content.content = _this.markdownHtml(replaceSpecialTag(visitorMes["content"]));
|
|||
|
} else {
|
|||
|
content.is_kefu = true;
|
|||
|
content.content = replaceContent(visitorMes["content"]);
|
|||
|
}
|
|||
|
if (visitorMes["read_status"] == "read") {
|
|||
|
content.read_status = KEFU_LANG[LANG].read;
|
|||
|
} else {
|
|||
|
content.read_status = KEFU_LANG[LANG].unread;
|
|||
|
if(i==0){
|
|||
|
hasUnread=true;
|
|||
|
_this.haveUnreadMessage=true;
|
|||
|
}
|
|||
|
}
|
|||
|
if((i+1)<msgList.length){
|
|||
|
const nextTime = new Date(msgList[i+1]["time"]).getTime();
|
|||
|
const currTime = new Date(visitorMes["time"]).getTime();
|
|||
|
if((currTime-nextTime)>=180000){
|
|||
|
content.show_time=true;
|
|||
|
}else{
|
|||
|
content.show_time=false;
|
|||
|
}
|
|||
|
}
|
|||
|
content.avator = visitorMes["avator"];
|
|||
|
content.name = visitorMes["name"];
|
|||
|
content.msg_id = visitorMes["msg_id"];
|
|||
|
content.time = shortTime(visitorMes["time"]);
|
|||
|
_this.msgList.unshift(content);
|
|||
|
}
|
|||
|
if(_this.currentPage==1){
|
|||
|
_this.scrollBottom();
|
|||
|
}
|
|||
|
_this.currentPage++;
|
|||
|
_this.flyLang.moremessage=moreMessage;
|
|||
|
_this.loadMoreDisable=false;
|
|||
|
});
|
|||
|
},
|
|||
|
//展示微信公众号带参二维码
|
|||
|
showWechatTip:function(){
|
|||
|
return;
|
|||
|
if(this.scanWechatQrcode!="true"){
|
|||
|
return;
|
|||
|
}
|
|||
|
if(this.visitor.visitor_id.substr(0,2)=='wx'){
|
|||
|
this.showTitle("微信访客用户已登录");
|
|||
|
return;
|
|||
|
}
|
|||
|
if(this.VisitorWechatQrcodeUrl==""){
|
|||
|
this.VisitorWechatQrcodeUrl="/wechat/visitorQrcode";
|
|||
|
}
|
|||
|
this.VisitorWechatQrcodeUrl=this.VisitorWechatQrcodeUrl+'?visitor_id=' + this.visitor.visitor_id + '&ent_id='+ENT_ID;
|
|||
|
// var msg={type:"wechatTip"};
|
|||
|
// this.msgList.push(msg);
|
|||
|
var child = '<div class="wechatTip">';
|
|||
|
child += '<img style="width:100px; margin:6px;" src="'+this.VisitorWechatQrcodeUrl+'">';
|
|||
|
child += '扫描或长按左侧二维码关注公众号。<br>可同步聊天消息,防止更换浏览器消息丢失<br>并可及时接收到回复通知</div>';
|
|||
|
$(".chatVisitorPage").append(child);
|
|||
|
},
|
|||
|
sendComment:function(tagName){
|
|||
|
var _this=this;
|
|||
|
if(!_this.commentScore){
|
|||
|
return;
|
|||
|
}
|
|||
|
_this.comment = false;
|
|||
|
this.sendAjax("/2/comment","post",{
|
|||
|
comment_score:_this.commentScore,
|
|||
|
comment_content:_this.commentContent,
|
|||
|
kefu_name:this.visitor.to_id,
|
|||
|
ent_id:ENT_ID,
|
|||
|
visitor_id:_this.visitor.visitor_id},function(result){});
|
|||
|
},
|
|||
|
//格式化时间
|
|||
|
formatTime:function(time) {
|
|||
|
return time;
|
|||
|
},
|
|||
|
|
|||
|
selectLang:function(lang){
|
|||
|
var url=changeURLPar(document.URL,"lang",lang);
|
|||
|
document.location.href=url;
|
|||
|
},
|
|||
|
//focus事件处理
|
|||
|
// focusHandle(){
|
|||
|
// clearFlashTitle();
|
|||
|
// window.location.reload();
|
|||
|
// },
|
|||
|
visitorPageHeight(){
|
|||
|
//$("#chatVisitorPage").css("height","calc(100% - 121px)");
|
|||
|
if(isWeiXin()){
|
|||
|
$("body").css("height","100vh");
|
|||
|
}else{
|
|||
|
let height = Math.min(
|
|||
|
document.documentElement.clientHeight,
|
|||
|
window.innerHeight
|
|||
|
);
|
|||
|
$("body").css("height",height+"px");
|
|||
|
}
|
|||
|
//document.getElementById('chatVisitorPage').style.height = (document.documentElement.clientHeight - 71) + 'px';
|
|||
|
},
|
|||
|
|
|||
|
initCallingDialog(){
|
|||
|
// this.canvasElement=$('#audioCanvas')[0];
|
|||
|
// this.videoElement=$('#chatRtc')[0];
|
|||
|
this.talkPeer();
|
|||
|
},
|
|||
|
//loading关闭
|
|||
|
loadingTimerTimeoutClose(){
|
|||
|
var _this=this;
|
|||
|
if(this.loadingTimer){
|
|||
|
clearTimeout(this.loadingTimer);
|
|||
|
this.loadingTimer=null;
|
|||
|
}
|
|||
|
this.loadingTimer=setTimeout(function(){
|
|||
|
if(_this.loading){
|
|||
|
_this.loading.close();
|
|||
|
}
|
|||
|
_this.callClear();
|
|||
|
}, 60000);
|
|||
|
},
|
|||
|
callClear() {
|
|||
|
var _this=this;
|
|||
|
_this.isCalling=false;
|
|||
|
if(_this.loading){
|
|||
|
_this.loading.close();
|
|||
|
}
|
|||
|
if(_this.call!=null){
|
|||
|
_this.call.close();
|
|||
|
}
|
|||
|
if(_this.localStream){
|
|||
|
var tracks=_this.localStream.getTracks();
|
|||
|
for(var i=0;i<tracks.length;i++){
|
|||
|
tracks[i].stop();
|
|||
|
}
|
|||
|
_this.localStream=null;
|
|||
|
}
|
|||
|
},
|
|||
|
//获取url中的扩展信息
|
|||
|
getUrlExtra(){
|
|||
|
let extra=getQuery("extra");
|
|||
|
if(!extra) return;
|
|||
|
try{
|
|||
|
let extraString=b64ToUtf8(extra);
|
|||
|
let extraJson=JSON.parse(extraString);
|
|||
|
if (typeof extraJson=="string"){
|
|||
|
extraJson=JSON.parse(extraJson);
|
|||
|
}
|
|||
|
this.visitorProduct=extraJson.visitorProduct;
|
|||
|
}catch (e) {
|
|||
|
console.log(e);
|
|||
|
}
|
|||
|
},
|
|||
|
//发送产品信息
|
|||
|
sendProductInfo(){
|
|||
|
if(this.visitorProduct==null) return;
|
|||
|
this.messageContent="product["+JSON.stringify(this.visitorProduct)+"]";
|
|||
|
this.chatToUser();
|
|||
|
this.visitorProduct=null;
|
|||
|
},
|
|||
|
//展示固定营销话术
|
|||
|
sendMarketing(answer){
|
|||
|
let _this=this;
|
|||
|
if(!this.marketing) return;
|
|||
|
let marktingList=this.marketing;
|
|||
|
let item=marktingList.shift();
|
|||
|
if(item){
|
|||
|
let itemArr=item.split("#");
|
|||
|
let ask=itemArr[0];
|
|||
|
if(itemArr.length==2){
|
|||
|
let answerArr=itemArr[1].split("|");
|
|||
|
for(let k in answerArr){
|
|||
|
ask+="<br/><a href='#'>"+answerArr[k]+"</a>";
|
|||
|
}
|
|||
|
}
|
|||
|
let msg={content:ask,avator:this.noticeAvatar,name:this.noticeName}
|
|||
|
setTimeout(function(){
|
|||
|
sendAjax("/2/syncMessage","POST",{
|
|||
|
content:itemArr[0],
|
|||
|
ent_id:ENT_ID,
|
|||
|
visitor_id:_this.visitor.visitor_id,
|
|||
|
kefu_name:_this.visitor.to_id},function(){});
|
|||
|
_this.msgList.push(msg);
|
|||
|
_this.scrollBottom();
|
|||
|
},1000)
|
|||
|
}
|
|||
|
},
|
|||
|
//企业信息
|
|||
|
getEntInfo(){
|
|||
|
let entId=ENT_ID;
|
|||
|
let _this=this;
|
|||
|
sendAjax("/2/entInfo","POST",{ent_id:entId},function(result){
|
|||
|
console.log(result);
|
|||
|
if(result.code!=20000 || !result.result){
|
|||
|
//禁止发送
|
|||
|
_this.sendDisabled=true;
|
|||
|
//隐藏输入框
|
|||
|
_this.reconnectDialog=true;
|
|||
|
//提示
|
|||
|
_this.$message({
|
|||
|
message: result.msg,
|
|||
|
type: 'error'
|
|||
|
});
|
|||
|
return;
|
|||
|
}
|
|||
|
let entInfo=result.result;
|
|||
|
_this.robotNoAnswer=entInfo.RobotNoAnswer;
|
|||
|
_this.noticeName=entInfo.RobotName;
|
|||
|
_this.noticeAvatar=entInfo.RobotAvator;
|
|||
|
_this.robotInfo.RobotCard=entInfo.RobotCard;
|
|||
|
//机器人模式
|
|||
|
if(entInfo.RobotStatus=="2"){
|
|||
|
_this.isRobotModel="yes";
|
|||
|
_this.msgList.push({type:"card"});
|
|||
|
_this.turnToMan=entInfo.TurnToMan.split(",");
|
|||
|
}
|
|||
|
//固定营销话术
|
|||
|
if(entInfo.Marketing) _this.marketing=entInfo.Marketing.replace("\r\n","\n").split("\n");
|
|||
|
//分配客服
|
|||
|
_this.getUserInfo();
|
|||
|
});
|
|||
|
},
|
|||
|
//提交讯前表单
|
|||
|
postPreVisitorForm(){
|
|||
|
this.preVisitorForm.visitor_id=this.visitor.visitor_id;
|
|||
|
this.preVisitorForm.ent_id=ENT_ID;
|
|||
|
let _this=this;
|
|||
|
this.sendAjax("/2/postPreVisitorForm","POST",this.preVisitorForm,function(res){
|
|||
|
_this.msgList.pop();
|
|||
|
_this.chatBoxSend=true;
|
|||
|
});
|
|||
|
},
|
|||
|
//判断微信环境
|
|||
|
checkWechatEnvironmentAndShowImage:function() {
|
|||
|
// 判断是否在 iframe 内
|
|||
|
const isInIframe = window.self !== window.top;
|
|||
|
// 判断是否在微信浏览器打开
|
|||
|
const isWeChatBrowser = /MicroMessenger/i.test(navigator.userAgent);
|
|||
|
// 如果不在 iframe 并且是在微信内打开的
|
|||
|
if (!isInIframe && isWeChatBrowser) {
|
|||
|
// 展示图片
|
|||
|
const img = document.createElement('div');
|
|||
|
img.style.width = '100%';
|
|||
|
img.style.height = '100vh';
|
|||
|
img.style.position = 'fixed'; // 使用 fixed 定位
|
|||
|
img.style.top = '0';
|
|||
|
img.style.left = '0';
|
|||
|
img.style.zIndex = '99999999';
|
|||
|
img.style.background = 'rgba(0, 0, 0, 0.7)';
|
|||
|
img.innerHTML = '<img width="100%" src="/static/images/wechat_notice.png"/>';
|
|||
|
document.body.appendChild(img);
|
|||
|
}
|
|||
|
},
|
|||
|
//解析markdown
|
|||
|
markdownHtml(str){
|
|||
|
var result = this.markdownIt.render(str);
|
|||
|
return result;
|
|||
|
},
|
|||
|
|
|||
|
},
|
|||
|
mounted:function() {
|
|||
|
var _this=this;
|
|||
|
document.addEventListener('paste', this.onPasteUpload);
|
|||
|
document.addEventListener('scroll',this.textareaBlur);
|
|||
|
window.addEventListener('message',function(e){
|
|||
|
var msg=e.data;
|
|||
|
if(msg.module&&msg.module=="locationPicker"){
|
|||
|
_this.qqMap=false;
|
|||
|
console.log('location', msg);
|
|||
|
var address={
|
|||
|
"title":msg.poiaddress,
|
|||
|
"price":msg.poiname,
|
|||
|
"img":"/static/images/qqmap.png",
|
|||
|
"url":"https://apis.map.qq.com/tools/poimarker?type=0&marker=coord:"+msg.latlng.lat+","+msg.latlng.lng+"&key=3ZPBZ-IDF63-PH33P-YOPSA-LUXIH-UKFVR&referer=myapp"
|
|||
|
};
|
|||
|
_this.messageContent="product["+JSON.stringify(address)+"]";
|
|||
|
_this.chatToUser();
|
|||
|
}
|
|||
|
if(msg.type=="inputing_message"){
|
|||
|
_this.sendInputingStrNow(msg.content);
|
|||
|
}
|
|||
|
if(msg.type=="send_message"){
|
|||
|
_this.messageContent=msg.content;
|
|||
|
_this.chatToUser();
|
|||
|
}
|
|||
|
});
|
|||
|
//监听页面关闭
|
|||
|
window.onbeforeunload = function(e) {
|
|||
|
if(_this.isCalling) _this.callClose();
|
|||
|
};
|
|||
|
},
|
|||
|
created: function () {
|
|||
|
this.init();
|
|||
|
this.getEntInfo();
|
|||
|
|
|||
|
|
|||
|
//加载历史记录
|
|||
|
//this.msgList=this.getHistory();
|
|||
|
//滚动底部
|
|||
|
//this.scrollBottom();
|
|||
|
//获取欢迎
|
|||
|
//this.initPeerjs();
|
|||
|
|
|||
|
//this.getVersion();
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
</script>
|
|||
|
</html>
|