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

@ -194,25 +194,22 @@ func (s *articleService) detailErr(err error) error {
// buildDetail 把查询行与图片集映射为详情 DTO(公开/后台共用,差异只在数据来源)。
func (s *articleService) buildDetail(row *model.RunwayRow, imgs []model.BrandRunwayImage, locale string) *dto.PublicArticleDetail {
// 主图(is_detail=0)进 Images,默认展示;细节图(is_detail=1)按 look_index
// 直接挂到所属主图的 Detail 子数组下 —— 「look → 细节」的层级与前端 UI 一致,
// 前端读 img.detail 即可,无需再单独维护一份「按 look_index 分组」的映射表。
// 主图(is_detail=0)进 Images,默认展示;细节图(is_detail=1)按 parent_image_id
// 直接挂到所属主图的 Detail 子数组下 —— 「主图 → 细节」的层级与前端 UI 一致,前端读 img.detail 即可。
mains := make([]model.BrandRunwayImage, 0, len(imgs))
byLook := make(map[uint32][]model.BrandRunwayImage)
detailsByParent := make(map[uint32][]model.BrandRunwayImage)
for _, im := range imgs {
if im.IsDetail == 0 {
if im.IsDetail == 0 || im.ParentImageID == 0 {
mains = append(mains, im)
} else {
byLook[im.LookIndex] = append(byLook[im.LookIndex], im)
detailsByParent[im.ParentImageID] = append(detailsByParent[im.ParentImageID], im)
}
}
pubMains := s.toPublicImages(mains)
for i := range pubMains {
// 挂载后即从 byLook 摘除:主图 look_index 若有重复,只归属第一张,避免同一批
// 细节图被复制进多个主图(正常数据不会重复,此处仅作防御)。
if kids, ok := byLook[pubMains[i].LookIndex]; ok && len(kids) > 0 {
// 主图 id 对应的细节图子集挂到该主图下(正常数据每个主图一份,无需防御性摘除)。
if kids, ok := detailsByParent[mains[i].ID]; ok && len(kids) > 0 {
pubMains[i].Detail = s.toPublicImages(kids)
delete(byLook, pubMains[i].LookIndex)
}
}
@ -231,7 +228,45 @@ func (s *articleService) buildDetail(row *model.RunwayRow, imgs []model.BrandRun
// ── 后台编辑支持 ──────────────────────────────────────────────────────────────
func (s *articleService) GetForEdit(ctx context.Context, id uint32) (*model.BrandRunway, []model.BrandRunwayImage, error) {
return s.articles.GetForEdit(ctx, id)
rw, imgs, err := s.articles.GetForEdit(ctx, id)
if err != nil {
return nil, nil, err
}
// 与街拍编辑页同构:把每张主图(is_detail=0)紧跟其细节图(同 parent_image_id、is_detail=1)重排,
// 避免细节图被甩到几百张图的最末尾、看起来像「没显示」。孤儿细节图(无主图)追加末尾。
return rw, orderRunwayImagesForEdit(imgs), nil
}
// orderRunwayImagesForEdit 走秀图片按 parent_image_id 重排为「主图后紧跟其细节图」的扁平顺序。
// 同一主图内的细节图按 sort_order 升序;孤儿细节图(parent 缺失)追加末尾,不丢图。
func orderRunwayImagesForEdit(imgs []model.BrandRunwayImage) []model.BrandRunwayImage {
mains := make([]model.BrandRunwayImage, 0, len(imgs))
mainSeen := make(map[uint32]bool, len(imgs))
for _, im := range imgs {
isMain := im.IsDetail == 0 || im.ParentImageID == 0
if isMain && !mainSeen[im.ID] {
mainSeen[im.ID] = true
mains = append(mains, im)
}
}
detailsByParent := make(map[uint32][]model.BrandRunwayImage, len(imgs))
for _, im := range imgs {
if im.IsDetail == 1 && im.ParentImageID != 0 && !mainSeen[im.ID] {
detailsByParent[im.ParentImageID] = append(detailsByParent[im.ParentImageID], im)
}
}
out := make([]model.BrandRunwayImage, 0, len(imgs))
for _, main := range mains {
out = append(out, main)
out = append(out, detailsByParent[main.ID]...)
}
// 孤儿细节图(parent 缺失):追加末尾,保证不丢图。
for _, im := range imgs {
if im.IsDetail == 1 && im.ParentImageID == 0 && !mainSeen[im.ID] {
out = append(out, im)
}
}
return out
}
func (s *articleService) UpdateRunway(ctx context.Context, id uint32, fields map[string]any) error {
@ -306,7 +341,6 @@ func (s *articleService) toPublicImages(imgs []model.BrandRunwayImage) []dto.Pub
Thumb: s.img.ComposeThumb(im.Image),
Name: im.Name,
IsDetail: im.IsDetail,
LookIndex: im.LookIndex,
})
}
return out
@ -325,7 +359,6 @@ func (s *articleService) toThumbImages(imgs []model.BrandRunwayImage) []dto.Publ
Image: s.img.ComposeThumb(im.Image),
Name: im.Name,
IsDetail: im.IsDetail,
LookIndex: im.LookIndex,
})
}
return out