This commit is contained in:
toom1996
2026-09-25 11:31:52 +08:00
parent 4f4c11d508
commit 42f6316125
51 changed files with 4489 additions and 998 deletions

View File

@ -46,6 +46,11 @@ type ReviewRepository interface {
AttachStreetSnapImages(ctx context.Context, snapID, mainImgID uint32, imgIDs []uint32) error
// DetachStreetSnapImage 把副图恢复为主图(is_detail=0, parent_image_id=0)。对主图调用是幂等成功。
DetachStreetSnapImage(ctx context.Context, snapID, imgID uint32) error
// AttachRunwayImages 走秀版「合并选中为一组」:把 imgIDs 变为主图 mainImgID 的明细图。
// 与 AttachStreetSnapImages 同构(按 parent_image_id 分组):先改挂孙辈,再把被并入图标为副图。
AttachRunwayImages(ctx context.Context, runwayID, mainImgID uint32, imgIDs []uint32) error
// DetachRunwayImage 走秀版「拆出」:把明细图恢复为独立主图(is_detail=0,parent_image_id 清零)。
DetachRunwayImage(ctx context.Context, runwayID, imgID uint32) error
// GetImageKey 取单张图片的S4 key(删除前清理用);不存在返回空串。
GetImageKey(ctx context.Context, kind string, recordID, imgID uint32) (string, error)
// CountByStatus 统计某表(dest 传表对应的零值指针,如 &model.BrandRunway{})中指定状态的行数。
@ -412,3 +417,89 @@ func (r *reviewRepository) DetachStreetSnapImage(ctx context.Context, snapID, im
Updates(map[string]any{"is_detail": 0, "parent_image_id": 0, "updated_at": uint32(time.Now().Unix())}).
Error
}
// AttachRunwayImages 走秀版「合并选中为一组」:把 imgIDs 变为主图 mainImgID 的明细图。
//
// 与 AttachStreetSnapImages 同构(均按 parent_image_id 分组):事务内先「改挂孙辈」
// (被并入图原有的副图 parent_image_id IN ids 改挂到新主图),再把被并入图自身标为副图并指向新主图。
func (r *reviewRepository) AttachRunwayImages(ctx context.Context, runwayID, mainImgID uint32, imgIDs []uint32) error {
ids := make([]uint32, 0, len(imgIDs))
for _, id := range imgIDs {
if id != 0 && id != mainImgID {
ids = append(ids, id)
}
}
if mainImgID == 0 || len(imgIDs) == 0 {
return ErrInvalidImageGroup
}
if len(ids) == 0 {
return nil // 集合里只有主图自身:无操作成功
}
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var main model.BrandRunwayImage
if err := tx.Where("id = ? AND runway_id = ? AND is_deleted = 0 AND is_detail = 0", mainImgID, runwayID).
First(&main).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrInvalidImageGroup
}
return err
}
now := uint32(time.Now().Unix())
// 先改挂孙辈:被并入图原有的副图(parent_image_id IN ids)改挂到新主图。
if err := tx.Model(&model.BrandRunwayImage{}).
Where("runway_id = ? AND is_deleted = 0 AND parent_image_id IN ?", runwayID, ids).
Updates(map[string]any{"parent_image_id": mainImgID, "updated_at": now}).Error; err != nil {
return err
}
// 再把被并入图自身标为副图并指向新主图。
return tx.Model(&model.BrandRunwayImage{}).
Where("runway_id = ? AND is_deleted = 0 AND id IN ?", runwayID, ids).
Updates(map[string]any{"is_detail": 1, "parent_image_id": mainImgID, "updated_at": now}).Error
})
}
// DetachRunwayImage 走秀版「拆出」:把明细图恢复为独立主图(is_detail=0,parent_image_id 清零)。
// 同主图下其余明细图仍挂在该主图之下,不变量成立。
func (r *reviewRepository) DetachRunwayImage(ctx context.Context, runwayID, imgID uint32) error {
return r.db.WithContext(ctx).
Model(&model.BrandRunwayImage{}).
Where("id = ? AND runway_id = ? AND is_deleted = 0 AND is_detail = 1", imgID, runwayID).
Updates(map[string]any{"is_detail": 0, "parent_image_id": 0, "updated_at": uint32(time.Now().Unix())}).
Error
}
// RepairRunwayDetailParents 按 sort_order 顺序回填走秀细节图的 parent_image_id:
// 每张 is_detail=1 的图挂到它之前最近的一张 is_detail=0(主图)之下。
// 入库时细节图紧随其主图之后(同一 Look 先主图后细节),故「最近主图」即其归属主图。
// 供入库后调用,使新入库的走秀自动成组,无需人工合并。
func (r *reviewRepository) RepairRunwayDetailParents(ctx context.Context, runwayID uint32) error {
var imgs []model.BrandRunwayImage
if err := r.db.WithContext(ctx).
Where("runway_id = ? AND is_deleted = 0", runwayID).
Order("sort_order ASC, id ASC").
Find(&imgs).Error; err != nil {
return err
}
lastMain := uint32(0)
type fix struct{ id, parent uint32 }
fixes := make([]fix, 0)
for _, im := range imgs {
if im.IsDetail == 0 {
lastMain = im.ID
continue
}
if im.IsDetail == 1 && im.ParentImageID == 0 && lastMain != 0 {
fixes = append(fixes, fix{im.ID, lastMain})
}
}
for _, f := range fixes {
if err := r.db.WithContext(ctx).
Model(&model.BrandRunwayImage{}).
Where("id = ? AND runway_id = ? AND is_deleted = 0", f.id, runwayID).
Update("parent_image_id", f.parent).Error; err != nil {
return err
}
}
return nil
}