diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php
index 2e49a6e..828b052 100644
--- a/app/Http/Controllers/ChatController.php
+++ b/app/Http/Controllers/ChatController.php
@@ -197,7 +197,11 @@ class ChatController extends Controller
// 统一走通用进场播报逻辑,管理员不再发送单独的特殊登录提示。
[$text, $color] = $this->broadcast->buildEntryBroadcast($user);
- $vipPresencePayload = $this->broadcast->buildVipPresencePayload($user, 'join');
+ $ridePresencePayload = $this->rideService->buildPresencePayload($user);
+ // 座驾优先级高于会员进场主题,避免同一用户进房时同时播放两套全屏特效。
+ $vipPresencePayload = $ridePresencePayload
+ ? []
+ : $this->broadcast->buildVipPresencePayload($user, 'join');
$generalWelcomeMsg = [
'id' => $this->chatState->nextMessageId($id),
@@ -232,14 +236,13 @@ class ChatController extends Controller
broadcast(new \App\Events\EffectBroadcast($id, $vipPresencePayload['presence_effect'], $user->username))->toOthers();
}
- $ridePresencePayload = $this->rideService->buildPresencePayload($user);
if ($ridePresencePayload) {
$rideWelcomeMsg = [
'id' => $this->chatState->nextMessageId($id),
'room_id' => $id,
'from_user' => '座驾播报',
'to_user' => '大家',
- 'content' => "{$ridePresencePayload['ride_icon']} {$ridePresencePayload['welcome_text']}",
+ 'content' => "{$ridePresencePayload['ride_icon']} {$ridePresencePayload['identity_text']} · {$ridePresencePayload['welcome_text']}",
'is_secret' => false,
'font_color' => '#0f766e',
'action' => 'ride_presence',
diff --git a/app/Services/RideService.php b/app/Services/RideService.php
index fc459af..5059c50 100644
--- a/app/Services/RideService.php
+++ b/app/Services/RideService.php
@@ -28,6 +28,7 @@ class RideService
*/
public function __construct(
private readonly UserCurrencyService $currencyService,
+ private readonly ChatUserPresenceService $chatUserPresenceService,
) {}
/**
@@ -234,12 +235,14 @@ class RideService
'{name}' => $user->username,
'{ride}' => $item->name,
]);
+ $identitySummary = $this->chatUserPresenceService->buildIdentitySummary($user);
return [
'ride_key' => $rideKey,
'ride_name' => $item->name,
'ride_icon' => (string) ($item->icon ?? '🚘'),
'effect_title' => "{$user->username} 乘坐【{$item->name}】闪亮登场",
+ 'identity_text' => ChatContentSanitizer::htmlText($identitySummary['inline']),
'welcome_text' => ChatContentSanitizer::htmlText($rendered),
];
}
diff --git a/tests/Feature/ChatControllerTest.php b/tests/Feature/ChatControllerTest.php
index 9022719..4b4328c 100644
--- a/tests/Feature/ChatControllerTest.php
+++ b/tests/Feature/ChatControllerTest.php
@@ -1142,6 +1142,79 @@ class ChatControllerTest extends TestCase
], $response->viewData('initialRideEffectOptions'));
}
+ /**
+ * 测试会员用户有座驾时优先播放座驾,并在座驾播报中展示完整身份摘要。
+ */
+ public function test_ride_presence_takes_priority_over_vip_presence_and_includes_identity_summary(): void
+ {
+ $room = Room::create(['room_name' => 'rvip']);
+ $vipLevel = VipLevel::factory()->create([
+ 'name' => '至尊会员',
+ 'icon' => '👑',
+ 'join_effect' => 'lightning',
+ 'join_banner_style' => 'storm',
+ 'allow_custom_messages' => true,
+ ]);
+ $user = User::factory()->create([
+ 'vip_level_id' => $vipLevel->id,
+ 'hy_time' => now()->addDays(30),
+ 'custom_join_message' => '{username} 带着风暴王座闪耀降临',
+ 'has_received_new_gift' => true,
+ ]);
+ $department = Department::create([
+ 'name' => '战备部',
+ 'rank' => 90,
+ 'color' => '#0f766e',
+ 'sort_order' => 1,
+ ]);
+ $position = Position::create([
+ 'department_id' => $department->id,
+ 'name' => '试飞官',
+ 'icon' => '🛡️',
+ 'rank' => 90,
+ 'level' => 90,
+ 'sort_order' => 1,
+ ]);
+ UserPosition::create([
+ 'user_id' => $user->id,
+ 'position_id' => $position->id,
+ 'appointed_at' => now(),
+ 'is_active' => true,
+ ]);
+ $ride = Ride::query()->updateOrCreate(['slug' => 'ride_99a'], [
+ 'name' => '99A测试座驾',
+ 'effect_key' => '99a',
+ 'description' => '测试座驾',
+ 'icon' => '🛡️',
+ 'price' => 28888,
+ 'duration_days' => 7,
+ 'sort_order' => 90,
+ 'is_active' => true,
+ 'welcome_message' => '【{name}】乘坐【{ride}】闪亮登场',
+ ]);
+ UserRidePurchase::create([
+ 'user_id' => $user->id,
+ 'ride_id' => $ride->id,
+ 'status' => 'active',
+ 'price_paid' => 28888,
+ 'expires_at' => now()->addDays(3),
+ ]);
+
+ $response = $this->actingAs($user)->get(route('chat.room', $room->id));
+
+ $response->assertOk();
+ $history = collect($response->viewData('historyMessages'));
+ $rideMessage = $history->first(fn (array $message): bool => ($message['welcome_kind'] ?? '') === 'ride_presence');
+ $vipPresenceMessage = $history->first(fn (array $message): bool => ($message['action'] ?? '') === 'vip_presence');
+
+ $this->assertNotNull($rideMessage);
+ $this->assertNull($vipPresenceMessage);
+ $this->assertStringContainsString('部门 战备部 · 职务 🛡️ 试飞官 · 会员 👑 至尊会员', $rideMessage['content']);
+ $this->assertStringContainsString($user->username, $rideMessage['content']);
+ $this->assertSame('99a', $response->viewData('initialRideEffect'));
+ $this->assertNull($response->viewData('initialPresenceTheme'));
+ }
+
/**
* 测试过期座驾用户进房时不会触发座驾播报。
*/