From 5b51754c589096964b2c6284c8871eac40276a4f Mon Sep 17 00:00:00 2001 From: lkddi Date: Tue, 3 Mar 2026 14:51:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E6=88=BF=E9=97=B4=E6=97=B6=E6=97=A7=E6=88=BF=E9=97=B4=E5=9C=A8?= =?UTF-8?q?=E7=BA=BF=E8=AE=B0=E5=BD=95=E6=AE=8B=E7=95=99=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E3=80=8C=E5=B9=BD=E7=81=B5=E5=9C=A8=E7=BA=BF=E3=80=8D=E4=BA=BA?= =?UTF-8?q?=E6=95=B0=E7=BB=9F=E8=AE=A1=E8=99=9A=E9=AB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 进入新房间 init() 时,先扫描 Redis 将用户从其他所有房间移除, 再写入新房间,确保每个用户同时只存在于一个房间的在线名单中。 根因:直接跳转 URL 切换房间时浏览器不触发 leave 接口, 旧房间的 Redis hash 记录永久残留,导致计数虚高。 --- app/Http/Controllers/ChatController.php | 29 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index 4699188..bfed7ae 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -66,25 +66,34 @@ class ChatController extends Controller // 用户进房时间刷新 $user->update(['in_time' => now()]); - // 1. 将当前用户加入到 Redis 房间在线列表(包含 VIP 和管理员信息) + // 1. 先将用户从其他所有房间的在线名单中移除(切换房间时旧记录自动清理) + // 避免直接跳转页面时 leave 接口未触发导致"幽灵在线"问题 + $oldRoomIds = $this->chatState->getUserRooms($user->username); + foreach ($oldRoomIds as $oldRoomId) { + if ($oldRoomId !== $id) { + $this->chatState->userLeave($oldRoomId, $user->username); + } + } + + // 2. 将当前用户加入到 Redis 房间在线列表(包含 VIP 和管理员信息) $superLevel = (int) Sysparam::getValue('superlevel', '100'); // 获取当前在职职务信息(用于内容显示) $activePosition = $user->activePosition; $userData = [ - 'user_id' => $user->id, - 'level' => $user->user_level, - 'sex' => $user->sex, - 'headface' => $user->headface, - 'vip_icon' => $user->vipIcon(), - 'vip_name' => $user->vipName(), - 'vip_color' => $user->isVip() ? ($user->vipLevel?->color ?? '') : '', - 'is_admin' => $user->user_level >= $superLevel, + 'user_id' => $user->id, + 'level' => $user->user_level, + 'sex' => $user->sex, + 'headface' => $user->headface, + 'vip_icon' => $user->vipIcon(), + 'vip_name' => $user->vipName(), + 'vip_color' => $user->isVip() ? ($user->vipLevel?->color ?? '') : '', + 'is_admin' => $user->user_level >= $superLevel, 'position_icon' => $activePosition?->position?->icon ?? '', 'position_name' => $activePosition?->position?->name ?? '', ]; $this->chatState->userJoin($id, $user->username, $userData); - // 2. 广播 UserJoined 事件,通知房间内的其他人 + // 3. 广播 UserJoined 事件,通知房间内的其他人 broadcast(new UserJoined($id, $user->username, $userData))->toOthers(); // 3. 新人首次进入:赠送 6666 金币、播放满场烟花、发送全场欢迎通告