This commit is contained in:
2025-12-23 15:04:53 +08:00
parent 446a5c7661
commit 6b41f3833a
17 changed files with 355 additions and 172 deletions

View File

@@ -10,12 +10,13 @@ import (
// Subscription 订阅实体
type Subscription struct {
ID string `gorm:"primaryKey;type:varchar(36)" comment:"订阅ID"`
UserID string `gorm:"type:varchar(36);not null;index" comment:"用户ID"`
ProductID string `gorm:"type:varchar(36);not null;index" comment:"产品ID"`
Price decimal.Decimal `gorm:"type:decimal(10,2);not null" comment:"订阅价格"`
APIUsed int64 `gorm:"default:0" comment:"已使用API调用次数"`
Version int64 `gorm:"default:1" comment:"乐观锁版本号"`
ID string `gorm:"primaryKey;type:varchar(36)" comment:"订阅ID"`
UserID string `gorm:"type:varchar(36);not null;index" comment:"用户ID"`
ProductID string `gorm:"type:varchar(36);not null;index" comment:"产品ID"`
Price decimal.Decimal `gorm:"type:decimal(10,2);not null" comment:"订阅价格"`
UIComponentPrice decimal.Decimal `gorm:"type:decimal(10,2);not null;default:0" comment:"UI组件价格组合包使用"`
APIUsed int64 `gorm:"default:0" comment:"已使用API调用次数"`
Version int64 `gorm:"default:1" comment:"乐观锁版本号"`
// 关联关系
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`

View File

@@ -9,22 +9,23 @@ import (
// UIComponent UI组件实体
type UIComponent struct {
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"组件ID"`
ComponentCode string `gorm:"type:varchar(50);not null;uniqueIndex" json:"component_code" comment:"组件编码"`
ComponentName string `gorm:"type:varchar(100);not null" json:"component_name" comment:"组件名称"`
Description string `gorm:"type:text" json:"description" comment:"组件描述"`
FilePath *string `gorm:"type:varchar(500)" json:"file_path" comment:"组件文件路径"`
FileHash *string `gorm:"type:varchar(64)" json:"file_hash" comment:"文件哈希值"`
FileSize *int64 `gorm:"type:bigint" json:"file_size" comment:"文件大小"`
FileType *string `gorm:"type:varchar(50)" json:"file_type" comment:"文件类型"`
FolderPath *string `gorm:"type:varchar(500)" json:"folder_path" comment:"组件文件夹路径"`
IsExtracted bool `gorm:"default:false" json:"is_extracted" comment:"是否已解压"`
Version string `gorm:"type:varchar(20)" json:"version" comment:"组件版本"`
IsActive bool `gorm:"default:true" json:"is_active" comment:"是否启用"`
SortOrder int `gorm:"default:0" json:"sort_order" comment:"排序"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at" comment:"软删除时间"`
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"组件ID"`
ComponentCode string `gorm:"type:varchar(50);not null;uniqueIndex" json:"component_code" comment:"组件编码"`
ComponentName string `gorm:"type:varchar(100);not null" json:"component_name" comment:"组件名称"`
Description string `gorm:"type:text" json:"description" comment:"组件描述"`
FilePath *string `gorm:"type:varchar(500)" json:"file_path" comment:"组件文件路径"`
FileHash *string `gorm:"type:varchar(64)" json:"file_hash" comment:"文件哈希值"`
FileSize *int64 `gorm:"type:bigint" json:"file_size" comment:"文件大小"`
FileType *string `gorm:"type:varchar(50)" json:"file_type" comment:"文件类型"`
FolderPath *string `gorm:"type:varchar(500)" json:"folder_path" comment:"组件文件夹路径"`
IsExtracted bool `gorm:"default:false" json:"is_extracted" comment:"是否已解压"`
FileUploadTime *time.Time `gorm:"type:timestamp" json:"file_upload_time" comment:"文件上传时间"`
Version string `gorm:"type:varchar(20)" json:"version" comment:"组件版本"`
IsActive bool `gorm:"default:true" json:"is_active" comment:"是否启用"`
SortOrder int `gorm:"default:0" json:"sort_order" comment:"排序"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at" comment:"软删除时间"`
}
func (UIComponent) TableName() string {

View File

@@ -104,9 +104,10 @@ func (s *ProductSubscriptionService) CreateSubscription(ctx context.Context, use
// 创建订阅
subscription := &entities.Subscription{
UserID: userID,
ProductID: productID,
Price: product.Price,
UserID: userID,
ProductID: productID,
Price: product.Price,
UIComponentPrice: product.UIComponentPrice,
}
createdSubscription, err := s.subscriptionRepo.Create(ctx, *subscription)
@@ -253,7 +254,7 @@ func (s *ProductSubscriptionService) IncrementSubscriptionAPIUsage(ctx context.C
// GetSubscriptionStats 获取订阅统计信息
func (s *ProductSubscriptionService) GetSubscriptionStats(ctx context.Context) (map[string]interface{}, error) {
stats := make(map[string]interface{})
// 获取总订阅数
totalSubscriptions, err := s.subscriptionRepo.Count(ctx, interfaces.CountOptions{})
if err != nil {
@@ -261,7 +262,7 @@ func (s *ProductSubscriptionService) GetSubscriptionStats(ctx context.Context) (
return nil, fmt.Errorf("获取订阅总数失败: %w", err)
}
stats["total_subscriptions"] = totalSubscriptions
// 获取总收入
totalRevenue, err := s.subscriptionRepo.GetTotalRevenue(ctx)
if err != nil {
@@ -269,30 +270,30 @@ func (s *ProductSubscriptionService) GetSubscriptionStats(ctx context.Context) (
return nil, fmt.Errorf("获取总收入失败: %w", err)
}
stats["total_revenue"] = totalRevenue
return stats, nil
}
// GetUserSubscriptionStats 获取用户订阅统计信息
func (s *ProductSubscriptionService) GetUserSubscriptionStats(ctx context.Context, userID string) (map[string]interface{}, error) {
stats := make(map[string]interface{})
// 获取用户订阅数
userSubscriptions, err := s.subscriptionRepo.FindByUserID(ctx, userID)
if err != nil {
s.logger.Error("获取用户订阅失败", zap.Error(err))
return nil, fmt.Errorf("获取用户订阅失败: %w", err)
}
// 计算用户总收入
var totalRevenue float64
for _, subscription := range userSubscriptions {
totalRevenue += subscription.Price.InexactFloat64()
}
stats["total_subscriptions"] = int64(len(userSubscriptions))
stats["total_revenue"] = totalRevenue
return stats, nil
}
@@ -303,20 +304,47 @@ func (s *ProductSubscriptionService) UpdateSubscriptionPrice(ctx context.Context
if err != nil {
return fmt.Errorf("订阅不存在: %w", err)
}
// 更新价格
subscription.Price = decimal.NewFromFloat(newPrice)
subscription.Version++ // 增加版本号
// 保存更新
if err := s.subscriptionRepo.Update(ctx, subscription); err != nil {
s.logger.Error("更新订阅价格失败", zap.Error(err))
return fmt.Errorf("更新订阅价格失败: %w", err)
}
s.logger.Info("订阅价格更新成功",
zap.String("subscription_id", subscriptionID),
zap.Float64("new_price", newPrice))
return nil
}
// UpdateSubscriptionPriceWithUIComponent 更新订阅价格和UI组件价格
func (s *ProductSubscriptionService) UpdateSubscriptionPriceWithUIComponent(ctx context.Context, subscriptionID string, newPrice float64, newUIComponentPrice float64) error {
// 获取订阅
subscription, err := s.subscriptionRepo.GetByID(ctx, subscriptionID)
if err != nil {
return fmt.Errorf("订阅不存在: %w", err)
}
// 更新价格
subscription.Price = decimal.NewFromFloat(newPrice)
subscription.UIComponentPrice = decimal.NewFromFloat(newUIComponentPrice)
subscription.Version++ // 增加版本号
// 保存更新
if err := s.subscriptionRepo.Update(ctx, subscription); err != nil {
s.logger.Error("更新订阅价格失败", zap.Error(err))
return fmt.Errorf("更新订阅价格失败: %w", err)
}
s.logger.Info("订阅价格更新成功",
zap.String("subscription_id", subscriptionID),
zap.Float64("new_price", newPrice),
zap.Float64("new_ui_component_price", newUIComponentPrice))
return nil
}