kefu/static/templates/default/main_guide.html

848 lines
37 KiB
HTML
Raw Permalink Normal View History

2024-12-10 02:50:12 +00:00
<!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>