3 Commits

2 changed files with 86 additions and 13 deletions
+20 -13
View File
@@ -200,34 +200,41 @@ function setFishingButton(text, disabled) {
} }
/** /**
* 启动自动钓鱼冷却倒计时。 * 启动自动钓鱼冷却倒计时(基于时间戳,不受浏览器后台节流影响)
* *
* @param {number} cooldown * @param {number} cooldown 冷却秒数
* @returns {void} * @returns {void}
*/ */
function startAutoFishingCooldown(cooldown) { function startAutoFishingCooldown(cooldown) {
let remaining = cooldown; const endTime = Date.now() + cooldown * 1000;
setFishingButton(`⏳ 冷却 ${remaining}s`, true); setFishingButton(`⏳ 冷却 ${cooldown}s`, true);
showAutoFishStopButton(cooldown); showAutoFishStopButton(cooldown);
// 基于时间戳更新倒计时 UI — 后台节流后回来也能准确显示
autoFishCooldownCountdown = window.setInterval(() => { autoFishCooldownCountdown = window.setInterval(() => {
remaining -= 1; const remaining = Math.max(0, Math.ceil((endTime - Date.now()) / 1000));
setFishingButton(`⏳ 冷却 ${remaining}s`, true); setFishingButton(`⏳ 冷却 ${remaining}s`, true);
if (remaining <= 0) { if (remaining <= 0) {
window.clearInterval(autoFishCooldownCountdown); window.clearInterval(autoFishCooldownCountdown);
autoFishCooldownCountdown = null; autoFishCooldownCountdown = null;
} }
}, 1000); }, 200);
autoFishCooldownTimer = window.setTimeout(() => { // 基于时间戳检测冷却结束 — 后台节流后立即触发
autoFishCooldownTimer = null; autoFishCooldownTimer = null;
hideAutoFishStopButton(); const checkEnd = () => {
if (Date.now() >= endTime) {
if (autoFishing) { autoFishCooldownTimer = null;
void startFishing(); hideAutoFishStopButton();
if (autoFishing) {
void startFishing();
}
return;
} }
}, cooldown * 1000); autoFishCooldownTimer = window.setTimeout(checkEnd, 200);
};
autoFishCooldownTimer = window.setTimeout(checkEnd, Math.min(cooldown * 1000, 200));
} }
/** /**
@@ -457,6 +457,23 @@ export function enqueueChatMessage(msg) {
state.chatMessageFlushTimer = scheduleFlush(flushQueuedChatMessages); state.chatMessageFlushTimer = scheduleFlush(flushQueuedChatMessages);
} }
/**
* 判断是否为普通用户聊天消息(非系统/游戏通知)。
*/
function isUserChatMessage(msg) {
if (!msg || !msg.from_user) return false;
const u = msg.from_user;
if (SYSTEM_USERS.includes(u)) return false;
if (u.endsWith("播报")) return false;
if (u === "百家乐" || u === "跑马") return false;
return true;
}
/** 后台恢复时系统通知最多保留条数 */
const MAX_SYSTEM_BURST = 20;
/** 后台恢复时超过该时间的系统通知直接丢弃(分钟) */
const MAX_SYSTEM_AGE_MINUTES = 10;
/** /**
* 分批渲染待处理消息,给动画、输入和滚动留出主线程时间。 * 分批渲染待处理消息,给动画、输入和滚动留出主线程时间。
*/ */
@@ -466,6 +483,55 @@ export function flushQueuedChatMessages() {
state.chatMessageFlushTimer = null; state.chatMessageFlushTimer = null;
// 大批量消息堆积(后台标签页恢复)时,保留所有用户聊天记录,
// 但过时的系统/游戏通知只保留最近 MAX_SYSTEM_BURST 条。
if (state.pendingChatMessages.length > MAX_SYSTEM_BURST + 30) {
const now = Date.now();
const maxAge = MAX_SYSTEM_AGE_MINUTES * 60 * 1000;
const totalSystem = state.pendingChatMessages.filter((m) => !isUserChatMessage(m)).length;
let systemSeen = 0;
let dropped = 0;
const filtered = state.pendingChatMessages.filter((msg) => {
if (isUserChatMessage(msg)) return true;
systemSeen++;
// 超过10分钟的系统通知直接丢弃
let msgTime = 0;
if (msg.sent_at) {
msgTime = new Date(msg.sent_at.replace(" ", "T")).getTime();
}
if (msgTime > 0 && now - msgTime > maxAge) {
dropped++;
return false;
}
// 从旧到新遍历,只保留最后 MAX_SYSTEM_BURST 条系统通知
const remainingAfter = totalSystem - systemSeen;
if (remainingAfter >= MAX_SYSTEM_BURST) {
dropped++;
return false;
}
return true;
});
if (dropped > 0) {
const container = state.container;
if (container) {
const notice = document.createElement("div");
notice.className = "msg-line msg-burst-notice";
notice.style.cssText =
"text-align:center;padding:6px 0;margin:4px 0;font-size:12px;color:#94a3b8;border-top:1px dashed #d1d5db;border-bottom:1px dashed #d1d5db;";
notice.textContent = `⏫ 省略了 ${dropped} 条系统通知`;
container.appendChild(notice);
}
}
state.pendingChatMessages = filtered;
}
const batch = state.pendingChatMessages.splice(0, CHAT_MESSAGE_FLUSH_BATCH_SIZE); const batch = state.pendingChatMessages.splice(0, CHAT_MESSAGE_FLUSH_BATCH_SIZE);
const renderBatch = createChatMessageRenderBatch(); const renderBatch = createChatMessageRenderBatch();
batch.forEach((msg) => appendMessage(msg, renderBatch)); batch.forEach((msg) => appendMessage(msg, renderBatch));