# API 合约草案 > 本文定义 MVP 后端 API 的目标形状。实现前可按任务细化,但不要在代码里另起一套不兼容的接口。 ## 通用约定 - 传输:JSON over HTTPS。 - 鉴权:httpOnly Session Cookie。 - 未登录访问需要登录的接口时返回 `401`。 - 请求体和响应体均使用 UTF-8 JSON。 - 内容数据不通过数据库 API 管理;课程内容来自静态 `episodes.json`。 通用错误响应: ```json { "error": { "code": "unauthorized", "message": "需要登录" } } ``` ## 账号 ### `POST /api/auth/register` 注册账号并建立登录会话。 请求: ```json { "email": "learner@example.com", "password": "password" } ``` 成功响应: ```json { "user": { "id": 1, "email": "learner@example.com" } } ``` ### `POST /api/auth/login` 登录并设置 httpOnly Session Cookie。 请求: ```json { "email": "learner@example.com", "password": "password" } ``` 成功响应同注册。 ### `POST /api/auth/logout` 清除当前会话。 成功响应: ```json { "ok": true } ``` ### `GET /api/me` 返回当前登录用户。 成功响应: ```json { "user": { "id": 1, "email": "learner@example.com" } } ``` ## 生词本 ### `GET /api/vocab` 返回当前用户的生词列表。 成功响应: ```json { "items": [ { "id": 1, "course_id": "family-album", "word": "excuse", "episode_id": 1, "act": 1, "context_sentence": "Excuse me. My name is Richard Stewart.", "created_at": "2026-06-21T10:00:00Z" } ] } ``` ### `POST /api/vocab` 添加一个生词。 请求: ```json { "word": "excuse", "episode_id": 1, "act": 1, "context_sentence": "Excuse me. My name is Richard Stewart." } ``` 说明: - `course_id` 由服务端固定写入 `"family-album"`。 - MVP 不接词典,不要求释义字段。 成功响应返回新增项。 ### `DELETE /api/vocab/{id}` 删除当前用户自己的一个生词。 成功响应: ```json { "ok": true } ``` ## 学习进度 ### `GET /api/progress` 返回当前用户全部学习进度。 成功响应: ```json { "items": [ { "course_id": "family-album", "episode_id": 1, "act": 1, "last_position": 42.5, "completed": false, "updated_at": "2026-06-21T10:00:00Z" } ] } ``` ### `PUT /api/progress` 写入或更新某一幕的学习进度。 请求: ```json { "episode_id": 1, "act": 1, "last_position": 42.5, "completed": false } ``` 说明: - `course_id` 由服务端固定写入 `"family-album"`。 - 定位维度是 `episode_id + act`,不是 `lesson_id`。 成功响应返回更新后的进度项。 ## 静态内容 课程内容和音频由静态路由提供: - `GET /family-album/episodes.json` - `GET /family-album/audio/u0101.mp3` 服务端需要把 `/family-album/audio/...` 映射到磁盘 `family-album-usa/audio/...`。 ## 待实现时确认 - 密码强度和错误文案。 - Session 存储方式和过期时间。 - 生词重复添加时返回已有项还是幂等更新。 - 进度上报频率由前端任务决定,API 保持幂等写入。