From 725a38eac37cc719e96e6f3fc696332402005a08 Mon Sep 17 00:00:00 2001 From: pllx Date: Tue, 5 May 2026 21:48:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A4=BC=E5=8C=85=E9=A2=86?= =?UTF-8?q?=E5=8F=96=E5=BC=B9=E7=AA=97=E9=87=8D=E5=A4=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Services/GameBetBroadcastService.php | 26 +++++++++++++++++------ resources/js/chat-room/chat-events.js | 18 ++++++++++++++++ tests/Feature/RedPacketControllerTest.php | 2 ++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/app/Services/GameBetBroadcastService.php b/app/Services/GameBetBroadcastService.php index 4e23bdd..c839988 100644 --- a/app/Services/GameBetBroadcastService.php +++ b/app/Services/GameBetBroadcastService.php @@ -94,6 +94,8 @@ class GameBetBroadcastService toastMessage: "{$username} 抢到 {$formattedAmount} {$typeLabel}礼包", toastIcon: '🧧', toastColor: $toastColor, + toastActorUsername: $username, + skipToastForActor: true, ); } @@ -109,7 +111,23 @@ class GameBetBroadcastService string $toastIcon, string $toastColor, string $action = '', + ?string $toastActorUsername = null, + bool $skipToastForActor = false, ): void { + $toastNotification = [ + 'title' => $toastTitle, + 'message' => $toastMessage, + 'icon' => $toastIcon, + 'color' => $toastColor, + 'duration' => 8000, + ]; + + if ($toastActorUsername !== null) { + // 记录触发人用于前端去重,避免本人同时看到本地到账提示和公屏领取提示。 + $toastNotification['actor_username'] = $toastActorUsername; + $toastNotification['skip_for_actor'] = $skipToastForActor; + } + $message = [ 'id' => $this->chatState->nextMessageId($roomId), 'room_id' => $roomId, @@ -120,13 +138,7 @@ class GameBetBroadcastService 'font_color' => $fontColor, 'action' => $action, 'sent_at' => now()->toDateTimeString(), - 'toast_notification' => [ - 'title' => $toastTitle, - 'message' => $toastMessage, - 'icon' => $toastIcon, - 'color' => $toastColor, - 'duration' => 8000, - ], + 'toast_notification' => $toastNotification, ]; // 下注通知必须进房间 Presence 频道,确保当前房间所有在线人员都能看到右下角提示。 diff --git a/resources/js/chat-room/chat-events.js b/resources/js/chat-room/chat-events.js index 5dab2f3..90d449b 100644 --- a/resources/js/chat-room/chat-events.js +++ b/resources/js/chat-room/chat-events.js @@ -70,6 +70,20 @@ function runWhenDomReady(callback) { callback(); } +/** + * 判断 Toast 通知是否需要对当前用户隐藏。 + * + * @param {Record} toastNotification 右下角通知载荷 + * @returns {boolean} + */ +function shouldSkipToastForCurrentUser(toastNotification) { + if (!toastNotification?.skip_for_actor) { + return false; + } + + return String(toastNotification.actor_username || "") === String(window.chatContext?.username || ""); +} + // ── 禁言逻辑 ── function handleMutedEvent(e) { const state = getState(); @@ -417,6 +431,10 @@ export function bindChatEvents() { // 若消息携带 toast_notification 字段且当前用户是接收者或为公屏广播或为欢迎动作,弹右下角小卡片 if (msg.toast_notification && (msg.to_user === window.chatContext?.username || msg.to_user === '大家' || msg.action === '欢迎')) { const t = msg.toast_notification; + if (shouldSkipToastForCurrentUser(t)) { + return; + } + window.chatToast?.show({ title: t.title || "通知", message: t.message || "", diff --git a/tests/Feature/RedPacketControllerTest.php b/tests/Feature/RedPacketControllerTest.php index 6952644..44c8d66 100644 --- a/tests/Feature/RedPacketControllerTest.php +++ b/tests/Feature/RedPacketControllerTest.php @@ -280,6 +280,8 @@ class RedPacketControllerTest extends TestCase $this->assertFalse((bool) ($publicMessage['is_secret'] ?? true)); $this->assertStringContainsString('金币礼包', (string) ($publicMessage['toast_notification']['message'] ?? '')); $this->assertSame('🧧', $publicMessage['toast_notification']['icon'] ?? null); + $this->assertSame($user->username, $publicMessage['toast_notification']['actor_username'] ?? null); + $this->assertTrue((bool) ($publicMessage['toast_notification']['skip_for_actor'] ?? false)); } /**