feat: 更新内容创建和更新表单,支持封面ID和媒体ID字段
This commit is contained in:
@@ -30,6 +30,7 @@ type ContentCreateForm struct {
|
|||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
|
CoverIDs []string `json:"cover_ids"`
|
||||||
MediaIDs []string `json:"media_ids"`
|
MediaIDs []string `json:"media_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +39,7 @@ type ContentUpdateForm struct {
|
|||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
|
CoverIDs []string `json:"cover_ids"`
|
||||||
MediaIDs []string `json:"media_ids"`
|
MediaIDs []string `json:"media_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,18 +173,30 @@ func (s *creator) CreateContent(ctx context.Context, userID int64, form *creator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Link Assets
|
// 2. Link Assets
|
||||||
if len(form.MediaIDs) > 0 {
|
var assets []*models.ContentAsset
|
||||||
var assets []*models.ContentAsset
|
// Covers
|
||||||
for i, mid := range form.MediaIDs {
|
for i, mid := range form.CoverIDs {
|
||||||
assets = append(assets, &models.ContentAsset{
|
assets = append(assets, &models.ContentAsset{
|
||||||
TenantID: tid,
|
TenantID: tid,
|
||||||
UserID: uid,
|
UserID: uid,
|
||||||
ContentID: content.ID,
|
ContentID: content.ID,
|
||||||
AssetID: cast.ToInt64(mid),
|
AssetID: cast.ToInt64(mid),
|
||||||
Sort: int32(i),
|
Sort: int32(i),
|
||||||
Role: consts.ContentAssetRoleMain,
|
Role: consts.ContentAssetRoleCover,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// Main Media
|
||||||
|
for i, mid := range form.MediaIDs {
|
||||||
|
assets = append(assets, &models.ContentAsset{
|
||||||
|
TenantID: tid,
|
||||||
|
UserID: uid,
|
||||||
|
ContentID: content.ID,
|
||||||
|
AssetID: cast.ToInt64(mid),
|
||||||
|
Sort: int32(i),
|
||||||
|
Role: consts.ContentAssetRoleMain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(assets) > 0 {
|
||||||
if err := tx.ContentAsset.WithContext(ctx).Create(assets...); err != nil {
|
if err := tx.ContentAsset.WithContext(ctx).Create(assets...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -258,23 +270,35 @@ func (s *creator) UpdateContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. Update Assets (Full replacement strategy)
|
// 4. Update Assets (Full replacement strategy)
|
||||||
if len(form.MediaIDs) > 0 {
|
_, err = tx.ContentAsset.WithContext(ctx).Where(tx.ContentAsset.ContentID.Eq(cid)).Delete()
|
||||||
_, err = tx.ContentAsset.WithContext(ctx).Where(tx.ContentAsset.ContentID.Eq(cid)).Delete()
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var assets []*models.ContentAsset
|
var assets []*models.ContentAsset
|
||||||
for i, mid := range form.MediaIDs {
|
// Covers
|
||||||
assets = append(assets, &models.ContentAsset{
|
for i, mid := range form.CoverIDs {
|
||||||
TenantID: tid,
|
assets = append(assets, &models.ContentAsset{
|
||||||
UserID: uid,
|
TenantID: tid,
|
||||||
ContentID: cid,
|
UserID: uid,
|
||||||
AssetID: cast.ToInt64(mid),
|
ContentID: cid,
|
||||||
Sort: int32(i),
|
AssetID: cast.ToInt64(mid),
|
||||||
Role: consts.ContentAssetRoleMain, // Default to main
|
Sort: int32(i),
|
||||||
})
|
Role: consts.ContentAssetRoleCover,
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
// Main Media
|
||||||
|
for i, mid := range form.MediaIDs {
|
||||||
|
assets = append(assets, &models.ContentAsset{
|
||||||
|
TenantID: tid,
|
||||||
|
UserID: uid,
|
||||||
|
ContentID: cid,
|
||||||
|
AssetID: cast.ToInt64(mid),
|
||||||
|
Sort: int32(i),
|
||||||
|
Role: consts.ContentAssetRoleMain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(assets) > 0 {
|
||||||
if err := tx.ContentAsset.WithContext(ctx).Create(assets...); err != nil {
|
if err := tx.ContentAsset.WithContext(ctx).Create(assets...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,4 +138,4 @@ LocalPath = "./storage"
|
|||||||
# 签名密钥
|
# 签名密钥
|
||||||
Secret = "your-storage-secret"
|
Secret = "your-storage-secret"
|
||||||
# 公共访问URL前缀
|
# 公共访问URL前缀
|
||||||
BaseURL = "http://localhost:8080/v1/storage"
|
BaseURL = "/v1/storage"
|
||||||
|
|||||||
@@ -338,44 +338,12 @@ const submit = async () => {
|
|||||||
visibility: 'public',
|
visibility: 'public',
|
||||||
preview_seconds: form.enableTrial ? form.trialTime : 0,
|
preview_seconds: form.enableTrial ? form.trialTime : 0,
|
||||||
price: form.priceType === 'paid' ? parseFloat(form.price) : 0, // API expects float price, service handles conversion
|
price: form.priceType === 'paid' ? parseFloat(form.price) : 0, // API expects float price, service handles conversion
|
||||||
media_ids: [] // API expects media_ids list? Wait, update DTO `ContentUpdateForm` expects `media_ids` string array?
|
cover_ids: [],
|
||||||
// Check `ContentCreateForm` and `ContentUpdateForm`.
|
media_ids: []
|
||||||
// `ContentCreateForm`: `MediaIDs []string`.
|
|
||||||
// Backend logic in `CreateContent` iterates `MediaIDs` and sets `Role` to `main`.
|
|
||||||
// It does NOT handle Covers explicitly in `CreateContent` logic I read!
|
|
||||||
// `CreateContent` logic: `assets = append(assets, ... Role: Main)`.
|
|
||||||
// So Covers are ignored or treated as Main?
|
|
||||||
// Wait, `UpdateContent` also iterates `MediaIDs` and sets `Role` to `Main`.
|
|
||||||
// So current backend implementation treats ALL sent IDs as Main assets.
|
|
||||||
// And assumes `Cover` is handled via `toContentItemDTO` fallback or separate logic?
|
|
||||||
// Backend logic for `CreateContent`:
|
|
||||||
// `assets = append(assets, ... Role: Main)`.
|
|
||||||
// This is a limitation. I need to update backend to support Roles map or assume first image is cover?
|
|
||||||
// But `ContentsEditView` sends `assets` array with roles in my previous assumption?
|
|
||||||
// No, the `submit` function in `ContentsEditView` (previous version) constructed `payload.assets`.
|
|
||||||
// But `creatorApi.createContent` sends `ContentCreateForm` which has `media_ids []string`.
|
|
||||||
// `ContentCreateForm` does NOT have `assets` structure!
|
|
||||||
// So I need to update `ContentCreateForm` / `ContentUpdateForm` to support asset structure OR just send IDs and let backend guess.
|
|
||||||
// Given I can't easily change `ContentCreateForm` structure extensively without breaking other things?
|
|
||||||
// Actually, I just read `ContentCreateForm` has `MediaIDs []string`.
|
|
||||||
// If I want to support covers, I need to update Backend DTO and Service.
|
|
||||||
// Or I can send all IDs in `MediaIDs` and Backend sets them as `Main`.
|
|
||||||
// This means Covers won't be distinguished.
|
|
||||||
// I should fix Backend `ContentCreateForm` / `ContentUpdateForm` to accept `Assets []AssetForm`?
|
|
||||||
// Or just `CoverIDs` and `MediaIDs`.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Let's check `backend/app/http/v1/dto/creator.go` again.
|
payload.cover_ids = form.covers.map(m => m.id);
|
||||||
// `ContentCreateForm` struct: `MediaIDs []string`.
|
payload.media_ids = [...form.videos, ...form.audios, ...form.images].map(m => m.id);
|
||||||
// `ContentUpdateForm` struct: `MediaIDs []string`.
|
|
||||||
|
|
||||||
// I will assume for now I pass ALL IDs. Backend sets Role=Main.
|
|
||||||
// To fix Cover, I should modify backend to accept `CoverIDs` or `Assets` structure.
|
|
||||||
// But for this task "Fix 404", I'll stick to passing IDs.
|
|
||||||
// I will update the logic to collect ALL IDs from covers, videos, audios, images.
|
|
||||||
|
|
||||||
const allMedia = [...form.covers, ...form.videos, ...form.audios, ...form.images];
|
|
||||||
payload.media_ids = allMedia.map(m => m.id);
|
|
||||||
|
|
||||||
if (isEditMode.value) {
|
if (isEditMode.value) {
|
||||||
await creatorApi.updateContent(contentId.value, payload);
|
await creatorApi.updateContent(contentId.value, payload);
|
||||||
|
|||||||
Reference in New Issue
Block a user