package mysqldao import ( "context" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/global" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/mysqlmodel" "gorm.io/gorm" "gorm.io/gorm/clause" ) // LikeDao 点赞数据访问 type LikeDao struct { db *gorm.DB } // NewLikeDao 创建点赞 DAO func NewLikeDao() *LikeDao { return &LikeDao{db: global.MysqlEngine} } // LikeCreate 创建点赞记录 func (d *LikeDao) LikeCreate(ctx context.Context, like *mysqlmodel.Like) error { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeCreate") defer span.End() if err := d.db.WithContext(ctx).Create(like).Error; err != nil { span.RecordError(err) return err } return nil } // LikeUpsertOn 点赞幂等写入:唯一索引冲突时仅置 status=1,防并发重复插入。 func (d *LikeDao) LikeUpsertOn(ctx context.Context, like *mysqlmodel.Like) error { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeUpsertOn") defer span.End() if err := d.db.WithContext(ctx).Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "like_type"}, {Name: "target_id"}, {Name: "user_id"}}, DoUpdates: clause.AssignmentColumns([]string{"status"}), }).Create(like).Error; err != nil { span.RecordError(err) return err } return nil } // LikeUpdateStatus 更新点赞状态(1=已点赞 0=已取消) func (d *LikeDao) LikeUpdateStatus(ctx context.Context, id int64, status int8) error { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeUpdateStatus") defer span.End() if err := d.db.WithContext(ctx).Model(&mysqlmodel.Like{}).Where("id = ?", id).UpdateColumn("status", status).Error; err != nil { span.RecordError(err) return err } return nil } // LikeGetByTargetAndUser 查询用户在目标上的点赞记录 func (d *LikeDao) LikeGetByTargetAndUser(ctx context.Context, likeType int8, targetID, userID int64) (*mysqlmodel.Like, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeGetByTargetAndUser") defer span.End() var like mysqlmodel.Like if err := d.db.WithContext(ctx).Where("like_type = ? AND target_id = ? AND user_id = ?", likeType, targetID, userID).First(&like).Error; err != nil { span.RecordError(err) return nil, err } return &like, nil } // LikeCountByTarget 统计目标点赞数(仅 status=1) func (d *LikeDao) LikeCountByTarget(ctx context.Context, likeType int8, targetID int64) (int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeCountByTarget") defer span.End() var count int64 if err := d.db.WithContext(ctx).Model(&mysqlmodel.Like{}). Where("like_type = ? AND target_id = ? AND status = ?", likeType, targetID, int8(1)). Count(&count).Error; err != nil { span.RecordError(err) return 0, err } return count, nil } // LikeCountByTargets 批量统计多个目标的点赞数(仅 status=1),返回 targetID -> count;空入参短路。 func (d *LikeDao) LikeCountByTargets(ctx context.Context, likeType int8, targetIDs []int64) (map[int64]int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeCountByTargets") defer span.End() counts := make(map[int64]int64, len(targetIDs)) if len(targetIDs) == 0 { return counts, nil } var rows []struct { TargetID int64 `gorm:"column:target_id"` Cnt int64 `gorm:"column:cnt"` } if err := d.db.WithContext(ctx).Model(&mysqlmodel.Like{}). Select("target_id, COUNT(*) AS cnt"). Where("like_type = ? AND target_id IN ? AND status = ?", likeType, targetIDs, int8(1)). Group("target_id"). Scan(&rows).Error; err != nil { span.RecordError(err) return nil, err } for _, r := range rows { counts[r.TargetID] = r.Cnt } return counts, nil } // LikeListUserIDsByTarget 查询点赞用户ID列表(仅 status=1) func (d *LikeDao) LikeListUserIDsByTarget(ctx context.Context, likeType int8, targetID int64) ([]int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.LikeListUserIDsByTarget") defer span.End() var ids []int64 if err := d.db.WithContext(ctx).Model(&mysqlmodel.Like{}). Where("like_type = ? AND target_id = ? AND status = ?", likeType, targetID, int8(1)). Pluck("user_id", &ids).Error; err != nil { span.RecordError(err) return nil, err } return ids, nil }