From dac0ec3afd04994898fb742ccc0cbc332cbdc8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=8F=E5=B0=98?= Date: Thu, 31 Oct 2019 20:13:01 +0800 Subject: [PATCH] core --- application/index/controller/Kefu.php | 1 + application/index/controller/Login.php | 3 + application/index/view/kefu/index.html | 6 +- application/index/view/login/login.html | 3 +- application/swoole/service/Event.php | 146 +++++++++++++++-------- extend/Logic/QueueLogic.php | 15 ++- extend/Logic/Visitor.php | 5 + extend/Logic/VisitorService.php | 14 +++ public/static/common/dist/js/examples.js | 102 ++++++++++++++-- public/static/common/dist/js/user.js | 10 +- 10 files changed, 232 insertions(+), 73 deletions(-) diff --git a/application/index/controller/Kefu.php b/application/index/controller/Kefu.php index 913fbe9..85fceae 100644 --- a/application/index/controller/Kefu.php +++ b/application/index/controller/Kefu.php @@ -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(){ diff --git a/application/index/controller/Login.php b/application/index/controller/Login.php index 727abb5..8ecc027 100644 --- a/application/index/controller/Login.php +++ b/application/index/controller/Login.php @@ -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'); } } diff --git a/application/index/view/kefu/index.html b/application/index/view/kefu/index.html index 0913063..beedba9 100644 --- a/application/index/view/kefu/index.html +++ b/application/index/view/kefu/index.html @@ -52,7 +52,7 @@ -
  • +
  • @@ -60,7 +60,7 @@
  • - +
  • @@ -170,6 +170,8 @@ diff --git a/application/index/view/login/login.html b/application/index/view/login/login.html index 45d07da..b938db5 100644 --- a/application/index/view/login/login.html +++ b/application/index/view/login/login.html @@ -28,7 +28,6 @@ - - + diff --git a/application/swoole/service/Event.php b/application/swoole/service/Event.php index c86c508..367896d 100644 --- a/application/swoole/service/Event.php +++ b/application/swoole/service/Event.php @@ -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 = '') diff --git a/extend/Logic/QueueLogic.php b/extend/Logic/QueueLogic.php index e7d9d6d..2754dfb 100644 --- a/extend/Logic/QueueLogic.php +++ b/extend/Logic/QueueLogic.php @@ -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]); + } + } diff --git a/extend/Logic/Visitor.php b/extend/Logic/Visitor.php index 6182f39..47b8850 100644 --- a/extend/Logic/Visitor.php +++ b/extend/Logic/Visitor.php @@ -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); + } } diff --git a/extend/Logic/VisitorService.php b/extend/Logic/VisitorService.php index 3c2028e..0e599f1 100644 --- a/extend/Logic/VisitorService.php +++ b/extend/Logic/VisitorService.php @@ -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; + } + + } + } diff --git a/public/static/common/dist/js/examples.js b/public/static/common/dist/js/examples.js index 6a8eb2d..a7cd60d 100644 --- a/public/static/common/dist/js/examples.js +++ b/public/static/common/dist/js/examples.js @@ -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'); + } + }; - -}); + } + }); diff --git a/public/static/common/dist/js/user.js b/public/static/common/dist/js/user.js index e381f7d..980f627 100644 --- a/public/static/common/dist/js/user.js +++ b/public/static/common/dist/js/user.js @@ -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); + } } }