feat: 支持加载进度提示和 API 重试机制
- 添加 ProgressTips 节点到 PageLoading 展示加载状态消息 - 连接 statusLabel 到 ProgressTips 组件 - LevelDataManager 添加 API 请求重试机制(重试 2 次) - 优化进度消息:正在请求服务端数据、正在加载游戏必备资源等 - 初始化失败时显示"网络异常,请重新打开游戏" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,9 @@ export class LevelDataManager {
|
||||
/** 请求超时时间(毫秒) */
|
||||
private readonly REQUEST_TIMEOUT = 8000;
|
||||
|
||||
/** API 请求重试次数 */
|
||||
private readonly API_RETRY_COUNT = 2;
|
||||
|
||||
/** API 返回的原始关卡数据 */
|
||||
private _apiData: ApiLevelData[] = [];
|
||||
|
||||
@@ -62,12 +65,12 @@ export class LevelDataManager {
|
||||
|
||||
try {
|
||||
// 阶段1: 获取 API 数据 (0-30%)
|
||||
onProgress?.(0, '正在获取关卡数据...');
|
||||
const apiData = await this._fetchApiData();
|
||||
onProgress?.(0, '正在请求服务端数据...');
|
||||
const apiData = await this._fetchApiData(onProgress);
|
||||
|
||||
if (!apiData || apiData.length === 0) {
|
||||
console.warn('[LevelDataManager] API 返回空数据');
|
||||
onProgress?.(0.3, 'API 数据为空,使用本地配置');
|
||||
onProgress?.(0.3, '网络异常,请重新打开游戏');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -78,7 +81,7 @@ export class LevelDataManager {
|
||||
|
||||
// 阶段2: 只预加载第一关图片 (30-80%)
|
||||
const firstLevel = apiData[0];
|
||||
onProgress?.(0.3, '正在加载第一关资源...');
|
||||
onProgress?.(0.3, '正在加载游戏必备资源...');
|
||||
|
||||
const spriteFrame = await this._loadImage(firstLevel.imageUrl);
|
||||
if (spriteFrame) {
|
||||
@@ -86,12 +89,12 @@ export class LevelDataManager {
|
||||
}
|
||||
|
||||
console.log('[LevelDataManager] 初始化完成,第一关资源已加载');
|
||||
onProgress?.(0.8, '第一关资源加载完成');
|
||||
onProgress?.(0.8, '游戏资源加载完成');
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[LevelDataManager] 初始化失败:', error);
|
||||
onProgress?.(0.3, '获取数据失败,使用本地配置');
|
||||
onProgress?.(0.3, '网络异常,请重新打开游戏');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,22 +208,44 @@ export class LevelDataManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 API 获取关卡数据
|
||||
* 从 API 获取关卡数据(带重试机制)
|
||||
* @param onProgress 进度回调
|
||||
*/
|
||||
private async _fetchApiData(): Promise<ApiLevelData[] | null> {
|
||||
try {
|
||||
const response = await HttpUtil.get<ApiResponse>(this.API_URL, this.REQUEST_TIMEOUT);
|
||||
private async _fetchApiData(onProgress?: ProgressCallback): Promise<ApiLevelData[] | null> {
|
||||
let lastError: Error | null = null;
|
||||
|
||||
if (!response.success) {
|
||||
console.warn(`[LevelDataManager] API 返回失败, 消息: ${response.message}`);
|
||||
return null;
|
||||
for (let attempt = 1; attempt <= this.API_RETRY_COUNT; attempt++) {
|
||||
const progress = (attempt - 1) / this.API_RETRY_COUNT * 0.3;
|
||||
|
||||
try {
|
||||
onProgress?.(progress, `正在请求服务端数据 (第${attempt}次)...`);
|
||||
|
||||
const response = await HttpUtil.get<ApiResponse>(this.API_URL, this.REQUEST_TIMEOUT);
|
||||
|
||||
if (!response.success) {
|
||||
console.warn(`[LevelDataManager] API 返回失败, 消息: ${response.message}`);
|
||||
lastError = new Error(response.message || 'API 返回失败');
|
||||
} else {
|
||||
return response.data.levels;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`[LevelDataManager] 第${attempt}次请求失败:`, error);
|
||||
lastError = error as Error;
|
||||
}
|
||||
|
||||
return response.data.levels;
|
||||
} catch (error) {
|
||||
console.error('[LevelDataManager] API 请求失败:', error);
|
||||
return null;
|
||||
// 重试逻辑(无论是 response.success 为 false 还是抛出异常)
|
||||
if (attempt < this.API_RETRY_COUNT) {
|
||||
onProgress?.(progress + 0.05, `请求失败,正在重试...`);
|
||||
await this._delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
console.error('[LevelDataManager] API 请求重试全部失败:', lastError);
|
||||
return null;
|
||||
}
|
||||
|
||||
private _delay(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user