2025-07-15 13:21:34 +08:00
|
|
|
|
package entities
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-07-31 15:41:00 +08:00
|
|
|
|
"errors"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"strings"
|
2025-07-15 13:21:34 +08:00
|
|
|
|
"time"
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
"github.com/google/uuid"
|
2025-07-15 13:21:34 +08:00
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// ProductDocumentation 产品文档实体
|
|
|
|
|
|
type ProductDocumentation struct {
|
2025-07-31 15:41:00 +08:00
|
|
|
|
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:"文档版本"`
|
|
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
// 关联关系
|
|
|
|
|
|
Product *Product `gorm:"foreignKey:ProductID" comment:"产品"`
|
2025-07-31 15:41:00 +08:00
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
CreatedAt time.Time `gorm:"autoCreateTime" comment:"创建时间"`
|
|
|
|
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime" comment:"更新时间"`
|
|
|
|
|
|
DeletedAt gorm.DeletedAt `gorm:"index" comment:"软删除时间"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-20 20:53:26 +08:00
|
|
|
|
// BeforeCreate GORM钩子:创建前自动生成UUID
|
|
|
|
|
|
func (pd *ProductDocumentation) BeforeCreate(tx *gorm.DB) error {
|
|
|
|
|
|
if pd.ID == "" {
|
|
|
|
|
|
pd.ID = uuid.New().String()
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-15 13:21:34 +08:00
|
|
|
|
// IsValid 检查文档是否有效
|
|
|
|
|
|
func (pd *ProductDocumentation) IsValid() bool {
|
|
|
|
|
|
return pd.DeletedAt.Time.IsZero()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateContent 更新文档内容
|
2025-07-31 15:41:00 +08:00
|
|
|
|
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
|
2025-07-15 13:21:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// IncrementVersion 增加版本号
|
|
|
|
|
|
func (pd *ProductDocumentation) IncrementVersion() {
|
|
|
|
|
|
// 简单的版本号递增逻辑,实际项目中可能需要更复杂的版本管理
|
|
|
|
|
|
if pd.Version == "" {
|
|
|
|
|
|
pd.Version = "1.0"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 这里可以实现更复杂的版本号递增逻辑
|
|
|
|
|
|
pd.Version = pd.Version + ".1"
|
|
|
|
|
|
}
|
2025-07-31 15:41:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
}
|