mirror of
https://github.com/chatopera/cosin.git
synced 2025-06-16 18:30:03 +08:00
#998 enable chatbot writing status
Signed-off-by: Hai Liang Wang <hai@chatopera.com>
This commit is contained in:
parent
0797a90fdd
commit
f0220ef91c
@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) 2019-Jun. 2023 Chatopera Inc, <https://www.chatopera.com>,
|
||||
* Licensed under the Apache License, Version 2.0,
|
||||
* Copyright (C) 2019-Jun. 2023 Chatopera Inc, <https://www.chatopera.com>,
|
||||
* Licensed under the Apache License, Version 2.0,
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package com.cskefu.cc.plugins.chatbot;
|
||||
@ -130,21 +130,31 @@ public class ChatbotEventHandler {
|
||||
logger.info("faqhot {}", faqhotresp.toString());
|
||||
if (faqhotresp.getInt("rc") == 0) {
|
||||
JSONObject faqhotdata = faqhotresp.getJSONObject("data");
|
||||
if ((!faqhotdata.getBoolean("logic_is_fallback")) &&
|
||||
faqhotdata.has("string") &&
|
||||
faqhotdata.has("params")) {
|
||||
if ((!faqhotdata.getBoolean("logic_is_fallback"))) {
|
||||
// 返回有效值,不是兜底回复
|
||||
ChatMessage faqhotmsg = new ChatMessage();
|
||||
faqhotmsg.setCalltype(MainContext.CallType.OUT.toString());
|
||||
faqhotmsg.setAppid(appid);
|
||||
faqhotmsg.setAiid(aiid);
|
||||
faqhotmsg.setMessage(faqhotdata.getString("string"));
|
||||
faqhotmsg.setExpmsg(faqhotdata.getJSONArray("params").toString());
|
||||
faqhotmsg.setTouser(user);
|
||||
faqhotmsg.setMsgtype(MainContext.MessageType.MESSAGE.toString());
|
||||
faqhotmsg.setUserid(user);
|
||||
faqhotmsg.setUsername(invite.getAiname());
|
||||
faqhotmsg.setUpdatetime(System.currentTimeMillis());
|
||||
client.sendEvent(MainContext.MessageType.MESSAGE.toString(), faqhotmsg);
|
||||
|
||||
if (faqhotdata.has("string") &&
|
||||
faqhotdata.has("params") &&
|
||||
faqhotdata.has("service") &&
|
||||
StringUtils.equals(faqhotdata.getJSONObject("service").getString("provider"), "conversation")) {
|
||||
// 多轮对话返回的热门问题
|
||||
faqhotmsg.setMessage(faqhotdata.getString("string"));
|
||||
faqhotmsg.setExpmsg(faqhotdata.getJSONArray("params").toString());
|
||||
faqhotmsg.setUpdatetime(System.currentTimeMillis());
|
||||
client.sendEvent(MainContext.MessageType.MESSAGE.toString(), faqhotmsg);
|
||||
} else if (faqhotdata.has("string") && StringUtils.isNotBlank(faqhotdata.getString("string"))) {
|
||||
faqhotmsg.setMessage(faqhotdata.getString("string"));
|
||||
faqhotmsg.setUpdatetime(System.currentTimeMillis());
|
||||
client.sendEvent(MainContext.MessageType.MESSAGE.toString(), faqhotmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (result.getRc() == 999 || result.getRc() == 998) {
|
||||
@ -322,7 +332,7 @@ public class ChatbotEventHandler {
|
||||
getAgentUserRes().save(p);
|
||||
|
||||
// 发送消息给Bot
|
||||
getChatbotProxy().publishMessage(data, Constants.CHATBOT_EVENT_TYPE_CHAT);
|
||||
getChatbotProxy().publishMessageDelayed(data, Constants.CHATBOT_EVENT_TYPE_CHAT, 2);
|
||||
});
|
||||
|
||||
|
||||
|
@ -61,6 +61,17 @@ public class ChatbotProxy {
|
||||
brokerPublisher.send(Constants.INSTANT_MESSAGING_MQ_QUEUE_CHATBOT, SerializeUtil.serialize(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish message in delayed manner.
|
||||
* @param data
|
||||
* @param eventType
|
||||
* @param delayedSeconds
|
||||
*/
|
||||
public void publishMessageDelayed(final ChatMessage data, final String eventType, int delayedSeconds) {
|
||||
logger.info("[publishMessageDelayed] eventType {}", eventType);
|
||||
brokerPublisher.send(Constants.INSTANT_MESSAGING_MQ_QUEUE_CHATBOT, SerializeUtil.serialize(data), false, delayedSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用chatbotID得到snsid
|
||||
*
|
||||
|
@ -1153,3 +1153,54 @@ p.submitBtnWrap{
|
||||
color: rgba(35, 39, 50, 0.8);
|
||||
background: url(/images/circle.png) no-repeat left 8px;
|
||||
}
|
||||
|
||||
.loading{
|
||||
margin: -3px auto;
|
||||
}
|
||||
.loading span{
|
||||
display: inline-block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
margin-right: 5px;
|
||||
border-radius: 50%;
|
||||
background-color: #19a55d !important;
|
||||
-webkit-animation: load 1.04s ease infinite;
|
||||
}
|
||||
.loading span:last-child{
|
||||
margin-right: 0px;
|
||||
}
|
||||
@-webkit-keyframes load{
|
||||
0%{
|
||||
opacity: 1;
|
||||
}
|
||||
100%{
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.loading span:nth-child(1){
|
||||
-webkit-animation-delay:0.13s;
|
||||
}
|
||||
.loading span:nth-child(2){
|
||||
-webkit-animation-delay:0.26s;
|
||||
}
|
||||
.loading span:nth-child(3){
|
||||
-webkit-animation-delay:0.39s;
|
||||
}
|
||||
.loading span:nth-child(4){
|
||||
-webkit-animation-delay:0.52s;
|
||||
}
|
||||
.chat-writing-message{
|
||||
font-size: 13px;
|
||||
margin-top:8px;
|
||||
margin-left:5px;
|
||||
border-radius: 3px;
|
||||
padding: 2px 4px 6px;
|
||||
margin-bottom: 5px;
|
||||
line-height: 25px;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
background-color: #EFEFEF !important;
|
||||
border: 1px solid #EFEFEF;
|
||||
float: left;
|
||||
min-width: 25px;
|
||||
}
|
@ -30,6 +30,7 @@ html
|
||||
script(src='/js/jquery-1.10.2.min.js')
|
||||
script(type='text/javascript', src='/im/js/kindeditor/kindeditor.js')
|
||||
script(type='text/javascript', src='/im/js/kindeditor/lang/zh-CN.js')
|
||||
script(type='text/javascript', src='/js/template.js')
|
||||
script(src='/im/js/socket.io.js')
|
||||
script(src='/im/js/dayjs.min.js')
|
||||
script(type='text/javascript').
|
||||
@ -265,6 +266,17 @@ html
|
||||
return false;
|
||||
}
|
||||
|
||||
function outputElementAndScroll(element, scroll, msgType){
|
||||
$('#above').append(element);
|
||||
if (scroll == null || scroll == true) {
|
||||
if (msgType && msgType == "image") {
|
||||
chatScorllBottom("above")
|
||||
} else {
|
||||
document.getElementById("above").scrollTop = document.getElementById("above").scrollHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function output(message, clazz, scroll, msgType) {
|
||||
if (clazz == "message connect-message") {
|
||||
var messages = document.getElementsByClassName("connect-message");
|
||||
@ -275,14 +287,7 @@ html
|
||||
}
|
||||
var element = $("<div class='clearfix " + clazz + "'></div>");
|
||||
element.append(message);
|
||||
$('#above').append(element);
|
||||
if (scroll == null || scroll == true) {
|
||||
if (msgType && msgType == "image") {
|
||||
chatScorllBottom("above")
|
||||
} else {
|
||||
document.getElementById("above").scrollTop = document.getElementById("above").scrollHeight
|
||||
}
|
||||
}
|
||||
outputElementAndScroll(element, scroll, msgType);
|
||||
}
|
||||
|
||||
function update(id, message) {
|
||||
@ -438,6 +443,7 @@ html
|
||||
}
|
||||
|
||||
body.ukefu-point-text(style='overflow:hidden; background:#E8E8E8')
|
||||
include ../templates/chatbot_tpls
|
||||
.large.ukefu-im-theme(style='background: white;', class=(type == 'text' ? 'ukefu-theme-border-' + inviteData.consult_dialog_color : ''))
|
||||
#containter.clearfix
|
||||
#header(class='theme' + inviteData.consult_dialog_color)
|
||||
@ -676,20 +682,43 @@ html
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('message', function (data) {
|
||||
socket.on("message", function (data) {
|
||||
// append message
|
||||
var chat = document.getElementsByClassName('chatting-left').innerText;
|
||||
data.createtime = dayjs(data.createtime).format('YYYY-MM-DD HH:mm:ss');
|
||||
chat = data.message;
|
||||
|
||||
if (data.msgtype == "image") {
|
||||
chat = "<a href='" + data.message + "&original=true' target='_blank'><img src='" + data.message + "' class='ukefu-media-image'/></a>";
|
||||
} else if (data.msgtype == "file") {
|
||||
chat = "<div class='ukefu-message-file'><div class='ukefu-file-icon'><img src='/im/img/file.png'></div><div class='ukefu-file-desc'><a href='" + data.message + "' target='_blank'><div>" + data.filename + "</div><div>" + (data.filesize / 1024).toFixed(3) + "Kb</div></a></div></div>";
|
||||
}
|
||||
|
||||
if (data.calltype == "呼入") {
|
||||
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">' + data.createtime + '</label><label class="user">' + data.username + '</label> </div><div class="chatting-right"><i class="arrow arrow#{inviteData.consult_dialog_colo}"></i><div class="chat-content theme#{inviteData.consult_dialog_color}">' + chat + '</div></div>', "chat-block", true,data.msgtype
|
||||
)
|
||||
;
|
||||
// Receive User's own sent message back from socket.io
|
||||
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">' + data.createtime + '</label><label class="user">' + data.username + '</label> </div><div class="chatting-right"><i class="arrow arrow#{inviteData.consult_dialog_colo}"></i><div class="chat-content theme#{inviteData.consult_dialog_color}">' + chat + '</div></div>', "chat-block", true, data.msgtype);
|
||||
setTimeout(() => {
|
||||
// botwriting: make sure bot writing on
|
||||
if($('#writing').length > 0){
|
||||
// console.log("bot writing is already on.");
|
||||
} else {
|
||||
// botwriting: now, set bot writing on
|
||||
// console.log("bot writing is off, now set it on.");
|
||||
var tplParams = {};
|
||||
tplParams.calltype = "呼出";
|
||||
tplParams.type = "writing";
|
||||
tplParams.createtime = data.createtime;
|
||||
tplParams.username = "#{inviteData.ainame ? inviteData.ainame : '小松'}";
|
||||
var msgWriting = template($('#chatbot_writing').html(), {data: tplParams});
|
||||
outputElementAndScroll($(msgWriting), true, data.msgtype);
|
||||
}
|
||||
}, 500); // on the backend, would wait 2 seconds to ensure the time window
|
||||
} else if (data.calltype == "呼出") {
|
||||
// botwriting: end bot writing message
|
||||
if ($('#writing').length > 0) {
|
||||
$('#writing').remove();
|
||||
}
|
||||
|
||||
if (data.expmsg) {
|
||||
showExtmsg(data.username, data.createtime, data.message, data.expmsg);
|
||||
} else {
|
||||
@ -710,11 +739,10 @@ html
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
function sendDisconnect() {
|
||||
socket.disconnect();
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
editor.sync();
|
||||
var count = editor.count("text");
|
||||
@ -752,8 +780,8 @@ html
|
||||
// POI:function(){
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// 回车事件
|
||||
document.onkeyup = function (e) {
|
||||
if (!e) e = window.event;
|
||||
@ -761,7 +789,7 @@ html
|
||||
document.getElementById('sent').click();
|
||||
}
|
||||
}
|
||||
|
||||
window.onresize = function () {
|
||||
R3Helper.resize();
|
||||
};
|
||||
|
||||
};
|
@ -30,6 +30,7 @@ html
|
||||
script(src='/js/jquery.form.js')
|
||||
script(type='text/javascript', src='/im/js/kindeditor/kindeditor.js')
|
||||
script(type='text/javascript', src='/im/js/kindeditor/lang/zh-CN.js')
|
||||
script(type='text/javascript', src='/js/template.js')
|
||||
style.
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
@ -158,6 +159,16 @@ html
|
||||
}
|
||||
}
|
||||
|
||||
function outputElementAndScroll(element, msgType){
|
||||
$('#above').append(element);
|
||||
if (msgType && msgType == "image") {
|
||||
chatScorllBottom("above")
|
||||
} else {
|
||||
document.getElementById("above").scrollTop = document.getElementById("above").scrollHeight
|
||||
}
|
||||
//$("#welcome-message").html(document.getElementById('above').scrollHeight);
|
||||
}
|
||||
|
||||
function output(message, clazz, msgType) {
|
||||
if (clazz == "message connect-message") {
|
||||
var messages = document.getElementsByClassName("connect-message");
|
||||
@ -168,13 +179,7 @@ html
|
||||
}
|
||||
var element = $("<div class='clearfix " + clazz + "'></div>");
|
||||
element.append(message);
|
||||
$('#above').append(element);
|
||||
if (msgType && msgType == "image") {
|
||||
chatScorllBottom("above")
|
||||
} else {
|
||||
document.getElementById("above").scrollTop = document.getElementById("above").scrollHeight
|
||||
}
|
||||
//$("#welcome-message").html(document.getElementById('above').scrollHeight);
|
||||
outputElementAndScroll(element, msgType);
|
||||
}
|
||||
|
||||
function update(id, message) {
|
||||
@ -352,6 +357,7 @@ html
|
||||
|
||||
// kindeditor
|
||||
body.ukefu-im-theme.ukefu-point-text(style='width:100%;overflow:hidden;height:100%;max-height:100%;position: fixed;/* 或者scroll */-webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */')
|
||||
include ../templates/chatbot_tpls
|
||||
#header(class="theme" + inviteData.consult_dialog_color)
|
||||
- var dialog_logo=inviteData.consult_dialog_logo?(inviteData.consult_dialog_logo.startsWith("http://") || inviteData.consult_dialog_logo.startsWith("https://")?inviteData.consult_dialog_logo:'/res/image.html?id='+inviteData.consult_dialog_logo):'/images/logo.png'
|
||||
img(src=dialog_logo, style='height:50px;padding:10px;')
|
||||
@ -482,10 +488,12 @@ html
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('message', function (data) {
|
||||
socket.on("message", function (data) {
|
||||
// append message
|
||||
var chat = document.getElementsByClassName('chatting-left').innerText;
|
||||
data.createtime = dayjs(data.createtime).format('YYYY-MM-DD HH:mm:ss');
|
||||
chat = data.message;
|
||||
|
||||
if (data.msgtype == "image") {
|
||||
chat = "<a href='" + data.message + "&original=true' target='_blank'><img src='" + data.message + "' class='ukefu-media-image'/></a>";
|
||||
} else if (data.msgtype == "cooperation") {
|
||||
@ -494,9 +502,32 @@ html
|
||||
//检查访客是否在协作页面上,如果在协作页面上,就开始执行重绘,否则不做处理
|
||||
drawCanvasImage(data.attachmentid);
|
||||
}
|
||||
|
||||
if (data.calltype == "呼入") {
|
||||
// Receive User's own sent message back from socket.io
|
||||
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">' + data.createtime + '</label><label class="user">' + data.username + '</label> </div><div class="chatting-right"><i class="arrow arrow#{inviteData.consult_dialog_color}"></i><div class="chat-content theme#{inviteData.consult_dialog_color}">' + chat + '</div></div>', "chat-block", data.msgtype);
|
||||
setTimeout(() => {
|
||||
// botwriting: make sure bot writing on
|
||||
if($('#writing').length > 0){
|
||||
// console.log("bot writing is already on.");
|
||||
} else {
|
||||
// botwriting: now, set bot writing on
|
||||
// console.log("bot writing is off, now set it on.");
|
||||
var tplParams = {};
|
||||
tplParams.calltype = "呼出";
|
||||
tplParams.type = "writing";
|
||||
tplParams.createtime = data.createtime;
|
||||
tplParams.username = "#{inviteData.ainame ? inviteData.ainame : '小松'}";
|
||||
var msgWriting = template($('#chatbot_writing').html(), {data: tplParams});
|
||||
outputElementAndScroll($(msgWriting), true, data.msgtype);
|
||||
}
|
||||
}, 500); // on the backend, would wait 2 seconds to ensure the time window
|
||||
} else if (data.calltype == "呼出") {
|
||||
// botwriting: end bot writing message
|
||||
if ($('#writing').length > 0) {
|
||||
$('#writing').remove();
|
||||
}
|
||||
|
||||
if (data.expmsg) {
|
||||
showExtmsg(data.username, data.createtime, data.message, data.expmsg);
|
||||
} else {
|
||||
@ -508,9 +539,11 @@ html
|
||||
socket.on('disconnect', function () {
|
||||
output('<span id="connect-message">连接坐席失败,在线咨询服务不可用</span>', 'message connect-message');
|
||||
});
|
||||
|
||||
function sendDisconnect() {
|
||||
socket.disconnect();
|
||||
}
|
||||
|
||||
function acceptInvite(msgid, fileid) {
|
||||
document.getElementById("cooperation").style.display = "block";
|
||||
document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=" + fileid + "&cooperation=true&original=true";
|
||||
@ -547,9 +580,11 @@ html
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function offCoop() {
|
||||
document.getElementById("cooperation").style.display = "none";
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
var count = document.getElementById('message').value.length;
|
||||
if (count > 0 && service_end == false) {
|
||||
@ -562,6 +597,7 @@ html
|
||||
}
|
||||
closeFaceDialog(0);
|
||||
}
|
||||
|
||||
function sendMessageText(message) {
|
||||
if (message != "") {
|
||||
socket.emit('message', {
|
||||
@ -599,6 +635,4 @@ html
|
||||
// POI:function(){
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
//- Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
//- <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
//- License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
//- Unless required by applicable law or agreed to in writing, software
|
||||
//- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//- See the License for the specific language governing permissions and
|
||||
//- limitations under the License.
|
||||
//- Copyright (C) 2018-Jun. 2023 Chatopera Inc, <https://www.chatopera.com>
|
||||
//- Licensed under the Apache License, Version 2.0
|
||||
//- http://www.apache.org/licenses/LICENSE-2.0
|
||||
script#chatbot_writing(type="text/html")
|
||||
include chatbot_writing.tpl
|
@ -0,0 +1,22 @@
|
||||
<div class="clearfix chat-block" <%if(data.type == 'writing'){%>id="writing"<%}%>>
|
||||
<div class="<% if(data.calltype == '呼出'){%>chat-left<%}else{%>chat-right<%}%>">
|
||||
<img alt="" src="<% if(data.calltype == '呼出'){%>/images/agent.png<%}else{%><% if(data.headimgurl && data.headimgurl !=''){%><%=data.headimgurl%><%}else{%>/im/img/user.png<%} %><%} %>" class="user-img" style="width:45px;height:45px;">
|
||||
<div class="chat-message">
|
||||
<span class="user"><%=data.username%></span>
|
||||
<span class="time"><%=data.createtime%></span>
|
||||
</div>
|
||||
<div class="<% if(data.calltype == '呼出'){%>chatting-left<%}else{%>chatting-right<%}%>">
|
||||
<i class="arrow"></i>
|
||||
<%if(data.type == 'writing'){%>
|
||||
<div class="chat-writing-message" title="正在输入...">
|
||||
<span class="loading">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user