docs: 更新 MiniMax 设计文档,修复审核问题
- 修复时间戳不一致问题,统一使用毫秒时间戳 - 添加 CompletedAt 字段 - 添加 JobStatus 枚举类型 - 添加 HTTP 状态码表格 - 添加 SSRF 防护说明 - 添加轮询间隔(3秒)和超时(120秒)建议 - 添加任务清理机制(24h过期) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cf7af5cfa5
commit
286db74837
@ -51,7 +51,7 @@ Content-Type: application/json
|
|||||||
"data": {
|
"data": {
|
||||||
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
"status": "PROCESSING",
|
"status": "PROCESSING",
|
||||||
"created_at": "2026-04-07T12:00:00Z"
|
"created_at": 1744118400000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -71,7 +71,7 @@ GET /api/v1/assets/mints/image/generation/:job_id
|
|||||||
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
"status": "PROCESSING",
|
"status": "PROCESSING",
|
||||||
"progress": 50,
|
"progress": 50,
|
||||||
"created_at": "2026-04-07T12:00:00Z"
|
"created_at": 1744118400000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -88,8 +88,8 @@ GET /api/v1/assets/mints/image/generation/:job_id
|
|||||||
"images": [
|
"images": [
|
||||||
"https://api.minimaxi.com/v1/images/xxx.png"
|
"https://api.minimaxi.com/v1/images/xxx.png"
|
||||||
],
|
],
|
||||||
"created_at": "2026-04-07T12:00:00Z",
|
"created_at": 1744118400000,
|
||||||
"completed_at": "2026-04-07T12:01:30Z"
|
"completed_at": 1744118490000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -104,7 +104,7 @@ GET /api/v1/assets/mints/image/generation/:job_id
|
|||||||
"status": "FAILED",
|
"status": "FAILED",
|
||||||
"progress": 0,
|
"progress": 0,
|
||||||
"error_msg": "MiniMax API 调用失败: timeout",
|
"error_msg": "MiniMax API 调用失败: timeout",
|
||||||
"created_at": "2026-04-07T12:00:00Z"
|
"created_at": 1744118400000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -114,18 +114,29 @@ GET /api/v1/assets/mints/image/generation/:job_id
|
|||||||
### Job 状态 (内存存储)
|
### Job 状态 (内存存储)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
// JobStatus 任务状态枚举
|
||||||
|
type JobStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusPending JobStatus = "PENDING"
|
||||||
|
StatusProcessing JobStatus = "PROCESSING"
|
||||||
|
StatusCompleted JobStatus = "COMPLETED"
|
||||||
|
StatusFailed JobStatus = "FAILED"
|
||||||
|
)
|
||||||
|
|
||||||
// ImageGenerationJob 图生图任务
|
// ImageGenerationJob 图生图任务
|
||||||
type ImageGenerationJob struct {
|
type ImageGenerationJob struct {
|
||||||
JobID string `json:"job_id"`
|
JobID string `json:"job_id"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
StarID int64 `json:"star_id"`
|
StarID int64 `json:"star_id"`
|
||||||
Status string `json:"status"` // PENDING, PROCESSING, COMPLETED, FAILED
|
Status JobStatus `json:"status"`
|
||||||
Progress int `json:"progress"` // 0-100
|
Progress int `json:"progress"` // 0-100
|
||||||
Images []string `json:"images,omitempty"`
|
Images []string `json:"images,omitempty"`
|
||||||
ErrorMsg string `json:"error_msg,omitempty"`
|
ErrorMsg string `json:"error_msg,omitempty"`
|
||||||
Request *ImageGenerationRequest `json:"request,omitempty"`
|
Request *ImageGenerationRequest `json:"request,omitempty"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt int64 `json:"created_at"` //毫秒时间戳
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
CompletedAt int64 `json:"completed_at,omitempty"` // 毫秒时间戳
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -138,12 +149,12 @@ type ImageGenerationRequest struct {
|
|||||||
Prompt string `json:"prompt" binding:"required"`
|
Prompt string `json:"prompt" binding:"required"`
|
||||||
AspectRatio string `json:"aspect_ratio"`
|
AspectRatio string `json:"aspect_ratio"`
|
||||||
SubjectReference []SubjectReference `json:"subject_reference"`
|
SubjectReference []SubjectReference `json:"subject_reference"`
|
||||||
N int `json:"n"`
|
N int `json:"n"` // 1-4
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubjectReference struct {
|
type SubjectReference struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ImageFile string `json:"image_file"`
|
ImageFile string `json:"image_file"` // 必须为有效 URL,需 SSRF 校验
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageJobResponse 图生图任务响应
|
// ImageJobResponse 图生图任务响应
|
||||||
@ -155,6 +166,7 @@ type ImageJobResponse struct {
|
|||||||
ErrorMsg string `json:"error_msg,omitempty"`
|
ErrorMsg string `json:"error_msg,omitempty"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
UpdatedAt int64 `json:"updated_at"`
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
CompletedAt int64 `json:"completed_at,omitempty"`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -166,7 +178,7 @@ type ImageJobResponse struct {
|
|||||||
backend/
|
backend/
|
||||||
├── services/assetService/
|
├── services/assetService/
|
||||||
│ └── service/
|
│ └── service/
|
||||||
│ └── minimax_service.go # MiniMax API 转发服务
|
│ └── minimax_service.go # MiniMax API 转发服务 + 任务管理
|
||||||
└── gateway/
|
└── gateway/
|
||||||
├── controller/
|
├── controller/
|
||||||
│ └── asset_controller.go # 新增 ImageGeneration, GetImageJob
|
│ └── asset_controller.go # 新增 ImageGeneration, GetImageJob
|
||||||
@ -178,16 +190,43 @@ backend/
|
|||||||
|
|
||||||
### 核心逻辑
|
### 核心逻辑
|
||||||
|
|
||||||
1. **创建任务**: 生成 job_id,存储任务到内存,返回 202
|
1. **创建任务**: 生成 job_id,存储任务到内存 map,返回 202
|
||||||
2. **异步处理**: goroutine 调用 MiniMax API,图片压缩,更新 job 状态
|
2. **异步处理**: goroutine 调用 MiniMax API,图片压缩(最大边1024px),更新 job 状态
|
||||||
3. **查询状态**: 从内存读取 job 状态返回
|
3. **查询状态**: 从内存读取 job 状态返回
|
||||||
|
4. **任务清理**: 后台 goroutine 定期清理超期(>24h)的已完成任务
|
||||||
|
|
||||||
### 前端改动
|
### 图片压缩
|
||||||
|
|
||||||
|
- 最大边压缩至 1024px,保持宽高比
|
||||||
|
- 格式转换: PNG/GIF → JPEG(质量85%)
|
||||||
|
- 返回 base64 data URI 格式
|
||||||
|
|
||||||
|
### SSRF 防护
|
||||||
|
|
||||||
|
`subject_reference[].image_file` 必须是有效 URL,下载前需校验:
|
||||||
|
- 不能是私有 IP (10.x, 172.16-31.x, 192.168.x)
|
||||||
|
- 不能是 localhost
|
||||||
|
- 不能是内网域名
|
||||||
|
- 校验失败则拒绝请求 (400)
|
||||||
|
|
||||||
|
## 前端改动
|
||||||
|
|
||||||
**generation-loading.vue**:
|
**generation-loading.vue**:
|
||||||
- 调用 `POST /generation` 获取 job_id
|
- 调用 `POST /generation` 获取 job_id
|
||||||
- 轮询 `GET /generation/:job_id` 直到 `status === 'COMPLETED'` 或 `'FAILED'`
|
- 每 3 秒轮询 `GET /generation/:job_id`
|
||||||
- 进度可通过 `progress` 字段模拟更新
|
- 超时时间: 120 秒后显示"生成超时,请重试"
|
||||||
|
- 完成后跳转到结果页
|
||||||
|
|
||||||
|
## HTTP 状态码
|
||||||
|
|
||||||
|
| 场景 | HTTP 状态码 |
|
||||||
|
|------|-------------|
|
||||||
|
| 成功 (创建/查询) | 200 / 202 |
|
||||||
|
| 参数校验失败 | 400 |
|
||||||
|
| 未认证 | 401 |
|
||||||
|
| 无权访问 job | 403 |
|
||||||
|
| Job 不存在 | 404 |
|
||||||
|
| MiniMax API 失败 | 500 |
|
||||||
|
|
||||||
## 错误处理
|
## 错误处理
|
||||||
|
|
||||||
@ -195,6 +234,7 @@ backend/
|
|||||||
|------|----------|
|
|------|----------|
|
||||||
| MiniMax API 超时 | 标记 job 为 FAILED,error_msg 包含原因 |
|
| MiniMax API 超时 | 标记 job 为 FAILED,error_msg 包含原因 |
|
||||||
| 图片压缩失败 | 使用原图,继续处理 |
|
| 图片压缩失败 | 使用原图,继续处理 |
|
||||||
|
| SSRF 校验失败 | 返回 400,"无效的图片URL" |
|
||||||
| Job 不存在 | 返回 404 |
|
| Job 不存在 | 返回 404 |
|
||||||
| 无权访问 job | 返回 403 |
|
| 无权访问 job | 返回 403 |
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user