Enhance ProductRoutes to include component report handling and related routes
This commit is contained in:
1001
docs/产品示例报告下载功能实现方案.md
Normal file
1001
docs/产品示例报告下载功能实现方案.md
Normal file
File diff suppressed because it is too large
Load Diff
34
internal/domains/product/entities/component_report_cache.go
Normal file
34
internal/domains/product/entities/component_report_cache.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package entities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComponentReportCache 报告文件匹配缓存
|
||||||
|
type ComponentReportCache struct {
|
||||||
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"缓存ID"`
|
||||||
|
ProductCode string `gorm:"type:varchar(50);not null;uniqueIndex" json:"product_code" comment:"产品编号"`
|
||||||
|
MatchedPath string `gorm:"type:varchar(500);not null" json:"matched_path" comment:"匹配到的文件夹/文件路径"`
|
||||||
|
FileType string `gorm:"type:varchar(20);not null" json:"file_type" comment:"文件类型:folder, file"`
|
||||||
|
CacheKey string `gorm:"type:varchar(64);not null;uniqueIndex" json:"cache_key" comment:"缓存键"`
|
||||||
|
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 指定数据库表名
|
||||||
|
func (ComponentReportCache) TableName() string {
|
||||||
|
return "component_report_cache"
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||||
|
func (c *ComponentReportCache) BeforeCreate(tx *gorm.DB) error {
|
||||||
|
if c.ID == "" {
|
||||||
|
c.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package entities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComponentReportDownload 组件报告下载记录
|
||||||
|
type ComponentReportDownload struct {
|
||||||
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"下载记录ID"`
|
||||||
|
UserID string `gorm:"type:varchar(36);not null;index" json:"user_id" comment:"用户ID"`
|
||||||
|
ProductID string `gorm:"type:varchar(36);not null;index" json:"product_id" comment:"产品ID"`
|
||||||
|
ProductCode string `gorm:"type:varchar(50);not null;index" json:"product_code" comment:"产品编号"`
|
||||||
|
SubProductIDs string `gorm:"type:text" json:"sub_product_ids" comment:"子产品ID列表(JSON数组)"`
|
||||||
|
SubProductCodes string `gorm:"type:text" json:"sub_product_codes" comment:"子产品编号列表(JSON数组)"`
|
||||||
|
DownloadPrice decimal.Decimal `gorm:"type:decimal(10,2);not null" json:"download_price" comment:"实际支付价格"`
|
||||||
|
OriginalPrice decimal.Decimal `gorm:"type:decimal(10,2);not null" json:"original_price" comment:"原始总价"`
|
||||||
|
DiscountAmount decimal.Decimal `gorm:"type:decimal(10,2);default:0" json:"discount_amount" comment:"减免金额"`
|
||||||
|
PaymentOrderID *string `gorm:"type:varchar(64)" json:"payment_order_id,omitempty" comment:"支付订单号"`
|
||||||
|
PaymentType *string `gorm:"type:varchar(20)" json:"payment_type,omitempty" comment:"支付类型:alipay, wechat"`
|
||||||
|
PaymentStatus string `gorm:"type:varchar(20);default:'pending';index" json:"payment_status" comment:"支付状态:pending, success, failed"`
|
||||||
|
FilePath *string `gorm:"type:varchar(500)" json:"file_path,omitempty" comment:"生成的ZIP文件路径"`
|
||||||
|
FileHash *string `gorm:"type:varchar(64)" json:"file_hash,omitempty" comment:"文件哈希值"`
|
||||||
|
DownloadCount int `gorm:"default:0" json:"download_count" comment:"下载次数"`
|
||||||
|
LastDownloadAt *time.Time `json:"last_download_at,omitempty" comment:"最后下载时间"`
|
||||||
|
ExpiresAt *time.Time `gorm:"index" json:"expires_at,omitempty" 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:"-" comment:"软删除时间"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName 指定数据库表名
|
||||||
|
func (ComponentReportDownload) TableName() string {
|
||||||
|
return "component_report_downloads"
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||||
|
func (c *ComponentReportDownload) BeforeCreate(tx *gorm.DB) error {
|
||||||
|
if c.ID == "" {
|
||||||
|
c.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPaymentSuccess 检查是否支付成功
|
||||||
|
func (c *ComponentReportDownload) IsPaymentSuccess() bool {
|
||||||
|
return c.PaymentStatus == "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired 检查是否已过期
|
||||||
|
func (c *ComponentReportDownload) IsExpired() bool {
|
||||||
|
if c.ExpiresAt == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return time.Now().After(*c.ExpiresAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanDownload 检查是否可以下载
|
||||||
|
func (c *ComponentReportDownload) CanDownload() bool {
|
||||||
|
return c.IsPaymentSuccess() && !c.IsExpired()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkPaymentSuccess 标记支付成功
|
||||||
|
func (c *ComponentReportDownload) MarkPaymentSuccess(orderID string, paymentType string) {
|
||||||
|
c.PaymentOrderID = &orderID
|
||||||
|
paymentTypeStr := paymentType
|
||||||
|
c.PaymentType = &paymentTypeStr
|
||||||
|
c.PaymentStatus = "success"
|
||||||
|
|
||||||
|
// 设置30天有效期
|
||||||
|
expiresAt := time.Now().Add(30 * 24 * time.Hour)
|
||||||
|
c.ExpiresAt = &expiresAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementDownloadCount 增加下载次数
|
||||||
|
func (c *ComponentReportDownload) IncrementDownloadCount() {
|
||||||
|
c.DownloadCount++
|
||||||
|
now := time.Now()
|
||||||
|
c.LastDownloadAt = &now
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"tyapi-server/internal/domains/product/entities"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComponentReportRepository 组件报告仓储接口
|
||||||
|
type ComponentReportRepository interface {
|
||||||
|
// 下载记录相关
|
||||||
|
CreateDownload(ctx context.Context, download *entities.ComponentReportDownload) (*entities.ComponentReportDownload, error)
|
||||||
|
UpdateDownload(ctx context.Context, download *entities.ComponentReportDownload) error
|
||||||
|
GetDownloadByID(ctx context.Context, id string) (*entities.ComponentReportDownload, error)
|
||||||
|
GetUserDownloads(ctx context.Context, userID string, productID *string) ([]*entities.ComponentReportDownload, error)
|
||||||
|
HasUserDownloaded(ctx context.Context, userID string, productCode string) (bool, error)
|
||||||
|
GetUserDownloadedProductCodes(ctx context.Context, userID string) ([]string, error)
|
||||||
|
GetDownloadByPaymentOrderID(ctx context.Context, orderID string) (*entities.ComponentReportDownload, error)
|
||||||
|
|
||||||
|
// 缓存相关
|
||||||
|
GetCacheByProductCode(ctx context.Context, productCode string) (*entities.ComponentReportCache, error)
|
||||||
|
CreateCache(ctx context.Context, cache *entities.ComponentReportCache) error
|
||||||
|
UpdateCache(ctx context.Context, cache *entities.ComponentReportCache) error
|
||||||
|
}
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
// ProductRoutes 产品路由
|
// ProductRoutes 产品路由
|
||||||
type ProductRoutes struct {
|
type ProductRoutes struct {
|
||||||
productHandler *handlers.ProductHandler
|
productHandler *handlers.ProductHandler
|
||||||
|
componentReportHandler *handlers.ComponentReportHandler
|
||||||
auth *middleware.JWTAuthMiddleware
|
auth *middleware.JWTAuthMiddleware
|
||||||
optionalAuth *middleware.OptionalAuthMiddleware
|
optionalAuth *middleware.OptionalAuthMiddleware
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
@@ -19,12 +20,14 @@ type ProductRoutes struct {
|
|||||||
// NewProductRoutes 创建产品路由
|
// NewProductRoutes 创建产品路由
|
||||||
func NewProductRoutes(
|
func NewProductRoutes(
|
||||||
productHandler *handlers.ProductHandler,
|
productHandler *handlers.ProductHandler,
|
||||||
|
componentReportHandler *handlers.ComponentReportHandler,
|
||||||
auth *middleware.JWTAuthMiddleware,
|
auth *middleware.JWTAuthMiddleware,
|
||||||
optionalAuth *middleware.OptionalAuthMiddleware,
|
optionalAuth *middleware.OptionalAuthMiddleware,
|
||||||
logger *zap.Logger,
|
logger *zap.Logger,
|
||||||
) *ProductRoutes {
|
) *ProductRoutes {
|
||||||
return &ProductRoutes{
|
return &ProductRoutes{
|
||||||
productHandler: productHandler,
|
productHandler: productHandler,
|
||||||
|
componentReportHandler: componentReportHandler,
|
||||||
auth: auth,
|
auth: auth,
|
||||||
optionalAuth: optionalAuth,
|
optionalAuth: optionalAuth,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
@@ -55,6 +58,19 @@ func (r *ProductRoutes) Register(router *sharedhttp.GinRouter) {
|
|||||||
|
|
||||||
// 订阅产品(需要认证)
|
// 订阅产品(需要认证)
|
||||||
products.POST("/:id/subscribe", r.auth.Handle(), r.productHandler.SubscribeProduct)
|
products.POST("/:id/subscribe", r.auth.Handle(), r.productHandler.SubscribeProduct)
|
||||||
|
|
||||||
|
// 组件报告相关路由(需要认证)
|
||||||
|
componentReport := products.Group("/:id/component-report", r.auth.Handle())
|
||||||
|
{
|
||||||
|
// 获取报告下载信息
|
||||||
|
componentReport.GET("/info", r.componentReportHandler.GetReportDownloadInfo)
|
||||||
|
|
||||||
|
// 创建支付订单(暂时注释,后续实现)
|
||||||
|
// componentReport.POST("/create-order", r.componentReportHandler.CreateReportPaymentOrder)
|
||||||
|
|
||||||
|
// 下载报告文件
|
||||||
|
componentReport.GET("/download/:downloadId", r.componentReportHandler.DownloadReport)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分类 - 公开接口
|
// 分类 - 公开接口
|
||||||
@@ -87,6 +103,9 @@ func (r *ProductRoutes) Register(router *sharedhttp.GinRouter) {
|
|||||||
// 取消订阅
|
// 取消订阅
|
||||||
subscriptions.POST("/:id/cancel", r.productHandler.CancelMySubscription)
|
subscriptions.POST("/:id/cancel", r.productHandler.CancelMySubscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 我的组件报告下载历史
|
||||||
|
my.GET("/component-reports", r.componentReportHandler.GetUserDownloadHistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.logger.Info("产品路由注册完成")
|
r.logger.Info("产品路由注册完成")
|
||||||
|
|||||||
Reference in New Issue
Block a user