/**
* Kefu v1.0.7
* FastAdmin在线客服系统
* https://www.fastadmin.net/store/kefu.html
*
* Copyright 2020 白衣素袖
*
* FastAdmin在线客服系统不是开源产品,所有文字、图片、样式、风格等版权归在线客服作者所有,如有复制、仿冒、抄袭、盗用,FastAdmin和在线客服作者将追究法律责任
*
* Released on: November 6, 2020
*/
// 音频播放初始化
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
var KeFu = {
ws: {
SocketTask: null,
Timer: null,
ErrorMsg: [],
MaxRetryCount: 3,// 最大重连次数
CurrentRetryCount: 0,
url: null
},
audio: {
context: new window.AudioContext(),
source: null,
buffer: null
},
config: null,
url: null,
fixed_csr: 0,
window_is_show: false,
fast_move: false,
csr: "",// 当前用户的客服代表ID
session_id: 0,
last_sender: null,
token_list: [],
fast_reply: [],// 快捷回复富文本支持
session_user: "",
select_session_user: "",// 右键菜单选中的 session_user
slider: null,// 幻灯片对象
clickkefu_button: false,// 防止浮动按钮被拖动时触发点击事件
allowed_close_window: true,// 是否允许ecs关闭窗口(当预览图片时,不允许关闭)
record_scroll_height: 0,// 聊天记录窗口的滚动条高度
resize_load: 0,
group_show: {
'dialogue': false,
'invitation': false,
'recently': false
}, // 分组是否展开,未展开时添加红点
initialize: function (url = document.domain, modulename = 'index', initSuccess = null, fixed_csr = 0) {
KeFu.url = url;
KeFu.fixed_csr = fixed_csr;
var initialize_url = KeFu.buildUrl(url, modulename, 'initialize');
$.ajax({
url: initialize_url,
success: function (data) {
if (data.code == 401) {
console.warn(data.msg);
return;
} else if (data.code != 1) {
layer.msg(data.msg);
return;
}
KeFu.config = data.data.config;
KeFu.config.user_id = data.data.user_info.user_id;
KeFu.token_list = data.data.token_list;
if (KeFu.token_list.kefu_tourists_token) {
localStorage.setItem('kefu_tourists_token', KeFu.token_list.kefu_tourists_token);
}
KeFu.fast_reply = data.data.fast_reply;
KeFu.bulidChat(data.data.window_html);
if (parseInt(KeFu.config.auto_invitation_switch) > 0 && KeFu.config.modulename != 'admin') {
let only_first_invitation = parseInt(KeFu.config.only_first_invitation);
// kefu_auto_invitation 在窗口成功弹出后创建
if ((only_first_invitation == 1 && !localStorage.getItem('kefu_auto_invitation')) || only_first_invitation == 0) {
setTimeout(function () {
KeFu.bulidInviteBox();
}, (KeFu.config.auto_invitation_timing * 1000));
}
}
// 构建ws和文件上传的url
KeFu.ws.url = KeFu.buildUrl(url, modulename, 'ws', KeFu.config.websocket_port);
KeFu.config.upload.uploadurl = KeFu.buildUrl(url, modulename, "upload");
if (modulename == 'admin') {
// 立即链接 Websocket
KeFu.ConnectSocket();
} else {
// 若用户 10 秒后任在此页面,链接Socket
setTimeout(function () {
if (!KeFu.ws.SocketTask || KeFu.ws.SocketTask.readyState == 3 || KeFu.ws.SocketTask.readyState == 2) {
KeFu.ConnectSocket();
}
}, 10000);
}
if (typeof initSuccess == 'function') {
initSuccess();
}
// 读取按钮位置
var kefu_button_coordinate = localStorage.getItem("kefu_button_coordinate");
if (kefu_button_coordinate) {
kefu_button_coordinate = kefu_button_coordinate.split(',');
if (kefu_button_coordinate[0] && kefu_button_coordinate[1] && $('body').width() > Number(kefu_button_coordinate[1])) {
$("#kefu_button").css({
"top": Number(kefu_button_coordinate[0]),
"left": Number(kefu_button_coordinate[1])
});
}
}
// 新消息
if (data.data.new_msg) {
KeFu.toggle_popover('show', data.data.new_msg);
KeFu.new_message_prompt('#kefu_button');
} else if (!localStorage.getItem('kefu_new_user')) {
KeFu.toggle_popover('show', KeFu.config.new_user_tip);
KeFu.new_message_prompt('#kefu_button');
}
KeFu.eventReg();
}
});
},
ConnectSocket: function () {
if ("WebSocket" in window) {
var ws = new WebSocket(KeFu.ws.url);
KeFu.ws.SocketTask = ws;
ws.onopen = function () {
// 重新发送所有出错的消息
if (KeFu.ws.ErrorMsg.length > 0) {
for (let i in KeFu.ws.ErrorMsg) {
KeFu.ws_send(KeFu.ws.ErrorMsg[i]);
}
KeFu.ws.ErrorMsg = [];
}
if (KeFu.ws.Timer != null) {
clearInterval(KeFu.ws.Timer);
}
KeFu.ws.Timer = setInterval(KeFu.ws_send, 28000);//定时发送心跳
};
ws.onmessage = function (evt) {
var msg = $.parseJSON(evt.data);
let action = KeFu.domsg[msg.msgtype] || KeFu.domsg['default']
action.call(this, msg)
};
ws.onclose = function (e) {
if (KeFu.ws.Timer != null) {
clearInterval(KeFu.ws.Timer);
}
KeFu.ws.ws_error = true;
$('#kefu_error').html('网络链接已断开');
KeFu.toggle_popover('show', 'WebSocket 链接已断开');
if (KeFu.ws.MaxRetryCount) {
KeFu.ws.Timer = setInterval(KeFu.retry_webSocket, 3000);//每3秒重新连接一次
}
};
ws.onerror = function (e) {
// 错误
KeFu.ws.ws_error = true;
console.error('websocket 错误:', e);
$('#kefu_error').html('WebSocket 发生错误');
KeFu.toggle_popover('show', 'WebSocket 发生错误');
};
} else {
KeFu.ws.ws_error = true;
layer.msg(KeFu.config.chat_name + ':您的浏览器不支持 WebSocket!');
}
},
retry_webSocket: function () {
if (KeFu.ws.CurrentRetryCount < KeFu.ws.MaxRetryCount) {
KeFu.ws.CurrentRetryCount++;
KeFu.ConnectSocket();
console.log('重连 WebSocket 第' + KeFu.ws.CurrentRetryCount + '次');
} else {
if (KeFu.ws.Timer != null) {
clearInterval(KeFu.ws.Timer);
}
console.log('每隔10秒将再次尝试重连 WebSocket')
KeFu.ws.Timer = setInterval(KeFu.ConnectSocket, 10000);//每10秒重新连接一次
}
},
change_csr_status: function (status_id) {
status_id = parseInt(status_id);
const states = new Map([
[0, ['离线', '#777']],
[1, ['繁忙', '#8a6d3b']],
[2, ['离开', '#a94442']],
[3, ['在线', '#3c763d']],
['default', ['未知', '#777']],
])
let state = states.get(status_id) || states.get('default');
if (KeFu.config.modulename == 'admin') {
$('#kefu_csr_status button .kefu_status').html(state[0]);
$('#kefu_csr_status button').css('color', state[1]);
} else {
$('.modal-title #csr_status').html(' • ' + state[0]);
$('.modal-title #csr_status').css('color', state[1]);
}
},
// 会话分组的红点管理
session_group_red_dot: function (group, red_dot) {
var element_id = '#heading_' + group;
if (red_dot) {
$('.KeFu .modal-body .kefu-left ' + element_id + ' .panel-title .red_dot').fadeIn();
} else {
$('.KeFu .modal-body .kefu-left ' + element_id + ' .panel-title .red_dot').fadeOut();
}
},
get_format_session_time: function () {
var date_obj = new Date();
var hours = date_obj.getHours();
hours = hours < 10 ? '0' + hours : hours;
var minutes = date_obj.getMinutes();
minutes = minutes < 10 ? '0' + minutes : minutes;
return hours + ':' + minutes;
},
domsg: {
default: (msg) => {
// console.log('default', msg);
},
initialize: (msg) => {
$('#kefu_error').html('');
if (KeFu.ws.ws_error) {
KeFu.ws.CurrentRetryCount = 0;
KeFu.toggle_popover('hide');
KeFu.ws.ws_error = false;
}
if (msg.data.modulename == 'admin') {
KeFu.change_csr_status(msg.data.user_info.status_text);
$('#modal-title').html(msg.data.chat_name + '-' + msg.data.user_info.nickname);
// 渲染聊天列表
if (msg.data.session.dialogue && msg.data.session.dialogue.length) {
for (let i in msg.data.session.dialogue) {
KeFu.buildSession(msg.data.session.dialogue[i], 'dialogue');
}
KeFu.session_id = msg.data.session.dialogue[msg.data.session.dialogue.length - 1].id;
$('#heading_dialogue a').click();
}
if (msg.data.session.invitation && msg.data.session.invitation.length) {
for (let i in msg.data.session.invitation) {
KeFu.buildSession(msg.data.session.invitation[i], 'invitation');
}
}
if (msg.data.session.recently && msg.data.session.recently.length) {
for (let i in msg.data.session.recently) {
KeFu.buildSession(msg.data.session.recently[i], 'recently');
}
if (!KeFu.session_id) {
KeFu.session_id = msg.data.session.recently[msg.data.session.recently.length - 1].id;
$('#heading_recently a').click();
}
}
KeFu.changeSession(KeFu.session_id);
} else {
if (msg.data.new_msg) {
KeFu.toggle_popover('show', msg.data.new_msg);
KeFu.new_message_prompt('#kefu_button');
}
}
},
user_card: (msg) => {
if (msg.data) {
$('#card-user').val(msg.data.nickname + ' ID:' + msg.data.id + (msg.data.user_id ? ' 会员ID:' + msg.data.user_id : ''));
$('#card-nickname').val(msg.data.nickname_origin);
$('#card-referrer').val(msg.data.referrer);
$('#card-contact').val(msg.data.contact);
$('#card-note').val(msg.data.note);
}
},
search_user: (msg) => {
// 渲染搜索结果列表
var element_id = '#session_list_search';
KeFu.search_primary = -1;
KeFu.search_select_id = '';
$(element_id).html('');
$(element_id).fadeIn();
if (msg.data.length) {
$.each(msg.data, function (index, item) {
$(element_id).append(
'
' +
'
' +
'' +
'' + item.nickname + '' +
'' + item.last_time + '' +
'
\
' +
'' + item.last_message + '' +
'
' +
''
);
});
} else {
$(element_id).append('找不到用户~
');
}
},
user_initialize: (msg) => {
// 用户客服分配结束
if (msg.code == 1) {
if (msg.data.session.user_tourists) {
KeFu.sendMessage = function () {
layer.msg('请登录后发送消息~');
}
KeFu.edit_send_tis('为保护您的隐私请 登录 后发送消息');
}
KeFu.csr = msg.data.session.csr;
KeFu.session_id = msg.data.session.id;
$('#modal-title').html('客服 ' + msg.data.session.nickname + ' 为您服务');
KeFu.toggle_window_view('kefu_scroll');
KeFu.change_csr_status(msg.data.session.csr_status);
} else if (msg.code == 302) {
if (!KeFu.csr) {
// 打开留言板
KeFu.csr = 'none';
$('#modal-title').html('当前无客服在线哦~');
KeFu.toggle_window_view('kefu_leave_message');
} else {
KeFu.edit_send_tis('当前客服暂时离开,您可以直接在此发送离线消息');
}
}
},
action_session: (msg) => {
if (msg.data.action == 'received_invitation' && !KeFu.window_is_show) {
// 显示邀请框
var kefu_invite_box = $('.kefu_invite_box');
if (kefu_invite_box.length) {
kefu_invite_box.fadeIn();
} else {
KeFu.bulidInviteBox();
}
} else if (msg.data.action == 'send_success' && KeFu.session_user == msg.data.session_user) {
// 重新加载轨迹
var session = $("#session_panel [data-session_user='" + msg.data.session_user + "']");
KeFu.changeSession(session.data('session'), 'trajectory');
} else if (msg.data.action == 'transfer') {
// 显示转接操作面板
var tpl = '\
';
var session = $("#session_panel [data-session_user='" + msg.data.session_user + "']");
session.after(tpl);
$.each(msg.data.csr_list, function (index, item) {
let html_text = item.nickname + '(ID:' + item.admin_id + ')';
$("#transfer_session_select").append("");
});
$(document).on('click', '#transfer_session_cancel', function (e) {
$('.kefu_transfer_session').remove();
});
$(document).on('click', '#transfer_session_ok', function (e) {
var transfer_user = $('.kefu_transfer_session').data('transfer_user');
var csr = $('#transfer_session_select').val();
if (transfer_user && csr) {
var action_session = {
c: 'Message',
a: 'actionSession',
data: {
action: 'transfer_done',
session_user: transfer_user,
csr: csr
}
};
KeFu.ws_send(action_session);
}
$('.kefu_transfer_session').remove();
});
} else if (msg.data.action == 'transfer_done' && msg.data.res) {
// 转移成功
layer.msg('会话已转移给客服 ' + msg.data.res);
$("#session_panel [data-session_user='" + msg.data.session_user + "']").remove();
KeFu.group_session_is_none('dialogue');
KeFu.group_session_is_none('recently');
} else if (msg.data.action == 'edit_nickname') {
var session = $("#session_panel [data-session_user='" + msg.data.session_user + "']");
session.children(".session_info_item").children(".name").eq(0).html(msg.data.list_nickname);
if (KeFu.session_user == msg.data.session_user) {
$('#session_user_name').html(msg.data.new_nickname);
}
}
},
leave_message: (msg) => {
layer.msg(msg.msg);
$('#kefu_leave_message form')[0].reset()
},
show_msg: (msg) => {
layer.msg(msg.msg);
},
clear: (msg) => {
if (msg.msg) {
layer.msg(msg.msg);
}
var clear = {
c: 'Message',
a: 'clear'
};
KeFu.ws_send(clear);
KeFu.retry_webSocket = function () {
clearInterval(KeFu.ws.Timer)
};
},
offline: (msg) => {
if (KeFu.config.modulename == 'admin') {
$("#session_panel [data-transfer_user='" + msg.user_id + "']").remove();
KeFu.edit_online_status(msg.user_id, false);
} else {
if (msg.user_id == KeFu.csr) {
KeFu.edit_send_tis('当前客服暂时离开,您可以直接在此发送离线消息');
KeFu.change_csr_status(0);
}
}
},
online: (msg) => {
var element = $("#session_panel [data-session_user='" + msg.user_id + "']");
if (msg.tourists != 'not' && !element.length) {
// 添加到邀请中
KeFu.buildSession(msg.tourists, 'invitation');
if (!KeFu.group_show.invitation) {
KeFu.session_group_red_dot('invitation', true);
}
}
if (KeFu.window_is_show && KeFu.session_user == msg.user_id) {
$('#session_user_name').html(msg.user_name);
}
// 修改用户在线状态
KeFu.edit_online_status(msg.user_id, true);
// 来自 admin 的用户上线了
if (msg.modulename == 'admin') {
if (msg.user_id == KeFu.csr) {
let send_tis_key = parseInt(KeFu.config.send_message_key) == 1 ? 'Enter' : 'Ctrl+Enter';
KeFu.edit_send_tis('按下' + send_tis_key + '发送消息', '按下' + (send_tis_key == 'Enter' ? 'Ctrl+Enter' : 'Enter') + '换行');
KeFu.change_csr_status(3);
} else if (KeFu.csr == 'none') {
// 重新为用户分配客服代表
var user_initialize = {
c: 'Message',
a: 'userInitialize'
};
KeFu.ws_send(user_initialize);
}
}
},
trajectory: (msg) => {
var trajectory = msg.data.trajectory;
KeFu.chat_record_page = msg.data.next_page;
if (msg.data.page == 1) {
$('#kefu_trajectory_log').html('');
// 修改会话的最后消息
let session = $("#session_panel [data-session_user='" + msg.data.user_info.session_user + "']");
session.children(".session_info_item").children(".time").eq(0).html(msg.data.last_message.last_time);
session.children(".session_info_item").find(".last_message").eq(0).html(msg.data.last_message.last_message);
}
$('#session_user_name').html(msg.data.user_info.nickname);
// 构建轨迹
var x = 'left';
for (let i in trajectory) {
if (msg.data.page == 1) {
KeFu.build_trajectory(i, msg.data.page, 'date');
}
for (let y in trajectory[i]) {
KeFu.build_trajectory(trajectory[i][y], msg.data.page, 'log', x);
x = (x == 'left') ? 'right' : 'left';
}
if (msg.data.page != 1) {
KeFu.build_trajectory(i, msg.data.page, 'date');
}
}
KeFu.kefu_blacklist(3, msg.data.user_info.session_user, msg.data.user_info.blacklist);
if (msg.data.page == 1) {
if (KeFu.window_is_show) {
$('#kefu_trajectory').scrollTop($('#kefu_trajectory')[0].scrollHeight);
} else {
KeFu.window_show_event = function () {
$('#kefu_trajectory').scrollTop($('#kefu_trajectory')[0].scrollHeight);
}
}
} else {
$('#kefu_trajectory').scrollTop($('#kefu_trajectory')[0].scrollHeight - KeFu.record_scroll_height);
}
},
chat_record: (msg) => {
if (msg.data.page == 1) {
$('#kefu_scroll').html('');
}
if (KeFu.config.modulename == 'admin') {
$('#session_user_name').html(msg.data.session_info.nickname);
}
var chat_record = msg.data.chat_record;
KeFu.chat_record_page = msg.data.next_page;
for (let i in chat_record) {
if (msg.data.page == 1) {
KeFu.buildPrompt(chat_record[i].datetime, msg.data.page);
}
for (let y in chat_record[i].data) {
KeFu.buildRecord(chat_record[i].data[y], msg.data.page)
}
if (msg.data.page != 1) {
KeFu.buildPrompt(chat_record[i].datetime, msg.data.page);
}
}
KeFu.kefu_blacklist(3, msg.data.session_info.session_user, msg.data.session_info.blacklist);
if (msg.data.page == 1) {
if (KeFu.window_is_show) {
setTimeout(function () {
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
}, 100)
} else {
KeFu.window_show_event = function () {
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
}
}
} else {
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight - KeFu.record_scroll_height);
}
// 消息输入框聚焦
setTimeout(function () {
$('#kefu_message').focus();
}, 500)
},
csr_change_status: (msg) => {
if (KeFu.config.modulename == 'admin' && KeFu.config.user_id == msg.data.csr) {
KeFu.change_csr_status(msg.data.csr_status);
} else if (KeFu.csr == msg.data.csr) {
KeFu.change_csr_status(msg.data.csr_status);
}
},
blacklist: (msg) => {
if (msg.data.action == 'del') {
KeFu.kefu_blacklist(2, msg.data.session_user);
} else if (msg.data.action == 'add') {
KeFu.kefu_blacklist(1, msg.data.session_user);
}
},
transfer_done: (msg) => {
KeFu.csr = msg.data.csr;
$('#modal-title').html('客服 ' + msg.data.nickname + ' 为您服务');
},
reload_record: (msg) => {
// 重载聊天记录
if (KeFu.session_id == msg.data.session_id) {
var load_record = {
c: 'Message',
a: 'chatRecord',
data: {
session_id: msg.data.session_id,
page: 1
}
};
KeFu.ws_send(load_record)
}
},
new_message: (msg) => {
var message_content = msg.data.nickname + ':' + msg.data.last_message;
if (KeFu.window_is_show) {
// 窗口打开状态
KeFu.new_message_prompt('#KeFuModal');
} else {
KeFu.toggle_popover('show', message_content);
KeFu.new_message_prompt('#kefu_button');
}
if ($('#kefu_scroll').children('.status').children('span').eq(0).html() == '还没有消息') {
$('#kefu_scroll').children('.status').children('span').eq(0).html(KeFu.get_format_session_time());
}
if (msg.data.session_id == KeFu.session_id) {
$('#kefu_input_status').html('');
}
if (KeFu.config.modulename == 'admin') {
// 为会话中添加一个红点
if (!KeFu.group_show.dialogue) {
KeFu.session_group_red_dot('dialogue', true);
}
// 检查是否有该会话
let session = $("#session_panel [data-session_user='" + msg.data.session_user + "']");
// 记录最后发信人
KeFu.last_sender = msg.data.session_id;
if (session.length == 0) {
KeFu.buildSession(msg.data, 'dialogue');
KeFu.group_session_is_none('dialogue');
} else {
// 会话将被移动->取消会话转移
$("#session_panel [data-transfer_user='" + msg.data.session_user + "']").remove();
// 确保 data 正确
session.data('session', msg.data.session_id);
session.attr("data-session", msg.data.session_id);
session.data('group', 'dialogue');
session.attr("data-group", 'dialogue');
// 修改该会话的最后消息
session.children(".session_info_item").children(".time").eq(0).html(msg.data.last_time);
session.children(".session_info_item").find(".last_message").eq(0).html(msg.data.last_message);
// 将会话移动到“会话中”的第一位
let first_session = $('#session_list_dialogue li');
if (first_session.length) {
// 会话中已有对话
first_session.eq(0).before(session);
} else {
// 会话中没有对话
$('#session_list_dialogue').prepend(session);
}
KeFu.group_session_is_none('dialogue');
KeFu.group_session_is_none('recently');
KeFu.group_session_is_none('invitation');
if (msg.data.session_user == KeFu.session_user && KeFu.window_is_show) {
if (session.data('group') != 'dialogue') {
// 会话被移动到“会话中”->取消该会话的选择状态
session.removeClass("active");
} else {
if ($('#kefu_trajectory').css('display') != 'block') {
// 必要时,去除该会话的红点
KeFu.buildRecord(msg.data, 1);
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
var load_message = {
c: 'Message',
a: 'readMessage',
data: {
record_id: msg.data.record_id,
session_id: KeFu.session_id
}
};
KeFu.ws_send(load_message);
return;
}
}
}
if (msg.data.unread_msg_count > 0) {
session.children(".session_info_item").children(".unread_msg_count").eq(0).html(msg.data.unread_msg_count).fadeIn();
} else {
session.children(".session_info_item").children(".unread_msg_count").eq(0).fadeOut();
}
}
} else {
KeFu.buildRecord(msg.data, 1);
if (msg.data.session_id == KeFu.session_id && KeFu.window_is_show) {
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
var load_message = {
c: 'Message',
a: 'readMessage',
data: {
record_id: msg.data.record_id,
session_id: KeFu.session_id
}
};
KeFu.ws_send(load_message);
return;
}
}
},
send_message: (msg) => {
if (!msg.data.message_id) {
return;
}
if (msg.code == 1) {
let message_record = $('.kefu_message_' + msg.data.message_id);
message_record.text('未读');
message_record.removeClass('kefu_message_' + msg.data.message_id);
message_record.addClass('kefu_message_' + msg.data.id);
} else {
$('.kefu_message_' + msg.data.message_id).addClass('kf-text-red').text('失败');
layer.msg(msg.data.msg)
}
},
read_message_done: (msg) => {
if (msg.data.record_id == 'all') {
if (KeFu.session_id == msg.data.session_id) {
$('.kefu_message_status').addClass('kf-text-grey').text('已读');
}
} else {
let message_record = $('.kefu_message_' + msg.data.record_id);
message_record.addClass('kf-text-grey').text('已读');
}
},
message_input: (msg) => {
var input_status_display = parseInt(KeFu.config.input_status_display);
if (input_status_display == 0) {
return;
} else if (input_status_display == 2 && KeFu.config.modulename != 'admin') {
return;
}
if (KeFu.session_id == msg.data.session_id) {
if (msg.data.type == 'input') {
$('#kefu_input_status').html('对方正在输入...');
} else {
$('#kefu_input_status').html('');
}
}
},
upload_multipart: (msg) => {
if (msg.data.upload_multipart) {
KeFu.config.upload.multipart = msg.data.upload_multipart
}
}
},
ws_send: function (message) {
if (!message) {
message = {c: 'Message', a: 'ping'};
}
if (KeFu.ws.SocketTask && KeFu.ws.SocketTask.readyState == 1) {
KeFu.ws.SocketTask.send(JSON.stringify(message));
} else {
// console.log('消息发送出错', message)
KeFu.ws.ErrorMsg.push(message);
}
},
edit_send_tis: function (tis, title = '') {
$('.KeFu .modal-body #send_tis').html(tis);
$('.KeFu .modal-body #send_tis').attr('title', title);
},
toggle_popover: function (toggle, content) {
if (!KeFu.window_is_show && content && toggle == 'show') {
$('#kefu_button').attr("data-content", content);
$('#kefu_button').popover('show');
} else {
$('#kefu_button').popover('hide');
}
},
// 切换显示的视图-聊天视图、轨迹视图、留言视图、用户名片视图
toggle_window_view: function (show_view_id) {
// 隐藏所有视图
$('.kefu_window_view').hide();
// 显示指定的视图
$('#' + show_view_id).show();
// 聊天
if (show_view_id == 'kefu_scroll') {
$('.modal-body .write').show();
if (KeFu.config.modulename == 'admin') {
$('.KeFu .modal-body .kefu-right .chat').height('calc(100% - 158px)');
}
} else {
if (KeFu.config.modulename == 'admin') {
KeFu.hide_tool_panel();
$('.KeFu .modal-body .kefu-right .chat').height('calc(100% - 58px)');
}
$('.modal-body .write').hide();
}
// 轨迹
if (show_view_id == 'kefu_trajectory') {
$('#kefu_view_trajectory').fadeOut();
} else {
$('#kefu_view_trajectory').fadeIn();
}
// 名片
if (show_view_id == 'kefu_user_card') {
$('#kefu_view_user_card').fadeOut();
} else {
$('#kefu_view_user_card').fadeIn();
}
},
toggle_window: function (toggle) {
if (toggle == 'show') {
KeFu.window_is_show = true;
if (!KeFu.isPc() && KeFu.config.modulename != 'admin') {
// 跳转到手机单页
window.location.href = KeFu.buildUrl(KeFu.url, KeFu.config.modulename, 'mobile');
return;
}
// 隐藏悬浮按钮
KeFu.toggle_popover('hide');
$('#kefu_button').fadeOut();
// 检查 websocket 是否连接
if (!KeFu.ws.SocketTask || KeFu.ws.SocketTask.readyState != 1) {
KeFu.ConnectSocket();
}
// 隐藏邀请框
$('.kefu_invite_box').fadeOut();
$('#KeFuModal').modal({
// keyboard: (KeFu.config.ecs_exit == '1') ? true:false,
keyboard: false,
show: true
});
if (KeFu.config.modulename != 'admin') {
// 分配/获取客服->获取聊天记录
var user_initialize = {
c: 'Message',
a: 'userInitialize',
data: {
fixed_csr: KeFu.fixed_csr
}
};
KeFu.ws_send(user_initialize);
// 绑定窗口中的动态数据
if (KeFu.config.slider_images.length > 0) {
var SlideLi = '' +
KeFu.buildSlideLi(KeFu.config.slider_images.length);
var slider_inner = '
';
for (var i = 0; i < KeFu.config.slider_images.length; i++) {
slider_inner += KeFu.buildSlide(i, KeFu.config.slider_images[i]);
}
slider_inner += '
';
$('#kefu_chat_slide_f').html(SlideLi + slider_inner);
$('#kefu_chat_slide_f').fadeIn();
$('#kefu_chat_slide').carousel({
interval: 3000
})
}
if (KeFu.config.chat_introduces) {
$('.KeFu .modal-body .kefu-right .chat_introduces').html(KeFu.config.chat_introduces);
} else {
$('.KeFu .modal-body .kefu-right .chat_introduces').fadeOut();
}
if (KeFu.config.announcement) {
$('.KeFu .modal-body .kefu-left .announcement #announcement').html(KeFu.config.announcement);
} else {
$('.KeFu .modal-body .kefu-left .announcement').fadeOut();
$('.KeFu .modal-body .kefu-left .chat').height('calc(100% - 110px)');
}
} else {
// 找到当前会话,去掉红点标记(直接重载当前会话)
if (KeFu.session_id) {
// 聊天记录的请求
var load_message = {
c: 'Message',
a: 'chatRecord',
data: {
session_id: KeFu.session_id,
page: 1
}
};
KeFu.ws_send(load_message);
// 清理红点
var session = $("#session_panel [data-session='" + KeFu.session_id + "']");
session.children(".session_info_item").children(".unread_msg_count").eq(0).fadeOut();
}
}
let send_tis_key = parseInt(KeFu.config.send_message_key) == 1 ? 'Enter' : 'Ctrl+Enter';
KeFu.edit_send_tis('按下' + send_tis_key + '发送消息', '按下' + (send_tis_key == 'Enter' ? 'Ctrl+Enter' : 'Enter') + '换行');
} else {
$('#KeFuModal').modal('hide');
}
},
bulidInviteBox: function () {
if (!KeFu.window_is_show && !KeFu.csr) {
var el = '';
$("body").append(el);
}
if (parseInt(KeFu.config.only_first_invitation) == 1) {
localStorage.setItem('kefu_auto_invitation', true);
}
$(document).on('click', '.invite_box_close,.kefu_invite_box .later', function () {
$('.kefu_invite_box').fadeOut();
});
},
bulidChat: function (window_html) {
$("body").append(window_html);
// 初始化 popover
$('#kefu_button').popover({
trigger: 'manual',
template: '',
container: '.KeFu'
});
if (KeFu.browserType() == "FF") {
$('#kefu_message').attr('contenteditable', true);
}
// 初始化文件md5库,该库已修改为支持getScript
if (KeFu.config.upload.storage != 'local') {
$.getScript(KeFu.buildUrl(KeFu.url, KeFu.config.modulename, 'spark'), function () {
// 更新云存储multipart
$(document).on('click', '#chatfile', function () {
var user_initialize = {
c: 'Message',
a: 'getUploadMultipart'
};
KeFu.ws_send(user_initialize);
});
KeFu.getFileMd5 = function (file, cb) {
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
chunkSize = 2097152,
chunks = Math.ceil(file.size / chunkSize),
currentChunk = 0,
spark = new $.fn.SparkMD5.ArrayBuffer(),
fileReader = new FileReader();
fileReader.onload = function (e) {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
cb && cb(spark.end());
}
};
fileReader.onerror = function () {
layer.msg('文件读取错误,请重试!');
};
function loadNext() {
var start = currentChunk * chunkSize,
end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
loadNext();
}
});
}
// 初始化图片粘贴/拖拽上传
$.getScript(KeFu.buildUrl(KeFu.url, KeFu.config.modulename, 'pasteupload.js'), function () {
var upload_msg_index = 0;
$.fn.pasteText = function (text) {
// $('#kefu_message').append(text);
upload_msg_index = layer.msg('正在上传图片...', {'time': 0});
};
$.fn.insertToTextArea = function (filename, url) {
var options = $(this).data("pu-options") || $.fn.pasteUploadImage.defaults;
var img_node = document.createElement('img');
img_node.src = url;
img_node.className = 'record';
KeFu.insertToMessage(img_node);
layer.close(upload_msg_index)
};
//粘贴上传图片
$.fn.pasteUploadImage.defaults = $.extend(true, $.fn.pasteUploadImage.defaults, {
fileName: "file",
appendMimetype: false,
uploadingText: '上传中...',
ajaxOptions: {
url: KeFu.config.upload.uploadurl,
beforeSend: function (jqXHR, settings) {
$.each(KeFu.config.upload.multipart, function (i, j) {
settings.data.append(i, j);
});
return true;
}
},
success: function (data, filename, file) {
var ret = KeFu.onUploadResponse(data);
var url = KeFu.config.upload.cdnurl + ret.data.url;
$(this).insertToTextArea(filename, url);
// 发送notify请求
if (KeFu.config.upload.storage != 'local') {
KeFu.getFileMd5(file, function (md5) {
var ajax_data = {
size: file.size,
name: file.name,
md5: md5,
type: file.type,
url: ret.data.url
};
for (let i in KeFu.config.upload.multipart) {
ajax_data[i] = KeFu.config.upload.multipart[i];
}
$.ajax({
url: KeFu.buildUrl(KeFu.url, KeFu.config.upload.storage, 'storage_notify'),
type: 'POST',
data: ajax_data
});
})
}
return false;
},
error: function (data, filename, file) {
console.log(data, filename, file);
layer.close(upload_msg_index)
layer.msg('图片上传失败,请重试~');
}
});
$('#kefu_message').pasteUploadImage();
});
},
buildPrompt: function (data, page) {
if (page == 1) {
$('#kefu_scroll').append('' + data + '
');
} else {
$('#kefu_scroll').prepend('' + data + '
');
}
},
onUploadResponse: function (response) {
try {
var ret = typeof response === 'object' ? response : JSON.parse(response);
if (!ret.hasOwnProperty('code')) {
$.extend(ret, {code: -2, msg: response, data: null});
}
} catch (e) {
var ret = {code: -1, msg: e.message, data: null};
}
return ret;
},
changeSession: function (session_id, why = 'session') {
if (KeFu.config.modulename != 'admin') {
return;
}
// 找到这个会话
var element = $("#session_panel [data-session='" + session_id + "']");
if (element.length == 0) {
KeFu.session_id = 0;
$('#session_user_name').html('无会话');
return;
}
// 取消所有选择
$('.person').removeClass("active");
element.addClass("active");
// 隐藏表情和快捷回复面板
KeFu.hide_tool_panel();
if ($('.KeFu .modal-body .kefu-left').css('display') != 'none') {
$('#kefu_message').focus();
}
// 该对话所在分组是否展开
let group = element.data('group');
if (group == 'invitation' && !KeFu.group_show.invitation) {
$('#heading_invitation a').click();
} else if (group == 'dialogue' && !KeFu.group_show.dialogue) {
$('#heading_dialogue a').click();
} else if (group == 'recently' && !KeFu.group_show.recently) {
$('#heading_recently a').click();
}
// 记录会话用户
KeFu.session_user = element.data('session_user');
KeFu.session_id = session_id;
if (element.data('group') == 'invitation' || why == 'trajectory') {
// 加载轨迹记录
var load_log = {
c: 'Message',
a: 'trajectory',
data: {
session_user: KeFu.session_user,
page: 1
}
};
// 打开轨迹视图
KeFu.toggle_window_view('kefu_trajectory');
} else {
// 打开聊天记录视图
KeFu.toggle_window_view('kefu_scroll');
// 清理红点
element.children(".session_info_item").children(".unread_msg_count").eq(0).fadeOut();
// 聊天记录的请求
var load_log = {
c: 'Message',
a: 'chatRecord',
data: {
session_id: session_id,
page: 1
}
};
}
if (KeFu.window_is_show) {
KeFu.ws_send(load_log);
} else {
KeFu.window_show_event = function () {
KeFu.ws_send(load_log);
}
}
},
buildSession: function (item, group) {
var element_id = '#session_list_' + group;
if ($("#session_panel [data-session='" + item.id + "']").length) {
// 去掉该会话再添加最新的
$("#session_panel [data-session='" + item.id + "']").remove();
}
$(element_id).prepend(
'' +
'
' +
'' +
'' + item.nickname + '' +
'' + item.last_time + '' +
'
\
' +
'[离线]' + item.last_message + '' +
(item.unread_msg_count ? '' + item.unread_msg_count + '' : '') +
'
' +
''
);
KeFu.group_session_is_none(group);
},
build_trajectory: function (data, page, build_way, pos = 'left') {
if (build_way == 'log') {
const log_data = new Map([
[0, ['访问', data.note + '访问页面:' + data.url + '
来路:' + data.referrer]],
[1, ['被邀请', '']],
[2, ['开始对话', '']],
[3, ['拒绝对话', '']],
[4, ['客服分配', '']],
[5, ['用户离开', '用户的workerman链接已断开']],
[6, ['留言', '点击查看留言']],
[7, ['其他', '']],
[8, ['转移会话', '']],
['default', ['未知', '']],
])
var log = log_data.get(parseInt(data.log_type)) || log_data.get('default');
var element = '\
\
\
' + data.createtime + '
\
\
\
' + (log[1] ? log[1] : data.note) + '
\
\
\
\
';
} else {
var element = ' ' + data + ' ';
}
if (page == 1) {
$('#kefu_trajectory_log').append(element);
} else {
$('#kefu_trajectory_log').prepend(element);
}
},
buildRecord: function (data, page, message_id = 'none') {
var message = '';
if (data.message_type == 1) {
message = KeFu.buildChatImg(data.message, '聊天图片', 'record');
} else if (data.message_type == 2) {
var file_name = data.message.split('.');
var file_suffix = file_name[file_name.length - 1];
message = KeFu.buildChatA(data.message, '点击下载 ' + file_suffix + ' 文件', 'record');
} else if (data.message_type == 3) {
KeFu.buildPrompt(data.message, page);
return;
} else if (data.message_type == 4 || data.message_type == 5) {
message = KeFu.buildChatCard(data.message, data.message_type);
} else {
message = data.message;
}
var status_html = '';
if (data.sender == 'me') {
if (message_id == 'none') {
message_id = data.id;
var msg_status = parseInt(data.status);
status_html = '' + (msg_status == 0 ? '未读' : '已读') + '';
} else {
status_html = '';
}
}
if (page == 1) {
$('#kefu_scroll').append('' + message + status_html + '
');
} else {
$('#kefu_scroll').prepend('' + message + status_html + '
');
}
},
/**
* 构建商品或订单卡片
*/
buildChatCard: function (message, message_type) {
var message = message.split('#');
var message_arr = [];
for (let i in message) {
let message_temp = message[i].split('=');
if (typeof message_temp[1] != 'undefined') {
message_arr[message_temp[0]] = message_temp[1];
}
}
var card_url = (KeFu.config.modulename == 'admin') ? "javascript:layer.msg('卡片未启用,请检查窗口工具管理');" : 'javascript:;';
var a_class_name = 'btn-addtabs';
if (message_type == 4 && KeFu.config.toolbar.goods && KeFu.config.modulename == 'admin') {
card_url = KeFu.config.toolbar.goods.card_url + '?ref=addtabs&id=' + message_arr['id'];
} else if (message_type == 5 && KeFu.config.toolbar.order && KeFu.config.modulename == 'admin') {
card_url = KeFu.config.toolbar.order.card_url + '?ref=addtabs&id=' + message_arr['id'];
} else {
a_class_name = '';
}
return '\n' +
' \n' +
'

\n' +
'
\n' +
'
' + message_arr['subject'] + '
\n' +
(message_arr['note'] ? '
' + message_arr['note'] + '
\n' : '') +
'
\n' +
(message_arr['price'] ? '¥' + message_arr['price'] + '\n' : '') +
(message_arr['number'] ? 'x' + message_arr['number'] + '\n' : '') +
'
\n' +
'
\n' +
'
\n' +
' ';
},
buildChatA: function (url, title, class_name) {
return '' + title + '';
},
buildChatImg: function (filename, facename, class_name = 'emoji') {
return '
';
},
buildSlideLi: function (count) {
var slider_li_el = '';
for (var i = 0; i < count; i++) {
slider_li_el += '';
}
return slider_li_el += '
';
},
buildSlide: function (index, img_scr) {
return '\
\

\
';
},
/**
* 构建各种Url,拼接参数
*/
buildUrl: function (url, modulename, type = 'ws', wsport = 1818) {
var protocol = window.location.protocol + '//';
var port = window.location.port;
port = port ? ':' + port : '';
// 用户的身份通过 KeFu.config.kefu_token 来识别
var token = KeFu.token_list.kefu_token ? '&token=' + KeFu.token_list.kefu_token : '';
// 游客的token
var kefu_tourists_token = localStorage.getItem('kefu_tourists_token');
kefu_tourists_token = kefu_tourists_token ? '&kefu_tourists_token=' + kefu_tourists_token : '';
var goods_and_order = () => {
var data_api_url = KeFu.config.toolbar[type].data_api;
var reg = new RegExp("(^https?:\/\/)", "i");
if (data_api_url.search(reg) === -1) {
return protocol + url + port + data_api_url + '?modulename=' + modulename + token;
} else {
return data_api_url + '?modulename=' + modulename + token;
}
}
var buildFun = new Map([
['ws', () => {
protocol = parseInt(KeFu.config.wss_switch) == 1 ? 'wss://' : 'ws://';
return protocol + url + ':' + wsport + '?modulename=' +
modulename + token + kefu_tourists_token;
}],
['initialize', () => {
return protocol + url + port + '/addons/kefu/index/initialize?modulename=' +
modulename + '&referrer=' + document.referrer + kefu_tourists_token;
}],
['upload', () => {
return KeFu.config.upload.uploadurl + '?modulename=' + modulename + kefu_tourists_token;
}],
['spark', () => {
if (KeFu.config.__CDN__) {
return KeFu.config.__CDN__ + '/assets/addons/kefu/js/spark.js';
}
return protocol + url + port + '/assets/addons/kefu/js/spark.js';
}],
['storage_notify', () => {
return protocol + url + port + '/addons/' + modulename + '/index/notify';
}],
['load_message_prompt', () => {
if (KeFu.config.upload.cdnurl) {
return KeFu.config.upload.cdnurl + KeFu.config.ringing;
}
return protocol + url + port + '/addons/kefu/index/loadMessagePrompt?modulename=' +
modulename + kefu_tourists_token;
}],
['pasteupload.js', () => {
if (KeFu.config.__CDN__) {
return KeFu.config.__CDN__ + '/assets/addons/kefu/js/jquery.pasteupload.js';
}
return protocol + url + port + '/assets/addons/kefu/js/jquery.pasteupload.js';
}],
['mobile', () => {
return protocol + url + port + '/addons/kefu/index/mobile?fixed_csr=' + KeFu.fixed_csr;
}],
['goods', goods_and_order],
['order', goods_and_order],
['default', () => {
return protocol + url + port
}]
]);
let action = buildFun.get(type) || buildFun.get('default')
return action.call(this);
},
edit_online_status: function (user_id, status) {
var element = $("#session_panel [data-session_user='" + user_id + "']");
if (status) {
$(element).children(".person_avatar").removeClass("person_head_gray");
element.children(".session_info_item").find(".session_user_status").eq(0).fadeOut();
} else {
$(element).children(".person_avatar").addClass("person_head_gray");
element.children(".session_info_item").find(".session_user_status").eq(0).fadeIn();
}
},
disableSelection: function (target) {
if (typeof target.onselectstart != "undefined") {
target.onselectstart = function () {
return false
};
} else if (typeof target.style.MozUserSelect != "undefined") {
target.style.MozUserSelect = "none";
} else {
target.οnmοusedοwn = function () {
return false;
}
target.style.cursor = "default";
}
},
sendMessage: function (message, message_type) {
// 检查 websocket 是否连接
if (!KeFu.ws.SocketTask || KeFu.ws.SocketTask.readyState != 1) {
layer.msg('网络链接异常,请刷新重试~');
return;
}
if (typeof KeFu.session_id == 'string' && KeFu.session_id.indexOf('invitation') !== -1) {
layer.msg('该访客还未接受会话请求哦~');
return;
}
if (!KeFu.session_id) {
layer.msg('请选择一个会话~');
return;
}
var message_id = new Date().getTime() + KeFu.session_id + Math.floor(Math.random() * 10000);
var load_message = {
c: 'Message',
a: 'sendMessage',
data: {
message: message,
message_type: message_type,
session_id: KeFu.session_id,
token: KeFu.token_list.kefu_token ? KeFu.token_list.kefu_token : '', // 发消息时检测用户登录态是否过期
modulename: KeFu.config.modulename,
message_id: message_id
}
};
KeFu.ws_send(load_message);
var data = {
sender: 'me',
message: (message_type == 1 || message_type == 2) ? KeFu.config.upload.cdnurl + message : message,
message_type: message_type
}
KeFu.buildRecord(data, 1, message_id);
if (message_type == 1) {
message = '[图片]';
} else if (message_type == 2) {
message = '[链接]';
} else {
message = message.replace(/
/g, "[图片]");
$('#kefu_message').html('');
}
if (KeFu.config.modulename == 'admin') {
// 修改该会话的最后消息
let session = $("#session_panel [data-session='" + KeFu.session_id + "']");
session.children(".session_info_item").children(".time").eq(0).html(KeFu.get_format_session_time());
session.children(".session_info_item").find(".last_message").eq(0).html(message);
// 移动会话到会话中的第一位
let first_session = $('#session_list_dialogue li');
if (first_session.length) {
// 分组中已有对话
first_session.eq(0).before(session);
} else {
// 分组中没有对话
$('#session_list_dialogue').prepend(session);
// 清理没有会话的提示文字
KeFu.group_session_is_none('dialogue');
}
// 展开分组
if (!KeFu.group_show.dialogue) {
$('#heading_dialogue a').click();
}
if ($('#kefu_scroll').children('.status').children('span').eq(0).html() == '还没有消息') {
$('#kefu_scroll').children('.status').children('span').eq(0).html(KeFu.get_format_session_time());
}
}
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
},
playSound: function () {
KeFu.audio.source = KeFu.audio.context.createBufferSource();
KeFu.audio.source.buffer = KeFu.audio.buffer;
KeFu.audio.source.loop = false;
KeFu.audio.source.connect(KeFu.audio.context.destination);
KeFu.audio.source.start(0); //立即播放
},
loadAudioFile: function (url) {
var xhr = new XMLHttpRequest(); //通过XHR下载音频文件
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) { //下载完成
KeFu.audio.context.decodeAudioData(this.response,
function (buffer) { //解码成功时的回调函数
KeFu.audio.buffer = buffer;
KeFu.playSound();
},
function (e) { //解码出错时的回调函数
console.log('音频解码失败', e);
});
};
xhr.send();
},
new_message_prompt: function (event) {
if (KeFu.config.is_shake) {
$(event).addClass('kefu-shake-horizontal');
setTimeout(function () {
$(event).removeClass('kefu-shake-horizontal');
}, 400);
}
if (KeFu.audio.buffer) {
KeFu.playSound();
} else {
let url = KeFu.buildUrl(KeFu.url, 'index', 'load_message_prompt');
KeFu.loadAudioFile(url);
}
},
kefu_blacklist: function (code, session_user, blacklist = null) {
// 修改用户黑名单状态
// code:1=屏蔽成功,2=解除屏蔽成功,3=通过 blacklist 判断屏蔽状态
if (code == 3) {
$('#kefu_blacklist').html(blacklist ? '取消拉黑' : '拉黑名单');
return;
}
if (session_user == KeFu.session_user) {
if (code == 1) {
$('#kefu_blacklist').html('取消拉黑');
} else if (code == 2) {
$('#kefu_blacklist').html('拉黑名单');
}
}
},
// 处理分组的没有会话提示
group_session_is_none: function (group) {
var element_id = '#session_list_' + group;
if ($(element_id + ' li').length) {
$(element_id).children('.none_session').fadeOut();
} else {
$(element_id).children('.none_session').fadeIn();
KeFu.session_group_red_dot(group, false);
}
},
// 移动光标到最未
po_last: function () {
var obj = $('#kefu_message')[0];
if (window.getSelection) {//ie11 10 9 ff safari
obj.focus(); //解决ff不获取焦点无法定位问题
var range = window.getSelection();//创建range
range.selectAllChildren(obj);//range 选择obj下所有子内容
range.collapseToEnd();//光标移至最后
} else if (document.selection) {//ie10 9 8 7 6 5
var range = document.selection.createRange();//创建选择对象
// var range = document.body.createTextRange();
range.moveToElementText(obj);//range定位到obj
range.collapse(false);//光标移至最后
range.select();
}
},
// 光标位置插入元素
insertToMessage: function (obj) {
// 获取编辑框对象
var Message = $('#kefu_message')[0]
// 编辑框设置焦点
Message.focus();
// 获取选定对象
var selection = getSelection()
// 判断是否有最后光标对象存在
// 获取包含当前节点的文档片段
var range = selection.getRangeAt(0)
// 将创建的文档片段插入到光标处
range.insertNode(obj)
// 光标对象的范围界定为新建的节点
// range.selectNodeContents(obj)
// 光标位置定位在节点的最大长度
// range.setStart(obj, obj.length||1)
// 使光标开始和光标结束重叠
range.collapse(false)
// 清除选定对象的所有光标对象
// selection.removeAllRanges()
// 插入新的光标对象
// selection.addRange(range)
},
/*
* 隐藏菜单工具面板
*/
hide_tool_panel: function (show_id = '') {
var tool_panel_action = {
'none': () => {
$('#kefu_link_form,#kefu_fast_reply_list,#kefu_emoji,#goods_select_model').hide();
},
'kefu_link_form': () => {
$('#kefu_fast_reply_list,#kefu_emoji,#goods_select_model').hide();
},
'kefu_fast_reply_list': () => {
$('#kefu_link_form,#kefu_emoji,#goods_select_model').hide();
},
'kefu_emoji': () => {
$('#kefu_link_form,#kefu_fast_reply_list,#goods_select_model').hide();
},
'goods_select_model': () => {
$('#kefu_link_form,#kefu_fast_reply_list,#kefu_emoji').hide();
}
}
var action = tool_panel_action[show_id] || tool_panel_action['none'];
action.call(this);
},
/*
* 统一注册事件
*/
eventReg: function () {
// 点击商品或订单卡片关闭会话窗口
$(document).on('click', '.KeFu .chat .bubble .record_card', function () {
if ($(this).parent().hasClass('btn-addtabs')) {
$('#KeFuModal').modal('hide');
}
})
// 提交留言
$(document).on('click', '#kefu_leave_message form button', function (event) {
var form_data = {};
var t = $('#kefu_leave_message form').serializeArray();
$.each(t, function () {
form_data[this.name] = this.value;
});
if (!form_data['contact']) {
layer.msg('联系方式不能为空哦~');
return false;
}
var leave_message = {
c: 'Message',
a: 'leaveMessage',
data: form_data
};
KeFu.ws_send(leave_message);
return false;
});
// 窗口大小变化时,隐藏按钮提示
$(window).on('resize', function (e) {
if (KeFu.resize_load <= 2) {
console.log('窗口大小发生变化,已恢复按钮至初始位置')
$("#kefu_button").css({
"top": '80%',
"left": 'unset'
});
KeFu.toggle_popover('hide');
}
KeFu.resize_load += 1;
});
// 用户名片保存按钮
$(document).on('click', '#kefu_user_card form button', function (event) {
if (!KeFu.session_user) {
layer.msg('用户找不到啦~');
return;
}
var form_data = {};
var t = $('#kefu_user_card form').serializeArray();
$.each(t, function () {
form_data[this.name] = this.value;
});
let user_card_done = {
c: 'Message',
a: 'userCard',
data: {
session_user: KeFu.session_user,
form_data: form_data,
action: 'done'
}
};
KeFu.ws_send(user_card_done);
return false;
});
// 点击轻提示和KeFu悬浮球的事件
$(document).on('click', '#kefu_button,.kefu_invite_box .consulting,.kefu_popover', function () {
if (KeFu.config.modulename == 'admin' && $(this).hasClass('kefu_popover')) {
// 打开最后发送消息的用户的会话窗口
if (KeFu.last_sender && parseInt(KeFu.last_sender) !== KeFu.session_id) {
KeFu.changeSession(KeFu.last_sender);
}
}
if (!KeFu.clickkefu_button) {
KeFu.toggle_window('show');
}
});
$(document).on('click', '.bubble img', function (e) {
var img_obj = $(e.target);
if (img_obj.hasClass('emoji')) {
return;
}
img_obj = img_obj[0];
KeFu.allowed_close_window = false;// 按下ecs不允许关闭会话窗口
layer.photos({
photos: {
"title": "聊天图片预览",
"id": "record",
data: [
{
"src": img_obj.src
}
]
},
end: function () {
// 图片预览已关闭
KeFu.allowed_close_window = true;
}, anim: 5 //0-6的选择,指定弹出图片动画类型,默认随机(请注意,3.0之前的版本用shift参数)
});
});
// 按键监听
$(document).on('keyup', function (event) {
// console.log('当前按钮的code:', event.keyCode);
// 对打开会话窗口的监听
// 打开会话窗口快捷键[ctrl + /],若需修改,请拿到对应键的keyCode替换下一行的191即可,191代表[/]键的keyCode
if (event.keyCode == 191 && event.ctrlKey) {
if (KeFu.last_sender) {
if (parseInt(KeFu.last_sender) === KeFu.session_id) {
// 展开分组
if (!KeFu.group_show.dialogue) {
$('#heading_dialogue a').click();
}
}
KeFu.changeSession(KeFu.last_sender.toString());
KeFu.last_sender = null;
} else if (KeFu.window_is_show) {
KeFu.toggle_window('hide');
}
// 需先切换会话再打开窗口
if (!KeFu.window_is_show) {
KeFu.toggle_window('show');
}
return;
}
// 对ecs键的监听
else if (event.keyCode == 27 && KeFu.window_is_show) {
if (parseInt(KeFu.config.ecs_exit) == 1 && KeFu.allowed_close_window) {
$('#KeFuModal').modal('hide');
} else {
layer.closeAll();
}
}
});
// 拖动悬浮球的事件
$(document).on('mousedown', '#kefu_button', function (e) {
KeFu.toggle_popover('hide');
KeFu.clickkefu_button = false;
document.onselectstart = function () {
return false;
};//解决拖动会选中文字的问题
document.ondragstart = function () {
return false;
};
$(document).find("iframe").css("pointer-events", "none");
KeFu.fast_move = true;
KeFu.fast_x = e.pageX - parseInt($("#kefu_button").css("left"));
KeFu.fast_y = e.pageY - parseInt($("#kefu_button").css("top"));
$(document).on('mousemove', function (e) {
if (KeFu.fast_move) {
var x = e.pageX - KeFu.fast_x;
var y = e.pageY - KeFu.fast_y;
if (Math.abs(parseInt($("#kefu_button").css("left")) - x) + Math.abs(parseInt($("#kefu_button").css("top")) - y) > 7) {
KeFu.clickkefu_button = true;
}
// 保存按钮位置
var kefu_button_coordinate = [y, x];
localStorage.setItem("kefu_button_coordinate", kefu_button_coordinate);
$("#kefu_button").css({"top": y, "left": x});
}
}).mouseup(function () {
document.onselectstart = null;
document.ondragstart = null;
$(document).find("iframe").css("pointer-events", "auto");
KeFu.fast_move = false;
});
});
// 展开分组
$(document).on('show.bs.collapse', '.dialogue_panel,.invitation_panel,.recently_panel', function (e) {
if ($(e.currentTarget).hasClass('dialogue_panel')) {
KeFu.group_show.dialogue = true;
KeFu.session_group_red_dot('dialogue', false);
$('.dialogue_panel').on('hide.bs.collapse', function () {
KeFu.group_show.dialogue = false;
});
} else if ($(e.currentTarget).hasClass('invitation_panel')) {
KeFu.group_show.invitation = true;
KeFu.session_group_red_dot('invitation', false);
$('.invitation_panel').on('hide.bs.collapse', function () {
KeFu.group_show.invitation = false;
});
} else if ($(e.currentTarget).hasClass('recently_panel')) {
KeFu.group_show.recently = true;
KeFu.session_group_red_dot('recently', false);
$('.recently_panel').on('hide.bs.collapse', function () {
KeFu.group_show.recently = false;
});
}
});
// 客服代表改变状态
$(document).on('click', '#kefu_csr_status ul li', function (e) {
var load_message = {
c: 'Message',
a: 'csrChangeStatus',
data: {
status: $(e.target).data('status')
}
};
KeFu.ws_send(load_message);
});
// 隐藏窗口时
$(document).on('hidden.bs.modal', '#KeFuModal', function (e) {
$('#kefu_button').fadeIn();
KeFu.window_is_show = false;
});
// 显示窗口时
$(document).on('shown.bs.modal', '#KeFuModal', function (e) {
KeFu.window_is_show = true;
$('#kefu_scroll').scrollTop($('#kefu_scroll')[0].scrollHeight);
if (!localStorage.getItem('kefu_new_user')) {
localStorage.setItem('kefu_new_user', true);
}
if (typeof KeFu.window_show_event == 'function') {
KeFu.window_show_event();
KeFu.window_show_event = null;
}
});
// 显示商品和订单选择面板
$(document).on('click', '.write_top .goods,.write_top .order', function (e) {
var panel_name = $(e.target).hasClass('goods') ? 'goods' : 'order';
KeFu.hide_tool_panel('goods_select_model');
if ($('#goods_select_model').css('display') == 'block') {
$('#goods_select_model').fadeOut();
return;
} else {
$('#goods_select_model').fadeIn();
}
var api_url = KeFu.buildUrl(KeFu.url, 'index', panel_name);
var index = layer.load(0, {shade: false});
$.ajax(api_url, {
success: res => {
if (res.code == 1) {
$('#goods_select_model .project_list').html('');
for (let i in res.data) {
var input_value = '';
for (let y in res.data[i]) {
input_value += y + '=' + res.data[i][y] + '#';
}
let project_item = '';
$('#goods_select_model .project_list').append(project_item);
}
} else {
layer.msg(res.msg)
}
},
error: res => {
layer.msg('加载失败,请重试~');
},
complete: res => {
layer.close(index)
}
});
});
// 选择订单或商品
$(document).on('click', '.KeFu .modal-body #goods_select_model input', function (e) {
KeFu.sendMessage($(e.target).val(), (e.target.name == 'goods') ? 4 : 5);
$('#goods_select_model').hide();
KeFu.po_last();
})
// 显示表情选择面板
$(document).on('click', '.write_top .smiley', function (e) {
KeFu.hide_tool_panel('kefu_emoji');
$('#kefu_emoji').fadeToggle();
// 获取焦点
KeFu.po_last();
});
// 显示输入链接面板
$(document).on('click', '.write_top .link,#kefu_link_form .btn-default', function (e) {
KeFu.hide_tool_panel('kefu_link_form');
$('#kefu_link_form').fadeToggle();
$('#kefu_link_form_url').focus().select();
});
// 确认链接
$(document).on('click', '#kefu_link_form .btn-success', function (e) {
var kefu_link_form_ins = $('#kefu_link_form_ins').val()
var kefu_link_form_url = $('#kefu_link_form_url').val()
kefu_link_form_ins = kefu_link_form_ins ? kefu_link_form_ins : kefu_link_form_url;
$('#kefu_link_form').fadeOut();
$('#kefu_message').append(KeFu.buildChatA(kefu_link_form_url, kefu_link_form_ins, 'link'));
KeFu.po_last();
});
// 选择表情
$(document).on('click', '#kefu_emoji img', function (e) {
$('#kefu_message').append($(e.target).clone());
$('#kefu_emoji').fadeOut();
KeFu.po_last()
});
// 用户点击聊天记录窗口,隐藏所有工具面板
$(document).on('click', '#kefu_scroll', function () {
KeFu.hide_tool_panel();
});
// 用户选择了文件
$(document).on('change', '#chatfile', function (e) {
var file = $('#chatfile')[0].files[0];
if (!file) {
return;
}
KeFu.hide_tool_panel();
// 上传文件
var formData = new FormData();
formData.append("file", file);
if (KeFu.config.upload.multipart) {
for (let i in KeFu.config.upload.multipart) {
formData.append(i, KeFu.config.upload.multipart[i]);
}
}
$.ajax({
url: KeFu.config.upload.uploadurl,
type: 'post',
data: formData,
contentType: false,
processData: false,
success: function (res) {
if (res.code == 1) {
// 发送notify请求
if (KeFu.config.upload.storage != 'local') {
KeFu.getFileMd5(file, function (md5) {
var ajax_data = {
size: file.size,
name: file.name,
md5: md5,
type: file.type,
url: res.data.url
};
for (let i in KeFu.config.upload.multipart) {
ajax_data[i] = KeFu.config.upload.multipart[i];
}
$.ajax({
url: KeFu.buildUrl(KeFu.url, KeFu.config.upload.storage, 'storage_notify'),
type: 'POST',
data: ajax_data
});
})
}
var file_name = res.data.url.split('.');
var file_suffix = file_name[file_name.length - 1];
if (file_suffix == 'png' ||
file_suffix == 'jpg' ||
file_suffix == 'gif' ||
file_suffix == 'jpeg') {
KeFu.sendMessage(res.data.url, 1);
} else {
KeFu.sendMessage(res.data.url, 2);
}
} else {
layer.msg(res.msg);
}
},
error: function (e) {
layer.msg('文件上传失败,请重试!');
},
complete: function () {
$('#chatfile').val('');
}
})
});
// 禁止回车键换行
$(document).on('keypress', '#kefu_message', function (event) {
if (parseInt(KeFu.config.send_message_key) == 1 && event.keyCode == "13" && !event.ctrlKey) {
event.preventDefault()
}
});
if (KeFu.browserType() == "FF") {
// 过滤输入框中的html标签
$(document).on('paste', '#kefu_message', function (e) {
setTimeout(function () {
var message = $(e.target).html();
$(e.target).html(message.replace("/<(?!img|div).*?>/g", ''));
KeFu.po_last();
}, 100);
});
}
// 按键发送消息监听
$(document).on('keyup', '#kefu_message', function (event) {
var message = $(event.currentTarget).html();
if (parseInt(KeFu.config.send_message_key) == 1 && event.keyCode == "13" && !event.ctrlKey) {
if (message) {
KeFu.sendMessage(message, 0);
}
} else if (parseInt(KeFu.config.send_message_key) == 0 && event.keyCode == "13" && event.ctrlKey) {
if (message) {
KeFu.sendMessage(message, 0);
}
} else if (parseInt(KeFu.config.send_message_key) == 1 && event.keyCode == "13" && event.ctrlKey) {
// Enter发送消息时,用户按下了ctrl+Enter
if (KeFu.browserType() == "IE" || KeFu.browserType() == "Edge") {
$(event.currentTarget).html(message + "");
} else if (KeFu.browserType() == "FF") {
$(event.currentTarget).html(message + "
");
} else {
$(event.currentTarget).html(message + "
");
}
// 获得焦点-光标挪到最后
KeFu.po_last()
}
event.preventDefault()
});
// 切换会话
$(document).on('click', '#session_panel li,#session_list_search li', function (e) {
if ($('.KeFu .modal-body .kefu-right').css('display') == 'none') {
$('.KeFu .modal-body .kefu-right').fadeIn();
$('.KeFu .modal-body .kefu-left').fadeOut();
}
KeFu.changeSession($(e.currentTarget).data('session'));
if ($(e.currentTarget).data('group') == 'search') {
$('#session_list_search').fadeOut();
}
});
// 手机版聊天窗口兼容
$(document).on('hide.bs.modal', '#KeFuModal', function (e) {
if ($('.KeFu .modal-body .kefu-left').css('display') == 'none') {
$('.KeFu .modal-body .kefu-left').fadeIn();
$('.KeFu .modal-body .kefu-right').fadeOut();
return false;
}
});
// 显示轨迹
$(document).on('click', '#kefu_view_trajectory', function (e) {
if (!KeFu.session_id) {
layer.msg('请选择会话~');
return;
}
KeFu.changeSession(KeFu.session_id, 'trajectory');
});
// 显示用户名片
$(document).on('click', '#kefu_view_user_card', function (e) {
if (!KeFu.session_user) {
layer.msg('请选择会话~');
return;
}
// 加载用户名片
KeFu.toggle_window_view('kefu_user_card');
var kefu_blacklist = {
c: 'Message',
a: 'userCard',
data: {
session_user: KeFu.session_user
}
};
KeFu.ws_send(kefu_blacklist);
});
// 拉黑名单
$(document).on('click', '#kefu_blacklist', function () {
if (!KeFu.session_user) {
layer.msg('请选择会话~');
return;
}
var kefu_blacklist = {
c: 'Message',
a: 'blacklist',
data: {
session_user: KeFu.session_user
}
};
KeFu.ws_send(kefu_blacklist);
});
// 加载更多聊天记录和轨迹
document.addEventListener('scroll', function (event) {
if ($(event.target).scrollTop() == 0 && KeFu.chat_record_page != 'done') {
if (event.target.id == 'kefu_scroll') {
if (!KeFu.session_id) {
return;
}
// 加载历史聊天记录
var load_message = {
c: 'Message',
a: 'chatRecord',
data: {
session_id: KeFu.session_id,
page: KeFu.chat_record_page
}
};
KeFu.record_scroll_height = $('#kefu_scroll')[0].scrollHeight;
KeFu.ws_send(load_message);
} else if (event.target.id == 'kefu_trajectory') {
if (!KeFu.session_user) {
return;
}
// 加载轨迹记录
var load_log = {
c: 'Message',
a: 'trajectory',
data: {
session_user: KeFu.session_user,
page: KeFu.chat_record_page
}
};
KeFu.record_scroll_height = $('#kefu_trajectory')[0].scrollHeight;
KeFu.ws_send(load_log);
}
}
}, true);
// 右键菜单
$(document).on('contextmenu', '.person', function (e) {
KeFu.select_session_user = $(e.currentTarget).data('session_user');
var popupmenu = $('#kefu_menu');
popupmenu.fadeOut();
$('.kefu_edit_user_nickname').remove();
$('.kefu_transfer_session').remove();
let l = ($(document).width() - e.clientX) < popupmenu.width() ? (e.clientX - popupmenu.width()) : e.clientX;
let t = ($(document).height() - e.clientY) < popupmenu.height() ? (e.clientY - popupmenu.height()) : e.clientY;
popupmenu.css({left: l, top: t}).fadeIn();
if ($(e.currentTarget).data('group') == 'invitation') {
$('#kefu_menu .invitation').fadeIn();
$('#kefu_menu .transfer').fadeOut();
} else {
$('#kefu_menu .invitation').fadeOut();
$('#kefu_menu .transfer').fadeIn();
}
e.preventDefault();
}).click(function () {
// 菜单的隐藏
$('#kefu_menu').fadeOut();
});
// 会话右键菜单 删除会话 & 邀请对话 & 转接会话 & 修改昵称
$(document).on('click', '.kefu_menu_item', function (e) {
var action = $(e.currentTarget).data('action');
if (KeFu.select_session_user) {
if (action == 'del') {
$("#session_panel [data-session_user='" + KeFu.select_session_user + "']").remove();
}
if (action == 'edit_nickname') {
var session = $("#session_panel [data-session_user='" + KeFu.select_session_user + "']");
var nickname = session.children(".session_info_item").children(".name").eq(0).html();
// 显示修改昵称的操作面板
var tpl = '\
';
session.after(tpl);
$(document).on('click', '#edit_user_nickname_cancel', function (e) {
$('.kefu_edit_user_nickname').remove();
});
$(document).on('click', '#edit_user_nickname_ok', function (e) {
var edit_nickname_user = $('.kefu_edit_user_nickname').data('edit_nickname_user');
var new_nickname = $('#new_nickname').val();
if (edit_nickname_user && new_nickname) {
var action_session = {
c: 'Message',
a: 'actionSession',
data: {
action: 'edit_nickname',
session_user: edit_nickname_user,
new_nickname: new_nickname
}
};
KeFu.ws_send(action_session);
}
$('.kefu_edit_user_nickname').remove();
});
return;
}
var action_session = {
c: 'Message',
a: 'actionSession',
data: {
action: action,
session_user: KeFu.select_session_user
}
};
KeFu.ws_send(action_session);
} else {
layer.msg('会话找不到啦~');
}
});
// 搜索会话
$(document).on('keyup', '#kefu_search_input', function (event) {
if (KeFu.config.modulename != 'admin') {
return;
}
if (event.keyCode == "13") {
var search_key = $('#kefu_search_input').val();
if (search_key.length <= 0) {
// 无搜索词,且预选框已显示,隐藏预选框
if ($('#session_list_search').css('display') != 'none') {
$('#session_list_search').fadeOut();
KeFu.search_select_id = '';
} else {
layer.msg('请输入要查找的用户!');
}
return;
} else {
// 有预选人,选中该会话
if ($('#session_list_search').css('display') != 'none' && KeFu.search_select_id) {
KeFu.changeSession(KeFu.search_select_id);
$('#session_list_search').fadeOut();
KeFu.search_select_id = '';
return;
}
}
var load_message = {
c: 'Message',
a: 'searchUser',
data: search_key
};
KeFu.ws_send(load_message);
} else if (event.keyCode == '38') {
KeFu.search_primary--;
KeFu.setSelectedItem();
} else if (event.keyCode == '40') {
KeFu.search_primary++;
KeFu.setSelectedItem();
}
event.preventDefault();
// 搜索框失去焦点
$(document).on('blur', '#kefu_search_input', function () {
setTimeout(function () {
// 等待点击事件冒泡-防止搜索结果中的蓝色聊天文字不能被点击
$('#session_list_search').fadeOut();
KeFu.search_select_id = 0;
}, 250);
});
});
/*快捷回复面板*/
$(document).on('click', '.kefu_fast_reply', function () {
KeFu.hide_tool_panel('kefu_fast_reply_list');
$('#kefu_fast_reply_list').fadeToggle();
});
/*选择快捷回复*/
$(document).on('click', '.kefu_fast_reply_list tr', function (e) {
var reply_id = $(e.currentTarget).data('id');
var content = KeFu.fast_reply[reply_id].content;
KeFu.sendMessage(content, 0);
KeFu.po_last();
$('#kefu_fast_reply_list').fadeOut();
});
KeFu.messageInputEventReg();
},
messageInputEventReg: function () {
var input_status_display = parseInt(KeFu.config.input_status_display);
if (input_status_display == 0) {
return;
} else if (input_status_display == 2 && KeFu.config.modulename != 'index') {
return;
}
$(document).on('input', '#kefu_message', function (e) {
var kefu_message_input = {
c: 'Message',
a: 'messageInput',
data: {
session_id: KeFu.session_id,
session_user: KeFu.csr || KeFu.session_user,
type: 'input'
}
};
KeFu.ws_send(kefu_message_input);
});
$(document).on('blur', '#kefu_message', function (e) {
var kefu_message_input = {
c: 'Message',
a: 'messageInput',
data: {
session_id: KeFu.session_id,
session_user: KeFu.csr || KeFu.session_user,
type: 'blur'
}
};
KeFu.ws_send(kefu_message_input);
});
},
setSelectedItem: function () {
if (KeFu.search_primary < 0) {
KeFu.search_primary = $('#session_list_search').find('li').length - 1;
} else if (KeFu.search_primary > $('#session_list_search').find('li').length - 1) {
KeFu.search_primary = 0;
}
$('#session_list_search').find('li').removeClass('select_item')
.eq(KeFu.search_primary).addClass('select_item');
// 将预选词放入输入框
$('#kefu_search_input').val($('#session_list_search').find('li').eq(KeFu.search_primary).data('nickname'));
KeFu.search_select_id = $('#session_list_search').find('li').eq(KeFu.search_primary).data('session');
},
browserType: function () {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isOpera = false;
if (userAgent.indexOf('Edge') > -1) {
return "Edge";
}
if (userAgent.indexOf('.NET') > -1) {
return "IE";
}
if (userAgent.indexOf("Opera") > -1 || userAgent.indexOf("OPR") > -1) {
isOpera = true;
return "Opera"
}
; //判断是否Opera浏览器
if (userAgent.indexOf("Firefox") > -1) {
return "FF";
} //判断是否Firefox浏览器
if (userAgent.indexOf("Chrome") > -1) {
return "Chrome";
}
if (userAgent.indexOf("Safari") > -1) {
return "Safari";
} //判断是否Safari浏览器
if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
return "IE";
}
; //判断是否IE浏览器
},
isPc: function () {
var is_touch = !!("ontouchstart" in window);
if (!is_touch) {
return true;
}
var userAgentInfo = navigator.userAgent;
var Agents = [
"Android",
"iPhone",
"SymbianOS",
"Windows Phone",
"iPad",
"iPod"
];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
}