初始化

This commit is contained in:
Ran
2026-08-25 17:59:42 +08:00
commit 4b7380dd9b
408 changed files with 327400 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
package service
import (
"fmt"
"github.com/google/uuid"
"gorm.io/gorm"
)
type deletionMediaRow struct {
ID uuid.UUID
ObjectKey string
}
type deletionMediaSet struct {
rows map[uuid.UUID]string
}
func newDeletionMediaSet() *deletionMediaSet {
return &deletionMediaSet{rows: make(map[uuid.UUID]string)}
}
func (set *deletionMediaSet) addQuery(query *gorm.DB) error {
var rows []deletionMediaRow
if err := query.Scan(&rows).Error; err != nil {
return err
}
for _, row := range rows {
if row.ID != uuid.Nil {
set.rows[row.ID] = row.ObjectKey
}
}
return nil
}
func (set *deletionMediaSet) objectKeys() []string {
keys := make([]string, 0, len(set.rows))
seen := make(map[string]struct{}, len(set.rows))
for _, key := range set.rows {
if key == "" {
continue
}
if _, exists := seen[key]; exists {
continue
}
seen[key] = struct{}{}
keys = append(keys, key)
}
return keys
}
func (set *deletionMediaSet) deleteRows(tx *gorm.DB) error {
if len(set.rows) == 0 {
return nil
}
ids := make([]uuid.UUID, 0, len(set.rows))
for id := range set.rows {
ids = append(ids, id)
}
if err := tx.Exec("DELETE FROM channel_asset_cache WHERE media_asset_id IN ?", ids).Error; err != nil {
return err
}
return tx.Exec("DELETE FROM media_assets WHERE id IN ?", ids).Error
}
func collectMediaByObjectKey(tx *gorm.DB, set *deletionMediaSet, pattern string) error {
return set.addQuery(tx.Table("media_assets").Select("id,object_key").Where("object_key LIKE ?", pattern))
}
// removeEpisodeDerivedContent removes everything produced from an episode analysis.
// It intentionally keeps the episode source/subtitle and all project assets.
func removeEpisodeDerivedContent(tx *gorm.DB, projectID, episodeID uuid.UUID, media *deletionMediaSet) error {
// 封面来自本剧集的首帧,删除反推结果前先清理外键引用,避免随后删除媒体对象时产生约束错误。
if err := tx.Exec(`UPDATE creative_projects SET cover_asset_id=NULL
WHERE id=? AND cover_asset_id=(SELECT cover_asset_id FROM project_episodes WHERE id=?)`, projectID, episodeID).Error; err != nil {
return err
}
if err := tx.Exec("UPDATE project_episodes SET cover_asset_id=NULL WHERE id=?", episodeID).Error; err != nil {
return err
}
taskScope := `(task_type IN ('prompt_reverse','video_generation')
OR (task_type='image_generation' AND input_data->>'target_type'='storyboard')) AND
(episode_id=? OR storyboard_id IN (SELECT id FROM episode_storyboards WHERE episode_id=?))`
if err := media.addQuery(tx.Table("media_assets media").Select("DISTINCT media.id,media.object_key").
Joins("JOIN generation_outputs output ON output.media_asset_id=media.id").
Joins("JOIN generation_tasks task ON task.id=output.task_id").
Where(taskScope, episodeID, episodeID)); err != nil {
return err
}
if err := media.addQuery(tx.Table("media_assets media").Select("DISTINCT media.id,media.object_key").
Joins("JOIN episode_storyboards storyboard ON storyboard.thumbnail_asset_id=media.id").
Where("storyboard.episode_id=?", episodeID)); err != nil {
return err
}
derivedPrefix := fmt.Sprintf("juyou_ran/video-redraw/projects/%s/episodes/%s/storyboards/%%", projectID, episodeID)
if err := collectMediaByObjectKey(tx, media, derivedPrefix); err != nil {
return err
}
if err := tx.Exec("UPDATE episode_storyboards SET active_output_id=NULL WHERE episode_id=?", episodeID).Error; err != nil {
return err
}
if err := tx.Exec("DELETE FROM generation_outputs WHERE task_id IN (SELECT id FROM generation_tasks WHERE "+taskScope+")", episodeID, episodeID).Error; err != nil {
return err
}
if err := tx.Exec("DELETE FROM generation_tasks WHERE "+taskScope, episodeID, episodeID).Error; err != nil {
return err
}
if err := tx.Exec(`UPDATE generation_tasks SET storyboard_id=NULL
WHERE storyboard_id IN (SELECT id FROM episode_storyboards WHERE episode_id=?)`, episodeID).Error; err != nil {
return err
}
return tx.Exec("DELETE FROM episode_storyboards WHERE episode_id=?", episodeID).Error
}