# Client Bootstrap（任务清单）

> 说明：本清单根据 `plan.md` 拆解，要求“可执行、可验收、可标记”。  
> 标记规则：执行完成后将对应项从 `- [ ]` 改为 `- [x]`，并把“状态”改为 **已完成**；进行中改为 **进行中**；阻塞写明原因与解除条件。

## 0. 清单状态说明

- **状态**：未开始 / 进行中 / 已完成 / 阻塞
- **阻塞**：必须写明阻塞点（例如“缺少 Expo 工程代码”）与下一步需要谁提供什么

## 1. 文档完善（README 为准入门）

- [x] **更新 `client/README.md` 的包管理器命令统一为 pnpm**  
  - **状态**：已完成  
  - **内容**：将 `npm install`、`npm run *` 改为 `pnpm install`、`pnpm *`（或在 README 中明确“团队统一 pnpm”且给出 pnpm 命令为主）  
  - **验收**：README 中安装/启动/平台命令不混用 npm/pnpm

- [x] **补充 i18n “设置页切换语言”的落地说明**  
  - **状态**：已完成  
  - **内容**：在多语言章节增加“语言优先级：用户设置 > 设备语言 > 默认回退（zh-CN）”与“设置入口建议位置”  
  - **验收**：README 的 i18n 规则与 `spec.md/plan.md` 完全一致

## 2. 初始化 Expo 工程（若仓库尚未提交客户端代码）

> 若 `client/` 下已经存在 Expo 工程（`package.json`、`app.json/app.config.*`），跳过本章节并在任务上标记“已完成（已存在）”。

- [x] **在 `client/` 初始化 Expo + TypeScript 工程**  
  - **状态**：已完成  
  - **命令**：
    - `cd client`
    - `npx create-expo-app@latest .`（按提示选择 TypeScript 模板）
  - **产出**：生成 `package.json`、`app.json/app.config.*`、`assets/`、入口代码等  
  - **验收**：`client/` 下存在可运行的 Expo 工程基础文件

- [x] **切换为 pnpm 并安装依赖**  
  - **状态**：已完成  
  - **命令**：
    - `cd client`
    - `pnpm install`
  - **验收**：依赖安装成功，可执行 `pnpm start`

## 3. 建立标准目录结构（目标态）

- [x] **创建标准目录骨架（`app/` + `src/` + `assets/`）**  
  - **状态**：已完成  
  - **目录**：
    - `app/`（expo-router 路由目录，若采用）
    - `src/components/`
    - `src/constants/`
    - `src/features/push/`
    - `src/features/widget/`
    - `src/features/cards/`
    - `src/hooks/`
    - `src/i18n/locales/`
    - `src/services/`
    - `src/store/`
    - `src/types/`
    - `src/utils/`
  - **验收**：目录与 `client/README.md` 中的“标准目录结构”一致

## 4. 接入 i18n 基座（CN/EN/ES/PT/TC）

- [x] **引入 i18n 依赖并记录版本**  
  - **状态**：已完成（i18next@25.8.0 / react-i18next@16.5.4 / expo-localization@17.0.8 / AsyncStorage@2.2.0）  
  - **依赖**：`i18next`、`react-i18next`、`expo-localization`（如需持久化再加 `@react-native-async-storage/async-storage`）  
  - **验收**：`package.json` 中依赖齐全，且能正常打包/运行

- [x] **创建语言资源文件（5 份）**  
  - **状态**：已完成  
  - **文件**：
    - `src/i18n/locales/zh-CN.json`
    - `src/i18n/locales/en.json`
    - `src/i18n/locales/es.json`
    - `src/i18n/locales/pt.json`
    - `src/i18n/locales/zh-TW.json`
  - **内容要求**：至少包含 `common.ok/common.cancel` 等最小 key 集合（五种语言都要齐全）  
  - **验收**：同一 key 在 5 个文件都存在，不允许缺 key

- [x] **实现 `src/i18n/index.ts` 初始化与语言优先级**  
  - **状态**：已完成  
  - **规则**：
    - ① 用户设置语言（存在则优先）
    - ② 设备语言（在支持列表内）
    - ③ 默认回退（`zh-CN` 或团队指定默认）
  - **验收**：能在运行时切换语言并立即生效；重启后仍保持用户选择

- [x] **提供语言设置的状态存储与 API（供设置页调用）**  
  - **状态**：已完成（已提供 `getLanguagePreference/setLanguagePreference/changeLanguage/clearLanguagePreference`）  
  - **建议**：`src/store/` 或 `src/features/settings/`（如后续新增）暴露 `setLanguage/getLanguage`  
  - **验收**：设置页接入时只需调用一个清晰接口即可完成切换

## 5. 环境变量与联调基座

- [x] **补齐 `.env.example` 并规范 `.env.dev/.env.prod`**  
  - **状态**：已完成（已创建 `.env.example`；注意该文件在当前环境会被 globalignore 过滤，终端可见但编辑工具不可见）  
  - **字段**：`EXPO_PUBLIC_API_BASE_URL`、`EXPO_PUBLIC_ENV`  
  - **验收**：文档与实际读取方式一致；真机联调注意事项明确

- [ ] **实现 API 客户端封装（`src/services/`）**  
  - **状态**：未开始  
  - **要求**：从 `EXPO_PUBLIC_API_BASE_URL` 读取 baseURL；统一错误处理与超时策略（先给默认）  
  - **验收**：任意页面可通过统一 client 发起请求，且环境切换能影响 baseURL

## 6. 模块骨架（push/widget/cards）

- [ ] **Push 模块：权限/Token/上报接口占位**  
  - **状态**：未开始  
  - **要求**：提供最小 API（例如 `requestPermission() / getToken() / reportToken()`）  
  - **验收**：模块对外 API 清晰，后续联调只需补实现不需改结构

- [ ] **Widget 模块：数据模型/缓存/刷新策略文档化与占位**  
  - **状态**：未开始  
  - **要求**：定义“情绪文案数据结构”、缓存 key、刷新建议（强调 iOS 限制）  
  - **验收**：能明确后续 iOS 小组件实现需要的数据与刷新行为

- [ ] **Cards 模块：数据模型与卡片滑动组件占位**  
  - **状态**：未开始  
  - **验收**：后续 UI 实现可以直接在该模块内扩展，不破坏目录约定

## 7. EAS Build（iOS 打包链路）

- [ ] **创建并配置 `eas.json`（development profile）**  
  - **状态**：未开始  
  - **要求**：区分 dev/prod；注入对应环境变量；bundle id 符合约定  
  - **验收**：可触发 iOS development 构建并产出安装包/构建产物

- [ ] **验证 iOS 构建最小闭环**  
  - **状态**：未开始  
  - **验收**：构建成功；App 能启动；基础 i18n 与环境变量读取无崩溃

