feat: 接入我创建的挑战列表接口
This commit is contained in:
16
AGENTS.md
Normal file
16
AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## 项目结构与模块组织
|
||||
本仓库是 `Cocos Creator 3.8.8` 小游戏项目。主入口在 `assets/main.ts`,主场景是 `assets/main.scene`。页面与弹窗组件集中在 `assets/prefabs/`,命名通常为 `PageXxx.ts`、`PassModal.ts`。公共逻辑位于 `assets/scripts/`:`core/` 放页面基类与视图管理,`utils/` 放 SDK、鉴权、存储、网络等工具,`config/` 放接口配置,`types/` 放类型定义。静态资源在 `assets/resources/`,编辑器配置在 `settings/v2/packages/`,设计说明在 `docs/` 与根目录分析文档中。
|
||||
|
||||
## 构建、调试与开发命令
|
||||
先运行 `npm install`,同步 `minigame-api-typings` 依赖。日常开发主要通过 Cocos Creator 编辑器完成:使用 3.8.8 打开仓库,点击 `Play` 预览,使用 `Project > Build` 或 `Cmd+B` 构建小游戏包。若编辑器已生成 `temp/tsconfig.cocos.json`,可执行 `npx tsc --noEmit` 做一次 TypeScript 静态检查。
|
||||
|
||||
## 代码风格与命名约定
|
||||
项目使用 TypeScript,当前代码统一为 4 空格缩进。组件类、页面类、管理器类使用 `PascalCase`,实例属性与私有方法使用 `camelCase` / `_camelCase`,管理器统一使用 `XxxManager` 后缀。新增页面、预制体、脚本请保持同名,例如 `PageLevel.prefab` 对应 `PageLevel.ts`。优先把复用逻辑放入 `assets/scripts/utils/` 或 `assets/scripts/core/`,不要把业务代码散落到场景脚本中。Cocos 资源的 `.meta` 文件必须一并提交。
|
||||
|
||||
## 测试与验证
|
||||
仓库当前未配置 Jest、Vitest 一类自动化测试。提交前至少完成三项验证:1. 编辑器预览主流程可进入页面;2. 目标平台构建成功;3. 涉及微信能力时,在真机或开发者工具验证登录、分享、隐私授权等流程。若修改接口或体力/关卡逻辑,补充手动验证步骤到 PR 描述。
|
||||
|
||||
## 提交与 Pull Request 规范
|
||||
Git 历史采用 Conventional Commits,且摘要多为中文,例如 `feat: 支持分享关卡通关上报`、`fix: 修复关卡排序`、`docs: 添加设计文档`。请继续使用 `feat:`、`fix:`、`perf:`、`docs:` 前缀,首行聚焦单一变更。PR 需说明改动范围、影响页面或模块、验证方式;涉及 UI 请附截图或录屏,涉及微信环境差异请写明复现条件与平台。
|
||||
@@ -1,6 +1,9 @@
|
||||
import { _decorator, Node, Button } from 'cc';
|
||||
import { BaseView } from 'db://assets/scripts/core/BaseView';
|
||||
import { ViewManager } from 'db://assets/scripts/core/ViewManager';
|
||||
import { CreatedShareItem } from 'db://assets/scripts/types/ApiTypes';
|
||||
import { ShareManager } from 'db://assets/scripts/utils/ShareManager';
|
||||
import { ToastManager } from 'db://assets/scripts/utils/ToastManager';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('PagePKData')
|
||||
@@ -8,6 +11,9 @@ export class PagePKData extends BaseView {
|
||||
@property({ type: Node, tooltip: '返回按钮' })
|
||||
backBtn: Node | null = null;
|
||||
|
||||
private _createdShares: CreatedShareItem[] = [];
|
||||
private _isLoading: boolean = false;
|
||||
|
||||
onViewLoad(): void {
|
||||
if (this.backBtn) {
|
||||
this.backBtn.on(Button.EventType.CLICK, this._onBackClick, this);
|
||||
@@ -15,6 +21,7 @@ export class PagePKData extends BaseView {
|
||||
}
|
||||
|
||||
onViewShow(): void {
|
||||
void this._loadCreatedShares();
|
||||
}
|
||||
|
||||
onViewHide(): void {
|
||||
@@ -24,6 +31,26 @@ export class PagePKData extends BaseView {
|
||||
ViewManager.instance.back();
|
||||
}
|
||||
|
||||
private async _loadCreatedShares(): Promise<void> {
|
||||
if (this._isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isLoading = true;
|
||||
try {
|
||||
const items = await ShareManager.instance.fetchCreatedShares();
|
||||
if (!items) {
|
||||
ToastManager.instance.show('获取挑战列表失败,请稍后重试');
|
||||
return;
|
||||
}
|
||||
|
||||
this._createdShares = items;
|
||||
console.log('[PagePKData] 我创建的挑战列表:', this._createdShares);
|
||||
} finally {
|
||||
this._isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
onViewDestroy(): void {
|
||||
if (this.backBtn) {
|
||||
this.backBtn.off(Button.EventType.CLICK, this._onBackClick, this);
|
||||
|
||||
@@ -20,6 +20,7 @@ export const API_ENDPOINTS = {
|
||||
GAME_CONFIGS: `${API_BASE}/game-configs`,
|
||||
/** 分享相关 */
|
||||
SHARE_CREATE: `${API_BASE}/share`,
|
||||
SHARE_CREATED: `${API_BASE}/share/created`,
|
||||
SHARE_PROGRESS: `${API_BASE}/share/progress`,
|
||||
/** 用户信息 */
|
||||
USER_INFO: `${API_BASE}/user/info`,
|
||||
|
||||
@@ -97,9 +97,9 @@ export interface ShareLevelData {
|
||||
level: number;
|
||||
imageUrl: string;
|
||||
answer: string;
|
||||
hint1: string;
|
||||
hint2: string;
|
||||
hint3: string;
|
||||
hint1: string | null;
|
||||
hint2: string | null;
|
||||
hint3: string | null;
|
||||
sortOrder: number;
|
||||
}
|
||||
|
||||
@@ -116,3 +116,19 @@ export interface ReportProgressData {
|
||||
timeLimit: number | null;
|
||||
withinTimeLimit: boolean;
|
||||
}
|
||||
|
||||
/** 我创建的分享挑战条目 */
|
||||
export interface CreatedShareItem {
|
||||
id: string;
|
||||
shareCode: string;
|
||||
title: string;
|
||||
levelCount: number;
|
||||
participantCount: number;
|
||||
userRank: number | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
/** 我创建的分享挑战列表响应 */
|
||||
export interface CreatedShareListData {
|
||||
items: CreatedShareItem[];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,15 @@ import { SpriteFrame, Texture2D, ImageAsset, assetManager } from 'cc';
|
||||
import { HttpUtil } from './HttpUtil';
|
||||
import { WxSDK } from './WxSDK';
|
||||
import { API_ENDPOINTS, getShareJoinUrl, API_TIMEOUT } from '../config/ApiConfig';
|
||||
import { ApiEnvelope, CreateShareData, JoinShareData, ReportProgressData, ShareLevelData } from '../types/ApiTypes';
|
||||
import {
|
||||
ApiEnvelope,
|
||||
CreateShareData,
|
||||
JoinShareData,
|
||||
ReportProgressData,
|
||||
ShareLevelData,
|
||||
CreatedShareItem,
|
||||
CreatedShareListData,
|
||||
} from '../types/ApiTypes';
|
||||
import { RuntimeLevelConfig } from '../types/LevelTypes';
|
||||
|
||||
/**
|
||||
@@ -20,6 +28,7 @@ export class ShareManager {
|
||||
|
||||
private _shareTitle: string = '';
|
||||
private _shareCode: string | null = null;
|
||||
private _createdShares: CreatedShareItem[] = [];
|
||||
|
||||
/** 图片缓存:URL -> SpriteFrame */
|
||||
private _imageCache: Map<string, SpriteFrame> = new Map();
|
||||
@@ -37,6 +46,10 @@ export class ShareManager {
|
||||
return this._shareLevels !== null && this._shareLevels.length > 0;
|
||||
}
|
||||
|
||||
get createdShares(): CreatedShareItem[] {
|
||||
return [...this._createdShares];
|
||||
}
|
||||
|
||||
async createShare(title: string, levelIds: string[]): Promise<string | null> {
|
||||
try {
|
||||
const response = await HttpUtil.post<ApiEnvelope<CreateShareData>>(
|
||||
@@ -83,6 +96,7 @@ export class ShareManager {
|
||||
clue2: level.hint2,
|
||||
clue3: level.hint3,
|
||||
answer: level.answer,
|
||||
completed: false,
|
||||
}));
|
||||
|
||||
// 预加载首关图片
|
||||
@@ -102,6 +116,27 @@ export class ShareManager {
|
||||
}
|
||||
}
|
||||
|
||||
async fetchCreatedShares(): Promise<CreatedShareItem[] | null> {
|
||||
try {
|
||||
const response = await HttpUtil.get<ApiEnvelope<CreatedShareListData>>(
|
||||
API_ENDPOINTS.SHARE_CREATED,
|
||||
API_TIMEOUT.DEFAULT,
|
||||
);
|
||||
|
||||
if (!response.success || !response.data) {
|
||||
console.error('[ShareManager] 获取我创建的挑战列表失败:', response.message);
|
||||
return null;
|
||||
}
|
||||
|
||||
this._createdShares = response.data.items ?? [];
|
||||
console.log(`[ShareManager] 获取我创建的挑战列表成功: ${this._createdShares.length} 条`);
|
||||
return this.createdShares;
|
||||
} catch (err) {
|
||||
console.error('[ShareManager] 获取我创建的挑战列表异常:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async ensureShareLevelReady(index: number): Promise<RuntimeLevelConfig | null> {
|
||||
if (!this._shareLevels || index < 0 || index >= this._shareLevels.length) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user