新增(Codex 起草,本次纳入并校对): - AGENTS.md:仓库级 AI 强约束入口 - docs/00-ai-start-here.md:AI 开发入口与导航 - docs/api.md:账号/生词本/进度 API 合约草案 - docs/routes.md:go-app 页面路由与组件归属 - docs/current-state.md:当前实现状态 补充与对齐: - 验证命令补 bash(WSL/Linux 为主,PowerShell 为备):00-ai-start-here、AGENTS - 04-architecture:新增第六节"项目结构(包布局)"+ 3.2 建表 SQL 草案 - docs/README 导航补 06-tasks;CLAUDE 目录树补 AGENTS/scripts/design_mockups - 00-ai-start-here 去除已过时的"需要补齐"段 - 06-tasks:Phase 2/3/4/5 交叉引用 api.md / routes.md / 包布局 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
210 lines
3.1 KiB
Markdown
210 lines
3.1 KiB
Markdown
# 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 保持幂等写入。
|