feat: 对接最新的关卡工作流
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { _decorator, Node, EditBox, instantiate, Vec3, Button, Label, Sprite, SpriteFrame, AudioClip, AudioSource, Prefab } from 'cc';
|
||||
import { BaseView } from 'db://assets/scripts/core/BaseView';
|
||||
import { ViewManager } from 'db://assets/scripts/core/ViewManager';
|
||||
import { StorageManager } from 'db://assets/scripts/utils/StorageManager';
|
||||
import { StaminaManager } from 'db://assets/scripts/utils/StaminaManager';
|
||||
import { WxSDK } from 'db://assets/scripts/utils/WxSDK';
|
||||
import { LevelDataManager } from 'db://assets/scripts/utils/LevelDataManager';
|
||||
@@ -10,13 +9,16 @@ import { RuntimeLevelConfig } from 'db://assets/scripts/types/LevelTypes';
|
||||
import { ToastManager } from 'db://assets/scripts/utils/ToastManager';
|
||||
import { ShareManager } from 'db://assets/scripts/utils/ShareManager';
|
||||
import { PassModal } from 'db://assets/prefabs/PassModal';
|
||||
import { StaminaInfo } from 'db://assets/scripts/types/ApiTypes';
|
||||
import { WrongModal } from 'db://assets/prefabs/WrongModal';
|
||||
import { TimeoutModal } from 'db://assets/prefabs/TimeoutModal';
|
||||
import { StaminaInfo, NextLevelData } from 'db://assets/scripts/types/ApiTypes';
|
||||
import { AchievementTitleManager } from 'db://assets/scripts/utils/AchievementTitleManager';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 关卡页面组件
|
||||
* 继承 BaseView,实现页面生命周期
|
||||
* 关卡流程由服务端 NextLevelData 驱动,客户端不再维护关卡列表
|
||||
*/
|
||||
@ccclass('PageLevel')
|
||||
export class PageLevel extends BaseView {
|
||||
@@ -29,9 +31,6 @@ export class PageLevel extends BaseView {
|
||||
/** 答案正确后展示包袱答案的停留时间 */
|
||||
private static readonly PASS_MODAL_DELAY_MS = 2000;
|
||||
|
||||
/** 答案错误后清空输入的延迟,给失败音效和错误答案留出反馈时间 */
|
||||
private static readonly CLEAR_INPUT_DELAY_MS = 500;
|
||||
|
||||
// ========== 节点引用 ==========
|
||||
@property(Node)
|
||||
inputLayout: Node | null = null;
|
||||
@@ -88,17 +87,11 @@ export class PageLevel extends BaseView {
|
||||
@property(Label)
|
||||
liveLabel: Label | null = null;
|
||||
|
||||
/** 关卡标题标签,显示为“第 N 关” */
|
||||
/** 关卡标题标签,显示为"第 N 关" */
|
||||
@property(Label)
|
||||
titleLevelLabel: Label | null = null;
|
||||
|
||||
// ========== 配置属性 ==========
|
||||
@property({
|
||||
min: 0,
|
||||
tooltip: '当前关卡索引'
|
||||
})
|
||||
currentLevelIndex: number = 0;
|
||||
|
||||
@property(AudioClip)
|
||||
clickAudio: AudioClip | null = null;
|
||||
|
||||
@@ -111,6 +104,12 @@ export class PageLevel extends BaseView {
|
||||
@property(Prefab)
|
||||
passModalPrefab: Prefab | null = null;
|
||||
|
||||
@property(Prefab)
|
||||
wrongModalPrefab: Prefab | null = null;
|
||||
|
||||
@property(Prefab)
|
||||
timeoutModalPrefab: Prefab | null = null;
|
||||
|
||||
// ========== 内部状态 ==========
|
||||
/** 当前创建的输入框节点数组 */
|
||||
private _inputNodes: Node[] = [];
|
||||
@@ -157,12 +156,32 @@ export class PageLevel extends BaseView {
|
||||
/** 本次通关弹窗使用的已通关数量 */
|
||||
private _passModalCompletedLevelCount: number | null = null;
|
||||
|
||||
/** 错误弹窗实例 */
|
||||
private _wrongModalNode: Node | null = null;
|
||||
|
||||
/** 超时弹窗实例 */
|
||||
private _timeoutModalNode: Node | null = null;
|
||||
|
||||
/** 是否处于分享挑战模式 */
|
||||
private _isShareMode: boolean = false;
|
||||
|
||||
/** 体力恢复倒计时定时器 */
|
||||
private _staminaTimerId: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
// ========== 关卡驱动状态(NextLevel 驱动) ==========
|
||||
|
||||
/** 当前关卡 ID */
|
||||
private _currentLevelId: string = '';
|
||||
|
||||
/** 当前关卡编号(仅显示用,来自 NextLevelData.level) */
|
||||
private _currentLevelNumber: number = 0;
|
||||
|
||||
/** 下一关数据(来自 complete 接口返回),点击"下一关"时使用 */
|
||||
private _nextLevelData: NextLevelData | null = null;
|
||||
|
||||
/** 分享模式下的关卡索引(仅分享模式使用) */
|
||||
private _shareLevelIndex: number = 0;
|
||||
|
||||
/**
|
||||
* 页面首次加载时调用
|
||||
*/
|
||||
@@ -173,14 +192,20 @@ export class PageLevel extends BaseView {
|
||||
this._isShareMode = params?.shareMode === true;
|
||||
|
||||
if (this._isShareMode) {
|
||||
this.currentLevelIndex = 0;
|
||||
this._shareLevelIndex = 0;
|
||||
console.log('[PageLevel] 进入分享挑战模式');
|
||||
} else {
|
||||
// 根据关卡列表找到第一个未通关的关卡
|
||||
this.currentLevelIndex = LevelDataManager.instance.getFirstUncompletedIndex();
|
||||
StorageManager.setCurrentLevelIndex(this.currentLevelIndex);
|
||||
console.log(`[PageLevel] 进入第一个未通关关卡: 第 ${this.currentLevelIndex + 1} 关`);
|
||||
// 从 AuthManager 获取首关数据(由 PageLoading → game-data 提供)
|
||||
const nextLevel = AuthManager.instance.nextLevel;
|
||||
if (nextLevel) {
|
||||
this._currentLevelId = nextLevel.id;
|
||||
this._currentLevelNumber = nextLevel.level;
|
||||
console.log(`[PageLevel] 进入关卡: 第 ${nextLevel.level} 关 (${nextLevel.id})`);
|
||||
} else {
|
||||
console.warn('[PageLevel] 没有可用关卡');
|
||||
}
|
||||
}
|
||||
|
||||
this.updateStaminaLabel();
|
||||
this.initIconSetting();
|
||||
this.initUnlockButtons();
|
||||
@@ -218,6 +243,8 @@ export class PageLevel extends BaseView {
|
||||
this.clearPunchBlocks();
|
||||
this.stopCountdown();
|
||||
this._closePassModal();
|
||||
this._closeWrongModal();
|
||||
this._closeTimeoutModal();
|
||||
this._stopStaminaRecoverTimer();
|
||||
|
||||
// 清理事件监听
|
||||
@@ -229,77 +256,85 @@ export class PageLevel extends BaseView {
|
||||
|
||||
/**
|
||||
* 进入关卡并初始化
|
||||
* 1. 加载关卡图片资源
|
||||
* 1. 加载关卡图片资源(从缓存或 NextLevelData)
|
||||
* 2. 调用进入关卡接口(消耗体力,获取答案和线索)
|
||||
* 3. 启动倒计时
|
||||
*/
|
||||
private async _enterAndInitLevel(): Promise<void> {
|
||||
// 先加载关卡图片资源
|
||||
let config: RuntimeLevelConfig | null = null;
|
||||
|
||||
if (this._isShareMode) {
|
||||
config = await ShareManager.instance.ensureShareLevelReady(this.currentLevelIndex);
|
||||
// 分享模式:使用 ShareManager 的关卡数据
|
||||
config = await ShareManager.instance.ensureShareLevelReady(this._shareLevelIndex);
|
||||
} else {
|
||||
config = LevelDataManager.instance.getLevelConfig(this.currentLevelIndex);
|
||||
// 正常模式:先尝试从缓存获取(PageLoading 初始化时已加载首关)
|
||||
config = LevelDataManager.instance.getLevelConfig(this._currentLevelId);
|
||||
|
||||
if (!config) {
|
||||
console.log(`[PageLevel] 关卡 ${this.currentLevelIndex + 1} 资源未缓存,开始加载...`);
|
||||
config = await LevelDataManager.instance.ensureLevelReady(this.currentLevelIndex);
|
||||
// 缓存未命中,从 nextLevel 数据加载(complete 返回的下一关)
|
||||
const nextLevelData = this._nextLevelData ?? AuthManager.instance.nextLevel;
|
||||
if (nextLevelData && nextLevelData.id === this._currentLevelId) {
|
||||
console.log(`[PageLevel] 关卡 ${this._currentLevelId} 资源未缓存,开始加载...`);
|
||||
config = await LevelDataManager.instance.ensureLevelReady(nextLevelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
console.warn(`[PageLevel] 没有找到关卡配置,索引: ${this.currentLevelIndex}`);
|
||||
console.warn(`[PageLevel] 没有找到关卡配置,ID: ${this._currentLevelId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 非分享模式下,调用进入关卡接口获取答案和线索
|
||||
if (!this._isShareMode) {
|
||||
const levelId = LevelDataManager.instance.getLevelId(this.currentLevelIndex);
|
||||
if (levelId) {
|
||||
const enterData = await StaminaManager.instance.enterLevel(levelId);
|
||||
if (!enterData) {
|
||||
// 进入关卡失败(可能是体力不足)
|
||||
const stamina = StaminaManager.instance.getStamina();
|
||||
if (stamina.current <= 0) {
|
||||
ToastManager.show('体力不足,请等待恢复');
|
||||
this._startStaminaRecoverTimer();
|
||||
} else {
|
||||
ToastManager.show('进入关卡失败,请重试');
|
||||
}
|
||||
this.updateStaminaLabel();
|
||||
return;
|
||||
const enterData = await StaminaManager.instance.enterLevel(this._currentLevelId);
|
||||
if (!enterData) {
|
||||
// 进入关卡失败(可能是体力不足)
|
||||
const stamina = StaminaManager.instance.getStamina();
|
||||
if (stamina.current <= 0) {
|
||||
ToastManager.show('体力不足,请等待恢复');
|
||||
this._startStaminaRecoverTimer();
|
||||
} else {
|
||||
ToastManager.show('进入关卡失败,请重试');
|
||||
}
|
||||
|
||||
// 提示用户消耗体力
|
||||
ToastManager.show(`消耗1点体力,剩余 ${enterData.stamina.current}/${this._getStaminaMax(enterData.stamina)}`);
|
||||
|
||||
// 用 enter 接口返回的数据更新关卡配置(填充答案和线索)
|
||||
LevelDataManager.instance.updateLevelDetails(
|
||||
this.currentLevelIndex,
|
||||
{
|
||||
answer: enterData.answer,
|
||||
image1Description: enterData.image1Description,
|
||||
image2Description: enterData.image2Description,
|
||||
punchline: enterData.punchline,
|
||||
hint1: enterData.hint1,
|
||||
hint2: enterData.hint2,
|
||||
hint3: enterData.hint3,
|
||||
}
|
||||
);
|
||||
|
||||
// 重新获取更新后的配置
|
||||
config = LevelDataManager.instance.getLevelConfig(this.currentLevelIndex);
|
||||
if (!config) {
|
||||
console.error('[PageLevel] 更新关卡详情后获取配置失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新体力显示
|
||||
this.updateStaminaLabel();
|
||||
return;
|
||||
}
|
||||
|
||||
// 提示用户消耗体力
|
||||
ToastManager.show(`消耗1点体力,剩余 ${enterData.stamina.current}/${this._getStaminaMax(enterData.stamina)}`);
|
||||
|
||||
// 用 enter 接口返回的数据更新关卡配置(填充答案和线索)
|
||||
LevelDataManager.instance.updateLevelDetails(
|
||||
this._currentLevelId,
|
||||
{
|
||||
answer: enterData.answer,
|
||||
image1Description: enterData.image1Description,
|
||||
image2Description: enterData.image2Description,
|
||||
punchline: enterData.punchline,
|
||||
hint1: enterData.hint1,
|
||||
hint2: enterData.hint2,
|
||||
hint3: enterData.hint3,
|
||||
}
|
||||
);
|
||||
|
||||
// 重新获取更新后的配置
|
||||
config = LevelDataManager.instance.getLevelConfig(this._currentLevelId);
|
||||
if (!config) {
|
||||
console.error('[PageLevel] 更新关卡详情后获取配置失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新体力显示
|
||||
this.updateStaminaLabel();
|
||||
|
||||
// 预加载下一关图片(enter 返回的 preloadNextLevel)
|
||||
if (enterData.preloadNextLevel) {
|
||||
LevelDataManager.instance.preloadLevel(enterData.preloadNextLevel);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[PageLevel] 初始化关卡 ${this.currentLevelIndex + 1}: ${config.name}`);
|
||||
console.log(`[PageLevel] 初始化关卡 第${this._currentLevelNumber}关: ${config.name}`);
|
||||
this._applyLevelConfig(config);
|
||||
this.startCountdown();
|
||||
}
|
||||
@@ -315,7 +350,7 @@ export class PageLevel extends BaseView {
|
||||
|
||||
// 重置倒计时状态
|
||||
this._isTimeUp = false;
|
||||
this._countdown = 60;
|
||||
this._countdown = config.timeLimit ?? 60;
|
||||
|
||||
// 设置主图(图片1)
|
||||
this.setMainImage(config.spriteFrame1);
|
||||
@@ -355,17 +390,16 @@ export class PageLevel extends BaseView {
|
||||
// 更新倒计时显示
|
||||
this.updateClockLabel();
|
||||
|
||||
// 预加载下一关图片(静默加载,不阻塞)
|
||||
// 分享模式下预加载下一关
|
||||
if (this._isShareMode) {
|
||||
const nextIndex = this.currentLevelIndex + 1;
|
||||
const nextIndex = this._shareLevelIndex + 1;
|
||||
if (nextIndex < ShareManager.instance.getShareLevelCount()) {
|
||||
ShareManager.instance.ensureShareLevelReady(nextIndex).catch(() => {});
|
||||
}
|
||||
} else {
|
||||
LevelDataManager.instance.preloadNextLevel(this.currentLevelIndex);
|
||||
}
|
||||
// 正常模式的预加载在 enter 返回 preloadNextLevel 时已处理
|
||||
|
||||
console.log(`[PageLevel] 初始化关卡 ${this.currentLevelIndex + 1}, 答案长度: ${Array.from(config.answer ?? '').length}`);
|
||||
console.log(`[PageLevel] 初始化关卡 第${this._currentLevelNumber}关, 答案长度: ${Array.from(config.answer ?? '').length}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -806,7 +840,7 @@ export class PageLevel extends BaseView {
|
||||
private updateTitleLevelLabel(): void {
|
||||
if (!this.titleLevelLabel) return;
|
||||
|
||||
this.titleLevelLabel.string = `第 ${this.currentLevelIndex + 1} 关`;
|
||||
this.titleLevelLabel.string = `第 ${this._currentLevelNumber} 关`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -972,12 +1006,12 @@ export class PageLevel extends BaseView {
|
||||
* 开始倒计时
|
||||
*/
|
||||
private startCountdown(): void {
|
||||
this._countdown = 60;
|
||||
// _countdown 已在 _applyLevelConfig 中根据 timeLimit 设置
|
||||
this._isTimeUp = false;
|
||||
this._levelStartTime = Date.now();
|
||||
this.updateClockLabel();
|
||||
this.schedule(this.onCountdownTick, 1);
|
||||
console.log('[PageLevel] 开始倒计时 60 秒');
|
||||
console.log(`[PageLevel] 开始倒计时 ${this._countdown} 秒`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1018,7 +1052,7 @@ export class PageLevel extends BaseView {
|
||||
private onTimeUp(): void {
|
||||
console.log('[PageLevel] 倒计时结束!');
|
||||
this.playFailSound();
|
||||
// 可以在这里添加游戏结束逻辑
|
||||
this._showTimeoutModal();
|
||||
}
|
||||
|
||||
// ========== 体力值相关方法 ==========
|
||||
@@ -1086,7 +1120,7 @@ export class PageLevel extends BaseView {
|
||||
|
||||
this._stopStaminaRecoverTimer();
|
||||
|
||||
if (newCurrent < currentStamina.max) {
|
||||
if (newCurrent < currentMaxStamina) {
|
||||
this._startStaminaRecoverTimer();
|
||||
}
|
||||
}, 1000);
|
||||
@@ -1151,22 +1185,26 @@ export class PageLevel extends BaseView {
|
||||
this._showPassModal();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上报通关并获取下一关数据
|
||||
*/
|
||||
private reportLevelCompleted(levelId: string, timeSpent: number): void {
|
||||
if (!this._isShareMode) {
|
||||
// 标记关卡为已通关(本地缓存),通关上报并行执行,不阻塞包袱展示节奏
|
||||
const wasCompleted = LevelDataManager.instance.isLevelCompleted(this.currentLevelIndex);
|
||||
if (!wasCompleted) {
|
||||
AuthManager.instance.addCompletedLevelCount();
|
||||
}
|
||||
// 乐观更新通关计数(用于称号展示)
|
||||
AuthManager.instance.addCompletedLevelCount();
|
||||
this._passModalCompletedLevelCount = AuthManager.instance.completedLevelCount;
|
||||
LevelDataManager.instance.markLevelCompleted(this.currentLevelIndex);
|
||||
|
||||
void StaminaManager.instance.completeLevel(levelId, timeSpent).then((result) => {
|
||||
if (result) {
|
||||
if (!result.firstClear && !wasCompleted) {
|
||||
// 保存 complete 返回的下一关数据
|
||||
this._nextLevelData = result.nextLevel;
|
||||
|
||||
if (!result.firstClear) {
|
||||
// 非首次通关,回退乐观更新
|
||||
AuthManager.instance.addCompletedLevelCount(-1);
|
||||
this._passModalCompletedLevelCount = AuthManager.instance.completedLevelCount;
|
||||
}
|
||||
console.log(`[PageLevel] 通关上报成功,首次通关: ${result.firstClear}`);
|
||||
console.log(`[PageLevel] 通关上报成功,首次通关: ${result.firstClear}, 有下一关: ${!!result.nextLevel}`);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -1215,13 +1253,13 @@ export class PageLevel extends BaseView {
|
||||
const passModal = modalNode.getComponent(PassModal);
|
||||
if (passModal) {
|
||||
passModal.setParams({
|
||||
levelIndex: this.currentLevelIndex + 1,
|
||||
levelIndex: this._currentLevelNumber,
|
||||
titleInfo: AchievementTitleManager.getTitleInfo(this._getPassModalCompletedLevelCount())
|
||||
});
|
||||
passModal.setCallbacks({
|
||||
onNextLevel: () => {
|
||||
this._closePassModal();
|
||||
this.nextLevel();
|
||||
this.goToNextLevel();
|
||||
},
|
||||
onShare: () => {
|
||||
// 分享后不关闭弹窗,用户可继续点击下一关
|
||||
@@ -1251,6 +1289,127 @@ export class PageLevel extends BaseView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误弹窗
|
||||
*/
|
||||
private _showWrongModal(): void {
|
||||
if (!this.wrongModalPrefab) {
|
||||
console.warn('[PageLevel] wrongModalPrefab 未设置');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果弹窗已显示,不再重复创建
|
||||
if (this._wrongModalNode && this._wrongModalNode.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modalNode = instantiate(this.wrongModalPrefab);
|
||||
modalNode.setPosition(PageLevel.ZERO_POS);
|
||||
modalNode.setSiblingIndex(WrongModal.MODAL_Z_INDEX);
|
||||
|
||||
const canvasNode = this.node.parent;
|
||||
if (canvasNode) {
|
||||
canvasNode.addChild(modalNode);
|
||||
} else {
|
||||
this.node.addChild(modalNode);
|
||||
}
|
||||
this._wrongModalNode = modalNode;
|
||||
|
||||
const wrongModal = modalNode.getComponent(WrongModal);
|
||||
if (wrongModal) {
|
||||
wrongModal.setCallbacks({
|
||||
onContinue: () => {
|
||||
this._closeWrongModal();
|
||||
this.clearInputText();
|
||||
}
|
||||
});
|
||||
wrongModal.onViewLoad();
|
||||
wrongModal.onViewShow();
|
||||
}
|
||||
|
||||
console.log('[PageLevel] 显示错误弹窗');
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭错误弹窗
|
||||
*/
|
||||
private _closeWrongModal(): void {
|
||||
if (this._wrongModalNode && this._wrongModalNode.isValid) {
|
||||
this._wrongModalNode.destroy();
|
||||
this._wrongModalNode = null;
|
||||
console.log('[PageLevel] 关闭错误弹窗');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示超时弹窗
|
||||
*/
|
||||
private _showTimeoutModal(): void {
|
||||
if (!this.timeoutModalPrefab) {
|
||||
console.warn('[PageLevel] timeoutModalPrefab 未设置');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果弹窗已显示,不再重复创建
|
||||
if (this._timeoutModalNode && this._timeoutModalNode.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modalNode = instantiate(this.timeoutModalPrefab);
|
||||
modalNode.setPosition(PageLevel.ZERO_POS);
|
||||
modalNode.setSiblingIndex(TimeoutModal.MODAL_Z_INDEX);
|
||||
|
||||
const canvasNode = this.node.parent;
|
||||
if (canvasNode) {
|
||||
canvasNode.addChild(modalNode);
|
||||
} else {
|
||||
this.node.addChild(modalNode);
|
||||
}
|
||||
this._timeoutModalNode = modalNode;
|
||||
|
||||
const timeoutModal = modalNode.getComponent(TimeoutModal);
|
||||
if (timeoutModal) {
|
||||
timeoutModal.setParams({
|
||||
levelIndex: this._currentLevelNumber
|
||||
});
|
||||
timeoutModal.setCallbacks({
|
||||
onShare: () => {
|
||||
console.log('[PageLevel] 超时弹窗分享完成');
|
||||
},
|
||||
onRestart: () => {
|
||||
this._closeTimeoutModal();
|
||||
this._enterAndInitLevel().catch(err => {
|
||||
console.error('[PageLevel] 重新进入关卡失败:', err);
|
||||
});
|
||||
},
|
||||
onHome: () => {
|
||||
this._closeTimeoutModal();
|
||||
if (this._isShareMode) {
|
||||
ShareManager.instance.clearShareMode();
|
||||
ViewManager.instance.replace('PageHome');
|
||||
} else {
|
||||
ViewManager.instance.back();
|
||||
}
|
||||
}
|
||||
});
|
||||
timeoutModal.onViewLoad();
|
||||
timeoutModal.onViewShow();
|
||||
}
|
||||
|
||||
console.log('[PageLevel] 显示超时弹窗');
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭超时弹窗
|
||||
*/
|
||||
private _closeTimeoutModal(): void {
|
||||
if (this._timeoutModalNode && this._timeoutModalNode.isValid) {
|
||||
this._timeoutModalNode.destroy();
|
||||
this._timeoutModalNode = null;
|
||||
console.log('[PageLevel] 关闭超时弹窗');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误提示
|
||||
*/
|
||||
@@ -1263,32 +1422,21 @@ export class PageLevel extends BaseView {
|
||||
// 触发手机震动
|
||||
WxSDK.vibrateLong();
|
||||
|
||||
// 显示 Toast 提示
|
||||
ToastManager.show('答案错误,再试试吧!');
|
||||
|
||||
// 输入识别失败或答案错误后延迟清空,避免错误内容瞬间消失
|
||||
void this.delay(PageLevel.CLEAR_INPUT_DELAY_MS).then(() => {
|
||||
if (!this._isTransitioning) {
|
||||
this.clearInputText();
|
||||
}
|
||||
});
|
||||
// 显示错误弹窗
|
||||
this._showWrongModal();
|
||||
}
|
||||
|
||||
/**
|
||||
* 进入下一关
|
||||
* 正常模式:使用 complete 返回的 nextLevel 数据
|
||||
* 分享模式:按索引递增
|
||||
*/
|
||||
private async nextLevel(): Promise<void> {
|
||||
// 标记当前关卡已通关
|
||||
if (!this._isShareMode) {
|
||||
StorageManager.onLevelCompleted(this.currentLevelIndex);
|
||||
LevelDataManager.instance.markLevelCompleted(this.currentLevelIndex);
|
||||
}
|
||||
|
||||
// 查找下一个未通关的关卡
|
||||
private async goToNextLevel(): Promise<void> {
|
||||
if (this._isShareMode) {
|
||||
this.currentLevelIndex++;
|
||||
// 分享模式:按索引递增
|
||||
this._shareLevelIndex++;
|
||||
const totalLevels = ShareManager.instance.getShareLevelCount();
|
||||
if (this.currentLevelIndex >= totalLevels) {
|
||||
if (this._shareLevelIndex >= totalLevels) {
|
||||
console.log('[PageLevel] 分享关卡全部完成');
|
||||
this.stopCountdown();
|
||||
ShareManager.instance.clearShareMode();
|
||||
@@ -1296,20 +1444,23 @@ export class PageLevel extends BaseView {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const nextIndex = LevelDataManager.instance.getNextUncompletedIndex(this.currentLevelIndex);
|
||||
if (nextIndex < 0) {
|
||||
// 所有关卡全部通关
|
||||
// 正常模式:使用 complete 返回的 nextLevel
|
||||
if (!this._nextLevelData) {
|
||||
// 没有下一关 → 全部通关
|
||||
console.log('[PageLevel] 恭喜通关!所有关卡已完成');
|
||||
this.stopCountdown();
|
||||
ViewManager.instance.back();
|
||||
return;
|
||||
}
|
||||
this.currentLevelIndex = nextIndex;
|
||||
StorageManager.setCurrentLevelIndex(this.currentLevelIndex);
|
||||
|
||||
// 切换到下一关
|
||||
this._currentLevelId = this._nextLevelData.id;
|
||||
this._currentLevelNumber = this._nextLevelData.level;
|
||||
this._nextLevelData = null;
|
||||
}
|
||||
|
||||
// 重置并加载下一关(包含进入关卡接口调用)
|
||||
await this._enterAndInitLevel();
|
||||
console.log(`[PageLevel] 进入关卡 ${this.currentLevelIndex + 1}`);
|
||||
console.log(`[PageLevel] 进入关卡 第${this._currentLevelNumber}关`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user