1
0
mirror of https://gitee.com/zhc02/timely_service.git synced 2025-07-24 08:41:43 +08:00
This commit is contained in:
柏尘 2019-10-31 20:13:01 +08:00
parent 2c2aba9cd2
commit dac0ec3afd
10 changed files with 232 additions and 73 deletions

View File

@ -21,6 +21,7 @@ class Kefu extends Base
$this->assign('url',request()->domain().'/index/index/user?kefu_code='.session('kefu_code'));
$this->assign('kefu_name',session('kefu_name'));
$this->assign('kefu_code',session('kefu_code'));
$this->assign('avatar',session('kefu_avatar'));
return $this->fetch();
}
public function getQueue(){

View File

@ -37,6 +37,7 @@ class Login extends Controller
}
session('kefu_name', $kefu_info['kefu_name']);
session('kefu_code', $kefu_info['kefu_code']);
session('kefu_avatar', $kefu_info['kefu_avatar']);
} else {
//同一个ip 限制注册3个账号
$num = Cache::get(request()->ip());
@ -60,6 +61,7 @@ class Login extends Controller
Cache::inc(request()->ip());
session('kefu_name', $kefu_data['kefu_name']);
session('kefu_code', $kefu_data['kefu_code']);
session('kefu_avatar', $kefu_data['kefu_avatar']);
}
@ -68,6 +70,7 @@ class Login extends Controller
public function logout(){
session('kefu_name',null);
session('kefu_code', null);
session('kefu_avatar', null);
return $this->redirect('login/login');
}
}

View File

@ -52,7 +52,7 @@
<i class="ti-comment-alt"></i>
</a>
</li>
<li id="aaa">
<li >
<a data-navigation-target="friends" href="#" class="notifiy_badge" title="历史会话">
<i class="ti-user"></i>
</a>
@ -60,7 +60,7 @@
<li data-navigation-target="favorites" class="brackets">
</li>
<li>
<a href="{:url('login/logout')}">
<a href="{:url('login/logout')}" class="logout">
<i class="ti-power-off" title="退出"></i>
</a>
</li>
@ -170,6 +170,8 @@
<script>
var code ='{$kefu_code}';
var port= '{$port}';
var name ="{$kefu_name}";
var avatar="{$avatar}";
</script>
<script src="/static/demo/js/jquery.min.js"></script>
<script src="/static/common/vendor/popper.min.js"></script>

View File

@ -28,7 +28,6 @@
<button class="btn btn-primary btn-lg btn-block">进入</button>
</form>
</div>
<script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script src="dist/js/soho.min.js"></script>
<script src="/static/demo/js/jquery.min.js"></script>
</body>
</html>

View File

@ -32,9 +32,9 @@ class Event
//设置客服
public static function setKefu($fd, $uid)
{
if(isset( self::$kefu[$uid])){
if (isset(self::$kefu[$uid])) {
self::$kefu[$uid]['fd'] = $fd;
}else{
} else {
self::$kefu[$uid]['fd'] = $fd;
self::$kefu[$uid]['visitor_fds'] = [];
}
@ -62,9 +62,17 @@ class Event
#1更新客服状态
$kefu_code = ltrim($data['uid'], 'KF_');
$info = KefuLogic::setKefuOnlineStatus($kefu_code, $fd);
//设置客服信息
#2.设置客服信息
self::$online[$fd] = $data['uid'];
self::setKefu($fd, $data['uid']);
//正在接管服务
$list = QueueLogic::getQueueing($kefu_code);
if ($list) {
foreach ($list as $item) {
self::$kefu[$data['uid']]['visitor_fds'][$item['visitor_id']] = $item['client_id'];
}
}
QueueLogic::updateQueueingkefuClientid($kefu_code, $fd);
return self::reposon($fd, 200, '客服上线成功', [], 'kefu_online');
} catch (BaseException $e) {
throw new BaseException('客服上线错误', 401);
@ -128,51 +136,55 @@ class Event
'visitor_avatar' => $data['avatar'],
'visitor_ip' => '127.0.0.1',
'client_id' => $fd,
'kefu_code'=>$data['kefu_code'],
'kefu_code' => $data['kefu_code'],
];
try {
Db::startTrans();
$kefu_info = KefuLogic::distributionKefu($visitor);
Log::record('分配客服数据:' . json_encode($kefu_info));
if ($kefu_info['code'] == 200) {
#1.记录服务日志
$logId = VisitorService::addServiceLog([
'visitor_id' => $visitor['visitor_id'],
'client_id' => $fd,
'visitor_name' => $visitor['visitor_name'],
'visitor_avatar' => $visitor['visitor_avatar'],
'visitor_ip' => $visitor['visitor_ip'],
'kefu_id' => $kefu_info['data']['kefu_id'],
'kefu_code' => ltrim($kefu_info['data']['kefu_code'], 'KF_'),
'start_date' => date('Y-m-d H:i:s'),
]);
try {
if ($server->exist((int)$kefu_info['data']['kefu_client_id']) == false) {
Db::rollback();
return self::reposon($fd, 201, '客服不存在或者客服不在线', [], 'visitorToKefu');
}
$kefu_info['data']['log_id'] = $logId;
// 更新队列表
$update['reception_status'] = 1;//更改连接状态
$update['kefu_code'] = ltrim($kefu_info['data']['kefu_code'], 'KF_');
$update['kefu_client_id'] = $kefu_info['data']['kefu_client_id'];
QueueLogic::updateQueueByCusomerID($visitor['visitor_id'], $update);
#3.绑定客服和游客 bengan
self::$visitor[$fd]['bind_kefu_fd'] = $kefu_info['data']['kefu_client_id'];
self::$visitor[$fd]['bind_kefu_code'] =$kefu_info['data']['kefu_code'];
self::$kefu[$kefu_info['data']['kefu_code']]['visitor_fds'][$visitor['visitor_id']]= $fd;
#end
Db::commit();
return self::reposon($fd, 200, $kefu_info['msg'], $kefu_info['data'], 'visitorToKefu');
} catch (Exception $e) {
#1.记录服务日志
$logId = VisitorService::addServiceLog([
'visitor_id' => $visitor['visitor_id'],
'client_id' => $fd,
'visitor_name' => $visitor['visitor_name'],
'visitor_avatar' => $visitor['visitor_avatar'],
'visitor_ip' => $visitor['visitor_ip'],
'kefu_id' => $kefu_info['data']['kefu_id'],
'kefu_code' => ltrim($kefu_info['data']['kefu_code'], 'KF_'),
'start_date' => date('Y-m-d H:i:s'),
]);
try {
if ($server->exist((int)$kefu_info['data']['kefu_client_id']) == false) {
Db::rollback();
Log::info('分配客服数据错误信息:' . $e->getMessage());
//取消客服在线状态
KefuLogic::setKefuOnlineStatus(ltrim($kefu_info['data']['kefu_code'], 'KF_'), '', 0);
return self::reposon($fd, 401, '请重新尝试分配客服1', [], 'visitorToKefu');
return self::reposon($fd, 201, '客服不存在或者客服不在线', [], 'visitorToKefu');
}
$kefu_info['data']['log_id'] = $logId;
// 更新队列表
$update['reception_status'] = 1;//更改连接状态
$update['kefu_code'] = ltrim($kefu_info['data']['kefu_code'], 'KF_');
$update['kefu_client_id'] = $kefu_info['data']['kefu_client_id'];
QueueLogic::updateQueueByCusomerID($visitor['visitor_id'], $update);
#3.绑定客服和游客 bengan
self::$visitor[$fd]['bind_kefu_fd'] = $kefu_info['data']['kefu_client_id'];
self::$visitor[$fd]['bind_kefu_code'] = $kefu_info['data']['kefu_code'];
self::$kefu[$kefu_info['data']['kefu_code']]['visitor_fds'][$visitor['visitor_id']] = $fd;
#end
//推送客服 通知 来新游客
$message['visitor_id'] = $visitor['visitor_id'];
$resut = self::reposon((int)self::$visitor[$fd]['bind_kefu_fd'], 200, '游客上线', $message, 'userUpper');
$server->push($resut['fd'], $resut['data']);
Db::commit();
return self::reposon($fd, 200, $kefu_info['msg'], $kefu_info['data'], 'visitorToKefu');
} catch (Exception $e) {
Db::rollback();
Log::info('分配客服数据错误信息:' . $e->getMessage());
//取消客服在线状态
KefuLogic::setKefuOnlineStatus(ltrim($kefu_info['data']['kefu_code'], 'KF_'), '', 0);
return self::reposon($fd, 401, '请重新尝试分配客服1', [], 'visitorToKefu');
}
}else if($kefu_info['code'] == 201){
} else if ($kefu_info['code'] == 201) {
return self::reposon($fd, 201, '客服不存在或者客服不在线', [], 'visitorToKefu');
}
Db::commit();
@ -192,9 +204,7 @@ class Event
public static function message($fd, $data, $server)
{
Log::record('聊天信息[' . json_encode($data) . ']');
Log::record('聊天信息1[' . json_encode(self::$online[$fd]) . ']');
Log::record('聊天信息2[' . json_encode(self::$visitor[$fd]) . ']');
Log::record('聊天信息3[' . json_encode(self::$kefu) . ']');
Log::record('聊天信息[' . json_encode( self::$online) . ']');
$uid = self::$online[$fd];
try {
//消息入库
@ -209,14 +219,23 @@ class Event
];
if (strstr($uid, "KF_") !== false) {//客服发信息给游客
if (!isset(self::$kefu[$uid]['visitor_fds'][$data['to_id']]) || ($server->exist((int)self::$kefu[$uid]['visitor_fds'][$data['to_id']])) == false) {
//更新聊天日志状态
ChatLogLogic::updateSendStatus($chat_log_id, 2);
return self::reposon($fd, 201, '游客离线', $message, 'message');
} else {
$v_fd = self::$kefu[$uid]['visitor_fds'][$data['to_id']];
$resut = self::reposon((int)$v_fd, 200, '来新信息了', $message, 'chatMessage');
$server->push($resut['fd'], $resut['data']);
}
} else { //游客发送给客服
//获取 客服的fd
if(!isset(self::$visitor[$fd]['bind_kefu_code']) || ($server->exist((int)self::$kefu[self::$visitor[$fd]['bind_kefu_code']]['fd']) == false)){
//获取 客服的fd
if (!isset(self::$visitor[$fd]['bind_kefu_code']) || ($server->exist((int)self::$kefu[self::$visitor[$fd]['bind_kefu_code']]['fd']) == false)) {
//更新聊天日志状态
ChatLogLogic::updateSendStatus($chat_log_id, 2);
return self::reposon($fd, 201, '客服离线', $message, 'message');
} else {
$kefu_fd = self::$kefu[self::$visitor[$fd]['bind_kefu_code']]['fd'];
$kefu_fd = self::$kefu[self::$visitor[$fd]['bind_kefu_code']]['fd'];
$resut = self::reposon((int)$kefu_fd, 200, '来新信息了', $message, 'chatMessage');
$server->push($resut['fd'], $resut['data']);
}
@ -229,8 +248,41 @@ class Event
return self::reposon($fd, 200, '信息发送成功', $message, 'message');
}
public static function disconnect($fd, $server){
return true;
/**
* 客服主动退出
* @param $fd 客户端标识
* @param $data 请求数据
*/
public static function kefuClose($fd, $data, $server)
{
}
public static function disconnect($fd, $server)
{
$uid = self::$online[$fd];
if (strstr($uid, "KF_") !== false) { //客服退出
//修改状态
KefuLogic::setKefuOnlineStatus(ltrim($uid, 'KF_'), 0, 0);
unset(self::$online[$fd], self::$kefu[$uid]);
} else {//游客退出
//更新状态
Visitor::setOnline($uid, 0);
//更新队列状态
QueueLogic::setReceptionStatus($uid, 2, 0);
//更新服务状态
VisitorService::setEndTimeEndId($uid);
//通知客服游客下线
$message['visitor_id'] = $uid;
$kufu_fd = self::$kefu[self::$visitor[$fd]['bind_kefu_code']]['fd'];
$resut = self::reposon((int)$kufu_fd, 200, '游客下线', $message, 'diffClose');
$server->push($resut['fd'], $resut['data']);
if (isset(self::$online[$fd])) unset(self::$online[$fd]);
if (isset(self::$visitor[$fd])) unset(self::$visitor[$fd]);
}
return true;
}
public static function reposon($fd, $code = 200, $msg = "操作成功", $data = '', $cmd = '')

View File

@ -29,14 +29,19 @@ class QueueLogic
}
}
public static function findFuwuNumByKefuCode($kefu_code)
{
return Db::name('visitor_queue')->where('reception_status', 1)->count();
}
public static function updateQueueByCusomerID($visitor_id, $update)
{
return Db::name('visitor_queue')->where('visitor_id', $visitor_id)->update($update);
}
public static function getQueueing($kefu_code){
return Db::name('visitor_queue')->where('kefu_code',$kefu_code)->where('reception_status', 1)->select();
}
public static function updateQueueingkefuClientid($kefu_code,$fd){
return Db::name('visitor_queue')->where('kefu_code',$kefu_code)->where('reception_status', 1)->update(['kefu_client_id'=>$fd]);
}
public static function setReceptionStatus($visitor_id,$status,$fd=0){
return Db::name('visitor_queue')->where('visitor_id',$visitor_id)->update(['client_id'=>$fd,'reception_status'=>$status]);
}
}

View File

@ -38,5 +38,10 @@ class Visitor
return $info;
}
public static function setOnline($visitor_id,$status,$fd=0){
$update['online_status'] =$status;
$update['client_id'] =$fd;
return Db::name('visitor')->where('visitor_id', $visitor_id)->update($update);
}
}

View File

@ -33,5 +33,19 @@ class VisitorService
return Db::name('visitor_service_log')->insertGetId($data);
}
public static function setEndTimeEndId($visitor_id){
//获取最新的记录
$info= Db::name('visitor_service_log')->where('visitor_id',$visitor_id)->order('start_date desc')->find();
if($info){
return Db::name('visitor_service_log')->where('vsid',$info['vsid'])->update([
'end_date'=>date('Y-m-d H:i:s'),
'connect_stauts'=>2,
]);
}else{
return true;
}
}
}

View File

@ -1,4 +1,7 @@
var kefu_code = 'KF_' + code;
var kefu_name= name;
var kefu_avatar =avatar;
$(function () {
var kefu = {
Message: {
@ -85,6 +88,11 @@ $(function () {
}
},
setOnlineL:function(){
$('#visitor_avatar').html(' ');
$('#visitor_info h5').text(' ');
$('#visitor_info i').text(' ');
},
getfirstChatLog: function () {
var show = $('.layout .content .chat .chat-body .show');
if (show.length > 0) {
@ -132,6 +140,18 @@ $(function () {
}
}
});
},
getChat: function (message,vid,vname,vavatar) {
var data = {
from_id: kefu_code,
from_name: kefu_name,
from_avatar: kefu_avatar,
to_id: vid,
to_name: vname,
to_avatar: vavatar,
message: message
};
return data;
}
}
};
@ -166,14 +186,37 @@ $(function () {
function onMessage(evt) {
var obj = JSON.parse(evt.data);
console.log(obj);
if (obj.cmd == "chatMessage") {
console.log(obj.data);
// kefu.Message.addLog(obj.data,'',0);
kefu.Message.toMeLog(obj.data);
} else if (obj.cmd == "kefu_online") {
$('#chats').find('.status').text('在线');
//获取当前会话
kefu.Message.getQueue()
}else if(obj.cmd == "userUpper"){
//用户上线
kefu.Message.getQueue();
}else if(obj.cmd == "diffClose"){
$('.layout .content .sidebar-group #chats #facing li').each(function () {
if($(this).attr('data-id') == obj.data.visitor_id){
var nextli=$(this).next();
$(this).remove();
if(nextli.length>0){
nextli.addClass('open-chat');
nextli.find('figure').addClass('avatar-state-success');
kefu.Message.getChatLog(nextli.attr('data-id'),kefu_code)
}else {
$('.layout .content .chat .chat-body .messages').html('');
kefu.Message.setOnlineL();
}
}
});
}else if(obj.cmd == "message"){
if (obj.code == 200) {
kefu.Message.addLog(obj.data, 'outgoing-message', 0);
} else if (obj.code == 201) {
kefu.Message.addLog(obj.data, 'outgoing-message', 1);
}
}
}
@ -190,7 +233,8 @@ $(function () {
if (!content) {
return false;
}
msg.cmd = 'message';
console.log($('.layout .content .sidebar-group #chats #facing .open-chat'));
msg.data = content;
console.log(msg)
websocket.send(JSON.stringify(msg));
@ -204,10 +248,19 @@ $(function () {
var input = $(this).find('input[type=text]');
var message = input.val();
message = $.trim(message);
var li=$('.layout .content .sidebar-group #chats #facing .open-chat');
if(li.length ==0 ){
input.focus();
return false;
}
var vid=li.attr('data-id');
var vname=li.find('h5').text();
var vavatar =li.find('img').attr('src');
if (message) {
var msg = {}
msg.cmd = 'message';
msg.data = kefu.Message.getChat(message);
msg.data = kefu.Message.getChat(message,vid,vname,vavatar);
websocket.send(JSON.stringify(msg));
input.val('');
@ -218,19 +271,19 @@ $(function () {
$(document).on('click', '.layout .navigation .nav-group li ', function (e) {
e.preventDefault();
if($(this).find('a').hasClass('queue')){
var obj= $(this).find('a');
if(obj.hasClass('queue')){
$('.layout .content .chat .chat-body .messages').html('');
kefu.Message.getQueue()
}else if($(this).find('a').hasClass('notifiy_badge')){
}else if(obj.hasClass('notifiy_badge')){
$('.layout .content .chat .chat-body .messages').html('');
kefu.Message.getQueue(2)
}else if(obj.hasClass('logout')){
window.location.href="/index/login/logout";
}
return true;
});
$(document).on('click', '.layout .content .sidebar-group .sidebar .list-group-item', function () {
if (jQuery.browser.mobile) {
$(this).closest('.sidebar-group').removeClass('mobile-open');
@ -272,6 +325,29 @@ $(function () {
}
});
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器
var isIE11 = userAgent.indexOf("rv:11.0") > -1; //判断是否是IE11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
if(!isIE && !isEdge && !isIE11) {//兼容chrome和firefox
var _beforeUnload_time = 0, _gap_time = 0;
var is_fireFox = navigator.userAgent.indexOf("Firefox") > -1;//是否是火狐浏览器
window.onunload = function () {
_gap_time = new Date().getTime() - _beforeUnload_time;
if (_gap_time <= 5) {
//执行浏览器关闭你所要做的事情比如登出
$.post('logout.do');
} else {//浏览器刷新
}
}
window.onbeforeunload = function () {
_beforeUnload_time = new Date().getTime();
if (is_fireFox) {//火狐关闭执行
//执行浏览器关闭你所要做的事情比如登出
$.post('logout.do');
}
};
});
}
});

View File

@ -95,7 +95,7 @@ $(function () {
}
} else if (item.log == 'kefu') {
if (item.send_status == 1) {
user.Message.add(item);
user.Message.add(item,'',0);
}
}
});
@ -136,6 +136,7 @@ $(function () {
function onMessage(evt) {
var obj = JSON.parse(evt.data);
console.log(obj);
//上线成功 连接客服
if (obj.cmd == 'online') {
var msg = {};
@ -156,16 +157,17 @@ $(function () {
alert('客服已下线')
}
} else if (obj.cmd = "message") {
} else if (obj.cmd == "message") {
if (obj.code == 200) {
user.Message.add(obj.data, 'outgoing-message', 0);
} else if (obj.code == 201) {
user.Message.add(obj.data, 'outgoing-message', 1);
}
return true;
} else if (obj.cmd = "chatMessage") {
//接收客服发送toMe的消息
if (obj.code == 200) {
user.Message.add(obj.data, '', 0);
}
}
}