Refresh API reference for current routes

This commit is contained in:
Wang Zhuoxuan 2026-05-18 11:55:54 +08:00
parent cd7e9e2a41
commit 7dcaf65585

View File

@ -1,6 +1,8 @@
# Duoqi API Reference # Duoqi API Reference
> 多奇服务端 API 接口文档。本文按当前 Fastify 路由和 TypeScript DTO 更新。 > 多奇服务端 API 接口文档。本文按当前 Fastify 路由和 TypeScript DTO 更新。
>
> 最近一次代码审计2026-05-18来源为 `src/index.ts` 注册的路由、`src/routes/**/*.ts`、`src/types/app-api.ts` 和相关 service 返回值。
## Base URL ## Base URL
@ -152,6 +154,24 @@
} }
``` ```
#### POST /auth/phone
认证:无
限流10 次/分钟
当前已注册但未实现,固定返回 HTTP 501
```json
{
"success": false,
"data": null,
"error": {
"code": "NOT_IMPLEMENTED",
"message": "Phone login not implemented yet"
}
}
```
#### GET /auth/me #### GET /auth/me
认证JWT 认证JWT
@ -204,6 +224,8 @@
"dailyAttemptsLeft": 5, "dailyAttemptsLeft": 5,
"dailyAttemptsMax": 5, "dailyAttemptsMax": 5,
"nextAttemptResetAt": "2026-05-06T00:00:00.000Z", "nextAttemptResetAt": "2026-05-06T00:00:00.000Z",
"highRewardSessionsLeft": 3,
"highRewardSessionsMax": 3,
"xp": 0, "xp": 0,
"level": 1, "level": 1,
"xpToNextLevel": 400, "xpToNextLevel": 400,
@ -315,6 +337,7 @@
"trackId": "history", "trackId": "history",
"nodeId": "chapter-uuid", "nodeId": "chapter-uuid",
"totalQuestions": 5, "totalQuestions": 5,
"highRewardEligible": true,
"questions": [ "questions": [
{ {
"challengeId": "challenge-session-uuid", "challengeId": "challenge-session-uuid",
@ -336,7 +359,7 @@
} }
``` ```
服务端会创建挑战组会话并一次返回 5 题,题目选项不包含正确答案标记。题库不足 5 题或没有可用题目时 `data``null` 服务端会创建挑战组会话并一次返回 5 题,题目选项不包含正确答案标记。`highRewardEligible=false` 表示今日高奖励挑战次数已用尽,本轮 XP 和宝箱掉落按降级规则结算。题库不足 5 题或没有可用题目时 `data``null`
#### POST /challenges/answer #### POST /challenges/answer
@ -370,6 +393,8 @@
"progress": { "progress": {
"hearts": 5, "hearts": 5,
"dailyAttemptsLeft": 5, "dailyAttemptsLeft": 5,
"highRewardSessionsLeft": 2,
"highRewardSessionsMax": 3,
"xp": 10, "xp": 10,
"streakDays": 0 "streakDays": 0
}, },
@ -393,7 +418,7 @@
认证JWT 认证JWT
响应:`ProgressSummaryDto`,字段同 `/app/bootstrap` 中的 `progress` 响应:`ProgressSummaryDto`,字段同 `/app/bootstrap` 中的 `progress`,包含 `highRewardSessionsLeft``highRewardSessionsMax`
#### PATCH /progress/preferences #### PATCH /progress/preferences
@ -783,8 +808,17 @@ Plus 用户响应(无需看广告,返回订阅权益摘要):
"maxHearts": 5, "maxHearts": 5,
"dailyAttemptsLeft": 2, "dailyAttemptsLeft": 2,
"dailyAttemptsMax": 5, "dailyAttemptsMax": 5,
"nextAttemptResetAt": "2026-05-06T00:00:00.000Z",
"highRewardSessionsLeft": 3,
"highRewardSessionsMax": 3,
"xp": 1200,
"level": 4,
"xpToNextLevel": 200,
"streakDays": 21, "streakDays": 21,
"streakProtectedUntil": null "checkInDays": 8,
"streakProtectedUntil": null,
"activeTrackId": "history",
"isSubscribed": false
}, },
"limits": { "limits": {
"remainingHeartsRecoveriesToday": 2, "remainingHeartsRecoveriesToday": 2,
@ -809,7 +843,18 @@ Plus 用户响应(无需看广告,返回订阅权益摘要):
"hearts": 2, "hearts": 2,
"maxHearts": 5, "maxHearts": 5,
"dailyAttemptsLeft": 1, "dailyAttemptsLeft": 1,
"dailyAttemptsMax": 5 "dailyAttemptsMax": 5,
"nextAttemptResetAt": "2026-05-06T00:00:00.000Z",
"highRewardSessionsLeft": 0,
"highRewardSessionsMax": 3,
"xp": 1200,
"level": 4,
"xpToNextLevel": 200,
"streakDays": 21,
"checkInDays": 8,
"streakProtectedUntil": null,
"activeTrackId": "history",
"isSubscribed": false
} }
}, },
"error": null "error": null
@ -882,6 +927,32 @@ Plus 用户响应(无需看广告,返回订阅权益摘要):
} }
``` ```
#### POST /admin/auth
认证:无
兼容旧管理端的 `ADMIN_TOKEN` 验证接口。新管理端应使用 `/admin/login` 获取 Admin JWT。
请求:
```json
{
"token": "admin-token"
}
```
响应:
```json
{
"success": true,
"data": {
"authenticated": true
},
"error": null
}
```
### 管理员管理 ### 管理员管理
#### GET /admin/admins #### GET /admin/admins
@ -1202,6 +1273,120 @@ categoryId,contentType,difficulty,stemText,correctAnswer,distractor1,distractor2
查询参数:`page`, `limit` 查询参数:`page`, `limit`
响应:反馈数组 + `pagination` 响应:反馈数组 + `pagination`
### 游戏化审计
#### GET /admin/gamification/users/:id/wallet
认证Admin JWT
响应:指定用户金币钱包,未创建钱包时 `data``null`
#### GET /admin/gamification/users/:id/inventory
认证Admin JWT
响应:指定用户道具库存数组。
#### GET /admin/gamification/users/:id/rewards
认证Admin JWT
查询参数:`page`, `limit`
响应:指定用户奖励流水数组 + `pagination`
#### GET /admin/gamification/users/:id/ad-recovery
认证Admin JWT
查询参数:`page`, `limit`
响应:指定用户广告恢复会话数组 + `pagination`
#### GET /admin/gamification/users/:id/transactions
认证Admin JWT
查询参数:`page`, `limit`
响应:指定用户资源变更流水数组 + `pagination`
### 定时任务
#### GET /admin/jobs
认证Admin JWT
响应:
```json
{
"success": true,
"data": [
{
"name": "weekly-settlement",
"description": "周榜结算:按组快照上周排名,给每组前 3 名发金币奖励",
"schedule": "每周一 UTC 00:30"
},
{
"name": "expire-subscriptions",
"description": "订阅过期检查:检查并过期到期的订阅",
"schedule": "每日 UTC 01:00"
}
],
"error": null
}
```
#### POST /admin/jobs/trigger
认证Admin JWT
请求:
```json
{
"job": "weekly-settlement",
"dryRun": true
}
```
`job` 取值:`weekly-settlement`, `expire-subscriptions`。`dryRun` 可选,默认 `false`
响应:
```json
{
"success": true,
"data": {
"job": "weekly-settlement",
"dryRun": true,
"executedAt": "2026-05-18T00:30:00.000Z",
"result": {}
},
"error": null
}
```
## 已注册兼容接口
以下接口仍在 `src/index.ts` 中注册,但不是新客户端的推荐主合同。新客户端优先使用上文的 Flutter 客户端聚合 API、订阅 API 和广告恢复两步流程。
| 路径 | 状态 | 推荐替代 |
|------|------|----------|
| `GET /quiz/categories` | 兼容旧出题接口 | `GET /tracks` |
| `GET /quiz/categories/:id/chapters` | 兼容旧出题接口 | `GET /tracks/:trackId` |
| `GET /quiz/chapters/:id/questions` | 兼容旧出题接口 | `GET /challenges/next` |
| `POST /quiz/answer` | 兼容旧出题接口 | `POST /challenges/answer` |
| `POST /quiz/rate` | 兼容旧反馈接口 | 仍可用于题目评分 |
| `GET /progress/dashboard` | 兼容旧进度接口 | `GET /progress/summary` |
| `GET /progress/streak` | 兼容旧进度接口 | `GET /progress/summary` |
| `GET /progress/hearts` | 兼容旧进度接口 | `GET /progress/summary` |
| `POST /progress/hearts/restore` | 已废弃恢复接口 | `POST /rewards/ad-recovery/session` + `POST /rewards/ad-recovery/complete` |
| `GET /progress/chapters` | 兼容旧进度接口 | `GET /tracks/:trackId` |
| `POST /feedback` | 兼容旧反馈接口 | 仍可用于用户反馈 |
| `GET /leaderboard` | 兼容旧排行榜接口 | `GET /leaderboards` |
| `GET /leaderboard/me` | 兼容旧排行榜接口 | `GET /leaderboards/me` |
| `GET /achievements` | 兼容旧成就接口 | 当前无聚合替代 |
| `POST /achievements/check` | 兼容旧成就接口 | 当前无聚合替代 |
| `POST /payment/verify-huawei` | 兼容旧支付接口 | `POST /subscription/verify` |
| `GET /payment/subscription` | 兼容旧订阅接口 | `GET /subscription` |
| `POST /rewards/hearts/restore` | 已废弃恢复接口 | `POST /rewards/ad-recovery/session` + `POST /rewards/ad-recovery/complete` |
| `POST /rewards/attempts/restore` | 已废弃恢复接口 | `POST /rewards/ad-recovery/session` + `POST /rewards/ad-recovery/complete` |
| `POST /rewards/streak/protect` | 已废弃恢复接口 | `POST /rewards/ad-recovery/session` + `POST /rewards/ad-recovery/complete` |
## 错误代码 ## 错误代码
| 代码 | 说明 | | 代码 | 说明 |
@ -1215,4 +1400,7 @@ categoryId,contentType,difficulty,stemText,correctAnswer,distractor1,distractor2
| `INVALID_STATUS_TRANSITION` | 题目状态流转不合法 | | `INVALID_STATUS_TRANSITION` | 题目状态流转不合法 |
| `INVALID_RECEIPT` | 支付收据验证失败 | | `INVALID_RECEIPT` | 支付收据验证失败 |
| `UNSUPPORTED_PLATFORM` | 订阅平台暂不支持 | | `UNSUPPORTED_PLATFORM` | 订阅平台暂不支持 |
| `NOT_IMPLEMENTED` | 路由已注册但功能未实现 |
| `INTERNAL_ERROR` | 服务器内部错误 | | `INTERNAL_ERROR` | 服务器内部错误 |
客户端应把 `error.code` 当作稳定的机器分支键,`error.message` 只用于调试或兜底展示。广告恢复等业务失败会以 `success=true` 返回,并把状态放在 `data.status` / `data.reason` 中;这类流程不要只依赖 `error.code` 判断。