1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-07-28 12:32:15 +08:00

Closed https://github.com/chatopera/cosin/issues/251 enhance chatbot services for agent and visitor

This commit is contained in:
Hai Liang Wang 2019-12-22 16:17:03 +08:00
parent 6abacc646e
commit ac7a346bf6
27 changed files with 693 additions and 68 deletions

View File

@ -276,6 +276,11 @@ public class AgentAuditController extends Handler {
if (agentUser != null) {
view.addObject("curagentuser", agentUser);
CousultInvite invite = OnlineUserProxy.consult(agentUser.getAppid(), agentUser.getOrgi());
if (invite != null) {
view.addObject("ccaAisuggest", invite.isAisuggest());
}
view.addObject("inviteData", OnlineUserProxy.consult(agentUser.getAppid(), agentUser.getOrgi()));
List<AgentUserTask> agentUserTaskList = agentUserTaskRes.findByIdAndOrgi(id, orgi);
if (agentUserTaskList.size() > 0) {

View File

@ -262,7 +262,7 @@
User logined = super.getUser(request);
view.addObject(
"agentUserList", agentUserRes.findByAgentnoAndOrgi(logined.getId(), logined.getOrgi(),
new Sort(Direction.DESC, "status")));
new Sort(Direction.DESC, "status")));
List<AgentUser> agentUserList = agentUserRes.findByUseridAndOrgi(userid, logined.getOrgi());
view.addObject(
"curagentuser", agentUserList != null && agentUserList.size() > 0 ? agentUserList.get(0) : null);
@ -317,7 +317,7 @@
String id,
String search,
String condition
) throws IOException, TemplateException {
) throws IOException, TemplateException {
String mainagentuserconter = "/apps/agent/mainagentusersearch";
ModelAndView view = request(super.createRequestPageTempletResponse(mainagentuserconter));
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
@ -386,6 +386,11 @@
if (agentUser != null) {
view.addObject("curagentuser", agentUser);
CousultInvite invite = OnlineUserProxy.consult(agentUser.getAppid(), agentUser.getOrgi());
if (invite != null) {
view.addObject("aisuggest", invite.isAisuggest());
}
view.addObject("inviteData", OnlineUserProxy.consult(agentUser.getAppid(), agentUser.getOrgi()));
List<AgentUserTask> agentUserTaskList = agentUserTaskRes.findByIdAndOrgi(id, orgi);
if (agentUserTaskList.size() > 0) {
@ -405,8 +410,8 @@
view.addObject(
"agentUserMessageList",
this.chatMessageRes.findByUsessionAndOrgi(agentUser.getUserid(), orgi,
new PageRequest(0, 20, Direction.DESC,
"updatetime")));
new PageRequest(0, 20, Direction.DESC,
"updatetime")));
AgentService agentService = null;
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
agentService = this.agentServiceRes.findOne(agentUser.getAgentserviceid());
@ -454,10 +459,10 @@
view.addObject("serviceCount", Integer
.valueOf(this.agentServiceRes
.countByUseridAndOrgiAndStatus(agentUser
.getUserid(), orgi,
MainContext.AgentUserStatusEnum.END
.toString())));
.countByUseridAndOrgiAndStatus(agentUser
.getUserid(), orgi,
MainContext.AgentUserStatusEnum.END
.toString())));
view.addObject("tagRelationList", tagRelationRes.findByUserid(agentUser.getUserid()));
}
@ -519,7 +524,7 @@
map.addAttribute(
"workOrdersList",
dataExchange.getListDataByIdAndOrgi(contactsid, super.getUser(request).getId(),
super.getOrgi(request)));
super.getOrgi(request)));
}
map.addAttribute("contactsid", contactsid);
}
@ -546,14 +551,14 @@
// 为该坐席分配访客
acdAgentService.assignVisitors(agentStatus.getAgentno(), orgi);
acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(),
agentStatus.getUsername(),
agentStatus.getAgentno(),
logined.isAdmin(), // 0代表admin
agentStatus.getAgentno(),
MainContext.AgentStatusEnum.NOTREADY.toString(),
MainContext.AgentStatusEnum.READY.toString(),
MainContext.AgentWorkType.MEIDIACHAT.toString(),
orgi, null);
agentStatus.getUsername(),
agentStatus.getAgentno(),
logined.isAdmin(), // 0代表admin
agentStatus.getAgentno(),
MainContext.AgentStatusEnum.NOTREADY.toString(),
MainContext.AgentStatusEnum.READY.toString(),
MainContext.AgentWorkType.MEIDIACHAT.toString(),
orgi, null);
return request(super.createRequestPageTempletResponse("/public/success"));
}
@ -584,14 +589,14 @@
agentStatusProxy.broadcastAgentsStatus(orgi, "agent", "notready", agentStatus.getAgentno());
acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(),
agentStatus.getUsername(),
agentStatus.getAgentno(),
logined.isAdmin(), // 0代表admin
agentStatus.getAgentno(),
MainContext.AgentStatusEnum.READY.toString(),
MainContext.AgentStatusEnum.NOTREADY.toString(),
MainContext.AgentWorkType.MEIDIACHAT.toString(),
orgi, null);
agentStatus.getUsername(),
agentStatus.getAgentno(),
logined.isAdmin(), // 0代表admin
agentStatus.getAgentno(),
MainContext.AgentStatusEnum.READY.toString(),
MainContext.AgentStatusEnum.NOTREADY.toString(),
MainContext.AgentWorkType.MEIDIACHAT.toString(),
orgi, null);
return request(super.createRequestPageTempletResponse("/public/success"));
}
@ -695,7 +700,7 @@
}
agentServiceRes.save(agentServiceList);
return request(super
.createRequestPageTempletResponse("redirect:/agent/index.html"));
.createRequestPageTempletResponse("redirect:/agent/index.html"));
}
@ -733,7 +738,7 @@
}
return request(super
.createRequestPageTempletResponse("redirect:/agent/index.html"));
.createRequestPageTempletResponse("redirect:/agent/index.html"));
}
@RequestMapping({"/readmsg"})

View File

@ -91,6 +91,9 @@ public class IMController extends Handler {
@Value("${web.upload-path}")
private String path;
@Value("${cskefu.settings.webim.visitor-separate}")
private Boolean channelWebIMVisitorSeparate;
@Autowired
private StreamingFileRepository streamingFileRepository;
@ -166,6 +169,8 @@ public class IMController extends Handler {
@Valid String title,
@Valid String aiid) {
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/point"));
view.addObject("channelVisitorSeparate", channelWebIMVisitorSeparate);
final String sessionid = MainUtils.getContextID(request.getSession().getId());
logger.info("[point] session snsid {}, session {}", id, sessionid);
@ -957,7 +962,7 @@ public class IMController extends Handler {
view.addObject("port", request.getServerPort());
view.addObject("schema", request.getScheme());
view.addObject("appid", appid);
view.addObject("channelVisitorSeparate", channelWebIMVisitorSeparate);
view.addObject("ip", MainUtils.md5(request.getRemoteAddr()));
if (invite.isSkill() && invite.isConsult_skill_fixed()) { // 添加技能组ID

View File

@ -40,6 +40,7 @@ public class Chatbot {
@Column(unique = true)
private String snsAccountIdentifier; // 渠道唯一标识
private boolean enabled; // 当前是否被启用
private boolean aisuggest; // 智能回复是否被启用
private String workmode; // 工作模式, 机器人优先还是人工客服优先
private Date createtime;
@ -84,6 +85,14 @@ public class Chatbot {
this.enabled = enabled;
}
public boolean isAisuggest() {
return aisuggest;
}
public void setAisuggest(boolean botAutocomplete) {
this.aisuggest = botAutocomplete;
}
public String getPrimaryLanguage() {
return primaryLanguage;
}

View File

@ -142,6 +142,7 @@ public class CousultInvite implements java.io.Serializable {
private String aimsg; //AI欢迎信息可以使用 HTML
private String aisuccesstip;//AI服务连接成功的消息提示
private String ainame; //AI服务 昵称
private boolean aisuggest;
private String aiid; //默认的机器人
@ -929,6 +930,14 @@ public class CousultInvite implements java.io.Serializable {
this.consult_skill_fixed_id = consult_skill_fixed_id;
}
public boolean isAisuggest() {
return aisuggest;
}
public void setAisuggest(boolean aisuggest) {
this.aisuggest = aisuggest;
}
public boolean isWhitelist_mode() {
return whitelist_mode;
}

View File

@ -105,8 +105,8 @@ public class AgentServiceProxy {
orgi,
MainContext.AgentUserStatusEnum.END.toString(),
defaultSort
)
);
)
);
if (StringUtils.isNotBlank(agentService.getAppid())) {
map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(agentService.getAppid(), orgi));
@ -200,6 +200,12 @@ public class AgentServiceProxy {
final User logined) {
view.addObject("curagentuser", agentUser);
CousultInvite invite = OnlineUserProxy.consult(agentUser.getAppid(), agentUser.getOrgi());
if (invite != null) {
view.addObject("aisuggest", invite.isAisuggest());
view.addObject("ccaAisuggest", invite.isAisuggest());
}
// 客服设置
if (agentUser != null && StringUtils.isNotBlank(agentUser.getAppid())) {
view.addObject("inviteData", OnlineUserProxy.consult(agentUser.getAppid(), orgi));
@ -216,8 +222,8 @@ public class AgentServiceProxy {
view.addObject(
"agentUserMessageList",
chatMessageRepository.findByUsessionAndOrgi(agentUser.getUserid(), logined.getOrgi(),
new PageRequest(0, 20, Sort.Direction.DESC,
"updatetime")));
new PageRequest(0, 20, Sort.Direction.DESC,
"updatetime")));
// 坐席服务记录
AgentService agentService = null;
@ -227,7 +233,7 @@ public class AgentServiceProxy {
/**
* 获取关联数据
*/
if(agentService != null){
if (agentService != null) {
processRelaData(logined.getId(), orgi, agentService, map);
}
}
@ -239,9 +245,9 @@ public class AgentServiceProxy {
// 标签快捷回复等
view.addObject("serviceCount", Integer
.valueOf(agentServiceRes
.countByUseridAndOrgiAndStatus(agentUser
.getUserid(), logined.getOrgi(),
MainContext.AgentUserStatusEnum.END.toString())));
.countByUseridAndOrgiAndStatus(agentUser
.getUserid(), logined.getOrgi(),
MainContext.AgentUserStatusEnum.END.toString())));
view.addObject("tagRelationList", tagRelationRes.findByUserid(agentUser.getUserid()));
}

View File

@ -186,6 +186,12 @@ cskefu.callout.watch.interval=60000
##############################################
bot.baseurl=https://bot.chatopera.com
##############################################
# 业务功能相关设置
##############################################
# 是否开启渠道访客独立 https://gitlab.chatopera.com/chatopera/cosinee/issues/838
cskefu.settings.webim.visitor-separate=false
##############################################
# Skype渠道集成配置
##############################################

View File

@ -352,10 +352,10 @@ input,textarea{
background-color: #c7dcfa !important;
}
.chatting-left div.chat-content img{
max-width:460px;
max-width:100%;
}
.chatting-right div.chat-content img{
max-width:460px;
max-width:100%;
}
.chatting-left div.chat-content a{
color:#4665d4;

View File

@ -52,6 +52,9 @@ $(document).ready(function(){
multiMediaDialogWin.Proxy.newAgentUserMessage(data,"agent");
if(data.type == 'message'){
WebIM.audioplayer('audioplane', newmessage, false); // 播放
if(multiMediaDialogWin.isAisuggest && multiMediaDialogWin.isAisuggest == "true"){
multiMediaDialogWin.Proxy.quickReply(data,"agent");
}
}
}else{
//来电弹屏
@ -74,6 +77,9 @@ $(document).ready(function(){
customerChatAudit.Proxy.newAgentUserMessage(data,"cca");
if(data.type == 'message'){
WebIM.audioplayer('audioplane', newmessage, false); // 播放
if(customerChatAudit.isCcaAisuggest && customerChatAudit.isCcaAisuggest == "true"){
customerChatAudit.Proxy.quickReply(data,"cca");
}
}
}
}).on('audit_new', function(data){

View File

@ -1,4 +1,4 @@
var layer , iframe , layerwin , cursession ;
var layer , iframe , layerwin , cursession ;
$(document).ready(function(){
var hide ;
$('.dropdown-menu').on("click" , function(){
@ -333,7 +333,6 @@ var Proxy = {
var newlist = template($('#message_tpl').html(), {data: data})
var nodeMeassage = $(newlist);
nodeMeassage.find(".iconclick").click(function () {
console.log("点击标注")
if($(this).attr('name') == 'nolabe'){
$(this).html('&#xe616;')
$(this).css('color','#46cad4')
@ -366,6 +365,62 @@ var Proxy = {
}
}
},
quickReply:function(data,type){
if(data.usession == cursession){
if(data.message!=""){
restApiRequest({
silent: true,
path: 'chatbot',
data: {
ops: 'faq',
snsaccountid: data.appid ,
userId:data.userid,
textMessage:data.message
}
}).then(function(result){
if(result.rc === 0){
if(result.data.length>0){
type == "agent" ? $("#quickReplyBox").html("") : $("#ccaQuickReplyBox").html("") ;
$.each(sortByKey(result.data,'score'),function(i,n){
var li = ' <li class="ukefu-agentservice-list" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">\n' +
' <div class="nowrap" title="'+result.data[i].post+'">问题:'+result.data[i].post+'</div>\n' +
' <div style="color: #333">\n' +
' <p class="nowrap" title="'+result.data[i].reply_plain_text+'" style="float: left ">答案:'+result.data[i].reply_plain_text+'</p>\n' +
' <button style="float: right" class="layui-btn layui-btn-mini" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">选择</button>\n' +
' </div>\n' +
' </li>'
type == "agent" ? $("#quickReplyBox").append(li) : $("#ccaQuickReplyBox").append(li) ;
if(i>4){
return false;
}
});
if(!$("#robot").hasClass('layui-this')){
$("#dot").css("display","inline-block")
}
}else{
type == "agent" ? $("#quickReplyBox").html("") : $("#ccaQuickReplyBox").html("") ;
$("#dot").css("display","none")
var liNone = ' <li style="list-style: none;background-image: url();padding: 50px 0 50px;">\n' +
' <div class="ukefu-empty" style="background: none">\n' +
' <i class="layui-icon"></i>\n' +
' <div style="">在知识库中未得到相关问题</div>\n' +
' </div>\n' +
' </li>'
type == "agent" ? $("#quickReplyBox").html(liNone) : $("#ccaQuickReplyBox").html(liNone) ;
}
}else{
type == "agent" ? $("#quickReplyBox").html("") : $("#ccaQuickReplyBox").html("") ;
$("#dot").css("display","none")
}
}, function(error){
console.log("error", error);
// 服务器异常
top.layer.msg('服务器抽风,请稍后再试!',{icon: 2, time: 3000})
})
}
}
},
endAgentUserService:function(data){
if($('#tip_message_'+data.userid).length >0){
if(data.channel){

View File

@ -1,6 +1,7 @@
<link rel="stylesheet" href="/js/ztree/zTreeStyle/zTreeStyle.css">
<script src="/js/ztree/jquery.ztree.all.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/lodash-4.17.4.min.js"></script>
<script src="/js/CSKeFu_Rest_Request.v1.js"></script>
<!--<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>-->
<script id="message_tpl" type="text/html">

View File

@ -1,6 +1,6 @@
<script language="javascript">
cursession = "<#if curagentuser??>${curagentuser.userid!''}</#if>" ;
var userid = "${curagentuser.userid!''}" , agentserviceid = "${curagentuser.agentserviceid!''}" , agentuserid = "${curagentuser.id}" , masscuragentuser = "${masscuragentuser}";
var userid = "${curagentuser.userid!''}" , agentserviceid = "${curagentuser.agentserviceid!''}" , agentuserid = "${curagentuser.id}" , masscuragentuser = "${masscuragentuser}" , isAisuggest = "${aisuggest}";
</script>
<div class="main-agentuser">
@ -59,6 +59,15 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
</div>
</div>
<div class="chat-bottom">
<div id="agentAnswer" style="width: 50%;min-width:310px;height: 180px;border: 1px solid #eee;position: absolute;top: -180px;right:0px;background: #ffffff;display: none">
<h1 class="site-h1" style="background-color:#EEEEEE;padding: 0px 10px" >知识库联想
<i class="layui-icon" style="position: absolute;top: 0px;right: 5px;font-size:16px;z-index: 10" onclick="showOrHide('none')">&#x1006;</i>
</h1>
<div style="width: calc(100% - 19px);height: 129px;position: absolute;top: 31px;overflow-y: scroll;padding: 10px 10px">
<ul class="info-list ukefu-quick-reply" style="width: 100%;height: auto" id="quickReplyAgentBox">
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<textarea id="message" name="message"></textarea>
@ -71,7 +80,7 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
}
</style>
<script language="javascript">
var editor , layer;
var editor , layer;
$(document).ready(function(){
// KindEditor.ready(function(K) {
var K = KindEditor;
@ -145,6 +154,53 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
});
// });
KindEditor.options.cssData = "body { font-size: 15px; font-family:'Microsoft Yahei', 'Helvetica', 'Simsun', 'Arial';}";
var agentEnterInput = $("iframe").contents().find("body");
agentEnterInput.keyup(function(event){
if(isAisuggest && isAisuggest == "true"){
debouncefun();
}
})
var debouncefun = _.debounce(agentQuickReply,500)
function agentQuickReply() {
restApiRequest({
silent: true,
path: 'chatbot',
data: {
ops: 'faq',
snsaccountid: "<#if curagentuser??>${curagentuser.appid!''}</#if>",
userId:"<#if curagentuser??>${curagentuser.userid!''}</#if>",
textMessage:editor.html()
}
}).then(function(result){
if(result.rc === 0){
if(result.data.length > 0){
$("#quickReplyAgentBox").html("");
$.each(sortByKey(result.data,'score'),function(i,n){
var li = ' <li class="ukefu-agentservice-list" style="font-size: 14px;line-height:22px" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">\n' +
' <div class="nowrap" title="'+result.data[i].post+'">问题:'+result.data[i].post+'</div>\n' +
' <div style="color: #333">\n' +
' <p title="'+result.data[i].reply_plain_text+'" class="nowrap" style="float: left ">答案:'+result.data[i].reply_plain_text+'</p>\n' +
' <button style="float: right" class="layui-btn layui-btn-mini" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">选择</button>\n' +
' </div>\n' +
' </li>'
$("#quickReplyAgentBox").append(li);
if(i>4){
return false;
}
});
showOrHide('block')
}else{
showOrHide('none')
}
}else{
showOrHide('none')
}
}, function(error){
console.log("error", error);
// 服务器异常
top.layer.msg('服务器抽风,请稍后再试!',{icon: 2, time: 3000})
})
}
});
</script>
</div>
@ -157,6 +213,12 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
<div class="layui-tab" style="margin-top:0px;">
<ul class="layui-tab-title">
<li class="layui-this">访客</li>
<#if aisuggest?? && aisuggest == true>
<li id="robot" onclick="$('#dot').css('display','none')">
<span>智能机器人</span>
<span id="dot" style=" width: 7px;height: 7px;background: red;-moz-border-radius: 50%;-webkit-border-radius: 50%;border-radius: 50%;position: absolute;top: 5px;display: none"></span>
</li>
</#if>
<li>历史</li>
<li>搜索历史消息</li>
<#if models?seq_contains("workorders")>
@ -260,6 +322,27 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
</#if>
</div>
<#if aisuggest?? && aisuggest == true>
<div class="layui-tab-item">
<div class="box">
<div class="box-title">
<h1 class="site-h1" style="background-color:#EEEEEE;">
知识库快捷
</h1>
</div>
<div class="box-body" style="padding:0px 10px;">
<ul class="info-list ukefu-quick-reply" id="quickReplyBox">
<li style="list-style: none;background-image: url();padding: 50px 0 50px;">
<div class="ukefu-empty" style="background: none">
<i class="layui-icon"></i>
<div style="">未触发知识库查询</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</#if>
<div class="layui-tab-item">
<div class="box">
<div class="box-title">
@ -418,12 +501,21 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
color: #00a65a;
font-weight: bold;
}
.nowrap{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 40px);
}
</style>
<script>
$(document).ready(function() {
var test = window.location.search;
if(isAisuggest && isAisuggest == "true"){
switchQuickReply();
}
})
document.getElementById('chat_msg_list').scrollTop = document.getElementById('chat_msg_list').scrollHeight;
layui.use('element', function(){
@ -478,12 +570,78 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
var count = editor.count("text");
if(count>0){
var message = document.getElementById('message').value;
top.WebIM.sendMessage(message , '${user.id!''}' , "${curagentuser.appid!''}" , "${user.sessionid!''}" , "${orgi!''}" , "<#if curagentuser??>${curagentuser.userid!''}</#if>" , "${user.username!''}");
top.WebIM.sendMessage(message , "${user.id!''}" , "${curagentuser.appid!''}" , "${user.sessionid!''}" , "${orgi!''}" , "<#if curagentuser??>${curagentuser.userid!''}</#if>" , "${user.username!''}");
}
editor.html('');
showOrHide('none');
};
$(document).keyup(function(event){
function chooseAnswer(data){
editor.html(data)
}
function showOrHide(data){
$("#agentAnswer").css("display",data)
}
// 排序
function sortByKey(array, key) {
return array.sort(function(a, b) {
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
function switchQuickReply(){
var hatContentHtml = $("#chat_msg_list .chat-block").last().find(".chatting-left .chat-content").html();
if($.trim(hatContentHtml)){
restApiRequest({
silent: true,
path: 'chatbot',
data: {
ops: 'faq',
snsaccountid: "<#if curagentuser??>${curagentuser.appid!''}</#if>",
userId:"<#if curagentuser??>${curagentuser.userid!''}</#if>",
textMessage:hatContentHtml
}
}).then(function(result){
if(result.rc === 0){
if(result.data.length>0){
$("#quickReplyBox").html("");
$.each(sortByKey(result.data,'score'),function(i,n){
var li = ' <li class="ukefu-agentservice-list" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">\n' +
' <div class="nowrap" title="'+result.data[i].post+'">问题:'+result.data[i].post+'</div>\n' +
' <div style="color: #333">\n' +
' <p class="nowrap" title="'+result.data[i].reply_plain_text+'" style="float: left ">答案:'+result.data[i].reply_plain_text+'</p>\n' +
' <button style="float: right" class="layui-btn layui-btn-mini" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">选择</button>\n' +
' </div>\n' +
' </li>'
$("#quickReplyBox").append(li);
if (i>4){
return false;
}
});
if(!$("#robot").hasClass('layui-this')){
$("#dot").css("display","inline-block")
}
}else{
$("#dot").css("display","none")
$("#quickReplyBox").html(' <li style="list-style: none;background-image: url();padding: 50px 0 50px;">\n' +
' <div class="ukefu-empty" style="background: none">\n' +
' <i class="layui-icon"></i>\n' +
' <div style="">在知识库中未得到相关问题</div>\n' +
' </div>\n' +
' </li>');
}
}
}, function(error){
console.log("error", error);
// 服务器异常
top.layer.msg('服务器抽风,请稍后再试!',{icon: 2, time: 3000})
})
}
}
$("#searchconter").keyup(function(event){
if(event.keyCode ==13){
$("#search").click();
}
@ -590,7 +748,6 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
,done: function(page, next){ //执行下一页的回调
//模拟数据插入
current += 20;
console.log(current);
setTimeout(function(){
var lis = [];
var pages = 0;

View File

@ -17,7 +17,7 @@
<select id="agent" name="agentno" class="ukefu-input" lay-ignore style="width: 100px;display: inline-block">
<option value="">请选择技能组</option>
</select>
<div class="layui-input-inline" style="float: right;width: auto">
<div class="layui-input-inline" style="float: right;width: auto;margin-right: 0px">
<button class="layui-btn layui-btn-small layui-btn-primary" style="color:#ffffff;">
<i class="layui-icon"></i>
</button>

View File

@ -1,5 +1,7 @@
<link rel="stylesheet" href="/js/ztree/zTreeStyle/zTreeStyle.css">
<script src="/js/ztree/jquery.ztree.all.min.js"></script>
<script src="/js/lodash-4.17.4.min.js"></script>
<script src="/js/CSKeFu_Rest_Request.v1.js"></script>
<!--<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>-->
<script id="message_tpl" type="text/html">
<div class="clearfix chat-block" <%if(data.type == 'writing'){%>id="writing"<%}%>>

View File

@ -1,6 +1,6 @@
<script language="javascript">
cursession = "<#if curagentuser??>${curagentuser.userid!''}</#if>";
var userid = "${curagentuser.userid!''}", agentserviceid = "${curagentuser.agentserviceid!''}", agentuserid = "${curagentuser.id}";
var userid = "${curagentuser.userid!''}", agentserviceid = "${curagentuser.agentserviceid!''}", agentuserid = "${curagentuser.id}" ,isCcaAisuggest = "${ccaAisuggest}";
</script>
<div class="main-agentuser">
@ -56,6 +56,15 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
</div>
</div>
<div class="chat-bottom">
<div id="ccaAgentAnswer" style="width: 50%;min-width:310px;height: 180px;border: 1px solid #eee;position: absolute;top: -180px;right:0px;background: #ffffff;display: none">
<h1 class="site-h1" style="background-color:#EEEEEE;padding: 0px 10px" >知识库联想
<i class="layui-icon" style="position: absolute;top: 0px;right: 5px;font-size:16px;z-index: 10" onclick="showOrHide('none')">&#x1006;</i>
</h1>
<div style="width: calc(100% - 19px);height: 129px;position: absolute;top: 31px;overflow-y: scroll;padding: 10px 10px">
<ul class="info-list ukefu-quick-reply" style="width: 100%;height: auto" id="ccaQuickReplyAgentBox">
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<textarea id="message" name="message"></textarea>
@ -142,6 +151,53 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
});
// });
KindEditor.options.cssData = "body { font-size: 15px; font-family:'Microsoft Yahei', 'Helvetica', 'Simsun', 'Arial';}";
var agentEnterInput = $("iframe").contents().find("body");
agentEnterInput.keyup(function(event){
if(isCcaAisuggest && isCcaAisuggest == "true"){
debouncefun();
}
})
var debouncefun = _.debounce(agentQuickReply,500)
function agentQuickReply() {
restApiRequest({
silent: true,
path: 'chatbot',
data: {
ops: 'faq',
snsaccountid: "<#if curagentuser??>${curagentuser.appid!''}</#if>",
userId:"<#if curagentuser??>${curagentuser.userid!''}</#if>",
textMessage:editor.html()
}
}).then(function(result){
if(result.rc === 0){
if(result.data.length > 0){
$("#ccaQuickReplyAgentBox").html("");
$.each(sortByKey(result.data,'score'),function(i,n){
var li = ' <li class="ukefu-agentservice-list" style="font-size: 14px;line-height:22px" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">\n' +
' <div class="nowrap" title="'+result.data[i].post+'">问题:'+result.data[i].post+'</div>\n' +
' <div style="color: #333">\n' +
' <p title="'+result.data[i].reply_plain_text+'" class="nowrap" style="float: left ">答案:'+result.data[i].reply_plain_text+'</p>\n' +
' <button style="float: right" class="layui-btn layui-btn-mini" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">选择</button>\n' +
' </div>\n' +
' </li>'
$("#ccaQuickReplyAgentBox").append(li);
if(i>4){
return false;
}
});
showOrHide('block')
}else{
showOrHide('none')
}
}else{
showOrHide('none')
}
}, function(error){
console.log("error", error);
// 服务器异常
top.layer.msg('服务器抽风,请稍后再试!',{icon: 2, time: 3000})
})
}
});
</script>
</div>
@ -154,6 +210,12 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
<div class="layui-tab" style="margin-top:0px;">
<ul class="layui-tab-title">
<li class="layui-this">访客</li>
<#if ccaAisuggest?? && ccaAisuggest == true>
<li id="robot" onclick="$('#dot').css('display','none')">
<span>智能机器人</span>
<span id="dot" style=" width: 7px;height: 7px;background: red;-moz-border-radius: 50%;-webkit-border-radius: 50%;border-radius: 50%;position: absolute;top: 5px;display: none"></span>
</li>
</#if>
<li>历史</li>
<li>搜索历史消息</li>
<#if models?seq_contains("workorders")>
@ -264,6 +326,28 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
</#if>
</div>
<#if ccaAisuggest?? && ccaAisuggest == true>
<div class="layui-tab-item">
<div class="box">
<div class="box-title">
<h1 class="site-h1" style="background-color:#EEEEEE;">
知识库快捷
</h1>
</div>
<div class="box-body" style="padding:0px 10px;">
<ul class="info-list ukefu-quick-reply" id="ccaQuickReplyBox">
<li style="list-style: none;background-image: url();padding: 50px 0 50px;">
<div class="ukefu-empty" style="background: none">
<i class="layui-icon"></i>
<div style="">未触发知识库查询</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</#if>
<div class="layui-tab-item">
<div class="box">
<div class="box-title">
@ -422,12 +506,19 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
color: #00a65a;
font-weight: bold;
}
.nowrap{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 40px);
}
</style>
<script>
$(document).ready(function() {
var test = window.location.search;
if(isCcaAisuggest && isCcaAisuggest == "true"){
switchQuickReply();
}
})
document.getElementById('chat_msg_list_cca').scrollTop = document.getElementById('chat_msg_list_cca').scrollHeight;
layui.use('element', function(){
@ -486,9 +577,76 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
top.WebIM.sendIntervention("${user.id!''}","${curagentuser.id!''}", "${user.sessionid!''}", "text", message);
}
editor.html('');
showOrHide('none');
};
$(document).keyup(function(event){
function chooseAnswer(data){
editor.html(data)
}
function showOrHide(data){
$("#ccaAgentAnswer").css("display",data)
}
// 排序
function sortByKey(array, key) {
return array.sort(function(a, b) {
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
function switchQuickReply(){
var hatContentHtml = $("#chat_msg_list_cca .chat-block").last().find(".chatting-left .chat-content").html();
if($.trim(hatContentHtml)){
restApiRequest({
silent: true,
path: 'chatbot',
data: {
ops: 'faq',
snsaccountid: "<#if curagentuser??>${curagentuser.appid!''}</#if>",
userId:"<#if curagentuser??>${curagentuser.userid!''}</#if>",
textMessage:hatContentHtml
}
}).then(function(result){
if(result.rc === 0){
if(result.data.length>0){
$("#ccaQuickReplyBox").html("");
$.each(sortByKey(result.data,'score'),function(i,n){
var li = ' <li class="ukefu-agentservice-list" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">\n' +
' <div class="nowrap" title="'+result.data[i].post+'">问题:'+result.data[i].post+'</div>\n' +
' <div style="color: #333">\n' +
' <p class="nowrap" title="'+result.data[i].reply_plain_text+'" style="float: left ">答案:'+result.data[i].reply_plain_text+'</p>\n' +
' <button style="float: right" class="layui-btn layui-btn-mini" onclick="chooseAnswer(\''+result.data[i].reply_plain_text+'\')">选择</button>\n' +
' </div>\n' +
' </li>'
$("#ccaQuickReplyBox").append(li);
if (i>4){
return false;
}
});
if(!$("#robot").hasClass('layui-this')){
$("#dot").css("display","inline-block")
}
}else{
$("#dot").css("display","none")
$("#ccaQuickReplyBox").html(' <li style="list-style: none;background-image: url();padding: 50px 0 50px;">\n' +
' <div class="ukefu-empty" style="background: none">\n' +
' <i class="layui-icon"></i>\n' +
' <div style="">在知识库中未得到相关问题</div>\n' +
' </div>\n' +
' </li>');
}
}
}, function(error){
console.log("error", error);
// 服务器异常
top.layer.msg('服务器抽风,请稍后再试!',{icon: 2, time: 3000})
})
}
}
$("#searchconter").keyup(function(event){
if(event.keyCode ==13){
$("#search").click();
}
@ -595,7 +753,6 @@ word-break: break-all;"><#if curagentuser??>${curagentuser.username!''}<#if cura
,done: function(page, next){ //执行下一页的回调
//模拟数据插入
current += 20;
console.log(current);
setTimeout(function(){
var lis = [];
var pages = 0;

View File

@ -21,10 +21,10 @@
<div id="header" class="theme${inviteData.consult_dialog_color!''}">
<img src="<#if inviteData?? && inviteData.consult_dialog_logo??>/res/image.html?id=${inviteData.consult_dialog_logo?url}<#else>/images/logo.png</#if>" style="height:30px;padding:10px;">
</div>
<div class="ukef-leavemsg-tip">
<div class="ukef-leavemsg-tip" style="width: 100%;max-width: 550px">
<#if inviteData?? && inviteData.consult_info_message??>${(inviteData.consult_info_message!'')?no_esc}</#if>
</div>
<div class="leaveCon">
<div class="leaveCon" style="width: 100%;max-width: 550px">
<form action="" method="" name="">
<#if inviteData?? && inviteData.consult_info_name == true>
<div class="layui-form-item ukefu-form-item">

View File

@ -17,7 +17,6 @@
<script type="text/javascript" src="/js/jquery-1.10.2.min.js"></script>
<script src="/js/jquery.form.js"></script>
<script type="text/javascript" src="/im/js/kindeditor/kindeditor.js"></script>
<script type="text/javascript" src="/im/js/kindeditor/lang/zh-CN.js"></script>
<style>
@ -168,8 +167,8 @@
});
</script>
<!-- kindeditor -->
</head>
<body class="ukefu-im-theme" style="overflow:hidden;height:calc(100%);overflow-y: atuo;/* 或者scroll */-webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */" class="ukefu-point-text">
</head> n
<body class="ukefu-im-theme ukefu-point-text" style="overflow:hidden;height:100%;max-height:100%;position: fixed;/* 或者scroll */-webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */">
<div id="header" class="theme${inviteData.consult_dialog_color!''}">
<img
src="<#if inviteData?? && inviteData.consult_dialog_logo??>/res/image.html?id=${inviteData.consult_dialog_logo?url}<#else>/images/logo.png</#if>"

View File

@ -454,9 +454,9 @@ function openAgentChatDialog(url){
}
<#if webimexist == true >
Fingerprint2.get({}, function(components){
Fingerprint2.get({extraComponents: [<#if channelVisitorSeparate?? && channelVisitorSeparate == true>{key: "cskefuAppId", getData: function(done, options){done("${appid!''}")}}</#if>]}, function(components){
var glue = components.map(function (component) { return component.value })
cskefuOnlineUserId = Fingerprint2.x64hash128(glue.join(''), 31)
cskefuOnlineUserId = Fingerprint2.x64hash128(glue.join(''), 31);
cskefu.ajax(cskefu.in+"&userid="+cskefuOnlineUserId+"&t="+new Date().getTime() , function(data){
if(data == "in"){}else{
cskefu.display();

View File

@ -33,7 +33,7 @@ var ukefu = {
window.location.replace(url+"&t="+new Date().getTime());
}
}
Fingerprint2.get({}, function(components){
Fingerprint2.get({extraComponents: [<#if channelVisitorSeparate?? && channelVisitorSeparate == true>{key: "cskefuAppId", getData: function(done, options){done("${appid!''}")}}</#if>]}, function(components){
var glue = components.map(function (component) { return component.value })
cskefuOnlineUserId = Fingerprint2.x64hash128(glue.join(''), 31)
ukefu.chat = ukefu.chat + "<#if userid??>&userid=${userid}<#else>&userid="+cskefuOnlineUserId+"</#if>&sessionid=${sessionid!''}<#if ai??>&ai=${ai}</#if><#if title??>&title=${title?url}</#if><#if traceid??>&url=${url?url}</#if><#if traceid??>&traceid=${traceid}</#if>";

View File

@ -2829,10 +2829,10 @@ select{
display:none;
}
.chatting-right div.chat-content img{
max-width:460px;
max-width:100%;
}
.chatting-left div.chat-content img{
max-width:460px;
max-width:100%;
}
.layui-layout-content .layui-nav-child dd a{
font-size:13px !important;

View File

@ -1538,6 +1538,7 @@ CREATE TABLE `uk_consult_invite` (
`agentctrlenter` tinyint(4) DEFAULT '0' COMMENT '启用坐席端CTRL+Enter发送消息',
`ctrlenter` tinyint(4) DEFAULT '0' COMMENT '启用访客端CTRL+Enter发送消息',
`whitelist_mode` tinyint(4) DEFAULT '0' COMMENT '启用白名单',
`aisuggest` tinyint(4) DEFAULT '0' COMMENT '启用智能建议',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='访客网站配置表';
@ -3414,6 +3415,7 @@ CREATE TABLE `cs_chatbot` (
`sns_account_identifier` varchar(100) NOT NULL COMMENT '渠道标识',
`enabled` tinyint(1) DEFAULT '0' COMMENT '是否开启',
`workmode` varchar(32) NOT NULL COMMENT '工作模式',
`aisuggest` tinyint(1) DEFAULT '0' COMMENT '启用智能建议',
PRIMARY KEY (`ID`) USING BTREE,
UNIQUE KEY `snsid` (`sns_account_identifier`,`orgi`) USING BTREE COMMENT '按照渠道标识唯一'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='机器人客服表';

View File

@ -0,0 +1,35 @@
USE `cosinee`;
-- -----------------
-- prepare variables
-- -----------------
SET @dbname = DATABASE ( );
SET @tablename = "cs_chatbot";
SET @columnname = "aisuggest";
SET @preparedStatement = (
SELECT
IF
(
(
SELECT
COUNT( * )
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
( table_name = @tablename )
AND ( table_schema = @dbname )
AND ( column_name = @columnname )
) > 0,
"SELECT 1",
CONCAT( "ALTER TABLE ", @tablename, " ADD ", @columnname, " tinyint(1) DEFAULT '0' COMMENT '启用智能建议';" )
)
);
PREPARE alterIfNotExists
FROM
@preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;

View File

@ -0,0 +1,35 @@
USE `cosinee`;
-- -----------------
-- prepare variables
-- -----------------
SET @dbname = DATABASE ( );
SET @tablename = "uk_consult_invite";
SET @columnname = "aisuggest";
SET @preparedStatement = (
SELECT
IF
(
(
SELECT
COUNT( * )
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
( table_name = @tablename )
AND ( table_schema = @dbname )
AND ( column_name = @columnname )
) > 0,
"SELECT 1",
CONCAT( "ALTER TABLE ", @tablename, " ADD ", @columnname, " TINYINT(4) DEFAULT '0' COMMENT '启用智能建议';" )
)
);
PREPARE alterIfNotExists
FROM
@preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;

View File

@ -48,8 +48,9 @@ services:
- CSKEFU_MODULE_CONTACTS=true
- CSKEFU_MODULE_CHATBOT=true
- SKYPE_CHANNEL_CRM=${SKYPE_CHANNEL_CRM:-placeholder}
- BOT_THRESHOLD_FAQ_BEST_REPLY=${BOT_THRESHOLD_FAQ_BEST_REPLY:-0.8}
- BOT_THRESHOLD_FAQ_SUGG_REPLY=${BOT_THRESHOLD_FAQ_SUGG_REPLY:-0.6}
- BOT_THRESHOLD_FAQ_BEST_REPLY=${BOT_THRESHOLD_FAQ_BEST_REPLY:-0.9}
- BOT_THRESHOLD_FAQ_SUGG_REPLY=${BOT_THRESHOLD_FAQ_SUGG_REPLY:-0.3}
- CSKEFU_SETTINGS_WEBIM_VISITOR_SEPARATE=false
depends_on:
- mysql
- redis

View File

@ -32,6 +32,7 @@ import com.chatopera.cc.proxy.OnlineUserProxy;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.util.SystemEnvHelper;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.lang.StringUtils;
@ -124,9 +125,18 @@ public class ApiChatbotController extends Handler {
case "disable":
json = enable(j, false);
break;
case "enableaisuggest":
json = enableAiSuggest(j, true);
break;
case "disableaisuggest":
json = enableAiSuggest(j, false);
break;
case "vacant":
json = vacant(j, orgi, logined.isAdmin());
break;
case "faq":
json = faq(j, orgi);
break;
default:
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2);
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作。");
@ -222,6 +232,44 @@ public class ApiChatbotController extends Handler {
return resp;
}
/**
* Enable Chatbot 智能回复
*
* @param j
* @return
*/
private JsonObject enableAiSuggest(JsonObject j, boolean isEnabled) {
JsonObject resp = new JsonObject();
if ((!j.has("id")) || StringUtils.isBlank(j.get("id").getAsString())) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作id不能为空。");
return resp;
}
final String id = j.get("id").getAsString();
Chatbot c = chatbotRes.findOne(id);
if (c == null) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
resp.addProperty(RestUtils.RESP_KEY_ERROR, "该聊天机器人不存在。");
return resp;
}
c.setAisuggest(isEnabled);
chatbotRes.save(c);
// 更新访客网站配置
CousultInvite invite = OnlineUserProxy.consult(c.getSnsAccountIdentifier(), c.getOrgi());
invite.setAisuggest(isEnabled);
consultInviteRes.save(invite);
OnlineUserProxy.cacheConsult(invite);
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
resp.addProperty(RestUtils.RESP_KEY_DATA, "完成。");
return resp;
}
/**
* 更新聊天机器人
*
@ -417,6 +465,7 @@ public class ApiChatbotController extends Handler {
invite.setAisuccesstip(null);
invite.setAifirst(false);
invite.setAiid(null);
invite.setAisuggest(false);
consultInviteRes.save(invite);
OnlineUserProxy.cacheConsult(invite);
}
@ -558,4 +607,57 @@ public class ApiChatbotController extends Handler {
return resp;
}
}
private JsonObject faq(final JsonObject j, String orgi) {
JsonObject resp = new JsonObject();
if ((!j.has("snsaccountid")) || StringUtils.isBlank(j.get("snsaccountid").getAsString())) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作snsaccountid不能为空。");
return resp;
}
final String snsaccountid = j.get("snsaccountid").getAsString();
Chatbot c = chatbotRes.findBySnsAccountIdentifierAndOrgi(snsaccountid, orgi);
if (c == null) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
resp.addProperty(RestUtils.RESP_KEY_ERROR, "该聊天机器人不存在。");
return resp;
}
String userId = j.get("userId").getAsString();
String textMessage = j.get("textMessage").getAsString();
try {
com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot(
c.getClientId(), c.getSecret(), botServiecProvider);
JSONObject result = bot.faq(
userId,
textMessage,
Double.parseDouble(SystemEnvHelper.getenv(ChatbotConstants.THRESHOLD_FAQ_BEST_REPLY, "0.8")),
Double.parseDouble(SystemEnvHelper.getenv(ChatbotConstants.THRESHOLD_FAQ_SUGG_REPLY, "0.6"))
);
if (result.getInt("rc") == 0) {
JsonParser jsonParser = new JsonParser();
JsonElement data = jsonParser.parse(result.getJSONArray("data").toString());
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
resp.add(RestUtils.RESP_KEY_DATA, data);
} else {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
resp.addProperty(RestUtils.RESP_KEY_DATA, "查询不成功,智能问答引擎服务异常。");
}
} catch (
MalformedURLException e) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_6);
resp.addProperty(RestUtils.RESP_KEY_DATA, "查询不成功,智能问答引擎地址不合法。");
} catch (
ChatbotException e) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
resp.addProperty(RestUtils.RESP_KEY_DATA, "查询不成功,智能问答引擎服务异常。");
}
return resp;
}
}

View File

@ -51,8 +51,8 @@ public class PluginDescriptor implements IPluginDescriptor {
public Map<String, String> getEnvironmentVariables() {
Map<String, String> env = new HashMap<>();
env.put(ChatbotConstants.BOT_PROVIDER, "https://bot.chatopera.com");
env.put(ChatbotConstants.THRESHOLD_FAQ_BEST_REPLY, "0.8");
env.put(ChatbotConstants.THRESHOLD_FAQ_SUGG_REPLY, "0.6");
env.put(ChatbotConstants.THRESHOLD_FAQ_BEST_REPLY, "0.9");
env.put(ChatbotConstants.THRESHOLD_FAQ_SUGG_REPLY, "0.3");
return env;
}
}

View File

@ -54,17 +54,29 @@
<div class="row" style="padding:5px;">
<div class="col-lg-12">
<fieldset class="layui-elem-field layui-field-title">
<legend>工作状态</legend>
<legend>智能客服</legend>
<div class="layui-field-box">
<blockquote class="layui-elem-quote layui-quote-nm">
<p>在开启状态下,在访客端可以看到【智能坐席】对话窗口并与机器人客服对话。</p>
<p>在开启状态下,在访客端可以看到<b>智能客服</b>对话窗口并与机器人客服对话。</p>
</blockquote>
<form class="layui-form" action="">
<div class="layui-form-item">
<div class="layui-input-block">
<input type="checkbox" lay-filter="bot-workstatus" name="switch" lay-skin="switch" lay-text="启用|禁用" <#if currentbot.enabled>checked</#if>>
</div>
<!-- <div class="layui-form-mid layui-word-aux">在开启状态下,在访客端可以看到【智能坐席】对话窗口并与机器人客服对话。</div>-->
</div>
</form>
</div>
<legend>知识库建议</legend>
<div class="layui-field-box">
<blockquote class="layui-elem-quote layui-quote-nm">
<p>知识库建议包括<b>知识库联想</b><b>知识库快捷</b><b>知识库联想</b>:当坐席与访客进行对话过程中,坐席输入消息时是否得到机器人的建议回复;<b>知识库快捷</b>:当坐席与访客进行对话过程中,坐席收到访客的消息时是否得到机器人的建议回复。</p>
</blockquote>
<form class="layui-form" action="">
<div class="layui-form-item">
<div class="layui-input-block">
<input type="checkbox" lay-filter="bot-aisuggest" name="bot-aisuggest" lay-skin="switch" lay-text="启用|禁用" <#if currentbot.aisuggest>checked</#if>>
</div>
</div>
</form>
</div>
@ -269,6 +281,7 @@
function setChatbotWorkstatus(id, workstatus){
restApiRequest({
path: "chatbot",
silent: true,
data: {
ops: workstatus?"enable":"disable",
id: id
@ -276,6 +289,17 @@
});
}
function setChatbotAiSuggest(id, aisuggest){
restApiRequest({
path: "chatbot",
silent: true,
data: {
ops: aisuggest?"enableAiSuggest":"disableAiSuggest",
id: id
}
});
}
layui.use(['form'], function(){
var form = layui.form();
form.render();
@ -283,5 +307,9 @@
form.on('switch(bot-workstatus)', function (data) {
setChatbotWorkstatus('${currentbotid}', data.elem.checked);
});
form.on('switch(bot-aisuggest)', function (data) {
setChatbotAiSuggest('${currentbotid}', data.elem.checked);
});
});
</script>