# 自然拼读训练工具 - 实现计划

> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.

**Goal:** 构建自然拼读训练工具 MVP，包含拼读学习、测验、每日任务和家长仪表盘。

**Architecture:** 前后端分离，React 前端 + Python FastAPI 后端 + SQLite 数据库。三层数据架构（内容层/课程层/进度层）松耦合设计。本机跑后端服务，NAS 做静态 CDN。

**Tech Stack:** React 18, Vite 5, TypeScript, Ant Design Mobile, Framer Motion, Zustand, Python 3.11+, FastAPI, SQLAlchemy, SQLite, edge-tts, PyMuPDF

---

## Phase 1: 项目脚手架 + 基础设施

### Task 1: 初始化前端项目

**Objective:** 创建 React + Vite + TypeScript 项目骨架

**Files:**
- Create: `frontend/package.json`
- Create: `frontend/vite.config.ts`
- Create: `frontend/tsconfig.json`
- Create: `frontend/src/main.tsx`
- Create: `frontend/src/App.tsx`
- Create: `frontend/index.html`

**Steps:**
```bash
cd /mnt/d/codes/MyProjects/easy-study
npx create-vite frontend --template react-ts
cd frontend
npm install antd-mobile framer-motion zustand react-router-dom
npm install -D @types/node
```

**Verify:** `cd frontend && npm run dev` 启动成功，浏览器访问 localhost:5173 看到默认页面

**Commit:** `git add frontend/ && git commit -m "feat: init React+Vite+TS frontend scaffold"`

---

### Task 2: 初始化后端项目

**Objective:** 创建 Python FastAPI 项目骨架

**Files:**
- Create: `backend/requirements.txt`
- Create: `backend/app/__init__.py`
- Create: `backend/app/main.py`
- Create: `backend/app/config.py`
- Create: `backend/app/database.py`

**Steps:**
```bash
cd /mnt/d/codes/MyProjects/easy-study
mkdir -p backend/app
```

`backend/requirements.txt`:
```
fastapi==0.111.0
uvicorn[standard]==0.30.1
sqlalchemy==2.0.30
pydantic==2.7.1
python-multipart==0.0.9
edge-tts==6.1.12
pymupdf==1.24.5
```

`backend/app/main.py`:
```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI(title="Easy Study API", version="0.1.0")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173", "http://192.168.11.94"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/api/health")
def health_check():
    return {"status": "ok", "version": "0.1.0"}
```

`backend/app/database.py`:
```python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, DeclarativeBase

DATABASE_URL = "sqlite:///./data/app.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

class Base(DeclarativeBase):
    pass

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
```

**Verify:**
```bash
cd backend
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
# 访问 http://localhost:8000/api/health 返回 {"status":"ok"}
```

**Commit:** `git add backend/ && git commit -m "feat: init FastAPI backend scaffold"`

---

### Task 3: 前端路由和布局框架

**Objective:** 搭建前端路由结构和基础布局（孩子端/家长端分离）

**Files:**
- Create: `frontend/src/routes/index.tsx`
- Create: `frontend/src/layouts/ChildLayout.tsx`
- Create: `frontend/src/layouts/ParentLayout.tsx`
- Create: `frontend/src/pages/child/Home.tsx`
- Create: `frontend/src/pages/parent/Dashboard.tsx`

**路由结构:**
```
/            → 孩子端首页（每日任务）
/learn/:id   → 拼读学习页
/quiz/:id    → 测验页
/explore     → 自由探索
/parent      → 家长管理端入口
/parent/dashboard  → 进度仪表盘
/parent/tasks      → 任务管理
/parent/courses    → 课程管理
```

**Verify:** 各路由可正常切换，布局正确渲染

**Commit:** `git commit -m "feat: add routing and layout structure"`

---

## Phase 2: 数据模型 + API

### Task 4: 内容层数据模型（Phoneme + Word + PhonicsRule）

**Objective:** 定义内容层 SQLAlchemy 模型

**Files:**
- Create: `backend/app/models/__init__.py`
- Create: `backend/app/models/content.py`

**Models:**
- Phoneme: id, symbol, common_spellings(JSON), audio, video, description
- Word: id, word, ipa, meaning, pos, phonics_breakdown(JSON), audio_en, audio_cn, image, tags(JSON)
- PhonicsRule: id, pattern, phoneme_id(FK), position, rule_description, examples(JSON), confusables(JSON), difficulty
- Media: id, type, url, title, duration, source, tags(JSON)
- Sentence: id, text, translation, audio, words(JSON), source(JSON), tags(JSON)
- ContentReference: id, content_type, content_id, course_id, unit_id, lesson_id, context_type, context_snippet, page, timestamp, highlight_range(JSON)

**Verify:** `python -c "from app.models.content import *; print('OK')"`

**Commit:** `git commit -m "feat: add content layer models"`

---

### Task 5: 课程层数据模型（Course + Unit + Lesson）

**Objective:** 定义课程层 SQLAlchemy 模型

**Files:**
- Create: `backend/app/models/course.py`

**Models:**
- Course: id, name, type, description, cover_image, difficulty, created_by, is_public, created_at
- Unit: id, course_id(FK), order, title, theme
- Lesson: id, unit_id(FK), order, title, type, estimated_minutes
- LessonItem: id, lesson_id(FK), order, content_type, content_id, activity, config(JSON)

**Verify:** 模型可正常导入，无循环依赖

**Commit:** `git commit -m "feat: add course layer models"`

---

### Task 6: 进度层数据模型（Progress + DailyTask）

**Objective:** 定义进度层 SQLAlchemy 模型

**Files:**
- Create: `backend/app/models/progress.py`
- Create: `backend/app/models/user.py`

**Models:**
- User: id, name, role("child"|"parent"), avatar, created_at
- UserCourseEnroll: id, user_id(FK), course_id(FK), current_unit_id, current_lesson_id, status, enrolled_at
- LessonRecord: id, user_id(FK), lesson_id(FK), course_id(FK), started_at, completed_at, score, items_detail(JSON)
- ContentMastery: id, user_id(FK), content_type, content_id, mastery, correct_streak, total_attempts, last_practice, next_review, notes(JSON)
- DailyTask: id, user_id(FK), date, source_course_id, review_items(JSON), new_items(JSON), free_explore, parent_override(JSON), status

**Verify:** 所有模型导入成功，`Base.metadata.create_all(engine)` 建表成功

**Commit:** `git commit -m "feat: add progress layer and user models"`

---

### Task 7: 内容层 CRUD API

**Objective:** 实现 Word/PhonicsRule/Phoneme 的增删改查接口

**Files:**
- Create: `backend/app/routers/__init__.py`
- Create: `backend/app/routers/content.py`
- Create: `backend/app/schemas/content.py`

**Endpoints:**
```
GET    /api/words?tags=CVC&limit=20
GET    /api/words/{id}
POST   /api/words (批量导入)
GET    /api/phonics-rules?difficulty=1-2
GET    /api/phonics-rules/{id}
GET    /api/phonemes
GET    /api/words/{id}/references  (跨课程引用查询)
```

**Verify:** curl 测试各接口返回正确 JSON

**Commit:** `git commit -m "feat: add content CRUD API"`

---

### Task 8: 课程层 API + 每日任务 API

**Objective:** 实现课程管理和每日任务接口

**Files:**
- Create: `backend/app/routers/course.py`
- Create: `backend/app/routers/task.py`
- Create: `backend/app/schemas/course.py`
- Create: `backend/app/services/task_scheduler.py`

**Endpoints:**
```
GET    /api/courses
GET    /api/courses/{id}/units
GET    /api/courses/{id}/units/{uid}/lessons
GET    /api/daily-task?user_id=x&date=today
POST   /api/daily-task/override (家长覆盖)
PATCH  /api/daily-task/{id}/status
```

**Verify:** 创建课程 → 获取每日任务 → 完成任务流程跑通

**Commit:** `git commit -m "feat: add course and daily task API"`

---

## Phase 3: 数据预处理工具

### Task 9: 牛津拼读教材内容提取

**Objective:** 从现有 Oxford Phonics World PDF 提取内容，生成标准化 JSON 数据

**Files:**
- Create: `backend/tools/extract_phonics_content.py`
- Create: `backend/tools/phonics_level_map.json` (Level→Unit→规则映射表)

**逻辑:**
1. 读取已有 `251228-words/phonics-data.json`（13691行，已有大量拆分数据）
2. 补充 Oxford Phonics World 1-5 的 Level/Unit 结构信息
3. 输出标准化 JSON：Phoneme[] + PhonicsRule[] + Word[]
4. 关联已有音频资源路径

**输入:** `/mnt/d/codes/MyProjects/easy-study/251228-words/phonics-data.json`
**输出:** `backend/data/seed/phonemes.json`, `rules.json`, `words.json`

**Verify:** 生成的 JSON 可被 API 导入，数据完整性检查通过

**Commit:** `git commit -m "feat: add phonics content extraction tool"`

---

### Task 10: TTS 音频批量生成工具

**Objective:** 为所有单词和音素生成 TTS 音频文件

**Files:**
- Create: `backend/tools/generate_tts.py`

**逻辑:**
1. 读取 words.json，对每个单词生成英文发音 + 中文释义音频
2. 读取 phonemes.json，对每个音素生成发音音频
3. 使用 edge-tts（en-US-AriaNeural / zh-CN-XiaoxiaoNeural）
4. 跳过已存在的文件，支持增量生成
5. 输出到 `assets/audio/en/`, `assets/audio/cn/`, `assets/audio/phonemes/`

**Verify:** 随机抽查 10 个音频文件可正常播放

**Commit:** `git commit -m "feat: add TTS batch generation tool"`

---

### Task 11: 数据库种子数据导入

**Objective:** 将预处理好的 JSON 数据导入 SQLite 数据库

**Files:**
- Create: `backend/tools/seed_database.py`

**逻辑:**
1. 读取 `data/seed/` 下的 JSON 文件
2. 创建默认用户（child + parent）
3. 导入 Phoneme/Word/PhonicsRule 到内容层
4. 创建默认课程（Oxford Phonics World Level 1-2）并编排 Unit/Lesson
5. 建立 ContentReference 索引

**Verify:**
```bash
python tools/seed_database.py
# 检查: sqlite3 data/app.db "SELECT COUNT(*) FROM words;"
# 预期: > 100 条记录
```

**Commit:** `git commit -m "feat: add database seed script"`

---

## Phase 4: 前端核心页面

### Task 12: 孩子端首页（每日任务卡）

**Objective:** 实现孩子打开 App 看到的首页，展示今日任务

**Files:**
- Create: `frontend/src/pages/child/Home.tsx`
- Create: `frontend/src/components/TaskCard.tsx`
- Create: `frontend/src/stores/taskStore.ts`
- Create: `frontend/src/api/client.ts`

**交互:**
- 展示今日任务卡片（复习 N 个 + 新学 N 个 + 测验）
- 每个环节显示完成状态（✓/进行中/待完成）
- 点击进入对应学习/测验页面
- 底部显示连续学习天数和星星数

**Verify:** 页面正确渲染，点击任务卡可跳转

**Commit:** `git commit -m "feat: add child home page with daily task"`

---

### Task 13: 拼读学习页面

**Objective:** 实现拼读规则学习的核心交互页面

**Files:**
- Create: `frontend/src/pages/child/Learn.tsx`
- Create: `frontend/src/components/PhonicsCard.tsx`
- Create: `frontend/src/components/WordBreakdown.tsx`
- Create: `frontend/src/components/AudioPlayer.tsx`

**交互流程:**
1. 大字展示字母/字母组合 + 自动播放音素发音
2. 示例单词逐个高亮拆解 + 播放对应音素
3. 多个示例轮播
4. AI 引导语音（TTS 预生成的引导语音频）
5. "下一个" 按钮进入下一规则

**关键组件:**
- PhonicsCard: 规则卡片（大字+音素+描述）
- WordBreakdown: 单词拆解动画（逐个高亮+播放）
- AudioPlayer: 音频播放控制（自动播放+重播按钮）

**Verify:** 完整学习流程可走通，音频正常播放

**Commit:** `git commit -m "feat: add phonics learning page"`

---

### Task 14: 拼读测验页面

**Objective:** 实现 3 种测验题型的交互页面

**Files:**
- Create: `frontend/src/pages/child/Quiz.tsx`
- Create: `frontend/src/components/quiz/ChoiceQuestion.tsx`
- Create: `frontend/src/components/quiz/SpellQuestion.tsx`
- Create: `frontend/src/components/quiz/CompareQuestion.tsx`
- Create: `frontend/src/components/quiz/QuizResult.tsx`

**题型实现:**

**ChoiceQuestion（听音选字母组合）:**
- 播放音素 → 4 个大按钮
- 选中后即时反馈（绿色✓ / 红色✗ + 正确答案高亮）
- Framer Motion 动画反馈

**SpellQuestion（乱序字母拼写）:**
- 展示图片 + 播放单词发音
- 打乱的字母块（字母组合保持整体）
- 点击排列顺序，支持撤销
- 正确后播放拆解发音

**CompareQuestion（易混淆项对比）:**
- 展示两个单词，播放其中一个
- 两个大按钮选择
- 答对后展示规则提示

**QuizResult:**
- 得分展示 + 星星动画
- 错题回顾列表
- "再来一次" / "回到首页" 按钮

**Verify:** 3 种题型均可正常作答，反馈动画流畅

**Commit:** `git commit -m "feat: add quiz page with 3 question types"`

---

### Task 15: 家长端进度仪表盘

**Objective:** 实现家长查看学习数据的管理页面

**Files:**
- Create: `frontend/src/pages/parent/Dashboard.tsx`
- Create: `frontend/src/pages/parent/TaskManager.tsx`
- Create: `frontend/src/components/parent/ProgressChart.tsx`
- Create: `frontend/src/components/parent/WeakPointsHeatmap.tsx`

**功能:**
- 今日/本周学习时长和完成率
- 课程进度条
- 薄弱点列表（错误率 Top 10 的规则/单词）
- 任务管理：查看/编辑明日任务

**Verify:** 仪表盘数据正确展示，任务编辑可保存

**Commit:** `git commit -m "feat: add parent dashboard and task manager"`

---

## Phase 5: 部署 + PWA

### Task 16: Docker Compose + Nginx 配置

**Objective:** 配置 NAS 部署环境

**Files:**
- Create: `oy/docker-compose.yml`
- Create: `deploy/nginx/nginx.conf`
- Create: `deploy/deploy.sh` (一键部署脚本)

**Nginx 配置:**
```nginx
server {
    listen 80;
    
    location / {
        root /www;
        try_files $uri $uri/ /index.html;
    }
    
    location /assets/ {
        root /data;
        expires 30d;
    }
    
    location /api/ {
        proxy_pass http://192.168.11.157:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    location /packages/ {
      root /data;
        autoindex on;
    }
}
```

**deploy.sh:**
```bash
#!/bin/bash
# 构建前端
cd frontend && npm run build
# 同步到 NAS
rsync -avz dist/ neotao@192.168.11.94:/www/
# 同步静态资源
rsync -avz assets/ neotao@192.168.11.94:/data/assets/
```

**Verify:** `http://192.168.11.94` 可访问前端，`/api/health` 返回正常

**Commit:** `git commit -m "feat: add Docker+Nginx deployment config"`

---

### Task 17: PWA 离线支持

**Objective:** 配置 PWA，支持课程包下载后离线使用

**Files:**
- Modify: `frontend/vite.config.ts` (添加 vite-plugin-pwa)
- Create: `frontend/src/sw.ts` (Service Worker 策略)
- Create: `frontend/public/manifest.json`

**离线策略:**
- 前端页面/JS/CSS: CacheFirst
- 音频/图片资源: CacheFirst（已下载的课程包）
- API 请求: NetworkFirst（离线时用 IndexedDB 缓存）

**Verify:** 断网后已缓存的课程内容仍可正常学习

**Commit:** `git commit -m "feat: add PWA offline support"`

---

## Phase 6: 集成测试 + 收尾

### Task 18: 端到端学习流程测试

**Objective:** 验证完整学习流程：打开App → 每日任务 → 学习 → 测验 → 完成

**Steps:**
1. 启动后端 + 导入种子数据
2. 构建前端 + 部署到 NAS
3. iPad 访问，走完一次完整学习流程
4. 家长端查看进度数据是否正确
5. 记录问题清单

**Verify:** 完整流程无阻断性错误，iPad 触控体验流畅

**Commit:** `git commit -m "test: verify end-to-end learning flow"`

---

### Task 19: 文档和 README

**Objective:** 补充项目文档

**Files:n- Modify: `README.md`
- Create: `docs/development.md` (开发指南)
- Create: `docs/deployment.md` (部署指南)

**内容:**
- 项目介绍和架构说明
- 本地开发环境搭建步骤
- 部署到 NAS 的操作步骤
- API 文档入口（FastAPI 自动生成的 /docs）

**Commit:** `git commit -m "docs: add project documentation"`

---

## 执行顺序总结

| Phase | Tasks | 预估时间 | 依赖 |
|-------|-------|----------|------|
| 1. 脚手架 | Task 1-3 | 1-2h | 无 |
| 2. 数据模型+API | Task 4-8 | 3-4h | Phase 1 |
| 3. 预处理工具 | Task 9-11 | 2-3h | Phase 2 |
| 4. 前端页面 | Task 12-15 | 4-6h | Phase 2+3 |
| 5. 部署+PWA | Task 16-17 | 1-2h | Phase 集成测试 | Task 18-19 | 1-2h | Phase 5 |

**总计预估：12-19 小时开发时间**

---

Plan complete. Ready to execute using subagent-driven-development — 可以逐 Task 派发子代理实现，每个 Task 完成后做规格合规检查 + 代码质量审查。要开始执行吗？
