修复房间列表在线人数不准:房间Tab每30秒自动刷新+懒清理掉线僵尸记录
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user