vali há 6 anos atrás
pai
commit
d6c60c4718

+ 286 - 10
vendor/GatewayWorker_windows/Applications/whisper/Events.php

@@ -38,6 +38,10 @@ class Events
     public static $redis = null;
     public static $logic = null;
 
+    const  KFINFOKEY = 'KFINFO';              //客服信息hash表
+    const  USERINFOKEY = 'USERINFO';          //用户信息hash表
+    const  USERLIST = 'USERLIST';             //用户排队表
+
     /**
      * 进程启动后初始化数据库连接
      */
@@ -227,7 +231,7 @@ class Events
             return true;
         }
 
-        $loginstate = self::$logic->Kfislogin($client_id, $uid, $group);
+        $loginstate = self::$logic->userIsLogin($client_id, $uid, $group);
         if ($loginstate == 1) {
             self::MySendMsg($oldcontid, (json_encode(['message_type' => 'reLoginErr', 'msg' => '正在登陆中,请稍后...'], 256)));
             Gateway::closeClient($oldcontid);
@@ -250,14 +254,16 @@ class Events
                 'name' => $kfinfo['user_name'],
                 'job_name' => $kfinfo['user_job_number'],
                 'avatar' => $kfinfo['user_avatar'],
+                'group' => $group,
                 'client_id' => $client_id,
                 'task' => 0,
                 'signature' => $kfinfo['signature'],
                 'status' => 2, // 1为在线(接收分配、接收消息)2为隐身(不接收分配、只接收消息)3、休息
-                'user_info' => []
+                'user_info' => [],  //在会话的用户cid
+                'serverids' => [],
             ];
 
-        self::$redis->hset('KFINFO', $uid, json_encode($newinfo, 256));
+        self::$redis->hset(self::KFINFOKEY, $uid, json_encode($newinfo, 256));
         $_SESSION['info'] = $newinfo;
 
         // 绑定 client_id 和 uid
@@ -321,9 +327,70 @@ class Events
     //用户发送邦定用户事件
     public static function userInitEnt($client_id, $message)
     {
+        $uid = intval($message['uid']);
+        $group = intval($message['group']);
+
+        if (isset(self::$global->groupmap[$group])) {
+            self::MySendMsg($client_id, (json_encode(['message_type' => 'reLoginErr', 'msg' => '不存在客服组....'], 256)));
+            Gateway::closeClient($oldcontid);
+        }
+
+        $loginstate = self::$logic->userIsLogin($client_id, $uid, $group);
+        if ($loginstate == 1) {
+            self::MySendMsg($oldcontid, (json_encode(['message_type' => 'reLoginErr', 'msg' => '正在登陆中,请稍后...'], 256)));
+            Gateway::closeClient($oldcontid);
+            return;
+        }
+
+        $hisdata = self::$redis->hget(self::USERINFOKEY, $uid);
+        if ($hisdata) {
+            $hisdata = json_decode($hisdata, true);
+            $oldclientid = $hisdata['client_id'];
+            self::MySendMsg($oldclientid, json_encode(['type' => 'reLoginErr', 'msg' => '相同账号登陆,本次退出'], 256));
+            Gateway::closeClient($oldclientid);
+            sleep(1);
+        }
+
+        $onlinekf = self::getOnlineKfData($group, 1);
+        if (empty($onlinekf)) {
+            Gateway::sendToClient($client_id, json_encode(['message_type' => 'notice', 'content' => '暂时没有客服上班,请稍后再咨询。'], 256));
+            Gateway::closeClient($client_id);
+            return;
+        }
+
+        self::$redis->hset('loginTmp:' . $uid, 'uid', time());
+        self::$redis->expire('loginTmp:' . $uid, 5);
+
+        $data = [
+            'id' => $uid,
+            'name' => $message['name'],
+            'avatar' => $message['avatar'],
+            'website' => $_SESSION['origin'],//$_SERVER['HTTP_ORIGIN'],
+            'browse' => Gateway::browse_info(),
+            'system' => Gateway::get_os(),
+            'ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
+            'group' => $message['group'],
+            'intime' => time(),
+            'kfuid' => '',
+            'serverid' => 0,
+            'client_id' => $client_id
+        ];
+        self::$redis->hset(self::USERLIST, $uid, json_encode($data, 256));
+        self::$redis->hset(self::USERINFOKEY, $uid, json_encode($data, 256));
+
+        // 写入接入值
+        $key = date('Ymd') . 'total_in';
+        $oldKey = date('Ymd', strtotime('-1 day')); // 删除前一天的统计值
+        unset(self::$global->$oldKey);
+        self::$global->increment($key);
+
+        // 绑定 client_id 和 uid
+        Gateway::bindUid($client_id, $uid);
+        $_SESSION['iskefu'] = 0;
+        $_SESSION['uid'] = $message['uid'];
 
         // 尝试分配新会员进入服务
-        self::userOnlineTask($client_id, $message['group'], $message['uid']);
+        self::userOnlineTask($group, $uid = 0);
     }
 
     /**
@@ -358,20 +425,76 @@ class Events
         return;
     }
 
-    //客服下线了
+    //客服下线了  系统调用,不能手动调用
     public static function serviceOffline($client_id, $uid)
     {
+        $group = $_SESSION['group'];
+        $uinfo = self::$redis->hget(self::KFINFOKEY, $uid);
+        $uinfo = json_decode($uinfo, true);
+        $user_info = $uinfo['user_info'];
+        $kfid = self::getkfid($uid);
+        $now = time();
+        $starttime = $now - 86400 * 7;
+        $serlogs = self::$db->select('servicelog_id')->from('ws_service_log')->where(" start_time>=$starttime  kf_id=$kfid AND status !=2 ")->query();
+
+        if (!empty($user_info)) {
+            foreach ($user_info as $val) {
+                self::MySendMsg($val, json_encode(['message_type' => 'serviceoffline', 'msg' => '客户人员下线!'], 256));
+                Gateway::closeClient($val);
+            }
+        }
 
+        self::$db->query("update `ws_service_log` set `status` = '2',end_time=$now,`servicelog_close_type` = 4   where  kf_id=$uiiid and  group_id=$group  and  `status`!=2 ");
+        self::$db->update('ws_users')->cols(array('online_status' => 0, 'online_connectid' => ''))->where('id=' . $kfid)->query();
         self::writeLogKfStatus($uid, 0);
 
         return;
     }
 
-    //用户下线了
+    //用户下线了          系统调用,不能手动调用
     public static function guestOffline($client_id, $uid)
     {
+        $uid = intval($uid);
+        $krclient_id = 0;
+
+        $data = self::$redis->hget(self::USERINFOKEY, $uid);
+        if (empty($data)) {
+            return;
+        }
+        $info = json_decode($data, true);
+        self::$redis->hdel(self::USERLIST, $uid);
+        self::$redis->hdel(self::USERINFOKEY, $uid);
+
+        if (!empty($info['kfuid'])) {
+            $kfinfo = self::$redis->hget(self::KFINFOKEY, $info['kfuid']);
+            if (!empty($kfinfo)) {
+                $kfinfoArr = json_decode($kfinfo, true);
+                $krclient_id = $kfinfoArr['client_id'];
+                $kfinfoArr['user_info'] = self::ArrayDataopt($kfinfoArr['user_info'], $client_id, 0);
+                $kfinfoArr['task'] = count($kfinfoArr['user_info']);
+                self::$redis->hset(self::KFINFOKEY, $info['kfuid'], json_encode($kfinfoArr, 256));
+            }
+        }
 
+        $chat_message = [
+            'message_type' => 'userClose',
+            'data' => [
+                'content' => '用户连接已断开',
+                'id' => $uid,
+                'time' => date('H:i'),
+            ]
+        ];
+        $now = time();
+        $serverid = intval($info['serverid']);
+        if ($serverid) {
+            $sql = "update `ws_service_log` set `status` = '3'  where servicelog_id=$serverid ";
+            self::$db->query($sql);
+        }
+        if ($krclient_id) {
+            Gateway::sendToClient($krclient_id, json_encode($chat_message, 256));
+        }
 
+        return;
     }
 
 
@@ -414,12 +537,96 @@ class Events
      * @param $group
      * @param $uid
      */
-    private static function userOnlineTask($client_id, $group, $uid = 0)
+    private static function userOnlineTask($group = 0, $uid = 0)
+    {
+        $alluser = self::$redis->hgetall(self::USERLIST);
+        if (empty($alluser)) {
+            return true;
+        }
+        $allusergkarr = [];
+        foreach ($alluser as $val) {
+            $now = json_decode($val, 256);
+            if ($now) {
+                //用户分组后的数组
+                $allusergkarr[$now['group']][] = $now;
+            }
+        }
+        if (!$allusergkarr) {
+            return false;
+        }
+        unset($alluser);
+
+
+        $allkfs = self::$redis->hgetall(self::KFINFOKEY);
+        if (empty($allkfs)) {
+            return true;
+        }
+        $allkfgkarr = [];
+        foreach ($allkfs as $val) {
+            $now = json_decode($val, 256);
+            if ($now && $now['status'] == 1) {
+                //客分组后的数组
+                $allkfgkarr[$now['group']][] = $now;
+            }
+        }
+        if (!$allkfgkarr) {
+            return false;
+        }
+        //客服每组按任务数由小到大排序
+        foreach ($allkfgkarr as $group => $nowgroups) {
+            usort($allkfgkarr[$group], function ($a, $b) {
+                if ($a['task'] == $b['task']) {
+                    return 0;
+                }
+                return ($a > $b) ? 1 : -1;
+            });
+        }
+        unset($allkfs);
+
+        $maxset = (self::$global->systemconfig)['KFMaxServices'] ?? 5;
+        $maxset = inval($maxset);
+
+        if ($group && $uid) {
+            // 指定用指定组 [可能存在断线重连的情况] 如果存在旧的会话,直接连线客服和用户
+            //否则按先到后到以及客服最大服务数限制
+            $last = self::UserHasOldTalk($uid);
+            if ($last) {
+                self::BeginTalk(self::getkfuid($last['kf_id']), $uid, $last['group_id'], $last['servicelog_id']);
+                return;
+            }
+        }
+        //系统定时调用时,无组,无用户
+        foreach ($allusergkarr as $group => $gusersArr) {
+            if (isset($allkfgkarr[$group])) {
+                //所属客服组无人在线
+                continue;
+            }
+            $nowkfs = $allkfgkarr[$group];
+            foreach ($gusersArr as $user) {
+
+
+            }
+        }
+
+        return;
+
+    }
+
+    //开启一个会话
+    private static function BeginTalk($kfuid, $uid, $group, $serviceid = 0)
     {
 
+    }
 
+    //找到用户是否有一条未关闭的会话
+    private static function UserHasOldTalk($uid)
+    {
+        $uid = intval($uid);
+        $ret = self::$db->select('*')->from('ws_service_log')->where("user_id=$uid and  status!=2")->orderByDESC(['id'])->row();
+        return $ret;
     }
 
+
     //今天排序累加
     private static function todayqueuelength()
     {
@@ -751,7 +958,7 @@ class Events
 
     public static function resetServiceLog($kfid = 0)
     {
-        $t = time() - 24 * 3600;
+        $t = time() - 24 * 3600 * 7;
 
         if ($kfid) {
             if ((substr($kfid, 0, 2) == 'KF')) {
@@ -759,7 +966,10 @@ class Events
             }
             $kfid = intval($kfid);
             self::$db->query("update ws_service_log set status=2 where kf_id=$kfid and  start_time>=$t and  status!=2");
+            self::$redis->hdel('KFINFO', 'KF' . $kfid);
         } else {
+            self::$redis->del('KFINFO');
+            self::$redis->del('USERINFOKEY');
             self::$db->query("update ws_service_log set status=2 where  start_time>=$t and  status!=2");
         }
 
@@ -821,7 +1031,6 @@ class Events
             unset($oldKey, $key);
         }
 
-
         // 定时统计数据
         if (0 == $worker->id) {
 
@@ -834,7 +1043,6 @@ class Events
                 self::upsystemconfig();
             });
 
-
             self::resetServiceLog();
         }
 
@@ -873,6 +1081,7 @@ class Events
         }
     }
 
+    //从数组中获取参数
     public static function getPars($array, $key, $default = '')
     {
         if (isset($array[$key])) {
@@ -881,5 +1090,72 @@ class Events
         return $default;
     }
 
+    //获取在线客服信息
+    public static function getOnlineKfData($group = 0, $status = 0)
+    {
+        $all = self::$redis->hgetall(self::KFINFOKEY);
+        if (!$all) {
+            return false;
+        }
+        $return = [];
+        foreach ($all as $val) {
+            $now = json_decode($val, true);
+            if ($group) {
+                if ($now['group'] != $group) {
+                    continue;
+                }
+            }
+            if ($status) {
+                if ($now['status'] != $status) {
+                    continue;
+                }
+            }
+            $return[$val['id']] = $now;
+        }
+        return $return;
+    }
+
+    //找到在排队的用户按时间先后顺序
+    public static function getUselistData($group)
+    {
+        $all = self::$redis->hgetall(self::USERLIST);
+        if (!$all) {
+            return false;
+        }
+        $return = [];
+        foreach ($all as $val) {
+            $now = json_decode($val, true);
+            if ($group == $now['group']) {
+                $return[] = $now;
+            }
+        }
+        usort($return, function ($a, $b) {
+            if ($a['intime'] == $b['intime']) {
+                return 0;
+            }
+            return $a['intime'] > $b['intime'] ? 1 : -1;
+        });
+        return $return;
+    }
+
+    //对客服的用户user_info数组进行加减操作  $clientid用户连接号    opt=1添加 0删除   $serverid服务工单号
+    public static function ArrayDataopt($array, $clientid, $opt, $serverid = 0)
+    {
+        if (!is_array($array)) {
+            return [];
+        }
+
+        if ($opt == 0) {
+            if (isset($array[$clientid])) {
+                unset($array[$clientid]);
+            }
+            return $array;
+        } else {
+            $array[$clientid] = $serverid;
+            return $array;
+        }
+    }
+
+
 }
 

+ 1 - 1
vendor/GatewayWorker_windows/Applications/whisper/Mlogic.php

@@ -110,7 +110,7 @@ class Mlogic
     }
 
     //客服是否正在登陆,或已经登陆 0未登陆   1正在登陆  2已登陆成功
-    public static function Kfislogin($client_id, $kfuid, $groupid)
+    public static function userIsLogin($client_id, $kfuid, $groupid)
     {
         $hakey = self::$redis->hget("loginTmp:" . $kfuid, $kfuid);
         if ($hakey) {