update
This commit is contained in:
@ -28,8 +28,8 @@ type RecordCard struct {
|
||||
|
||||
// RecordImageRef 记录图片引用(统一结构)。
|
||||
//
|
||||
// IsDetail / ParentImageID 只有街拍模块会填(走秀的主/细节图走 LookIndex 那套,语义不同,不复用);
|
||||
// DetailCount 让模板不用自己数副图。
|
||||
// 街拍 / 走秀共用同一套主副图模型:is_detail=0 为主图(parent_image_id=0),
|
||||
// =1 为副图(parent_image_id 指向同记录内主图的行 id)。DetailCount 让模板不用自己数副图。
|
||||
type RecordImageRef struct {
|
||||
ID uint32 `json:"id"`
|
||||
Image string `json:"image"`
|
||||
@ -70,8 +70,9 @@ type RecordDetailView struct {
|
||||
Images []RecordImageRef `json:"images"`
|
||||
// Fields 是审核前可微调的字段列表(按模块声明顺序渲染),替代模板里的 IsStreet 分支。
|
||||
Fields []EditField `json:"fields"`
|
||||
// Groups 街拍详情的「主图 → 其副图」分组视图(按 sort_order 顺序)。走秀模块留空。
|
||||
// 与 Images 同源同序:Images 保持扁平(既有渲染 / runway 仍用),Groups 供按组折叠。
|
||||
// Groups 详情的「主图 → 其副图」分组视图(按 sort_order 顺序)。
|
||||
// 街拍与走秀均按 parent_image_id 分组(见各模块 RecordDetail),结构同构。
|
||||
// 与 Images 同源同序:Images 保持扁平(既有渲染),Groups 供按组折叠。
|
||||
Groups []ImageGroup `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
@ -286,20 +287,28 @@ func (s *reviewService) DeleteImage(ctx context.Context, kind string, recordID,
|
||||
}
|
||||
|
||||
func (s *reviewService) AttachImages(ctx context.Context, kind string, recordID, mainImgID uint32, imgIDs []uint32) error {
|
||||
if kind != dto.IngestKindStreet {
|
||||
return ErrInvalidImageGroup
|
||||
}
|
||||
if len(imgIDs) == 0 {
|
||||
return ErrInvalidImageGroup
|
||||
}
|
||||
return translateGroupErr(s.repo.AttachStreetSnapImages(ctx, recordID, mainImgID, imgIDs))
|
||||
switch kind {
|
||||
case dto.IngestKindStreet:
|
||||
return translateGroupErr(s.repo.AttachStreetSnapImages(ctx, recordID, mainImgID, imgIDs))
|
||||
case dto.IngestKindRunway:
|
||||
return translateGroupErr(s.repo.AttachRunwayImages(ctx, recordID, mainImgID, imgIDs))
|
||||
default:
|
||||
return ErrInvalidImageGroup
|
||||
}
|
||||
}
|
||||
|
||||
func (s *reviewService) DetachImage(ctx context.Context, kind string, recordID, imgID uint32) error {
|
||||
if kind != dto.IngestKindStreet {
|
||||
switch kind {
|
||||
case dto.IngestKindStreet:
|
||||
return translateGroupErr(s.repo.DetachStreetSnapImage(ctx, recordID, imgID))
|
||||
case dto.IngestKindRunway:
|
||||
return translateGroupErr(s.repo.DetachRunwayImage(ctx, recordID, imgID))
|
||||
default:
|
||||
return ErrInvalidImageGroup
|
||||
}
|
||||
return translateGroupErr(s.repo.DetachStreetSnapImage(ctx, recordID, imgID))
|
||||
}
|
||||
|
||||
// translateGroupErr 把仓储层的哨兵错误翻成给用户看的中文文案;其余错误原样透传。
|
||||
@ -367,12 +376,58 @@ func (m *runwayModule) RecordDetail(ctx context.Context, id uint32) (*RecordDeta
|
||||
{Name: "season_code", Label: "季节码", Value: d.SeasonCode, Type: "text"},
|
||||
},
|
||||
}
|
||||
// 按 parent_image_id 成组(与街拍同构):is_detail=0 为主图;is_detail=1 且 parent_image_id>0
|
||||
// 的是其副图;is_detail=1 且 parent_image_id=0 的孤儿细节图按主图渲染(自成一组,不丢图)。
|
||||
// 这样走秀详情页(消费 Groups)与街拍同构,编辑页(消费 Images)也能按主图→细节图顺序渲染。
|
||||
mains := make([]model.BrandRunwayImage, 0, len(imgs))
|
||||
mainSeen := make(map[uint32]bool, len(imgs))
|
||||
for _, im := range imgs {
|
||||
v.Images = append(v.Images, RecordImageRef{ID: im.ID, Image: m.img.Compose(im.Image), Name: im.Name, SortOrder: im.SortOrder})
|
||||
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)
|
||||
}
|
||||
}
|
||||
detailCount := make(map[uint32]int, len(detailsByParent))
|
||||
for p, ds := range detailsByParent {
|
||||
detailCount[p] = len(ds)
|
||||
}
|
||||
for _, main := range mains {
|
||||
ref := RecordImageRef{
|
||||
ID: main.ID,
|
||||
Image: m.img.Compose(main.Image),
|
||||
Name: main.Name,
|
||||
SortOrder: main.SortOrder,
|
||||
IsDetail: 0,
|
||||
ParentImageID: 0,
|
||||
DetailCount: detailCount[main.ID],
|
||||
}
|
||||
v.Images = append(v.Images, ref)
|
||||
grp := ImageGroup{Image: ref}
|
||||
for _, d := range detailsByParent[main.ID] {
|
||||
dref := RecordImageRef{
|
||||
ID: d.ID,
|
||||
Image: m.img.Compose(d.Image),
|
||||
Name: d.Name,
|
||||
SortOrder: d.SortOrder,
|
||||
IsDetail: 1,
|
||||
ParentImageID: d.ParentImageID,
|
||||
}
|
||||
grp.Details = append(grp.Details, dref)
|
||||
v.Images = append(v.Images, dref)
|
||||
}
|
||||
v.Groups = append(v.Groups, grp)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
|
||||
func (m *runwayModule) UpdateRecord(ctx context.Context, id uint32, fields map[string]any) error {
|
||||
return m.repo.UpdateRecord(ctx, id, fields)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user