Procházet zdrojové kódy

Merge branch 'master' of http://git.bocai108.com:10180/Ethan/Customer-Service

Jonlin před 6 roky
rodič
revize
8f01b1331c

+ 6 - 0
application/service/view/index/index.html

@@ -47,6 +47,12 @@
                     <textarea class="msg-area" id="msg-area"></textarea>
                 </div>
                 <div class="send-area">
+                    <button class="layui-btn layui-btn-small layui-bg-cyan" style="float:right;margin-right:10px;height: 40px;padding: 0 15px;" onclick="dd()">
+                        <i class="layui-icon">&#xe609;</i>上线
+                    </button>
+                    <button class="layui-btn layui-btn-small layui-bg-cyan" style="float:right;margin-right:10px;height: 40px;padding: 0 15px;" onclick="ee()">
+                        <i class="layui-icon">&#xe609;</i>拒接
+                    </button>
                     <span style="margin-left:10px;color:gray">快捷键 Enter</span>
                     <button class="layui-btn layui-btn-small layui-bg-cyan" style="float:right;margin-right:10px;height: 40px;padding: 0 15px;" id="send">
                         <i class="layui-icon">&#xe609;</i>发送

+ 5 - 1
public/index.php

@@ -10,7 +10,11 @@
 // +----------------------------------------------------------------------
 
 // [ 应用入口文件 ]
-
+//编码
+header('content-type:text/html;charset=utf-8');
+//跨域
+header('Access-Control-Allow-Origin: *');
+header("Access-Control-Allow-Credentials: true");
 // 定义应用目录
 define('APP_PATH', __DIR__ . '/../application/');
 // 加载框架引导文件

+ 22 - 0
public/static/service/js/whisper.js

@@ -311,6 +311,28 @@ function cc() {
     }));
 }
 
+// 上线
+function dd() {
+
+    var uid = $("#active-user").attr('data-id');
+
+    socket.send(JSON.stringify({
+        type: 'kfOnline',
+        data: {status: 1,uid: uinfo.id}
+    }));
+}
+
+// 拒接
+function ee() {
+
+    var uid = $("#active-user").attr('data-id');
+
+    socket.send(JSON.stringify({
+        type: 'kfOnline',
+        data: {status: 2,uid: uinfo.id}
+    }));
+}
+
 // 展示客服发送来的消息
 function showUserMessage(uinfo, content) {
     if ($('#f-' + uinfo.id).length == 0) {

+ 119 - 43
vendor/GatewayWorker_windows/Applications/whisper/Events.php

@@ -89,11 +89,17 @@ class Events
                 self::writeLog(2);
             });
 
+            //每60分钟发一次本组排队数
+            Timer::add(60 * 1, function () {
+                self::lineup();
+            });
+
+
         }
 
 
         // 检查对话时效给出.
-        Timer::add(3, function () {
+        Timer::add(60, function () {
             // 查询对话时效设置.
             $systemConfigData = self::$db->query("SELECT `systemconfig_data`,`systemconfig_enName`,`systemconfig_content` FROM `ws_systemconfig`");
             foreach ($systemConfigData as $k => $v) {
@@ -110,29 +116,29 @@ class Events
             $whereOr = '1=0';
             foreach ($serviceLog as $k => $v) {
                 if ($k == 0) {
-                    $whereOr = "`servicelog_id`=".$v['servicelog_id'];
+                    $whereOr = "`servicelog_id`=" . $v['servicelog_id'];
                 } else {
-                    $whereOr .= " OR `servicelog_id`=".$v['servicelog_id'];
+                    $whereOr .= " OR `servicelog_id`=" . $v['servicelog_id'];
                 }
             }
             // 查询最后一次会话.
             //$chatLog = self::$db->query("SELECT `servicelog_id`,MAX(`time_line`) FROM `ws_chat_log` WHERE ".$whereOr." group by `servicelog_id`");
             $chatLog = self::$db->query("
                 select * from ws_chat_log as a where  time_line=(
-                  select max(b.time_line) from ws_chat_log as b where a.servicelog_id = b.servicelog_id and (".$whereOr.") group by servicelog_id
+                  select max(b.time_line) from ws_chat_log as b where a.servicelog_id = b.servicelog_id and (" . $whereOr . ") group by servicelog_id
                 )
             ");
-            $setOvertime = strtotime('-'.(self::$global->overtime['systemconfig_data']-60).' second');
-            $overtime = strtotime('-'.(self::$global->overtime['systemconfig_data']).' second');
-            $setUnoperated = strtotime('-'.(self::$global->unoperated['systemconfig_data']-60).' second');
-            $unoperated = strtotime('-'.(self::$global->unoperated['systemconfig_data']).' second');
-            $noResponse = strtotime('-'.(self::$global->noResponse['systemconfig_data']).' second');
+            $setOvertime = strtotime('-' . (self::$global->overtime['systemconfig_data'] - 60) . ' second');
+            $overtime = strtotime('-' . (self::$global->overtime['systemconfig_data']) . ' second');
+            $setUnoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data'] - 60) . ' second');
+            $unoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data']) . ' second');
+            $noResponse = strtotime('-' . (self::$global->noResponse['systemconfig_data']) . ' second');
             foreach ($serviceLog as $k => $v) {//注意该循环时间
                 if (!strlen(array_search($v['servicelog_id'], array_column($chatLog, 'servicelog_id')))) {
                     // 如果小于设定时间则关闭会话.
                     if ($v['start_time'] <= $unoperated) {
-                        self::serverClose($v['client_id']);
-                    // 如果小于设定时间前一分钟则给出提示.
+                        self::serverClose($v['client_id'], $v['servicelog_id']);
+                        // 如果小于设定时间前一分钟则给出提示.
                     } elseif ($v['start_time'] <= $setUnoperated) {
                         $chat_message = [
                             'message_type' => 'overtime',
@@ -146,13 +152,13 @@ class Events
             }
             // 循环检测会话时效.
             foreach ($chatLog as $k => $v) {
-                $toWho = substr($v['to_id'],0,2);
+                $toWho = substr($v['to_id'], 0, 2);
                 // 如果对话为客服的最后一次对话且时间小于设定时间则结束工单.
-                if ($toWho != 'KF' && $v['time_line'] <= $overtime) {
+                if ($v['time_line'] <= $overtime) {
                     $found_key = array_search($v['servicelog_id'], array_column($serviceLog, 'servicelog_id'));
-                    self::serverClose($serviceLog[$found_key]['client_id']);
-                // 如果对话为客服的最后一次对话且时间小于设定时间前一分钟则给出提示.
-                } elseif ($toWho != 'KF' && $v['time_line'] <= $setOvertime) {
+                    self::serverClose($serviceLog[$found_key]['client_id'], $v['servicelog_id']);
+                    // 如果对话为客服的最后一次对话且时间小于设定时间前一分钟则给出提示.
+                } elseif ($v['time_line'] <= $setOvertime) {
                     $chat_message = [
                         'message_type' => 'overtime',
                         'data' => [
@@ -166,6 +172,41 @@ class Events
         });
     }
 
+    /**
+     * 每分钟定时向客服发送一次排队情况
+     */
+
+    public static function lineup()
+    {
+        $userlist = self::$global->userList;
+        $kflist = self::$global->kfList;
+
+        if (empty($userlist) || empty($kflist)) {
+            return;
+        }
+
+        $return = [];
+        foreach ($userlist as $val) {
+            $return[$val['group']] = isset($return[$val['group']]) ? $return[$val['group']] + 1 : 1;
+        }
+
+        $krgroupclientid = [];
+        foreach ($kflist as $gid => $sval) {
+            foreach ($sval as $tval) {
+                $krgroupclientid[$gid][] = $tval['client_id'];
+            }
+        }
+
+        foreach ($return as $fgroup => $fval) {
+            foreach ($krgroupclientid as $sikey => $sival) {
+                if ($fgroup == $sikey) {
+                    Gateway::sendToClient($sival, json_encode(['type' => 'lineupCount', $fval], 256));
+                }
+            }
+        }
+        return;
+    }
+
 
     /**
      * 当客户端连接时触发
@@ -204,8 +245,8 @@ class Events
             Gateway::sendToCurrentClient('{"type":"pong"}');
             return;
         } else {
-            /*echo "onMessage: " . $message . "\r\n";
-            print_r([self::$global->kfList, self::$global->userList, self::$global->uidSimpleList, self::$global->userToKf]);*/
+            echo "onMessage: " . $message . "\r\n";
+            print_r([self::$global->kfList, self::$global->userList, self::$global->uidSimpleList, self::$global->userToKf]);
         }
 
         $message = json_decode($message, true);
@@ -356,10 +397,30 @@ class Events
                 break;
             // 客服关闭会话.
             case 'kfCloseUser':
-                $client = Gateway::getClientIdByUid($message['data']['to_id']);
+                $client = Gateway::getClientIdByUid($userId);
                 if (!empty($client)) {
-                    self::serverClose($client['0']);
+                    $userId = $message['data']['to_id'];
+                    $kfId = $message['data']['kf_id'];
+                    $groupId = $message['data']['group_id'];
+                    $clientId = $client['0'];
+                    $sql = "select 'servicelog_id' from `ws_service_log` where `user_id`= '$userId' and `client_id`= '$clientId' and `status`!= '2' and `group_id`!= '$groupId' and `kf_id`!= '$kfId'";
+                    $serviceLog = self::$db->query($sql);
+                    self::serverClose($clientId, $serviceLog[0]['servicelog_id']);
+                }
+                break;
+            // 客服更改状态.
+            case 'kfOnline':
+                $kfList = self::$global->kfList;
+                $userId = $message['data']['uid'];
+                $status = $message['data']['status'];
+                foreach ($kfList as $k => $v) {
+                    foreach ($v as $ke => $va) {
+                        if ($ke == $userId) {
+                            $kfList[$k][$ke]['status'] = $status;
+                        }
+                    }
                 }
+                self::$global->kfList = $kfList;
                 break;
             case 'changeOtherhKeFu';
                 self::changeOtherhKeFu($client_id, $message);
@@ -386,7 +447,7 @@ class Events
             return false;
         }
 
-        $tokfidclientid =  Gateway::getClientIdByUid($toukfid);
+        $tokfidclientid = Gateway::getClientIdByUid($toukfid);
         $tokfidclientid = $tokfidclientid['0'];
         $uidclientid = Gateway::getClientIdByUid($uid);
         $uidclientid = $uidclientid['0'];
@@ -423,15 +484,17 @@ class Events
 
 
         /////////取消原有会话,开启新会话
-        $histarttimelimit = time() - 3600*24 ;
-        $bindval = ['user_id'=>$uid,'kf_id'=>intval(trim($toukfid,'KF')),'histime'=>$histarttimelimit] ;
-        $oldlog = self::$db->select('*')->from('ws_service_log')->where('user_id= :user_id and  client_id=:client_id and kf_id=:kf_id and  status=2 and  start_time>=:histime ' )->bindValues($bindval)->row();
-        if (!$oldlog){            return false;        }
-        self::$db->update('ws_service_log')->cols(['status'=>2,'endtime'=>time()])->where('servicelog_id='.$oldlog['servicelog_id'])->query();
+        $histarttimelimit = time() - 3600 * 24;
+        $bindval = ['user_id' => $uid, 'kf_id' => intval(trim($toukfid, 'KF')), 'histime' => $histarttimelimit];
+        $oldlog = self::$db->select('*')->from('ws_service_log')->where('user_id= :user_id and  client_id=:client_id and kf_id=:kf_id and  status=2 and  start_time>=:histime ')->bindValues($bindval)->row();
+        if (!$oldlog) {
+            return false;
+        }
+        self::$db->update('ws_service_log')->cols(['status' => 2, 'endtime' => time()])->where('servicelog_id=' . $oldlog['servicelog_id'])->query();
         unset($oldlog['servicelog_id']);
-        $oldlog = array_merge($oldlog,['kf_id'=>intval(trim($toukfid,'KF')),'start_time'=>time(),'end_time'=>0,'status'=>1,'evaluate_id'=>0]);
+        $oldlog = array_merge($oldlog, ['kf_id' => intval(trim($toukfid, 'KF')), 'start_time' => time(), 'end_time' => 0, 'status' => 1, 'evaluate_id' => 0]);
         $new_id = self::$db->insert('ws_service_log')->cols($oldlog)->query();
-        if (!$new_id){
+        if (!$new_id) {
             return false;
         }
 
@@ -457,9 +520,9 @@ class Events
         Gateway::sendToClient($tokfidclientid, json_encode($noticeKf, 256));
         unset($noticeKf);
         //回转接人,转接成功
-        Gateway::sendToCurrentClient(json_encode(['message_type'=>'trunconnect','data'=>['status'=>1],256]));
+        Gateway::sendToCurrentClient(json_encode(['message_type' => 'trunconnect', 'data' => ['status' => 1], 256]));
 
-        return ;
+        return;
     }
 
     //客服接入sock,及初始化
@@ -486,6 +549,7 @@ class Events
                     'avatar' => $message['avatar'],
                     'client_id' => $client_id,
                     'task' => 0,
+                    'status' => 2,// 1为在线(接收分配、接收消息)2为隐身(不接收分配、只接收消息)
                     'user_info' => []
                 ];
             } while (!self::$global->cas('kfList', $kfList, $newKfList));
@@ -590,7 +654,6 @@ class Events
 
         // 尝试分配新会员进入服务
         self::userOnlineTask($client_id, $message['group'], $message['uid']);
-
     }
 
     /**
@@ -739,7 +802,7 @@ class Events
      * tips: 当服务端主动退出的时候,会出现 exit status 9.原因是:服务端主动断开之后,连接的客户端会走这个方法,而短时间内进程
      * 需要处理这多的逻辑,又有cas操作,导致进程退出会超时,然后会被内核杀死,从而报出错误 9.实际对真正的业务没有任何的影响。
      */
-    public static function serverClose($client_id)
+    public static function serverClose($client_id, $servicelog_id)
     {
         // 返回.
         $chat_message = [
@@ -751,6 +814,10 @@ class Events
         ];
         Gateway::sendToClient($client_id, json_encode($chat_message, 256));
         Gateway::closeClient($client_id);
+        $now = time();
+        $sql = "update `ws_service_log` set `status`='2',end_time=$now  where `servicelog_id`= '$servicelog_id'";
+        //echo "客户退出:". $sql ."\n";
+        self::$db->query($sql);
         $isServiceUserOut = false;
         // 将会员服务信息,从客服的服务列表中移除
         $old = $kfList = self::$global->kfList;
@@ -1102,8 +1169,17 @@ class Events
      */
     private static function assignmentTask($kfList, $userList, $group, $total, $uid = 0)
     {
+        // 注:修改为已上线(status为1上线status为2不接受分配)
+        $onlineKF = [];
+        foreach ($kfList as $k => $v) {
+            foreach ($v as $ke => $va) {
+                if ($va['status'] == 1) {
+                    $onlineKF[$k][$ke] = $va;
+                }
+            }
+        }
         // 没有客服上线
-        if (empty($kfList) || empty($kfList[$group])) {
+        if (empty($onlineKF) || empty($onlineKF[$group])) {
             return ['code' => -1];
         }
 
@@ -1118,7 +1194,7 @@ class Events
         }
 
         // 查看该组的客服是否在线
-        if (!isset($kfList[$group])) {
+        if (!isset($onlineKF[$group])) {
             return ['code' => -1];
         }
 
@@ -1144,22 +1220,22 @@ class Events
         //上次用户掉线后,还可以继续上一次 (如果没有关闭) 的会话  --2
         if ($odltalksession) {
             $oldkrid = 'KF' . $odltalksession['kf_id'];
-            if (isset($kfList[$group][$oldkrid])) {
-                $kf = $kfList[$group][$oldkrid];
+            if (isset($onlineKF[$group][$oldkrid])) {
+                $kf = $onlineKF[$group][$oldkrid];
                 $min = $kf['task'];
                 $flag = $kf['id'];
-                unset($kfList[$group][$oldkrid]);
+                unset($onlineKF[$group][$oldkrid]);
             } else {
                 goto NOSIGNKF;
             }
         } else {
             NOSIGNKF:
-            $kf = $kfList[$group];
+            $kf = $onlineKF[$group];
             $kf = array_shift($kf);
             $min = $kf['task'];
             $flag = $kf['id'];
 
-            foreach ($kfList[$group] as $key => $vo) {
+            foreach ($onlineKF[$group] as $key => $vo) {
                 if ($vo['task'] < $min) {
                     $min = $vo['task'];
                     $flag = $key;
@@ -1169,7 +1245,7 @@ class Events
         }
 
         // 需要排队了
-        if ($kfList[$group][$flag]['task'] == $total) {
+        if ($onlineKF[$group][$flag]['task'] == $total) {
             return ['code' => -4];
         }
 
@@ -1179,9 +1255,9 @@ class Events
         return [
             'code' => 1,
             'data' => [
-                $kfList[$group][$flag]['id'],
-                $kfList[$group][$flag]['name'],
-                $kfList[$group][$flag]['client_id'],
+                $onlineKF[$group][$flag]['id'],
+                $onlineKF[$group][$flag]['name'],
+                $onlineKF[$group][$flag]['client_id'],
                 $user,
                 $kfList,
                 $userList