feat: 支持批量上传关卡
This commit is contained in:
452
API_REFERENCE.md
Normal file
452
API_REFERENCE.md
Normal file
@@ -0,0 +1,452 @@
|
||||
# MemeStudio API Reference
|
||||
|
||||
## Base URL
|
||||
- Development: `http://localhost:3001/studio`
|
||||
- Production: `https://119.91.211.52/studio`
|
||||
|
||||
## Authentication
|
||||
All endpoints except `/api/auth/*` require a valid session cookie:
|
||||
- `better-auth.session_token` (HTTP)
|
||||
- `__Secure-better-auth.session_token` (HTTPS)
|
||||
|
||||
Error response if unauthorized: `{ error: 'Unauthorized' }` (401)
|
||||
|
||||
---
|
||||
|
||||
## Authentication Endpoints
|
||||
|
||||
### POST /api/auth/sign-in/email
|
||||
Sign in with email and password.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "admin@example.com",
|
||||
"password": "password123"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": "uuid",
|
||||
"email": "admin@example.com",
|
||||
"name": "Admin",
|
||||
"emailVerified": true
|
||||
},
|
||||
"session": {
|
||||
"id": "session_id",
|
||||
"expiresAt": "2024-04-14T10:00:00Z",
|
||||
"token": "session_token"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST /api/auth/sign-out
|
||||
Sign out and invalidate session.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Levels API
|
||||
|
||||
### GET /api/levels
|
||||
Get all levels, sorted by sortOrder.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"imageUrl": "https://bucket.myqcloud.com/mini_game/images/...",
|
||||
"answer": "答案文本",
|
||||
"hint1": "提示1",
|
||||
"hint2": "提示2",
|
||||
"hint3": "提示3",
|
||||
"sortOrder": 1,
|
||||
"createdAt": "2024-04-01T10:00:00Z",
|
||||
"updatedAt": "2024-04-01T10:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST /api/levels
|
||||
Create a new level. sortOrder is auto-calculated as max+1.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"imageUrl": "https://bucket.myqcloud.com/mini_game/images/...",
|
||||
"answer": "答案",
|
||||
"hint1": "提示1",
|
||||
"hint2": "提示2",
|
||||
"hint3": "提示3"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Level object (201 Created)
|
||||
|
||||
**Validation:**
|
||||
- `imageUrl` and `answer` are required
|
||||
- Returns 400 if missing required fields
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/levels
|
||||
Update a level.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"imageUrl": "...",
|
||||
"answer": "新答案",
|
||||
"hint1": "...",
|
||||
"hint2": "...",
|
||||
"hint3": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Updated Level object
|
||||
|
||||
**Validation:**
|
||||
- `id` is required
|
||||
- Other fields are optional (only provided fields are updated)
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/levels?id=<levelId>
|
||||
Delete a level.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Levels Reorder API
|
||||
|
||||
### PUT /api/levels/reorder
|
||||
Batch update sort order for multiple levels (atomic transaction).
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"orders": [
|
||||
{ "id": "uuid1", "sortOrder": 1 },
|
||||
{ "id": "uuid2", "sortOrder": 2 },
|
||||
{ "id": "uuid3", "sortOrder": 3 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
- `orders` must be an array of objects with `id` and `sortOrder`
|
||||
|
||||
---
|
||||
|
||||
## Admin Users API
|
||||
|
||||
### GET /api/users
|
||||
Get all admin users, sorted by createdAt DESC.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"email": "admin@example.com",
|
||||
"emailVerified": true,
|
||||
"name": "Admin Name",
|
||||
"image": null,
|
||||
"createdAt": "2024-04-01T10:00:00Z",
|
||||
"updatedAt": "2024-04-01T10:00:00Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST /api/users
|
||||
Create a new admin user.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "newadmin@example.com",
|
||||
"password": "securepassword123",
|
||||
"name": "New Admin"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** User object (201 Created)
|
||||
|
||||
**Validation:**
|
||||
- `email` and `password` are required
|
||||
- `email` must be unique (returns 400 if already exists: "该邮箱已被注册")
|
||||
- Password is automatically hashed using Better Auth's hashPassword
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/users
|
||||
Update a user.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"email": "newemail@example.com",
|
||||
"password": "newpassword123",
|
||||
"name": "Updated Name"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Updated User object
|
||||
|
||||
**Validation:**
|
||||
- `id` is required
|
||||
- Email must be unique across other users (returns 400 if taken: "该邮箱已被其他用户使用")
|
||||
- If `password` is provided, it's hashed and Account record is updated
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/users?id=<userId>
|
||||
Delete a user.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
- `id` is required
|
||||
- Cannot delete yourself (returns 400: "不能删除自己的账户")
|
||||
- Cascading delete removes all sessions and accounts
|
||||
|
||||
---
|
||||
|
||||
## WeChat Users API
|
||||
|
||||
### GET /api/wx-users?search=<text>&page=<1>&limit=<20>
|
||||
Get WeChat users with pagination and search.
|
||||
|
||||
**Query Parameters:**
|
||||
- `search` (optional): Search in nickname or openid (contains search)
|
||||
- `page` (optional, default 1): Page number
|
||||
- `limit` (optional, default 20): Items per page
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"openid": "oABCDEF123456",
|
||||
"nickname": "用户昵称",
|
||||
"avatarUrl": "https://...",
|
||||
"points": 100,
|
||||
"createdAt": "2024-04-01T10:00:00Z",
|
||||
"updatedAt": "2024-04-01T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"total": 150,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"totalPages": 8
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /api/wx-users/<userId>
|
||||
Get a specific WeChat user with their level progress.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"openid": "oABCDEF123456",
|
||||
"nickname": "用户昵称",
|
||||
"avatarUrl": "https://...",
|
||||
"points": 100,
|
||||
"sessionKey": "...",
|
||||
"createdAt": "2024-04-01T10:00:00Z",
|
||||
"updatedAt": "2024-04-01T10:00:00Z",
|
||||
"levelProgress": [
|
||||
{
|
||||
"id": "progress_uuid",
|
||||
"userId": "uuid",
|
||||
"levelId": "uuid",
|
||||
"completedAt": "2024-04-02T15:30:00Z",
|
||||
"level": {
|
||||
"id": "uuid",
|
||||
"answer": "答案"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/wx-users/level-progress
|
||||
Delete multiple level progress records (batch).
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"ids": [
|
||||
"progress_uuid1",
|
||||
"progress_uuid2",
|
||||
"progress_uuid3"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "deleted": 3 }
|
||||
```
|
||||
|
||||
**Validation:**
|
||||
- `ids` must be a non-empty array of strings
|
||||
- Returns 400 if validation fails
|
||||
|
||||
---
|
||||
|
||||
## Tencent COS API
|
||||
|
||||
### GET /api/cos/temp-key
|
||||
Get temporary credentials for uploading images to COS.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"credentials": {
|
||||
"tmpSecretId": "AKIA...",
|
||||
"tmpSecretKey": "...",
|
||||
"sessionToken": "..."
|
||||
},
|
||||
"startTime": 1712000000,
|
||||
"expiredTime": 1712001800,
|
||||
"bucket": "mybucket-1234567890",
|
||||
"region": "ap-guangzhou"
|
||||
}
|
||||
```
|
||||
|
||||
**Details:**
|
||||
- Credentials are valid for 30 minutes (1800 seconds)
|
||||
- Limited to upload to `mini_game/images/*` directory
|
||||
- Use returned `bucket` and `region` for upload configuration
|
||||
- Browser should upload directly to COS using these credentials (S3-compatible API)
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Standard Error Response
|
||||
```json
|
||||
{
|
||||
"error": "Error message"
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP Status Codes
|
||||
- `200`: Success
|
||||
- `201`: Created
|
||||
- `400`: Bad Request (validation error)
|
||||
- `401`: Unauthorized (no session)
|
||||
- `404`: Not Found (resource doesn't exist)
|
||||
- `500`: Server Error
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Session Validation Pattern
|
||||
```typescript
|
||||
const session = await auth.api.getSession({ headers: request.headers })
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
```
|
||||
|
||||
### Pagination Pattern
|
||||
- `skip = (page - 1) * limit`
|
||||
- `totalPages = Math.ceil(total / limit)`
|
||||
|
||||
### Transaction Pattern (Multi-step operations)
|
||||
```typescript
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// Multiple database operations in atomic transaction
|
||||
})
|
||||
```
|
||||
|
||||
### Error Handling Pattern
|
||||
All endpoints log errors to console and return appropriate status codes.
|
||||
|
||||
---
|
||||
|
||||
## Testing with cURL
|
||||
|
||||
### Sign In
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/studio/api/auth/sign-in/email \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"admin@example.com","password":"admin123456"}' \
|
||||
-c cookies.txt
|
||||
```
|
||||
|
||||
### Get Levels (with session cookie)
|
||||
```bash
|
||||
curl http://localhost:3001/studio/api/levels \
|
||||
-b cookies.txt
|
||||
```
|
||||
|
||||
### Create Level
|
||||
```bash
|
||||
curl -X POST http://localhost:3001/studio/api/levels \
|
||||
-H "Content-Type: application/json" \
|
||||
-b cookies.txt \
|
||||
-d '{
|
||||
"imageUrl":"https://bucket.myqcloud.com/mini_game/images/test.jpg",
|
||||
"answer":"答案",
|
||||
"hint1":"提示1",
|
||||
"hint2":"提示2",
|
||||
"hint3":"提示3"
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables Required for API
|
||||
|
||||
```
|
||||
DATABASE_URL=mysql://user:pass@host:port/dbname
|
||||
BETTER_AUTH_SECRET=<32+ chars>
|
||||
BETTER_AUTH_URL=http://localhost:3001
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3001
|
||||
NEXT_PUBLIC_BASE_PATH=/studio
|
||||
COS_SECRET_ID=<tencent secret>
|
||||
COS_SECRET_KEY=<tencent secret>
|
||||
COS_BUCKET=bucket-name
|
||||
COS_REGION=ap-guangzhou
|
||||
COS_APPID=<tencent app id>
|
||||
```
|
||||
Reference in New Issue
Block a user