## 🧪 API测试系统完善 - 创建完整的单元测试套件 (tests/unit_test.go) - 认证流程、CRUD操作、文件上传测试 - 中间件、错误处理、性能测试 - 创建集成测试套件 (tests/integration_test.go) - 业务流程、数据一致性、并发测试 - 创建综合API测试 (test_api_comprehensive.http) - 92个测试场景,覆盖所有API端点 - 更新Makefile添加测试命令 - test-unit, test-integration, test-api, test-cover, test-bench ## 🗄️ 生产环境数据库配置 - Docker Compose生产环境配置 (configs/docker/docker-compose.prod.yml) - PostgreSQL 16 + Redis 7 + Nginx + 监控栈 - 数据库初始化脚本 (configs/docker/init-db.sql) - 完整表结构、索引优化、触发器、视图 - 生产环境配置脚本 (scripts/production-db-setup.sh) - 自动化配置、连接池、备份策略、监控 ## 📚 API文档完善 - 完整的API文档 (docs/API_DOCUMENTATION.md) - 详细接口说明、请求响应示例 - 认证流程、错误处理、性能优化 - SDK支持、部署指南、安全考虑 - 包含cURL示例和Postman Collection支持 ## 📊 项目进度 - 总进度: 50.0% → 57.5% - 中优先级任务: 55% → 70% - 并行完成3个重要任务,显著提升项目完成度 ## 🎯 技术成果 - 测试覆盖率大幅提升,支持自动化测试 - 生产环境就绪,支持Docker部署 - 完整的API文档,便于前后端协作 - 性能优化和监控配置,确保生产稳定性
853 lines
17 KiB
Markdown
853 lines
17 KiB
Markdown
# Photography Portfolio API Documentation
|
||
|
||
## 📋 API 概览
|
||
|
||
Photography Portfolio API 是一个基于 go-zero 框架的 RESTful API 服务,提供完整的摄影作品集管理功能。
|
||
|
||
### 基本信息
|
||
|
||
- **API 版本**: v1.0.0
|
||
- **基础URL**: `https://api.photography.iriver.top/api/v1`
|
||
- **开发环境**: `http://localhost:8080/api/v1`
|
||
- **认证方式**: JWT Bearer Token
|
||
- **数据格式**: JSON
|
||
- **字符编码**: UTF-8
|
||
|
||
### 响应格式
|
||
|
||
所有 API 响应都遵循统一的格式:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
// 实际数据
|
||
}
|
||
}
|
||
```
|
||
|
||
### 状态码
|
||
|
||
| HTTP状态码 | 业务码 | 说明 |
|
||
|-----------|-------|------|
|
||
| 200 | 200 | 请求成功 |
|
||
| 400 | 400 | 请求参数错误 |
|
||
| 401 | 401 | 未授权 |
|
||
| 403 | 403 | 权限不足 |
|
||
| 404 | 404 | 资源不存在 |
|
||
| 500 | 500 | 服务器内部错误 |
|
||
|
||
### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "参数验证失败",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
## 🔐 认证接口
|
||
|
||
### 用户注册
|
||
|
||
**接口地址**: `POST /auth/register`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"username": "string", // 用户名,3-20个字符
|
||
"email": "string", // 邮箱地址
|
||
"password": "string" // 密码,6-20个字符
|
||
}
|
||
```
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "注册成功",
|
||
"data": {
|
||
"user": {
|
||
"id": 1,
|
||
"username": "johndoe",
|
||
"email": "john@example.com",
|
||
"avatar": "",
|
||
"status": 1,
|
||
"created_at": "2024-01-10T10:30:00Z"
|
||
},
|
||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例**:
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/auth/register" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"username": "johndoe",
|
||
"email": "john@example.com",
|
||
"password": "password123"
|
||
}'
|
||
```
|
||
|
||
### 用户登录
|
||
|
||
**接口地址**: `POST /auth/login`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"username": "string", // 用户名或邮箱
|
||
"password": "string" // 密码
|
||
}
|
||
```
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "登录成功",
|
||
"data": {
|
||
"user": {
|
||
"id": 1,
|
||
"username": "johndoe",
|
||
"email": "john@example.com",
|
||
"avatar": "/uploads/avatars/1.jpg",
|
||
"status": 1
|
||
},
|
||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"expires_at": "2024-01-11T10:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例**:
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/auth/login" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"username": "johndoe",
|
||
"password": "password123"
|
||
}'
|
||
```
|
||
|
||
## 👥 用户管理接口
|
||
|
||
### 获取用户列表
|
||
|
||
**接口地址**: `GET /users`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**查询参数**:
|
||
- `page`: 页码,默认 1
|
||
- `limit`: 每页数量,默认 10,最大 100
|
||
- `status`: 用户状态,可选值 0(禁用) 1(正常)
|
||
- `keyword`: 搜索关键词
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"users": [
|
||
{
|
||
"id": 1,
|
||
"username": "johndoe",
|
||
"email": "john@example.com",
|
||
"avatar": "/uploads/avatars/1.jpg",
|
||
"status": 1,
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
],
|
||
"total": 50,
|
||
"page": 1,
|
||
"limit": 10,
|
||
"pages": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例**:
|
||
```bash
|
||
curl -X GET "http://localhost:8080/api/v1/users?page=1&limit=10" \
|
||
-H "Authorization: Bearer <your-token>"
|
||
```
|
||
|
||
### 获取用户详情
|
||
|
||
**接口地址**: `GET /users/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**路径参数**:
|
||
- `id`: 用户ID
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"id": 1,
|
||
"username": "johndoe",
|
||
"email": "john@example.com",
|
||
"avatar": "/uploads/avatars/1.jpg",
|
||
"status": 1,
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 创建用户
|
||
|
||
**接口地址**: `POST /users`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"username": "string", // 用户名,必填
|
||
"email": "string", // 邮箱,必填
|
||
"password": "string", // 密码,必填
|
||
"avatar": "string", // 头像URL,可选
|
||
"status": 1 // 状态,可选,默认1
|
||
}
|
||
```
|
||
|
||
### 更新用户
|
||
|
||
**接口地址**: `PUT /users/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"username": "string", // 用户名,可选
|
||
"email": "string", // 邮箱,可选
|
||
"avatar": "string", // 头像URL,可选
|
||
"status": 1 // 状态,可选
|
||
}
|
||
```
|
||
|
||
### 删除用户
|
||
|
||
**接口地址**: `DELETE /users/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "用户删除成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 上传用户头像
|
||
|
||
**接口地址**: `POST /users/{id}/avatar`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求格式**: `multipart/form-data`
|
||
|
||
**表单字段**:
|
||
- `file`: 图片文件(必填)
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "头像上传成功",
|
||
"data": {
|
||
"avatar_url": "/uploads/avatars/1_1704875400.jpg"
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例**:
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/users/1/avatar" \
|
||
-H "Authorization: Bearer <your-token>" \
|
||
-F "file=@avatar.jpg"
|
||
```
|
||
|
||
## 📸 照片管理接口
|
||
|
||
### 获取照片列表
|
||
|
||
**接口地址**: `GET /photos`
|
||
|
||
**查询参数**:
|
||
- `page`: 页码,默认 1
|
||
- `limit`: 每页数量,默认 10
|
||
- `category_id`: 分类ID
|
||
- `user_id`: 用户ID
|
||
- `status`: 照片状态
|
||
- `keyword`: 搜索关键词
|
||
- `sort`: 排序方式,可选值:`created_at_desc`、`created_at_asc`、`title_asc`、`title_desc`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"photos": [
|
||
{
|
||
"id": 1,
|
||
"title": "美丽的日落",
|
||
"description": "在海边拍摄的日落景色",
|
||
"file_path": "/uploads/photos/sunset.jpg",
|
||
"thumbnail_path": "/uploads/photos/thumbs/sunset_thumb.jpg",
|
||
"file_size": 2048576,
|
||
"mime_type": "image/jpeg",
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"category_id": 1,
|
||
"category_name": "风景",
|
||
"user_id": 1,
|
||
"username": "johndoe",
|
||
"status": 1,
|
||
"view_count": 150,
|
||
"like_count": 25,
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
],
|
||
"total": 100,
|
||
"page": 1,
|
||
"limit": 10,
|
||
"pages": 10
|
||
}
|
||
}
|
||
```
|
||
|
||
### 获取照片详情
|
||
|
||
**接口地址**: `GET /photos/{id}`
|
||
|
||
**路径参数**:
|
||
- `id`: 照片ID
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"id": 1,
|
||
"title": "美丽的日落",
|
||
"description": "在海边拍摄的日落景色",
|
||
"file_path": "/uploads/photos/sunset.jpg",
|
||
"thumbnail_path": "/uploads/photos/thumbs/sunset_thumb.jpg",
|
||
"file_size": 2048576,
|
||
"mime_type": "image/jpeg",
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"category": {
|
||
"id": 1,
|
||
"name": "风景",
|
||
"description": "自然风光和城市景观"
|
||
},
|
||
"user": {
|
||
"id": 1,
|
||
"username": "johndoe",
|
||
"avatar": "/uploads/avatars/1.jpg"
|
||
},
|
||
"tags": [
|
||
{
|
||
"id": 1,
|
||
"name": "精选",
|
||
"color": "#ff4444"
|
||
}
|
||
],
|
||
"status": 1,
|
||
"view_count": 150,
|
||
"like_count": 25,
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 上传照片
|
||
|
||
**接口地址**: `POST /photos`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求格式**: `multipart/form-data`
|
||
|
||
**表单字段**:
|
||
- `file`: 图片文件(必填)
|
||
- `title`: 照片标题(必填)
|
||
- `description`: 照片描述(可选)
|
||
- `category_id`: 分类ID(可选)
|
||
- `tags`: 标签ID列表,逗号分隔(可选)
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "照片上传成功",
|
||
"data": {
|
||
"id": 1,
|
||
"title": "美丽的日落",
|
||
"description": "在海边拍摄的日落景色",
|
||
"file_path": "/uploads/photos/sunset_1704875400.jpg",
|
||
"thumbnail_path": "/uploads/photos/thumbs/sunset_1704875400_thumb.jpg",
|
||
"file_size": 2048576,
|
||
"mime_type": "image/jpeg",
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"category_id": 1,
|
||
"user_id": 1,
|
||
"status": 1,
|
||
"created_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例**:
|
||
```bash
|
||
curl -X POST "http://localhost:8080/api/v1/photos" \
|
||
-H "Authorization: Bearer <your-token>" \
|
||
-F "file=@sunset.jpg" \
|
||
-F "title=美丽的日落" \
|
||
-F "description=在海边拍摄的日落景色" \
|
||
-F "category_id=1"
|
||
```
|
||
|
||
### 更新照片
|
||
|
||
**接口地址**: `PUT /photos/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"title": "string", // 照片标题,可选
|
||
"description": "string", // 照片描述,可选
|
||
"category_id": 1, // 分类ID,可选
|
||
"status": 1 // 状态,可选
|
||
}
|
||
```
|
||
|
||
### 删除照片
|
||
|
||
**接口地址**: `DELETE /photos/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "照片删除成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
## 📂 分类管理接口
|
||
|
||
### 获取分类列表
|
||
|
||
**接口地址**: `GET /categories`
|
||
|
||
**查询参数**:
|
||
- `parent_id`: 父分类ID,获取子分类
|
||
- `is_active`: 是否激活,可选值 0、1
|
||
- `with_count`: 是否包含照片数量统计,默认 false
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"name": "风景",
|
||
"description": "自然风光和城市景观",
|
||
"parent_id": null,
|
||
"sort_order": 1,
|
||
"is_active": 1,
|
||
"photo_count": 25,
|
||
"children": [
|
||
{
|
||
"id": 2,
|
||
"name": "海景",
|
||
"description": "海洋和海滩景色",
|
||
"parent_id": 1,
|
||
"sort_order": 1,
|
||
"is_active": 1,
|
||
"photo_count": 10
|
||
}
|
||
],
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 获取分类详情
|
||
|
||
**接口地址**: `GET /categories/{id}`
|
||
|
||
**路径参数**:
|
||
- `id`: 分类ID
|
||
|
||
### 创建分类
|
||
|
||
**接口地址**: `POST /categories`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"name": "string", // 分类名称,必填
|
||
"description": "string", // 分类描述,可选
|
||
"parent_id": 1, // 父分类ID,可选
|
||
"sort_order": 1, // 排序序号,可选
|
||
"is_active": 1 // 是否激活,可选
|
||
}
|
||
```
|
||
|
||
### 更新分类
|
||
|
||
**接口地址**: `PUT /categories/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"name": "string", // 分类名称,可选
|
||
"description": "string", // 分类描述,可选
|
||
"parent_id": 1, // 父分类ID,可选
|
||
"sort_order": 1, // 排序序号,可选
|
||
"is_active": 1 // 是否激活,可选
|
||
}
|
||
```
|
||
|
||
### 删除分类
|
||
|
||
**接口地址**: `DELETE /categories/{id}`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "分类删除成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
## 🏷️ 标签管理接口
|
||
|
||
### 获取标签列表
|
||
|
||
**接口地址**: `GET /tags`
|
||
|
||
**查询参数**:
|
||
- `is_active`: 是否激活
|
||
- `keyword`: 搜索关键词
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"name": "精选",
|
||
"color": "#ff4444",
|
||
"description": "精选优质作品",
|
||
"is_active": 1,
|
||
"photo_count": 15,
|
||
"created_at": "2024-01-10T10:30:00Z",
|
||
"updated_at": "2024-01-10T10:30:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 创建标签
|
||
|
||
**接口地址**: `POST /tags`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"name": "string", // 标签名称,必填
|
||
"color": "#ff4444", // 标签颜色,可选
|
||
"description": "string", // 标签描述,可选
|
||
"is_active": 1 // 是否激活,可选
|
||
}
|
||
```
|
||
|
||
## 🏥 健康检查接口
|
||
|
||
### 健康检查
|
||
|
||
**接口地址**: `GET /health`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"status": "ok",
|
||
"timestamp": "2024-01-10T10:30:00Z",
|
||
"version": "v1.0.0",
|
||
"uptime": "2h30m15s",
|
||
"database": "connected",
|
||
"redis": "connected"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 📊 统计接口
|
||
|
||
### 获取仪表盘统计
|
||
|
||
**接口地址**: `GET /dashboard/stats`
|
||
|
||
**请求头**: `Authorization: Bearer <token>`
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"users": {
|
||
"total": 150,
|
||
"active": 142,
|
||
"new_today": 5
|
||
},
|
||
"photos": {
|
||
"total": 2500,
|
||
"published": 2350,
|
||
"new_today": 25,
|
||
"total_views": 150000,
|
||
"total_likes": 8500
|
||
},
|
||
"categories": {
|
||
"total": 12,
|
||
"active": 10
|
||
},
|
||
"tags": {
|
||
"total": 25,
|
||
"active": 22
|
||
},
|
||
"storage": {
|
||
"used": "15.5GB",
|
||
"total": "100GB",
|
||
"usage_percent": 15.5
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🔧 文件服务接口
|
||
|
||
### 静态文件访问
|
||
|
||
**接口地址**: `GET /uploads/{path}`
|
||
|
||
**路径参数**:
|
||
- `path`: 文件相对路径
|
||
|
||
**示例**:
|
||
- 照片原图: `GET /uploads/photos/sunset_1704875400.jpg`
|
||
- 缩略图: `GET /uploads/photos/thumbs/sunset_1704875400_thumb.jpg`
|
||
- 用户头像: `GET /uploads/avatars/1_1704875400.jpg`
|
||
|
||
## 📝 开发指南
|
||
|
||
### 环境配置
|
||
|
||
1. **开发环境**:
|
||
```bash
|
||
# 设置环境变量
|
||
export ENV=development
|
||
export DATABASE_HOST=localhost
|
||
export DATABASE_PORT=5432
|
||
export JWT_SECRET=your-jwt-secret
|
||
|
||
# 启动服务
|
||
go run cmd/api/main.go -f etc/photography-api.yaml
|
||
```
|
||
|
||
2. **生产环境**:
|
||
```bash
|
||
# 使用 Docker Compose
|
||
docker-compose -f configs/docker/docker-compose.prod.yml up -d
|
||
```
|
||
|
||
### 认证流程
|
||
|
||
1. 用户注册或登录获取 JWT Token
|
||
2. 在请求头中添加 `Authorization: Bearer <token>`
|
||
3. 服务器验证 Token 并提取用户信息
|
||
4. 权限检查通过后执行业务逻辑
|
||
|
||
### 错误处理
|
||
|
||
API 遵循统一的错误处理机制:
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "参数验证失败: 用户名不能为空",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
常见错误码:
|
||
- `401`: 未登录或 Token 无效
|
||
- `403`: 权限不足
|
||
- `400`: 参数错误
|
||
- `404`: 资源不存在
|
||
- `500`: 服务器错误
|
||
|
||
### 性能优化
|
||
|
||
1. **分页查询**: 大数据量接口支持分页,减少单次传输数据量
|
||
2. **字段过滤**: 支持 `fields` 参数指定返回字段
|
||
3. **缓存机制**: 热点数据使用 Redis 缓存
|
||
4. **数据库优化**: 合理使用索引,避免N+1查询
|
||
|
||
### 安全考虑
|
||
|
||
1. **输入验证**: 所有用户输入都进行严格验证
|
||
2. **SQL注入防护**: 使用参数化查询
|
||
3. **文件上传安全**: 文件类型和大小限制
|
||
4. **Rate Limiting**: 接口频率限制
|
||
5. **CORS配置**: 跨域请求控制
|
||
|
||
## 📚 SDK 和工具
|
||
|
||
### JavaScript/TypeScript SDK
|
||
|
||
```typescript
|
||
import { PhotographyAPI } from 'photography-api-sdk';
|
||
|
||
const api = new PhotographyAPI({
|
||
baseURL: 'https://api.photography.iriver.top/api/v1',
|
||
token: 'your-jwt-token'
|
||
});
|
||
|
||
// 获取照片列表
|
||
const photos = await api.photos.list({
|
||
page: 1,
|
||
limit: 10,
|
||
category_id: 1
|
||
});
|
||
|
||
// 上传照片
|
||
const photo = await api.photos.upload({
|
||
file: fileBlob,
|
||
title: '美丽的日落',
|
||
description: '在海边拍摄的日落景色',
|
||
category_id: 1
|
||
});
|
||
```
|
||
|
||
### Postman Collection
|
||
|
||
项目提供完整的 Postman Collection,包含所有接口的示例请求:
|
||
|
||
```bash
|
||
# 导入 Postman Collection
|
||
curl -o photography-api.postman_collection.json \
|
||
https://raw.githubusercontent.com/photography/api-docs/main/postman/collection.json
|
||
```
|
||
|
||
### OpenAPI 规范
|
||
|
||
API 提供标准的 OpenAPI 3.0 规范文档:
|
||
|
||
- **Swagger UI**: `https://api.photography.iriver.top/swagger`
|
||
- **OpenAPI JSON**: `https://api.photography.iriver.top/api/openapi.json`
|
||
|
||
## 🚀 部署说明
|
||
|
||
### Docker 部署
|
||
|
||
```bash
|
||
# 拉取镜像
|
||
docker pull photography/api:latest
|
||
|
||
# 运行容器
|
||
docker run -d \
|
||
--name photography-api \
|
||
-p 8080:8080 \
|
||
-e DATABASE_HOST=your-db-host \
|
||
-e DATABASE_PASSWORD=your-db-password \
|
||
-e JWT_SECRET=your-jwt-secret \
|
||
photography/api:latest
|
||
```
|
||
|
||
### Kubernetes 部署
|
||
|
||
```yaml
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: photography-api
|
||
spec:
|
||
replicas: 3
|
||
selector:
|
||
matchLabels:
|
||
app: photography-api
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: photography-api
|
||
spec:
|
||
containers:
|
||
- name: api
|
||
image: photography/api:latest
|
||
ports:
|
||
- containerPort: 8080
|
||
env:
|
||
- name: DATABASE_HOST
|
||
value: "postgres-service"
|
||
- name: JWT_SECRET
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: api-secrets
|
||
key: jwt-secret
|
||
```
|
||
|
||
## 📞 支持
|
||
|
||
- **技术文档**: https://docs.photography.iriver.top
|
||
- **GitHub Issues**: https://github.com/photography/api/issues
|
||
- **邮箱支持**: api-support@photography.com
|
||
|
||
---
|
||
|
||
*最后更新: 2024-01-10* |