From 9cf499a5e15d51d336a34668765944f22e1aa25b Mon Sep 17 00:00:00 2001 From: richarjiang Date: Fri, 10 Apr 2026 11:00:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=85=B3=E5=8D=A1?= =?UTF-8?q?=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/PageLoading.ts | 12 +++++-- assets/prefabs/PageLevel.ts | 45 +++++++++++++----------- assets/scripts/utils/LevelDataManager.ts | 30 ++++++++++++++++ 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/assets/PageLoading.ts b/assets/PageLoading.ts index c97a6fc..6f7034b 100644 --- a/assets/PageLoading.ts +++ b/assets/PageLoading.ts @@ -113,8 +113,10 @@ export class PageLoading extends Component { } /** - * 用服务端通关进度覆盖本地进度 - * 将 completedLevelIds 转换为本地的 currentLevelIndex / maxUnlockedLevelIndex + * 用服务端通关进度同步本地进度 + * 1. 根据 completedLevelIds 标记已通关关卡 + * 2. 更新 maxUnlockedLevelIndex + * 3. 将 currentLevelIndex 设为第一个未通关关卡 */ private _syncProgressFromServer(): void { const completedIds = AuthManager.instance.completedLevelIds; @@ -132,9 +134,13 @@ export class PageLoading extends Component { // 取服务端和本地的较大值,防止进度回退 if (maxCompletedIndex > localMax) { - // onLevelCompleted 会同时设置 currentLevelIndex = maxCompletedIndex + 1 和 maxUnlockedLevelIndex StorageManager.onLevelCompleted(maxCompletedIndex); console.log(`[PageLoading] 服务端进度同步:已通关到第 ${maxCompletedIndex + 1} 关`); } + + // 根据关卡列表找到第一个未通关关卡,设为当前关卡 + const firstUncompleted = LevelDataManager.instance.getFirstUncompletedIndex(); + StorageManager.setCurrentLevelIndex(firstUncompleted); + console.log(`[PageLoading] 当前关卡设为第一个未通关: 第 ${firstUncompleted + 1} 关`); } } diff --git a/assets/prefabs/PageLevel.ts b/assets/prefabs/PageLevel.ts index 751edfd..9d65b5c 100644 --- a/assets/prefabs/PageLevel.ts +++ b/assets/prefabs/PageLevel.ts @@ -125,9 +125,10 @@ export class PageLevel extends BaseView { this.currentLevelIndex = 0; console.log('[PageLevel] 进入分享挑战模式'); } else { - // 从本地存储恢复关卡进度 - this.currentLevelIndex = StorageManager.getCurrentLevelIndex(); - console.log(`[PageLevel] 恢复关卡进度: 第 ${this.currentLevelIndex + 1} 关`); + // 根据关卡列表找到第一个未通关的关卡 + this.currentLevelIndex = LevelDataManager.instance.getFirstUncompletedIndex(); + StorageManager.setCurrentLevelIndex(this.currentLevelIndex); + console.log(`[PageLevel] 进入第一个未通关关卡: 第 ${this.currentLevelIndex + 1} 关`); } this.updateStaminaLabel(); this.initIconSetting(); @@ -905,30 +906,34 @@ export class PageLevel extends BaseView { * 进入下一关 */ private async nextLevel(): Promise { - // 分享模式不保存本地进度 + // 标记当前关卡已通关 if (!this._isShareMode) { StorageManager.onLevelCompleted(this.currentLevelIndex); + LevelDataManager.instance.markLevelCompleted(this.currentLevelIndex); } - this.currentLevelIndex++; - - // 检查是否还有关卡 - const totalLevels = this._isShareMode - ? ShareManager.instance.getShareLevelCount() - : LevelDataManager.instance.getLevelCount(); - - if (this.currentLevelIndex >= totalLevels) { - // 所有关卡完成 - console.log('[PageLevel] 恭喜通关!'); - this.stopCountdown(); - - if (this._isShareMode) { + // 查找下一个未通关的关卡 + if (this._isShareMode) { + this.currentLevelIndex++; + const totalLevels = ShareManager.instance.getShareLevelCount(); + if (this.currentLevelIndex >= totalLevels) { + console.log('[PageLevel] 分享关卡全部完成'); + this.stopCountdown(); ShareManager.instance.clearShareMode(); ViewManager.instance.replace('PageHome'); - } else { - ViewManager.instance.back(); + return; } - return; + } else { + const nextIndex = LevelDataManager.instance.getNextUncompletedIndex(this.currentLevelIndex); + if (nextIndex < 0) { + // 所有关卡全部通关 + console.log('[PageLevel] 恭喜通关!所有关卡已完成'); + this.stopCountdown(); + ViewManager.instance.back(); + return; + } + this.currentLevelIndex = nextIndex; + StorageManager.setCurrentLevelIndex(this.currentLevelIndex); } // 重置并加载下一关(包含进入关卡接口调用) diff --git a/assets/scripts/utils/LevelDataManager.ts b/assets/scripts/utils/LevelDataManager.ts index b0f71e6..12bc427 100644 --- a/assets/scripts/utils/LevelDataManager.ts +++ b/assets/scripts/utils/LevelDataManager.ts @@ -131,6 +131,36 @@ export class LevelDataManager { return this._apiData[index].completed; } + /** + * 获取第一个未通关的关卡索引 + * 遍历关卡列表,返回第一个 completed === false 的索引 + * 如果全部通关,返回最后一关的索引 + * @returns 第一个未通关关卡索引(0-based) + */ + getFirstUncompletedIndex(): number { + for (let i = 0; i < this._apiData.length; i++) { + if (!this._apiData[i].completed) { + return i; + } + } + // 全部通关,返回最后一关 + return Math.max(0, this._apiData.length - 1); + } + + /** + * 获取指定索引之后第一个未通关的关卡索引 + * @param afterIndex 从该索引之后开始查找(不含该索引) + * @returns 下一个未通关关卡索引,如果后续全部通关则返回 -1 + */ + getNextUncompletedIndex(afterIndex: number): number { + for (let i = afterIndex + 1; i < this._apiData.length; i++) { + if (!this._apiData[i].completed) { + return i; + } + } + return -1; + } + /** * 标记指定关卡为已通关(本地缓存更新) * @param index 关卡索引