chore: 初始化TikTok短剧后端项目基础架构
创建了完整的NestJS项目结构,包含配置文件、核心模块、工具类、拦截器、过滤器等基础代码,实现了健康检查、用户认证、管理员RBAC、剧集管理、订单支付、媒体管理等核心功能的基础框架,配置了ESLint、TypeScript、Jest等开发工具链。
This commit is contained in:
225
docs/api-standard.md
Normal file
225
docs/api-standard.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# API Standard
|
||||
|
||||
This document defines the API contract for the TikTok short drama backend.
|
||||
All current and future endpoints must follow this standard.
|
||||
|
||||
## Base Rules
|
||||
|
||||
- API style: RESTful API.
|
||||
- Response content type: `application/json`.
|
||||
- All responses must include `requestId`.
|
||||
- `requestId` must be UUID v4.
|
||||
- The client may pass `X-Request-Id`; if it is a valid UUID v4, the server reuses it.
|
||||
- If `X-Request-Id` is missing or invalid, the server generates a new UUID v4.
|
||||
- `requestId` is the primary lookup key for request logs.
|
||||
- `cost` is the server-side request duration, formatted as a string such as `3ms`.
|
||||
- `timestamp` is the server response time in ISO 8601 format.
|
||||
- `data` must always exist. Use `{}` for empty object responses. Paginated list responses must use `data.list`.
|
||||
|
||||
## Success Response
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {},
|
||||
"message": "success",
|
||||
"timestamp": "2026-06-30T00:00:00.000Z",
|
||||
"requestId": "0f5c2e16-1e44-4d55-93a4-ef7c66d9d1f2",
|
||||
"cost": "3ms"
|
||||
}
|
||||
```
|
||||
|
||||
## List Response
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"list": [],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"pageSize": 20,
|
||||
"total": 100
|
||||
}
|
||||
},
|
||||
"message": "success",
|
||||
"timestamp": "2026-06-30T00:00:00.000Z",
|
||||
"requestId": "0f5c2e16-1e44-4d55-93a4-ef7c66d9d1f2",
|
||||
"cost": "3ms"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Response
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 403,
|
||||
"data": {},
|
||||
"message": "No permission",
|
||||
"timestamp": "2026-06-30T00:00:00.000Z",
|
||||
"requestId": "0f5c2e16-1e44-4d55-93a4-ef7c66d9d1f2",
|
||||
"cost": "3ms"
|
||||
}
|
||||
```
|
||||
|
||||
## Code Rules
|
||||
|
||||
- `0`: success.
|
||||
- `400`: invalid request parameters.
|
||||
- `401`: not authenticated.
|
||||
- `403`: no permission.
|
||||
- `404`: resource not found.
|
||||
- `409`: conflict, duplicate operation, or invalid state transition.
|
||||
- `422`: business validation failed.
|
||||
- `429`: too many requests.
|
||||
- `500`: internal server error.
|
||||
|
||||
HTTP status codes should match the response `code` for errors.
|
||||
For successful responses, use the correct HTTP status code such as `200` or `201`, while response `code` remains `0`.
|
||||
|
||||
## Request Log Rules
|
||||
|
||||
Every API request must create one request log record.
|
||||
|
||||
The request log must include:
|
||||
|
||||
- `requestId`
|
||||
- `method`
|
||||
- `path`
|
||||
- `query`
|
||||
- `body`
|
||||
- `statusCode`
|
||||
- `responseCode`
|
||||
- `message`
|
||||
- `costMs`
|
||||
- `userId`
|
||||
- `adminId`
|
||||
- `ip`
|
||||
- `userAgent`
|
||||
- `errorStack`
|
||||
- `createdAt`
|
||||
|
||||
`requestId` must have a unique index in the request log table.
|
||||
|
||||
Admin log endpoints:
|
||||
|
||||
- `GET /api/admin/v1/logs/requests`
|
||||
- `GET /api/admin/v1/logs/requests/:requestId`
|
||||
|
||||
## Playback Error Log Rules
|
||||
|
||||
The app must be able to report video playback errors.
|
||||
|
||||
Endpoint:
|
||||
|
||||
- `POST /api/app/v1/logs/playback-errors`
|
||||
|
||||
Request body:
|
||||
|
||||
```json
|
||||
{
|
||||
"requestId": "0f5c2e16-1e44-4d55-93a4-ef7c66d9d1f2",
|
||||
"dramaId": 1,
|
||||
"episodeId": 10,
|
||||
"playUrl": "https://cdn.example.com/video.mp4",
|
||||
"playerErrorCode": "MEDIA_DECODE_ERROR",
|
||||
"message": "Video decode failed",
|
||||
"progressSeconds": 128,
|
||||
"networkType": "wifi",
|
||||
"device": {
|
||||
"platform": "ios",
|
||||
"model": "iPhone",
|
||||
"systemVersion": "17.0",
|
||||
"appVersion": "1.0.0"
|
||||
},
|
||||
"occurredAt": "2026-06-30T00:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
The playback error log must include:
|
||||
|
||||
- `id`
|
||||
- `requestId`
|
||||
- `userId`
|
||||
- `dramaId`
|
||||
- `episodeId`
|
||||
- `playUrl`
|
||||
- `playerErrorCode`
|
||||
- `message`
|
||||
- `progressSeconds`
|
||||
- `networkType`
|
||||
- `device`
|
||||
- `occurredAt`
|
||||
- `createdAt`
|
||||
|
||||
`PlaybackErrorLog.requestId` must have a normal index so playback errors can be linked with request logs.
|
||||
|
||||
Admin playback error endpoints:
|
||||
|
||||
- `GET /api/admin/v1/logs/playback-errors`
|
||||
- `GET /api/admin/v1/logs/playback-errors/:id`
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
The NestJS implementation must include:
|
||||
|
||||
- `RequestIdMiddleware` to generate or validate `requestId`.
|
||||
- A global response interceptor to wrap successful responses.
|
||||
- A global exception filter to wrap error responses.
|
||||
- A request logging interceptor or middleware to write request logs.
|
||||
- DTO validation with `class-validator`.
|
||||
- Swagger/OpenAPI definitions for all endpoints.
|
||||
- Tests that verify every endpoint includes `code`, `data`, `message`, `timestamp`, `requestId`, and `cost`.
|
||||
|
||||
## Admin Permission Rules
|
||||
|
||||
Admin APIs under `/api/admin/v1/*` must require an admin bearer token, except `/api/admin/v1/auth/login`.
|
||||
|
||||
The backend uses RBAC:
|
||||
|
||||
- `Permission`: atomic capability, such as `drama:create`.
|
||||
- `Role`: a group of permissions.
|
||||
- `AdminUser`: an admin account with one or more roles.
|
||||
- Super admin accounts bypass permission checks.
|
||||
|
||||
Default local super admin:
|
||||
|
||||
```text
|
||||
username: admin
|
||||
password: admin123
|
||||
```
|
||||
|
||||
Core admin endpoints:
|
||||
|
||||
- `POST /api/admin/v1/auth/login`
|
||||
- `GET /api/admin/v1/auth/profile`
|
||||
- `GET /api/admin/v1/permissions`
|
||||
- `POST /api/admin/v1/permissions`
|
||||
- `GET /api/admin/v1/roles`
|
||||
- `POST /api/admin/v1/roles`
|
||||
- `GET /api/admin/v1/admin-users`
|
||||
- `POST /api/admin/v1/admin-users`
|
||||
- `PATCH /api/admin/v1/admin-users/:id/status`
|
||||
- `GET /api/admin/v1/users`
|
||||
- `GET /api/admin/v1/users/:id`
|
||||
- `PATCH /api/admin/v1/users/:id/status`
|
||||
|
||||
## Core Domain Modules
|
||||
|
||||
The backend is organized around these modules:
|
||||
|
||||
- `auth`: TikTok code exchange placeholder, local `user_id` binding, app access token issuing.
|
||||
- `drama`: album list, episode list, free or paid state, review and publish state.
|
||||
- `media`: cover records, video upload jobs, BytePlus `vid`, TikTok album or episode sync placeholders.
|
||||
- `payment`: SKU or unlock price, trade order, TikTok order id, webhook status, unlock records.
|
||||
- `player`: album id, episode id, BytePlus vid, play auth token, and playback permission checks.
|
||||
- `admin`: drama upload, episode edits, review submit, publish or offline, order and playback data.
|
||||
|
||||
Core table targets:
|
||||
|
||||
- `users`: `id`, `tiktok_open_id`, `nickname`, `avatar`, `created_at`.
|
||||
- `drama_albums`: `id`, `tiktok_album_id`, `title`, `description`, `cover_id`, `cover_url`, `status`, `online_version`.
|
||||
- `drama_episodes`: `id`, `album_id`, `tiktok_episode_id`, `seq`, `title`, `byteplus_vid`, `cover_id`, `free_type`, `price`, `review_status`, `publish_status`.
|
||||
- `orders`: `id`, `user_id`, `album_id`, `episode_id`, `tiktok_order_id`, `trade_order_id`, `amount`, `status`.
|
||||
- `unlock_records`: `id`, `user_id`, `episode_id`, `source`, `created_at`.
|
||||
- `media_upload_jobs`: `id`, `job_id`, `byteplus_vid`, `status`, `raw_response`.
|
||||
Reference in New Issue
Block a user