fix: 工程类型与素材风格标签分离,支持双栏自定义标签

- 工程层面:新增 PROJECT_TYPES(2D平台跳跃/角色扮演等8种),替代原先与素材生成重复的风格标签栏
- 素材生成层面:StyleSelector 作为素材风格主配置项,新增 CustomTagsEditor 支持任务级自定义标签
- extractTags 合并工程类型、风格分类、工程自定义标签、任务自定义标签
- StyleSelector 支持 categories 参数复用
- 后端:spritesheet 拆分失败回退为单帧、GIF 上传为独立素材、AssetResponse 增加 metadata 字段
This commit is contained in:
2026-05-25 19:31:36 +08:00
parent c48ba6e61d
commit ab2b72e746
14 changed files with 149 additions and 57 deletions
+18 -12
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
"gen2d/internal/db"
@@ -46,8 +47,8 @@ type GenerateResponse struct {
// AssetsResponse 素材列表响应。
type AssetsResponse struct {
Assets []model.AssetResponse `json:"assets"`
Metadata service.AssetMetadata `json:"metadata"`
Assets []model.AssetResponse `json:"assets"`
Metadata service.AssetMetadata `json:"metadata"`
}
// Generate 素材生成接口(异步)。
@@ -135,6 +136,7 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
updateTaskInDB(ctx, taskID, "saving", "format_adapter", "", 90)
// 上传素材并保存到数据库
var lastCDNURL string
for i, a := range output.Assets {
key := fmt.Sprintf("generation/%s/%s/%d.%s", projectID, taskID, i, a.Format)
cdnURL, err := storageSvc.Upload(ctx, key, a.Data)
@@ -143,15 +145,15 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
updateTaskInDB(ctx, taskID, "failed", "", "上传素材失败: "+err.Error(), 0)
return
}
lastCDNURL = cdnURL
// 序列化单个素材的元数据
var metadata map[string]interface{}
if i < len(output.Assets) {
metadata = map[string]interface{}{
"index": i,
}
var assetMeta map[string]interface{}
if a.Format == "gif" {
assetMeta = map[string]interface{}{"index": i, "type": "preview"}
} else {
assetMeta = map[string]interface{}{"index": i}
}
metadataJSON, _ := json.Marshal(metadata)
metadataJSON, _ := json.Marshal(assetMeta)
asset := &model.Asset{
TaskID: getTaskDBID(ctx, taskID),
@@ -166,7 +168,11 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
}
}
// 更新为完成状态
// GIF URL 替换为实际上传后的 CDN 地址
if output.Metadata.GIFURL != "" && lastCDNURL != "" {
output.Metadata.GIFURL = lastCDNURL
}
var fullMetadata string
if metadataJSON, err := json.Marshal(output.Metadata); err == nil {
fullMetadata = string(metadataJSON)
@@ -274,8 +280,8 @@ func saveTaskToDB(ctx context.Context, projectID, taskID string, req GenerateReq
// updateTaskInDB 更新数据库中的任务状态。
func updateTaskInDB(ctx context.Context, taskID, status, stage, error string, progress int) {
updates := map[string]interface{}{
"status": status,
"progress": progress,
"status": status,
"progress": progress,
"updated_at": time.Now(),
}
if stage != "" {