1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-06-16 18:30:03 +08:00

https://github.com/chatopera/cskefu/issues/471 enable rendering card message for agent and vistor chatbox

This commit is contained in:
Hai Liang Wang 2021-09-16 20:13:43 +08:00
parent 73d8c52116
commit fb56341625
5 changed files with 464 additions and 359 deletions

View File

@ -1,16 +1,10 @@
package com.chatopera.cc.util; package com.chatopera.cc.util;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.google.common.collect.BoundType; import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Range;
import org.apache.commons.lang.StringUtils;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Date;
import java.util.Collections;
import java.util.List;
public class PugHelper { public class PugHelper {
public String formatDate(String pattern, Date value) { public String formatDate(String pattern, Date value) {
@ -38,6 +32,15 @@ public class PugHelper {
return new String(charr); return new String(charr);
} }
/**
* String 转化为 JSONArray
* @param str
* @return
*/
public JSONArray parseStringToJsonArray(final String str) {
return JSON.parseArray(str);
}
public String toJSON(Object input) { public String toJSON(Object input) {
return JSON.toJSON(input).toString(); return JSON.toJSON(input).toString();
} }

View File

@ -1,4 +1,12 @@
if chatmessage.msgtype && chatmessage.msgtype == "image" if chatmessage.expmsg && chatmessage.expmsg.contains("hyperlink\":\"http")
- var expmsg = pugHelper.parseStringToJsonArray(chatmessage.expmsg)[0];
| 图文消息:#{expmsg.title}
br
= expmsg.summary
br
a(href="#{expmsg.hyperlink}", target="_blank")
img.ukefu-media-image(src="!{chatmessage.message ? chatmessage.message : ''}", id="#{chatmessage.id}")
else if chatmessage.msgtype && chatmessage.msgtype == "image"
a(href="/agent/message/image.html?id=" + chatmessage.id, data-toggle="ajax", data-width="950", data-height="600", title="图片") a(href="/agent/message/image.html?id=" + chatmessage.id, data-toggle="ajax", data-width="950", data-height="600", title="图片")
img.ukefu-media-image(src="!{chatmessage.message ? chatmessage.message : ''}", id="#{chatmessage.id}") img.ukefu-media-image(src="!{chatmessage.message ? chatmessage.message : ''}", id="#{chatmessage.id}")
else if chatmessage.msgtype && chatmessage.msgtype == "cooperation" else if chatmessage.msgtype && chatmessage.msgtype == "cooperation"

View File

@ -1,4 +1,6 @@
doctype html doctype html
// constants
- var dialog_headimg = inviteData.consult_dialog_headimg ? '/res/image.html?id=' + inviteData.consult_dialog_headimg : '/images/agent.png'
html html
head head
meta(charset='utf-8') meta(charset='utf-8')
@ -259,6 +261,138 @@ html
return false; return false;
} }
function output(message, clazz, scroll, msgType) {
if (clazz == "message connect-message") {
var messages = document.getElementsByClassName("connect-message");
for (inx = 0; inx < messages.length;) {
document.getElementById('above').removeChild(messages[inx]);
inx++;
}
}
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
}
}
}
function update(id, message) {
document.getElementById(id).innerHTML = message;
}
function createButton(message, data) {
var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>')
var list = element.find('.button-box');
for (let i = 0; i < data.length; i++) {
var item = data[i];
var allowClick = true;
var btn = $('<div class="msg-btn" style="background-color: #e6f2ff !important;">' + item.label + '</div>');
var regClick = function (key) {
btn.click(function () {
if (allowClick) {
allowClick = false;
socket.emit('message', {
appid: "#{appid}",
userid: "#{userid}",
type: "message",
session: "#{sessionid}",
orgi: "#{orgi}",
message: key
});
}
});
}
regClick(item.text);
list.append(btn);
}
return element;
}
function createQList(message, data) {
var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>')
var list = element.find('.button-box');
for (let i = 0; i < data.length; i++) {
var item = data[i];
var btn = $('<div class="msg-list">' + item.label + '</div>');
var regClick = function (key) {
btn.click(function () {
socket.emit('message', {
appid: "#{appid}",
userid: "#{userid}",
type: "message",
session: "#{sessionid}",
orgi: "#{orgi}",
message: key
});
});
}
regClick(item.text);
list.append(btn);
}
return element;
}
function createCard(message, data) {
let item = data[0];
let html = '<div class="card-box" style="background-color: #fff !important;"><div class="msg-card" style="background-color: #fff !important;"><img src="' + item.thumbnail + '" style="width: 80px;height: 80px;"></div><div class="msg-card msg-crad-right" style="background-color: #fff !important;"><h3 style="background-color: #fff !important;">' + item.title + '</h3><p style="background-color: #fff !important;">' + item.summary + '</p></div></div>'
var element = $(html);
element.click(function () {
window.open(item.hyperlink);
})
return element;
}
function showExtmsg(username, createtime, message, json) {
var expmsg = JSON.parse(json.replace(/&quot;/g,'"'));
var type = expmsg[0].type;
var content;
if (type == 'button') {
content = createButton(message, expmsg);
} else if (type == 'qlist') {
content = createQList(message, expmsg);
} else if (type == 'card') {
content = createCard(message, expmsg);
}
var box = $('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + username + '</label><label class="time">' + createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content"></div></div>');
box.find('.chat-content').append(content);
output(box, 'chat-block')
}
function showExtmsgBody(username, createtime, message, json) {
var expmsg = JSON.parse(json.replace(/&quot;/g,'"'));
var type = expmsg[0].type;
var content;
if (type == 'button') {
content = createButton(message, expmsg);
} else if (type == 'qlist') {
content = createQList(message, expmsg);
} else if (type == 'card') {
content = createCard(message, expmsg);
}
var box = $('')
var box = $('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + username + '</label><label class="time">' + createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content"></div></div>');
box.find('.chat-content').append(content);
output(box, 'chat-block')
}
window.onbeforeunload = function () { window.onbeforeunload = function () {
} }
@ -301,7 +435,6 @@ html
} }
body.ukefu-point-text(style='overflow:hidden; background:#E8E8E8') body.ukefu-point-text(style='overflow:hidden; background:#E8E8E8')
- var dialog_headimg= inviteData.consult_dialog_headimg ? '/res/image.html?id=' + inviteData.consult_dialog_headimg : '/images/agent.png'
.large.ukefu-im-theme(style='background: white;', class=(type == 'text' ? 'ukefu-theme-border-' + inviteData.consult_dialog_color : '')) .large.ukefu-im-theme(style='background: white;', class=(type == 'text' ? 'ukefu-theme-border-' + inviteData.consult_dialog_color : ''))
#containter.clearfix #containter.clearfix
#header(class='theme' + inviteData.consult_dialog_color) #header(class='theme' + inviteData.consult_dialog_color)
@ -347,20 +480,36 @@ html
include ../media/message include ../media/message
else else
.clearfix.chat-block .clearfix.chat-block
.chat-left // for debugging purpose
img.user-img(src=dialog_headimg , alt="") //script.
.chat-message // console.log("chatMessage.message", '#{chatMessage.message.replaceAll("\\r|\\n", "")}'.replace(/\r?\n|\r/g, ''))
label.user // console.log("chatMessage.username", "#{chatMessage.username}")
if chatMessage.chatype == 'aireply' // var expmsg = "#{chatMessage.expmsg}";
| #{inviteData.ainame ? inviteData.ainame : '小松'} // if(expmsg) console.log("chatMessage.expmsg", JSON.parse(expmsg.replace(/&quot;/g,'"')))
else // // && (chatMessage.message == "{CLEAR} 混合类型消息" || chatMessage.message == "{CLEAR} 图文消息")
| #{chatMessage.username} - var createtime = pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
if chatMessage.expmsg
script.
try {
showExtmsgBody("#{chatMessage.username}", "#{createtime}", "#{chatMessage.message}", "#{chatMessage.expmsg}");
} catch (e) {
console.log("unexpected result", e)
}
else
.chat-left
img.user-img(src=dialog_headimg , alt="")
.chat-message
label.user
if chatMessage.chatype == 'aireply'
| #{inviteData.ainame ? inviteData.ainame : '小松'}
else
| #{chatMessage.username}
label.time= createtime
.chatting-left
i.arrow
.chat-content
include ../media/message
label.time= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
.chatting-left
i.arrow
.chat-content
include ../media/message
.chat-bottom#bottom .chat-bottom#bottom
textarea#message(name='content', style='visibility:hidden;') textarea#message(name='content', style='visibility:hidden;')
.btn-push.clearfix .btn-push.clearfix
@ -556,92 +705,7 @@ html
} }
}); });
function createButton(message, data) {
var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>')
var list = element.find('.button-box');
for (let i = 0; i < data.length; i++) {
var item = data[i];
var allowClick = true;
var btn = $('<div class="msg-btn" style="background-color: #e6f2ff !important;">' + item.label + '</div>');
var regClick = function (key) {
btn.click(function () {
if (allowClick) {
allowClick = false;
socket.emit('message', {
appid: "#{appid}",
userid: "#{userid}",
type: "message",
session: "#{sessionid}",
orgi: "#{orgi}",
message: key
});
}
});
}
regClick(item.text);
list.append(btn);
}
return element;
}
function createQList(message, data) {
var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>')
var list = element.find('.button-box');
for (let i = 0; i < data.length; i++) {
var item = data[i];
var btn = $('<div class="msg-list">' + item.label + '</div>');
var regClick = function (key) {
btn.click(function () {
socket.emit('message', {
appid: "#{appid}",
userid: "#{userid}",
type: "message",
session: "#{sessionid}",
orgi: "#{orgi}",
message: key
});
});
}
regClick(item.text);
list.append(btn);
}
return element;
}
function createCard(message, data) {
let item = data[0];
let html = '<div class="card-box" style="background-color: #fff !important;"><div class="msg-card" style="background-color: #fff !important;"><img src="' + item.thumbnail + '" style="width: 80px;height: 80px;"></div><div class="msg-card msg-crad-right" style="background-color: #fff !important;"><h3 style="background-color: #fff !important;">' + item.title + '</h3><p style="background-color: #fff !important;">' + item.summary + '</p></div></div>'
var element = $(html);
element.click(function () {
window.open(item.hyperlink);
})
return element;
}
function showExtmsg(username, createtime, message, json) {
var expmsg = JSON.parse(json);
var type = expmsg[0].type;
var content;
if (type == 'button') {
content = createButton(message, expmsg);
} else if (type == 'qlist') {
content = createQList(message, expmsg);
} else if (type == 'card') {
content = createCard(message, expmsg);
}
var box = $('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + username + '</label><label class="time">' + createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content"></div></div>');
box.find('.chat-content').append(content);
output(box, 'chat-block')
}
function sendDisconnect() { function sendDisconnect() {
socket.disconnect(); socket.disconnect();
@ -666,28 +730,6 @@ html
} }
editor.html(''); editor.html('');
} }
function output(message, clazz, scroll, msgType) {
if (clazz == "message connect-message") {
var messages = document.getElementsByClassName("connect-message");
for (inx = 0; inx < messages.length;) {
document.getElementById('above').removeChild(messages[inx]);
inx++;
}
}
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
}
}
}
function update(id, message) {
document.getElementById(id).innerHTML = message;
}
var message = { var message = {
// text:data.message, // text:data.message,

View File

@ -1,4 +1,6 @@
doctype html doctype html
// constants
- var dialog_headimg= inviteData.consult_dialog_headimg ? '/res/image.html?id=' + inviteData.consult_dialog_headimg : '/images/agent.png'
html html
head head
meta(charset='utf-8') meta(charset='utf-8')
@ -142,210 +144,29 @@ html
wordinx = wordinx + 2 + obj.length; wordinx = wordinx + 2 + obj.length;
} }
} }
$(document).ready(function () {
window.addEventListener('resize', function () {
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
window.setTimeout(function () {
document.activeElement.scrollIntoViewIfNeeded()
}, 0)
}
});
// 在输入框获取焦点, 键盘弹起后, 真的是一行代码
$(document).on('submit.form.data-api', '[data-toggle="ajax-form"]', function (e) { function output(message, clazz, msgType) {
var formValue = $(e.target); if (clazz == "message connect-message") {
$(this).ajaxSubmit({ var messages = document.getElementsByClassName("connect-message");
url: formValue.attr("action"), for (inx = 0; inx < messages.length;) {
success: function (data) { document.getElementById('above').removeChild(messages[inx]);
inx++;
},
error: function (xhr, type, s) {
//notification("",false); //结束
}
});
return false;
});
});
style.
.msg-btn {
border: #4598ee 1px solid;
padding: 5px;
margin: 5px;
min-width: 125px;
text-align: center;
display: inline-block;
background-color: #e6f2ff;
cursor: default;
}
.msg-list {
color: #4598ee
}
.msg-card {
display: inline-block;
color: #000000;
}
.msg-crad-right {
position: relative;
left: 10px;
width: 170px;
height: 60px;
overflow: hidden;
text-overflow: ellipsis;
}
.card-box {
cursor: default;
width: 250px;
height: 72px;
padding: 6px;
line-height: 20px;
}
// 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滑动不流畅问题 */')
- var dialog_headimg= inviteData.consult_dialog_headimg ? '/res/image.html?id=' + inviteData.consult_dialog_headimg : '/images/agent.png'
#header(class="theme" + inviteData.consult_dialog_color)
img(src=(inviteData.consult_dialog_logo ? '/res/image.html?id=' + inviteData.consult_dialog_logo : '/images/logo.png'), style='height:50px;padding:10px;')
.ukefu-func-tab
ul
if models.contains("chatbot") && inviteData.ai && inviteData.ai == true && aiid
if exchange || exchange == "true"
li
a(href="/im/index.html?appid=" + appid + "&orgi=" + orgi + (aiid ? '&aiid=' + aiid : '') + "&ai=false" + (client ? '&client=' + client : '') + (type ? '&type=' + type : '') + (skill ? '&skill=' + skill : '') + (agent ? '&agent=' + agent : '') + "&userid=" + userid + "&sessionid=" + sessionid + "&t=" + pugHelper.currentTimeMillis()) 人工客服
li.cur
a(href="javascript:void(0)") 智能坐席
else
li.cur
a(href="javascript:void(0)") 智能坐席
#cooperation.ukefu-cooperation(style='display:none;z-index: 100;background-color: #ffffff;position: fixed;left: 0px;width: 100%;top: 0px;top:0px;height: 100%;')
.ukefu-image-canvas#ukefu-image-content(style='margin-top:2px;')
img#ukefu_img_ctx(style='max-width: 100%;max-height: 100%;')
.drawBoard(style='position: absolute;left: 0;top: 0;margin-top:2px;z-index: 998;')
canvas#canvas-borad.brushBorad 你的浏览器不支持 canvas 绘图
div(style='position: absolute;bottom: 10px;width: 100%;text-align: center;z-index:10000')
button#offcoop-btn(style='border-color:#009688 !important;color:#FFFFFF;display: inline-block;height: 38px;line-height: 38px;padding: 0 18px;background-color: #009688;color: #fff;white-space: nowrap;text-align: center;font-size: 14px;margin-right:10px;border: none;border-radius: 2px;cursor: pointer;opacity: .9;filter: alpha(opacity=90);background-color: #377FED !important;border:1px solid #FFFFFF;', onclick='offCoop();') 退出协作
.chat-above#above
.clearfix.message.welcome
span#welcome-message= inviteData.dialog_message ? inviteData.dialog_message : '欢迎您来咨询!欢迎使用春松客服!如需帮助请联系 info@chatopera.com'
for chatMessage in pugHelper.reverse(chatMessageList.content)
if chatMessage.userid && userid && chatMessage.calltype && chatMessage.calltype == "呼入"
.clearfix.chat-block
.chat-right
img.user-img(src="/im/img/user.png", alt="")
.chat-message
label.time= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
label.user #{chatMessage.username}
.chatting-right
i.arrow(class="arrow" + inviteData.consult_dialog_color)
.chat-content(class="theme" + inviteData.consult_dialog_color)
include ../media/message
else
.clearfix.chat-block
.chat-left
img.user-img(src=dialog_headimg, alt="")
.chat-message
label.user= chatMessage.username
label.time= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
.chatting-left
i.arrow
.chat-content
include ../media/message
.mobile-chat-bottom#bottom
textarea#message(name='content', maxlength=(inviteData.maxwordsnum > 0 ? inviteData.maxwordsnum : 300))
.btn-push.clearfix
img#facedialog(onclick='return openFaceDialog()', src='/im/img/face.png', style='width:32px;height:32px;')
a(href='javascript:void(0)', onclick='sendMessage();return false;')
img(src='/im/img/send.png', style='width:32px;height:32px;')
#faceindex(style='display:none;height:200px;position: absolute;bottom: 0px;width:100%;overflow-x:auto;')
table.ke-table(cellpadding='0', cellspacing='0', border='0', style='min-width:100%;')
tbody
for row in pugHelper.range(0,4)
tr
for col in pugHelper.range(0,20)
- var emoid=row * 20 + col;
td.ke-cell
span.ke-img
img(src="/im/js/kindeditor/plugins/emoticons/images/" + emoid + ".png", border="0", alt="", onclick="insertImg('" + emoid + "')")
script.
var service_end = false;
// 调查问卷
var diaShade = document.getElementById('diaShade');
var dialogWrap = document.getElementById('dialogWrap');
function popup(para) {
diaShade.style.display = para;
dialogWrap.style.display = para;
}
function chatScorllBottom(box) {
var imgdefereds = []; //定义一个操作数组
$('#' + box + ' .ukefu-media-image').each(function () { //遍历所有图片,将图片
var dfd = $.Deferred(); //定义一个将要完成某个操作的对象
$(this).bind('load', function () {
dfd.resolve(); //图片加载完成后,表示操作成功
});
if (this.complete) { //如果图片加载状态为完成,那么也标识操作成功
setTimeout(function () {
dfd.resolve();
}, 1000);
}
imgdefereds.push(dfd); //将所有操作对象放入数组中
})
$.when.apply(null, imgdefereds).done(function () { //注册所有操作完成后的执行方法
document.getElementById(box).scrollTop = document.getElementById(box).scrollHeight
});
}
chatScorllBottom('above')
// 参数连接
// 参数连接
var hostname = location.hostname;
var protocol = window.location.protocol.replace(/:/g, '');
var username = encodeURIComponent("#{username}");
var socket = io(protocol + '://' + hostname + ':#{port}/im/chatbot?userid=#{userid}&orgi=#{orgi}&session=#{sessionid}&appid=#{appid}&osname=!{osname}&browser=!{browser}!{skill ? "&skill=" + skill : ""}!{username ? "&nickname='+username+'" : ""}!{agent ? "&agent=" + agent : ""}!{title ? "&title=" + encodeURIComponent(title) : ""}!{traceid ? "&url=" + url : ""}!{traceid ? "&traceid=" + traceid : ""}!{aiid ? "&aiid=" + aiid : ""}', {transports: ['websocket', 'polling']});
socket.on('connect', function () {
//service.sendRequestMessage();
//output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message');
})
socket.on("agentstatus", function (data) {
document.getElementById('connect-message').innerHTML = data.message;
})
socket.on("status", function (data) {
output('<span id="connect-message">' + data.message + '</span>', 'message connect-message');
if (data.messageType == "end") {
service_end = true;
//editor.readonly();
}
if (document.getElementById("agentserviceid")) {
document.getElementById("agentserviceid").value = data.agentserviceid;
}
})
socket.on('message', function (data) {
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") {
chat = "<a href='javascript:void(0)' onclick='acceptInvite(\"" + data.message + "\", \"" + data.attachmentid + "\")'>您收到一个协作邀请,点击进入协作</a>";
} else if (data.msgtype == "action") {
//检查访客是否在协作页面上,如果在协作页面上,就开始执行重绘,否则不做处理
drawCanvasImage(data.attachmentid);
}
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_color}"></i><div class="chat-content theme#{inviteData.consult_dialog_color}">' + chat + '</div></div>', "chat-block", data.msgtype);
} else if (data.calltype == "呼出") {
if (data.expmsg) {
showExtmsg(data.username, data.createtime, data.message, data.expmsg);
} else {
output('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + data.username + '</label><label class="time">' + data.createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">' + chat + '</div></div>', "chat-block", data.msgtype);
} }
} }
}); 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);
}
function update(id, message) {
document.getElementById(id).innerHTML = message;
}
function showExtmsg(username, createtime, message, json) { function showExtmsg(username, createtime, message, json) {
var expmsg = JSON.parse(json); var expmsg = JSON.parse(json);
@ -367,6 +188,26 @@ html
output(box, 'chat-block') output(box, 'chat-block')
} }
function showExtmsgBody(username, createtime, message, json) {
var expmsg = JSON.parse(json.replace(/&quot;/g,'"'));
var type = expmsg[0].type;
var content;
if (type == 'button') {
content = createButton(message, expmsg);
} else if (type == 'qlist') {
content = createQList(message, expmsg);
} else if (type == 'card') {
content = createCard(message, expmsg);
}
var box = $('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + username + '</label><label class="time">' + createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content"></div></div>');
box.find('.chat-content').append(content);
output(box, 'chat-block')
}
function createButton(message, data) { function createButton(message, data) {
var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>') var element = $('<div><p>' + message + '</p><div class="button-box"></div></div>')
var list = element.find('.button-box'); var list = element.find('.button-box');
@ -434,6 +275,223 @@ html
return element; return element;
} }
$(document).ready(function () {
window.addEventListener('resize', function () {
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
window.setTimeout(function () {
document.activeElement.scrollIntoViewIfNeeded()
}, 0)
}
});
// 在输入框获取焦点, 键盘弹起后, 真的是一行代码
$(document).on('submit.form.data-api', '[data-toggle="ajax-form"]', function (e) {
var formValue = $(e.target);
$(this).ajaxSubmit({
url: formValue.attr("action"),
success: function (data) {
},
error: function (xhr, type, s) {
//notification("",false); //结束
}
});
return false;
});
});
style.
.msg-btn {
border: #4598ee 1px solid;
padding: 5px;
margin: 5px;
min-width: 125px;
text-align: center;
display: inline-block;
background-color: #e6f2ff;
cursor: default;
}
.msg-list {
color: #4598ee
}
.msg-card {
display: inline-block;
color: #000000;
}
.msg-crad-right {
position: relative;
left: 10px;
width: 170px;
height: 60px;
overflow: hidden;
text-overflow: ellipsis;
}
.card-box {
cursor: default;
width: 250px;
height: 72px;
padding: 6px;
line-height: 20px;
}
// 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滑动不流畅问题 */')
#header(class="theme" + inviteData.consult_dialog_color)
img(src=(inviteData.consult_dialog_logo ? '/res/image.html?id=' + inviteData.consult_dialog_logo : '/images/logo.png'), style='height:50px;padding:10px;')
.ukefu-func-tab
ul
if models.contains("chatbot") && inviteData.ai && inviteData.ai == true && aiid
if exchange || exchange == "true"
li
a(href="/im/index.html?appid=" + appid + "&orgi=" + orgi + (aiid ? '&aiid=' + aiid : '') + "&ai=false" + (client ? '&client=' + client : '') + (type ? '&type=' + type : '') + (skill ? '&skill=' + skill : '') + (agent ? '&agent=' + agent : '') + "&userid=" + userid + "&sessionid=" + sessionid + "&t=" + pugHelper.currentTimeMillis()) 人工客服
li.cur
a(href="javascript:void(0)") 智能坐席
else
li.cur
a(href="javascript:void(0)") 智能坐席
#cooperation.ukefu-cooperation(style='display:none;z-index: 100;background-color: #ffffff;position: fixed;left: 0px;width: 100%;top: 0px;top:0px;height: 100%;')
.ukefu-image-canvas#ukefu-image-content(style='margin-top:2px;')
img#ukefu_img_ctx(style='max-width: 100%;max-height: 100%;')
.drawBoard(style='position: absolute;left: 0;top: 0;margin-top:2px;z-index: 998;')
canvas#canvas-borad.brushBorad 你的浏览器不支持 canvas 绘图
div(style='position: absolute;bottom: 10px;width: 100%;text-align: center;z-index:10000')
button#offcoop-btn(style='border-color:#009688 !important;color:#FFFFFF;display: inline-block;height: 38px;line-height: 38px;padding: 0 18px;background-color: #009688;color: #fff;white-space: nowrap;text-align: center;font-size: 14px;margin-right:10px;border: none;border-radius: 2px;cursor: pointer;opacity: .9;filter: alpha(opacity=90);background-color: #377FED !important;border:1px solid #FFFFFF;', onclick='offCoop();') 退出协作
.chat-above#above
.clearfix.message.welcome
span#welcome-message= inviteData.dialog_message ? inviteData.dialog_message : '欢迎您来咨询!欢迎使用春松客服!如需帮助请联系 info@chatopera.com'
for chatMessage in pugHelper.reverse(chatMessageList.content)
if chatMessage.userid && userid && chatMessage.calltype && chatMessage.calltype == "呼入"
.clearfix.chat-block
.chat-right
img.user-img(src="/im/img/user.png", alt="")
.chat-message
label.time= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
label.user #{chatMessage.username}
.chatting-right
i.arrow(class="arrow" + inviteData.consult_dialog_color)
.chat-content(class="theme" + inviteData.consult_dialog_color)
include ../media/message
else
.clearfix.chat-block
- var createtime = pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
if chatMessage.expmsg
script.
try {
showExtmsgBody("#{chatMessage.username}", "#{createtime}", "#{chatMessage.message}", "#{chatMessage.expmsg}");
} catch (e) {
console.log("unexpected result", e)
}
else
.chat-left
img.user-img(src=dialog_headimg, alt="")
.chat-message
label.user= chatMessage.username
label.time= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', chatMessage.createtime)
.chatting-left
i.arrow
.chat-content
include ../media/message
.mobile-chat-bottom#bottom
textarea#message(name='content', maxlength=(inviteData.maxwordsnum > 0 ? inviteData.maxwordsnum : 300))
.btn-push.clearfix
img#facedialog(onclick='return openFaceDialog()', src='/im/img/face.png', style='width:32px;height:32px;')
a(href='javascript:void(0)', onclick='sendMessage();return false;')
img(src='/im/img/send.png', style='width:32px;height:32px;')
#faceindex(style='display:none;height:200px;position: absolute;bottom: 0px;width:100%;overflow-x:auto;')
table.ke-table(cellpadding='0', cellspacing='0', border='0', style='min-width:100%;')
tbody
for row in pugHelper.range(0,4)
tr
for col in pugHelper.range(0,20)
- var emoid=row * 20 + col;
td.ke-cell
span.ke-img
img(src="/im/js/kindeditor/plugins/emoticons/images/" + emoid + ".png", border="0", alt="", onclick="insertImg('" + emoid + "')")
script.
var service_end = false;
// 调查问卷
var diaShade = document.getElementById('diaShade');
var dialogWrap = document.getElementById('dialogWrap');
function popup(para) {
diaShade.style.display = para;
dialogWrap.style.display = para;
}
function chatScorllBottom(box) {
var imgdefereds = []; //定义一个操作数组
$('#' + box + ' .ukefu-media-image').each(function () { //遍历所有图片,将图片
var dfd = $.Deferred(); //定义一个将要完成某个操作的对象
$(this).bind('load', function () {
dfd.resolve(); //图片加载完成后,表示操作成功
});
if (this.complete) { //如果图片加载状态为完成,那么也标识操作成功
setTimeout(function () {
dfd.resolve();
}, 1000);
}
imgdefereds.push(dfd); //将所有操作对象放入数组中
})
$.when.apply(null, imgdefereds).done(function () { //注册所有操作完成后的执行方法
document.getElementById(box).scrollTop = document.getElementById(box).scrollHeight
});
}
chatScorllBottom('above')
// 参数连接
// 参数连接
var hostname = location.hostname;
var protocol = window.location.protocol.replace(/:/g, '');
var username = encodeURIComponent("#{username}");
var socket = io(protocol + '://' + hostname + ':#{port}/im/chatbot?userid=#{userid}&orgi=#{orgi}&session=#{sessionid}&appid=#{appid}&osname=!{osname}&browser=!{browser}!{skill ? "&skill=" + skill : ""}!{username ? "&nickname='+username+'" : ""}!{agent ? "&agent=" + agent : ""}!{title ? "&title=" + encodeURIComponent(title) : ""}!{traceid ? "&url=" + url : ""}!{traceid ? "&traceid=" + traceid : ""}!{aiid ? "&aiid=" + aiid : ""}', {transports: ['websocket', 'polling']});
socket.on('connect', function () {
//service.sendRequestMessage();
//output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message');
})
socket.on("agentstatus", function (data) {
document.getElementById('connect-message').innerHTML = data.message;
})
socket.on("status", function (data) {
output('<span id="connect-message">' + data.message + '</span>', 'message connect-message');
if (data.messageType == "end") {
service_end = true;
//editor.readonly();
}
if (document.getElementById("agentserviceid")) {
document.getElementById("agentserviceid").value = data.agentserviceid;
}
})
socket.on('message', function (data) {
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") {
chat = "<a href='javascript:void(0)' onclick='acceptInvite(\"" + data.message + "\", \"" + data.attachmentid + "\")'>您收到一个协作邀请,点击进入协作</a>";
} else if (data.msgtype == "action") {
//检查访客是否在协作页面上,如果在协作页面上,就开始执行重绘,否则不做处理
drawCanvasImage(data.attachmentid);
}
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_color}"></i><div class="chat-content theme#{inviteData.consult_dialog_color}">' + chat + '</div></div>', "chat-block", data.msgtype);
} else if (data.calltype == "呼出") {
if (data.expmsg) {
showExtmsg(data.username, data.createtime, data.message, data.expmsg);
} else {
output('<div class="chat-left"> <img class="user-img" src="#{dialog_headimg}" alt=""><div class="chat-message"><label class="user">' + data.username + '</label><label class="time">' + data.createtime + '</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">' + chat + '</div></div>', "chat-block", data.msgtype);
}
}
});
socket.on('disconnect', function () { socket.on('disconnect', function () {
output('<span id="connect-message">连接坐席失败,在线咨询服务不可用</span>', 'message connect-message'); output('<span id="connect-message">连接坐席失败,在线咨询服务不可用</span>', 'message connect-message');
}); });
@ -457,6 +515,7 @@ html
}); });
} }
function drawCanvasImage(fileid) { function drawCanvasImage(fileid) {
var canvas = document.getElementById("canvas-borad"); var canvas = document.getElementById("canvas-borad");
@ -504,27 +563,7 @@ html
}); });
} }
} }
function output(message, clazz, msgType) {
if (clazz == "message connect-message") {
var messages = document.getElementsByClassName("connect-message");
for (inx = 0; inx < messages.length;) {
document.getElementById('above').removeChild(messages[inx]);
inx++;
}
}
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);
}
function update(id, message) {
document.getElementById(id).innerHTML = message;
}
autoTextarea(document.getElementById("message"));// 调用 autoTextarea(document.getElementById("message"));// 调用
$('#message').click(function () { $('#message').click(function () {
wordinx = getPositionForTextArea(document.getElementById('message')); wordinx = getPositionForTextArea(document.getElementById('message'));

View File

@ -20,6 +20,7 @@ import com.chatopera.bot.exception.ChatbotException;
import com.chatopera.bot.sdk.Response; import com.chatopera.bot.sdk.Response;
import com.chatopera.cc.basic.Constants; import com.chatopera.cc.basic.Constants;
import com.chatopera.cc.basic.MainContext; import com.chatopera.cc.basic.MainContext;
import com.chatopera.cc.basic.MainUtils;
import com.chatopera.cc.cache.Cache; import com.chatopera.cc.cache.Cache;
import com.chatopera.cc.model.Chatbot; import com.chatopera.cc.model.Chatbot;
import com.chatopera.cc.persistence.repository.AgentUserRepository; import com.chatopera.cc.persistence.repository.AgentUserRepository;
@ -126,7 +127,9 @@ public class ChatbotEventSubscription {
ChatMessage respHelp = new ChatMessage(); ChatMessage respHelp = new ChatMessage();
JSONArray respParams = new JSONArray(); JSONArray respParams = new JSONArray();
if (!StringUtils.equals(MainContext.ChannelType.WEBIM.toString(), c.getChannel())) { if (!StringUtils.equals(MainContext.ChannelType.WEBIM.toString(), c.getChannel())) {
// WEBIM 情况比如 Facebook Messenger使用下面的方法 /**
* WEBIM 情况比如 Facebook Messenger使用下面的方法
*/
// 如果在更多渠道下此处可能仅适应于 Messenger那么宜将检测条件调整为 ChannelType.MESSENGER // 如果在更多渠道下此处可能仅适应于 Messenger那么宜将检测条件调整为 ChannelType.MESSENGER
if (data.getBoolean("logic_is_fallback")) { if (data.getBoolean("logic_is_fallback")) {
if (!StringUtils.equals(Constants.CHATBOT_HUMAN_FIRST, c.getWorkmode())) { if (!StringUtils.equals(Constants.CHATBOT_HUMAN_FIRST, c.getWorkmode())) {
@ -219,7 +222,9 @@ public class ChatbotEventSubscription {
} }
} }
} else { } else {
// 当前渠道为 WEBIM /**
* 当前渠道为 WEBIM
*/
if (data.getBoolean("logic_is_fallback")) { if (data.getBoolean("logic_is_fallback")) {
// 兜底回复检查FAQ // 兜底回复检查FAQ
JSONArray faqReplies = data.getJSONArray("faq"); JSONArray faqReplies = data.getJSONArray("faq");
@ -249,22 +254,30 @@ public class ChatbotEventSubscription {
if (MainContext.ChannelType.WEBIM.toString().equals(resp.getChannel())) { if (MainContext.ChannelType.WEBIM.toString().equals(resp.getChannel())) {
// WEBIM 渠道 // WEBIM 渠道
if (StringUtils.equals(resp.getMessage(), "{CLEAR} 混合类型消息") || StringUtils.equals(resp.getMessage(), "{CLEAR} 图文消息")) { if (StringUtils.equals(resp.getMessage(), "{CLEAR} 混合类型消息") || StringUtils.equals(resp.getMessage(), "{CLEAR} 图文消息")) {
// 处理多答案
JSONArray params = data.getJSONArray("params"); JSONArray params = data.getJSONArray("params");
for (int i = 0; i < params.length(); i++) { for (int i = 0; i < params.length(); i++) {
JSONObject item = params.getJSONObject(i); JSONObject item = params.getJSONObject(i);
ChatMessage itemResp = (ChatMessage) resp.clone(); ChatMessage itemResp = (ChatMessage) resp.clone();
itemResp.setId(MainUtils.getUUID());
itemResp.setExpmsg(null); itemResp.setExpmsg(null);
// 处理不同答案类型
// 数据格式https://github.com/chatopera/cskefu/issues/468
if (item.getString("type").equals("plain")) { if (item.getString("type").equals("plain")) {
itemResp.setMessage(item.getString("content")); itemResp.setMessage(item.getString("content"));
chatbotProxy.saveAndPublish(itemResp); chatbotProxy.saveAndPublish(itemResp);
} else if (item.getString("type").equals("card")) { } else if (item.getString("type").equals("card")) {
if (item.has("thumbnail")) { if (item.has("thumbnail")) {
item.put("thumbnail", ChatbotConstants.DEFAULT_BOT_PROVIDER + item.getString("thumbnail")); String thumbnailUrl = botServiceProvider + item.getString("thumbnail");
item.put("thumbnail", thumbnailUrl);
JSONArray expmsg = new JSONArray();
expmsg.put(item);
itemResp.setExpmsg(expmsg.toString());
// itemResp.setMsgtype("image");
itemResp.setMessage(thumbnailUrl);
chatbotProxy.saveAndPublish(itemResp);
} }
JSONArray expmsg = new JSONArray();
expmsg.put(item);
itemResp.setExpmsg(expmsg.toString());
chatbotProxy.saveAndPublish(itemResp);
} }
} }
} else { } else {