Skip to content

1. 概述

本引导系统采用**递增序号(1, 2, 3, 4, 5)**管理用户的新手引导进度, 与服务端 AdvanceGuideStep 的"严格递增"语义天然契合。

2. 核心设计原则

2.1. 引导与领养分离

  • 真正的引导:仅包含主页操作引导(喂食、收蛋、兑奖、赚鹅粮、碰一碰)
  • 领养流程:选鹅、取名、领养成功属于首次领养流程,由 PetService.getFirstPet() 判定
  • 边界清晰:没有宠物时弹 AdoptPage,有宠物但 guide_step < STEP_LAST 时弹 GuidePage

2.2. 递增序号机制

  • 单调递增:每完成一步,guide_step 增加到对应步骤号
  • 顺序固定:引导必须按 STEP_ORDER 顺序完成
  • 服务端友好:服务端只要校验 新step > 旧step 即可

3. 引导步骤定义

typescript
export const STEP_NONE = 0;          // 未开始
export const STEP_FEED = 1;          // 喂食引导
export const STEP_COLLECT = 2;       // 收蛋引导
export const STEP_CLAIM_PRIZE = 3;   // 兑奖
export const STEP_EARN_FOOD = 4;     // 赚鹅粮引导
export const STEP_TAP = 5;           // 碰一碰

export const STEP_LAST = STEP_TAP;   // guide_step >= STEP_LAST 视为全部完成

export const STEP_ORDER: readonly number[] = [
  STEP_FEED,
  STEP_COLLECT,
  STEP_CLAIM_PRIZE,
  STEP_EARN_FOOD,
  STEP_TAP,
];

4. 辅助函数

typescript
/** 某个 step 是否已完成(已走过/到达) */
export function isStepDone(current: number, step: number): boolean {
  return current >= step;
}

/** 找出第一个未完成的 step;全部完成返回 null */
export function nextPendingStep(current: number): number | null {
  for (const s of STEP_ORDER) {
    if (s > current) return s;
  }
  return null;
}

/** 是否全部引导步骤都已完成 */
export function isAllFinished(current: number): boolean {
  return current >= STEP_LAST;
}

5. 数据流

PlayerService.getGuideStep()   ← 服务端 guide_step(当前进度序号)

nextPendingStep(current)        ← 找下一个 step > current 的步骤

渲染该 step 的卡片

用户点"知道了"

advanceGuideStep({ step: cur }) ← 上报当前 step 作为新进度
PlayerService.reload()           ← 拉取最新 guide_step

循环找下一个 / 全部完成则关闭

6. API 契约

6.1. advanceGuideStep

  • 入参{ step: number } — 完成本步后期望的新进度序号
  • 服务端校验step > 当前 guide_step,否则报错
  • 返回{ guide_step: number }

6.2. Mock 实现策略

mock 端用 Math.max(old, step) 合并,确保进度只能前进不能回退,与服务端"严格递增"语义一致。

7. 典型场景

7.1. 场景 1:用户从 0 开始

guide_step = 0 → nextPendingStep → STEP_FEED(1) → 展示喂食引导
点"知道了" → advanceGuideStep(1) → guide_step = 1
guide_step = 1 → nextPendingStep → STEP_COLLECT(2) → 展示收蛋引导
...依次推进

7.2. 场景 2:用户中途退出后再进入

guide_step = 2(已完成喂食、收蛋)
nextPendingStep(2) → STEP_CLAIM_PRIZE(3) → 直接从兑奖开始

7.3. 场景 3:全部完成

guide_step = 5 → isAllFinished(5) === true → 不再展示引导

8. 调试技巧

8.1. 强制从指定步骤开始

typescript
oops.gui.open(UIID.Guide, { startStep: STEP_CLAIM_PRIZE });

8.2. 临时调整 mock 起点

修改 assets/scripts/api/data/player.ts 中的 mockState.guideStep 初值(如 3 = 从兑奖开始)。

8.3. 重置 mock 进度

typescript
import { resetMockGuideStep } from 'src/api/data/player';
resetMockGuideStep(0);

9. 扩展性

9.1. 新增引导步骤

  1. GuideConfig.ts 末尾追加新常量(如 export const STEP_SHARE = 6
  2. 把它加到 STEP_ORDER 数组末尾
  3. 更新 STEP_LAST = STEP_SHARE
  4. STEP_META 中补充对应的文案

9.2. 调整引导顺序

直接调整 STEP_ORDER 数组顺序即可,但需要注意:

  • 由于服务端 guide_step 是单调递增的序号,调整顺序后已完成用户的状态会发生语义偏移
  • 推荐做法:保持现有 step 序号不变,新需求叠加在末尾

10. 最佳实践

10.1. 无魔法数字

  • 业务代码只引用导出的常量与 helper
  • 禁止硬编码 1/2/3 等数字

10.2. 错误处理

  • advanceGuideStep 失败时不阻塞 UI 推进
  • 用本地 currentStep 兜底,让用户能正常走完流程

10.3. 状态同步

  • 推进后调用 PlayerService.reload() 拿最新进度
  • reload 失败时用 Math.max(local, server) 兜底,避免回退

11. 总结

本引导系统通过递增序号机制实现了灵活、可扩展的引导进度管理,支持:

  • 多步骤并行完成
  • 独立的状态标记
  • 灵活的查询和推进
  • 良好的服务端兼容性
  • 易于扩展和维护

12. 掩码机制的核心优势

12.1. 步骤独立性

  • 每个步骤可以独立完成,不受顺序限制
  • 用户可以先完成"收蛋"(2),再完成"喂食"(1)
  • 服务端只需要记录完成状态,不需要关心完成顺序

12.2. 灵活的状态查询

typescript
// 快速判断特定步骤是否完成
const hasFeed = (guideStep & STEP_FEED) === STEP_FEED;
const hasCollect = (guideStep & STEP_COLLECT) === STEP_COLLECT;

// 判断是否全部完成
const allFinished = (guideStep & STEP_ALL) === STEP_ALL;

12.3. 服务端兼容性强

  • 位掩码模式:服务端使用 guide_step |= step 操作
  • 严格递增模式:前端可以一次性提交 STEP_ALL 兼容旧版本

12.4. 易于扩展

  • 新增步骤只需添加新的2的幂次方常量
  • 不影响现有步骤的完成状态

13. 关于30这个值的分析

13.1. 二进制分解

30的二进制: 11110
分解为: 16 + 8 + 4 + 2 = 30

13.2. 步骤完成状态

  • STEP_TAP(16) - 已完成
  • STEP_EARN_FOOD(8) - 已完成
  • STEP_CLAIM_PRIZE(4) - 已完成
  • STEP_COLLECT(2) - 已完成
  • STEP_FEED(1) - 未完成

13.3. 引导起点推断

typescript
// nextPendingStep(30) 的逻辑
STEP_ORDER = [1, 2, 4, 8, 16]  // 按顺序检查

// 检查STEP_FEED(1): (30 & 1) === 1? false → 返回STEP_FEED

结论:后台返回30确实会落到第一步(STEP_FEED),这是完全符合预期的!

14. 这种设计的业务意义

14.1. 支持用户跳过步骤

  • 用户可能因为各种原因跳过某些引导
  • 系统能够智能地从第一个未完成的步骤继续

14.2. 乱序完成的容错性

  • 即使步骤完成顺序与设计不一致,系统也能正确处理
  • 确保用户不会错过任何必要的引导

14.3. 调试和测试友好

  • 可以通过设置不同的掩码值来测试各种场景
  • 比如设置30来测试"只剩喂食未完成"的情况

15. 实际应用场景

15.1. 场景1:用户跳过喂食直接收蛋

初始状态: 0 (未开始)
用户完成收蛋: 0 | 2 = 2
下次引导: nextPendingStep(2) → 返回STEP_FEED(1)

15.2. 场景2:用户完成除第一步外的所有步骤

状态: 30 (16+8+4+2)
下次引导: nextPendingStep(30) → 返回STEP_FEED(1)

掩码机制的核心价值在于它的灵活性和鲁棒性,能够适应各种用户行为模式,确保引导系统既不会重复展示已完成的步骤,也不会遗漏未完成的步骤。