Index.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. // 导出动画弹出框管理器
  2. window.ExportViewManager = (function() {
  3. let frame = null;
  4. let isShowing = false;
  5. let resolveCallback = null;
  6. function init() {
  7. frame = document.getElementById('exportViewFrame');
  8. if (!frame) {
  9. return;
  10. }
  11. // 监听来自 export-view 的消息
  12. window.addEventListener('message', (event) => {
  13. if (event.origin !== window.location.origin) {
  14. return;
  15. }
  16. const { data } = event;
  17. if (data && data.type === 'close-export-view') {
  18. hide();
  19. } else if (data && data.type === 'export-confirmed') {
  20. handleExportConfirmed(data);
  21. } else if (data && data.type === 'export-view-ready') {
  22. // 内容准备好后显示 iframe
  23. if (frame && isShowing) {
  24. frame.style.display = 'block';
  25. frame.style.pointerEvents = 'auto';
  26. frame.style.visibility = 'visible';
  27. }
  28. }
  29. });
  30. }
  31. function show(folderName, options = {}) {
  32. if (!frame) {
  33. init();
  34. }
  35. if (!frame) {
  36. return Promise.resolve(false);
  37. }
  38. const { skipPreviewUI = false } = options;
  39. return new Promise((resolve) => {
  40. resolveCallback = resolve;
  41. isShowing = true;
  42. // 等待 iframe 加载完成后发送文件夹名称
  43. // iframe 会在内容准备好后发送 'export-view-ready' 消息,此时再显示
  44. const sendFolderName = () => {
  45. if (frame.contentWindow) {
  46. // 发送消息,让 iframe 准备内容
  47. frame.contentWindow.postMessage({
  48. type: 'generate-export-preview',
  49. folderName: folderName,
  50. skipPreviewUI: skipPreviewUI
  51. }, '*');
  52. // iframe 会在准备好后发送 'export-view-ready' 消息
  53. } else {
  54. setTimeout(sendFolderName, 100);
  55. }
  56. };
  57. // 监听 iframe 加载完成
  58. const handleLoad = () => {
  59. setTimeout(() => {
  60. sendFolderName();
  61. }, 100);
  62. };
  63. frame.onload = handleLoad;
  64. // 如果 iframe 已经加载,立即发送
  65. if (frame.contentDocument && frame.contentDocument.readyState === 'complete') {
  66. handleLoad();
  67. } else {
  68. const baseSrc = frame.src.split('?')[0];
  69. frame.src = baseSrc + '?t=' + Date.now();
  70. }
  71. });
  72. }
  73. function hide() {
  74. if (frame) {
  75. frame.style.display = 'none';
  76. frame.style.pointerEvents = 'none';
  77. frame.style.visibility = 'hidden';
  78. }
  79. isShowing = false;
  80. if (resolveCallback) {
  81. resolveCallback(false);
  82. resolveCallback = null;
  83. }
  84. }
  85. function handleExportConfirmed(data) {
  86. if (resolveCallback) {
  87. resolveCallback(true);
  88. resolveCallback = null;
  89. }
  90. hide();
  91. }
  92. // 初始化
  93. if (document.readyState === 'loading') {
  94. document.addEventListener('DOMContentLoaded', init);
  95. } else {
  96. init();
  97. }
  98. return {
  99. show,
  100. hide
  101. };
  102. })();
  103. // 全局 Loading 控制器
  104. window.GlobalLoading = (function() {
  105. let overlay = null;
  106. let loadingText = null;
  107. function init() {
  108. overlay = document.getElementById('globalLoadingOverlay');
  109. loadingText = overlay ? overlay.querySelector('.global-loading-text') : null;
  110. }
  111. function show(text = '正在处理...') {
  112. // console.log('[GlobalLoading] show() 被调用');
  113. // console.log('[GlobalLoading] 文本:', text);
  114. if (!overlay) {
  115. // console.log('[GlobalLoading] → 初始化overlay元素...');
  116. init();
  117. }
  118. if (!overlay) {
  119. // console.error('[GlobalLoading] ✗ overlay元素未找到!');
  120. return;
  121. }
  122. // console.log('[GlobalLoading] ✓ overlay元素存在');
  123. if (loadingText) {
  124. loadingText.textContent = text;
  125. // console.log('[GlobalLoading] ✓ 设置Loading文本:', text);
  126. }
  127. overlay.classList.add('is-visible');
  128. // console.log('[GlobalLoading] ✓ 添加is-visible类,Loading应该可见了');
  129. }
  130. function hide() {
  131. // console.log('[GlobalLoading] hide() 被调用');
  132. if (!overlay) {
  133. // console.error('[GlobalLoading] ✗ overlay元素不存在');
  134. return;
  135. }
  136. overlay.classList.remove('is-visible');
  137. // console.log('[GlobalLoading] ✓ 移除is-visible类,Loading已隐藏');
  138. }
  139. return {
  140. show,
  141. hide
  142. };
  143. })();
  144. // 全局 Alert 控制器
  145. window.GlobalAlert = (function() {
  146. let alertContainer = null;
  147. let alertMessage = null;
  148. let hideTimer = null;
  149. function init() {
  150. alertContainer = document.getElementById('globalAlert');
  151. alertMessage = alertContainer ? alertContainer.querySelector('#alertMessage') : null;
  152. }
  153. function show(text, duration = 1500) {
  154. console.log('[GlobalAlert] show() 被调用:', { text, duration });
  155. if (!alertContainer) {
  156. console.log('[GlobalAlert] 初始化 alertContainer');
  157. init();
  158. }
  159. if (!alertContainer) {
  160. console.error('[GlobalAlert] alertContainer 未找到!');
  161. return;
  162. }
  163. if (!alertMessage) {
  164. console.error('[GlobalAlert] alertMessage 未找到!');
  165. return;
  166. }
  167. console.log('[GlobalAlert] 设置消息:', text);
  168. // 清除之前的自动隐藏定时器
  169. if (hideTimer) {
  170. clearTimeout(hideTimer);
  171. hideTimer = null;
  172. }
  173. alertMessage.textContent = text;
  174. alertContainer.classList.add('show');
  175. console.log('[GlobalAlert] 已添加 show 类,alert 应该可见了');
  176. // 自动隐藏
  177. if (duration > 0) {
  178. hideTimer = setTimeout(() => {
  179. hide();
  180. }, duration);
  181. }
  182. }
  183. function hide() {
  184. if (!alertContainer) return;
  185. alertContainer.classList.remove('show');
  186. if (hideTimer) {
  187. clearTimeout(hideTimer);
  188. hideTimer = null;
  189. }
  190. }
  191. return {
  192. show,
  193. hide
  194. };
  195. })();
  196. // 页面管理:负责切换 iframe 中的子页面,并保持与导航栏状态同步
  197. (function () {
  198. console.log('[Index] index.js 已加载');
  199. const DEFAULT_PAGE = "store";
  200. function getPageFrame() {
  201. return document.getElementById("pageFrame");
  202. }
  203. function getNavigationFrame() {
  204. return document.getElementById("navigationFrame");
  205. }
  206. function switchPage(page) {
  207. // 只处理实际的页面切换,不处理login/register
  208. if (page === "login" || page === "register") {
  209. return;
  210. }
  211. // profile页面是独立页面,直接跳转
  212. if (page === "profile") {
  213. window.location.href = "page/profile/profile.html";
  214. return;
  215. }
  216. const frame = getPageFrame();
  217. if (!frame) {
  218. return;
  219. }
  220. switch (page) {
  221. case "store":
  222. frame.src = "page/store/store.html";
  223. break;
  224. case "assets":
  225. frame.src = "page/assets/assets.html";
  226. break;
  227. default:
  228. frame.src = "page/store/store.html";
  229. break;
  230. }
  231. // 同步导航栏状态
  232. syncNavigationState(page);
  233. }
  234. // 同步导航栏状态
  235. function syncNavigationState(page) {
  236. const navigationFrame = getNavigationFrame();
  237. if (navigationFrame && navigationFrame.contentWindow) {
  238. // 使用setTimeout确保iframe已加载
  239. setTimeout(() => {
  240. navigationFrame.contentWindow.postMessage(
  241. { type: "navigation", page },
  242. "*"
  243. );
  244. }, 100);
  245. }
  246. }
  247. window.addEventListener("message", (event) => {
  248. // 调试:记录所有收到的消息
  249. console.log('[Index] 收到message事件:', {
  250. origin: event.origin,
  251. expectedOrigin: window.location.origin,
  252. data: event.data,
  253. source: event.source,
  254. type: event.data?.type
  255. });
  256. // 检查 origin(允许同源或 localhost,或者来自 iframe)
  257. const isSameOrigin = event.origin === window.location.origin;
  258. const isLocalhost = event.origin === 'http://localhost:3000' ||
  259. event.origin === 'http://127.0.0.1:3000' ||
  260. event.origin.startsWith('http://localhost:') ||
  261. event.origin.startsWith('http://127.0.0.1:');
  262. // 允许来自同源的 iframe(即使 origin 不完全匹配)
  263. const isFromIframe = event.source && event.source !== window;
  264. console.log('[Index] Origin 检查:', {
  265. eventOrigin: event.origin,
  266. windowOrigin: window.location.origin,
  267. isSameOrigin,
  268. isLocalhost,
  269. isFromIframe,
  270. willPass: isSameOrigin || isLocalhost || isFromIframe
  271. });
  272. // 对于 global-alert 消息,放宽 origin 检查(允许来自任何同源 iframe)
  273. if (event.data && event.data.type === 'global-alert') {
  274. console.log('[Index] 这是 global-alert 消息,放宽 origin 检查');
  275. // 允许来自任何 iframe 的消息(只要 source 存在且不是 window 本身)
  276. if (isFromIframe || isSameOrigin || isLocalhost) {
  277. console.log('[Index] global-alert 消息通过检查');
  278. } else {
  279. console.warn('[Index] global-alert 消息被 origin 检查过滤:', event.origin);
  280. // 即使 origin 不匹配,也允许 global-alert 消息通过(因为来自同源 iframe)
  281. console.log('[Index] 但允许通过(来自 iframe)');
  282. }
  283. } else if (!isSameOrigin && !isLocalhost && !isFromIframe) {
  284. console.log('[Index] 消息被 origin 检查过滤:', event.origin);
  285. return;
  286. }
  287. console.log('[Index] 消息通过 origin 检查,继续处理');
  288. const { data } = event;
  289. if (data && data.type === "navigation" && (data.page === "login" || data.page === "register")) {
  290. // console.log('[2-Index] 收到login/register消息');
  291. const loginFrame = document.getElementById('loginViewFrame');
  292. if (loginFrame) {
  293. const mode = data.page === "register" ? "register" : "login";
  294. loginFrame.style.display = 'block';
  295. // console.log('[3-Index] iframe已显示');
  296. const sendMode = () => {
  297. if (loginFrame.contentWindow) {
  298. loginFrame.contentWindow.postMessage({
  299. type: 'open-login-view',
  300. mode: mode
  301. }, '*');
  302. // console.log('[4-Index] 消息已发送到login iframe');
  303. } else {
  304. setTimeout(sendMode, 100);
  305. }
  306. };
  307. sendMode();
  308. const handleLoad = () => {
  309. setTimeout(() => {
  310. sendMode();
  311. }, 50);
  312. };
  313. if (loginFrame.contentDocument && loginFrame.contentDocument.readyState === 'complete') {
  314. handleLoad();
  315. } else {
  316. loginFrame.addEventListener('load', handleLoad, { once: true });
  317. }
  318. }
  319. } else if (data && data.type === "navigation" && data.page) {
  320. switchPage(data.page);
  321. }
  322. // 注意:global-alert、global-loading、global-confirm 消息不再通过 index.js 处理
  323. // 各个 view 现在直接调用父窗口的 GlobalAlert/GlobalLoading/GlobalConfirm
  324. else if (data && data.type === "open-export-view") {
  325. // 处理打开导出弹出框
  326. console.log('[Index] 收到open-export-view消息:', data);
  327. if (!data.folderName) {
  328. console.error('[Index] 缺少文件夹名称');
  329. return;
  330. }
  331. if (!window.ExportViewManager) {
  332. console.error('[Index] ExportViewManager 未初始化');
  333. return;
  334. }
  335. // 直接打开弹出框,传递文件夹名称
  336. window.ExportViewManager.show(data.folderName, { skipPreviewUI: data.skipPreviewUI }).then((confirmed) => {
  337. console.log('[Index] 用户选择:', confirmed ? '确认导出' : '取消');
  338. // 如果用户确认,可以在这里处理实际的导出下载逻辑
  339. if (confirmed) {
  340. // TODO: 处理实际的导出下载逻辑
  341. console.log('[Index] 用户确认导出,文件夹:', data.folderName);
  342. }
  343. }).catch(error => {
  344. console.error('[Index] ExportViewManager显示失败:', error);
  345. });
  346. } else if (data && data.type === "close-login-view") {
  347. const loginFrame = document.getElementById('loginViewFrame');
  348. if (loginFrame) {
  349. loginFrame.style.display = 'none';
  350. }
  351. } else if (data && data.type === "open-ai-generate-view") {
  352. // 处理打开AI生图界面
  353. console.log('[Index] 收到open-ai-generate-view消息:', data);
  354. const aiGenerateFrame = document.getElementById('aiGenerateViewFrame');
  355. if (aiGenerateFrame) {
  356. aiGenerateFrame.style.display = 'block';
  357. aiGenerateFrame.style.pointerEvents = 'auto';
  358. aiGenerateFrame.style.visibility = 'visible';
  359. const sendAIData = () => {
  360. if (aiGenerateFrame.contentWindow) {
  361. aiGenerateFrame.contentWindow.postMessage({
  362. type: 'show-ai-generate',
  363. folderName: data.folderName,
  364. spritesheetData: data.spritesheetData,
  365. spritesheetLayout: data.spritesheetLayout
  366. }, '*');
  367. } else {
  368. setTimeout(sendAIData, 100);
  369. }
  370. };
  371. sendAIData();
  372. }
  373. } else if (data && data.type === "close-ai-generate-view") {
  374. const aiGenerateFrame = document.getElementById('aiGenerateViewFrame');
  375. if (aiGenerateFrame) {
  376. aiGenerateFrame.style.display = 'none';
  377. aiGenerateFrame.style.pointerEvents = 'none';
  378. aiGenerateFrame.style.visibility = 'hidden';
  379. }
  380. } else if (data && data.type === "open-pay-view") {
  381. // 处理打开支付界面
  382. const payFrame = document.getElementById('payViewFrame');
  383. if (payFrame) {
  384. payFrame.style.display = 'block';
  385. payFrame.style.pointerEvents = 'auto';
  386. payFrame.style.visibility = 'visible';
  387. const sendPayData = () => {
  388. if (payFrame.contentWindow) {
  389. payFrame.contentWindow.postMessage({
  390. type: 'open-pay-view',
  391. itemName: data.itemName,
  392. price: data.price,
  393. resourcePath: data.resourcePath,
  394. categoryDir: data.categoryDir
  395. }, '*');
  396. } else {
  397. setTimeout(sendPayData, 100);
  398. }
  399. };
  400. sendPayData();
  401. const handleLoad = () => {
  402. setTimeout(() => {
  403. sendPayData();
  404. }, 50);
  405. };
  406. if (payFrame.contentDocument && payFrame.contentDocument.readyState === 'complete') {
  407. handleLoad();
  408. } else {
  409. payFrame.addEventListener('load', handleLoad, { once: true });
  410. }
  411. }
  412. } else if (data && data.type === "close-pay-view") {
  413. const payFrame = document.getElementById('payViewFrame');
  414. if (payFrame) {
  415. payFrame.style.display = 'none';
  416. payFrame.style.pointerEvents = 'none';
  417. // 确保 iframe 不会遮挡其他元素
  418. payFrame.style.visibility = 'hidden';
  419. }
  420. } else if (data && data.type === "payment-success") {
  421. // 支付成功,刷新商店页面(如果需要)
  422. if (window.HintView) {
  423. window.HintView.success(`购买成功!${data.itemName} 已添加到网盘`, 3000);
  424. }
  425. } else if (data && data.type === "open-recharge-view") {
  426. // 处理打开充值界面
  427. const rechargeFrame = document.getElementById('rechargeViewFrame');
  428. if (rechargeFrame) {
  429. rechargeFrame.style.display = 'block';
  430. rechargeFrame.style.pointerEvents = 'auto';
  431. rechargeFrame.style.visibility = 'visible';
  432. const sendRechargeData = () => {
  433. if (rechargeFrame.contentWindow) {
  434. rechargeFrame.contentWindow.postMessage({
  435. type: 'open-recharge-view',
  436. needPoints: data.needPoints,
  437. currentPoints: data.currentPoints
  438. }, '*');
  439. } else {
  440. setTimeout(sendRechargeData, 100);
  441. }
  442. };
  443. sendRechargeData();
  444. const handleLoad = () => {
  445. setTimeout(() => {
  446. sendRechargeData();
  447. }, 50);
  448. };
  449. if (rechargeFrame.contentDocument && rechargeFrame.contentDocument.readyState === 'complete') {
  450. handleLoad();
  451. } else {
  452. rechargeFrame.addEventListener('load', handleLoad, { once: true });
  453. }
  454. }
  455. } else if (data && data.type === "close-recharge-view") {
  456. const rechargeFrame = document.getElementById('rechargeViewFrame');
  457. if (rechargeFrame) {
  458. rechargeFrame.style.display = 'none';
  459. rechargeFrame.style.pointerEvents = 'none';
  460. rechargeFrame.style.visibility = 'hidden';
  461. }
  462. } else if (data && data.type === "recharge-success") {
  463. // 充值成功,关闭充值界面
  464. const rechargeFrame = document.getElementById('rechargeViewFrame');
  465. if (rechargeFrame) {
  466. rechargeFrame.style.display = 'none';
  467. rechargeFrame.style.pointerEvents = 'none';
  468. rechargeFrame.style.visibility = 'hidden';
  469. }
  470. // 刷新点数显示
  471. if (window.postMessage) {
  472. window.postMessage({ type: 'refresh-points' }, '*');
  473. }
  474. // 显示成功提示
  475. if (window.HintView) {
  476. window.HintView.success(`充值成功!获得 ${data.points} Ani币`, 3000);
  477. }
  478. } else if (data && data.type === "avatar-updated") {
  479. // 头像更新,通知导航栏更新
  480. const navigationFrame = document.getElementById('navigationFrame');
  481. if (navigationFrame && navigationFrame.contentWindow) {
  482. // 从localStorage获取用户信息并更新头像
  483. try {
  484. const loginDataStr = localStorage.getItem('loginData');
  485. if (loginDataStr) {
  486. const loginData = JSON.parse(loginDataStr);
  487. if (loginData.user) {
  488. loginData.user.avatar = data.avatar;
  489. localStorage.setItem('loginData', JSON.stringify(loginData));
  490. // 通知导航栏更新
  491. navigationFrame.contentWindow.postMessage({
  492. type: 'login-success',
  493. user: loginData.user
  494. }, '*');
  495. }
  496. }
  497. } catch (error) {
  498. console.error('[Index] 更新头像信息失败:', error);
  499. }
  500. }
  501. } else if (data && data.type === "login-success" && data.user) {
  502. // 显示登录成功提示(在主窗口)
  503. if (window.HintView) {
  504. window.HintView.success('登录成功', 2000);
  505. }
  506. // 处理登录成功消息,转发给 navigation iframe 和 pageFrame
  507. const navigationFrame = getNavigationFrame();
  508. if (navigationFrame && navigationFrame.contentWindow) {
  509. navigationFrame.contentWindow.postMessage({
  510. type: 'login-success',
  511. user: data.user
  512. }, '*');
  513. }
  514. // 也转发给 pageFrame(store 页面)
  515. const pageFrame = getPageFrame();
  516. if (pageFrame && pageFrame.contentWindow) {
  517. pageFrame.contentWindow.postMessage({
  518. type: 'login-success',
  519. user: data.user
  520. }, '*');
  521. }
  522. // 转发给 assets iframe(如果存在),它会再转发给 disk iframe
  523. const assetsFrame = document.getElementById('assetsFrame');
  524. if (assetsFrame && assetsFrame.contentWindow) {
  525. assetsFrame.contentWindow.postMessage({
  526. type: 'login-success',
  527. user: data.user
  528. }, '*');
  529. }
  530. } else if (data && data.type === "refresh-points") {
  531. // 刷新用户点数显示
  532. console.log('[Index] 收到刷新点数请求');
  533. // 转发给导航栏更新点数
  534. const navigationFrame = getNavigationFrame();
  535. if (navigationFrame && navigationFrame.contentWindow) {
  536. navigationFrame.contentWindow.postMessage({ type: 'refresh-points' }, '*');
  537. }
  538. // 也转发给个人中心页面(如果打开的话)
  539. const pageFrame = getPageFrame();
  540. if (pageFrame && pageFrame.contentWindow) {
  541. pageFrame.contentWindow.postMessage({ type: 'refresh-points' }, '*');
  542. }
  543. } else if (data && data.type === "logout") {
  544. // 清除 localStorage 中的登录信息
  545. try {
  546. localStorage.removeItem('loginData');
  547. console.log('[Index] 登出,已清除登录信息');
  548. } catch (error) {
  549. console.error('[Index] 清除登录信息失败:', error);
  550. }
  551. // 处理登出消息,转发给所有 iframe
  552. const navigationFrame = getNavigationFrame();
  553. if (navigationFrame && navigationFrame.contentWindow) {
  554. navigationFrame.contentWindow.postMessage({
  555. type: 'logout'
  556. }, '*');
  557. }
  558. const pageFrame = getPageFrame();
  559. if (pageFrame && pageFrame.contentWindow) {
  560. pageFrame.contentWindow.postMessage({
  561. type: 'logout'
  562. }, '*');
  563. }
  564. const assetsFrame = document.getElementById('assetsFrame');
  565. if (assetsFrame && assetsFrame.contentWindow) {
  566. assetsFrame.contentWindow.postMessage({
  567. type: 'logout'
  568. }, '*');
  569. }
  570. }
  571. });
  572. // 检查并恢复登录状态
  573. function checkAndRestoreLogin() {
  574. try {
  575. const loginDataStr = localStorage.getItem('loginData');
  576. if (!loginDataStr) {
  577. return;
  578. }
  579. const loginData = JSON.parse(loginDataStr);
  580. const now = Date.now();
  581. // 检查是否过期(2小时)
  582. if (now >= loginData.expireTime) {
  583. // 已过期,清除登录信息
  584. localStorage.removeItem('loginData');
  585. console.log('[Index] 登录信息已过期(2小时),已清除');
  586. return;
  587. }
  588. // 未过期,恢复登录状态
  589. if (loginData.user) {
  590. console.log('[Index] 恢复登录状态,用户:', loginData.user.username);
  591. // 通知所有 iframe 登录成功
  592. const navigationFrame = getNavigationFrame();
  593. if (navigationFrame && navigationFrame.contentWindow) {
  594. navigationFrame.contentWindow.postMessage({
  595. type: 'login-success',
  596. user: loginData.user
  597. }, '*');
  598. }
  599. const pageFrame = getPageFrame();
  600. if (pageFrame && pageFrame.contentWindow) {
  601. pageFrame.contentWindow.postMessage({
  602. type: 'login-success',
  603. user: loginData.user
  604. }, '*');
  605. }
  606. const assetsFrame = document.getElementById('assetsFrame');
  607. if (assetsFrame && assetsFrame.contentWindow) {
  608. assetsFrame.contentWindow.postMessage({
  609. type: 'login-success',
  610. user: loginData.user
  611. }, '*');
  612. }
  613. }
  614. } catch (error) {
  615. console.error('[Index] 恢复登录状态失败:', error);
  616. localStorage.removeItem('loginData');
  617. }
  618. }
  619. window.addEventListener("DOMContentLoaded", () => {
  620. // 先检查并恢复登录状态
  621. checkAndRestoreLogin();
  622. switchPage(DEFAULT_PAGE);
  623. syncNavigationState(DEFAULT_PAGE);
  624. });
  625. })();