From 2c8cb212066748c87e0053527542e0ae53fecd7b Mon Sep 17 00:00:00 2001 From: pllx Date: Mon, 27 Apr 2026 14:43:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=99=AE=E9=80=9A=E5=AE=9A?= =?UTF-8?q?=E5=90=91=E5=8F=91=E8=A8=80=E5=85=AC=E5=B1=8F=E5=8F=AF=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Events/MessageSent.php | 12 ++-- app/Http/Controllers/ChatController.php | 4 +- tests/Feature/ChatControllerTest.php | 74 ++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/app/Events/MessageSent.php b/app/Events/MessageSent.php index fc2cead..5e6f56d 100644 --- a/app/Events/MessageSent.php +++ b/app/Events/MessageSent.php @@ -26,9 +26,9 @@ class MessageSent implements ShouldBroadcastNow use Dispatchable, InteractsWithSockets, SerializesModels; /** - * Create a new event instance. + * 创建消息广播事件实例。 * - * @param int $roomId 房间ID + * @param int $roomId 房间 ID * @param array $message 发送的消息数据 */ public function __construct( @@ -39,8 +39,8 @@ class MessageSent implements ShouldBroadcastNow /** * 获取消息应广播到的频道。 * - * 公共消息走房间 Presence 频道; - * 定向消息 / 悄悄话只发给发送方与接收方的私有用户频道。 + * 公共消息和普通定向发言走房间 Presence 频道; + * 悄悄话只发给发送方与接收方的私有用户频道。 * * @return array */ @@ -78,9 +78,7 @@ class MessageSent implements ShouldBroadcastNow */ private function shouldBroadcastPrivately(): bool { - $toUser = trim((string) ($this->message['to_user'] ?? '')); - - return $toUser !== '' && $toUser !== '大家'; + return (bool) ($this->message['is_secret'] ?? false); } /** diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index 4218242..63f015c 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -248,8 +248,8 @@ class ChatController extends Controller return $fromUser === $username || $toUser === $username; } - // 对特定人说话:只显示发给自己或自己发出的(含系统通知) - return $fromUser === $username || $toUser === $username; + // 非悄悄话的定向发言仍属于公屏消息,历史回放也要让房间内其他人可见。 + return true; })); // 7. 如果用户有在职職务,开始记录这次入场的心跳登录 (仅初次) diff --git a/tests/Feature/ChatControllerTest.php b/tests/Feature/ChatControllerTest.php index ec4aac8..ebaa5d6 100644 --- a/tests/Feature/ChatControllerTest.php +++ b/tests/Feature/ChatControllerTest.php @@ -568,9 +568,54 @@ class ChatControllerTest extends TestCase } /** - * 测试定向消息仅广播到发送方与接收方私有频道。 + * 测试历史消息会让旁观用户看到普通定向发言,但不会泄露悄悄话。 */ - public function test_targeted_message_event_uses_private_user_channels(): void + public function test_room_history_keeps_non_secret_targeted_messages_visible_to_others(): void + { + $room = Room::create(['room_name' => 'histtg']); + $sender = User::factory()->create(['username' => 'history-sender']); + $receiver = User::factory()->create(['username' => 'history-receiver']); + $observer = User::factory()->create(['username' => 'history-observer']); + $chatState = app(\App\Services\ChatStateService::class); + + $chatState->pushMessage($room->id, [ + 'id' => 1, + 'room_id' => $room->id, + 'from_user' => $sender->username, + 'to_user' => $receiver->username, + 'content' => '公开对你说', + 'is_secret' => false, + 'font_color' => '#000000', + 'action' => '', + 'sent_at' => now()->toDateTimeString(), + ]); + $chatState->pushMessage($room->id, [ + 'id' => 2, + 'room_id' => $room->id, + 'from_user' => $sender->username, + 'to_user' => $receiver->username, + 'content' => '旁人不可见悄悄话', + 'is_secret' => true, + 'font_color' => '#000000', + 'action' => '', + 'sent_at' => now()->toDateTimeString(), + ]); + + $response = $this->actingAs($observer)->get(route('chat.room', $room->id)); + + $response->assertOk(); + $response->assertViewHas('historyMessages', function (array $messages): bool { + $contents = collect($messages)->pluck('content'); + + return $contents->contains('公开对你说') + && ! $contents->contains('旁人不可见悄悄话'); + }); + } + + /** + * 测试悄悄话消息仅广播到发送方与接收方私有频道。 + */ + public function test_secret_message_event_uses_private_user_channels(): void { $sender = User::factory()->create(['username' => 'sender-user']); $receiver = User::factory()->create(['username' => 'receiver-user']); @@ -597,7 +642,30 @@ class ChatControllerTest extends TestCase } /** - * 测试公共消息仍广播到房间 Presence 频道。 + * 测试普通定向消息仍广播到房间 Presence 频道。 + */ + public function test_non_secret_targeted_message_event_uses_room_presence_channel(): void + { + $event = new MessageSent(3, [ + 'room_id' => 3, + 'from_user' => 'tester', + 'to_user' => 'receiver-user', + 'content' => '公开对你说', + 'is_secret' => false, + 'font_color' => '#000000', + 'action' => '', + 'sent_at' => now()->toDateTimeString(), + ]); + + $channels = $event->broadcastOn(); + + $this->assertCount(1, $channels); + $this->assertInstanceOf(PresenceChannel::class, $channels[0]); + $this->assertSame('presence-room.3', $channels[0]->name); + } + + /** + * 测试对大家消息仍广播到房间 Presence 频道。 */ public function test_public_message_event_still_uses_room_presence_channel(): void {