diff --git a/resources/js/chat-room/fishing.js b/resources/js/chat-room/fishing.js index 746c473..a984a6f 100644 --- a/resources/js/chat-room/fishing.js +++ b/resources/js/chat-room/fishing.js @@ -50,19 +50,12 @@ function appendFishingMessage(html) { return; } - const blockedSet = window.chatState?.blockedSystemSenders; - const isBlocked = blockedSet instanceof Set && blockedSet.has("钓鱼播报"); const line = document.createElement("div"); line.className = "msg-line"; - line.dataset.blockKey = "钓鱼播报"; - if (isBlocked) { - line.dataset.blockHidden = "1"; - line.style.display = "none"; - } line.innerHTML = html; container.appendChild(line); - if (!isBlocked && shouldAutoScroll()) { + if (shouldAutoScroll()) { container.scrollTop = container.scrollHeight; } } @@ -233,6 +226,8 @@ function hasActiveFishingSession() { * @returns {void} */ function startAutoFishingCooldown(cooldown) { + clearAutoFishingTimers(); + const endTime = Date.now() + cooldown * 1000; setFishingButton(`⏳ 冷却 ${cooldown}s`, true); showAutoFishStopButton(cooldown); @@ -254,10 +249,13 @@ function startAutoFishingCooldown(cooldown) { const checkEnd = () => { if (Date.now() >= endTime) { autoFishCooldownTimer = null; - hideAutoFishStopButton(); if (autoFishing) { + updateAutoFishStopButtonCountdown(0, "正在继续自动钓鱼"); void startFishing(); + return; } + + hideAutoFishStopButton(); return; } autoFishCooldownTimer = window.setTimeout(checkEnd, 200); @@ -272,7 +270,9 @@ function startAutoFishingCooldown(cooldown) { * @returns {void} */ function showAutoFishStopButton(cooldown) { - if (document.getElementById("auto-fish-stop-btn")) { + const currentButton = document.getElementById("auto-fish-stop-btn"); + if (currentButton) { + updateAutoFishStopButtonCountdown(cooldown); return; } @@ -304,16 +304,17 @@ function showAutoFishStopButton(cooldown) { * 同步更新停止自动钓鱼浮层上的冷却秒数,避免与主按钮倒计时不一致。 * * @param {number} cooldown + * @param {string|null} text * @returns {void} */ -function updateAutoFishStopButtonCountdown(cooldown) { +function updateAutoFishStopButtonCountdown(cooldown, text = null) { const hint = document.querySelector("#auto-fish-stop-btn .drag-hint"); if (!(hint instanceof HTMLElement)) { return; } - hint.textContent = `冷却 ${Number(cooldown) || 0}s · 可拖动`; + hint.textContent = text || `冷却 ${Number(cooldown) || 0}s · 可拖动`; } /** @@ -425,6 +426,12 @@ export async function startFishing() { const data = await response.json(); if (!response.ok || data.status !== "success") { + if (autoFishing && response.status === 429) { + // 服务端冷却 TTL 可能与前端倒计时有毫秒级误差,自动模式下按服务端剩余时间续等。 + startAutoFishingCooldown(Math.max(1, Number(data.cooldown) || 1)); + return; + } + window.chatDialog?.alert?.(data.message || "钓鱼失败", "操作失败", "#cc4444"); setFishingButton("🎣 钓鱼", false); return; @@ -439,11 +446,20 @@ export async function startFishing() { const bobber = createBobber(data.bobber_x, data.bobber_y); document.body.appendChild(bobber); + if (data.auto_fishing) { + showAutoFishStopButton(0); + updateAutoFishStopButtonCountdown(0, "等待鱼儿上钩 · 可拖动"); + } + fishingTimer = window.setTimeout(() => { + // 等待计时器触发后必须立即释放句柄,否则自动钓鱼冷却结束会误判仍有会话进行中。 + fishingTimer = null; bobber.classList.add("sinking"); bobber.textContent = "🐟"; if (data.auto_fishing) { + showAutoFishStopButton(0); + updateAutoFishStopButtonCountdown(0, "自动收竿中 · 可拖动"); appendFishingMessage(`🎣 自动钓鱼卡生效!自动收竿中... (剩余${Number(data.auto_fishing_minutes_left) || 0}分钟)`); fishingReelTimeout = window.setTimeout(() => { removeBobber(); diff --git a/resources/js/chat-room/message-renderer.js b/resources/js/chat-room/message-renderer.js index 7c08267..1e4cb4c 100644 --- a/resources/js/chat-room/message-renderer.js +++ b/resources/js/chat-room/message-renderer.js @@ -585,9 +585,13 @@ export function appendMessage(msg, renderBatch = null) { } const isMe = msg.from_user === window.chatContext?.username; + // 系统播报屏蔽只作用于公屏窗口;自己相关消息仍要进入包厢窗口,避免屏蔽误伤个人提示。 + const isIdiomWinnerHistory = msg.action === "idiom_result" && msg.winner_username === window.chatContext?.username; + const isRelatedToMe = isMe || msg.is_secret || msg.to_user === window.chatContext?.username || isIdiomWinnerHistory; const fontColor = msg.font_color || "#000000"; const blockRuleKey = resolveBlockedSystemSenderKey(msg); - const shouldHideByBlock = blockRuleKey ? state.blockedSystemSenders.has(blockRuleKey) : false; + const shouldApplyBlockRule = Boolean(blockRuleKey && !isRelatedToMe); + const shouldHideByBlock = shouldApplyBlockRule ? state.blockedSystemSenders.has(blockRuleKey) : false; const div = document.createElement("div"); div.className = "msg-line"; @@ -598,7 +602,7 @@ export function appendMessage(msg, renderBatch = null) { div.dataset.idiomRoundId = String(idiomRoundId); div.dataset.quizRoundId = String(idiomRoundId); } - if (blockRuleKey) { + if (shouldApplyBlockRule) { div.dataset.blockKey = blockRuleKey; } @@ -848,10 +852,6 @@ export function appendMessage(msg, renderBatch = null) { removeSameWelcome(renderBatch?.privateFragment); } - // 路由规则:公众窗口(say1) — 别人的公聊消息;包厢窗口(say2) — 自己发的 + 悄悄话 + 对自己说的 - const isIdiomWinnerHistory = msg.action === "idiom_result" && msg.winner_username === window.chatContext?.username; - const isRelatedToMe = isMe || msg.is_secret || msg.to_user === window.chatContext?.username || isIdiomWinnerHistory; - // 存点通知标记 const isAutoSave = (msg.from_user === "系统" || msg.from_user === "") && msg.content && (msg.content.includes("自动存点") || msg.content.includes("手动存点")); diff --git a/resources/js/chat-room/preferences-status.js b/resources/js/chat-room/preferences-status.js index 17cb753..3456845 100644 --- a/resources/js/chat-room/preferences-status.js +++ b/resources/js/chat-room/preferences-status.js @@ -673,27 +673,28 @@ export function syncBlockedSystemSenderCheckboxes() { */ export function setRenderedMessagesVisibilityBySender(blockKey, hidden) { const state = window.chatState; - [state?.container, state?.container2].forEach(targetContainer => { - if (!targetContainer) return; + const targetContainer = state?.container; + if (targetContainer) { targetContainer.querySelectorAll("[data-block-key]").forEach(node => { - if (node.dataset.blockKey === blockKey) { - if (hidden) { - node.dataset.blockHidden = "1"; - node.style.display = "none"; - } else if (node.dataset.blockHidden === "1") { - node.removeAttribute("data-block-hidden"); - node.style.display = ""; - } + if (node.dataset.blockKey !== blockKey) { + return; + } + + // 屏蔽项只清理公屏已有播报,包厢窗口保留用户自己的钓鱼过程和结果提示。 + if (hidden) { + node.dataset.blockHidden = "1"; + node.style.display = "none"; + } else if (node.dataset.blockHidden === "1") { + node.removeAttribute("data-block-hidden"); + node.style.display = ""; } }); - }); + } if (!hidden && state?.autoScroll) { const container = state.container; - const container2 = state.container2; if (container) container.scrollTop = container.scrollHeight; - if (container2) container2.scrollTop = container2.scrollHeight; } }