package repository import ( "context" "errors" "fmt" "carrotskin/internal/model" "gorm.io/gorm" ) // profileRepository ProfileRepository的实现 type profileRepository struct { db *gorm.DB } // NewProfileRepository 创建ProfileRepository实例 func NewProfileRepository(db *gorm.DB) ProfileRepository { return &profileRepository{db: db} } func (r *profileRepository) Create(ctx context.Context, profile *model.Profile) error { return r.db.WithContext(ctx).Create(profile).Error } func (r *profileRepository) FindByUUID(ctx context.Context, uuid string) (*model.Profile, error) { var profile model.Profile err := r.db.WithContext(ctx).Where("uuid = ?", uuid). Preload("Skin"). Preload("Cape"). First(&profile).Error if err != nil { return nil, err } return &profile, nil } func (r *profileRepository) FindByName(ctx context.Context, name string) (*model.Profile, error) { var profile model.Profile // 使用 LOWER 函数进行不区分大小写的查询,并预加载 Skin 和 Cape err := r.db.WithContext(ctx).Where("LOWER(name) = LOWER(?)", name). Preload("Skin"). Preload("Cape"). First(&profile).Error if err != nil { return nil, err } return &profile, nil } func (r *profileRepository) FindByUserID(ctx context.Context, userID int64) ([]*model.Profile, error) { var profiles []*model.Profile err := r.db.WithContext(ctx).Where("user_id = ?", userID). Preload("Skin"). Preload("Cape"). Order("created_at DESC"). Find(&profiles).Error return profiles, err } func (r *profileRepository) FindByUUIDs(ctx context.Context, uuids []string) ([]*model.Profile, error) { if len(uuids) == 0 { return []*model.Profile{}, nil } var profiles []*model.Profile // 使用 IN 查询优化批量查询,并预加载关联 err := r.db.WithContext(ctx).Where("uuid IN ?", uuids). Preload("Skin"). Preload("Cape"). Find(&profiles).Error return profiles, err } func (r *profileRepository) Update(ctx context.Context, profile *model.Profile) error { return r.db.WithContext(ctx).Save(profile).Error } func (r *profileRepository) UpdateFields(ctx context.Context, uuid string, updates map[string]interface{}) error { return r.db.WithContext(ctx).Model(&model.Profile{}). Where("uuid = ?", uuid). Updates(updates).Error } func (r *profileRepository) Delete(ctx context.Context, uuid string) error { return r.db.WithContext(ctx).Where("uuid = ?", uuid).Delete(&model.Profile{}).Error } func (r *profileRepository) BatchUpdate(ctx context.Context, uuids []string, updates map[string]interface{}) (int64, error) { if len(uuids) == 0 { return 0, nil } result := r.db.WithContext(ctx).Model(&model.Profile{}).Where("uuid IN ?", uuids).Updates(updates) return result.RowsAffected, result.Error } func (r *profileRepository) BatchDelete(ctx context.Context, uuids []string) (int64, error) { if len(uuids) == 0 { return 0, nil } result := r.db.WithContext(ctx).Where("uuid IN ?", uuids).Delete(&model.Profile{}) return result.RowsAffected, result.Error } func (r *profileRepository) CountByUserID(ctx context.Context, userID int64) (int64, error) { var count int64 err := r.db.WithContext(ctx).Model(&model.Profile{}). Where("user_id = ?", userID). Count(&count).Error return count, err } func (r *profileRepository) UpdateLastUsedAt(ctx context.Context, uuid string) error { return r.db.WithContext(ctx).Model(&model.Profile{}). Where("uuid = ?", uuid). Update("last_used_at", gorm.Expr("CURRENT_TIMESTAMP")).Error } func (r *profileRepository) GetByNames(ctx context.Context, names []string) ([]*model.Profile, error) { if len(names) == 0 { return []*model.Profile{}, nil } var profiles []*model.Profile // 与 FindByName 保持一致:使用 LOWER() 做大小写不敏感匹配, // 客户端按文档会 toLowerCase 规范化用户名后发送。 err := r.db.WithContext(ctx).Where("LOWER(name) IN (?)", names). Preload("Skin"). Preload("Cape"). Find(&profiles).Error return profiles, err } func (r *profileRepository) GetKeyPair(ctx context.Context, profileId string) (*model.KeyPair, error) { if profileId == "" { return nil, errors.New("参数不能为空") } var profile model.Profile result := r.db.WithContext(ctx). Select("rsa_private_key", "rsa_public_key", "public_key_signature", "public_key_signature_v2", "key_expires_at", "key_refresh_at"). Where("uuid = ?", profileId). First(&profile) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, errors.New("key pair未找到") } return nil, fmt.Errorf("获取key pair失败: %w", result.Error) } keyPair := &model.KeyPair{ PrivateKey: profile.RSAPrivateKey, PublicKey: profile.RSAPublicKey, PublicKeySignature: profile.PublicKeySignature, PublicKeySignatureV2: profile.PublicKeySignatureV2, } if profile.KeyExpiresAt != nil { keyPair.Expiration = *profile.KeyExpiresAt } if profile.KeyRefreshAt != nil { keyPair.Refresh = *profile.KeyRefreshAt } return keyPair, nil } func (r *profileRepository) UpdateKeyPair(ctx context.Context, profileId string, keyPair *model.KeyPair) error { if profileId == "" { return errors.New("profileId 不能为空") } if keyPair == nil { return errors.New("keyPair 不能为 nil") } return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { result := tx.Model(&model.Profile{}). Where("uuid = ?", profileId). Updates(map[string]interface{}{ "rsa_private_key": keyPair.PrivateKey, "rsa_public_key": keyPair.PublicKey, "public_key_signature": keyPair.PublicKeySignature, "public_key_signature_v2": keyPair.PublicKeySignatureV2, "key_expires_at": keyPair.Expiration, "key_refresh_at": keyPair.Refresh, }) if result.Error != nil { return fmt.Errorf("更新 keyPair 失败: %w", result.Error) } return nil }) }