diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js
index 5f34b4b..2d673bb 100644
--- a/resources/js/chat-room.js
+++ b/resources/js/chat-room.js
@@ -42,6 +42,7 @@ export { bindGameHallControls } from "./chat-room/game-hall.js";
export { bindGameBootstrapControls, deferChatGameBootstrap } from "./chat-room/game-bootstrap.js";
export { bindGamePanelControls } from "./chat-room/game-panels.js";
export { bindHolidayModalControls, openHolidayRunFromSystemMessage } from "./chat-room/holiday-modal.js";
+export { bindChatInitialStateControls } from "./chat-room/initial-state.js";
export {
bankAction,
bankLoadInfo,
@@ -125,6 +126,7 @@ import { bindGameHallControls } from "./chat-room/game-hall.js";
import { bindGameBootstrapControls, deferChatGameBootstrap } from "./chat-room/game-bootstrap.js";
import { bindGamePanelControls } from "./chat-room/game-panels.js";
import { bindHolidayModalControls, openHolidayRunFromSystemMessage } from "./chat-room/holiday-modal.js";
+import { bindChatInitialStateControls } from "./chat-room/initial-state.js";
import {
bankAction,
bankLoadInfo,
@@ -221,6 +223,7 @@ if (typeof window !== "undefined") {
bindGamePanelControls,
bindHolidayModalControls,
openHolidayRunFromSystemMessage,
+ bindChatInitialStateControls,
loadAdminCurrentLossCoverEvent,
openAdminBaccaratLossCoverModal,
submitBaccaratLossCoverEvent,
@@ -329,6 +332,7 @@ if (typeof window !== "undefined") {
bindGameBootstrapControls();
bindGamePanelControls();
bindHolidayModalControls();
+ bindChatInitialStateControls();
bindBankControls();
bindFishingControls();
bindMarriageStatusControls();
diff --git a/resources/js/chat-room/initial-state.js b/resources/js/chat-room/initial-state.js
new file mode 100644
index 0000000..7890a6e
--- /dev/null
+++ b/resources/js/chat-room/initial-state.js
@@ -0,0 +1,143 @@
+// 聊天室页面初始状态恢复,负责首屏历史消息、入场特效和挂起婚姻事件。
+
+/**
+ * DOM 就绪后执行回调。
+ *
+ * @param {Function} callback
+ * @returns {void}
+ */
+function onDomReady(callback) {
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", callback, { once: true });
+ return;
+ }
+
+ callback();
+}
+
+/**
+ * 追加一条聊天消息,等待核心聊天脚本暴露 appendMessage。
+ *
+ * @param {object} message
+ * @returns {void}
+ */
+function appendInitialMessage(message) {
+ if (typeof window.appendMessage === "function") {
+ window.appendMessage(message);
+ }
+}
+
+/**
+ * 恢复页面初始历史消息。
+ *
+ * @param {object} initialState
+ * @returns {void}
+ */
+function restoreHistoryMessages(initialState) {
+ const messages = Array.isArray(initialState.historyMessages) ? initialState.historyMessages : [];
+ if (messages.length === 0) {
+ return;
+ }
+
+ const clearId = Number.parseInt(localStorage.getItem(initialState.localClearStorageKey || "") || "0", 10);
+
+ messages.forEach((message) => {
+ // 本地清屏后,只恢复清屏点之后的新消息。
+ if (Number(message.id || 0) > clearId) {
+ appendInitialMessage(message);
+ }
+ });
+}
+
+/**
+ * 追加页面入场欢迎消息。
+ *
+ * @param {object} initialState
+ * @returns {void}
+ */
+function appendWelcomeMessage(initialState) {
+ if (!initialState.welcomeMessage) {
+ return;
+ }
+
+ window.setTimeout(() => appendInitialMessage(initialState.welcomeMessage), 220);
+}
+
+/**
+ * 播放页面入场特效。
+ *
+ * @param {object} initialState
+ * @returns {void}
+ */
+function playEntryEffect(initialState) {
+ if (!initialState.entryEffect) {
+ return;
+ }
+
+ window.setTimeout(() => {
+ window.EffectManager?.play?.(initialState.entryEffect);
+ }, 1000);
+}
+
+/**
+ * 显示会员进出场横幅。
+ *
+ * @param {object} initialState
+ * @returns {void}
+ */
+function showInitialPresenceBanner(initialState) {
+ if (!initialState.presenceTheme) {
+ return;
+ }
+
+ window.setTimeout(() => {
+ window.showVipPresenceBanner?.(initialState.presenceTheme);
+ }, 700);
+}
+
+/**
+ * 派发挂起的求婚或离婚请求事件。
+ *
+ * @param {object} initialState
+ * @returns {void}
+ */
+function dispatchPendingMarriageEvents(initialState) {
+ if (!initialState.pendingProposal && !initialState.pendingDivorce) {
+ return;
+ }
+
+ window.setTimeout(() => {
+ if (initialState.pendingProposal) {
+ window.dispatchEvent(new CustomEvent("chat:marriage-proposed", {
+ detail: initialState.pendingProposal,
+ }));
+ }
+
+ if (initialState.pendingDivorce) {
+ window.dispatchEvent(new CustomEvent("chat:divorce-requested", {
+ detail: initialState.pendingDivorce,
+ }));
+ }
+ }, 800);
+}
+
+/**
+ * 绑定聊天室页面初始状态恢复。
+ *
+ * @returns {void}
+ */
+export function bindChatInitialStateControls() {
+ if (typeof window === "undefined") {
+ return;
+ }
+
+ onDomReady(() => {
+ const initialState = window.chatContext?.initialState || {};
+
+ restoreHistoryMessages(initialState);
+ appendWelcomeMessage(initialState);
+ playEntryEffect(initialState);
+ showInitialPresenceBanner(initialState);
+ dispatchPendingMarriageEvents(initialState);
+ });
+}
diff --git a/resources/views/chat/frame.blade.php b/resources/views/chat/frame.blade.php
index b3c0b5a..21f0e0f 100644
--- a/resources/views/chat/frame.blade.php
+++ b/resources/views/chat/frame.blade.php
@@ -124,7 +124,16 @@
envelopeStatusUrl: (id) => `/wedding/${id}/envelope-status`,
},
earnRewardUrl: "{{ route('earn.video_reward') }}",
- chatImageRetentionDays: 3
+ 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),
+ }
};
@vite(['resources/css/app.css', 'resources/js/app.js', 'resources/js/chat.js'])
@@ -236,90 +245,7 @@
{{-- 辅助与全局事件组件 --}}
@include('chat.partials.ai-chatbot')
@include('chat.partials.system-events')
- {{-- 页面初始加载时,渲染自带的历史记录(解决入场欢迎语错过断网的问题) --}}
- @if (!empty($historyMessages))
-
- @endif
- @if (!empty($initialWelcomeMessage))
-
- @endif
- @if (!empty($newbieEffect) || !empty($weekEffect) || !empty($initialPresenceTheme['presence_effect']))
-
- @endif
- @if (!empty($initialPresenceTheme))
-
- @endif
-
- {{-- 页面初始加载时,若存在挂起的求婚 / 离婚请求,则弹窗 --}}
- @if (!empty($pendingProposal) || !empty($pendingDivorce))
-
- @endif
+ {{-- 初始历史消息、入场欢迎、进场特效、会员横幅和挂起婚姻事件已迁移到 resources/js/chat-room/initial-state.js --}}