修复房间列表在线人数不准:房间Tab每30秒自动刷新+懒清理掉线僵尸记录

This commit is contained in:
2026-03-17 20:54:43 +08:00
parent 7d984ebe64
commit ad754a704e
2 changed files with 30 additions and 1 deletions

View File

@@ -28,6 +28,8 @@ class ChatStateService
{
$key = "room:{$roomId}:users";
Redis::hset($key, $username, json_encode($info, JSON_UNESCAPED_UNICODE));
// 写入活跃标记90秒 TTL心跳每次刷新超出则被认定为掉线
Redis::setex("room:{$roomId}:alive:{$username}", 90, 1);
}
/**
@@ -40,6 +42,19 @@ class ChatStateService
{
$key = "room:{$roomId}:users";
Redis::hdel($key, $username);
// 同时删除活跃标记
Redis::del("room:{$roomId}:alive:{$username}");
}
/**
* 刷新用户心跳活跃标记(心跳接口调用)。
*
* @param int $roomId 房间ID
* @param string $username 用户名
*/
public function refreshAlive(int $roomId, string $username): void
{
Redis::setex("room:{$roomId}:alive:{$username}", 90, 1);
}
/**
@@ -85,6 +100,13 @@ class ChatStateService
$result = [];
foreach ($users as $username => $jsonInfo) {
// 过滤掌心跳已超出活跃窗口的用户(掉线超 90秒
if (! Redis::exists("room:{$roomId}:alive:{$username}")) {
// 懒清理:顺手将僵尸记录从 hash 中移除
Redis::hdel($key, $username);
continue;
}
$result[$username] = json_decode($jsonInfo, true);
}

View File

@@ -42,15 +42,22 @@
let _maxMsgId = 0; // 记录当前收到的最大消息 ID
// ── Tab 切换 ──────────────────────────────────────
let _roomsRefreshTimer = null;
function switchTab(tab) {
// 切换名单/房间 面板
['users', 'rooms'].forEach(t => {
document.getElementById('panel-' + t).style.display = t === tab ? 'block' : 'none';
document.getElementById('tab-' + t)?.classList.toggle('active', t === tab);
});
// 房间 Tab拉取在线人数列表
// 房间 Tab立即拉取 + 每 30 秒自动刷新在线人数
if (tab === 'rooms') {
loadRoomsOnlineStatus();
clearInterval(_roomsRefreshTimer);
_roomsRefreshTimer = setInterval(loadRoomsOnlineStatus, 30000);
} else {
clearInterval(_roomsRefreshTimer);
_roomsRefreshTimer = null;
}
}