package repository import ( "errors" "time" "github.com/sirupsen/logrus" appErrors "github.com/topfans/backend/pkg/errors" "github.com/topfans/backend/pkg/models" "gorm.io/gorm" ) // AssetRepository 资产Repository接口 type AssetRepository interface { // Create 创建资产 Create(asset *models.Asset) error // GetByID 根据ID查询资产 GetByID(assetID int64) (*models.Asset, error) // GetByIDs 批量查询资产 GetByIDs(assetIDs []int64) ([]*models.Asset, error) // GetByIDAndOwner 根据ID和所有者查询资产(用于权限验证) GetByIDAndOwner(assetID, ownerUID, starID int64) (*models.Asset, error) // GetByOwner 查询用户的资产列表 GetByOwner(ownerUID, starID int64, limit, offset int) ([]*models.Asset, error) // CountByOwner 统计用户的资产数量 CountByOwner(ownerUID, starID int64) (int64, error) // UpdateStatus 更新资产状态 UpdateStatus(assetID int64, status int32) error // UpdateBlockchainInfo 更新区块链信息 UpdateBlockchainInfo(assetID int64, txHash string, blockNumber int64, mintedAt int64) error // IncrementLikeCount 增加点赞数 IncrementLikeCount(assetID int64) error // DecrementLikeCount 减少点赞数 DecrementLikeCount(assetID int64) error // IsExhibiting 检查资产是否正在展出中 IsExhibiting(assetID int64) (bool, error) } // assetRepository 资产Repository实现 type assetRepository struct { db *gorm.DB } // NewAssetRepository 创建资产Repository实例 func NewAssetRepository(db *gorm.DB) AssetRepository { return &assetRepository{ db: db, } } // Create 创建资产 func (r *assetRepository) Create(asset *models.Asset) error { if asset == nil { return errors.New("asset cannot be nil") } if asset.OwnerUID <= 0 { return errors.New("owner_uid must be greater than 0") } if asset.StarID <= 0 { return errors.New("star_id must be greater than 0") } if err := r.db.Create(asset).Error; err != nil { return err } return nil } // GetByID 根据ID查询资产 func (r *assetRepository) GetByID(assetID int64) (*models.Asset, error) { if assetID <= 0 { return nil, errors.New("asset_id must be greater than 0") } var asset models.Asset if err := r.db.Where("id = ? AND is_active = ?", assetID, true). First(&asset).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, appErrors.ErrAssetNotFound } return nil, err } return &asset, nil } // GetByIDs 批量查询资产 func (r *assetRepository) GetByIDs(assetIDs []int64) ([]*models.Asset, error) { if len(assetIDs) == 0 { return []*models.Asset{}, nil } var assets []*models.Asset if err := r.db.Where("id IN ? AND is_active = ?", assetIDs, true). Find(&assets).Error; err != nil { return nil, err } return assets, nil } // GetByIDAndOwner 根据ID和所有者查询资产(用于权限验证) func (r *assetRepository) GetByIDAndOwner(assetID, ownerUID, starID int64) (*models.Asset, error) { if assetID <= 0 { return nil, errors.New("asset_id must be greater than 0") } if ownerUID <= 0 { return nil, errors.New("owner_uid must be greater than 0") } if starID <= 0 { return nil, errors.New("star_id must be greater than 0") } var asset models.Asset if err := r.db.Where("id = ? AND owner_uid = ? AND star_id = ? AND is_active = ?", assetID, ownerUID, starID, true). First(&asset).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, appErrors.ErrAssetNotFound } return nil, err } logrus.WithFields(logrus.Fields{ "owner_uid": ownerUID, "star_id": starID, "asset_id": asset.ID, "name": asset.Name, "cover_url": asset.CoverURL, "info": asset.Info, "status": asset.Status, "tx_hash": asset.TxHash, "block_number": asset.BlockNumber, "minted_at": asset.MintedAt, "created_at": asset.CreatedAt, "updated_at": asset.UpdatedAt, }).Info("GetByIDAndOwner 查询结果") return &asset, nil } // GetByOwner 查询用户的资产列表 func (r *assetRepository) GetByOwner(ownerUID, starID int64, limit, offset int) ([]*models.Asset, error) { if ownerUID <= 0 { return nil, errors.New("owner_uid must be greater than 0") } if starID <= 0 { return nil, errors.New("star_id must be greater than 0") } var assets []*models.Asset query := r.db.Where("owner_uid = ? AND star_id = ? AND is_active = ?", ownerUID, starID, true). Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } if offset > 0 { query = query.Offset(offset) } if err := query.Find(&assets).Error; err != nil { return nil, err } return assets, nil } // CountByOwner 统计用户的资产数量 func (r *assetRepository) CountByOwner(ownerUID, starID int64) (int64, error) { if ownerUID <= 0 { return 0, errors.New("owner_uid must be greater than 0") } if starID <= 0 { return 0, errors.New("star_id must be greater than 0") } var count int64 if err := r.db.Model(&models.Asset{}). Where("owner_uid = ? AND star_id = ? AND is_active = ?", ownerUID, starID, true). Count(&count).Error; err != nil { return 0, err } return count, nil } // UpdateStatus 更新资产状态 func (r *assetRepository) UpdateStatus(assetID int64, status int32) error { if assetID <= 0 { return errors.New("asset_id must be greater than 0") } result := r.db.Model(&models.Asset{}). Where("id = ?", assetID). Update("status", status) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return appErrors.ErrAssetNotFound } return nil } // UpdateBlockchainInfo 更新区块链信息 func (r *assetRepository) UpdateBlockchainInfo(assetID int64, txHash string, blockNumber int64, mintedAt int64) error { if assetID <= 0 { return errors.New("asset_id must be greater than 0") } updates := map[string]interface{}{ "tx_hash": txHash, "block_number": blockNumber, "minted_at": mintedAt, "status": models.AssetStatusActive, } result := r.db.Model(&models.Asset{}). Where("id = ?", assetID). Updates(updates) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return appErrors.ErrAssetNotFound } return nil } // IncrementLikeCount 增加点赞数 func (r *assetRepository) IncrementLikeCount(assetID int64) error { if assetID <= 0 { return errors.New("asset_id must be greater than 0") } return r.db.Model(&models.Asset{}). Where("id = ?", assetID). UpdateColumn("like_count", gorm.Expr("like_count + ?", 1)).Error } // DecrementLikeCount 减少点赞数 func (r *assetRepository) DecrementLikeCount(assetID int64) error { if assetID <= 0 { return errors.New("asset_id must be greater than 0") } return r.db.Model(&models.Asset{}). Where("id = ? AND like_count > ?", assetID, 0). UpdateColumn("like_count", gorm.Expr("like_count - ?", 1)).Error } // IsExhibiting 检查资产是否正在展出中 // 通过关联 exhibitions 表,查询未过期的展出记录 func (r *assetRepository) IsExhibiting(assetID int64) (bool, error) { if assetID <= 0 { return false, errors.New("asset_id must be greater than 0") } var count int64 // 查询 exhibitions 表中是否存在该资产的未过期展出记录 err := r.db.Model(&models.Exhibition{}). Where("asset_id = ? AND expire_at > ?", assetID, time.Now().UnixMilli()). Count(&count).Error if err != nil { return false, err } return count > 0, nil }