From f0220ef91c6e5ff2eaf648271eed5f657c11716a Mon Sep 17 00:00:00 2001 From: Hai Liang Wang Date: Wed, 17 Jan 2024 16:13:14 +0800 Subject: [PATCH] #998 enable chatbot writing status Signed-off-by: Hai Liang Wang --- .../plugins/chatbot/ChatbotEventHandler.java | 36 +++++++---- .../cc/plugins/chatbot/ChatbotProxy.java | 11 ++++ .../main/resources/static/im/css/ukefu.css | 51 +++++++++++++++ .../templates/apps/im/chatbot/index.pug | 62 ++++++++++++++----- .../templates/apps/im/chatbot/mobile.pug | 56 +++++++++++++---- .../apps/im/templates/chatbot_tpls.pug | 13 ++++ .../apps/im/templates/chatbot_writing.tpl | 22 +++++++ 7 files changed, 210 insertions(+), 41 deletions(-) create mode 100644 contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_tpls.pug create mode 100644 contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_writing.tpl diff --git a/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotEventHandler.java b/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotEventHandler.java index 1ef1de9d..a70218ef 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotEventHandler.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotEventHandler.java @@ -1,14 +1,14 @@ -/* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public +/* + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , 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, , - * Licensed under the Apache License, Version 2.0, + * Copyright (C) 2019-Jun. 2023 Chatopera Inc, , + * 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); }); diff --git a/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotProxy.java b/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotProxy.java index a3ae6a69..c9934c01 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotProxy.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/plugins/chatbot/ChatbotProxy.java @@ -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 * diff --git a/contact-center/app/src/main/resources/static/im/css/ukefu.css b/contact-center/app/src/main/resources/static/im/css/ukefu.css index 13b37fff..bcc33433 100644 --- a/contact-center/app/src/main/resources/static/im/css/ukefu.css +++ b/contact-center/app/src/main/resources/static/im/css/ukefu.css @@ -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; +} \ No newline at end of file diff --git a/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.pug b/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.pug index 7c9e026b..d0d64511 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.pug +++ b/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.pug @@ -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 = $("
"); 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 = ""; } else if (data.msgtype == "file") { chat = ""; } + if (data.calltype == "呼入") { - output('
' + chat + '
', "chat-block", true,data.msgtype - ) - ; + // Receive User's own sent message back from socket.io + output('
' + chat + '
', "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(); - }; - + }; \ No newline at end of file diff --git a/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.pug b/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.pug index e28db68f..3c482410 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.pug +++ b/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.pug @@ -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 = $("
"); 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 = ""; } 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('
' + chat + '
', "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('连接坐席失败,在线咨询服务不可用', '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(){ // } - - } - + } \ No newline at end of file diff --git a/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_tpls.pug b/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_tpls.pug new file mode 100644 index 00000000..ffb6e82b --- /dev/null +++ b/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_tpls.pug @@ -0,0 +1,13 @@ +//- Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. +//- , 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, +//- 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 \ No newline at end of file diff --git a/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_writing.tpl b/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_writing.tpl new file mode 100644 index 00000000..84bcf807 --- /dev/null +++ b/contact-center/app/src/main/resources/templates/apps/im/templates/chatbot_writing.tpl @@ -0,0 +1,22 @@ +
id="writing"<%}%>> +
+ +
+ <%=data.username%> + <%=data.createtime%> +
+
+ + <%if(data.type == 'writing'){%> +
+ + + + + + +
+ <%}%> +
+
+
\ No newline at end of file