diff --git a/resources/js/chat-room.js b/resources/js/chat-room.js index 7b87627..5f3e922 100644 --- a/resources/js/chat-room.js +++ b/resources/js/chat-room.js @@ -769,16 +769,49 @@ if (typeof window !== "undefined") { window.marriageAction = (...args) => _marriageStatus.wrap('marriageAction')(...args); window.openMarriageStatusModal = (...args) => _marriageStatus.wrap('openMarriageStatusModal')(...args); window.appendSystemMessage = (...args) => _marriageModals.wrap('appendSystemMessage')(...args); - window.divorceConfirmModal = (...args) => _marriageModals.wrap('divorceConfirmModal')(...args); - window.divorceRequestModal = (...args) => _marriageModals.wrap('divorceRequestModal')(...args); - window.marriageAcceptedModal = (...args) => _marriageModals.wrap('marriageAcceptedModal')(...args); - window.marriageDivorcedModal = (...args) => _marriageModals.wrap('marriageDivorcedModal')(...args); - window.marriageIncomingModal = (...args) => _marriageModals.wrap('marriageIncomingModal')(...args); - window.marriageProposeModal = (...args) => _marriageModals.wrap('marriageProposeModal')(...args); window.openProposeModal = (...args) => _marriageModals.wrap('openProposeModal')(...args); window.openWeddingSetupModal = (...args) => _marriageModals.wrap('openWeddingSetupModal')(...args); - window.weddingEnvelopeModal = (...args) => _marriageModals.wrap('weddingEnvelopeModal')(...args); - window.weddingSetupModal = (...args) => _marriageModals.wrap('weddingSetupModal')(...args); + // ── 婚姻弹窗 Alpine 组件(createLazyAlpineComponent 懒加载) ── + window.marriageProposeModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "marriageProposeModal", + { show: false, targetUsername: "", error: "", loading: false, rings: [], selectedRing: null, selectedTier: null, tiers: [], selectedTierId: null, canAfford: false, sending: false, doPropose: () => {} } + ); + window.marriageIncomingModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "marriageIncomingModal", + { show: false } + ); + window.marriageAcceptedModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "marriageAcceptedModal", + { show: false } + ); + window.marriageDivorcedModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "marriageDivorcedModal", + { show: false } + ); + window.divorceConfirmModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "divorceConfirmModal", + { show: false } + ); + window.divorceRequestModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "divorceRequestModal", + { show: false } + ); + window.weddingSetupModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "weddingSetupModal", + { show: false } + ); + window.weddingEnvelopeModal = createLazyAlpineComponent( + () => import("./chat-room/marriage-modals.js"), + "weddingEnvelopeModal", + { show: false } + ); window.renderMarriedList = (...args) => _marriageStatus.wrap('renderMarriedList')(...args); window.renderMarriageStatus = (...args) => _marriageStatus.wrap('renderMarriageStatus')(...args); window.switchMarriageTab = (...args) => _marriageStatus.wrap('switchMarriageTab')(...args); @@ -855,7 +888,42 @@ if (typeof window !== "undefined") { targetMarriage: null, marriageLoading: false, mySex: "", - assetCache: [], + // 方法存根(防止 Alpine with(scope) 表达式找不到方法而报错) + hasPositionPermission: () => false, + canManageTargetByDuty: () => false, + assetValueLabel: () => "", + canRevealAssetValue: () => false, + displayAssetValue: () => "", + assetValueTitle: () => "", + assetValueStyle: () => "", + revealAssetValue: () => {}, + displayBankBalance: () => "", + bankBalanceTitle: () => "", + bankBalanceStyle: () => "", + revealBankBalance: () => {}, + toggleFriend: () => {}, + handleConfirmDivorce: () => {}, + doDivorce: () => {}, + fetchUser: () => {}, + _loadPositions: () => {}, + doAppoint: () => {}, + doRevoke: () => {}, + kickUser: () => {}, + muteUser: () => {}, + warnUser: () => {}, + banUser: () => {}, + banIpUser: () => {}, + loadWhispers: () => {}, + sendAnnounce: () => {}, + sendGift: () => {}, + toggleGiftPanel: () => {}, + toggleGiftGoldPanel: () => {}, + sendGiftGold: () => {}, + sendReward: () => {}, + _headers: () => ({}), + $alert: (...args) => window.chatDialog?.alert(...args), + $confirm: (...args) => window.chatDialog?.confirm(...args), + $prompt: (...args) => window.chatDialog?.prompt(...args), }, "showUserModal" ); diff --git a/resources/js/chat-room/lazy-loader.js b/resources/js/chat-room/lazy-loader.js index 248840a..2e842dd 100644 --- a/resources/js/chat-room/lazy-loader.js +++ b/resources/js/chat-room/lazy-loader.js @@ -101,13 +101,11 @@ export function createLazyAlpineComponent(importFn, exportName, defaults = {}, w const proxy = this; let loaded = false; - // 使用 Alpine 的 $watch 监听显示状态变化 - // 仅在组件变为可见时才加载真实模块 if ( watchKey in proxy && typeof proxy.$watch === "function" ) { - proxy.$watch(watchKey, (value, oldValue) => { + proxy.$watch(watchKey, (value) => { if (value && !loaded) { loaded = true; importFn() @@ -118,21 +116,18 @@ export function createLazyAlpineComponent(importFn, exportName, defaults = {}, w ? componentFn(...args) : componentFn; - // 通过 Alpine 响应式代理写入所有属性 Object.keys(realData).forEach((key) => { if (key !== "init") { proxy[key] = realData[key]; } }); - // 处理继承属性 for (const key in realData) { if (!(key in proxy)) { proxy[key] = realData[key]; } } - // 调用真实组件的 init(如果存在) if ( typeof proxy.init === "function" && proxy.init !== stub.init @@ -145,7 +140,7 @@ export function createLazyAlpineComponent(importFn, exportName, defaults = {}, w `[懒加载] Alpine 组件 "${exportName}" 加载失败:`, err, ); - loaded = false; // 允许重试 + loaded = false; }); } }); @@ -153,33 +148,6 @@ export function createLazyAlpineComponent(importFn, exportName, defaults = {}, w }, }; - // 使用 Proxy 包裹 stub,对任何未在 defaults 中定义的属性/方法提供安全兜底 - // 这样组件模板中的所有表达式(方法调用、属性访问)都不会抛出 "not defined" 错误 - return new Proxy(stub, { - get(target, prop, receiver) { - // 已存在的属性直接返回 - if (prop in target) { - return Reflect.get(target, prop, receiver); - } - // 对于未定义的属性/方法,返回一个安全的、支持调用的兜底值 - // - 作为值访问(如 targetMarriage?.status): 返回 '',保证 .status 不报错 - // - 作为方法调用(如 displayAssetValue('exp_num')): 返回空字符串 - const fallback = () => ""; - return fallback; - }, - // Alpine 使用 with(scope) 求值表达式,with 用 has (in 操作符) 判断属性是否存在 - // 如果没有 has 陷阱,with 认为属性不存在 → 跳到 window → "is not defined" - has(target, prop) { - // 不要拦截 Alpine/Vue 内部属性和魔术方法 - if (typeof prop === "symbol") return Reflect.has(target, prop); - if (String(prop).startsWith("__v_")) return Reflect.has(target, prop); - if (String(prop).startsWith("$")) return Reflect.has(target, prop); - // 所有其他属性都报告存在,让 with 继续用 get 获取兜底值 - return true; - }, - set(target, prop, value, receiver) { - return Reflect.set(target, prop, value, receiver); - }, - }); + return stub; }; }