tapi/app/event/SysGatewayEvent.php
2025-08-29 22:26:37 +08:00

164 lines
5.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\event;
/**
* 用于检测业务代码死循环或者长时间阻塞等问题
* 如果发现业务卡死可以将下面declare打开去掉//注释并执行php start.php reload
* 然后观察一段时间workerman.log看是否有process_timeout异常
*/
//declare(ticks=1);
use app\entity\gateway\ws\OutMessage;
use app\entity\gateway\ws\PutMessage;
use app\entity\SysRole;
use app\entity\SysUser;
use app\enum\gateway\WsEventEnum;
use app\enum\gateway\WsTypeEnum;
use app\service\admin\LoginService;
use app\service\GatewayClientService;
use think\exception\ValidateException;
use think\facade\Event;
class SysGatewayEvent
{
public static function onMessage(string $client_id, string $message): void
{
// 1. 客户端应该传递标准的json数据
$message_data = json_decode($message, true);
if (!$message_data) {
return;
}
// 2. 封装进来的消息体
$put = new PutMessage(
$client_id,
isset($message_data['type']) ? (string)$message_data['type'] : '',
isset($message_data['event']) ? (string)$message_data['event'] : '',
isset($message_data['data']) ? (array)$message_data['data'] : []
);
/*
* 客户端登录
*/
if ($put->type == WsTypeEnum::System && $put->event == WsEventEnum::Login) {
self::authEvent($put);
return;
}
$isLogin = $put->login($_SESSION['user_id'] ?? 0,
$_SESSION['user_type'] ?? '',
$_SESSION['client'] ?? []
);
if (!$isLogin) {
echo "用户未登录\r\n";
// 未登录
return;
}
// 3. 调度: 根据类型执行不同的业务
switch ($put->type) {
// 客户端回应服务端的心跳
case WsTypeEnum::Pong:
break;
// 系统类型组操作
case WsTypeEnum::System:
switch ($put->event) {
case WsEventEnum::Lock_Client:
/**
* 触发后续其他事件
*/
Event::trigger("gateway.lockClient", [$put]);
break;
}
return;
}
}
public static function onClose(string $client_id)
{
echo "客户端:{$client_id},关闭了\r\n";
// 客户端离线的相关逻辑操作
if (isset($_SESSION['group_list']) && is_array($_SESSION['group_list'])) {
foreach ($_SESSION['group_list'] as $group) {
/*
* 客户端退出了某个房间
*/
GatewayClientService::sendToGroup($group, new OutMessage(
WsTypeEnum::System,
WsEventEnum::Client_quit_room,
));
}
}
/**
* 触发后续其他事件
*/
Event::trigger("gateway.clientClose", [$client_id]);
}
private static function authEvent(PutMessage $put): void
{
$token = $put->get('token', '');
$clientVersion = $put->get('clientVersion', '');
$clientName = $put->get('clientName', '');
$clientId = $put->get('clientId', '');
try {
$token = str_replace('Bearer ', '', $token);
$loginSrv = new LoginService();
$auth = $loginSrv->checkUserAccessToken($token);
} catch (ValidateException $e) {
// 校验失败
var_dump('E1.登录凭证校验失败: '.$e->getMessage());
return;
}
/**
* 加入同角色房间
*/
$sysUser = SysUser::find($auth->userId);
if (empty($sysUser)) {
return;
}
// 登录
$put->login($auth->userId, $auth->userType->value, [
'id' => $clientId,
'name' => $clientName,
'version' => $clientVersion
]);
/**
* 记录登录凭证信息到$SESSION中
*/
$_SESSION['user_id'] = $put->userId;
$_SESSION['user_type'] = $put->userType;
$_SESSION['client'] = [
'id' => $put->getClientId(),
'name' => $put->getClientName(),
'version' => $put->getClientVersion()
];
/**
* 推送登录成功的消息到客户端
*/
GatewayClientService::sendToClient($put->wsClientId, new OutMessage(
WsTypeEnum::System,
WsEventEnum::Login_SUCCESS,
['userId' => $auth->userId]
));
/**
*
*/
GatewayClientService::bindUid($put->wsClientId, $auth->userId);
/**
* 加入已登录的用户公共大厅
*/
GatewayClientService::joinGroup($put->wsClientId, 'PUBLIC_ROOM');
/**
* 加入同角色的房间
*/
$sysUser->roles->each(function (SysRole $role) use ($put) {
GatewayClientService::joinGroup($put->wsClientId, "ROLE_{$role['id']}");
});
/**
* 触发后续其他事件
*/
Event::trigger("gateway.clientLogin", compact('put','sysUser'));
}
}