import { _decorator, Component, ProgressBar, Label, assetManager } from 'cc'; import type { AssetManager } from 'cc'; import { ViewManager } from './scripts/core/ViewManager'; import { LevelDataManager } from './scripts/utils/LevelDataManager'; import { AuthManager } from './scripts/utils/AuthManager'; import { StorageManager } from './scripts/utils/StorageManager'; import { ShareManager } from './scripts/utils/ShareManager'; import { WxSDK } from './scripts/utils/WxSDK'; const { ccclass, property } = _decorator; /** * 页面加载组件 * 负责用户登录、预加载资源并显示加载进度 * 登录与关卡数据加载并行执行以减少等待时间 */ @ccclass('PageLoading') export class PageLoading extends Component { private static readonly FONT_BUNDLE_NAME = 'fonts'; @property(ProgressBar) progressBar: ProgressBar | null = null; @property(Label) statusLabel: Label | null = null; start() { this._startPreload(); } private async _startPreload(): Promise { if (this.progressBar) { this.progressBar.progress = 0; } this._updateStatusLabel('正在加载...'); // 登录和关卡数据并行加载 const [loginSuccess, levelSuccess] = await Promise.all([ AuthManager.instance.initialize(), LevelDataManager.instance.initialize((progress, message) => { // 关卡加载占 0-80% 进度 this._updateProgress(progress); this._updateStatusLabel(message); }), ]); if (loginSuccess) { console.log('[PageLoading] 用户登录成功'); } else { console.warn('[PageLoading] 登录失败,继续离线模式'); } if (!levelSuccess) { this._updateStatusLabel('加载失败,请重新打开游戏'); return; } const fontSuccess = await this._loadFontBundle(); if (!fontSuccess) { this._updateStatusLabel('字体资源加载失败,请重新打开游戏'); return; } // 登录 + 关卡数据都就绪后,用服务端进度覆盖本地进度 if (loginSuccess) { this._syncProgressFromServer(); } // 检测分享码:从微信启动参数中获取 const shareCode = WxSDK.getShareCodeFromLaunch(); if (shareCode && loginSuccess) { this._updateStatusLabel('正在加载挑战关卡...'); const joinSuccess = await ShareManager.instance.joinShare(shareCode); if (joinSuccess) { this._updateProgress(1); this._updateStatusLabel('加载完成'); // 跳过首页,直接进入分享挑战关卡 ViewManager.instance.open('PageLevel', { params: { shareMode: true }, onComplete: () => { this.node.destroy(); }, }); return; } console.warn('[PageLoading] 加入分享失败,进入正常模式'); } // 正常流程:预加载 PageHome (82-100%) ViewManager.instance.preload('PageHome', (progress) => { this._updateProgress(0.82 + progress * 0.18); this._updateStatusLabel('正在加载界面资源...'); }, () => { this._onPreloadComplete(); } ); } private _updateProgress(progress: number): void { if (this.progressBar) { this.progressBar.progress = progress; } } private _updateStatusLabel(message: string): void { if (this.statusLabel) { this.statusLabel.string = message; } } private _onPreloadComplete(): void { this._updateProgress(1); this._updateStatusLabel('加载完成'); ViewManager.instance.open('PageHome', { onComplete: () => { this.node.destroy(); } }); } /** * 加载字体分包,避免字体资源进入小游戏主包 */ private _loadFontBundle(): Promise { const bundleName = PageLoading.FONT_BUNDLE_NAME; const cachedBundle = assetManager.getBundle(bundleName); if (cachedBundle) { console.log(`[PageLoading] 字体分包已加载: ${bundleName}`); this._updateProgress(0.82); return Promise.resolve(true); } this._updateStatusLabel('正在加载字体资源...'); this._updateProgress(0.8); return new Promise((resolve) => { assetManager.loadBundle(bundleName, (err: Error | null, bundle: AssetManager.Bundle | null) => { if (err || !bundle) { console.error(`[PageLoading] 字体分包加载失败: ${bundleName}`, err); resolve(false); return; } console.log(`[PageLoading] 字体分包加载完成: ${bundleName}`); this._updateProgress(0.82); resolve(true); }); }); } /** * 用服务端通关进度同步本地进度 * 1. 根据 completedLevelIds 标记已通关关卡 * 2. 更新 maxUnlockedLevelIndex * 3. 将 currentLevelIndex 设为第一个未通关关卡 */ private _syncProgressFromServer(): void { const completedIds = AuthManager.instance.completedLevelIds; if (completedIds.length === 0) { console.log('[PageLoading] 服务端无通关记录,使用本地进度'); return; } const maxCompletedIndex = LevelDataManager.instance.getMaxCompletedIndex(completedIds); if (maxCompletedIndex < 0) { return; } const localMax = StorageManager.getMaxUnlockedLevelIndex(); // 取服务端和本地的较大值,防止进度回退 if (maxCompletedIndex > localMax) { StorageManager.onLevelCompleted(maxCompletedIndex); console.log(`[PageLoading] 服务端进度同步:已通关到第 ${maxCompletedIndex + 1} 关`); } // 根据关卡列表找到第一个未通关关卡,设为当前关卡 const firstUncompleted = LevelDataManager.instance.getFirstUncompletedIndex(); StorageManager.setCurrentLevelIndex(firstUncompleted); console.log(`[PageLoading] 当前关卡设为第一个未通关: 第 ${firstUncompleted + 1} 关`); } }