f
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
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)" comment:"下载记录ID"`
|
||||
UserID string `gorm:"type:varchar(36);not null;index" comment:"用户ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;index" comment:"产品ID"`
|
||||
ProductCode string `gorm:"type:varchar(50);not null;index" comment:"产品编号"`
|
||||
ProductName string `gorm:"type:varchar(200);not null" comment:"产品名称"`
|
||||
// 直接关联购买订单
|
||||
OrderID *string `gorm:"type:varchar(36);index" comment:"关联的购买订单ID"`
|
||||
OrderNumber *string `gorm:"type:varchar(64);index" comment:"关联的购买订单号"`
|
||||
|
||||
// 组合包相关字段(从购买记录复制)
|
||||
SubProductIDs string `gorm:"type:text" comment:"子产品ID列表(JSON数组,组合包使用)"`
|
||||
SubProductCodes string `gorm:"type:text" comment:"子产品编号列表(JSON数组)"`
|
||||
|
||||
// 价格相关字段
|
||||
OriginalPrice decimal.Decimal `gorm:"type:decimal(10,2);default:0.00" comment:"原始价格(组合包使用UIComponentPrice,单品使用Price)"`
|
||||
DownloadPrice decimal.Decimal `gorm:"type:decimal(10,2);default:0.00" comment:"实际支付价格"`
|
||||
|
||||
// 下载相关信息
|
||||
FilePath *string `gorm:"type:varchar(500)" comment:"生成的ZIP文件路径(用于二次下载)"`
|
||||
FileHash *string `gorm:"type:varchar(64)" comment:"文件哈希值(用于缓存验证)"`
|
||||
DownloadCount int `gorm:"default:0" comment:"下载次数"`
|
||||
LastDownloadAt *time.Time `comment:"最后下载时间"`
|
||||
ExpiresAt *time.Time `gorm:"index" comment:"下载有效期(从创建日起30天)"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" 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
|
||||
}
|
||||
|
||||
// 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.IsExpired()
|
||||
}
|
||||
153
internal/domains/product/entities/product.go
Normal file
153
internal/domains/product/entities/product.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Product 产品实体
|
||||
type Product struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"产品ID"`
|
||||
OldID *string `gorm:"type:varchar(36);index" comment:"旧产品ID,用于兼容"`
|
||||
Name string `gorm:"type:varchar(100);not null" comment:"产品名称"`
|
||||
Code string `gorm:"type:varchar(50);uniqueIndex;not null" comment:"产品编号"`
|
||||
Description string `gorm:"type:text" comment:"产品简介"`
|
||||
Content string `gorm:"type:text" comment:"产品内容"`
|
||||
CategoryID string `gorm:"type:varchar(36);not null" comment:"一级分类ID"`
|
||||
SubCategoryID *string `gorm:"type:varchar(36);index" comment:"二级分类ID"`
|
||||
Price decimal.Decimal `gorm:"type:decimal(10,2);not null;default:0" comment:"产品价格"`
|
||||
CostPrice decimal.Decimal `gorm:"type:decimal(10,2);default:0" comment:"成本价"`
|
||||
Remark string `gorm:"type:text" comment:"备注"`
|
||||
IsEnabled bool `gorm:"default:false" comment:"是否启用"`
|
||||
IsVisible bool `gorm:"default:false" comment:"是否展示"`
|
||||
IsPackage bool `gorm:"default:false" comment:"是否组合包"`
|
||||
// 组合包相关关联
|
||||
PackageItems []*ProductPackageItem `gorm:"foreignKey:PackageID" comment:"组合包项目列表"`
|
||||
// UI组件相关字段
|
||||
SellUIComponent bool `gorm:"default:false" comment:"是否出售UI组件"`
|
||||
UIComponentPrice decimal.Decimal `gorm:"type:decimal(10,2);default:0" comment:"UI组件销售价格(组合包使用)"`
|
||||
// SEO信息
|
||||
SEOTitle string `gorm:"type:varchar(200)" comment:"SEO标题"`
|
||||
SEODescription string `gorm:"type:text" comment:"SEO描述"`
|
||||
SEOKeywords string `gorm:"type:text" comment:"SEO关键词"`
|
||||
|
||||
// 关联关系
|
||||
Category *ProductCategory `gorm:"foreignKey:CategoryID" comment:"一级分类"`
|
||||
SubCategory *ProductSubCategory `gorm:"foreignKey:SubCategoryID" comment:"二级分类"`
|
||||
Documentation *ProductDocumentation `gorm:"foreignKey:ProductID" comment:"产品文档"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (p *Product) BeforeCreate(tx *gorm.DB) error {
|
||||
if p.ID == "" {
|
||||
p.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查产品是否有效
|
||||
func (p *Product) IsValid() bool {
|
||||
return p.DeletedAt.Time.IsZero() && p.IsEnabled
|
||||
}
|
||||
|
||||
// IsVisibleToUser 检查产品是否对用户可见
|
||||
func (p *Product) IsVisibleToUser() bool {
|
||||
return p.IsValid() && p.IsVisible
|
||||
}
|
||||
|
||||
// CanBeSubscribed 检查产品是否可以订阅
|
||||
func (p *Product) CanBeSubscribed() bool {
|
||||
return p.IsValid()
|
||||
}
|
||||
|
||||
// UpdateSEO 更新SEO信息
|
||||
func (p *Product) UpdateSEO(title, description, keywords string) {
|
||||
p.SEOTitle = title
|
||||
p.SEODescription = description
|
||||
p.SEOKeywords = keywords
|
||||
}
|
||||
|
||||
// Enable 启用产品
|
||||
func (p *Product) Enable() {
|
||||
p.IsEnabled = true
|
||||
}
|
||||
|
||||
// Disable 禁用产品
|
||||
func (p *Product) Disable() {
|
||||
p.IsEnabled = false
|
||||
}
|
||||
|
||||
// Show 显示产品
|
||||
func (p *Product) Show() {
|
||||
p.IsVisible = true
|
||||
}
|
||||
|
||||
// Hide 隐藏产品
|
||||
func (p *Product) Hide() {
|
||||
p.IsVisible = false
|
||||
}
|
||||
|
||||
// SetAsPackage 设置为组合包
|
||||
func (p *Product) SetAsPackage() {
|
||||
p.IsPackage = true
|
||||
}
|
||||
|
||||
func (p *Product) IsCombo() bool {
|
||||
return p.IsPackage
|
||||
}
|
||||
|
||||
// SetOldID 设置旧ID
|
||||
func (p *Product) SetOldID(oldID string) {
|
||||
p.OldID = &oldID
|
||||
}
|
||||
|
||||
// GetOldID 获取旧ID
|
||||
func (p *Product) GetOldID() string {
|
||||
if p.OldID != nil {
|
||||
return *p.OldID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// HasOldID 检查是否有旧ID
|
||||
func (p *Product) HasOldID() bool {
|
||||
return p.OldID != nil && *p.OldID != ""
|
||||
}
|
||||
|
||||
// HasSubCategory 检查是否有二级分类
|
||||
func (p *Product) HasSubCategory() bool {
|
||||
return p.SubCategoryID != nil && *p.SubCategoryID != ""
|
||||
}
|
||||
|
||||
// GetFullCategoryPath 获取完整分类路径(一级分类/二级分类)
|
||||
func (p *Product) GetFullCategoryPath() string {
|
||||
if p.Category == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if p.SubCategory != nil {
|
||||
return p.Category.Name + " / " + p.SubCategory.Name
|
||||
}
|
||||
|
||||
return p.Category.Name
|
||||
}
|
||||
|
||||
// GetFullCategoryCode 获取完整分类编号(一级分类编号.二级分类编号)
|
||||
func (p *Product) GetFullCategoryCode() string {
|
||||
if p.Category == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if p.SubCategory != nil {
|
||||
return p.Category.Code + "." + p.SubCategory.Code
|
||||
}
|
||||
|
||||
return p.Category.Code
|
||||
}
|
||||
159
internal/domains/product/entities/product_api_config.go
Normal file
159
internal/domains/product/entities/product_api_config.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductApiConfig 产品API配置实体
|
||||
type ProductApiConfig struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"配置ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;uniqueIndex" comment:"产品ID"`
|
||||
|
||||
// 请求参数配置
|
||||
RequestParams string `gorm:"type:json;not null" comment:"请求参数配置JSON"`
|
||||
|
||||
// 响应字段配置
|
||||
ResponseFields string `gorm:"type:json;not null" comment:"响应字段配置JSON"`
|
||||
|
||||
// 响应示例
|
||||
ResponseExample string `gorm:"type:json;not null" comment:"响应示例JSON"`
|
||||
|
||||
// 关联关系
|
||||
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// RequestParam 请求参数结构
|
||||
type RequestParam struct {
|
||||
Name string `json:"name" comment:"参数名称"`
|
||||
Field string `json:"field" comment:"参数字段名"`
|
||||
Type string `json:"type" comment:"参数类型"`
|
||||
Required bool `json:"required" comment:"是否必填"`
|
||||
Description string `json:"description" comment:"参数描述"`
|
||||
Example string `json:"example" comment:"参数示例"`
|
||||
Validation string `json:"validation" comment:"验证规则"`
|
||||
}
|
||||
|
||||
// ResponseField 响应字段结构
|
||||
type ResponseField struct {
|
||||
Name string `json:"name" comment:"字段名称"`
|
||||
Path string `json:"path" comment:"字段路径"`
|
||||
Type string `json:"type" comment:"字段类型"`
|
||||
Description string `json:"description" comment:"字段描述"`
|
||||
Required bool `json:"required" comment:"是否必填"`
|
||||
Example string `json:"example" comment:"字段示例"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (pac *ProductApiConfig) BeforeCreate(tx *gorm.DB) error {
|
||||
if pac.ID == "" {
|
||||
pac.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Validate 验证产品API配置
|
||||
func (pac *ProductApiConfig) Validate() error {
|
||||
if pac.ProductID == "" {
|
||||
return NewValidationError("产品ID不能为空")
|
||||
}
|
||||
if pac.RequestParams == "" {
|
||||
return NewValidationError("请求参数配置不能为空")
|
||||
}
|
||||
if pac.ResponseFields == "" {
|
||||
return NewValidationError("响应字段配置不能为空")
|
||||
}
|
||||
if pac.ResponseExample == "" {
|
||||
return NewValidationError("响应示例不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewValidationError 创建验证错误
|
||||
func NewValidationError(message string) error {
|
||||
return &ValidationError{Message: message}
|
||||
}
|
||||
|
||||
// ValidationError 验证错误
|
||||
type ValidationError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e *ValidationError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// GetRequestParams 获取请求参数列表
|
||||
func (pac *ProductApiConfig) GetRequestParams() ([]RequestParam, error) {
|
||||
var params []RequestParam
|
||||
if pac.RequestParams != "" {
|
||||
err := json.Unmarshal([]byte(pac.RequestParams), ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// SetRequestParams 设置请求参数列表
|
||||
func (pac *ProductApiConfig) SetRequestParams(params []RequestParam) error {
|
||||
data, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pac.RequestParams = string(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetResponseFields 获取响应字段列表
|
||||
func (pac *ProductApiConfig) GetResponseFields() ([]ResponseField, error) {
|
||||
var fields []ResponseField
|
||||
if pac.ResponseFields != "" {
|
||||
err := json.Unmarshal([]byte(pac.ResponseFields), &fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
// SetResponseFields 设置响应字段列表
|
||||
func (pac *ProductApiConfig) SetResponseFields(fields []ResponseField) error {
|
||||
data, err := json.Marshal(fields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pac.ResponseFields = string(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetResponseExample 获取响应示例
|
||||
func (pac *ProductApiConfig) GetResponseExample() (map[string]interface{}, error) {
|
||||
var example map[string]interface{}
|
||||
if pac.ResponseExample != "" {
|
||||
err := json.Unmarshal([]byte(pac.ResponseExample), &example)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return example, nil
|
||||
}
|
||||
|
||||
// SetResponseExample 设置响应示例
|
||||
func (pac *ProductApiConfig) SetResponseExample(example map[string]interface{}) error {
|
||||
data, err := json.Marshal(example)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pac.ResponseExample = string(data)
|
||||
return nil
|
||||
}
|
||||
65
internal/domains/product/entities/product_category.go
Normal file
65
internal/domains/product/entities/product_category.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductCategory 产品分类实体
|
||||
type ProductCategory struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"分类ID"`
|
||||
Name string `gorm:"type:varchar(100);not null" comment:"分类名称"`
|
||||
Code string `gorm:"type:varchar(50);uniqueIndex;not null" comment:"分类编号"`
|
||||
Description string `gorm:"type:text" comment:"分类描述"`
|
||||
Sort int `gorm:"default:0" comment:"排序"`
|
||||
IsEnabled bool `gorm:"default:true" comment:"是否启用"`
|
||||
IsVisible bool `gorm:"default:true" comment:"是否展示"`
|
||||
|
||||
// 关联关系
|
||||
Products []Product `gorm:"foreignKey:CategoryID" comment:"产品列表"`
|
||||
SubCategories []ProductSubCategory `gorm:"foreignKey:CategoryID" comment:"二级分类列表"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (pc *ProductCategory) BeforeCreate(tx *gorm.DB) error {
|
||||
if pc.ID == "" {
|
||||
pc.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查分类是否有效
|
||||
func (pc *ProductCategory) IsValid() bool {
|
||||
return pc.DeletedAt.Time.IsZero() && pc.IsEnabled
|
||||
}
|
||||
|
||||
// IsVisibleToUser 检查分类是否对用户可见
|
||||
func (pc *ProductCategory) IsVisibleToUser() bool {
|
||||
return pc.IsValid() && pc.IsVisible
|
||||
}
|
||||
|
||||
// Enable 启用分类
|
||||
func (pc *ProductCategory) Enable() {
|
||||
pc.IsEnabled = true
|
||||
}
|
||||
|
||||
// Disable 禁用分类
|
||||
func (pc *ProductCategory) Disable() {
|
||||
pc.IsEnabled = false
|
||||
}
|
||||
|
||||
// Show 显示分类
|
||||
func (pc *ProductCategory) Show() {
|
||||
pc.IsVisible = true
|
||||
}
|
||||
|
||||
// Hide 隐藏分类
|
||||
func (pc *ProductCategory) Hide() {
|
||||
pc.IsVisible = false
|
||||
}
|
||||
249
internal/domains/product/entities/product_documentation.go
Normal file
249
internal/domains/product/entities/product_documentation.go
Normal file
@@ -0,0 +1,249 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductDocumentation 产品文档实体
|
||||
type ProductDocumentation struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"文档ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;uniqueIndex" comment:"产品ID"`
|
||||
RequestURL string `gorm:"type:varchar(500);not null" comment:"请求链接"`
|
||||
RequestMethod string `gorm:"type:varchar(20);not null" comment:"请求方法"`
|
||||
BasicInfo string `gorm:"type:text" comment:"基础说明(请求头配置、参数加密等)"`
|
||||
RequestParams string `gorm:"type:text" comment:"请求参数"`
|
||||
ResponseFields string `gorm:"type:text" comment:"返回字段说明"`
|
||||
ResponseExample string `gorm:"type:text" comment:"响应示例"`
|
||||
ErrorCodes string `gorm:"type:text" comment:"错误代码"`
|
||||
Version string `gorm:"type:varchar(20);default:'1.0'" comment:"文档版本"`
|
||||
PDFFilePath string `gorm:"type:varchar(500)" comment:"PDF文档文件路径或URL"`
|
||||
|
||||
// 关联关系
|
||||
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (pd *ProductDocumentation) BeforeCreate(tx *gorm.DB) error {
|
||||
if pd.ID == "" {
|
||||
pd.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查文档是否有效
|
||||
func (pd *ProductDocumentation) IsValid() bool {
|
||||
return pd.DeletedAt.Time.IsZero()
|
||||
}
|
||||
|
||||
// UpdateContent 更新文档内容
|
||||
func (pd *ProductDocumentation) UpdateContent(requestURL, requestMethod, basicInfo, requestParams, responseFields, responseExample, errorCodes string) {
|
||||
pd.RequestURL = requestURL
|
||||
pd.RequestMethod = requestMethod
|
||||
pd.BasicInfo = basicInfo
|
||||
pd.RequestParams = requestParams
|
||||
pd.ResponseFields = responseFields
|
||||
pd.ResponseExample = responseExample
|
||||
pd.ErrorCodes = errorCodes
|
||||
}
|
||||
|
||||
// IncrementVersion 增加版本号
|
||||
func (pd *ProductDocumentation) IncrementVersion() {
|
||||
if pd.Version == "" {
|
||||
pd.Version = "1.0"
|
||||
return
|
||||
}
|
||||
|
||||
// 解析版本号 major.minor
|
||||
parts := strings.Split(pd.Version, ".")
|
||||
if len(parts) < 2 {
|
||||
// 如果格式不正确,重置为 1.0
|
||||
pd.Version = "1.0"
|
||||
return
|
||||
}
|
||||
|
||||
// 解析 major 和 minor
|
||||
var major, minor int
|
||||
_, err := fmt.Sscanf(parts[0], "%d", &major)
|
||||
if err != nil {
|
||||
pd.Version = "1.0"
|
||||
return
|
||||
}
|
||||
_, err = fmt.Sscanf(parts[1], "%d", &minor)
|
||||
if err != nil {
|
||||
pd.Version = "1.0"
|
||||
return
|
||||
}
|
||||
|
||||
// 递增 minor
|
||||
minor++
|
||||
// 如果 minor 达到 10,则 major +1,minor 重置为 0
|
||||
if minor >= 10 {
|
||||
major++
|
||||
minor = 0
|
||||
}
|
||||
|
||||
// 更新版本号
|
||||
pd.Version = fmt.Sprintf("%d.%d", major, minor)
|
||||
}
|
||||
|
||||
// Validate 验证文档完整性
|
||||
func (pd *ProductDocumentation) Validate() error {
|
||||
if pd.RequestURL == "" {
|
||||
return errors.New("请求链接不能为空")
|
||||
}
|
||||
if pd.RequestMethod == "" {
|
||||
return errors.New("请求方法不能为空")
|
||||
}
|
||||
if pd.ProductID == "" {
|
||||
return errors.New("产品ID不能为空")
|
||||
}
|
||||
|
||||
// 验证请求方法
|
||||
validMethods := []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
|
||||
methodValid := false
|
||||
for _, method := range validMethods {
|
||||
if strings.ToUpper(pd.RequestMethod) == method {
|
||||
methodValid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !methodValid {
|
||||
return fmt.Errorf("无效的请求方法: %s", pd.RequestMethod)
|
||||
}
|
||||
|
||||
// 验证URL格式(简单验证)
|
||||
if !strings.HasPrefix(pd.RequestURL, "http://") && !strings.HasPrefix(pd.RequestURL, "https://") {
|
||||
return errors.New("请求链接必须以http://或https://开头")
|
||||
}
|
||||
|
||||
// 验证版本号格式
|
||||
if pd.Version != "" {
|
||||
if !isValidVersion(pd.Version) {
|
||||
return fmt.Errorf("无效的版本号格式: %s", pd.Version)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanPublish 检查是否可以发布
|
||||
func (pd *ProductDocumentation) CanPublish() error {
|
||||
if err := pd.Validate(); err != nil {
|
||||
return fmt.Errorf("文档验证失败: %w", err)
|
||||
}
|
||||
if pd.BasicInfo == "" {
|
||||
return errors.New("基础说明不能为空")
|
||||
}
|
||||
if pd.RequestParams == "" {
|
||||
return errors.New("请求参数不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateDocumentation 更新文档内容并自动递增版本
|
||||
func (pd *ProductDocumentation) UpdateDocumentation(requestURL, requestMethod, basicInfo, requestParams, responseFields, responseExample, errorCodes string) error {
|
||||
// 验证必填字段
|
||||
if requestURL == "" || requestMethod == "" {
|
||||
return errors.New("请求链接和请求方法不能为空")
|
||||
}
|
||||
|
||||
// 更新内容
|
||||
pd.UpdateContent(requestURL, requestMethod, basicInfo, requestParams, responseFields, responseExample, errorCodes)
|
||||
|
||||
// 自动递增版本
|
||||
pd.IncrementVersion()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDocumentationSummary 获取文档摘要
|
||||
func (pd *ProductDocumentation) GetDocumentationSummary() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": pd.ID,
|
||||
"product_id": pd.ProductID,
|
||||
"request_url": pd.RequestURL,
|
||||
"method": pd.RequestMethod,
|
||||
"version": pd.Version,
|
||||
"created_at": pd.CreatedAt,
|
||||
"updated_at": pd.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// HasRequiredFields 检查是否包含必需字段
|
||||
func (pd *ProductDocumentation) HasRequiredFields() bool {
|
||||
return pd.RequestURL != "" &&
|
||||
pd.RequestMethod != "" &&
|
||||
pd.ProductID != "" &&
|
||||
pd.BasicInfo != "" &&
|
||||
pd.RequestParams != ""
|
||||
}
|
||||
|
||||
// IsComplete 检查文档是否完整
|
||||
func (pd *ProductDocumentation) IsComplete() bool {
|
||||
return pd.HasRequiredFields() &&
|
||||
pd.ResponseFields != "" &&
|
||||
pd.ResponseExample != "" &&
|
||||
pd.ErrorCodes != ""
|
||||
}
|
||||
|
||||
// GetCompletionPercentage 获取文档完成度百分比
|
||||
func (pd *ProductDocumentation) GetCompletionPercentage() int {
|
||||
totalFields := 8 // 总字段数
|
||||
completedFields := 0
|
||||
|
||||
if pd.RequestURL != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.RequestMethod != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.BasicInfo != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.RequestParams != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.ResponseFields != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.ResponseExample != "" {
|
||||
completedFields++
|
||||
}
|
||||
if pd.ErrorCodes != "" {
|
||||
completedFields++
|
||||
}
|
||||
return (completedFields * 100) / totalFields
|
||||
}
|
||||
|
||||
// isValidVersion 验证版本号格式
|
||||
func isValidVersion(version string) bool {
|
||||
// 简单的版本号验证:x.y.z 格式
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) < 1 || len(parts) > 3 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
return false
|
||||
}
|
||||
// 检查是否为数字
|
||||
for _, char := range part {
|
||||
if char < '0' || char > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
32
internal/domains/product/entities/product_package_item.go
Normal file
32
internal/domains/product/entities/product_package_item.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductPackageItem 产品组合包项目
|
||||
type ProductPackageItem struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)"`
|
||||
PackageID string `gorm:"type:varchar(36);not null;index" comment:"组合包产品ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;index" comment:"子产品ID"`
|
||||
SortOrder int `gorm:"default:0" comment:"排序"`
|
||||
|
||||
// 关联关系
|
||||
Package *Product `gorm:"foreignKey:PackageID" comment:"组合包产品"`
|
||||
Product *Product `gorm:"foreignKey:ProductID" comment:"子产品"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (ppi *ProductPackageItem) BeforeCreate(tx *gorm.DB) error {
|
||||
if ppi.ID == "" {
|
||||
ppi.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
53
internal/domains/product/entities/product_parameter.go
Normal file
53
internal/domains/product/entities/product_parameter.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductParameter 产品参数配置实体
|
||||
type ProductParameter struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"参数配置ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;index" comment:"产品ID"`
|
||||
Name string `gorm:"type:varchar(100);not null" comment:"参数名称"`
|
||||
Field string `gorm:"type:varchar(50);not null" comment:"参数字段名"`
|
||||
Type string `gorm:"type:varchar(20);not null;default:'string'" comment:"参数类型"`
|
||||
Required bool `gorm:"default:true" comment:"是否必填"`
|
||||
Description string `gorm:"type:text" comment:"参数描述"`
|
||||
Example string `gorm:"type:varchar(200)" comment:"参数示例"`
|
||||
Validation string `gorm:"type:text" comment:"验证规则"`
|
||||
SortOrder int `gorm:"default:0" comment:"排序"`
|
||||
|
||||
// 关联关系
|
||||
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (pp *ProductParameter) BeforeCreate(tx *gorm.DB) error {
|
||||
if pp.ID == "" {
|
||||
pp.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查参数配置是否有效
|
||||
func (pp *ProductParameter) IsValid() bool {
|
||||
return pp.DeletedAt.Time.IsZero()
|
||||
}
|
||||
|
||||
// GetValidationRules 获取验证规则
|
||||
func (pp *ProductParameter) GetValidationRules() map[string]interface{} {
|
||||
if pp.Validation == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 这里可以解析JSON格式的验证规则
|
||||
// 暂时返回空map,后续可以扩展
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
82
internal/domains/product/entities/product_sub_category.go
Normal file
82
internal/domains/product/entities/product_sub_category.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductSubCategory 产品二级分类实体
|
||||
type ProductSubCategory struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"二级分类ID"`
|
||||
Name string `gorm:"type:varchar(100);not null" comment:"二级分类名称"`
|
||||
Code string `gorm:"type:varchar(50);uniqueIndex;not null" comment:"二级分类编号"`
|
||||
Description string `gorm:"type:text" comment:"二级分类描述"`
|
||||
CategoryID string `gorm:"type:varchar(36);not null;index" comment:"一级分类ID"`
|
||||
Sort int `gorm:"default:0" comment:"排序"`
|
||||
IsEnabled bool `gorm:"default:true" comment:"是否启用"`
|
||||
IsVisible bool `gorm:"default:true" comment:"是否展示"`
|
||||
|
||||
// 关联关系
|
||||
Category *ProductCategory `gorm:"foreignKey:CategoryID" comment:"一级分类"`
|
||||
Products []Product `gorm:"foreignKey:SubCategoryID" comment:"产品列表"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (psc *ProductSubCategory) BeforeCreate(tx *gorm.DB) error {
|
||||
if psc.ID == "" {
|
||||
psc.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查二级分类是否有效
|
||||
func (psc *ProductSubCategory) IsValid() bool {
|
||||
return psc.DeletedAt.Time.IsZero() && psc.IsEnabled
|
||||
}
|
||||
|
||||
// IsVisibleToUser 检查二级分类是否对用户可见
|
||||
func (psc *ProductSubCategory) IsVisibleToUser() bool {
|
||||
return psc.IsValid() && psc.IsVisible
|
||||
}
|
||||
|
||||
// Enable 启用二级分类
|
||||
func (psc *ProductSubCategory) Enable() {
|
||||
psc.IsEnabled = true
|
||||
}
|
||||
|
||||
// Disable 禁用二级分类
|
||||
func (psc *ProductSubCategory) Disable() {
|
||||
psc.IsEnabled = false
|
||||
}
|
||||
|
||||
// Show 显示二级分类
|
||||
func (psc *ProductSubCategory) Show() {
|
||||
psc.IsVisible = true
|
||||
}
|
||||
|
||||
// Hide 隐藏二级分类
|
||||
func (psc *ProductSubCategory) Hide() {
|
||||
psc.IsVisible = false
|
||||
}
|
||||
|
||||
// GetFullPath 获取完整路径(一级分类/二级分类)
|
||||
func (psc *ProductSubCategory) GetFullPath() string {
|
||||
if psc.Category != nil {
|
||||
return psc.Category.Name + " / " + psc.Name
|
||||
}
|
||||
return psc.Name
|
||||
}
|
||||
|
||||
// GetFullCode 获取完整编号(一级分类编号.二级分类编号)
|
||||
func (psc *ProductSubCategory) GetFullCode() string {
|
||||
if psc.Category != nil {
|
||||
return psc.Category.Code + "." + psc.Code
|
||||
}
|
||||
return psc.Code
|
||||
}
|
||||
36
internal/domains/product/entities/product_ui_component.go
Normal file
36
internal/domains/product/entities/product_ui_component.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductUIComponent 产品UI组件关联实体
|
||||
type ProductUIComponent struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(36)" comment:"关联ID"`
|
||||
ProductID string `gorm:"type:varchar(36);not null;index" comment:"产品ID"`
|
||||
UIComponentID string `gorm:"type:varchar(36);not null;index" comment:"UI组件ID"`
|
||||
Price decimal.Decimal `gorm:"type:decimal(10,2);not null;default:0" comment:"销售价格"`
|
||||
IsEnabled bool `gorm:"default:true" comment:"是否启用销售"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
|
||||
// 关联关系
|
||||
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`
|
||||
UIComponent *UIComponent `gorm:"foreignKey:UIComponentID" comment:"UI组件"`
|
||||
}
|
||||
|
||||
func (ProductUIComponent) TableName() string {
|
||||
return "product_ui_components"
|
||||
}
|
||||
|
||||
func (p *ProductUIComponent) BeforeCreate(tx *gorm.DB) error {
|
||||
if p.ID == "" {
|
||||
p.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
52
internal/domains/product/entities/subscription.go
Normal file
52
internal/domains/product/entities/subscription.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 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:"订阅价格"`
|
||||
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:"产品"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (s *Subscription) BeforeCreate(tx *gorm.DB) error {
|
||||
if s.ID == "" {
|
||||
s.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid 检查订阅是否有效
|
||||
func (s *Subscription) IsValid() bool {
|
||||
return s.DeletedAt.Time.IsZero()
|
||||
}
|
||||
|
||||
// IncrementAPIUsage 增加API使用次数
|
||||
func (s *Subscription) IncrementAPIUsage(count int64) {
|
||||
s.APIUsed += count
|
||||
s.Version++ // 增加版本号
|
||||
}
|
||||
|
||||
// ResetAPIUsage 重置API使用次数
|
||||
func (s *Subscription) ResetAPIUsage() {
|
||||
s.APIUsed = 0
|
||||
s.Version++ // 增加版本号
|
||||
}
|
||||
40
internal/domains/product/entities/ui_component.go
Normal file
40
internal/domains/product/entities/ui_component.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 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:"是否已解压"`
|
||||
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 {
|
||||
return "ui_components"
|
||||
}
|
||||
|
||||
func (u *UIComponent) BeforeCreate(tx *gorm.DB) error {
|
||||
if u.ID == "" {
|
||||
u.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user