kefu/static/templates/default/main_guide.html

848 lines
37 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<title>客服系统</title>
<link rel="stylesheet" href="/static/cdn/element-ui/2.15.7/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.7/index.js"></script>
<script src="/static/cdn/jquery/3.6.0/jquery.min.js"></script>
<script src="/static/cdn/jquery/jquery.qrcode.min.js"></script>
<link rel="stylesheet" href="/static/css/common.css?v=xx2222ddddddddd">
<script src="/static/js/functions.js"></script>
<script src="/static/js/chat-lang.js?v=1.0.1"></script>
</head>
<style>
ul{
margin-left:unset;
}
.el-message-box{
width: 800px;
overflow: auto;
}
</style>
<body class="text-center">
<div id="app">
<template>
<div class="guideHeader">
<span>您好,<{nickname}>&nbsp; <{tel}></span>
<span v-if="roleId=='1'">
<el-button type="text" @click="cleanServer">清理</el-button>
<el-button type="text" @click="stopServer">关闭</el-button>
</span>
</div>
<div class="guideBg margin20" style="display: none">
<{noticeContent}>
</div>
<div class="guideContent">
<div class="guideNotice">
<h6><img src="/static/images/banicon.svg" style="margin-right: 2px"/> 欢迎使用智能在线客服系统</h6>
<p>我们是一站式的AI服务平台轻松构建您和企业的多功能智能在线客服。</p>
<p>可对接渠道网站渠道、二维码对话、H5聊天链接、APP渠道、微信公众号、微信小程序、企业微信客服、企业微信应用、抖音视频评论、抖音小店飞鸽客服、抖音私信、个人微信、钉钉机器人、QQ机器人、
视频号直播中控、淘宝直播中控、小红书直播中控 、抖音直播主播版、抖音直播间、支付宝直播中控</p>
<div class="guideNoticeBtns">
<div>
<el-button size="small" type="primary" v-on:click="window.open(host+'/chatIndex?kefu_id='+kefuName+'&ent_id='+entId)">测试对话</el-button>
<el-button size="small" type="primary" v-on:click="window.open(host+'/kefu/downloadDeploy?token='+localStorage.getItem('token'))">下载部署</el-button>
</div>
<div>
<el-button size="small" type="primary" @click="payDialog=true;">在线充值</el-button>
<el-button size="small" type="primary" v-on:click="window.location.href='/setting_pay'">查看订单</el-button>
</div>
</div>
<img src="/static/images/banner.svg" class="guideNoticeBg"/>
</div>
<div class="left">
<div style="display: flex;margin-top: 10px">
<ul>
<dl>
<dt>商户编号</dt>
<dd><{entId}></dd>
</dl>
<dl>
<dt>客服账号</dt>
<dd><{kefuName}>
</dd>
</dl>
<dl v-show="kefu.role_id!='3'">
<dt>子账号数</dt>
<dd><{kefu.agent_num}>
</dd>
</dl>
<dl v-show="kefuExpired=='on'">
<dt><{flyLang.expireTime}></dt>
<dd><{expireTime}>
<a @click="payDialog=true;">充值</a>
<a href="/setting_pay">订单</a>
</dd>
</dl>
<dl>
<dt>微信通知</dt>
<dd>
微信扫码并关注公众号即可开启,重要消息一个不漏
</dd>
</dl>
<dl style="display: none">
<dt><{flyLang.wechatLink}></dt>
<dd>
<el-button size="small" type="primary" v-on:click="copyText(wechatMenuUrl)"><{flyLang.copy}></el-button>
</dd>
</dl>
<dl v-if="roleId!='3'" style="display: none">
<dt>关闭聊天</dt>
<dd>
<el-button size="small" type="primary" v-on:click="closeDialog=true">关闭</el-button>
</dd>
</dl>
<dl style="display: none">
<dt><{flyLang.dynLink}></dt>
<dd>
<el-button size="small" type="primary" v-on:click="dynicQrcodeDialog=true"><{flyLang.apply}></el-button>
</dd>
</dl>
</ul>
<div style="text-align: center">
<div><img :src="wechatQrcode"></div>
<a @click="showQrcode()"><i class="el-icon-refresh"></i>刷新</a>
</div>
</div>
<el-tabs>
<el-tab-pane :label="flyLang.activity">
<div class="news">
<el-empty :description="flyLang.nodata" v-show="newsList.list.length==0"></el-empty>
<div class="newsItem" v-for="v in newsList.list">
<el-tag effect="dark" :type='v.tag' class="newsTag">
<{v.tag}>
</el-tag>
<a class="newsTitle" @click="showNewsContent(v)"><{v.title}></a>
<span class="newsTime"><{v.created_at}></span>
<div class="clear"></div>
</div>
</div>
<el-pagination
background
@current-change="getNews"
:current-page="newsList.page"
layout="prev,pager, next"
:page-size="newsList.pagesize"
:total="newsList.count">
</el-pagination>
</el-tab-pane>
</el-tabs>
</div>
<div class="middle">
<el-tabs>
<el-tab-pane :label="flyLang.serviceStatistic">
<div class="news" style="font-size: 12px;color: #333;">
<el-table
:empty-text="flyLang.nodata"
:data="rate.list"
style="width: 100%;">
<el-table-column
prop="created_at"
:label="flyLang.createTime"
>
</el-table-column>
<el-table-column
prop="kefu_nickname"
:label="flyLang.account">
</el-table-column>
<el-table-column
:label="flyLang.content"
prop="content">
<template slot-scope="scope">
<el-rate v-model="scope.row.score"
disabled
show-score
text-color="#ff9900"
score-template="{value}"
></el-rate>
<p><{scope.row.content}></p>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
</el-tabs>
</div>
<div style="display: none" class="right">
<el-tabs>
<el-tab-pane :label="flyLang.updownLine">
<div class="news" style="font-size: 12px;color: #333;">
<el-table
:empty-text="flyLang.nodata"
:data="updownList.list"
style="width: 100%;">
<el-table-column
prop="created_at"
:label="flyLang.createTime"
>
</el-table-column>
<el-table-column
prop="client_ip"
:label="flyLang.ipAddress"
>
</el-table-column>
<el-table-column
prop="kefu_name"
:label="flyLang.account">
</el-table-column>
<el-table-column
width="70px"
:label="flyLang.status"
prop="地址">
<template slot-scope="scope">
<el-tag v-if="scope.row.online_status==1" effect="dark" type='success'>
<{flyLang.online}>
</el-tag>
<el-tag effect="dark" v-if="scope.row.online_status==2" type='danger'>
<{flyLang.offline}>
</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<el-pagination
background
@current-change="getUpdownList"
:current-page="updownList.page"
layout="prev,pager, next"
:page-size="updownList.pagesize"
:total="updownList.count">
</el-pagination>
</el-tab-pane>
</el-tabs>
</div>
</div>
<div class="guideStatistics" id="visitorNums" style="height:500px;"></div>
<el-table
v-show="monitorList.length!=0"
:data="monitorList"
border
style="margin-bottom: 10px;" class="guideStatistics">
<el-table-column
width="150px"
prop="ClientIp"
label="ClientIp">
</el-table-column>
<el-table-column
prop="Title"
label="Title">
</el-table-column>
<el-table-column
prop="Url"
label="Url">
</el-table-column>
<el-table-column
prop="Refer"
label="Refer">
</el-table-column>
<el-table-column
prop="StartTime"
label="StartTime">
</el-table-column>
<el-table-column
:label="flyLang.doIt">
<template slot-scope="scope">
<el-button size="mini" type="warning" @click="sendMonitorMessage(scope.row.UinqId,'chat')">chat</el-button>
</template>
</el-table-column>
</el-table>
<!--评价-->
<el-dialog
title="生成访客链接动态二维码"
:close-on-click-modal="false"
:show-close="true"
width="500px"
:visible.sync="dynicQrcodeDialog"
>
<el-alert
style="margin-bottom: 10px"
title="请谨慎生成新二维码,点击重置会使旧二维码失效。确认下面域名已经解析并绑定到客服平台服务器(例如当前网站域名),该域名访客链接可访问"
type="warning"
show-icon>
</el-alert>
<el-input
style="margin-bottom: 10px"
type="textarea"
:rows="2"
placeholder="二维码域名(http/https开头留空为当前登录域名)"
v-model="dynicQrDomain">
</el-input>
<div style="margin-bottom: 20px">
<el-select v-model="dynicQrType" placeholder="请选择链接类型">
<el-option label="普通链接" value="chatIndex"></el-option>
<el-option label="微信链接" value="wechatIndex"></el-option>
</el-select>
</div>
<div id="qrcodeBox" style="position: relative;margin-bottom: 30px">
<img :src="avator" id="qrcodeLogo" style="top:130px;margin-top:-30px;left:130px;margin-left:-30px;position:absolute;border:2px solid #fff;display: none;width: 60px;height:60px;border-radius: 8px;">
<div id="dynicQrImg">
</div>
</div>
<el-button type="warning" @click="mkDynicImage(true)">重置</el-button>
<el-button type="primary" @click="mkDynicImage(false)">生成</el-button>
</el-dialog>
<el-dialog
title="关闭聊天界面公告"
:close-on-click-modal="false"
:show-close="true"
width="500px"
:visible.sync="closeDialog"
>
<el-alert
style="margin-bottom: 10px"
title="关闭聊天请填写,例如:您好,我现在正在休息,暂时停止服务; 如果想取消关闭,请置为空"
type="warning"
show-icon>
</el-alert>
<el-input
style="margin-bottom: 10px"
type="textarea"
:rows="2"
placeholder="您好,我现在正在休息,暂时停止服务"
v-model="CloseNotice">
</el-input>
<el-button type="primary" @click="setCloseNotice()">确定</el-button>
</el-dialog>
<el-dialog
title="在线支付"
:show-close="true"
width="500px"
:visible.sync="payDialog"
>
<div class="payBox">
<div class="payItem">
<div class="payKey">选择时长</div>
<div class="payValue">
<div class="payBtn" v-bind:class="{'active': payMonth==1}" @click="payMonth=1">一个月</div>
<div class="payBtn" v-bind:class="{'active': payMonth==3}" @click="payMonth=3">三个月</div>
<div class="payBtn" v-bind:class="{'active': payMonth==6}" @click="payMonth=6">六个月</div>
<div class="payBtn" v-bind:class="{'active': payMonth==12}" @click="payMonth=12">十二个月</div>
</div>
</div>
<div class="payItem">
<div class="payKey">支付方式</div>
<div class="payValue">
<div class="payBtn" v-bind:class="{'active': payMethod=='wechat'}" @click="payMethod='wechat'">
<i><img width="25" src="/static/images/ua/wechat-pay.svg"/></i>
微信支付
</div>
</div>
</div>
<div class="payItem">
<div class="payKey"></div>
<div class="payValue">
<el-button type="warning" @click="createOrder">确定</el-button>
</div>
</div>
</div>
</el-dialog>
</template>
</div>
</body>
<script src="/static/js/functions.js?v=1.0.0"></script>
<script src="/static/js/echarts.min.js?v=1.0.0"></script>
<script src="/static/js/jquery.qrcode.js"></script>
<script>
var LANG=checkLang();
new Vue({
el: '#app',
delimiters:["<{","}>"],
data: {
flyLang:KEFU_LANG[LANG],
window:window,
host:getBaseUrl(),
kefuId:"",
entId:"",
nickname:"",
kefuName:"",
versionName:"",
lastTime:"",
ipAddress:"",
noticeContent:"",
versionCode:"",
visitorQrcode:"",
visitorUrl:"",
wechatUrl:"",
deployLink:"",
wechatQrcode:"/static/images/textqrcode.png",
wechatMenuUrl:"",
avator:"",
roleId:"",
kefu:{},
newsList:{
list:[],
count:0,
page:1,
pagesize:10,
},
updownList:{
list:[],
count:0,
page:1,
pagesize:7,
},
rate:{
list:[],
count:0,
page:1,
pagesize:10,
},
statistics:{},
needUpdate:false,
dynicQrcodeDialog:false,
dynicQrDomain:"",
dynicQrType:"chatIndex",
dynicQrImg:"",
expireTime:"",
kefuExpired:"",
KefuBindTel:"",
tel:"",
//访客监控列表
monitorList:[],
// 设置重连时间间隔(单位:毫秒)
RECONNECT_INTERVAL: 1000,
// 设置最大重连次数
MAX_RECONNECT_TIMES:30,
reconnectTimes :0,
ws:null,
configs:[],
//关闭服务公告
closeDialog:false,
CloseNotice:"",
//在线支付
payDialog:false,
payMonth:1,
payMethod:"wechat",
},
methods: {
//跳转
openSelfUrl(url){
window.location.href=url;
//this.iframeUrl=url;
},
showStatistics(){
var _this=this;
sendAjax("/statistics","get",{},function(result) {
_this.statistics = result.result;
});
sendAjax("/kefu/chartStatistics","get",{},function(data) {
var result=data.result;
var days=[];
var nums=[];
if(result.length<=0){
return;
}
for(var i=result.length-1;i>=0;i--){
days.push(result[i].day);
nums.push(result[i].num)
}
// 基于准备好的dom初始化echarts实例
$(function () {
var myChart = echarts.init($('#visitorNums')[0],null, {
width: document.documentElement.clientWidth-80,
height: 500
});
// 指定图表的配置项和数据
var option = {
title: {
text: _this.flyLang.visitorPerDay
},
tooltip: {},
legend: {
data: ['数量']
},
xAxis: {
data: days
},
yAxis: {},
series: [
{
name: 'nums',
type: 'line',
data: nums,
barCategoryGap: '40%',
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
});
});
},
copyText(text){
copyText(text);
this.$message({
message: "ok",
type: 'success'
});
},
kefuInfo() {
var _this = this;
sendAjax("/kefu/kefuinfo","get",{},function (data) {
if (data.code != 200) {
window.location.href = "/ironMan/signInx";
} else {
let result = data.result;
_this.kefu=result;
_this.expireTime=dateFormat("Y-m-d",new Date(result.expired_at));
_this.kefuId = result.id;
_this.entId = result.ent_id;
_this.kefuName = result.name;
_this.nickname = result.nickname;
_this.avator = result.avator;
_this.roleId=result.role_id;
_this.tel = result.tel.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
_this.visitorUrl=_this.host+'/chatIndex?kefu_id='+result.name+'%26ent_id='+result.ent_id;
_this.wechatUrl=_this.host+'/wechat/server/'+result.ent_id+'/'+result.name;
_this.visitorQrcode=_this.host+"/kefu/qrcode?str="+_this.visitorUrl+"&token="+localStorage.getItem("token");
_this.wechatMenuUrl=_this.host+'/wechatIndex?ent_id='+result.ent_id+'&kefu_id='+result.name;
_this.showQrcode();
var info=_this.host+'/chatIndex?kefu_id='+result.name+'&ent_id='+result.ent_id;
$("#qrcodeLogo2").show();
$('#dynicQrImg2').empty().qrcode({
text: info, // 二维码的内容
render: "canvas", // 设置渲染方式
width: 180, // 设置宽度: 默认256
height: 180, // 设置高度: 默认256
background: "#ffffff", // 背景颜色
foreground: "#000000", // 前景颜色
});
var info=_this.host+'/wechatIndex?kefu_id='+result.name+'&ent_id='+result.ent_id;
$("#qrcodeLogo3").show();
$('#dynicQrImg3').empty().qrcode({
text: info, // 二维码的内容
render: "canvas", // 设置渲染方式
width: 180, // 设置宽度: 默认256
height: 180, // 设置高度: 默认256
background: "#ffffff", // 背景颜色
foreground: "#000000", // 前景颜色
});
_this.getVersion();
}
});
},
getVersion(){
var _this=this;
sendAjax("/other/systemConfig","get",{},function(data){
var result=data.result;
_this.versionName=result.versionName;
var nowCode=result.version;
_this.versionCode=nowCode;
_this.kefuExpired=result.kefuExpired;
_this.KefuBindTel=result.KefuBindTel;
//判断过期时间
if(_this.kefuExpired){
var endTime=new Date(_this.expireTime).getTime();
var startTime=new Date().getTime();
var day = parseInt((endTime - startTime) / (1000*3600*24))+1
if(day<30){
_this.$confirm('您的账户还剩 <span style="color:#ce3c39;font-weight: bold;">'+day+"</span> 天到期,到期时间"+_this.expireTime+",请充值时间后继续使用!", '通知', {
confirmButtonText: '支付',
cancelButtonText: '关闭',
dangerouslyUseHTMLString: true,
}).then(() => {
_this.payDialog=true;
}).catch(() => {
});
}
}
//判断展示绑定手机号
if(_this.KefuBindTel=="true" && _this.tel==""){
_this.$alert("根据《中华人民共和国网络安全法》,互联网服务需手机实名验证,请前往【菜单=>修改资料】绑定手机号!", '通知', {
confirmButtonText: '确定',
dangerouslyUseHTMLString: true,
});
}
});
},
getNews(page) {
var _this = this;
sendAjax("/other/news","get",{page:page,pagesize:this.newsList.pagesize},function(result){
_this.newsList=result.result;
});
},
getUpdownList(page) {
var _this = this;
sendAjax("/kefu/upDownLineList","get",{page:page,pagesize:this.updownList.pagesize},function(result){
_this.updownList=result.result;
});
},
getServiceStatis() {
var _this=this;
var parames={pagesize:this.rate.pagesize,page:1};
sendAjax("/kefu/rateList","get",parames,function(result){
_this.rate=result.result;
});
},
showNewsContent(item){
this.$alert(item.content, item.title, {
dangerouslyUseHTMLString: true,
});
},
//
showQrcode(){
let _this=this;
sendAjax("/wechat/showQrcode","get",{entId:this.entId,sceneName:"kf_"+this.kefuName},function(res){
if(res.code!=200){
}else{
_this.wechatQrcode=res.result.url
}
});
},
mkDynicImage(reset){
var _this=this;
if(_this.dynicQrDomain==""){
_this.dynicQrDomain=_this.host;
}
var resetFlag="";
if(reset){
resetFlag="reset";
$confirmTitle='此操作将会使旧二维码失效,二维码图片请手动截图另存到本地,是否继续?';
}else{
$confirmTitle="此操作将生成新二维码,二维码图片请手动截图另存到本地,是否继续?"
}
this.$confirm($confirmTitle, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function(){
sendAjax("/kefu/mkDynicQrcode","post",{
domain:_this.dynicQrDomain,
dynicQrType:_this.dynicQrType,
resetFlag:resetFlag,
},function(res) {
var uuid=res.result.uuid;
var info=_this.dynicQrDomain+"/other/checkQrcode?uuid="+uuid;
_this.dynicQrImg=_this.host+"/kefu/qrcode?str="+info+"&token="+localStorage.getItem("token");
$("#qrcodeLogo").show();
$('#dynicQrImg').empty().qrcode({
text: info, // 二维码的内容
render: "canvas", // 设置渲染方式
width: 260, // 设置宽度: 默认256
height: 260, // 设置高度: 默认256
background: "#ffffff", // 背景颜色
foreground: "#000000", // 前景颜色
});
});
});
},
//关闭服务
stopServer(){
var _this=this;
sendAjax("/system/stop","get",{},function(res){
_this.$message({
message: "服务在守护模式下会重启,非守护则直接关闭",
type: 'success'
});
});
},
//清理服务
cleanServer(){
var _this=this;
sendAjax("/system/clean","get",{},function(res){
_this.$message({
message: "操作成功!",
type: 'success'
});
});
},
//获取监控列表
getMonitorList(){
var _this=this;
sendAjax("/kefu/monitorList","get",{},function(result){
_this.monitorList=result.result;
});
},
//发送监控消息
sendMonitorMessage(id,message){
var _this=this;
sendAjax("/kefu/monitorMessage","post",{
"uniqid":id,
"message":message
},function(result){
_this.$message({
message: "ok",
type: 'success'
});
});
},
//创建支付订单
createOrder(){
var _this=this;
sendAjax("/kefu/createOrder","post",{
"pay_method":this.payMethod,
"pay_month":this.payMonth
},function(res){
if(res.code!=20000){
_this.$message({
message: res.msg,
type: 'error'
});
return;
}
let orderId=res.result.order_id;
if(res.result.code_url){
// window.open("/api/v2/qrcode?str="+res.result.code_url);
let html='<div style="text-align: center"><h2>金额:'+res.result.ammount/100+'</h2><img src="/api/v2/qrcode?str='+res.result.code_url+'" /></div>';
_this.$confirm(html, '通知', {
confirmButtonText: '查询订单状态',
dangerouslyUseHTMLString: true,
}).then(() => {
sendAjax("/kefu/queryWechatOrder","post",{
"order_id":orderId,
},function(res){
if(res.code!="20000"){
_this.$message({
message: "订单未成功支付!",
type: 'error'
});
}else{
_this.$message({
message: "订单已经成功支付!",
type: 'success'
});
location.reload();
}
})
}).catch(() => {
});
// _this.$alert('请在扫码支付后,点击同步状态,将查询微信支付订单结果并同步本地订单状态', '支付订单', {
// confirmButtonText: '同步状态',
// callback: action => {
//
// }
// });
}
});
},
getConfigs(){
let _this=this;
sendAjax("/kefu/ent_configs","get",{},function(result){
_this.configs=result.result;
_this.CloseNotice=_this.getConfig("CloseNotice");
});
},
getConfig(key){
for(index in this.configs){
if(key==this.configs[index].conf_key){
return this.configs[index].conf_value;
}
}
return "";
},
//切换机器人
setCloseNotice(){
let _this=this;
sendAjax("/kefu/entConfigs","POST",{name:"服务关闭公告",key:"CloseNotice",value:_this.CloseNotice},function(result) {
_this.$message({
message: "success",
type: 'success'
});
_this.getConfigs();
});
},
/**
* 连接websocket
*/
connect () {
var _this=this;
var domain=getDomainFromUrl("");
var protocol=getProtocolFromUrl("");
var wsProtocol="ws://";
if(protocol=="https"){
wsProtocol="wss://";
}
let ws = new WebSocket(wsProtocol+domain+"/ws_kefu?token="+localStorage.getItem("token"));
ws.onopen = function () {
console.log('WebSocket 连接已打开');
_this.reconnectTimes = 0;
};
ws.onclose = function () {
console.log('WebSocket 连接已关闭');
// 尝试重连
_this.reconnect();
};
ws.onmessage = function (event) {
console.log(`收到服务器的消息:${event.data}`);
// 解析消息
const message = JSON.parse(event.data);
//监控列表删除
if (message.type === 'monitorOffline') {
let id=message.data.UinqId;
_this.monitorList=removeObjects(_this.monitorList,"UinqId",id);
}
//监控列表增加
if (message.type === 'monitorOnline') {
let obj=message.data;
_this.monitorList.unshift(obj);
}
};
_this.ws=ws;
},
// 尝试重连
reconnect(){
var _this=this;
if (_this.reconnectTimes >= _this.MAX_RECONNECT_TIMES) {
console.log('重连失败');
return;
}
_this.reconnectTimes++;
console.log(`正在尝试重连(第 ${_this.reconnectTimes} 次)`);
setTimeout(function () {
_this.connect();
}, _this.RECONNECT_INTERVAL);
}
},
mounted:function(){
},
created: function () {
this.getConfigs();
this.showStatistics();
this.kefuInfo();
this.getNews(1);
this.getUpdownList(1);
this.getServiceStatis();
this.getMonitorList();
var _this=this;
setTimeout(function () {
_this.connect();
},5000)
}
})
</script>
</html>