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

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

根因:直接跳转 URL 切换房间时浏览器不触发 leave 接口,
旧房间的 Redis hash 记录永久残留,导致计数虚高。
This commit is contained in:
2026-03-03 14:51:38 +08:00
parent 154d9ca8a2
commit 5b51754c58
+19 -10
View File
@@ -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 金币、播放满场烟花、发送全场欢迎通告