|
|
@@ -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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|