修复新人进房欢迎消息显示
This commit is contained in:
@@ -127,14 +127,9 @@ class ChatController extends Controller
|
||||
// 必须在推送新消息之前执行,否则可能误删刚刚创建的欢迎播报
|
||||
$this->chatState->removeOldWelcomeMessages($id, $user->username);
|
||||
|
||||
// 新人首次进入:赠送 6666 金币、播放满场烟花、发送全场欢迎通告
|
||||
// 双重校验:优先以 has_received_new_gift 标记为准,若标记异常则用 created_at 时间兜底
|
||||
// 新人首次进入:赠送 6666 金币、播放满场烟花、发送全场欢迎通告。
|
||||
$user->refresh();
|
||||
$isNewbie = ! $user->has_received_new_gift;
|
||||
// 兜底:如果用户创建时间在 2 分钟内,即使标记异常也按新人处理
|
||||
if (! $isNewbie && $user->created_at && $user->created_at->diffInSeconds(now()) < 120) {
|
||||
$isNewbie = true;
|
||||
}
|
||||
if ($isNewbie) {
|
||||
// 通过统一积分服务发放新人礼包 6666 金币并记录流水
|
||||
$this->currencyService->change(
|
||||
@@ -153,6 +148,7 @@ class ChatController extends Controller
|
||||
'font_color' => '#b91c1c',
|
||||
'action' => '',
|
||||
'welcome_user' => $user->username,
|
||||
'welcome_kind' => 'newbie_bonus',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
$this->chatState->pushMessage($id, $newbieMsg);
|
||||
@@ -178,11 +174,13 @@ class ChatController extends Controller
|
||||
'id' => $this->chatState->nextMessageId($id),
|
||||
'room_id' => $id,
|
||||
'from_user' => 'AI小班长',
|
||||
'to_user' => $user->username,
|
||||
'to_user' => '大家',
|
||||
'content' => $aiWelcomeContent,
|
||||
'is_secret' => false,
|
||||
'font_color' => '#16a34a',
|
||||
'action' => '大声宣告',
|
||||
'welcome_user' => $user->username,
|
||||
'welcome_kind' => 'ai_newbie_welcome',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
$this->chatState->pushMessage($id, $aiWelcomeMsg);
|
||||
@@ -204,6 +202,7 @@ class ChatController extends Controller
|
||||
'font_color' => $color,
|
||||
'action' => empty($vipPresencePayload) ? 'system_welcome' : 'vip_presence',
|
||||
'welcome_user' => $user->username,
|
||||
'welcome_kind' => 'entry_broadcast',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
|
||||
|
||||
@@ -220,8 +220,9 @@ class ChatStateService
|
||||
|
||||
foreach ($messages as $msgJson) {
|
||||
$msg = json_decode($msgJson, true);
|
||||
// 只要消息里带了 welcome_user 且等于当前用户,就抛弃这条旧的
|
||||
if ($msg && isset($msg['welcome_user']) && $msg['welcome_user'] === $username) {
|
||||
// 只清理普通进出播报,避免误删新人礼包公告和 AI 小班长新人欢迎。
|
||||
$welcomeKind = $msg['welcome_kind'] ?? 'entry_broadcast';
|
||||
if ($msg && isset($msg['welcome_user']) && $msg['welcome_user'] === $username && $welcomeKind === 'entry_broadcast') {
|
||||
continue;
|
||||
}
|
||||
$filtered[] = $msgJson;
|
||||
|
||||
@@ -2642,13 +2642,20 @@
|
||||
|
||||
// 后端下发的带有 welcome_user 的也是系统欢迎/离开消息,加上属性标记
|
||||
if (msg.welcome_user) {
|
||||
const welcomeKind = msg.welcome_kind || 'entry_broadcast';
|
||||
div.setAttribute('data-system-user', msg.welcome_user);
|
||||
// 收到后端来的新欢迎消息时,把界面上该用户旧的都删掉
|
||||
const welcomeSelector = `[data-system-user="${msg.welcome_user}"]`;
|
||||
const oldWelcomes = container.querySelectorAll(welcomeSelector);
|
||||
oldWelcomes.forEach(el => el.remove());
|
||||
renderBatch?.publicFragment.querySelectorAll(welcomeSelector).forEach(el => el.remove());
|
||||
renderBatch?.privateFragment.querySelectorAll(welcomeSelector).forEach(el => el.remove());
|
||||
div.setAttribute('data-system-welcome-kind', welcomeKind);
|
||||
// 收到后端来的同类欢迎消息时,只替换同类旧消息,避免进场播报误删新人礼包和 AI 欢迎。
|
||||
const removeSameWelcome = (root) => {
|
||||
root?.querySelectorAll('[data-system-user]').forEach(el => {
|
||||
if (el.dataset.systemUser === msg.welcome_user && (el.dataset.systemWelcomeKind || 'entry_broadcast') === welcomeKind) {
|
||||
el.remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
removeSameWelcome(container);
|
||||
removeSameWelcome(renderBatch?.publicFragment);
|
||||
removeSameWelcome(renderBatch?.privateFragment);
|
||||
}
|
||||
|
||||
// 路由规则(复刻原版):
|
||||
|
||||
@@ -721,6 +721,8 @@ class ChatControllerTest extends TestCase
|
||||
$room = Room::create(['room_name' => 'annsafe']);
|
||||
$user = $this->createUserWithPositionPermissions([
|
||||
PositionPermissionRegistry::ROOM_ANNOUNCEMENT,
|
||||
], [
|
||||
'has_received_new_gift' => true,
|
||||
]);
|
||||
|
||||
$this->actingAs($user)->get(route('chat.room', $room->id));
|
||||
@@ -992,6 +994,38 @@ class ChatControllerTest extends TestCase
|
||||
$this->assertStringContainsString($user->username, $presenceMessage['presence_text']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试新人首次进房时首屏历史包含礼包公告、AI 欢迎和普通进场播报。
|
||||
*/
|
||||
public function test_newbie_first_join_keeps_bonus_ai_and_entry_welcome_messages(): void
|
||||
{
|
||||
$room = Room::create(['room_name' => 'newbie']);
|
||||
$user = User::factory()->create([
|
||||
'jjb' => 0,
|
||||
'has_received_new_gift' => false,
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->get(route('chat.room', $room->id));
|
||||
|
||||
$response->assertOk();
|
||||
$history = collect($response->viewData('historyMessages'));
|
||||
|
||||
$newbieBonusMessage = $history->first(fn (array $message): bool => ($message['welcome_kind'] ?? '') === 'newbie_bonus');
|
||||
$aiWelcomeMessage = $history->first(fn (array $message): bool => ($message['welcome_kind'] ?? '') === 'ai_newbie_welcome');
|
||||
$entryMessage = $history->first(fn (array $message): bool => ($message['welcome_kind'] ?? '') === 'entry_broadcast');
|
||||
|
||||
$this->assertNotNull($newbieBonusMessage);
|
||||
$this->assertSame('系统公告', $newbieBonusMessage['from_user']);
|
||||
$this->assertStringContainsString('6666 金币新人大礼包', $newbieBonusMessage['content']);
|
||||
$this->assertNotNull($aiWelcomeMessage);
|
||||
$this->assertSame('AI小班长', $aiWelcomeMessage['from_user']);
|
||||
$this->assertSame('大家', $aiWelcomeMessage['to_user']);
|
||||
$this->assertNotNull($entryMessage);
|
||||
$this->assertSame($user->username, $entryMessage['welcome_user']);
|
||||
$this->assertTrue($user->fresh()->has_received_new_gift);
|
||||
$this->assertSame(6666, (int) $user->fresh()->jjb);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试可以获取所有房间的在线人数状态。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user