Files
carrotskin/API文档.md
Wuying Created Local Users 5f90f48a1c feat: 完成navbar隐藏优化和侧边栏冻结功能
- 优化navbar滚动隐藏逻辑,更敏感响应
- 添加返回顶部按钮,固定在右下角
- 实现profile页面侧边栏真正冻结效果
- 修复首页滑动指示器位置
- 优化整体布局确保首屏内容完整显示
2025-12-04 20:05:13 +08:00

944 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CarrotSkin 后端 API 文档
## 概述
本文档总结了 CarrotSkin 后端 API主要关注前端需要的接口不包括 Yggdrasil 相关接口(除了更换 Yggdrasil 密码)。
## 基础信息
- **基础URL**: `/api/v1`
- **认证方式**: JWT Bearer Token
- **数据格式**: JSON
- **字符编码**: UTF-8
## 通用响应格式
所有API响应都遵循以下格式
```json
{
"code": 200,
"message": "操作成功",
"data": {
// 具体数据内容
}
}
```
分页响应格式:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [],
"total": 100,
"page": 1,
"page_size": 20,
"total_pages": 5
}
}
```
## 认证相关 API
### 1. 用户注册
- **URL**: `POST /api/v1/auth/register`
- **认证**: 无需认证
- **请求参数**:
```json
{
"username": "newuser", // 用户名3-50字符
"email": "user@example.com", // 邮箱地址
"password": "password123", // 密码6-128字符
"verification_code": "123456", // 邮箱验证码6位数字
"avatar": "https://example.com/avatar.png" // 可选头像URL
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "注册成功",
"data": {
"token": "jwt_token_here",
"user_info": {
"id": 1,
"username": "newuser",
"email": "user@example.com",
"avatar": "https://example.com/avatar.png",
"points": 0,
"role": "user",
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
}
```
### 2. 用户登录
- **URL**: `POST /api/v1/auth/login`
- **认证**: 无需认证
- **请求参数**:
```json
{
"username": "testuser", // 用户名或邮箱
"password": "password123" // 密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "登录成功",
"data": {
"token": "jwt_token_here",
"user_info": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
}
```
### 3. 发送验证码
- **URL**: `POST /api/v1/auth/send-code`
- **认证**: 无需认证
- **请求参数**:
```json
{
"email": "user@example.com", // 邮箱地址
"type": "register" // 类型: register/reset_password/change_email
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "验证码已发送,请查收邮件",
"data": {
"message": "验证码已发送,请查收邮件"
}
}
```
### 4. 重置密码
- **URL**: `POST /api/v1/auth/reset-password`
- **认证**: 无需认证
- **请求参数**:
```json
{
"email": "user@example.com", // 邮箱地址
"verification_code": "123456", // 邮箱验证码
"new_password": "newpassword123" // 新密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "密码重置成功",
"data": {
"message": "密码重置成功"
}
}
```
## 用户相关 API
### 1. 获取用户信息
- **URL**: `GET /api/v1/user/profile`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 2. 更新用户信息
- **URL**: `PUT /api/v1/user/profile`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"avatar": "https://example.com/new-avatar.png", // 可选新头像URL
"old_password": "oldpassword123", // 可选,修改密码时需要
"new_password": "newpassword123" // 可选,新密码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/new-avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 3. 生成头像上传URL
- **URL**: `POST /api/v1/user/avatar/upload-url`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"file_name": "avatar.png" // 文件名
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"post_url": "https://rustfs.example.com/avatars",
"form_data": {
"key": "user_1/xxx.png",
"policy": "base64_policy",
"x-amz-signature": "signature"
},
"avatar_url": "https://rustfs.example.com/avatars/user_1/xxx.png",
"expires_in": 900
}
}
```
### 4. 更新头像URL
- **URL**: `PUT /api/v1/user/avatar`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数: `avatar_url` - 头像URL
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "test@example.com",
"avatar": "https://example.com/new-avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 5. 更换邮箱
- **URL**: `POST /api/v1/user/change-email`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"new_email": "newemail@example.com", // 新邮箱地址
"verification_code": "123456" // 邮箱验证码
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "testuser",
"email": "newemail@example.com",
"avatar": "https://example.com/avatar.png",
"points": 100,
"role": "user",
"status": 1,
"last_login_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 6. 重置Yggdrasil密码
- **URL**: `POST /api/v1/user/yggdrasil-password/reset`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"password": "new_yggdrasil_password"
}
}
```
## 材质相关 API
### 1. 搜索材质
- **URL**: `GET /api/v1/texture`
- **认证**: 无需认证
- **请求参数**:
- Query参数:
- `keyword`: 搜索关键词
- `type`: 材质类型 (SKIN/CAPE)
- `public_only`: 是否只搜索公开材质 (true/false)
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 100,
"page": 1,
"page_size": 20,
"total_pages": 5
}
}
```
### 2. 获取材质详情
- **URL**: `GET /api/v1/texture/{id}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 3. 直接上传材质文件(推荐)
- **URL**: `POST /api/v1/texture/upload`
- **认证**: 需要JWT认证
- **Content-Type**: `multipart/form-data`
- **请求参数**:
- `file`: 材质文件PNG格式1KB-10MB
- `name`: 材质名称必填1-100字符
- `description`: 材质描述可选最多500字符
- `type`: 材质类型可选默认SKIN可选值SKIN/CAPE
- `is_public`: 是否公开可选默认falsetrue/false
- `is_slim`: 是否为细臂模型可选默认falsetrue/false
- **说明**:
- 后端会自动计算文件的SHA256哈希值
- 如果已存在相同哈希的材质会复用已存在的文件URL不重复上传
- 允许多次上传相同哈希的材质(包括同一用户),每次都会创建新的数据库记录
- 文件存储路径格式:`{type}/{hash[:2]}/{hash[2:4]}/{hash}.png`
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/skin/e3/b0/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 0,
"favorite_count": 0,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 4. 生成材质上传URL兼容接口
- **URL**: `POST /api/v1/texture/upload-url`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"file_name": "skin.png", // 文件名
"texture_type": "SKIN" // 材质类型: SKIN/CAPE
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"post_url": "https://rustfs.example.com/textures",
"form_data": {
"key": "user_1/skin/xxx.png",
"policy": "base64_policy",
"x-amz-signature": "signature"
},
"texture_url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"expires_in": 900
}
}
```
### 5. 创建材质记录配合预签名URL使用
- **URL**: `POST /api/v1/texture`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"name": "My Cool Skin", // 材质名称1-100字符
"description": "A very cool skin", // 描述最多500字符
"type": "SKIN", // 材质类型: SKIN/CAPE
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png", // 材质URL
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", // SHA256哈希
"size": 2048, // 文件大小(字节)
"is_public": true, // 是否公开
"is_slim": false // 是否为细臂模型(Alex)
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "My Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 0,
"favorite_count": 0,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 6. 更新材质
- **URL**: `PUT /api/v1/texture/{id}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- 请求体:
```json
{
"name": "Updated Skin Name", // 可选,新名称
"description": "Updated description", // 可选,新描述
"is_public": false // 可选,是否公开
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"uploader_id": 1,
"name": "Updated Skin Name",
"description": "Updated description",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/user_1/skin/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": false,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 7. 删除材质
- **URL**: `DELETE /api/v1/texture/{id}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": null
}
```
### 8. 切换收藏状态
- **URL**: `POST /api/v1/texture/{id}/favorite`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `id` - 材质ID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"is_favorited": true
}
}
```
### 9. 获取用户上传的材质列表
- **URL**: `GET /api/v1/texture/my`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数:
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 1,
"name": "My Skin",
"description": "A cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 50,
"page": 1,
"page_size": 20,
"total_pages": 3
}
}
```
### 10. 获取用户收藏的材质列表
- **URL**: `GET /api/v1/texture/favorites`
- **认证**: 需要JWT认证
- **请求参数**:
- Query参数:
- `page`: 页码默认1
- `page_size`: 每页数量默认20
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"list": [
{
"id": 1,
"uploader_id": 2,
"name": "Cool Skin",
"description": "A very cool skin",
"type": "SKIN",
"url": "https://rustfs.example.com/textures/xxx.png",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 2048,
"is_public": true,
"download_count": 100,
"favorite_count": 50,
"is_slim": false,
"status": 1,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
],
"total": 30,
"page": 1,
"page_size": 20,
"total_pages": 2
}
}
```
## 档案相关 API
### 1. 创建档案
- **URL**: `POST /api/v1/profile`
- **认证**: 需要JWT认证
- **请求参数**:
```json
{
"name": "PlayerName" // 角色名1-16字符
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": null,
"cape_id": null,
"is_active": false,
"last_used_at": null,
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 2. 获取档案列表
- **URL**: `GET /api/v1/profile`
- **认证**: 需要JWT认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
]
}
```
### 3. 获取档案详情
- **URL**: `GET /api/v1/profile/{uuid}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "PlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 4. 更新档案
- **URL**: `PUT /api/v1/profile/{uuid}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- 请求体:
```json
{
"name": "NewPlayerName", // 可选,新角色名
"skin_id": 1, // 可选皮肤ID
"cape_id": 2 // 可选披风ID
}
```
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"user_id": 1,
"name": "NewPlayerName",
"skin_id": 1,
"cape_id": 2,
"is_active": true,
"last_used_at": "2025-10-01T12:00:00Z",
"created_at": "2025-10-01T10:00:00Z",
"updated_at": "2025-10-01T10:00:00Z"
}
}
```
### 5. 删除档案
- **URL**: `DELETE /api/v1/profile/{uuid}`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"message": "删除成功"
}
}
```
### 6. 设置活跃档案
- **URL**: `POST /api/v1/profile/{uuid}/activate`
- **认证**: 需要JWT认证
- **请求参数**:
- 路径参数: `uuid` - 档案UUID
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"message": "设置成功"
}
}
```
## 验证码相关 API
### 1. 生成验证码
- **URL**: `GET /api/v1/captcha/generate`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"data": {
"masterImage": "base64_encoded_master_image",
"tileImage": "base64_encoded_tile_image",
"captchaId": "captcha_id_here",
"y": 100
}
}
```
### 2. 验证验证码
- **URL**: `POST /api/v1/captcha/verify`
- **认证**: 无需认证
- **请求参数**:
```json
{
"captchaId": "captcha_id_here",
"dx": 150 // 滑动距离
}
```
- **响应数据**:
```json
{
"code": 200,
"msg": "验证成功"
}
```
## 系统相关 API
### 1. 获取系统配置
- **URL**: `GET /api/v1/system/config`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"code": 200,
"message": "操作成功",
"data": {
"site_name": "CarrotSkin",
"site_description": "A Minecraft Skin Station",
"registration_enabled": true,
"max_textures_per_user": 100,
"max_profiles_per_user": 5
}
}
```
## CustomSkin API
### 1. 获取玩家信息
- **URL**: `GET /api/v1/csl/{username}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `username` - 玩家用户名
- **响应数据**:
```json
{
"username": "PlayerName",
"textures": {
"default": "skin_hash_here",
"slim": "skin_hash_here",
"cape": "cape_hash_here",
"elytra": "cape_hash_here"
}
}
```
或简化格式:
```json
{
"username": "PlayerName",
"skin": "skin_hash_here"
}
```
### 2. 获取资源文件
- **URL**: `GET /api/v1/csl/textures/{hash}`
- **认证**: 无需认证
- **请求参数**:
- 路径参数: `hash` - 资源哈希值
- **响应数据**: 二进制文件内容
## 健康检查
### 1. 健康检查
- **URL**: `GET /health`
- **认证**: 无需认证
- **请求参数**: 无
- **响应数据**:
```json
{
"status": "ok"
}
```
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 操作成功 |
| 400 | 请求参数错误 |
| 401 | 未认证或认证失败 |
| 403 | 无权限操作 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
## 认证说明
需要JWT认证的API需要在请求头中添加
```
Authorization: Bearer {jwt_token}
```
JWT Token在用户登录或注册成功后返回有效期内可用于访问需要认证的API。