Files
mp-xieyingeng/assets/PageLoading.ts
2026-04-24 21:44:22 +08:00

186 lines
6.5 KiB
TypeScript

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<void> {
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<boolean> {
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}`);
}
}