# MemeMind API 变更文档 — 双图关卡 & 体力上限调整 > **版本**:v1.1.0 > **日期**:2026-04-19 > **影响范围**:关卡列表、进入关卡、分享挑战、体力系统 > **兼容性**:⚠️ Breaking Change — 客户端必须适配后方可上线 --- ## 一、变更概览 | 变更项 | 旧值 | 新值 | |--------|------|------| | 关卡图片数量 | 1 张(`imageUrl`) | 2 张(`image1Url` + `image2Url`) | | 图片文本说明 | 无 | 每张图片各有一个 `description` 字段 | | 谐音梗说明 | 无 | 新增 `punchline` 字段 | | 体力上限 | 5 | **50** | | 新用户默认体力 | 5 | **50** | | 体力恢复速率 | 每 10 分钟 1 点 | **不变** | --- ## 二、体力系统变更 ### StaminaInfo 结构(不变,数值范围扩大) ```typescript interface StaminaInfo { current: number; // 0 ~ 50(原 0 ~ 5) max: number; // 固定 50(原 5) nextRecoverAt: string | null; } ``` **客户端注意**: - 体力 UI 需要适配 0–50 的显示范围 - 恢复速率不变,满体力恢复时间从 50 分钟变为 500 分钟(约 8.3 小时) - 进入关卡仍消耗 1 点体力,已通关关卡仍免费 --- ## 三、接口字段变更 ### 3.1 `GET /api/v1/levels` — 获取关卡列表 **删除字段**: | 字段 | 类型 | 说明 | |------|------|------| | ~~`imageUrl`~~ | ~~string~~ | 已删除,替换为下方双图字段 | **新增字段**: | 字段 | 类型 | 说明 | |------|------|------| | `image1Url` | string | 图片1 URL | | `image1Description` | string \| null | 图片1 文本说明 | | `image2Url` | string | 图片2 URL | | `image2Description` | string \| null | 图片2 文本说明 | | `punchline` | string \| null | 谐音梗说明(**仅通关后返回**,未通关为 null) | **完整响应示例**: ```json { "success": true, "data": { "levels": [ { "id": "level_001", "level": 1, "image1Url": "https://cdn.example.com/levels/001_1.png", "image1Description": "一只猫在看鱼", "image2Url": "https://cdn.example.com/levels/001_2.png", "image2Description": "一条鱼在飞", "answer": "猫和鱼", "punchline": "谐音梗:鱼跃龙门 → 鱼越猫门", "hint1": "这是一个经典的...", "hint2": "和某个动物有关", "hint3": null, "completed": true, "timeSpent": 45 }, { "id": "level_002", "level": 2, "image1Url": "https://cdn.example.com/levels/002_1.png", "image1Description": "一个人在走路", "image2Url": "https://cdn.example.com/levels/002_2.png", "image2Description": "一辆车在跑", "answer": null, "punchline": null, "hint1": null, "hint2": null, "hint3": null, "completed": false, "timeSpent": null } ], "total": 2 }, "message": null, "timestamp": "2026-04-19T12:00:00.000Z" } ``` > **可见性规则**:`answer`、`punchline`、`hint1`、`hint2`、`hint3` 仅在 `completed: true` 时返回,未通关均为 `null`。`image1Url`、`image1Description`、`image2Url`、`image2Description` 始终返回。 --- ### 3.2 `POST /api/v1/levels/{id}/enter` — 进入关卡 **删除字段**: | 字段 | 类型 | 说明 | |------|------|------| | ~~`imageUrl`~~ | ~~string~~ | 已删除 | **新增字段**: | 字段 | 类型 | 说明 | |------|------|------| | `image1Url` | string | 图片1 URL | | `image1Description` | string \| null | 图片1 文本说明 | | `image2Url` | string | 图片2 URL | | `image2Description` | string \| null | 图片2 文本说明 | | `punchline` | string \| null | 谐音梗说明 | **完整响应示例**: ```json { "success": true, "data": { "id": "level_002", "level": 2, "image1Url": "https://cdn.example.com/levels/002_1.png", "image1Description": "一个人在走路", "image2Url": "https://cdn.example.com/levels/002_2.png", "image2Description": "一辆车在跑", "answer": "人车赛跑", "punchline": "谐音梗:车水马龙 → 车水人龙", "hint1": "第一个线索", "hint2": "第二个线索", "hint3": null, "stamina": { "current": 47, "max": 50, "nextRecoverAt": "2026-04-19T12:10:00.000Z" } }, "message": null, "timestamp": "2026-04-19T12:00:00.000Z" } ``` > **注意**:进入关卡时 `answer` 和 `punchline` 始终返回(无论是否通关),因为用户已消耗体力进入。 --- ### 3.3 `POST /api/v1/share/{shareCode}/join` — 加入分享挑战 分享挑战中的关卡数据同步变更。 **删除字段**(`levels[]` 中每个关卡): | 字段 | 类型 | 说明 | |------|------|------| | ~~`imageUrl`~~ | ~~string~~ | 已删除 | **新增字段**(`levels[]` 中每个关卡): | 字段 | 类型 | 说明 | |------|------|------| | `image1Url` | string | 图片1 URL | | `image1Description` | string \| null | 图片1 文本说明 | | `image2Url` | string | 图片2 URL | | `image2Description` | string \| null | 图片2 文本说明 | | `punchline` | string \| null | 谐音梗说明 | --- ### 3.4 未变更的接口 以下接口**无任何变更**,客户端无需修改: | 接口 | 说明 | |------|------| | `POST /api/v1/auth/wx-login` | 登录(新用户 stamina 初始为 50,但 login 返回结构不变) | | `GET /api/v1/user/profile` | 用户资料(stamina.max 变为 50,结构不变) | | `GET /api/v1/user/game-data` | 游戏数据(stamina.max 变为 50,结构不变) | | `POST /api/v1/levels/{id}/complete` | 通关上报(结构完全不变) | | `GET /api/v1/game-configs` | 游戏配置(不变) | | `GET /api/v1/game-configs/{key}` | 单个配置(不变) | --- ## 四、客户端适配清单 ### 必须修改 - [ ] 所有使用 `imageUrl` 的地方改为 `image1Url` + `image2Url` - [ ] 关卡详情页展示两张图片,每张图片下方展示 `image1Description` / `image2Description` - [ ] 通关后展示 `punchline`(谐音梗说明) - [ ] 体力 UI 适配 0–50 范围(进度条、数字显示等) - [ ] 更新 TypeScript 接口定义(见下方) ### 建议修改 - [ ] 体力恢复倒计时逻辑无需修改(恢复速率不变) - [ ] `punchline` 为 `null` 时不展示(未配置谐音梗的关卡) - [ ] `image2Url` 为空字符串时做兜底处理(历史关卡可能尚未配置第二张图) --- ## 五、客户端 TypeScript 接口定义 直接复制替换旧接口: ```typescript /** 关卡列表项 */ interface LevelListItem { id: string; level: number; image1Url: string; image1Description: string | null; image2Url: string; image2Description: string | null; answer: string | null; punchline: string | null; hint1: string | null; hint2: string | null; hint3: string | null; completed: boolean; timeSpent: number | null; } /** 进入关卡响应 */ interface EnterLevelResponse { id: string; level: number; image1Url: string; image1Description: string | null; image2Url: string; image2Description: string | null; answer: string; punchline: string | null; hint1: string | null; hint2: string | null; hint3: string | null; stamina: StaminaInfo; } /** 体力信息(结构不变,数值范围 0-50) */ interface StaminaInfo { current: number; max: number; // 50 nextRecoverAt: string | null; } /** 分享关卡 */ interface ShareLevel { id: string; level: number; image1Url: string; image1Description: string | null; image2Url: string; image2Description: string | null; answer: string; punchline: string | null; hint1: string | null; hint2: string | null; hint3: string | null; sortOrder: number; } ``` --- ## 六、字段映射速查表 方便全局搜索替换: | 旧字段 | 新字段 | 备注 | |--------|--------|------| | `imageUrl` | `image1Url` | 原图片字段,直接重命名 | | — | `image1Description` | 新增,图片1 说明文字 | | — | `image2Url` | 新增,第二张图片 | | — | `image2Description` | 新增,图片2 说明文字 | | — | `punchline` | 新增,谐音梗说明 | | `stamina.max = 5` | `stamina.max = 50` | 数值变更 |