refactor(street): 审核页改为统一网格+勾选成组;移除并入上一张

This commit is contained in:
toom1996
2026-09-21 23:59:59 +08:00
parent 9807752e4e
commit 0d4000bba5
7 changed files with 63 additions and 206 deletions

View File

@ -43,9 +43,6 @@ type ReviewRepository interface {
// 避免出现「副图的副图」破坏不变量(见计划「实现裁决」第 1 条)。
// 幂等:已是 mainImgID 副图的行重复并入不报错。
AttachStreetDraftImages(ctx context.Context, draftID, mainImgID uint32, imgIDs []uint32) error
// AttachPrevStreetDraftImage 把 imgID 并入「同草稿内 sort_order 紧邻的前一行所属组的主图」。
// imgID 是首行(没有上一行)时返回 ErrNotFound。
AttachPrevStreetDraftImage(ctx context.Context, draftID, imgID uint32) error
// DetachStreetDraftImage 把副图恢复为主图(is_detail=0, parent_image_id=0)。
// 对主图调用是幂等成功(无副作用)。
DetachStreetDraftImage(ctx context.Context, draftID, imgID uint32) error
@ -708,52 +705,6 @@ func (r *reviewRepository) AttachStreetDraftImages(ctx context.Context, draftID,
})
}
// AttachPrevStreetDraftImage 把 imgID 并入「同草稿内 sort_order 紧邻的前一行所属组的主图」。
// 折回组主图是刻意的:连续「并入上一张」应链式归并到同一主图,而不是造出副图的副图。
func (r *reviewRepository) AttachPrevStreetDraftImage(ctx context.Context, draftID, imgID uint32) error {
var target uint32
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var cur model.StreetSnapDraftImage
if err := tx.Where("id = ? AND draft_id = ? AND is_deleted = 0", imgID, draftID).First(&cur).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrNotFound
}
return err
}
var prev model.StreetSnapDraftImage
err := tx.Where("draft_id = ? AND is_deleted = 0 AND (sort_order < ? OR (sort_order = ? AND id < ?))",
draftID, cur.SortOrder, cur.SortOrder, cur.ID).
Order("sort_order DESC, id DESC").First(&prev).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrNotFound
}
return err
}
if prev.IsDetail == 1 && prev.ParentImageID != 0 {
target = prev.ParentImageID
} else {
target = prev.ID
}
if target == imgID {
return ErrInvalidImageGroup
}
now := uint32(time.Now().Unix())
if err := tx.Model(&model.StreetSnapDraftImage{}).
Where("draft_id = ? AND is_deleted = 0 AND parent_image_id = ?", draftID, imgID).
Updates(map[string]any{"parent_image_id": target, "updated_at": now}).Error; err != nil {
return err
}
return tx.Model(&model.StreetSnapDraftImage{}).
Where("id = ? AND draft_id = ?", imgID, draftID).
Updates(map[string]any{"is_detail": 1, "parent_image_id": target, "updated_at": now}).Error
})
return err
}
// DetachStreetDraftImage 把副图恢复为主图。对主图调用为幂等成功。
// 拆出的图若自身带着副图,那些副图保持挂在它下面——它重新成为主图,不变量依然成立。
func (r *reviewRepository) DetachStreetDraftImage(ctx context.Context, draftID, imgID uint32) error {

View File

@ -108,22 +108,6 @@ func TestStreetMainDetail(t *testing.T) {
t.Fatalf("对主图拆出应幂等成功: %v", err)
}
// 并入上一张:d3 的前一行是 d2(d2 已是 m1 的副图)→ 目标应折回 m1。
if err := repo.AttachPrevStreetDraftImage(ctx, draftID, d3); err != nil {
t.Fatalf("并入上一张失败: %v", err)
}
for _, im := range reloadStreetImages(t, repo, draftID) {
if im.ID == d3 && (im.IsDetail != 1 || im.ParentImageID != m1) {
t.Fatalf("并入上一张应折回主图 %d,实际 is_detail=%d parent=%d", m1, im.IsDetail, im.ParentImageID)
}
}
// 首行「并入上一张」应返回 ErrNotFound。
first := seedStreetDraftImage(t, repo, draftID, "z", 0)
if err := repo.AttachPrevStreetDraftImage(ctx, draftID, first); !errors.Is(err, ErrNotFound) {
t.Fatalf("首行并入上一张应返回 ErrNotFound,实际 %v", err)
}
// 跨草稿拦截:空集合 + 跨草稿主图。
if err := repo.AttachStreetDraftImages(ctx, draftID, m1, nil); !errors.Is(err, ErrInvalidImageGroup) {
t.Fatalf("空集合应返回 ErrInvalidImageGroup,实际 %v", err)