This commit is contained in:
toom1996
2026-09-07 00:01:48 +08:00
parent b049104a0b
commit 74ba700598
31 changed files with 1113 additions and 606 deletions

View File

@ -3,6 +3,8 @@ package repository
import (
"context"
"errors"
"strconv"
"time"
"fashionapi/internal/dto"
"fashionapi/internal/model"
@ -22,6 +24,20 @@ type StreetSnapRepository interface {
ImagesBySnapIDs(ctx context.Context, ids []uint32) (map[uint32][]model.StreetSnapImage, error)
// Popular 按图片数降序返回热度前 N 个街拍,供 SSG 首页热门街拍使用。
Popular(ctx context.Context, limit int) ([]model.StreetSnap, error)
// GetForEdit 取原始街拍记录与图片,供后台编辑表单预填。
GetForEdit(ctx context.Context, id uint32) (*model.StreetSnap, []model.StreetSnapImage, error)
// UpdateSnap 编辑后更新字段(白名单,杜绝任意列注入)。
UpdateSnap(ctx context.Context, id uint32, fields map[string]any) error
// DeleteSnapImage 软删单张街拍图片。
DeleteSnapImage(ctx context.Context, imageID uint32) error
// GetSnapImageKey 取单张街拍图片的七牛 key(删除前清理用);不存在返回空串。
GetSnapImageKey(ctx context.Context, imageID uint32) (string, error)
// SoftDeleteSnapImages 软删某街拍的全部图片(级联下架用),返回被删图片的 key 列表。
SoftDeleteSnapImages(ctx context.Context, snapID uint32) ([]string, error)
// SetSnapCover 更新街拍封面。
SetSnapCover(ctx context.Context, snapID uint32, image string) error
// SetSnapDeleted 上下架:deleted=1 下架,0 上架。
SetSnapDeleted(ctx context.Context, id uint32, deleted uint8) error
}
type streetSnapRepository struct {
@ -143,3 +159,103 @@ func (r *streetSnapRepository) Popular(ctx context.Context, limit int) ([]model.
}
return rows, nil
}
// ── 后台编辑支持 ──────────────────────────────────────────────────────────────
// snapEditable 后台可编辑的街拍字段白名单(键即列名)。
var snapEditable = map[string]bool{
"title": true,
"year": true,
"city": true,
"cover": true,
}
func (r *streetSnapRepository) GetForEdit(ctx context.Context, id uint32) (*model.StreetSnap, []model.StreetSnapImage, error) {
var snap model.StreetSnap
if err := r.db.WithContext(ctx).Where("id = ? AND is_deleted = 0", id).First(&snap).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil, ErrNotFound
}
return nil, nil, err
}
imgs, err := r.ListImages(ctx, strconv.FormatUint(uint64(id), 10))
if err != nil {
return nil, nil, err
}
return &snap, imgs, nil
}
func (r *streetSnapRepository) UpdateSnap(ctx context.Context, id uint32, fields map[string]any) error {
clean := map[string]any{}
for k, v := range fields {
if snapEditable[k] {
clean[k] = v
}
}
if len(clean) == 0 {
return nil
}
clean["updated_at"] = uint32(time.Now().Unix())
return r.db.WithContext(ctx).
Model(&model.StreetSnap{}).
Where("id = ?", id).
Updates(clean).Error
}
func (r *streetSnapRepository) DeleteSnapImage(ctx context.Context, imageID uint32) error {
return r.db.WithContext(ctx).
Model(&model.StreetSnapImage{}).
Where("id = ? AND is_deleted = 0", imageID).
Updates(map[string]any{"is_deleted": 1, "updated_at": uint32(time.Now().Unix())}).Error
}
func (r *streetSnapRepository) GetSnapImageKey(ctx context.Context, imageID uint32) (string, error) {
var img model.StreetSnapImage
err := r.db.WithContext(ctx).Where("id = ?", imageID).First(&img).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return "", nil
}
if err != nil {
return "", err
}
return img.Image, nil
}
// SoftDeleteSnapImages 软删某街拍的全部图片(级联下架用)。
// 先取非删除图片的 key 列表返回给调用方(用于后续七牛孤儿清理),再统一置 is_deleted=1。
func (r *streetSnapRepository) SoftDeleteSnapImages(ctx context.Context, snapID uint32) ([]string, error) {
var imgs []model.StreetSnapImage
if err := r.db.WithContext(ctx).
Select("image").
Where("snap_id = ? AND is_deleted = 0", snapID).
Find(&imgs).Error; err != nil {
return nil, err
}
keys := make([]string, 0, len(imgs))
for _, im := range imgs {
if im.Image != "" {
keys = append(keys, im.Image)
}
}
if err := r.db.WithContext(ctx).
Model(&model.StreetSnapImage{}).
Where("snap_id = ? AND is_deleted = 0", snapID).
Updates(map[string]any{"is_deleted": 1, "updated_at": uint32(time.Now().Unix())}).Error; err != nil {
return nil, err
}
return keys, nil
}
func (r *streetSnapRepository) SetSnapCover(ctx context.Context, snapID uint32, image string) error {
return r.db.WithContext(ctx).
Model(&model.StreetSnap{}).
Where("id = ?", snapID).
Updates(map[string]any{"cover": image, "updated_at": uint32(time.Now().Unix())}).Error
}
func (r *streetSnapRepository) SetSnapDeleted(ctx context.Context, id uint32, deleted uint8) error {
return r.db.WithContext(ctx).
Model(&model.StreetSnap{}).
Where("id = ?", id).
Updates(map[string]any{"is_deleted": deleted, "updated_at": uint32(time.Now().Unix())}).Error
}