feat: 支持关卡数据

This commit is contained in:
richarjiang
2026-03-15 23:12:06 +08:00
parent c54a404c12
commit 9ec8106733
8 changed files with 1246 additions and 1291 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -7,27 +7,6 @@ import { LevelDataManager } from 'db://assets/scripts/utils/LevelDataManager';
import { RuntimeLevelConfig } from 'db://assets/scripts/types/LevelTypes'; import { RuntimeLevelConfig } from 'db://assets/scripts/types/LevelTypes';
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
/**
* 关卡配置类
*/
@ccclass('LevelConfig')
export class LevelConfig {
@property(SpriteFrame)
mainImage: SpriteFrame | null = null;
@property({ tooltip: '线索1内容默认解锁' })
clue1: string = '';
@property({ tooltip: '线索2内容' })
clue2: string = '';
@property({ tooltip: '线索3内容' })
clue3: string = '';
@property({ tooltip: '答案(用于确定输入框数量和验证)' })
answer: string = '';
}
/** /**
* 关卡页面组件 * 关卡页面组件
* 继承 BaseView实现页面生命周期 * 继承 BaseView实现页面生命周期
@@ -78,9 +57,6 @@ export class PageLevel extends BaseView {
liveLabel: Label | null = null; liveLabel: Label | null = null;
// ========== 配置属性 ========== // ========== 配置属性 ==========
@property([LevelConfig])
levelConfigs: LevelConfig[] = [];
@property({ @property({
min: 0, min: 0,
tooltip: '当前关卡索引' tooltip: '当前关卡索引'
@@ -106,9 +82,12 @@ export class PageLevel extends BaseView {
/** 倒计时是否结束 */ /** 倒计时是否结束 */
private _isTimeUp: boolean = false; private _isTimeUp: boolean = false;
/** 当前关卡配置API 或本地) */ /** 当前关卡配置 */
private _currentConfig: RuntimeLevelConfig | null = null; private _currentConfig: RuntimeLevelConfig | null = null;
/** 是否正在切换关卡(防止重复提交) */
private _isTransitioning: boolean = false;
/** /**
* 页面首次加载时调用 * 页面首次加载时调用
*/ */
@@ -147,64 +126,28 @@ export class PageLevel extends BaseView {
} }
/** /**
* 初始化关卡 * 初始化关卡(从 API 数据加载)
*/ */
private initLevel(): void { private initLevel(): void {
// 优先使用 API 数据
if (LevelDataManager.instance.hasApiData()) {
this._initFromApiConfig();
} else {
this._initFromLocalConfig();
}
}
/**
* 从 API 配置初始化关卡
*/
private _initFromApiConfig(): void {
const config = LevelDataManager.instance.getLevelConfig(this.currentLevelIndex); const config = LevelDataManager.instance.getLevelConfig(this.currentLevelIndex);
if (!config) { if (!config) {
console.warn('[PageLevel] 没有找到 API 关卡配置'); console.warn(`[PageLevel] 没有找到关卡配置,索引: ${this.currentLevelIndex}`);
// 降级到本地配置
this._initFromLocalConfig();
return; return;
} }
console.log(`[PageLevel] 使用 API 配置初始化关卡 ${this.currentLevelIndex + 1}: ${config.name}`); console.log(`[PageLevel] 初始化关卡 ${this.currentLevelIndex + 1}: ${config.name}`);
this._applyLevelConfig(config); this._applyLevelConfig(config);
} }
/**
* 从本地配置初始化关卡
*/
private _initFromLocalConfig(): void {
const config = this.levelConfigs[this.currentLevelIndex];
if (!config) {
console.warn('[PageLevel] 没有找到本地关卡配置');
return;
}
// 创建 RuntimeLevelConfig 从本地配置
const runtimeConfig: RuntimeLevelConfig = {
id: this.currentLevelIndex,
name: `关卡 ${this.currentLevelIndex + 1}`,
spriteFrame: config.mainImage,
clue1: config.clue1,
clue2: config.clue2,
clue3: config.clue3,
answer: config.answer
};
console.log(`[PageLevel] 使用本地配置初始化关卡 ${this.currentLevelIndex + 1}`);
this._applyLevelConfig(runtimeConfig);
}
/** /**
* 应用关卡配置(通用初始化逻辑) * 应用关卡配置(通用初始化逻辑)
*/ */
private _applyLevelConfig(config: RuntimeLevelConfig): void { private _applyLevelConfig(config: RuntimeLevelConfig): void {
this._currentConfig = config; this._currentConfig = config;
// 重置关卡切换状态,允许再次提交
this._isTransitioning = false;
// 重置倒计时状态 // 重置倒计时状态
this._isTimeUp = false; this._isTimeUp = false;
this._countdown = 60; this._countdown = 60;
@@ -668,6 +611,7 @@ export class PageLevel extends BaseView {
*/ */
onSubmitAnswer(): void { onSubmitAnswer(): void {
if (!this._currentConfig) return; if (!this._currentConfig) return;
if (this._isTransitioning) return;
const userAnswer = this.getAnswer(); const userAnswer = this.getAnswer();
console.log(`[PageLevel] 提交答案: ${userAnswer}, 正确答案: ${this._currentConfig.answer}`); console.log(`[PageLevel] 提交答案: ${userAnswer}, 正确答案: ${this._currentConfig.answer}`);
@@ -688,6 +632,9 @@ export class PageLevel extends BaseView {
private showSuccess(): void { private showSuccess(): void {
console.log('[PageLevel] 答案正确!'); console.log('[PageLevel] 答案正确!');
// 标记正在切换关卡,防止重复提交
this._isTransitioning = true;
// 停止倒计时 // 停止倒计时
this.stopCountdown(); this.stopCountdown();
@@ -723,10 +670,7 @@ export class PageLevel extends BaseView {
this.currentLevelIndex++; this.currentLevelIndex++;
// 检查是否还有关卡 // 检查是否还有关卡
const manager = LevelDataManager.instance; const totalLevels = LevelDataManager.instance.getLevelCount();
const totalLevels = manager.hasApiData()
? manager.getLevelCount()
: this.levelConfigs.length;
if (this.currentLevelIndex >= totalLevels) { if (this.currentLevelIndex >= totalLevels) {
// 所有关卡完成 // 所有关卡完成

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "b6801da6-5ffd-48d2-8d5c-a2d837c825d3",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -4,32 +4,37 @@ import { SpriteFrame } from 'cc';
* API 返回的单个关卡数据结构 * API 返回的单个关卡数据结构
*/ */
export interface ApiLevelData { export interface ApiLevelData {
/** 关卡 ID */ /** 关卡 ID (UUID) */
id: number; id: string;
/** 关卡名称 */ /** 关卡序号 */
name: string; level: number;
/** 主图 URL */ /** 主图 URL */
imageUrl: string; imageUrl: string;
/** 线索1(映射到 clue1 */ /** 线索1 */
hint1: string; hint1: string;
/** 线索2(映射到 clue2 */ /** 线索2 */
hint2: string; hint2: string;
/** 线索3(映射到 clue3 */ /** 线索3 */
hint3: string; hint3: string;
/** 答案 */ /** 答案 */
answer: string; answer: string;
/** 排序 */
sortOrder: number;
} }
/** /**
* API 响应结构 * API 响应结构
*/ */
export interface ApiResponse { export interface ApiResponse {
/** 状态码0 表示成功 */ /** 是否成功 */
code: number; success: boolean;
/** 响应消息 */ /** 响应消息 */
message: string; message: string | null;
/** 关卡数据数组 */ /** 响应数据 */
data: ApiLevelData[]; data: {
levels: ApiLevelData[];
total: number;
};
} }
/** /**
@@ -37,7 +42,7 @@ export interface ApiResponse {
*/ */
export interface RuntimeLevelConfig { export interface RuntimeLevelConfig {
/** 关卡 ID */ /** 关卡 ID */
id: number; id: string;
/** 关卡名称 */ /** 关卡名称 */
name: string; name: string;
/** 主图 SpriteFrame可能为 null 如果加载失败) */ /** 主图 SpriteFrame可能为 null 如果加载失败) */

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "4cf882b6-b17f-470d-a76b-ea0783d5d424",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "5b29e766-746d-4646-98fd-7908fdd9dbe0",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -119,12 +119,12 @@ export class LevelDataManager {
try { try {
const response = await HttpUtil.get<ApiResponse>(this.API_URL, this.REQUEST_TIMEOUT); const response = await HttpUtil.get<ApiResponse>(this.API_URL, this.REQUEST_TIMEOUT);
if (response.code !== 0) { if (!response.success) {
console.warn(`[LevelDataManager] API 返回错误码: ${response.code}, 消息: ${response.message}`); console.warn(`[LevelDataManager] API 返回失败, 消息: ${response.message}`);
return null; return null;
} }
return response.data; return response.data.levels;
} catch (error) { } catch (error) {
console.error('[LevelDataManager] API 请求失败:', error); console.error('[LevelDataManager] API 请求失败:', error);
return null; return null;
@@ -149,7 +149,7 @@ export class LevelDataManager {
configs.push({ configs.push({
id: data.id, id: data.id,
name: data.name, name: `${data.level}`,
spriteFrame: spriteFrame, spriteFrame: spriteFrame,
clue1: data.hint1, clue1: data.hint1,
clue2: data.hint2, clue2: data.hint2,

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "082391a3-f1eb-476c-b5b3-810c757f536c",
"files": [],
"subMetas": {},
"userData": {}
}