package repository import ( "context" "fashionapi/internal/model" "gorm.io/gorm" "gorm.io/gorm/clause" ) // FavoriteRepository 收藏数据访问接口。 type FavoriteRepository interface { // ListPaged 分页取某用户收藏,按收藏时间倒序。 ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]model.Favorite, error) // CountByUser 取某用户收藏总数(分页用)。 CountByUser(ctx context.Context, userID uint32) (int64, error) // Add 新增收藏;同用户同 target 已存在时幂等忽略(ON DUPLICATE KEY DO NOTHING)。 Add(ctx context.Context, f *model.Favorite) error // Remove 删除某用户对某个 target 的收藏。 Remove(ctx context.Context, userID uint32, targetUID string) error // FilterExisting 返回在给定 ids 中、且属于该用户已收藏的 target_uid 子集(列表页打勾用)。 FilterExisting(ctx context.Context, userID uint32, ids []string) ([]string, error) } type favoriteRepository struct { db *gorm.DB } // NewFavoriteRepository 创建收藏仓储。 func NewFavoriteRepository(db *gorm.DB) FavoriteRepository { return &favoriteRepository{db: db} } func (r *favoriteRepository) ListPaged(ctx context.Context, userID uint32, page, perPage int) ([]model.Favorite, error) { var rows []model.Favorite offset := (page - 1) * perPage if offset < 0 { offset = 0 } err := r.db.WithContext(ctx). Where("user_id = ?", userID). Order("created_at DESC"). Offset(offset). Limit(perPage). Find(&rows).Error return rows, err } func (r *favoriteRepository) CountByUser(ctx context.Context, userID uint32) (int64, error) { var n int64 err := r.db.WithContext(ctx). Model(&model.Favorite{}). Where("user_id = ?", userID). Count(&n).Error return n, err } func (r *favoriteRepository) Add(ctx context.Context, f *model.Favorite) error { // 复合唯一索引 (user_id, target_uid) 保证不重复;冲突时忽略而非报错,使接口天然幂等。 return r.db.WithContext(ctx). Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "user_id"}, {Name: "target_uid"}}, DoNothing: true, }).Create(f).Error } func (r *favoriteRepository) Remove(ctx context.Context, userID uint32, targetUID string) error { return r.db.WithContext(ctx). Where("user_id = ? AND target_uid = ?", userID, targetUID). Delete(&model.Favorite{}).Error } func (r *favoriteRepository) FilterExisting(ctx context.Context, userID uint32, ids []string) ([]string, error) { if len(ids) == 0 { return []string{}, nil } var uids []string err := r.db.WithContext(ctx). Model(&model.Favorite{}). Where("user_id = ? AND target_uid IN ?", userID, ids). Pluck("target_uid", &uids).Error return uids, err }