339 lines
8.7 KiB
Go
339 lines
8.7 KiB
Go
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)
|
||
|
||
// GetDisplayStatusByAssetID 根据asset_id查询展示状态(从asset_registry表)
|
||
GetDisplayStatusByAssetID(assetID int64) (int32, 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
|
||
|
||
// UpdateMaterialTypeByLikes 根据点赞数和创建时间更新素材类型
|
||
UpdateMaterialTypeByLikes(assetID int64, likes int32, createdAt 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
|
||
}
|
||
|
||
// GetDisplayStatusByAssetID 根据asset_id查询展示状态(从public.asset_registry表)
|
||
func (r *assetRepository) GetDisplayStatusByAssetID(assetID int64) (int32, error) {
|
||
if assetID <= 0 {
|
||
return 0, errors.New("asset_id must be greater than 0")
|
||
}
|
||
|
||
var registry models.AssetRegistry
|
||
// 直接使用表名查询 public.asset_registry
|
||
if err := r.db.Table("public.asset_registry").Where("asset_id = ?", assetID).First(®istry).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return 0, nil // 没找到返回0,不报错
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
return registry.DisplayStatus, 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
|
||
}
|
||
|
||
// UpdateMaterialTypeByLikes 根据点赞数和创建时间更新素材类型
|
||
func (r *assetRepository) UpdateMaterialTypeByLikes(assetID int64, likes int32, createdAt int64) error {
|
||
if assetID <= 0 {
|
||
return errors.New("asset_id must be greater than 0")
|
||
}
|
||
|
||
now := time.Now().UnixMilli()
|
||
var materialType string
|
||
if likes > 20 {
|
||
materialType = "hot"
|
||
} else if createdAt > 0 && now-createdAt < 3600*1000 && likes >= 10 {
|
||
materialType = "potential"
|
||
} else {
|
||
materialType = "new"
|
||
}
|
||
|
||
return r.db.Model(&models.Asset{}).
|
||
Where("id = ?", assetID).
|
||
UpdateColumn("material_type", materialType).Error
|
||
}
|
||
// 通过关联 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
|
||
}
|