feat: 结果页添加帧预览、GIF动画和导出选项
- 后端: GetAssets 返回素材级别 metadata,区分 frame/preview/spritesheet 类型 - 后端: 上传时区分素材类型标签,GIF URL 独立追踪 - 前端: 结果详情页默认展示拆分后的单帧网格 - 前端: 添加动作帧 GIF 预览弹窗 - 前端: 添加导出下拉菜单(整张精灵表/自动切分帧) - 前端: 失败任务展示错误信息和重试次数
This commit is contained in:
@@ -47,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 素材生成接口(异步)。
|
||||
@@ -136,7 +136,7 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
|
||||
updateTaskInDB(ctx, taskID, "saving", "format_adapter", "", 90)
|
||||
|
||||
// 上传素材并保存到数据库
|
||||
var lastCDNURL string
|
||||
var lastGIFCDNURL 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)
|
||||
@@ -145,13 +145,15 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
|
||||
updateTaskInDB(ctx, taskID, "failed", "", "上传素材失败: "+err.Error(), 0)
|
||||
return
|
||||
}
|
||||
lastCDNURL = cdnURL
|
||||
|
||||
var assetMeta map[string]interface{}
|
||||
if a.Format == "gif" {
|
||||
assetMeta = map[string]interface{}{"index": i, "type": "preview"}
|
||||
lastGIFCDNURL = cdnURL
|
||||
} else if strings.Contains(a.URL, "spritesheet") {
|
||||
assetMeta = map[string]interface{}{"index": i, "type": "spritesheet"}
|
||||
} else {
|
||||
assetMeta = map[string]interface{}{"index": i}
|
||||
assetMeta = map[string]interface{}{"index": i, "type": "frame"}
|
||||
}
|
||||
metadataJSON, _ := json.Marshal(assetMeta)
|
||||
|
||||
@@ -169,8 +171,8 @@ func runPipelineBg(ctx context.Context, projectID, taskID string, req GenerateRe
|
||||
}
|
||||
|
||||
// GIF URL 替换为实际上传后的 CDN 地址
|
||||
if output.Metadata.GIFURL != "" && lastCDNURL != "" {
|
||||
output.Metadata.GIFURL = lastCDNURL
|
||||
if output.Metadata.GIFURL != "" && lastGIFCDNURL != "" {
|
||||
output.Metadata.GIFURL = lastGIFCDNURL
|
||||
}
|
||||
|
||||
var fullMetadata string
|
||||
@@ -232,9 +234,10 @@ func GetAssets(c *gin.Context) {
|
||||
response := []model.AssetResponse{}
|
||||
for _, a := range assets {
|
||||
response = append(response, model.AssetResponse{
|
||||
Key: a.Key,
|
||||
URL: storageSvc.GetSignedURL(a.Key),
|
||||
Format: a.Format,
|
||||
Key: a.Key,
|
||||
URL: storageSvc.GetSignedURL(a.Key),
|
||||
Format: a.Format,
|
||||
Metadata: a.Metadata,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user