迁移聊天室上下文注入脚本

This commit is contained in:
2026-04-25 19:05:56 +08:00
parent 6f779edb91
commit 925f2498c5
3 changed files with 181 additions and 107 deletions
+105 -107
View File
@@ -36,114 +36,112 @@
$fishingCooldownSeconds = \Illuminate\Support\Facades\Redis::ttl($fishingCooldownKey);
$fishingCooldownSeconds = $fishingCooldownSeconds > 0 ? $fishingCooldownSeconds : 0;
@endphp
<script>
window.chatContext = {
roomId: {{ $room->id }},
userId: {{ $user->id }},
username: "{{ $user->username }}",
userSex: "{{ match ((int) $user->sex) {1 => '男',2 => '女',default => ''} }}",
userLevel: {{ $user->user_level }},
superLevel: {{ $superLevel }},
levelKick: {{ $levelKick }},
levelMute: {{ $levelMute }},
levelBan: {{ $levelBan }},
levelBanip: {{ $levelBanip }},
sendUrl: "{{ route('chat.send', $room->id) }}",
leaveUrl: "{{ route('chat.leave', $room->id) }}",
expiredLeaveUrl: "{{ \Illuminate\Support\Facades\URL::temporarySignedRoute('chat.leave.expired', now()->addHours(12), ['id' => $room->id, 'user' => $user->id]) }}",
heartbeatUrl: "{{ route('chat.heartbeat', $room->id) }}",
fishCastUrl: "{{ route('fishing.cast', $room->id) }}",
fishReelUrl: "{{ route('fishing.reel', $room->id) }}",
autoFishingMinutesLeft: {{ (int) $autoFishingMinutesLeft }},
fishingCooldownSeconds: {{ (int) $fishingCooldownSeconds }},
chatBotUrl: "{{ route('chatbot.chat') }}",
chatBotClearUrl: "{{ route('chatbot.clear') }}",
@php
$chatbotEnabledState = \App\Models\Sysparam::getValue('chatbot_enabled', '0') === '1';
$botUserData = null;
if ($chatbotEnabledState) {
$botUser = \App\Models\User::where('username', 'AI小班长')->first();
if ($botUser) {
$botUserData = app(\App\Services\ChatUserPresenceService::class)->build($botUser);
$botUserData['headfaceUrl'] = $botUser->headfaceUrl;
}
}
@endphp
chatBotEnabled: {{ $chatbotEnabledState ? 'true' : 'false' }},
botUser: @json($botUserData),
hasPosition: {{ Auth::user()->activePosition || Auth::user()->user_level >= $superLevel ? 'true' : 'false' }},
hasRoomManagementPermission: {{ (! empty($hasRoomManagementPermission) || Auth::id() === 1) ? 'true' : 'false' }},
isSiteOwner: {{ Auth::id() === 1 ? 'true' : 'false' }},
positionPermissions: @json($positionPermissions),
positionPermissionMap: @json($roomPermissionMap ?? []),
@php
$activePos = Auth::user()->activePosition;
$deptName = $activePos?->position?->department?->name ?? '';
$posName = $activePos?->position?->name ?? '';
@endphp
welcomePrefix: "{{ $deptName ? "{$deptName} {$posName} {$user->username}" : $user->username }}",
operatorDepartmentRank: {{ $operatorDepartmentRank }},
operatorPositionRank: {{ $operatorPositionRank }},
myMaxReward: @php
if (Auth::id() === 1) {
// 超级管理员(id=1)无需职务,直接拥有不限量奖励权
echo -1;
} else {
$pos = Auth::user()->activePosition?->position;
// -1 = 有权限但无上限(null),0 = 禁止,正整数 = 有具体上限
echo $pos ? ($pos->max_reward === null ? -1 : (int) $pos->max_reward) : 0;
}
@endphp,
appointPositionsUrl: "{{ route('chat.appoint.positions') }}",
appointUrl: "{{ route('chat.appoint.appoint') }}",
revokeUrl: "{{ route('chat.appoint.revoke') }}",
rewardUrl: "{{ route('command.reward') }}",
rewardQuotaUrl: "{{ route('command.reward_quota') }}",
refreshAllUrl: "{{ route('command.refresh_all') }}",
chatPreferencesUrl: "{{ route('user.update_chat_preferences') }}",
dailyStatusUpdateUrl: "{{ route('user.update_daily_status') }}",
dailySignInStatusUrl: @json(\Illuminate\Support\Facades\Route::has('daily-sign-in.status') ? route('daily-sign-in.status') : null),
dailySignInCalendarUrl: @json(\Illuminate\Support\Facades\Route::has('daily-sign-in.calendar') ? route('daily-sign-in.calendar') : null),
dailySignInClaimUrl: @json(\Illuminate\Support\Facades\Route::has('daily-sign-in.claim') ? route('daily-sign-in.claim') : null),
dailySignInMakeupUrl: @json(\Illuminate\Support\Facades\Route::has('daily-sign-in.makeup') ? route('daily-sign-in.makeup') : null),
userJjb: {{ (int) $user->jjb }}, // 当前用户金币(求婚前金额预检查用)
myGold: {{ (int) $user->jjb }}, // 赠金币面板显示余额用(赠送成功后前端更新)
profileHeadface: @json(Auth::user()->usersf ?: '1.gif'),
profileSign: @json(Auth::user()->sign ?? ''),
chatPreferences: @json($user->chat_preferences ?? []),
currentDailyStatus: @json($activeDailyStatus),
dailyStatusCatalog: @json($dailyStatusCatalog),
// ─── 婚姻系统 ──────────────────────────────
minWeddingCost: {{ (int) \App\Models\WeddingTier::where('is_active', true)->orderBy('amount')->value('amount') ?? 0 }},
marriage: {
proposeUrl: "{{ route('marriage.propose') }}",
statusUrl: "{{ route('marriage.status') }}",
targteStatusUrl: "/marriage/target",
myRingsUrl: "{{ route('marriage.rings') }}",
acceptUrl: (id) => `/marriage/${id}/accept`,
rejectUrl: (id) => `/marriage/${id}/reject`,
divorceUrl: (id) => `/marriage/${id}/divorce`,
confirmDivorceUrl: (id) => `/marriage/${id}/confirm-divorce`,
rejectDivorceUrl: (id) => `/marriage/${id}/reject-divorce`,
divorceConfigUrl: '/marriage/divorce-config',
weddingTiersUrl: "/wedding/tiers",
weddingSetupUrl: (id) => `/wedding/${id}/setup`,
claimEnvelopeUrl: (id, ceremonyId) => `/wedding/${id}/claim`,
envelopeStatusUrl: (id) => `/wedding/${id}/envelope-status`,
},
earnRewardUrl: "{{ route('earn.video_reward') }}",
chatImageRetentionDays: 3,
initialState: {
historyMessages: @json($historyMessages ?? []),
localClearStorageKey: "local_clear_msg_id_{{ $room->id }}",
welcomeMessage: @json($initialWelcomeMessage ?? null),
entryEffect: @json($newbieEffect ?: ($initialPresenceTheme['presence_effect'] ?? ($weekEffect ?? null))),
presenceTheme: @json($initialPresenceTheme ?? null),
pendingProposal: @json($pendingProposal ?? null),
pendingDivorce: @json($pendingDivorce ?? null),
@php
$chatbotEnabledState = \App\Models\Sysparam::getValue('chatbot_enabled', '0') === '1';
$botUserData = null;
if ($chatbotEnabledState) {
$botUser = \App\Models\User::query()->where('username', 'AI小班长')->first();
if ($botUser) {
$botUserData = app(\App\Services\ChatUserPresenceService::class)->build($botUser);
$botUserData['headfaceUrl'] = $botUser->headfaceUrl;
}
};
}
$activePos = Auth::user()->activePosition;
$deptName = $activePos?->position?->department?->name ?? '';
$posName = $activePos?->position?->name ?? '';
if (Auth::id() === 1) {
$myMaxReward = -1;
} else {
$pos = Auth::user()->activePosition?->position;
$myMaxReward = $pos ? ($pos->max_reward === null ? -1 : (int) $pos->max_reward) : 0;
}
$chatContext = [
'roomId' => $room->id,
'userId' => $user->id,
'username' => $user->username,
'userSex' => match ((int) $user->sex) {1 => '男', 2 => '女', default => ''},
'userLevel' => $user->user_level,
'superLevel' => $superLevel,
'levelKick' => $levelKick,
'levelMute' => $levelMute,
'levelBan' => $levelBan,
'levelBanip' => $levelBanip,
'sendUrl' => route('chat.send', $room->id),
'leaveUrl' => route('chat.leave', $room->id),
'expiredLeaveUrl' => \Illuminate\Support\Facades\URL::temporarySignedRoute('chat.leave.expired', now()->addHours(12), ['id' => $room->id, 'user' => $user->id]),
'heartbeatUrl' => route('chat.heartbeat', $room->id),
'fishCastUrl' => route('fishing.cast', $room->id),
'fishReelUrl' => route('fishing.reel', $room->id),
'autoFishingMinutesLeft' => (int) $autoFishingMinutesLeft,
'fishingCooldownSeconds' => (int) $fishingCooldownSeconds,
'chatBotUrl' => route('chatbot.chat'),
'chatBotClearUrl' => route('chatbot.clear'),
'chatBotEnabled' => $chatbotEnabledState,
'botUser' => $botUserData,
'hasPosition' => (bool) (Auth::user()->activePosition || Auth::user()->user_level >= $superLevel),
'hasRoomManagementPermission' => (bool) (! empty($hasRoomManagementPermission) || Auth::id() === 1),
'isSiteOwner' => Auth::id() === 1,
'positionPermissions' => $positionPermissions,
'positionPermissionMap' => $roomPermissionMap ?? [],
'welcomePrefix' => $deptName ? "{$deptName} {$posName} {$user->username}" : $user->username,
'operatorDepartmentRank' => $operatorDepartmentRank,
'operatorPositionRank' => $operatorPositionRank,
'myMaxReward' => $myMaxReward,
'appointPositionsUrl' => route('chat.appoint.positions'),
'appointUrl' => route('chat.appoint.appoint'),
'revokeUrl' => route('chat.appoint.revoke'),
'rewardUrl' => route('command.reward'),
'rewardQuotaUrl' => route('command.reward_quota'),
'refreshAllUrl' => route('command.refresh_all'),
'chatPreferencesUrl' => route('user.update_chat_preferences'),
'dailyStatusUpdateUrl' => route('user.update_daily_status'),
'dailySignInStatusUrl' => \Illuminate\Support\Facades\Route::has('daily-sign-in.status') ? route('daily-sign-in.status') : null,
'dailySignInCalendarUrl' => \Illuminate\Support\Facades\Route::has('daily-sign-in.calendar') ? route('daily-sign-in.calendar') : null,
'dailySignInClaimUrl' => \Illuminate\Support\Facades\Route::has('daily-sign-in.claim') ? route('daily-sign-in.claim') : null,
'dailySignInMakeupUrl' => \Illuminate\Support\Facades\Route::has('daily-sign-in.makeup') ? route('daily-sign-in.makeup') : null,
'userJjb' => (int) $user->jjb,
'myGold' => (int) $user->jjb,
'profileHeadface' => Auth::user()->usersf ?: '1.gif',
'profileSign' => Auth::user()->sign ?? '',
'chatPreferences' => $user->chat_preferences ?? [],
'currentDailyStatus' => $activeDailyStatus,
'dailyStatusCatalog' => $dailyStatusCatalog,
'minWeddingCost' => (int) (\App\Models\WeddingTier::query()->where('is_active', true)->orderBy('amount')->value('amount') ?? 0),
'marriage' => [
'proposeUrl' => route('marriage.propose'),
'statusUrl' => route('marriage.status'),
'targteStatusUrl' => '/marriage/target',
'myRingsUrl' => route('marriage.rings'),
'acceptUrlTemplate' => '/marriage/__ID__/accept',
'rejectUrlTemplate' => '/marriage/__ID__/reject',
'divorceUrlTemplate' => '/marriage/__ID__/divorce',
'confirmDivorceUrlTemplate' => '/marriage/__ID__/confirm-divorce',
'rejectDivorceUrlTemplate' => '/marriage/__ID__/reject-divorce',
'divorceConfigUrl' => '/marriage/divorce-config',
'weddingTiersUrl' => '/wedding/tiers',
'weddingSetupUrlTemplate' => '/wedding/__ID__/setup',
'claimEnvelopeUrlTemplate' => '/wedding/__ID__/claim',
'envelopeStatusUrlTemplate' => '/wedding/__ID__/envelope-status',
],
'earnRewardUrl' => route('earn.video_reward'),
'chatImageRetentionDays' => 3,
'initialState' => [
'historyMessages' => $historyMessages ?? [],
'localClearStorageKey' => "local_clear_msg_id_{$room->id}",
'welcomeMessage' => $initialWelcomeMessage ?? null,
'entryEffect' => $newbieEffect ?: ($initialPresenceTheme['presence_effect'] ?? ($weekEffect ?? null)),
'presenceTheme' => $initialPresenceTheme ?? null,
'pendingProposal' => $pendingProposal ?? null,
'pendingDivorce' => $pendingDivorce ?? null,
],
];
@endphp
<script type="application/json" id="chat-context-data">@json($chatContext)</script>
<script>
// 兼容底部存量同步脚本,完整 URL 工厂由 Vite 的 chat-room/context.js 继续补齐。
window.chatContext = JSON.parse(document.getElementById('chat-context-data')?.textContent || '{}');
</script>
@vite(['resources/css/app.css', 'resources/js/app.js', 'resources/js/chat.js'])
<script defer src="/js/alpinejs.min.js"></script>