本文档定义 WordSprint 第一版的核心接口。接口风格以 REST 为主,统一返回结构,统一登录鉴权。
/api
{
"code": 200,
"message": "success",
"data": {}
}{
"code": 200,
"message": "success",
"data": {
"list": [],
"total": 0,
"pageNum": 1,
"pageSize": 10
}
}登录后,在请求头中携带:
Authorization: Bearer {token}
| code | 含义 |
|---|---|
| 200 | 成功 |
| 400 | 参数错误 |
| 401 | 未登录或 token 无效 |
| 403 | 无权限 |
| 404 | 数据不存在 |
| 409 | 业务冲突,如重复创建 |
| 500 | 系统异常 |
- 方法:
POST - 路径:
/api/auth/register - 鉴权:否
请求体:
{
"username": "demo_user",
"password": "123456",
"nickname": "Demo"
}返回体(MVP 当前实现):
{
"code": 200,
"message": "success",
"data": {
"userId": 1,
"username": "demo_user"
}
}- 方法:
POST - 路径:
/api/auth/login - 鉴权:否
请求体:
{
"username": "demo_user",
"password": "123456"
}返回体:
{
"code": 200,
"message": "success",
"data": {
"token": "jwt-token",
"tokenType": "Bearer",
"expireIn": 86400,
"userInfo": {
"id": 1,
"username": "demo_user",
"nickname": "Demo",
"role": "USER"
}
}
}- 方法:
GET - 路径:
/api/user/me - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"username": "demo_user",
"nickname": "Demo",
"avatar": null,
"role": "USER"
}
}- 方法:
PUT - 路径:
/api/user/profile - 鉴权:是
请求体:
{
"nickname": "Demo New",
"avatar": "https://example.com/avatar.png"
}说明:
nickname必填,去除首尾空白后长度需在2-20个字符之间avatar可为空;若传入非空字符串,长度不能超过255- 仅允许更新当前登录用户自己的资料
返回体:
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"username": "demo_user",
"nickname": "Demo New",
"avatar": "https://example.com/avatar.png",
"role": "USER"
}
}- 方法:
POST - 路径:
/api/auth/logout - 鉴权:是
说明:
- JWT 无状态方案可只由前端删除 token
- 若实现黑名单机制,可把 token 写入 Redis 黑名单
- 方法:
GET - 路径:
/api/study-plan - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"dailyTargetCount": 20,
"reviewTargetCount": 10,
"reminderEnabled": false,
"reminderTime": null
}
}说明:
- 若当前用户还没有学习计划记录,返回默认值:
dailyTargetCount=20、reviewTargetCount=10、reminderEnabled=false、reminderTime=null
- 方法:
PUT - 路径:
/api/study-plan - 鉴权:是
请求体:
{
"dailyTargetCount": 20,
"reviewTargetCount": 10,
"reminderEnabled": false,
"reminderTime": null
}说明:
dailyTargetCount、reviewTargetCount为正整数,当前实现限制为1-500reminderEnabled=false时,reminderTime可为空,服务端会清空已保存的提醒时间reminderEnabled=true时,reminderTime必填,格式为HH:mm:ss- 若当前用户还没有学习计划记录,更新时会自动创建
返回体:
{
"code": 200,
"message": "success",
"data": {
"dailyTargetCount": 20,
"reviewTargetCount": 10,
"reminderEnabled": false,
"reminderTime": null
}
}- 方法:
POST - 路径:
/api/word-cards - 鉴权:是
请求体:
{
"word": "abandon",
"phonetic": "/əˈbændən/",
"meaning": "放弃",
"exampleSentence": "He had to abandon the plan.",
"tags": ["cet4", "verb"],
"isPublic": false
}- 方法:
PUT - 路径:
/api/word-cards/{id} - 鉴权:是
- 方法:
DELETE - 路径:
/api/word-cards/{id} - 鉴权:是
说明:
- 建议逻辑删除,不做物理删除
- 方法:
GET - 路径:
/api/word-cards/{id} - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"word": "abandon",
"phonetic": "/əˈbændən/",
"meaning": "放弃",
"exampleSentence": "He had to abandon the plan.",
"tags": ["cet4", "verb"],
"familiarityLevel": 2,
"memoryStatus": "LEARNING",
"wrongCount": 1,
"correctCount": 3,
"lastStudiedAt": "2026-03-29 10:30:00"
}
}- 方法:
GET - 路径:
/api/word-cards - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| pageNum | int | 页码 |
| pageSize | int | 每页数量 |
| keyword | string | 关键字,匹配单词/词义 |
| tag | string | 标签筛选 |
| memoryStatus | string | 记忆状态 |
| minFamiliarity | int | 最小熟练度 |
| maxFamiliarity | int | 最大熟练度 |
| wrongOnly | boolean | 是否只看错题 |
- 方法:
POST - 路径:
/api/word-cards/import/csv - 鉴权:是
- 请求类型:
multipart/form-data
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | file | 是 | CSV 文件 |
CSV 列顺序(前两列必填):
word,meaning,phonetic,exampleSentence,tags,isPublic
说明:
- 支持首行表头(
word,meaning,...) tags建议用|分隔,如cet4|verbisPublic支持true/false/1/0- 文件大小上限
20MB - 当前实现会跳过无效行并继续导入其余行
返回体:
{
"code": 200,
"message": "success",
"data": {
"totalRows": 6,
"successCount": 4,
"failedCount": 2,
"errors": [
{
"lineNumber": 4,
"reason": "word 和 meaning 不能为空"
}
]
}
}- 方法:
GET - 路径:
/api/public-words - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| pageNum | int | 页码,默认 1 |
| pageSize | int | 每页数量,默认 10 |
| keyword | string | 关键字,匹配单词/词义 |
| levelTag | string | 难度标签,如 CET4 |
返回体:
{
"code": 200,
"message": "success",
"data": {
"list": [
{
"id": 1,
"word": "abandon",
"phonetic": "/əˈbændən/",
"meaning": "放弃",
"exampleSentence": "He had to abandon the plan.",
"levelTag": "CET4",
"sourceName": "official"
}
],
"total": 126,
"pageNum": 1,
"pageSize": 10
}
}- 方法:
POST - 路径:
/api/public-words/{id}/import - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"wordCardId": 88,
"imported": true,
"word": "abandon"
}
}说明:
- 从公共词库复制一份到当前用户的
word_card - 若用户已导入同单词同词义,返回
imported=false,避免重复导入
- 方法:
GET - 路径:
/api/study/random - 鉴权:是
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| mode | string | 是 | WORD_TO_MEANING / MEANING_TO_WORD / CHOICE / WRONG_REVIEW |
| size | int | 否 | 一次拉取题数,默认 10 |
返回体:
{
"code": 200,
"message": "success",
"data": {
"sessionId": "study-session-001",
"mode": "WORD_TO_MEANING",
"questions": [
{
"questionId": "q1",
"wordCardId": 1,
"word": "abandon",
"meaning": null,
"options": []
}
]
}
}说明:
- 若采用 Redis 随机池,可先缓存本轮训练题 ID 集合
MEANING_TO_WORD模式下可不返回word
- 方法:
POST - 路径:
/api/study/submit - 鉴权:是
请求体:
{
"wordCardId": 1,
"studyMode": "MEANING_TO_WORD",
"answerContent": "abandon",
"durationSeconds": 8
}返回体:
{
"code": 200,
"message": "success",
"data": {
"isCorrect": true,
"correctAnswer": "abandon",
"familiarityLevel": 3,
"memoryStatus": "LEARNING"
}
}当前实现通常会联动返回以下反馈字段:
pointsEarnedtodayStudyCounttodayCorrectCountcurrentStreakDays
当前提交答题后已完成以下联动:
- 判题
- 写入
study_record - 更新
word_card - 更新
wrong_word - 更新
daily_checkin - 更新
user_points - 刷新 Redis 排行榜和签到状态
- Redis 防重复提交保护
- 方法:
GET - 路径:
/api/study/today-summary - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"date": "2026-03-29",
"studyCount": 20,
"correctCount": 16,
"accuracyRate": 80.0,
"durationSeconds": 680,
"pointsEarned": 16,
"reviewCount": 9,
"checkedIn": true,
"streakDays": 5,
"totalPoints": 128,
"pendingReviewCount": 6,
"totalStudied": 240,
"totalCorrect": 188
}
}说明:
- 今日维度数据来自
daily_checkin reviewCount表示当天study_mode=WRONG_REVIEW的提交次数,来自study_record- 累计积分、累计学习数、连续天数来自
user_points pendingReviewCount表示当前ACTIVE状态错题数
- 方法:
GET - 路径:
/api/study/statistics - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| rangeType | string | 支持 WEEK / MONTH / ALL;分别表示最近 7 天、最近 30 天、全部历史 |
返回体:
{
"code": 200,
"message": "success",
"data": {
"rangeType": "MONTH",
"startDate": "2026-02-28",
"endDate": "2026-03-29",
"rangeStudyCount": 126,
"rangeCorrectCount": 101,
"rangeAccuracyRate": 80.16,
"rangeDurationSeconds": 3860,
"rangePointsEarned": 101,
"totalStudied": 240,
"totalCorrect": 188,
"totalAccuracyRate": 78.33,
"totalPoints": 128,
"streakDays": 5,
"maxStreakDays": 9,
"pendingReviewCount": 6,
"totalWrongCount": 11,
"trend": [
{
"date": "2026-02-28",
"studyCount": 6,
"correctCount": 5,
"accuracyRate": 83.33,
"durationSeconds": 180,
"pointsEarned": 5
}
]
}
}说明:
- 区间趋势数据来自
daily_checkin WEEK返回最近 7 天趋势,MONTH返回最近 30 天趋势ALL返回从首次学习日到今天的按日趋势;若没有历史数据,则返回当天一条全0数据trend会补齐区间内缺失日期,未学习日期返回0- 累计数据来自
user_points
- 方法:
GET - 路径:
/api/study/familiarity-distribution - 鉴权:是
返回体:
{
"code": 200,
"message": "success",
"data": {
"totalCards": 24,
"items": [
{
"familiarityLevel": 0,
"count": 5
},
{
"familiarityLevel": 1,
"count": 7
}
]
}
}说明:
- 仅统计当前登录用户自己的单词卡
- 默认返回
0-5全部熟练度档位,没有数据的档位也会返回count: 0
- 方法:
GET - 路径:
/api/wrong-words - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| pageNum | int | 页码 |
| pageSize | int | 每页数量 |
| status | string | ACTIVE / RESOLVED |
- 方法:
POST - 路径:
/api/wrong-words/{wordCardId}/remove - 鉴权:是
说明:
- 本质上是把状态改为
RESOLVED
- 方法:
POST - 路径:
/api/wrong-words/{wordCardId}/restore - 鉴权:是
说明:
- 用于把已移除或已解决的错题重新标记为
ACTIVE
- 方法:
GET - 路径:
/api/wrong-words/practice - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| size | int | 默认 10 |
- 方法:
GET - 路径:
/api/checkin/calendar - 鉴权:是
返回体(MVP 当前实现,最近 30 天):
{
"code": 200,
"message": "success",
"data": {
"startDate": "2026-02-28",
"endDate": "2026-03-29",
"currentStreakDays": 5,
"days": [
{
"date": "2026-03-29",
"checkedIn": true,
"studyCount": 20,
"correctCount": 16,
"pointsEarned": 18
}
]
}
}说明:
- 当前实现固定返回最近
30天数据,用于统计页最小可用日历区 days会补齐区间内缺失日期,未学习日期返回checkedIn: false和各统计字段0currentStreakDays来自user_points
- 方法:
GET - 路径:
/api/rank/points - 鉴权:是
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| limit | int | 默认 20 |
返回体建议:
{
"code": 200,
"message": "success",
"data": {
"myRank": 3,
"myScore": 128,
"list": [
{
"rank": 1,
"userId": 2,
"nickname": "Alice",
"score": 150
}
]
}
}- 方法:
GET - 路径:
/api/rank/streak - 鉴权:是
- 方法:
POST - 路径:
/api/admin/public-words - 鉴权:管理员
- 方法:
PUT - 路径:
/api/admin/public-words/{id} - 鉴权:管理员
- 方法:
POST - 路径:
/api/admin/public-words/{id}/disable - 鉴权:管理员
- 方法:
POST - 路径:
/api/admin/public-words/import/csv - 鉴权:管理员
- 请求类型:
multipart/form-data
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | file | 是 | CSV 文件 |
CSV 列顺序(前两列必填):
word,meaning,phonetic,exampleSentence,levelTag,sourceName,status
说明:
- 支持首行表头(
word,meaning,...) status支持1/0/true/false,默认1- 文件大小上限
20MB - 以
word + levelTag作为匹配键:存在则更新,不存在则新增
返回体:
{
"code": 200,
"message": "success",
"data": {
"totalRows": 6,
"insertedCount": 4,
"updatedCount": 1,
"failedCount": 1,
"errors": [
{
"lineNumber": 5,
"reason": "word 和 meaning 不能为空"
}
]
}
}username:4-20 位,仅字母数字下划线password:6-20 位nickname:2-20 位
word:不能为空,最长 100meaning:不能为空,最长 255exampleSentence:最长 500
wordCardId:必须存在且属于当前用户studyMode:必须在允许范围内durationSeconds:不小于 0
建议按下面顺序实现:
/api/auth/register/api/auth/login/api/user/me/api/word-cards全套 CRUD/api/study/random/api/study/submit/api/wrong-words/api/checkin/calendar/api/rank/points/api/study/statistics