// 导出动画弹出框管理器 window.ExportViewManager = (function() { let frame = null; let isShowing = false; let resolveCallback = null; function init() { frame = document.getElementById('exportViewFrame'); if (!frame) { return; } // 监听来自 export-view 的消息 window.addEventListener('message', (event) => { if (event.origin !== window.location.origin) { return; } const { data } = event; if (data && data.type === 'close-export-view') { hide(); } else if (data && data.type === 'export-confirmed') { handleExportConfirmed(data); } else if (data && data.type === 'export-view-ready') { // 内容准备好后显示 iframe if (frame && isShowing) { frame.style.display = 'block'; frame.style.pointerEvents = 'auto'; frame.style.visibility = 'visible'; } } }); } function show(folderName, options = {}) { if (!frame) { init(); } if (!frame) { return Promise.resolve(false); } const { skipPreviewUI = false } = options; return new Promise((resolve) => { resolveCallback = resolve; isShowing = true; // 等待 iframe 加载完成后发送文件夹名称 // iframe 会在内容准备好后发送 'export-view-ready' 消息,此时再显示 const sendFolderName = () => { if (frame.contentWindow) { // 发送消息,让 iframe 准备内容 frame.contentWindow.postMessage({ type: 'generate-export-preview', folderName: folderName, skipPreviewUI: skipPreviewUI }, '*'); // iframe 会在准备好后发送 'export-view-ready' 消息 } else { setTimeout(sendFolderName, 100); } }; // 监听 iframe 加载完成 const handleLoad = () => { setTimeout(() => { sendFolderName(); }, 100); }; frame.onload = handleLoad; // 如果 iframe 已经加载,立即发送 if (frame.contentDocument && frame.contentDocument.readyState === 'complete') { handleLoad(); } else { const baseSrc = frame.src.split('?')[0]; frame.src = baseSrc + '?t=' + Date.now(); } }); } function hide() { if (frame) { frame.style.display = 'none'; frame.style.pointerEvents = 'none'; frame.style.visibility = 'hidden'; } isShowing = false; if (resolveCallback) { resolveCallback(false); resolveCallback = null; } } function handleExportConfirmed(data) { if (resolveCallback) { resolveCallback(true); resolveCallback = null; } hide(); } // 初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } return { show, hide }; })(); // 全局 Loading 控制器 window.GlobalLoading = (function() { let overlay = null; let loadingText = null; function init() { overlay = document.getElementById('globalLoadingOverlay'); loadingText = overlay ? overlay.querySelector('.global-loading-text') : null; } function show(text = '正在处理...') { // console.log('[GlobalLoading] show() 被调用'); // console.log('[GlobalLoading] 文本:', text); if (!overlay) { // console.log('[GlobalLoading] → 初始化overlay元素...'); init(); } if (!overlay) { // console.error('[GlobalLoading] ✗ overlay元素未找到!'); return; } // console.log('[GlobalLoading] ✓ overlay元素存在'); if (loadingText) { loadingText.textContent = text; // console.log('[GlobalLoading] ✓ 设置Loading文本:', text); } overlay.classList.add('is-visible'); // console.log('[GlobalLoading] ✓ 添加is-visible类,Loading应该可见了'); } function hide() { // console.log('[GlobalLoading] hide() 被调用'); if (!overlay) { // console.error('[GlobalLoading] ✗ overlay元素不存在'); return; } overlay.classList.remove('is-visible'); // console.log('[GlobalLoading] ✓ 移除is-visible类,Loading已隐藏'); } return { show, hide }; })(); // 全局 Alert 控制器 window.GlobalAlert = (function() { let alertContainer = null; let alertMessage = null; let hideTimer = null; function init() { alertContainer = document.getElementById('globalAlert'); alertMessage = alertContainer ? alertContainer.querySelector('#alertMessage') : null; } function show(text, duration = 1500) { console.log('[GlobalAlert] show() 被调用:', { text, duration }); if (!alertContainer) { console.log('[GlobalAlert] 初始化 alertContainer'); init(); } if (!alertContainer) { console.error('[GlobalAlert] alertContainer 未找到!'); return; } if (!alertMessage) { console.error('[GlobalAlert] alertMessage 未找到!'); return; } console.log('[GlobalAlert] 设置消息:', text); // 清除之前的自动隐藏定时器 if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; } alertMessage.textContent = text; alertContainer.classList.add('show'); console.log('[GlobalAlert] 已添加 show 类,alert 应该可见了'); // 自动隐藏 if (duration > 0) { hideTimer = setTimeout(() => { hide(); }, duration); } } function hide() { if (!alertContainer) return; alertContainer.classList.remove('show'); if (hideTimer) { clearTimeout(hideTimer); hideTimer = null; } } return { show, hide }; })(); // 页面管理:负责切换 iframe 中的子页面,并保持与导航栏状态同步 (function () { console.log('[Index] index.js 已加载'); const DEFAULT_PAGE = "store"; function getPageFrame() { return document.getElementById("pageFrame"); } function getNavigationFrame() { return document.getElementById("navigationFrame"); } function switchPage(page) { // 只处理实际的页面切换,不处理login/register if (page === "login" || page === "register") { return; } // profile页面是独立页面,直接跳转 if (page === "profile") { window.location.href = "page/profile/profile.html"; return; } const frame = getPageFrame(); if (!frame) { return; } switch (page) { case "store": frame.src = "page/store/store.html"; break; case "assets": frame.src = "page/assets/assets.html"; break; default: frame.src = "page/store/store.html"; break; } // 同步导航栏状态 syncNavigationState(page); } // 同步导航栏状态 function syncNavigationState(page) { const navigationFrame = getNavigationFrame(); if (navigationFrame && navigationFrame.contentWindow) { // 使用setTimeout确保iframe已加载 setTimeout(() => { navigationFrame.contentWindow.postMessage( { type: "navigation", page }, "*" ); }, 100); } } window.addEventListener("message", (event) => { // 调试:记录所有收到的消息 console.log('[Index] 收到message事件:', { origin: event.origin, expectedOrigin: window.location.origin, data: event.data, source: event.source, type: event.data?.type }); // 检查 origin(允许同源或 localhost,或者来自 iframe) const isSameOrigin = event.origin === window.location.origin; const isLocalhost = event.origin === 'http://localhost:3000' || event.origin === 'http://127.0.0.1:3000' || event.origin.startsWith('http://localhost:') || event.origin.startsWith('http://127.0.0.1:'); // 允许来自同源的 iframe(即使 origin 不完全匹配) const isFromIframe = event.source && event.source !== window; console.log('[Index] Origin 检查:', { eventOrigin: event.origin, windowOrigin: window.location.origin, isSameOrigin, isLocalhost, isFromIframe, willPass: isSameOrigin || isLocalhost || isFromIframe }); // 对于 global-alert 消息,放宽 origin 检查(允许来自任何同源 iframe) if (event.data && event.data.type === 'global-alert') { console.log('[Index] 这是 global-alert 消息,放宽 origin 检查'); // 允许来自任何 iframe 的消息(只要 source 存在且不是 window 本身) if (isFromIframe || isSameOrigin || isLocalhost) { console.log('[Index] global-alert 消息通过检查'); } else { console.warn('[Index] global-alert 消息被 origin 检查过滤:', event.origin); // 即使 origin 不匹配,也允许 global-alert 消息通过(因为来自同源 iframe) console.log('[Index] 但允许通过(来自 iframe)'); } } else if (!isSameOrigin && !isLocalhost && !isFromIframe) { console.log('[Index] 消息被 origin 检查过滤:', event.origin); return; } console.log('[Index] 消息通过 origin 检查,继续处理'); const { data } = event; if (data && data.type === "navigation" && (data.page === "login" || data.page === "register")) { // console.log('[2-Index] 收到login/register消息'); const loginFrame = document.getElementById('loginViewFrame'); if (loginFrame) { const mode = data.page === "register" ? "register" : "login"; loginFrame.style.display = 'block'; // console.log('[3-Index] iframe已显示'); const sendMode = () => { if (loginFrame.contentWindow) { loginFrame.contentWindow.postMessage({ type: 'open-login-view', mode: mode }, '*'); // console.log('[4-Index] 消息已发送到login iframe'); } else { setTimeout(sendMode, 100); } }; sendMode(); const handleLoad = () => { setTimeout(() => { sendMode(); }, 50); }; if (loginFrame.contentDocument && loginFrame.contentDocument.readyState === 'complete') { handleLoad(); } else { loginFrame.addEventListener('load', handleLoad, { once: true }); } } } else if (data && data.type === "navigation" && data.page) { switchPage(data.page); } // 注意:global-alert、global-loading、global-confirm 消息不再通过 index.js 处理 // 各个 view 现在直接调用父窗口的 GlobalAlert/GlobalLoading/GlobalConfirm else if (data && data.type === "open-export-view") { // 处理打开导出弹出框 console.log('[Index] 收到open-export-view消息:', data); if (!data.folderName) { console.error('[Index] 缺少文件夹名称'); return; } if (!window.ExportViewManager) { console.error('[Index] ExportViewManager 未初始化'); return; } // 直接打开弹出框,传递文件夹名称 window.ExportViewManager.show(data.folderName, { skipPreviewUI: data.skipPreviewUI }).then((confirmed) => { console.log('[Index] 用户选择:', confirmed ? '确认导出' : '取消'); // 如果用户确认,可以在这里处理实际的导出下载逻辑 if (confirmed) { // TODO: 处理实际的导出下载逻辑 console.log('[Index] 用户确认导出,文件夹:', data.folderName); } }).catch(error => { console.error('[Index] ExportViewManager显示失败:', error); }); } else if (data && data.type === "close-login-view") { const loginFrame = document.getElementById('loginViewFrame'); if (loginFrame) { loginFrame.style.display = 'none'; } } else if (data && data.type === "open-ai-generate-view") { // 处理打开AI生图界面 console.log('[Index] 收到open-ai-generate-view消息:', data); const aiGenerateFrame = document.getElementById('aiGenerateViewFrame'); if (aiGenerateFrame) { aiGenerateFrame.style.display = 'block'; aiGenerateFrame.style.pointerEvents = 'auto'; aiGenerateFrame.style.visibility = 'visible'; const sendAIData = () => { if (aiGenerateFrame.contentWindow) { aiGenerateFrame.contentWindow.postMessage({ type: 'show-ai-generate', folderName: data.folderName, spritesheetData: data.spritesheetData, spritesheetLayout: data.spritesheetLayout }, '*'); } else { setTimeout(sendAIData, 100); } }; sendAIData(); } } else if (data && data.type === "close-ai-generate-view") { const aiGenerateFrame = document.getElementById('aiGenerateViewFrame'); if (aiGenerateFrame) { aiGenerateFrame.style.display = 'none'; aiGenerateFrame.style.pointerEvents = 'none'; aiGenerateFrame.style.visibility = 'hidden'; } } else if (data && data.type === "open-pay-view") { // 处理打开支付界面 const payFrame = document.getElementById('payViewFrame'); if (payFrame) { payFrame.style.display = 'block'; payFrame.style.pointerEvents = 'auto'; payFrame.style.visibility = 'visible'; const sendPayData = () => { if (payFrame.contentWindow) { payFrame.contentWindow.postMessage({ type: 'open-pay-view', itemName: data.itemName, price: data.price, resourcePath: data.resourcePath, categoryDir: data.categoryDir }, '*'); } else { setTimeout(sendPayData, 100); } }; sendPayData(); const handleLoad = () => { setTimeout(() => { sendPayData(); }, 50); }; if (payFrame.contentDocument && payFrame.contentDocument.readyState === 'complete') { handleLoad(); } else { payFrame.addEventListener('load', handleLoad, { once: true }); } } } else if (data && data.type === "close-pay-view") { const payFrame = document.getElementById('payViewFrame'); if (payFrame) { payFrame.style.display = 'none'; payFrame.style.pointerEvents = 'none'; // 确保 iframe 不会遮挡其他元素 payFrame.style.visibility = 'hidden'; } } else if (data && data.type === "payment-success") { // 支付成功,刷新商店页面(如果需要) if (window.HintView) { window.HintView.success(`购买成功!${data.itemName} 已添加到网盘`, 3000); } } else if (data && data.type === "open-recharge-view") { // 处理打开充值界面 const rechargeFrame = document.getElementById('rechargeViewFrame'); if (rechargeFrame) { rechargeFrame.style.display = 'block'; rechargeFrame.style.pointerEvents = 'auto'; rechargeFrame.style.visibility = 'visible'; const sendRechargeData = () => { if (rechargeFrame.contentWindow) { rechargeFrame.contentWindow.postMessage({ type: 'open-recharge-view', needPoints: data.needPoints, currentPoints: data.currentPoints }, '*'); } else { setTimeout(sendRechargeData, 100); } }; sendRechargeData(); const handleLoad = () => { setTimeout(() => { sendRechargeData(); }, 50); }; if (rechargeFrame.contentDocument && rechargeFrame.contentDocument.readyState === 'complete') { handleLoad(); } else { rechargeFrame.addEventListener('load', handleLoad, { once: true }); } } } else if (data && data.type === "close-recharge-view") { const rechargeFrame = document.getElementById('rechargeViewFrame'); if (rechargeFrame) { rechargeFrame.style.display = 'none'; rechargeFrame.style.pointerEvents = 'none'; rechargeFrame.style.visibility = 'hidden'; } } else if (data && data.type === "recharge-success") { // 充值成功,关闭充值界面 const rechargeFrame = document.getElementById('rechargeViewFrame'); if (rechargeFrame) { rechargeFrame.style.display = 'none'; rechargeFrame.style.pointerEvents = 'none'; rechargeFrame.style.visibility = 'hidden'; } // 刷新点数显示 if (window.postMessage) { window.postMessage({ type: 'refresh-points' }, '*'); } // 显示成功提示 if (window.HintView) { window.HintView.success(`充值成功!获得 ${data.points} Ani币`, 3000); } } else if (data && data.type === "avatar-updated") { // 头像更新,通知导航栏更新 const navigationFrame = document.getElementById('navigationFrame'); if (navigationFrame && navigationFrame.contentWindow) { // 从localStorage获取用户信息并更新头像 try { const loginDataStr = localStorage.getItem('loginData'); if (loginDataStr) { const loginData = JSON.parse(loginDataStr); if (loginData.user) { loginData.user.avatar = data.avatar; localStorage.setItem('loginData', JSON.stringify(loginData)); // 通知导航栏更新 navigationFrame.contentWindow.postMessage({ type: 'login-success', user: loginData.user }, '*'); } } } catch (error) { console.error('[Index] 更新头像信息失败:', error); } } } else if (data && data.type === "login-success" && data.user) { // 显示登录成功提示(在主窗口) if (window.HintView) { window.HintView.success('登录成功', 2000); } // 处理登录成功消息,转发给 navigation iframe 和 pageFrame const navigationFrame = getNavigationFrame(); if (navigationFrame && navigationFrame.contentWindow) { navigationFrame.contentWindow.postMessage({ type: 'login-success', user: data.user }, '*'); } // 也转发给 pageFrame(store 页面) const pageFrame = getPageFrame(); if (pageFrame && pageFrame.contentWindow) { pageFrame.contentWindow.postMessage({ type: 'login-success', user: data.user }, '*'); } // 转发给 assets iframe(如果存在),它会再转发给 disk iframe const assetsFrame = document.getElementById('assetsFrame'); if (assetsFrame && assetsFrame.contentWindow) { assetsFrame.contentWindow.postMessage({ type: 'login-success', user: data.user }, '*'); } } else if (data && data.type === "refresh-points") { // 刷新用户点数显示 console.log('[Index] 收到刷新点数请求'); // 转发给导航栏更新点数 const navigationFrame = getNavigationFrame(); if (navigationFrame && navigationFrame.contentWindow) { navigationFrame.contentWindow.postMessage({ type: 'refresh-points' }, '*'); } // 也转发给个人中心页面(如果打开的话) const pageFrame = getPageFrame(); if (pageFrame && pageFrame.contentWindow) { pageFrame.contentWindow.postMessage({ type: 'refresh-points' }, '*'); } } else if (data && data.type === "logout") { // 清除 localStorage 中的登录信息 try { localStorage.removeItem('loginData'); console.log('[Index] 登出,已清除登录信息'); } catch (error) { console.error('[Index] 清除登录信息失败:', error); } // 处理登出消息,转发给所有 iframe const navigationFrame = getNavigationFrame(); if (navigationFrame && navigationFrame.contentWindow) { navigationFrame.contentWindow.postMessage({ type: 'logout' }, '*'); } const pageFrame = getPageFrame(); if (pageFrame && pageFrame.contentWindow) { pageFrame.contentWindow.postMessage({ type: 'logout' }, '*'); } const assetsFrame = document.getElementById('assetsFrame'); if (assetsFrame && assetsFrame.contentWindow) { assetsFrame.contentWindow.postMessage({ type: 'logout' }, '*'); } } }); // 检查并恢复登录状态 function checkAndRestoreLogin() { try { const loginDataStr = localStorage.getItem('loginData'); if (!loginDataStr) { return; } const loginData = JSON.parse(loginDataStr); const now = Date.now(); // 检查是否过期(2小时) if (now >= loginData.expireTime) { // 已过期,清除登录信息 localStorage.removeItem('loginData'); console.log('[Index] 登录信息已过期(2小时),已清除'); return; } // 未过期,恢复登录状态 if (loginData.user) { console.log('[Index] 恢复登录状态,用户:', loginData.user.username); // 通知所有 iframe 登录成功 const navigationFrame = getNavigationFrame(); if (navigationFrame && navigationFrame.contentWindow) { navigationFrame.contentWindow.postMessage({ type: 'login-success', user: loginData.user }, '*'); } const pageFrame = getPageFrame(); if (pageFrame && pageFrame.contentWindow) { pageFrame.contentWindow.postMessage({ type: 'login-success', user: loginData.user }, '*'); } const assetsFrame = document.getElementById('assetsFrame'); if (assetsFrame && assetsFrame.contentWindow) { assetsFrame.contentWindow.postMessage({ type: 'login-success', user: loginData.user }, '*'); } } } catch (error) { console.error('[Index] 恢复登录状态失败:', error); localStorage.removeItem('loginData'); } } window.addEventListener("DOMContentLoaded", () => { // 先检查并恢复登录状态 checkAndRestoreLogin(); switchPage(DEFAULT_PAGE); syncNavigationState(DEFAULT_PAGE); }); })();