修复:切换房间时旧房间在线记录残留导致「幽灵在线」人数统计虚高

进入新房间 init() 时,先扫描 Redis 将用户从其他所有房间移除,
再写入新房间,确保每个用户同时只存在于一个房间的在线名单中。

根因:直接跳转 URL 切换房间时浏览器不触发 leave 接口,
旧房间的 Redis hash 记录永久残留,导致计数虚高。
This commit is contained in:
2026-03-03 14:51:38 +08:00
parent 154d9ca8a2
commit 5b51754c58
+11 -2
View File
@@ -66,7 +66,16 @@ class ChatController extends Controller
// 用户进房时间刷新 // 用户进房时间刷新
$user->update(['in_time' => now()]); $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'); $superLevel = (int) Sysparam::getValue('superlevel', '100');
// 获取当前在职职务信息(用于内容显示) // 获取当前在职职务信息(用于内容显示)
$activePosition = $user->activePosition; $activePosition = $user->activePosition;
@@ -84,7 +93,7 @@ class ChatController extends Controller
]; ];
$this->chatState->userJoin($id, $user->username, $userData); $this->chatState->userJoin($id, $user->username, $userData);
// 2. 广播 UserJoined 事件,通知房间内的其他人 // 3. 广播 UserJoined 事件,通知房间内的其他人
broadcast(new UserJoined($id, $user->username, $userData))->toOthers(); broadcast(new UserJoined($id, $user->username, $userData))->toOthers();
// 3. 新人首次进入:赠送 6666 金币、播放满场烟花、发送全场欢迎通告 // 3. 新人首次进入:赠送 6666 金币、播放满场烟花、发送全场欢迎通告