|
@@ -80,7 +80,7 @@ class Events
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 定时统计数据
|
|
// 定时统计数据
|
|
|
- if (0 === $worker->id) {
|
|
|
|
|
|
|
+ if (0 == $worker->id) {
|
|
|
|
|
|
|
|
self::writeLogKfStatus(0, 0, 0);
|
|
self::writeLogKfStatus(0, 0, 0);
|
|
|
|
|
|
|
@@ -106,7 +106,7 @@ class Events
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 检查对话时效给出.
|
|
// 检查对话时效给出.
|
|
|
- Timer::add(60, function () {
|
|
|
|
|
|
|
+ Timer::add(6, function () {
|
|
|
self::overTime();
|
|
self::overTime();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -392,12 +392,16 @@ class Events
|
|
|
// 客服关闭会话.
|
|
// 客服关闭会话.
|
|
|
case 'kfCloseUser':
|
|
case 'kfCloseUser':
|
|
|
$userId = $message['data']['to_id'];
|
|
$userId = $message['data']['to_id'];
|
|
|
|
|
+ $kfId = $message['data']['kf_id'];
|
|
|
|
|
+ $groupId = $message['data']['group_id'];
|
|
|
$client = Gateway::getClientIdByUid($userId);
|
|
$client = Gateway::getClientIdByUid($userId);
|
|
|
|
|
+ $servicelog_id = $message['data']['conversationId'];
|
|
|
|
|
+ self::$db->query("update `ws_service_log` set `servicelog_close_type` = 3 where `servicelog_id`= '$servicelog_id'");
|
|
|
if (!empty($client)) {
|
|
if (!empty($client)) {
|
|
|
$clientId = $client['0'];
|
|
$clientId = $client['0'];
|
|
|
- $servicelog_id = $message['data']['conversationId'];
|
|
|
|
|
- self::$db->query("update `ws_service_log` set `servicelog_close_type` = 3 where `servicelog_id`= '$servicelog_id'");
|
|
|
|
|
- self::serverClose($clientId, $servicelog_id);
|
|
|
|
|
|
|
+ self::serverClose($clientId, $servicelog_id, $userId, $kfId, $groupId);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self::closeUser($servicelog_id, $userId, $kfId, $groupId);
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
// 客服更改状态.
|
|
// 客服更改状态.
|
|
@@ -455,7 +459,7 @@ class Events
|
|
|
'data' => [],
|
|
'data' => [],
|
|
|
];
|
|
];
|
|
|
$nowkfid = isset($_SESSION['uid']) ? $_SESSION['uid'] : 0;
|
|
$nowkfid = isset($_SESSION['uid']) ? $_SESSION['uid'] : 0;
|
|
|
- $fromgrouupid = isset($_SESSION['uid']) ? $_SESSION['group'] : 0;
|
|
|
|
|
|
|
+ $fromgrouupid = isset($_SESSION['group']) ? $_SESSION['group'] : 0;
|
|
|
|
|
|
|
|
if (empty($fromgrouupid) || empty($nowkfid)) {
|
|
if (empty($fromgrouupid) || empty($nowkfid)) {
|
|
|
return $return;
|
|
return $return;
|
|
@@ -465,7 +469,7 @@ class Events
|
|
|
$groupnamemap = self::$global->groupmap;
|
|
$groupnamemap = self::$global->groupmap;
|
|
|
|
|
|
|
|
|
|
|
|
|
- if (!$kfs || empty($nowkfid)) {
|
|
|
|
|
|
|
+ if (!$kfs || empty($groupnamemap)) {
|
|
|
return $return;
|
|
return $return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -473,7 +477,7 @@ class Events
|
|
|
|
|
|
|
|
foreach ($kfs as $gruop => $users) {
|
|
foreach ($kfs as $gruop => $users) {
|
|
|
foreach ($users as $uid => $uinfo) {
|
|
foreach ($users as $uid => $uinfo) {
|
|
|
- if ($uid != $nowkfid && $fromgrouupid == $gruop) {
|
|
|
|
|
|
|
+ if ($uid != $nowkfid && $fromgrouupid == $gruop && $uinfo['status'] == 1) {
|
|
|
$ret[] = ['groupid' => $gruop, 'groupname' => $groupnamemap[$gruop], 'kfuid' => $uid, 'kfname' => $uinfo['name'], 'kfjobname' => $uinfo['job_name']];
|
|
$ret[] = ['groupid' => $gruop, 'groupname' => $groupnamemap[$gruop], 'kfuid' => $uid, 'kfname' => $uinfo['name'], 'kfjobname' => $uinfo['job_name']];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -622,9 +626,10 @@ class Events
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isset($kfList[$message['group']][$message['uid']])) {
|
|
if (isset($kfList[$message['group']][$message['uid']])) {
|
|
|
- Gateway::sendToCurrentClient(json_encode(['message_type' => 'reLoginErr', 'msg' => '你的账号已经登陆过,请先退出再登陆'], 256));
|
|
|
|
|
- Gateway::closeCurrentClient();
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ $oldcontid = $kfList[$message['group']][$message['uid']]['client_id'];
|
|
|
|
|
+ Gateway::sendToClient($oldcontid, (json_encode(['message_type' => 'reLoginErr', 'msg' => '你的账号在其它登陆,本次下线'], 256)));
|
|
|
|
|
+ Gateway::closeClient($oldcontid);
|
|
|
|
|
+ sleep(3);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 如果该客服未在内存中记录则记录
|
|
// 如果该客服未在内存中记录则记录
|
|
@@ -875,14 +880,18 @@ class Events
|
|
|
$kfuid = -1;
|
|
$kfuid = -1;
|
|
|
$krclient_id = 0;
|
|
$krclient_id = 0;
|
|
|
$kfgroup = -1;
|
|
$kfgroup = -1;
|
|
|
|
|
+ $istalking = 1;
|
|
|
|
|
|
|
|
$userToKf = $userToKfNew = self::$global->userToKf;
|
|
$userToKf = $userToKfNew = self::$global->userToKf;
|
|
|
if (isset($userToKfNew[$uid])) {
|
|
if (isset($userToKfNew[$uid])) {
|
|
|
$kfuid = isset($userToKfNew[$uid]['1']) ? $userToKfNew[$uid]['1'] : -1;
|
|
$kfuid = isset($userToKfNew[$uid]['1']) ? $userToKfNew[$uid]['1'] : -1;
|
|
|
$krclient_id = isset(Gateway::getClientIdByUid($kfuid)['0']) ? Gateway::getClientIdByUid($kfuid)['0'] : 0;
|
|
$krclient_id = isset(Gateway::getClientIdByUid($kfuid)['0']) ? Gateway::getClientIdByUid($kfuid)['0'] : 0;
|
|
|
|
|
+
|
|
|
|
|
+ /*用户可能意外掉线,还可以再连上来的情况下,暂不删除些关联,待公单关闭时再删除
|
|
|
unset($userToKfNew[$uid]);
|
|
unset($userToKfNew[$uid]);
|
|
|
do {
|
|
do {
|
|
|
} while (!self::$global->cas('userToKf', $userToKf, $userToKfNew));
|
|
} while (!self::$global->cas('userToKf', $userToKf, $userToKfNew));
|
|
|
|
|
+ */
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
$uidSimpleList = $uidSimpleListNew = self::$global->uidSimpleList;
|
|
$uidSimpleList = $uidSimpleListNew = self::$global->uidSimpleList;
|
|
@@ -909,6 +918,7 @@ class Events
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if ($ischange) {
|
|
if ($ischange) {
|
|
|
|
|
+ $istalking = 0;
|
|
|
do {
|
|
do {
|
|
|
} while (!self::$global->cas('userList', $userList, $userListNew));
|
|
} while (!self::$global->cas('userList', $userList, $userListNew));
|
|
|
Gateway::sendToGroup('group_' . $kfgroup, json_encode(['message_type' => 'kfqueuelength', 'leng' => $group_wait_count], 256));
|
|
Gateway::sendToGroup('group_' . $kfgroup, json_encode(['message_type' => 'kfqueuelength', 'leng' => $group_wait_count], 256));
|
|
@@ -954,6 +964,27 @@ class Events
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 客服结束会话
|
|
|
|
|
+ *
|
|
|
|
|
+ * tips: 未有$client_id的关闭
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function closeUser($servicelog_id, $userId, $kf_id, $groupId)
|
|
|
|
|
+ {
|
|
|
|
|
+ $userToKf = $userToKfNew = self::$global->userToKf;
|
|
|
|
|
+ $kfList = $userToKfNew = self::$global->kfList;
|
|
|
|
|
+ $del_message = [
|
|
|
|
|
+ 'message_type' => 'delUser',
|
|
|
|
|
+ 'data' => [
|
|
|
|
|
+ 'id' => $userId
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ Gateway::sendToClient($kfList[$groupId]['KF'.$kf_id]['client_id'], json_encode($del_message, 256));
|
|
|
|
|
+ unset($del_message);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -964,7 +995,7 @@ class Events
|
|
|
* tips: 当服务端主动退出的时候,会出现 exit status 9.原因是:服务端主动断开之后,连接的客户端会走这个方法,而短时间内进程
|
|
* tips: 当服务端主动退出的时候,会出现 exit status 9.原因是:服务端主动断开之后,连接的客户端会走这个方法,而短时间内进程
|
|
|
* 需要处理这多的逻辑,又有cas操作,导致进程退出会超时,然后会被内核杀死,从而报出错误 9.实际对真正的业务没有任何的影响。
|
|
* 需要处理这多的逻辑,又有cas操作,导致进程退出会超时,然后会被内核杀死,从而报出错误 9.实际对真正的业务没有任何的影响。
|
|
|
*/
|
|
*/
|
|
|
- public static function serverClose($client_id, $servicelog_id)
|
|
|
|
|
|
|
+ public static function serverClose($client_id, $servicelog_id, $userId, $kf_id, $groupId)
|
|
|
{
|
|
{
|
|
|
// 返回.
|
|
// 返回.
|
|
|
$chat_message = [
|
|
$chat_message = [
|
|
@@ -981,6 +1012,24 @@ class Events
|
|
|
//echo "客户退出:". $sql ."\n";
|
|
//echo "客户退出:". $sql ."\n";
|
|
|
self::$db->query($sql);
|
|
self::$db->query($sql);
|
|
|
$isServiceUserOut = false;
|
|
$isServiceUserOut = false;
|
|
|
|
|
+ $noticeIs = 0;
|
|
|
|
|
+
|
|
|
|
|
+ $userToKf = $userToKfNew = self::$global->userToKf;
|
|
|
|
|
+ $kfList = $userToKfNew = self::$global->kfList;
|
|
|
|
|
+ $del_message = [
|
|
|
|
|
+ 'message_type' => 'delUser',
|
|
|
|
|
+ 'data' => [
|
|
|
|
|
+ 'id' => $userId
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ Gateway::sendToClient($kfList[$groupId]['KF'.$kf_id]['client_id'], json_encode($del_message, 256));
|
|
|
|
|
+ unset($del_message);
|
|
|
|
|
+ // 删除关联.
|
|
|
|
|
+ if (isset($userToKfNew[$userId])) {
|
|
|
|
|
+ unset($userToKfNew[$userId]);
|
|
|
|
|
+ do {
|
|
|
|
|
+ } while (!self::$global->cas('userToKf', $userToKf, $userToKfNew));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 修改会话时长
|
|
// 修改会话时长
|
|
|
$serviceLog = self::$db->query("select `start_time`,`intime` from `ws_service_log` where `servicelog_id`= '$servicelog_id'");
|
|
$serviceLog = self::$db->query("select `start_time`,`intime` from `ws_service_log` where `servicelog_id`= '$servicelog_id'");
|
|
@@ -1022,14 +1071,6 @@ class Events
|
|
|
$outUser = self::$db->query("select `user_id`,`group_id` from `ws_service_log` where `client_id`= '" . $client_id . "'");
|
|
$outUser = self::$db->query("select `user_id`,`group_id` from `ws_service_log` where `client_id`= '" . $client_id . "'");
|
|
|
// 通知 客服删除退出的用户
|
|
// 通知 客服删除退出的用户
|
|
|
if (!empty($outUser)) {
|
|
if (!empty($outUser)) {
|
|
|
- $del_message = [
|
|
|
|
|
- 'message_type' => 'delUser',
|
|
|
|
|
- 'data' => [
|
|
|
|
|
- 'id' => $outUser['0']['user_id']
|
|
|
|
|
- ]
|
|
|
|
|
- ];
|
|
|
|
|
- Gateway::sendToClient($vo['client_id'], json_encode($del_message, 256));
|
|
|
|
|
- unset($del_message);
|
|
|
|
|
|
|
|
|
|
// 尝试分配新会员进入服务
|
|
// 尝试分配新会员进入服务
|
|
|
self::userOfflineTask($outUser['0']['group_id']);
|
|
self::userOfflineTask($outUser['0']['group_id']);
|
|
@@ -1221,8 +1262,32 @@ class Events
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case -2:
|
|
case -2:
|
|
|
|
|
+ $waitMsg = '暂时没有客服上班,请稍后再咨询。';
|
|
|
|
|
+ // 逐一通知
|
|
|
|
|
+ foreach (self::$global->userList as $vo) {
|
|
|
|
|
+
|
|
|
|
|
+ $waitMessage = [
|
|
|
|
|
+ 'message_type' => 'wait',
|
|
|
|
|
+ 'data' => [
|
|
|
|
|
+ 'content' => $waitMsg,
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ Gateway::sendToClient($vo['client_id'], json_encode($waitMessage, 256));
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
case -3:
|
|
case -3:
|
|
|
|
|
+ $waitMsg = '暂时没有客服上班,请稍后再咨询。';
|
|
|
|
|
+ // 逐一通知
|
|
|
|
|
+ foreach (self::$global->userList as $vo) {
|
|
|
|
|
+
|
|
|
|
|
+ $waitMessage = [
|
|
|
|
|
+ 'message_type' => 'wait',
|
|
|
|
|
+ 'data' => [
|
|
|
|
|
+ 'content' => $waitMsg,
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ Gateway::sendToClient($vo['client_id'], json_encode($waitMessage, 256));
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
case -4:
|
|
case -4:
|
|
|
// 逐一通知
|
|
// 逐一通知
|
|
@@ -1363,7 +1428,7 @@ class Events
|
|
|
|
|
|
|
|
case -1:
|
|
case -1:
|
|
|
$waitMsg = '暂时没有客服上班,请稍后再咨询。';
|
|
$waitMsg = '暂时没有客服上班,请稍后再咨询。';
|
|
|
- Gateway::sendToClient($client_id, json_encode(['message_type' => "noservice", 'data' => ['content' => $waitMsg]], 256));
|
|
|
|
|
|
|
+ Gateway::sendToClient($client_id, json_encode(['message_type' => "notice", 'content' => $waitMsg], 256));
|
|
|
Gateway::closeClient($client_id);
|
|
Gateway::closeClient($client_id);
|
|
|
return;
|
|
return;
|
|
|
break;
|
|
break;
|
|
@@ -1711,7 +1776,7 @@ class Events
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// 查询未断开的工单.
|
|
// 查询未断开的工单.
|
|
|
- $serviceLog = self::$db->query("SELECT `servicelog_id`,`client_id`,`start_time` FROM `ws_service_log` WHERE `status`='1' OR `status`='3'");
|
|
|
|
|
|
|
+ $serviceLog = self::$db->query("SELECT `servicelog_id`,`client_id`,`start_time`,`user_id`,`kf_id`,`group_id` FROM `ws_service_log` WHERE `status`='1' OR `status`='3'");
|
|
|
$whereOr = '1=0';
|
|
$whereOr = '1=0';
|
|
|
foreach ($serviceLog as $k => $v) {
|
|
foreach ($serviceLog as $k => $v) {
|
|
|
if ($k == 0) {
|
|
if ($k == 0) {
|
|
@@ -1732,14 +1797,30 @@ class Events
|
|
|
$setUnoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data'] - 60) . ' second');
|
|
$setUnoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data'] - 60) . ' second');
|
|
|
$unoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data']) . ' second');
|
|
$unoperated = strtotime('-' . (self::$global->unoperated['systemconfig_data']) . ' second');
|
|
|
$noResponse = strtotime('-' . (self::$global->noResponse['systemconfig_data']) . ' second');
|
|
$noResponse = strtotime('-' . (self::$global->noResponse['systemconfig_data']) . ' second');
|
|
|
- // 访客静默超时.
|
|
|
|
|
foreach ($serviceLog as $k => $v) {
|
|
foreach ($serviceLog as $k => $v) {
|
|
|
|
|
+ // 会话超时关闭.
|
|
|
|
|
+ if ($v['start_time'] <= $overtime) {
|
|
|
|
|
+ $servicelog_id = $v['servicelog_id'];
|
|
|
|
|
+ self::$db->query("update `ws_service_log` set `servicelog_close_type` = 2 where `servicelog_id`= '$servicelog_id'");
|
|
|
|
|
+ self::serverClose($v['client_id'], $servicelog_id, $v['user_id'], $v['kf_id'], $v['group_id']);
|
|
|
|
|
+ // 如果小于设定时间前一分钟则给出提示.
|
|
|
|
|
+ } elseif ($v['start_time'] <= $setOvertime) {
|
|
|
|
|
+ $chat_message = [
|
|
|
|
|
+ 'message_type' => 'overtime',
|
|
|
|
|
+ 'data' => [
|
|
|
|
|
+ 'content' => self::$global->overtime['systemconfig_content'],
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ Gateway::sendToClient($v['client_id'], json_encode($chat_message, 256));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 访客静默超时.
|
|
|
|
|
+ // 如果没有说一句话.
|
|
|
if (!strlen(array_search($v['servicelog_id'], array_column($chatLog, 'servicelog_id')))) {
|
|
if (!strlen(array_search($v['servicelog_id'], array_column($chatLog, 'servicelog_id')))) {
|
|
|
- // 如果小于设定时间则关闭会话.
|
|
|
|
|
if ($v['start_time'] <= $unoperated) {
|
|
if ($v['start_time'] <= $unoperated) {
|
|
|
$servicelog_id = $v['servicelog_id'];
|
|
$servicelog_id = $v['servicelog_id'];
|
|
|
self::$db->query("update `ws_service_log` set `servicelog_close_type` = 1 where `servicelog_id`= '$servicelog_id'");
|
|
self::$db->query("update `ws_service_log` set `servicelog_close_type` = 1 where `servicelog_id`= '$servicelog_id'");
|
|
|
- self::serverClose($v['client_id'], $servicelog_id);
|
|
|
|
|
|
|
+ self::serverClose($v['client_id'], $servicelog_id, $v['user_id'], $v['kf_id'], $v['group_id']);
|
|
|
// 如果小于设定时间前一分钟则给出提示.
|
|
// 如果小于设定时间前一分钟则给出提示.
|
|
|
} elseif ($v['start_time'] <= $setUnoperated) {
|
|
} elseif ($v['start_time'] <= $setUnoperated) {
|
|
|
$chat_message = [
|
|
$chat_message = [
|
|
@@ -1752,17 +1833,16 @@ class Events
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // 循环检测会话时效,会话超时关闭.
|
|
|
|
|
|
|
+ // 访客静默超时.如果说了话
|
|
|
foreach ($chatLog as $k => $v) {
|
|
foreach ($chatLog as $k => $v) {
|
|
|
- $toWho = substr($v['to_id'], 0, 2);
|
|
|
|
|
// 如果对话为客服的最后一次对话且时间小于设定时间则结束工单.
|
|
// 如果对话为客服的最后一次对话且时间小于设定时间则结束工单.
|
|
|
- if ($v['time_line'] <= $overtime) {
|
|
|
|
|
|
|
+ if ($v['time_line'] <= $unoperated) {
|
|
|
$found_key = array_search($v['servicelog_id'], array_column($serviceLog, 'servicelog_id'));
|
|
$found_key = array_search($v['servicelog_id'], array_column($serviceLog, 'servicelog_id'));
|
|
|
$servicelog_id = $v['servicelog_id'];
|
|
$servicelog_id = $v['servicelog_id'];
|
|
|
- self::$db->query("update `ws_service_log` set `servicelog_close_type` = 2 where `servicelog_id`= '$servicelog_id'");
|
|
|
|
|
- self::serverClose($serviceLog[$found_key]['client_id'], $servicelog_id);
|
|
|
|
|
|
|
+ self::$db->query("update `ws_service_log` set `servicelog_close_type` = 1 where `servicelog_id`= '$servicelog_id'");
|
|
|
|
|
+ self::serverClose($serviceLog[$found_key]['client_id'], $servicelog_id, $serviceLog[$found_key]['user_id'], $serviceLog[$found_key]['kf_id'], $serviceLog[$found_key]['group_id']);
|
|
|
// 如果对话为客服的最后一次对话且时间小于设定时间前一分钟则给出提示.
|
|
// 如果对话为客服的最后一次对话且时间小于设定时间前一分钟则给出提示.
|
|
|
- } elseif ($v['time_line'] <= $setOvertime) {
|
|
|
|
|
|
|
+ } elseif ($v['time_line'] <= $setUnoperated) {
|
|
|
$chat_message = [
|
|
$chat_message = [
|
|
|
'message_type' => 'overtime',
|
|
'message_type' => 'overtime',
|
|
|
'data' => [
|
|
'data' => [
|