Compare commits
	
		
			47 Commits
		
	
	
		
			feature/fi
			...
			0b18c69e6e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0b18c69e6e | |||
| cef0969b3e | |||
| 2363b2aa83 | |||
| 130c302ad2 | |||
| b5dbc330fc | |||
| 22550f9ac0 | |||
| 71d6db967d | |||
| 1538b52cf7 | |||
| 22d937a4b1 | |||
| 2fe0d11b46 | |||
| 6987b4829b | |||
| d7cbf81799 | |||
| bd7f6d2cfd | |||
| f76641346f | |||
| d248c1a093 | |||
| 9f915c779d | |||
| 58ba52f919 | |||
| 0e1ceaf613 | |||
| 998c1613e4 | |||
| e2d0efe09e | |||
| f6c3e0380d | |||
| e1191b8c05 | |||
| 32186500f5 | |||
| 57dfd12aa5 | |||
| 339b7aca77 | |||
| b8a7f0585a | |||
| 7aa4d3c417 | |||
| 93d399d845 | |||
| ab8f68c799 | |||
| 8cd00367e4 | |||
| db15e16f99 | |||
| 4e54b5fe33 | |||
| d407826f88 | |||
| 848adb5b29 | |||
| f0f15a4df3 | |||
| 1ff465b953 | |||
| 0fc52fe51b | |||
| f6810bafbd | |||
| 6449c7399f | |||
| 670d2b5cb3 | |||
| 04febf36a1 | |||
| 4ef680d917 | |||
| bd25ea3d96 | |||
| 15b7f1ad4e | |||
| dab7b0c811 | |||
| 31a407e241 | |||
| d23a5651af | 
@ -64,7 +64,7 @@ func GetDataType(docParamType string, formatType string) string {
 | 
			
		||||
	case "boolean":
 | 
			
		||||
		return consts.DataTypeBool.String()
 | 
			
		||||
	case "number", "float", "double", "float32", "float64":
 | 
			
		||||
		return consts.DataTypeFloat.String()
 | 
			
		||||
		return consts.DataTypeFloat64.String()
 | 
			
		||||
	case "array":
 | 
			
		||||
		if formatType == "integer" {
 | 
			
		||||
			return consts.DataTypeSliceInt.String()
 | 
			
		||||
 | 
			
		||||
@ -119,21 +119,29 @@ type PathConfigParameter struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:32 2024/7/19
 | 
			
		||||
type Schema struct {
 | 
			
		||||
	Nullable      bool                 `json:"nullable,omitempty"`      // 对于定义的schema,允许发送 null 值。默认值是 false.
 | 
			
		||||
	Discriminator *SchemaDiscriminator `json:"discriminator,omitempty"` // 说白了, 就是一个字段可能是不同的数据结构。。。
 | 
			
		||||
	ReadOnly      bool                 `json:"readOnly,omitempty"`      // 仅与 Schema "properties" 定义有关。 声明此属性是 "readonly" 的。这意味着它可以作为 response 的一部分但不应该作为 request 的一部分被发送。如果一个 property 的 readOnly 被标记为 true 且在 required 列表中,required 将只作用于 response。一个 property 的 readOnly 和 writeOnly 不允许同时被标记为 true。默认值是 false。
 | 
			
		||||
	WriteOnly     bool                 `json:"writeOnly,omitempty"`     // 仅与 Schema "properties" 定义有关。声明此 property 为 "write only"。所以它可以作为 request 的一部分而不应该作为 response 的一部分被发送。如果一个 property 的 writeOnly 被标记为 true 且在 required 列表中,required 将只作用于 request。一个 property 的 readOnly 和 writeOnly 不能同时被标记为 true。默认值是 false。
 | 
			
		||||
	Xml           *XML                 `json:"xml,omitempty"`           // 这只能用于 properties schemas,在root schemas 中没有效果。
 | 
			
		||||
	ExternalDocs  *ExternalDocs        `json:"externalDocs,omitempty"`  // 此 schema 附加的外部文档。
 | 
			
		||||
	Example       string               `json:"example,omitempty"`       // 一个用于示范此 schema实例的示例,可以是任意格式。为了表达无法用 JSON 或 YAML 格式呈现的示例,可以使用 string 类型的值,且在必要的地方需要使用字符转义。
 | 
			
		||||
	Deprecated    bool                 `json:"deprecated,omitempty"`    // 表示一个 schema 是废弃的,应该逐渐被放弃使用。默认值是 false.
 | 
			
		||||
	Properties    map[string]*Property `json:"properties,omitempty"`    // 数据字段 => 数据规则
 | 
			
		||||
	Required      []string             `json:"required,omitempty"`      // 必传属性列表
 | 
			
		||||
	Enum          []any                `json:"enum,omitempty"`          // 枚举值列表
 | 
			
		||||
	Type          string               `json:"type,omitempty"`          // 类型
 | 
			
		||||
	Items         *PropertyXOf         `json:"items,omitempty"`         // items 必须存在如果 type 的值是 array。
 | 
			
		||||
	Ref           string               `json:"$ref,omitempty"`          // 类型引用
 | 
			
		||||
	Format        string               `json:"format,omitempty"`        // 格式化类型
 | 
			
		||||
	Nullable         bool                 `json:"nullable,omitempty"`           // 对于定义的schema,允许发送 null 值。默认值是 false.
 | 
			
		||||
	Discriminator    *SchemaDiscriminator `json:"discriminator,omitempty"`      // 说白了, 就是一个字段可能是不同的数据结构。。。
 | 
			
		||||
	ReadOnly         bool                 `json:"readOnly,omitempty"`           // 仅与 Schema "properties" 定义有关。 声明此属性是 "readonly" 的。这意味着它可以作为 response 的一部分但不应该作为 request 的一部分被发送。如果一个 property 的 readOnly 被标记为 true 且在 required 列表中,required 将只作用于 response。一个 property 的 readOnly 和 writeOnly 不允许同时被标记为 true。默认值是 false。
 | 
			
		||||
	WriteOnly        bool                 `json:"writeOnly,omitempty"`          // 仅与 Schema "properties" 定义有关。声明此 property 为 "write only"。所以它可以作为 request 的一部分而不应该作为 response 的一部分被发送。如果一个 property 的 writeOnly 被标记为 true 且在 required 列表中,required 将只作用于 request。一个 property 的 readOnly 和 writeOnly 不能同时被标记为 true。默认值是 false。
 | 
			
		||||
	Xml              *XML                 `json:"xml,omitempty"`                // 这只能用于 properties schemas,在root schemas 中没有效果。
 | 
			
		||||
	ExternalDocs     *ExternalDocs        `json:"externalDocs,omitempty"`       // 此 schema 附加的外部文档。
 | 
			
		||||
	Example          any                  `json:"example,omitempty"`            // 一个用于示范此 schema实例的示例,可以是任意格式。为了表达无法用 JSON 或 YAML 格式呈现的示例,可以使用 string 类型的值,且在必要的地方需要使用字符转义。
 | 
			
		||||
	Description      string               `json:"description,omitempty"`        // 一个用于示范此 schema实例的示例,可以是任意格式。为了表达无法用 JSON 或 YAML 格式呈现的示例,可以使用 string 类型的值,且在必要的地方需要使用字符转义。
 | 
			
		||||
	Deprecated       bool                 `json:"deprecated,omitempty"`         // 表示一个 schema 是废弃的,应该逐渐被放弃使用。默认值是 false.
 | 
			
		||||
	Properties       map[string]*Property `json:"properties,omitempty"`         // 数据字段 => 数据规则
 | 
			
		||||
	Required         []string             `json:"required,omitempty"`           // 必传属性列表
 | 
			
		||||
	Enum             []any                `json:"enum,omitempty"`               // 枚举值列表
 | 
			
		||||
	XEnumDescription map[string]string    `json:"x-enumDescriptions,omitempty"` // 枚举值描述的扩展, redoc-free支持
 | 
			
		||||
	Type             any                  `json:"type,omitempty"`               // 类型 (string | []string)
 | 
			
		||||
	Items            *PropertyXOf         `json:"items,omitempty"`              // items 必须存在如果 type 的值是 array。
 | 
			
		||||
	OneOf            []*PropertyXOf       `json:"oneOf,omitempty"`              // type 是一个对象, allOf 指向对象描述
 | 
			
		||||
	Ref              string               `json:"$ref,omitempty"`               // 类型引用
 | 
			
		||||
	Format           string               `json:"format,omitempty"`             // 格式化类型
 | 
			
		||||
	Maximum          *int64               `json:"maximum,omitempty"`            // 最大值
 | 
			
		||||
	Minimum          *int64               `json:"minimum,omitempty"`            // 最小值
 | 
			
		||||
	MinLength        *int64               `json:"minLength,omitempty"`          // 字符串最小长度
 | 
			
		||||
	MaxLength        *int64               `json:"maxLength,omitempty"`          // 字符串最大长度
 | 
			
		||||
	Default          any                  `json:"default,omitempty"`            // 默认值
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Property 是从 JSON Schema 提取出来的,但是做了一些调整以适应 OpenAPI Specification。
 | 
			
		||||
@ -142,16 +150,22 @@ type Schema struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:05 2024/7/19
 | 
			
		||||
type Property struct {
 | 
			
		||||
	Type                 string               `json:"type,omitempty"`                 // 数据类型, swagger本身的定义
 | 
			
		||||
	Type                 any                  `json:"type,omitempty"`                 // 数据类型(string | []string), swagger本身的定义
 | 
			
		||||
	Format               string               `json:"format,omitempty"`               // 对应编程语言中的数据类型描述
 | 
			
		||||
	Enum                 []any                `json:"enum,omitempty"`                 // 枚举值列表
 | 
			
		||||
	XEnumDescription     map[string]string    `json:"x-enumDescriptions,omitempty"`   // 枚举值描述的扩展, redoc-free支持
 | 
			
		||||
	Default              any                  `json:"default,omitempty"`              // 默认值 : 不同于 JSON Schema,这个值必须符合定义与相同级别的 Schema 对象 中定义的类型,比如 type 是 string,那么 default 可以是 "foo" 但不能是 1。
 | 
			
		||||
	Description          string               `json:"description,omitempty"`          // 数据描述, CommonMark syntax可以被用来呈现富文本格式.
 | 
			
		||||
	Example              any                  `json:"example,omitempty"`              // 媒体类型的示例。示例对象应该符合此媒体类型的格式, 这里指定的example对象 object is mutually exclusive of the examples object. 而且如果引用的schema也包含示例,在这里指定的example值将会覆盖schema提供的示例。
 | 
			
		||||
	Maximum              *int64               `json:"maximum,omitempty"`              // 最大值
 | 
			
		||||
	Minimum              *int64               `json:"minimum,omitempty"`              // 最小值
 | 
			
		||||
	MinLength            *int64               `json:"minLength,omitempty"`            // 字符串最小长度
 | 
			
		||||
	MaxLength            *int64               `json:"maxLength,omitempty"`            // 字符串最大长度
 | 
			
		||||
	AllOf                []*PropertyXOf       `json:"allOf,omitempty"`                // type 是一个对象, allOf 指向对象描述
 | 
			
		||||
	OneOf                []*PropertyXOf       `json:"oneOf,omitempty"`                // type 是一个对象, allOf 指向对象描述
 | 
			
		||||
	AnyOf                []*PropertyXOf       `json:"anyOf,omitempty"`                // type 是一个对象, allOf 指向对象描述
 | 
			
		||||
	Items                *PropertyXOf         `json:"items,omitempty"`                // items 必须存在如果 type 的值是 array。
 | 
			
		||||
	AdditionalProperties *PropertyXOf         `json:"additionalProperties,omitempty"` // additionalProperties 是一个用于描述模型中包含未在属性列表中定义的额外属性的选项。它允许接受任意的一个或多个键值对。它的作用是为了在模型定义中包含未知或动态属性。通常,在设计 API 时,我们无法预先知道 API 用户会传递什么样的额外属性,这时就可以使用 additionalProperties 功能来灵活地处理这些未知属性。
 | 
			
		||||
	AdditionalProperties any                  `json:"additionalProperties,omitempty"` // additionalProperties(PropertyXOf | bool) 是一个用于描述模型中包含未在属性列表中定义的额外属性的选项。它允许接受任意的一个或多个键值对。它的作用是为了在模型定义中包含未知或动态属性。通常,在设计 API 时,我们无法预先知道 API 用户会传递什么样的额外属性,这时就可以使用 additionalProperties 功能来灵活地处理这些未知属性。
 | 
			
		||||
	Properties           map[string]*Property `json:"properties,omitempty"`           // type = object 时, 定义对象属性
 | 
			
		||||
	Ref                  string               `json:"$ref,omitempty"`                 // 对描述的引用
 | 
			
		||||
}
 | 
			
		||||
@ -162,7 +176,12 @@ type Property struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:13 2024/7/19
 | 
			
		||||
type PropertyXOf struct {
 | 
			
		||||
	Ref string `json:"$ref"` // 引用的结构描述
 | 
			
		||||
	Type    string `json:"type,omitempty"`    // 基础类型
 | 
			
		||||
	Format  string `json:"format,omitempty"`  // 真实类型
 | 
			
		||||
	Maximum *int64 `json:"maximum,omitempty"` // 最大值
 | 
			
		||||
	Minimum *int64 `json:"minimum,omitempty"` // 最小值
 | 
			
		||||
	Ref     string `json:"$ref,omitempty"`    // 引用的结构描述
 | 
			
		||||
	// Items   *PropertyXOf `json:"items,omitempty"`   // 数据每一项已用类型
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验
 | 
			
		||||
@ -208,7 +227,7 @@ type RequestBody struct {
 | 
			
		||||
// Date : 17:21 2024/7/19
 | 
			
		||||
type Media struct {
 | 
			
		||||
	Schema   *Schema              `json:"schema,omitempty"`   // 定义此媒体类型的结构。
 | 
			
		||||
	Example  string               `json:"example,omitempty"`  // 媒体类型的示例。示例对象应该符合此媒体类型的格式, 这里指定的example对象 object is mutually exclusive of the examples object. 而且如果引用的schema也包含示例,在这里指定的example值将会覆盖schema提供的示例。
 | 
			
		||||
	Example  map[string]any       `json:"example,omitempty"`  // 媒体类型的示例。示例对象应该符合此媒体类型的格式, 这里指定的example对象 object is mutually exclusive of the examples object. 而且如果引用的schema也包含示例,在这里指定的example值将会覆盖schema提供的示例。
 | 
			
		||||
	Examples map[string]*Example  `json:"examples,omitempty"` // 媒体类型的示例,每个媒体对象的值都应该匹配它对应的媒体类型的格式。 The examples object is mutually exclusive of the example object. 而且如果引用的schema也包含示例,在这里指定的example值将会覆盖schema提供的示例。
 | 
			
		||||
	Encoding map[string]*Encoding `json:"encoding,omitempty"` // 属性名与编码信息的映射。每个属性名必须存在于schema属性的key中,当媒体类型等于multipart或application/x-www-form-urlencoded时,编码对象信息仅适用于requestBody。
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								define/seagger_ui.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								define/seagger_ui.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
// Package define ...
 | 
			
		||||
//
 | 
			
		||||
// Description : define ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 2025-02-16 13:18
 | 
			
		||||
package define
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	SwaggerUIThemeDefault   = "swaggerUI"     // 文档默认主题
 | 
			
		||||
	SwaggerUIThemeKnife4go  = "knife4go"      // knife4go 主题
 | 
			
		||||
	SwaggerUIThemeYDocLucky = "ydoc-lucky-ui" // YDoc Lucky UI 主题: https://github.com/NoBugBoy/LuckyUI
 | 
			
		||||
	SwaggerUIThemeRedocFree = "redoc-free"    // redoc UI 主题, 开源免费版: https://github.com/Redocly/redoc
 | 
			
		||||
)
 | 
			
		||||
@ -8,26 +8,31 @@
 | 
			
		||||
package define
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	TagJson              = "json"
 | 
			
		||||
	TagXml               = "xml"
 | 
			
		||||
	TagYaml              = "yaml"
 | 
			
		||||
	TagYml               = "yml"
 | 
			
		||||
	TagForm              = "form"
 | 
			
		||||
	TagBinding           = "binding"
 | 
			
		||||
	TagValidate          = "validate"
 | 
			
		||||
	TagErr               = "err"
 | 
			
		||||
	TagMsg               = "msg"
 | 
			
		||||
	TagDesc              = "desc"
 | 
			
		||||
	TagDescription       = "description"
 | 
			
		||||
	TagD                 = "d"
 | 
			
		||||
	TagDefault           = "default"
 | 
			
		||||
	TagDeprecated        = "deprecated"
 | 
			
		||||
	TagSummary           = "summary"
 | 
			
		||||
	TagPath              = "path"          // 接口的请求路径
 | 
			
		||||
	TagMethod            = "method"        // 接口的请求方法
 | 
			
		||||
	TagUriTag            = "tag"           // 接口的tag
 | 
			
		||||
	TagOutputStrict      = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map,非严格模式返回任意值
 | 
			
		||||
	TagErrMsg            = "err"           // 验证失败错误信息tag
 | 
			
		||||
	TagContentType       = "content_type"
 | 
			
		||||
	TagOutputContentType = "output_content_type"
 | 
			
		||||
	TagJson                = "json"
 | 
			
		||||
	TagXml                 = "xml"
 | 
			
		||||
	TagYaml                = "yaml"
 | 
			
		||||
	TagYml                 = "yml"
 | 
			
		||||
	TagForm                = "form"
 | 
			
		||||
	TagBinding             = "binding"
 | 
			
		||||
	TagValidate            = "validate"
 | 
			
		||||
	TagErr                 = "err"
 | 
			
		||||
	TagMsg                 = "msg"
 | 
			
		||||
	TagDc                  = "dc"
 | 
			
		||||
	TagDesc                = "desc"
 | 
			
		||||
	TagDescription         = "description"
 | 
			
		||||
	TagD                   = "d"
 | 
			
		||||
	TagDefault             = "default"
 | 
			
		||||
	TagDeprecated          = "deprecated"
 | 
			
		||||
	TagSummary             = "summary"
 | 
			
		||||
	TagPath                = "path"          // 接口的请求路径
 | 
			
		||||
	TagMethod              = "method"        // 接口的请求方法
 | 
			
		||||
	TagUriTag              = "tag"           // 接口的tag
 | 
			
		||||
	TagOutputStrict        = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map,非严格模式返回任意值
 | 
			
		||||
	TagErrMsg              = "err"           // 验证失败错误信息tag
 | 
			
		||||
	TagExample             = "example"       // 示例值
 | 
			
		||||
	TagEg                  = "eg"            // 示例值
 | 
			
		||||
	TagContentType         = "content_type"
 | 
			
		||||
	TagOutputContentType   = "output_content_type"
 | 
			
		||||
	TagNameOmitempty       = "omitempty"
 | 
			
		||||
	TagNameEnumDescription = "enum-desc" // 枚举值描述: enum1:enum1-desc||enum2:enum2-desc
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										393
									
								
								generate.go
									
									
									
									
									
								
							
							
						
						
									
										393
									
								
								generate.go
									
									
									
									
									
								
							@ -207,7 +207,7 @@ func (g *Generate) AddApiFromInAndOut(uriPrefix string, paramType reflect.Type,
 | 
			
		||||
				Schema: &define.Schema{
 | 
			
		||||
					Ref: g.getSchemaRef(paramSchemaName),
 | 
			
		||||
				},
 | 
			
		||||
				Example:  "",
 | 
			
		||||
				Example:  nil,
 | 
			
		||||
				Examples: nil,
 | 
			
		||||
				Encoding: nil,
 | 
			
		||||
			}
 | 
			
		||||
@ -220,7 +220,7 @@ func (g *Generate) AddApiFromInAndOut(uriPrefix string, paramType reflect.Type,
 | 
			
		||||
			Schema: &define.Schema{
 | 
			
		||||
				Ref: g.getSchemaRef(resultSchemaName),
 | 
			
		||||
			},
 | 
			
		||||
			Example:  "",
 | 
			
		||||
			Example:  nil,
 | 
			
		||||
			Examples: nil,
 | 
			
		||||
			Encoding: nil,
 | 
			
		||||
		}
 | 
			
		||||
@ -270,7 +270,7 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
 | 
			
		||||
		Summary:      baseCfg.Summary,
 | 
			
		||||
		Description:  baseCfg.Description,
 | 
			
		||||
		ExternalDocs: nil,
 | 
			
		||||
		OperationID:  baseCfg.Method + "-" + baseCfg.Uri,
 | 
			
		||||
		OperationID:  baseCfg.Summary + "(" + baseCfg.Method + "-" + strings.ReplaceAll(strings.TrimLeft(baseCfg.Uri, "/"), "/", "-") + ")",
 | 
			
		||||
		Parameters:   make([]*define.PathConfigParameter, 0),
 | 
			
		||||
		RequestBody: &define.RequestBody{
 | 
			
		||||
			Required:    true,
 | 
			
		||||
@ -326,7 +326,12 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
 | 
			
		||||
		baseReqCfg.Parameters = make([]*define.PathConfigParameter, 0)
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < inputType.NumField(); i++ {
 | 
			
		||||
		propertyName := ParseStructField.GetParamName(inputType.Field(i))
 | 
			
		||||
		if inputType.Field(i).Anonymous {
 | 
			
		||||
			// 匿名字段, 直接对齐到当前的父级
 | 
			
		||||
			g.ParseReadConfigParam(requestCfg, baseReqCfg, inputType.Field(i).Type)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
 | 
			
		||||
		if propertyName == "-" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
@ -334,11 +339,46 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
 | 
			
		||||
			// 空Meta字段认为是用来描述元信息的, 忽略
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		convertBaseType, isBaseType := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
 | 
			
		||||
		realInputTypeFormat := inputType.Field(i).Type.String()
 | 
			
		||||
		fieldType := inputType.Field(i).Type
 | 
			
		||||
		/*if inputType.Field(i).Type.Kind() == reflect.Ptr {
 | 
			
		||||
			fieldType = inputType.Field(i).Type.Elem()
 | 
			
		||||
		}*/
 | 
			
		||||
		if isBaseType {
 | 
			
		||||
			// 当做默认基础类型, 默认不会出现 *map *[]
 | 
			
		||||
			itemParam := &define.PathConfigParameter{
 | 
			
		||||
				Name:        propertyName,
 | 
			
		||||
				In:          consts.SwaggerParameterInQuery,
 | 
			
		||||
				Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
				Required:    ValidateRule.IsRequired(inputType.Field(i)),
 | 
			
		||||
				Deprecated:  ParseStructFieldTag.Deprecated(inputType.Field(i)),
 | 
			
		||||
				Schema: &define.Schema{
 | 
			
		||||
					Type:   convertBaseType,
 | 
			
		||||
					Format: realInputTypeFormat,
 | 
			
		||||
				},
 | 
			
		||||
				AllowEmptyValue: false,
 | 
			
		||||
				Style:           "",
 | 
			
		||||
				Explode:         false,
 | 
			
		||||
				AllowReserved:   false,
 | 
			
		||||
			}
 | 
			
		||||
			g.setStructFieldProperty(itemParam.Schema, inputType.Field(i))
 | 
			
		||||
			baseReqCfg.Parameters = append(baseReqCfg.Parameters, itemParam)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if inputType.Field(i).Type.Kind() == reflect.Interface {
 | 
			
		||||
			itemParam := &define.PathConfigParameter{
 | 
			
		||||
				Name:        ParseStructFieldTag.GetParamName(inputType.Field(i)),
 | 
			
		||||
				In:          consts.SwaggerParameterInQuery,
 | 
			
		||||
				Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
				Required:    ValidateRule.IsRequired(inputType.Field(i)),
 | 
			
		||||
				Deprecated:  ParseStructFieldTag.Deprecated(inputType.Field(i)),
 | 
			
		||||
				Schema: &define.Schema{
 | 
			
		||||
					OneOf:  g.anyTypeConfig(inputType.Field(i)).OneOf,
 | 
			
		||||
					Format: realInputTypeFormat,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
			g.setStructFieldProperty(itemParam.Schema, inputType.Field(i))
 | 
			
		||||
			baseReqCfg.Parameters = append(baseReqCfg.Parameters, itemParam)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if inputType.Field(i).Type.Kind() == reflect.Ptr {
 | 
			
		||||
			// 处理指针
 | 
			
		||||
			if inputType.Field(i).Type.Elem().Kind() == reflect.Struct {
 | 
			
		||||
@ -347,9 +387,9 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
 | 
			
		||||
				baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
 | 
			
		||||
					Name:        propertyName,
 | 
			
		||||
					In:          consts.SwaggerParameterInQuery,
 | 
			
		||||
					Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
					Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
					Required:    ValidateRule.IsRequired(inputType.Field(i)),
 | 
			
		||||
					Deprecated:  ParseStructField.Deprecated(inputType.Field(i)),
 | 
			
		||||
					Deprecated:  ParseStructFieldTag.Deprecated(inputType.Field(i)),
 | 
			
		||||
					Schema: &define.Schema{
 | 
			
		||||
						// Format: realInputTypeFormat,
 | 
			
		||||
						Ref: g.getSchemaRef(schemaNameNext),
 | 
			
		||||
@ -359,22 +399,7 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
 | 
			
		||||
					AllowReserved:      false,
 | 
			
		||||
				})
 | 
			
		||||
			} else {
 | 
			
		||||
				// 当做默认基础类型, 默认不会出现 *map *[]
 | 
			
		||||
				baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
 | 
			
		||||
					Name:        propertyName,
 | 
			
		||||
					In:          consts.SwaggerParameterInQuery,
 | 
			
		||||
					Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
					Required:    ValidateRule.IsRequired(inputType.Field(i)),
 | 
			
		||||
					Deprecated:  ParseStructField.Deprecated(inputType.Field(i)),
 | 
			
		||||
					Schema: &define.Schema{
 | 
			
		||||
						Type:   g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
 | 
			
		||||
						Format: realInputTypeFormat,
 | 
			
		||||
					},
 | 
			
		||||
					AllowEmptyValue: false,
 | 
			
		||||
					Style:           "",
 | 
			
		||||
					Explode:         false,
 | 
			
		||||
					AllowReserved:   false,
 | 
			
		||||
				})
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
@ -382,19 +407,20 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
 | 
			
		||||
			fieldType.Kind() == reflect.Map ||
 | 
			
		||||
			fieldType.Kind() == reflect.Array ||
 | 
			
		||||
			fieldType.Kind() == reflect.Slice {
 | 
			
		||||
			// TODO: 完善逻辑解析
 | 
			
		||||
		} else {
 | 
			
		||||
			baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
 | 
			
		||||
				Name:        ParseStructField.GetParamName(inputType.Field(i)),
 | 
			
		||||
				Name:        ParseStructFieldTag.GetParamName(inputType.Field(i)),
 | 
			
		||||
				In:          consts.SwaggerParameterInQuery,
 | 
			
		||||
				Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
				Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
				Required:    ValidateRule.IsRequired(inputType.Field(i)),
 | 
			
		||||
				Deprecated:  ParseStructField.Deprecated(inputType.Field(i)),
 | 
			
		||||
				Deprecated:  ParseStructFieldTag.Deprecated(inputType.Field(i)),
 | 
			
		||||
				Schema: &define.Schema{
 | 
			
		||||
					Type:   g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
 | 
			
		||||
					Items:  nil,
 | 
			
		||||
					Ref:    "",
 | 
			
		||||
					Format: realInputTypeFormat,
 | 
			
		||||
					Type:             convertBaseType,
 | 
			
		||||
					Items:            nil,
 | 
			
		||||
					Ref:              "",
 | 
			
		||||
					Format:           realInputTypeFormat,
 | 
			
		||||
					Enum:             ValidateRule.Enum(inputType.Field(i)),
 | 
			
		||||
					XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)),
 | 
			
		||||
					Example:          ParseStructFieldTag.GetExampleValue(inputType.Field(i)),
 | 
			
		||||
				},
 | 
			
		||||
				AllowEmptyValue: false,
 | 
			
		||||
				Style:           "",
 | 
			
		||||
@ -430,7 +456,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
 | 
			
		||||
	}
 | 
			
		||||
	inputNameArr := strings.Split(inputType.Name(), ".")
 | 
			
		||||
	inputName := inputNameArr[len(inputNameArr)-1]
 | 
			
		||||
	schemaName := strings.ReplaceAll(pkgPath+"."+inputName, "/", "-")
 | 
			
		||||
	schemaName := strings.ReplaceAll(pkgPath+"."+inputName, "/", ".")
 | 
			
		||||
	if schemaName == "-" {
 | 
			
		||||
		// 忽略的属性
 | 
			
		||||
		return schemaName
 | 
			
		||||
@ -461,45 +487,66 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
 | 
			
		||||
	}
 | 
			
		||||
	// 数组
 | 
			
		||||
	if inputType.Kind() == reflect.Slice || inputType.Kind() == reflect.Array {
 | 
			
		||||
		sliceItemType, itemIsBaseType := g.parseSliceItem(schemaName, inputType)
 | 
			
		||||
		propertyXOf := &define.PropertyXOf{}
 | 
			
		||||
		if itemIsBaseType {
 | 
			
		||||
			propertyXOf.Type, _ = g.realBaseType2SwaggerType(sliceItemType)
 | 
			
		||||
			propertyXOf.Format = sliceItemType
 | 
			
		||||
			propertyXOf.Ref = ""
 | 
			
		||||
		} else {
 | 
			
		||||
			propertyXOf.Type = ""
 | 
			
		||||
			propertyXOf.Format = ""
 | 
			
		||||
			propertyXOf.Ref = g.getSchemaRef(sliceItemType)
 | 
			
		||||
		}
 | 
			
		||||
		if len(rootSchemaName) == 0 {
 | 
			
		||||
			g.docData.Components.Schemas[schemaName].Type = consts.SwaggerDataTypeArray
 | 
			
		||||
			sliceItemType := g.parseSliceItem(schemaName, inputType)
 | 
			
		||||
			g.docData.Components.Schemas[schemaName].Items = &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)}
 | 
			
		||||
			g.docData.Components.Schemas[schemaName].Items = propertyXOf
 | 
			
		||||
		} else {
 | 
			
		||||
			sliceItemType := g.parseSliceItem(schemaName, inputType)
 | 
			
		||||
			g.docData.Components.Schemas[rootSchemaName].Properties[schemaName] = &define.Property{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeArray,
 | 
			
		||||
				Format: inputType.String(),
 | 
			
		||||
				Items:  &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)},
 | 
			
		||||
				Items:  propertyXOf,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return schemaName
 | 
			
		||||
	}
 | 
			
		||||
	// 结构体
 | 
			
		||||
	if inputType.Kind() == reflect.Struct {
 | 
			
		||||
		for i := 0; i < inputType.NumField(); i++ {
 | 
			
		||||
			propertyName := ParseStructField.GetParamName(inputType.Field(i))
 | 
			
		||||
			propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
 | 
			
		||||
			if propertyName == "-" {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if inputType.Field(i).Anonymous {
 | 
			
		||||
				// 处理匿名字段
 | 
			
		||||
				g.handleAnonymousField(schemaName, inputType.Field(i))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if inputType.Kind() == reflect.Interface {
 | 
			
		||||
				// 处理interface{}类型参数
 | 
			
		||||
				g.docData.Components.Schemas[schemaName].Properties[propertyName] = g.anyTypeConfig(inputType.Field(i))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if inputType.Field(i).Type.Kind() == reflect.Ptr {
 | 
			
		||||
				// 处理指针
 | 
			
		||||
				if inputType.Field(i).Type.Elem().Kind() == reflect.Struct {
 | 
			
		||||
					// 结构体指针
 | 
			
		||||
					schemaNameNext := g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type.Elem())
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
						// Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
						Ref: g.getSchemaRef(schemaNameNext),
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// 当做默认基础类型, 默认不会出现 *map *[]
 | 
			
		||||
					convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
						Type:        g.realBaseType2SwaggerType(g.realBaseType2SwaggerType(inputType.Field(i).Type.String())),
 | 
			
		||||
						Format:      inputType.Field(i).Type.String(),
 | 
			
		||||
						Default:     ParseStructField.GetDefaultValue(inputType.Field(i)),
 | 
			
		||||
						Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
						Type:   convertBaseType,
 | 
			
		||||
						Format: inputType.Field(i).Type.String(),
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				// 设置参数各种属性
 | 
			
		||||
				g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if inputType.Field(i).Type.Kind() == reflect.Struct ||
 | 
			
		||||
@ -509,36 +556,45 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
 | 
			
		||||
				if inputType.Field(i).Type.Kind() == reflect.Struct ||
 | 
			
		||||
					inputType.Field(i).Type.Kind() == reflect.Map {
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
						Type:        consts.SwaggerDataTypeObject,
 | 
			
		||||
						Format:      inputType.Field(i).Type.String(),
 | 
			
		||||
						Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
						Properties:  map[string]*define.Property{},
 | 
			
		||||
						Type:       consts.SwaggerDataTypeObject,
 | 
			
		||||
						Format:     inputType.Field(i).Type.String(),
 | 
			
		||||
						Properties: map[string]*define.Property{},
 | 
			
		||||
					}
 | 
			
		||||
				} else if inputType.Field(i).Type.Kind() == reflect.Array ||
 | 
			
		||||
					inputType.Field(i).Type.Kind() == reflect.Slice {
 | 
			
		||||
					sliceItemType, itemIsBaseType := g.parseSliceItem(schemaName, inputType.Field(i).Type)
 | 
			
		||||
					propertyXOf := &define.PropertyXOf{}
 | 
			
		||||
					if itemIsBaseType {
 | 
			
		||||
						propertyXOf.Type, _ = g.realBaseType2SwaggerType(sliceItemType)
 | 
			
		||||
						propertyXOf.Format = sliceItemType
 | 
			
		||||
						propertyXOf.Ref = ""
 | 
			
		||||
					} else {
 | 
			
		||||
						propertyXOf.Type = ""
 | 
			
		||||
						propertyXOf.Format = ""
 | 
			
		||||
						propertyXOf.Ref = g.getSchemaRef(sliceItemType)
 | 
			
		||||
					}
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
						Type:        consts.SwaggerDataTypeArray,
 | 
			
		||||
						Format:      inputType.Field(i).Type.String(),
 | 
			
		||||
						Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
						Items: &define.PropertyXOf{
 | 
			
		||||
							Ref: g.getSchemaRef(g.parseSliceItem(schemaName, inputType.Field(i).Type)),
 | 
			
		||||
						},
 | 
			
		||||
						Properties: map[string]*define.Property{},
 | 
			
		||||
						Type:   consts.SwaggerDataTypeArray,
 | 
			
		||||
						Format: inputType.Field(i).Type.String(),
 | 
			
		||||
						Items:  propertyXOf,
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			} else {
 | 
			
		||||
				g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
					Type:        g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
 | 
			
		||||
					Format:      inputType.Field(i).Type.String(),
 | 
			
		||||
					Default:     ParseStructField.GetDefaultValue(inputType.Field(i)),
 | 
			
		||||
					Description: ParseStructField.GetParamDesc(inputType.Field(i)),
 | 
			
		||||
				if inputType.Field(i).Type.Kind() == reflect.Interface {
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = g.anyTypeConfig(inputType.Field(i))
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName].Example = ParseStructFieldTag.GetExampleValue(inputType.Field(i))
 | 
			
		||||
				} else {
 | 
			
		||||
					convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
 | 
			
		||||
						Type:   convertBaseType,
 | 
			
		||||
						Format: inputType.Field(i).Type.String(),
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// 设置参数各种属性
 | 
			
		||||
			g.setStructFieldProperty(schemaName, inputType.Field(i))
 | 
			
		||||
			g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
 | 
			
		||||
		}
 | 
			
		||||
		return schemaName
 | 
			
		||||
	}
 | 
			
		||||
@ -548,7 +604,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
 | 
			
		||||
			// 非基础数据类型
 | 
			
		||||
			return g.AddComponentsSchema(schemaName, inputType.Elem().String(), inputType.Elem())
 | 
			
		||||
		} else {
 | 
			
		||||
			convertType := g.realBaseType2SwaggerType(inputType.String())
 | 
			
		||||
			convertType, _ := g.realBaseType2SwaggerType(inputType.String())
 | 
			
		||||
			g.docData.Components.Schemas[schemaName].Properties[schemaName] = &define.Property{
 | 
			
		||||
				Type:       convertType,
 | 
			
		||||
				Format:     inputType.String(),
 | 
			
		||||
@ -559,26 +615,79 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
 | 
			
		||||
	return schemaName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleAnonymousField 处理匿名字段
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 18:43 2025/2/17
 | 
			
		||||
func (g *Generate) handleAnonymousField(schemaName string, field reflect.StructField) {
 | 
			
		||||
	if !field.Anonymous {
 | 
			
		||||
		// 不是匿名字段
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	handleType := field.Type
 | 
			
		||||
	if handleType.Kind() == reflect.Ptr {
 | 
			
		||||
		handleType = handleType.Elem()
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < handleType.NumField(); i++ {
 | 
			
		||||
		itemField := handleType.Field(i)
 | 
			
		||||
		if itemField.Anonymous {
 | 
			
		||||
			// 递归处理多层嵌套匿名字段
 | 
			
		||||
			g.handleAnonymousField(schemaName, itemField)
 | 
			
		||||
			continue
 | 
			
		||||
		} else {
 | 
			
		||||
			baseConvertType, isBaseType := g.realBaseType2SwaggerType(itemField.Type.String())
 | 
			
		||||
			if !isBaseType {
 | 
			
		||||
				paramName := ParseStructFieldTag.GetParamName(itemField)
 | 
			
		||||
				if itemField.Type.Kind() == reflect.Interface {
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Properties[paramName] = g.anyTypeConfig(itemField)
 | 
			
		||||
				}
 | 
			
		||||
				g.AddComponentsSchema(schemaName, handleType.Field(i).Type.PkgPath(), handleType.Field(i).Type)
 | 
			
		||||
				continue
 | 
			
		||||
			} else {
 | 
			
		||||
				paramName := ParseStructFieldTag.GetParamName(itemField)
 | 
			
		||||
				g.docData.Components.Schemas[schemaName].Properties[paramName] = &define.Property{
 | 
			
		||||
					Type:             baseConvertType,
 | 
			
		||||
					Format:           itemField.Type.String(),
 | 
			
		||||
					Example:          ParseStructFieldTag.GetExampleValue(itemField),
 | 
			
		||||
					Enum:             ValidateRule.Enum(itemField),
 | 
			
		||||
					XEnumDescription: ParseStructFieldTag.EnumDescription(itemField),
 | 
			
		||||
					Default:          ParseStructFieldTag.GetDefaultValue(handleType.Field(i)),
 | 
			
		||||
					Description:      ParseStructFieldTag.GetParamDesc(handleType.Field(i)),
 | 
			
		||||
				}
 | 
			
		||||
				if ValidateRule.IsRequired(itemField) {
 | 
			
		||||
					g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseSliceItem 解析数组每一项
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:33 2025/2/8
 | 
			
		||||
func (g *Generate) parseSliceItem(rootSchemaName string, inputType reflect.Type) string {
 | 
			
		||||
func (g *Generate) parseSliceItem(rootSchemaName string, inputType reflect.Type) (string, bool) {
 | 
			
		||||
	if inputType.Kind() != reflect.Slice && inputType.Kind() != reflect.Array {
 | 
			
		||||
		// 不是数组
 | 
			
		||||
		return ""
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	sliceValue := reflect.MakeSlice(inputType, 1, 1)
 | 
			
		||||
	sliceItemType := sliceValue.Index(0).Type()
 | 
			
		||||
	realSliceItemType := sliceItemType.String()
 | 
			
		||||
	if sliceItemType.Kind() == reflect.Ptr {
 | 
			
		||||
		sliceItemType = sliceItemType.Elem()
 | 
			
		||||
	}
 | 
			
		||||
	_, isBaseType := g.realBaseType2SwaggerType(sliceItemType.String())
 | 
			
		||||
	if isBaseType {
 | 
			
		||||
		return realSliceItemType, true
 | 
			
		||||
	}
 | 
			
		||||
	g.AddComponentsSchema(rootSchemaName, sliceItemType.PkgPath(), sliceItemType)
 | 
			
		||||
	if len(sliceItemType.PkgPath()) == 0 {
 | 
			
		||||
		return sliceItemType.String()
 | 
			
		||||
		return realSliceItemType, false
 | 
			
		||||
	}
 | 
			
		||||
	return sliceItemType.PkgPath() + "." + sliceItemType.Name()
 | 
			
		||||
	return sliceItemType.PkgPath() + "." + sliceItemType.Name(), false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSchemaRef 获取引用的类型
 | 
			
		||||
@ -591,7 +700,11 @@ func (g *Generate) getSchemaRef(schemaName string) string {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	schemaName = strings.ReplaceAll(schemaName, "*", "") // 去除指针类型 *
 | 
			
		||||
	return "#/components/schemas/" + strings.ReplaceAll(schemaName, "/", "-")
 | 
			
		||||
	convertType, isBaseType := g.realBaseType2SwaggerType(schemaName)
 | 
			
		||||
	if isBaseType {
 | 
			
		||||
		return convertType
 | 
			
		||||
	}
 | 
			
		||||
	return "#/components/schemas/" + strings.ReplaceAll(convertType, "/", ".")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// realType2SwaggerType golang 真实数据类型转换为golang数据类型
 | 
			
		||||
@ -599,48 +712,75 @@ func (g *Generate) getSchemaRef(schemaName string) string {
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 20:25 2025/2/11
 | 
			
		||||
func (g *Generate) realBaseType2SwaggerType(realType string) string {
 | 
			
		||||
func (g *Generate) realBaseType2SwaggerType(realType string) (string, bool) {
 | 
			
		||||
	switch realType {
 | 
			
		||||
	case "bool", "*bool":
 | 
			
		||||
		return consts.SwaggerDataTypeBoolean
 | 
			
		||||
		return consts.SwaggerDataTypeBoolean, true
 | 
			
		||||
	case "string", "*string":
 | 
			
		||||
		return consts.SwaggerDataTypeString
 | 
			
		||||
		return consts.SwaggerDataTypeString, true
 | 
			
		||||
	case "byte", "*byte":
 | 
			
		||||
		return consts.SwaggerDataTypeByte
 | 
			
		||||
		return consts.SwaggerDataTypeByte, true
 | 
			
		||||
	case "float32", "*float32", "float64", "*float64":
 | 
			
		||||
		return consts.SwaggerDataTypeDouble
 | 
			
		||||
		return consts.SwaggerDataTypeDouble, true
 | 
			
		||||
	case "int", "*int", "uint", "*uint", "int64", "*int64", "uint64", "*uint64":
 | 
			
		||||
		return consts.SwaggerDataTypeInteger
 | 
			
		||||
		return consts.SwaggerDataTypeInteger, true
 | 
			
		||||
	case "int8", "*int8", "uint8", "*uint8", "int16", "*int16", "uint16", "*uint16", "int32", "*int32", "uint32", "*uint32":
 | 
			
		||||
		return consts.SwaggerDataTypeInteger
 | 
			
		||||
		return consts.SwaggerDataTypeInteger, true
 | 
			
		||||
	default:
 | 
			
		||||
		return realType
 | 
			
		||||
		if strings.HasPrefix(realType, "[]") {
 | 
			
		||||
			return consts.SwaggerDataTypeArray, true
 | 
			
		||||
		}
 | 
			
		||||
		return realType, false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// realType2SwaggerType ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:20 2025/2/11
 | 
			
		||||
func (g *Generate) realType2SwaggerType(realType string) string {
 | 
			
		||||
	if strings.HasPrefix(realType, "[]") {
 | 
			
		||||
		return consts.SwaggerDataTypeArray
 | 
			
		||||
	}
 | 
			
		||||
	return g.realBaseType2SwaggerType(realType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setStructFieldProperty 添加struct_field各种属性
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 16:13 2025/2/13
 | 
			
		||||
func (g *Generate) setStructFieldProperty(schemaName string, structField reflect.StructField) {
 | 
			
		||||
	paramName := ParseStructField.GetParamName(structField)
 | 
			
		||||
	if ValidateRule.IsRequired(structField) {
 | 
			
		||||
		g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName)
 | 
			
		||||
func (g *Generate) setStructFieldProperty(schema *define.Schema, structField reflect.StructField) {
 | 
			
		||||
	paramName := ParseStructFieldTag.GetParamName(structField)
 | 
			
		||||
	if paramName == "" || paramName == "-" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	isRequired := ValidateRule.IsRequired(structField)
 | 
			
		||||
	enum := ValidateRule.Enum(structField)
 | 
			
		||||
	xEnumDescription := ParseStructFieldTag.EnumDescription(structField)
 | 
			
		||||
	example := ParseStructFieldTag.GetExampleValue(structField)
 | 
			
		||||
	description := ParseStructFieldTag.GetParamDesc(structField)
 | 
			
		||||
	maxVal := ValidateRule.Maximum(structField)
 | 
			
		||||
	minVal := ValidateRule.Minimum(structField)
 | 
			
		||||
	if nil != schema {
 | 
			
		||||
		if isRequired {
 | 
			
		||||
			schema.Required = append(schema.Required, paramName)
 | 
			
		||||
		}
 | 
			
		||||
		if nil == schema.Properties[paramName] {
 | 
			
		||||
			if schema.Type == consts.SwaggerDataTypeString {
 | 
			
		||||
				schema.MinLength = minVal
 | 
			
		||||
				schema.MaxLength = maxVal
 | 
			
		||||
			} else {
 | 
			
		||||
				schema.Minimum = minVal
 | 
			
		||||
				schema.Maximum = maxVal
 | 
			
		||||
			}
 | 
			
		||||
			schema.Enum = enum
 | 
			
		||||
			schema.XEnumDescription = xEnumDescription
 | 
			
		||||
			schema.Example = example
 | 
			
		||||
			schema.Description = description
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if schema.Properties[paramName].Type == consts.SwaggerDataTypeString {
 | 
			
		||||
			schema.Properties[paramName].MinLength = minVal
 | 
			
		||||
			schema.Properties[paramName].MaxLength = maxVal
 | 
			
		||||
		} else {
 | 
			
		||||
			schema.Properties[paramName].Minimum = minVal
 | 
			
		||||
			schema.Properties[paramName].Maximum = maxVal
 | 
			
		||||
		}
 | 
			
		||||
		schema.Properties[paramName].Enum = enum
 | 
			
		||||
		schema.Properties[paramName].XEnumDescription = xEnumDescription
 | 
			
		||||
		schema.Properties[paramName].Example = example
 | 
			
		||||
		schema.Properties[paramName].Description = description
 | 
			
		||||
	}
 | 
			
		||||
	g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseBaseUriConfig 通过Meta字段解析Uri基础配置信息
 | 
			
		||||
@ -697,12 +837,75 @@ func (g *Generate) parseBaseUriConfig(uriPrefix string, paramType reflect.Type)
 | 
			
		||||
		responseContentType = consts.MimeTypeJson
 | 
			
		||||
	}
 | 
			
		||||
	res.OutputContentType = strings.Split(responseContentType, ",")
 | 
			
		||||
	res.Summary = ParseStructField.Summary(metaField)
 | 
			
		||||
	res.Summary = ParseStructFieldTag.Summary(metaField)
 | 
			
		||||
	if len(res.Summary) == 0 {
 | 
			
		||||
		res.Summary = wrapper.String(strings.ReplaceAll(strings.TrimLeft(res.Uri, "/"), "/", "_")).SnakeCaseToCamel()
 | 
			
		||||
	}
 | 
			
		||||
	if res.Method == "" {
 | 
			
		||||
		return nil, errors.New("baseCfg.Method is empty")
 | 
			
		||||
	}
 | 
			
		||||
	if res.Uri == "" {
 | 
			
		||||
		return nil, errors.New("baseCfg.Uri is empty")
 | 
			
		||||
	}
 | 
			
		||||
	if nil == g.docData.Tags {
 | 
			
		||||
		g.docData.Tags = make([]*define.TagItem, 0)
 | 
			
		||||
	}
 | 
			
		||||
	// 增加tag
 | 
			
		||||
	for _, itemTag := range res.TagList {
 | 
			
		||||
		exist := false
 | 
			
		||||
		for _, t := range g.docData.Tags {
 | 
			
		||||
			if itemTag == t.Name {
 | 
			
		||||
				exist = true
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !exist {
 | 
			
		||||
			g.docData.Tags = append(g.docData.Tags, &define.TagItem{
 | 
			
		||||
				Name:        itemTag,
 | 
			
		||||
				Description: itemTag,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// anyTypeConfig 任意类型数据配置
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:33 2025/2/19
 | 
			
		||||
func (g *Generate) anyTypeConfig(structField reflect.StructField) *define.Property {
 | 
			
		||||
	return &define.Property{
 | 
			
		||||
		Description: ParseStructFieldTag.GetParamDesc(structField),
 | 
			
		||||
		OneOf: []*define.PropertyXOf{
 | 
			
		||||
			{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeObject,
 | 
			
		||||
				Format: "map[string]any",
 | 
			
		||||
			},
 | 
			
		||||
			/*	{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeArray,
 | 
			
		||||
				Format: "[]any",
 | 
			
		||||
				Items: &define.PropertyXOf{
 | 
			
		||||
					Items: nil,
 | 
			
		||||
				},
 | 
			
		||||
			},*/
 | 
			
		||||
			{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeInteger,
 | 
			
		||||
				Format: "int/uint",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeNumber,
 | 
			
		||||
				Format: "int/uint/float",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeString,
 | 
			
		||||
				Format: "string",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Type:   consts.SwaggerDataTypeBoolean,
 | 
			
		||||
				Format: "bool",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								go.mod
									
									
									
									
									
								
							@ -1,22 +1,65 @@
 | 
			
		||||
module git.zhangdeman.cn/gateway/api-doc
 | 
			
		||||
 | 
			
		||||
go 1.22.2
 | 
			
		||||
go 1.23.0
 | 
			
		||||
 | 
			
		||||
toolchain go1.24.1
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250208020330-a50062af46a1
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
 | 
			
		||||
	github.com/gin-gonic/gin v1.10.0
 | 
			
		||||
	github.com/go-webtools/knife4go v1.0.4
 | 
			
		||||
	github.com/swaggo/files v1.0.1
 | 
			
		||||
	github.com/swaggo/gin-swagger v1.6.0
 | 
			
		||||
	github.com/tidwall/gjson v1.18.0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
 | 
			
		||||
	github.com/BurntSushi/toml v1.4.0 // indirect
 | 
			
		||||
	github.com/BurntSushi/toml v1.5.0 // indirect
 | 
			
		||||
	github.com/KyleBanks/depth v1.2.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/purell v1.2.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
 | 
			
		||||
	github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
 | 
			
		||||
	github.com/bytedance/sonic v1.13.2 // indirect
 | 
			
		||||
	github.com/bytedance/sonic/loader v0.2.4 // indirect
 | 
			
		||||
	github.com/cloudwego/base64x v0.1.5 // indirect
 | 
			
		||||
	github.com/cloudwego/iasm v0.2.0 // indirect
 | 
			
		||||
	github.com/gabriel-vasile/mimetype v1.4.8 // indirect
 | 
			
		||||
	github.com/gin-contrib/sse v1.1.0 // indirect
 | 
			
		||||
	github.com/go-ini/ini v1.67.0 // indirect
 | 
			
		||||
	github.com/go-openapi/jsonpointer v0.21.1 // indirect
 | 
			
		||||
	github.com/go-openapi/jsonreference v0.21.0 // indirect
 | 
			
		||||
	github.com/go-openapi/spec v0.21.0 // indirect
 | 
			
		||||
	github.com/go-openapi/swag v0.23.1 // indirect
 | 
			
		||||
	github.com/go-playground/locales v0.14.1 // indirect
 | 
			
		||||
	github.com/go-playground/universal-translator v0.18.1 // indirect
 | 
			
		||||
	github.com/go-playground/validator/v10 v10.26.0 // indirect
 | 
			
		||||
	github.com/goccy/go-json v0.10.5 // indirect
 | 
			
		||||
	github.com/josharian/intern v1.0.0 // indirect
 | 
			
		||||
	github.com/json-iterator/go v1.1.12 // indirect
 | 
			
		||||
	github.com/klauspost/cpuid/v2 v2.2.10 // indirect
 | 
			
		||||
	github.com/leodido/go-urn v1.4.0 // indirect
 | 
			
		||||
	github.com/mailru/easyjson v0.9.0 // indirect
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.20 // indirect
 | 
			
		||||
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 | 
			
		||||
	github.com/modern-go/reflect2 v1.0.2 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 | 
			
		||||
	github.com/spaolacci/murmur3 v1.1.0 // indirect
 | 
			
		||||
	github.com/swaggo/swag v1.16.4 // indirect
 | 
			
		||||
	github.com/tidwall/match v1.1.1 // indirect
 | 
			
		||||
	github.com/tidwall/pretty v1.2.1 // indirect
 | 
			
		||||
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
			
		||||
	github.com/ugorji/go/codec v1.2.12 // indirect
 | 
			
		||||
	golang.org/x/arch v0.16.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.37.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.39.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.32.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.24.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.32.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.36.6 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										238
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										238
									
								
								go.sum
									
									
									
									
									
								
							@ -1,5 +1,9 @@
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250208020330-a50062af46a1 h1:vv4X72I6s6XcTi0ykj2v/cgMZyseFyE2LkS4WloICCs=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250208020330-a50062af46a1/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250321102241-d6e86b64f7ca h1:uxjzbY5fDozjyK6jkoQtuQouVTcVfXjbe3chARYSjRM=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250321102241-d6e86b64f7ca/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c h1:cl3gQGXQpJ8ugDs0C/hQLfcvF4lGBm5BeABLvROFDoM=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
 | 
			
		||||
@ -8,22 +12,161 @@ git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6Cc
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 h1:yF770WIDNwyiKL0nwmBGmjZvNCLXtHQL4xJyffPjTMU=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9/go.mod h1:I76wxEsWq7KnMQ84elpwTjEqq4I49QFw60tp5h7iGBs=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
 | 
			
		||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
 | 
			
		||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
 | 
			
		||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
 | 
			
		||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
 | 
			
		||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
 | 
			
		||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 | 
			
		||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
 | 
			
		||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
 | 
			
		||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
 | 
			
		||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
 | 
			
		||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
 | 
			
		||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
 | 
			
		||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
 | 
			
		||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
 | 
			
		||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
 | 
			
		||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
 | 
			
		||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
 | 
			
		||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
 | 
			
		||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
 | 
			
		||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
 | 
			
		||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
 | 
			
		||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
 | 
			
		||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
 | 
			
		||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
 | 
			
		||||
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
 | 
			
		||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 | 
			
		||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 | 
			
		||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
 | 
			
		||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
 | 
			
		||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
 | 
			
		||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
 | 
			
		||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
 | 
			
		||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
 | 
			
		||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 | 
			
		||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
 | 
			
		||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
 | 
			
		||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
 | 
			
		||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
 | 
			
		||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
 | 
			
		||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 | 
			
		||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
 | 
			
		||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 | 
			
		||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
 | 
			
		||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
 | 
			
		||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 | 
			
		||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 | 
			
		||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
 | 
			
		||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 | 
			
		||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 | 
			
		||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
 | 
			
		||||
github.com/go-webtools/knife4go v1.0.4 h1:p32SApmM0sx2/Y5p0QfeaGv5KD96R1mj2CaHdyH8jy8=
 | 
			
		||||
github.com/go-webtools/knife4go v1.0.4/go.mod h1:trOlXN1tqBJ7R44sHON3exGvzCwjbsVriIHEenry3d8=
 | 
			
		||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
 | 
			
		||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 | 
			
		||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
 | 
			
		||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 | 
			
		||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 | 
			
		||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 | 
			
		||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 | 
			
		||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 | 
			
		||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
 | 
			
		||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
			
		||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
			
		||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 | 
			
		||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
			
		||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 | 
			
		||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
 | 
			
		||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 | 
			
		||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
 | 
			
		||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 | 
			
		||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 | 
			
		||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 | 
			
		||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 | 
			
		||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
 | 
			
		||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 | 
			
		||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 | 
			
		||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 | 
			
		||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
			
		||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
			
		||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 | 
			
		||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
			
		||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 | 
			
		||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
			
		||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
			
		||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
 | 
			
		||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
 | 
			
		||||
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
 | 
			
		||||
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
 | 
			
		||||
github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
 | 
			
		||||
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
 | 
			
		||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
 | 
			
		||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
 | 
			
		||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
 | 
			
		||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 | 
			
		||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
 | 
			
		||||
@ -31,7 +174,100 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT
 | 
			
		||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
			
		||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
 | 
			
		||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
			
		||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 | 
			
		||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
			
		||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
 | 
			
		||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 | 
			
		||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 | 
			
		||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
 | 
			
		||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 | 
			
		||||
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
 | 
			
		||||
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
 | 
			
		||||
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
 | 
			
		||||
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
 | 
			
		||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 | 
			
		||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
 | 
			
		||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
 | 
			
		||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
 | 
			
		||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
 | 
			
		||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
			
		||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
 | 
			
		||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
			
		||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
 | 
			
		||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
			
		||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
			
		||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
 | 
			
		||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 | 
			
		||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
 | 
			
		||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
 | 
			
		||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
 | 
			
		||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
 | 
			
		||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
 | 
			
		||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
 | 
			
		||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
 | 
			
		||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
			
		||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
 | 
			
		||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
			
		||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
			
		||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
 | 
			
		||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
			
		||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
 | 
			
		||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
 | 
			
		||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
 | 
			
		||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
			
		||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
 | 
			
		||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
 | 
			
		||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
 | 
			
		||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
 | 
			
		||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
 | 
			
		||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
 | 
			
		||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 | 
			
		||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
 | 
			
		||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 | 
			
		||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 | 
			
		||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 | 
			
		||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
 | 
			
		||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								parser.go
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								parser.go
									
									
									
									
									
								
							@ -8,34 +8,35 @@
 | 
			
		||||
package api_doc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"git.zhangdeman.cn/gateway/api-doc/define"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/serialize"
 | 
			
		||||
	"github.com/tidwall/gjson"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Parse 解析swagger文档
 | 
			
		||||
// ParseOpenapi3 解析openapi文档
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 16:54 2024/12/23
 | 
			
		||||
func Parse(docUrl string) (*define.DocParseResult, error) {
 | 
			
		||||
// Date : 21:02 2025/2/25
 | 
			
		||||
func ParseOpenapi3(docUrl string, docContent string) (*define.OpenapiDoc, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err        error
 | 
			
		||||
		docContent []byte
 | 
			
		||||
		docRes  define.OpenapiDoc
 | 
			
		||||
		err     error
 | 
			
		||||
		docByte []byte
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if docContent, err = serialize.File.ReadFromRemote(docUrl); nil != err {
 | 
			
		||||
	if len(docContent) < 2 {
 | 
			
		||||
		if len(docUrl) == 0 {
 | 
			
		||||
			return nil, errors.New("doc url and doc content all empty")
 | 
			
		||||
		}
 | 
			
		||||
		if docByte, err = serialize.File.ReadFromRemote(docUrl); nil != err {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		docByte = []byte(docContent)
 | 
			
		||||
	}
 | 
			
		||||
	if err = serialize.JSON.UnmarshalWithNumber(docByte, &docRes); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	swaggerVersion := gjson.GetBytes(docContent, "swagger").String()
 | 
			
		||||
	if "" == swaggerVersion || !strings.HasPrefix(swaggerVersion, "2.") {
 | 
			
		||||
		// 未指定swagger版本或swagger版本3.x
 | 
			
		||||
		return ParseOpenapi3(docContent)
 | 
			
		||||
	}
 | 
			
		||||
	return ParseSwagger2(docContent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseOpenapi3(docContent []byte) (*define.DocParseResult, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
	return &docRes, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,6 @@ import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"git.zhangdeman.cn/gateway/api-doc/define"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/serialize"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
@ -25,10 +24,18 @@ type Meta struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:55 2024/7/19
 | 
			
		||||
func Test_parser_Openapi3(t *testing.T) {
 | 
			
		||||
	type UserExt struct {
 | 
			
		||||
		Job    string  `json:"job" dc:"job" binding:"required"`
 | 
			
		||||
		JobPtr *string `json:"job_ptr" dc:"job_ptr" binding:"required"`
 | 
			
		||||
		Height string  `json:"height" dc:"height" binding:"required"`
 | 
			
		||||
	}
 | 
			
		||||
	type User struct {
 | 
			
		||||
		Meta `json:"-" deprecated:"false" path:"/user/detail" method:"POST" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`
 | 
			
		||||
		Name *string `json:"name" d:"zhang" desc:"用户姓名" binding:"required"`
 | 
			
		||||
		Age  string  `json:"age" d:"18" desc:"年龄" binding:"required,oneof=12 13 18 90"`
 | 
			
		||||
		Meta      `json:"-" deprecated:"false" path:"/user/detail" method:"POST" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`
 | 
			
		||||
		Name      *string  `json:"name" d:"zhang" desc:"用户姓名" binding:"required"`
 | 
			
		||||
		Age       string   `json:"age" d:"18" desc:"年龄" binding:"required,oneof=12 13 18 90"`
 | 
			
		||||
		IDList    []int64  `json:"id_list" dc:"id_list...." binding:"required"`
 | 
			
		||||
		IDPtrList []*int64 `json:"id_ptr_list" dc:"id_ptr_list...." binding:"required"`
 | 
			
		||||
		UserExt
 | 
			
		||||
	}
 | 
			
		||||
	type UserDelete struct {
 | 
			
		||||
		Meta `json:"-" deprecated:"false" path:"/user/detail" method:"DELETE" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`
 | 
			
		||||
@ -88,8 +95,7 @@ func Test_parser_Openapi3(t *testing.T) {
 | 
			
		||||
	fmt.Println(string(byteData))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseForSwagger(t *testing.T) {
 | 
			
		||||
	docUrl := "https://git.zhangdeman.cn/swagger.v1.json"
 | 
			
		||||
	res, _ := Parse(docUrl)
 | 
			
		||||
	serialize.JSON.ConsoleOutput(res)
 | 
			
		||||
func Test_parse_Openapi3_doc(t *testing.T) {
 | 
			
		||||
	res, err := ParseOpenapi3("http://localhost:10990/static-server/github-openapi.json", "")
 | 
			
		||||
	fmt.Println(res, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								redoc-free/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								redoc-free/index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <title>{{DOC_TITLE}}</title>
 | 
			
		||||
    <!-- needed for adaptive design -->
 | 
			
		||||
    <meta charset="utf-8"/>
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
    <!-- https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700 -->
 | 
			
		||||
    <!-- 预留占位符, 可以通过外部替换 -->
 | 
			
		||||
    <link href="{{CSS_FAMILY}}" rel="stylesheet">
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
    Redoc doesn't change outer page styles
 | 
			
		||||
    -->
 | 
			
		||||
    <style>
 | 
			
		||||
        body {
 | 
			
		||||
            margin: 0;
 | 
			
		||||
            padding: 0;
 | 
			
		||||
        }
 | 
			
		||||
    </style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!-- 预留占位符, 可以通过外部替换 -->
 | 
			
		||||
<!--doc.json, 相对于外部设置好的base_url-->
 | 
			
		||||
<redoc spec-url='{{DOC_PATH}}'></redoc>
 | 
			
		||||
<!--https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js-->
 | 
			
		||||
<script src="{{REDOC_STANDALONE_JS}}"> </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										141
									
								
								struct_field.go
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								struct_field.go
									
									
									
									
									
								
							@ -15,10 +15,10 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ParseStructField = parseStructField{}
 | 
			
		||||
	ParseStructFieldTag = parseStructFieldTag{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type parseStructField struct {
 | 
			
		||||
type parseStructFieldTag struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetParamName 获取参数名称
 | 
			
		||||
@ -26,7 +26,7 @@ type parseStructField struct {
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:58 2025/2/11
 | 
			
		||||
func (psf parseStructField) GetParamName(structField reflect.StructField) string {
 | 
			
		||||
func (psf parseStructFieldTag) GetParamName(structField reflect.StructField) string {
 | 
			
		||||
	paramNameTagList := []string{
 | 
			
		||||
		define.TagJson, define.TagForm,
 | 
			
		||||
		define.TagXml, define.TagYaml,
 | 
			
		||||
@ -34,7 +34,9 @@ func (psf parseStructField) GetParamName(structField reflect.StructField) string
 | 
			
		||||
	}
 | 
			
		||||
	for _, tag := range paramNameTagList {
 | 
			
		||||
		tagVal := structField.Tag.Get(tag)
 | 
			
		||||
		if tagVal != "" {
 | 
			
		||||
		tagVal = strings.TrimSuffix(strings.TrimPrefix(tagVal, define.TagNameOmitempty+","), ","+define.TagNameOmitempty)
 | 
			
		||||
		tagVal = strings.Trim(tagVal, ",")
 | 
			
		||||
		if tagVal != "" && tagVal != define.TagNameOmitempty {
 | 
			
		||||
			return tagVal
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -47,12 +49,12 @@ func (psf parseStructField) GetParamName(structField reflect.StructField) string
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 22:01 2025/2/11
 | 
			
		||||
func (psf parseStructField) GetParamDesc(structField reflect.StructField) string {
 | 
			
		||||
	descTagList := []string{define.TagDesc, define.TagDescription}
 | 
			
		||||
func (psf parseStructFieldTag) GetParamDesc(structField reflect.StructField) string {
 | 
			
		||||
	descTagList := []string{define.TagDc, define.TagDesc, define.TagDescription}
 | 
			
		||||
	for _, tag := range descTagList {
 | 
			
		||||
		tagVal := structField.Tag.Get(tag)
 | 
			
		||||
		if tagVal != "" {
 | 
			
		||||
			return tagVal
 | 
			
		||||
			return strings.ReplaceAll(tagVal, "###", "`")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// 没有显示的设置参数描述, 则使用参数名作为参数描述
 | 
			
		||||
@ -64,35 +66,38 @@ func (psf parseStructField) GetParamDesc(structField reflect.StructField) string
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 22:05 2025/2/11
 | 
			
		||||
func (psf parseStructField) GetDefaultValue(structField reflect.StructField) any {
 | 
			
		||||
func (psf parseStructFieldTag) GetDefaultValue(structField reflect.StructField) any {
 | 
			
		||||
	defaultTagList := []string{define.TagD, define.TagDefault}
 | 
			
		||||
	fieldType := structField.Type.Kind().String()
 | 
			
		||||
	for _, tag := range defaultTagList {
 | 
			
		||||
		if val, exist := structField.Tag.Lookup(tag); exist && val != "" {
 | 
			
		||||
			if strings.HasPrefix(fieldType, "int") {
 | 
			
		||||
				i, _ := strconv.Atoi(val)
 | 
			
		||||
				return i
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(fieldType, "uint") {
 | 
			
		||||
				uintVal, _ := strconv.ParseUint(val, 10, 64)
 | 
			
		||||
				return uintVal
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(fieldType, "float") {
 | 
			
		||||
				floatVal, _ := strconv.ParseFloat(val, 64)
 | 
			
		||||
				return floatVal
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(fieldType, "string") {
 | 
			
		||||
				return val
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(fieldType, "bool") {
 | 
			
		||||
				if val == "true" {
 | 
			
		||||
					return true
 | 
			
		||||
				} else {
 | 
			
		||||
					return false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		val, exist := structField.Tag.Lookup(tag)
 | 
			
		||||
		val = strings.TrimSpace(val)
 | 
			
		||||
		if !exist || len(val) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "int") {
 | 
			
		||||
			i, _ := strconv.Atoi(val)
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "uint") {
 | 
			
		||||
			uintVal, _ := strconv.ParseUint(val, 10, 64)
 | 
			
		||||
			return uintVal
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "float") {
 | 
			
		||||
			floatVal, _ := strconv.ParseFloat(val, 64)
 | 
			
		||||
			return floatVal
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "string") {
 | 
			
		||||
			return val
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "bool") {
 | 
			
		||||
			if val == "true" {
 | 
			
		||||
				return true
 | 
			
		||||
			} else {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return val
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -102,7 +107,7 @@ func (psf parseStructField) GetDefaultValue(structField reflect.StructField) any
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:30 2025/2/13
 | 
			
		||||
func (psf parseStructField) GetValidateRule(structField reflect.StructField) string {
 | 
			
		||||
func (psf parseStructFieldTag) GetValidateRule(structField reflect.StructField) string {
 | 
			
		||||
	defaultTagList := []string{define.TagValidate, define.TagBinding}
 | 
			
		||||
	for _, tag := range defaultTagList {
 | 
			
		||||
		if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {
 | 
			
		||||
@ -117,7 +122,7 @@ func (psf parseStructField) GetValidateRule(structField reflect.StructField) str
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:12 2025/2/13
 | 
			
		||||
func (psf parseStructField) Deprecated(structField reflect.StructField) bool {
 | 
			
		||||
func (psf parseStructFieldTag) Deprecated(structField reflect.StructField) bool {
 | 
			
		||||
	defaultTagList := []string{define.TagDeprecated}
 | 
			
		||||
	for _, tag := range defaultTagList {
 | 
			
		||||
		if tagVal, exist := structField.Tag.Lookup(tag); exist && (tagVal == "1" || strings.ToLower(tagVal) == "true") {
 | 
			
		||||
@ -132,7 +137,7 @@ func (psf parseStructField) Deprecated(structField reflect.StructField) bool {
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:15 2025/2/14
 | 
			
		||||
func (psf parseStructField) Summary(structField reflect.StructField) string {
 | 
			
		||||
func (psf parseStructFieldTag) Summary(structField reflect.StructField) string {
 | 
			
		||||
	defaultTagList := []string{define.TagSummary}
 | 
			
		||||
	for _, tag := range defaultTagList {
 | 
			
		||||
		if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {
 | 
			
		||||
@ -145,3 +150,71 @@ func (psf parseStructField) Summary(structField reflect.StructField) string {
 | 
			
		||||
	}
 | 
			
		||||
	return paramName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnumDescription .枚举值详细描述
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 22:40 2025/2/18
 | 
			
		||||
func (psf parseStructFieldTag) EnumDescription(structField reflect.StructField) map[string]string {
 | 
			
		||||
	defaultTagList := []string{define.TagNameEnumDescription}
 | 
			
		||||
	res := map[string]string{}
 | 
			
		||||
	for _, tag := range defaultTagList {
 | 
			
		||||
		if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {
 | 
			
		||||
			tagVal = strings.ReplaceAll(tagVal, "###", "`")
 | 
			
		||||
			enumList := strings.Split(tagVal, "||")
 | 
			
		||||
			for _, enum := range enumList {
 | 
			
		||||
				enumArr := strings.Split(enum, ":")
 | 
			
		||||
				if len(enumArr) < 2 {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				res[enumArr[0]] = strings.Join(enumArr[1:], ":")
 | 
			
		||||
			}
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(res) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExampleValue 示例值
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:42 2025/2/20
 | 
			
		||||
func (psf parseStructFieldTag) GetExampleValue(structField reflect.StructField) any {
 | 
			
		||||
	descTagList := []string{define.TagEg, define.TagExample}
 | 
			
		||||
	fieldType := structField.Type.Kind().String()
 | 
			
		||||
	for _, tag := range descTagList {
 | 
			
		||||
		val := strings.TrimSpace(structField.Tag.Get(tag))
 | 
			
		||||
		if val == "" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "int") {
 | 
			
		||||
			i, _ := strconv.Atoi(val)
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "uint") {
 | 
			
		||||
			uintVal, _ := strconv.ParseUint(val, 10, 64)
 | 
			
		||||
			return uintVal
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "float") {
 | 
			
		||||
			floatVal, _ := strconv.ParseFloat(val, 64)
 | 
			
		||||
			return floatVal
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "string") {
 | 
			
		||||
			return val
 | 
			
		||||
		}
 | 
			
		||||
		if strings.HasPrefix(fieldType, "bool") {
 | 
			
		||||
			if val == "true" {
 | 
			
		||||
				return true
 | 
			
		||||
			} else {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return val
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								swagger/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								swagger/parser.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
// Package swagger ...
 | 
			
		||||
//
 | 
			
		||||
// Description : swagger ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 2025-04-11 20:07
 | 
			
		||||
package swagger
 | 
			
		||||
							
								
								
									
										194
									
								
								swagger_ui.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								swagger_ui.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,194 @@
 | 
			
		||||
// Package api_doc ...
 | 
			
		||||
//
 | 
			
		||||
// Description : api_doc ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 2025-02-16 13:19
 | 
			
		||||
package api_doc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"git.zhangdeman.cn/gateway/api-doc/define"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/consts"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	knife4goFiles "github.com/go-webtools/knife4go"
 | 
			
		||||
	knife4goGin "github.com/go-webtools/knife4go/gin"
 | 
			
		||||
	swaggerFiles "github.com/swaggo/files"
 | 
			
		||||
	ginSwagger "github.com/swaggo/gin-swagger"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed ydoc-lucky-ui/*
 | 
			
		||||
var ydocUIFiles embed.FS
 | 
			
		||||
 | 
			
		||||
//go:embed redoc-free/index.html
 | 
			
		||||
var redocFreeIndexContent string
 | 
			
		||||
 | 
			
		||||
// NewSwaggerUI ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:21 2025/2/15
 | 
			
		||||
func NewSwaggerUI(info *define.Info, servers []*define.ServerItem, uiTheme string) *SwaggerUI {
 | 
			
		||||
	return &SwaggerUI{
 | 
			
		||||
		docInstance: NewOpenapiDoc(info, servers),
 | 
			
		||||
		uiTheme:     uiTheme,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SwaggerUI struct {
 | 
			
		||||
	docInstance *Generate // 文档实例
 | 
			
		||||
	uiTheme     string    // 文档主题, swaggerUI / knife4go, 默认 knife4go
 | 
			
		||||
	router      *gin.Engine
 | 
			
		||||
	baseUri     string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DocInstance 文档实例
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 13:23 2025/2/16
 | 
			
		||||
func (su *SwaggerUI) DocInstance() *Generate {
 | 
			
		||||
	return su.docInstance
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterHandler ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:00 2025/2/16
 | 
			
		||||
func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
 | 
			
		||||
	su.router = router
 | 
			
		||||
	baseUri = strings.TrimRight(baseUri, "/")
 | 
			
		||||
	if len(baseUri) == 0 {
 | 
			
		||||
		baseUri = "/docs/swagger"
 | 
			
		||||
	}
 | 
			
		||||
	su.baseUri = baseUri
 | 
			
		||||
	router.GET(baseUri+"/*any", func(ctx *gin.Context) {
 | 
			
		||||
		if ctx.Request.RequestURI == baseUri+"/doc.json" {
 | 
			
		||||
			// 默认swagger, 通过此接口读取文档数据
 | 
			
		||||
			ctx.JSON(http.StatusOK, su.docInstance.Doc())
 | 
			
		||||
			ctx.Abort()
 | 
			
		||||
		}
 | 
			
		||||
		if ctx.Request.RequestURI == "/doc/swagger/openapi.json" {
 | 
			
		||||
			// knife4go 文档通过此接口读取文档列表
 | 
			
		||||
			ctx.JSON(http.StatusOK, []map[string]any{
 | 
			
		||||
				{
 | 
			
		||||
					"name":           "服务文档",
 | 
			
		||||
					"url":            "doc.json",
 | 
			
		||||
					"swaggerVersion": consts.SwaggerDocVersion3,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			ctx.Abort()
 | 
			
		||||
		}
 | 
			
		||||
	}, su.Handler())
 | 
			
		||||
	router.GET("/swagger-resources", func(ctx *gin.Context) { // lucky UI获取分组信息
 | 
			
		||||
		ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域
 | 
			
		||||
		ctx.JSON(http.StatusOK, []map[string]any{
 | 
			
		||||
			{
 | 
			
		||||
				"name":           "服务文档",
 | 
			
		||||
				"url":            baseUri + "/doc.json",
 | 
			
		||||
				"swaggerVersion": consts.SwaggerDocVersion3,
 | 
			
		||||
			},
 | 
			
		||||
		})
 | 
			
		||||
		// ctx.JSON(http.StatusOK, swaggerInstance.docInstance.Data())
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handler 访问文档的接口处理
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:34 2025/2/15
 | 
			
		||||
func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
 | 
			
		||||
	switch su.uiTheme {
 | 
			
		||||
	case define.SwaggerUIThemeKnife4go:
 | 
			
		||||
		return su.HandleKnife4goUI()
 | 
			
		||||
	case define.SwaggerUIThemeYDocLucky:
 | 
			
		||||
		// YDoc-Lucky-UI 主题处理
 | 
			
		||||
		return su.HandleLuckyUI()
 | 
			
		||||
	case define.SwaggerUIThemeDefault:
 | 
			
		||||
		return su.HandleSwaggerUI()
 | 
			
		||||
	case define.SwaggerUIThemeRedocFree:
 | 
			
		||||
		// redoc免费版
 | 
			
		||||
		return su.HandleRedocFreeUI()
 | 
			
		||||
	default:
 | 
			
		||||
		return su.HandleSwaggerUI()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleLuckyUI ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 16:04 2025/2/16
 | 
			
		||||
func (su *SwaggerUI) HandleLuckyUI() func(ctx *gin.Context) {
 | 
			
		||||
	// su.router.StaticFS(su.baseUri+"/assets", http.FS(ydocUIFiles))
 | 
			
		||||
	return func(ctx *gin.Context) {
 | 
			
		||||
		fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, su.baseUri)
 | 
			
		||||
		byteData, _ := ydocUIFiles.ReadFile(define.SwaggerUIThemeYDocLucky + fileRealPath)
 | 
			
		||||
		if strings.HasSuffix(ctx.Request.RequestURI, "html") {
 | 
			
		||||
			byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", su.baseUri))
 | 
			
		||||
		}
 | 
			
		||||
		uriArr := strings.Split(ctx.Request.RequestURI, ".")
 | 
			
		||||
		contentType := "text/" + uriArr[len(uriArr)-1]
 | 
			
		||||
		if strings.HasSuffix(ctx.Request.RequestURI, "png") {
 | 
			
		||||
			contentType = "image/png"
 | 
			
		||||
		} else if strings.HasSuffix(ctx.Request.RequestURI, "js") {
 | 
			
		||||
			contentType = "application/javascript"
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Header("Content-Type", contentType)
 | 
			
		||||
		ctx.String(http.StatusOK, string(byteData))
 | 
			
		||||
		ctx.Abort()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleKnife4goUI ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:38 2025/2/15
 | 
			
		||||
func (su *SwaggerUI) HandleKnife4goUI() func(ctx *gin.Context) {
 | 
			
		||||
	resetOption := func(cfg *knife4goGin.Config) {
 | 
			
		||||
		if nil == cfg {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		cfg.Title = "服务接口文档"
 | 
			
		||||
	}
 | 
			
		||||
	return knife4goGin.WrapHandler(knife4goFiles.Handler, resetOption)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleSwaggerUI ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:41 2025/2/15
 | 
			
		||||
func (su *SwaggerUI) HandleSwaggerUI() func(ctx *gin.Context) {
 | 
			
		||||
	return ginSwagger.WrapHandler(swaggerFiles.Handler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleRedocFreeUI 处理redoc_free主题
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 16:40 2025/2/18
 | 
			
		||||
func (su *SwaggerUI) HandleRedocFreeUI() func(ctx *gin.Context) {
 | 
			
		||||
	return func(ctx *gin.Context) {
 | 
			
		||||
		// TODO : 这部分数据支持外部传参替换
 | 
			
		||||
		replaceTable := map[string]string{
 | 
			
		||||
			"{{DOC_TITLE}}":           fmt.Sprintf("【%v】%v", su.docInstance.Doc().Info.Version, su.docInstance.Doc().Info.Title),
 | 
			
		||||
			"{{CSS_FAMILY}}":          "https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700",
 | 
			
		||||
			"{{DOC_PATH}}":            "doc.json",
 | 
			
		||||
			"{{REDOC_STANDALONE_JS}}": "https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js",
 | 
			
		||||
		}
 | 
			
		||||
		for k, v := range replaceTable {
 | 
			
		||||
			redocFreeIndexContent = strings.ReplaceAll(redocFreeIndexContent, k, v)
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Header("Content-Type", "text/html; charset=utf-8")
 | 
			
		||||
		ctx.String(http.StatusOK, redocFreeIndexContent)
 | 
			
		||||
		ctx.Abort()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -78,6 +78,84 @@ func (r validateRule) Enum(structField reflect.StructField) []any {
 | 
			
		||||
	return anySlice
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minimum 最小值
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 21:51 2025/2/18
 | 
			
		||||
func (r validateRule) Minimum(structField reflect.StructField) *int64 {
 | 
			
		||||
	ruleTable := r.getValidateRuleTable(structField)
 | 
			
		||||
	var (
 | 
			
		||||
		err                      error
 | 
			
		||||
		minVal, gteVal           int64
 | 
			
		||||
		minStr, gteStr           string
 | 
			
		||||
		minStrExist, gteStrExist bool
 | 
			
		||||
	)
 | 
			
		||||
	if minStr, minStrExist = ruleTable[consts.ValidatorRuleCommonMin.String()]; minStrExist && len(minStr) > 0 {
 | 
			
		||||
		if minVal, err = strconv.ParseInt(minStr, 10, 64); nil != err {
 | 
			
		||||
			panic("validate rule min val = " + minStr + " : " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if gteStr, gteStrExist = ruleTable[consts.ValidateRuleGte.String()]; gteStrExist && len(gteStr) > 0 {
 | 
			
		||||
		if gteVal, err = strconv.ParseInt(gteStr, 10, 64); nil != err {
 | 
			
		||||
			panic("validate rule gte val = " + gteStr + " : " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !minStrExist && !gteStrExist {
 | 
			
		||||
		// 未配置
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(minStr) > 0 {
 | 
			
		||||
		if len(gteStr) > 0 {
 | 
			
		||||
			if gteVal > minVal {
 | 
			
		||||
				return &minVal
 | 
			
		||||
			}
 | 
			
		||||
			return >eVal
 | 
			
		||||
		}
 | 
			
		||||
		return &minVal
 | 
			
		||||
	}
 | 
			
		||||
	return >eVal
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Maximum 最大值
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 22:00 2025/2/18
 | 
			
		||||
func (r validateRule) Maximum(structField reflect.StructField) *int64 {
 | 
			
		||||
	ruleTable := r.getValidateRuleTable(structField)
 | 
			
		||||
	var (
 | 
			
		||||
		err                      error
 | 
			
		||||
		maxVal, lteVal           int64
 | 
			
		||||
		maxStr, lteStr           string
 | 
			
		||||
		maxStrExist, gleStrExist bool
 | 
			
		||||
	)
 | 
			
		||||
	if maxStr, maxStrExist = ruleTable[consts.ValidatorRuleCommonMax.String()]; maxStrExist && len(maxStr) > 0 {
 | 
			
		||||
		if maxVal, err = strconv.ParseInt(maxStr, 10, 64); nil != err {
 | 
			
		||||
			panic("validate rule min val = " + maxStr + " : " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if lteStr, gleStrExist = ruleTable[consts.ValidateRuleLte.String()]; gleStrExist && len(lteStr) > 0 {
 | 
			
		||||
		if lteVal, err = strconv.ParseInt(lteStr, 10, 64); nil != err {
 | 
			
		||||
			panic("validate rule gte val = " + lteStr + " : " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !maxStrExist && !gleStrExist {
 | 
			
		||||
		// 未配置
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(maxStr) > 0 {
 | 
			
		||||
		if len(lteStr) > 0 {
 | 
			
		||||
			if lteVal > maxVal {
 | 
			
		||||
				return <eVal
 | 
			
		||||
			}
 | 
			
		||||
			return &maxVal
 | 
			
		||||
		}
 | 
			
		||||
		return &maxVal
 | 
			
		||||
	}
 | 
			
		||||
	return <eVal
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getValidateRuleTable 解析验证规则表
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
@ -85,7 +163,7 @@ func (r validateRule) Enum(structField reflect.StructField) []any {
 | 
			
		||||
// Date : 15:29 2025/2/13
 | 
			
		||||
func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string {
 | 
			
		||||
	res := map[string]string{}
 | 
			
		||||
	ruleStr := ParseStructField.GetValidateRule(structField)
 | 
			
		||||
	ruleStr := ParseStructFieldTag.GetValidateRule(structField)
 | 
			
		||||
	if len(ruleStr) == 0 {
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/Api.525b760d.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/Api.525b760d.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
#titleDoc[data-v-bf5b8710]{font-size:21px}[data-v-bf5b8710] .too-old td{color:#ff231e!important}
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/Api.73b14880.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/Api.73b14880.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/FirstPage.1d240e81.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/FirstPage.1d240e81.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
import{i as e,e as t,f as a,g as l,j as u,w as s,a3 as d,a4 as o,z as f,A as n,a5 as i,O as r}from"./vendor.08310185.js";const _={id:"typeCount"},p={id:"typeCount"},c={id:"typeCount"},b={id:"typeCount"},h={setup(h){let v=e("g"),y=v.value.data,g=v.value.resource,E=y.paths,k=Object.keys(E),j=0,m=0,x=0,C=0;return k.forEach((e=>{let t=E[e];Object.keys(t).forEach((e=>{switch(e){case"get":j+=1;break;case"post":m+=1;break;case"put":x+=1;break;case"delete":C+=1}}))})),(e,h)=>(t(),a("div",null,[l(u(d),{title:"基础信息"},{default:s((()=>[l(u(o),{"x-gap":12,"y-gap":20,cols:2},{default:s((()=>[l(u(i),null,{default:s((()=>[l(u(d),{title:"标题:",hoverable:""},{default:s((()=>[f(n(u(y).info.title),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"Host:",hoverable:""},{default:s((()=>[f(n(u(y).info.contact.url),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"简介:",hoverable:""},{default:s((()=>[f(n(u(y).info.description),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"base path:",hoverable:""},{default:s((()=>[f(n(u(y).basePath),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"作者:",hoverable:""},{default:s((()=>[f(n(u(y).info.contact.name),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"分组名称:",hoverable:""},{default:s((()=>[f(n(u(g)[0].url),1)])),_:1})])),_:1})])),_:1})])),_:1}),l(u(d),{title:"Api类型统计",style:{"margin-top":"30px"}},{default:s((()=>[l(u(o),{"x-gap":50,"y-gap":10,cols:4},{default:s((()=>[l(u(i),null,{default:s((()=>[l(u(d),{title:"POST",hoverable:""},{default:s((()=>[r("span",_,n(u(m)),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"GET",hoverable:""},{default:s((()=>[r("span",p,n(u(j)),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"PUT",hoverable:""},{default:s((()=>[r("span",c,n(u(x)),1)])),_:1})])),_:1}),l(u(i),null,{default:s((()=>[l(u(d),{title:"DELETE",hoverable:""},{default:s((()=>[r("span",b,n(u(C)),1)])),_:1})])),_:1})])),_:1})])),_:1})]))}};export{h as default};
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/FirstPage.48bcf13f.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/FirstPage.48bcf13f.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
#typeCount{font-size:24px}
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/Manager.02a611ee.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/Manager.02a611ee.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
import{r as e,u as a,o as t,e as l,y as s,w as r,j as i,T as o,a3 as u,f as n,g as d,ao as c,q as p,ap as g,t as y,v,x as f,aq as m,W as k,z as S,b as h,ar as _,as as x,O,A as I,aa as J}from"./vendor.08310185.js";const N={key:0},b=S("点我清除全部用例"),q=S(" 你确定要全部清理吗,我会把LocalStorage全部干掉哦。 "),z={style:{"font-size":"18px"}},C={key:1},E={setup(S){let E=e([]),j=e([{title:"名称",key:"title"},{title:"状态",key:"status"},{title:"创建时间",key:"time"},{title:"请求参数",key:"param",render:e=>(e.param.forEach((e=>{delete e.in,delete e.type,delete e.required,delete e.active})),JSON.stringify(e.param))},{title:"请求体",key:"body"},{title:"操作",key:"action",render:e=>h(y,{type:"primary",onClick:()=>W(e)},{default:()=>"删除"})}]),P=e(!0);a();let W=e=>{let a=localStorage.getItem(e.group),t=JSON.parse(a);for(var l=0;l<t.length;l++)if(t[l].title==e.title){1==t.length?localStorage.removeItem(e.group):(t.splice(l,1),localStorage.setItem(e.group,JSON.stringify(t)));break}A()},w=()=>{localStorage.clear(),A()},A=()=>{P.vlaue=!1,E.value=[];for(var e=0;e<localStorage.length;e++){var a=localStorage.key(e);if(a.startsWith("lucky")){let e={},t=JSON.parse(localStorage.getItem(a));t.forEach((e=>{e.group=a})),e.key=a.split("_")[1],e.value=t,E.value.push(e)}}P.vlaue=!0};return t((()=>{A()})),(e,a)=>(l(),s(i(o),{vertical:""},{default:r((()=>[i(P)?(l(),s(i(u),{key:0,title:"请求用例管理"},{default:r((()=>[i(E).length>0?(l(),n("div",N,[d(i(o),{vertical:"",size:15},{default:r((()=>[d(i(c),{"positive-text":"好的,没关系.","negative-text":"Emmm,算了吧.",onPositiveClick:i(w)},{icon:r((()=>[d(i(p),null,{default:r((()=>[d(i(g))])),_:1})])),trigger:r((()=>[d(i(y),{dashed:"",type:"primary"},{default:r((()=>[b])),_:1})])),default:r((()=>[q])),_:1},8,["onPositiveClick"]),(l(!0),n(v,null,f(i(E),((e,a)=>(l(),n("div",null,[d(i(_),null,{default:r((()=>[d(i(x),{name:"index"},{header:r((()=>[O("span",z,I(e.key),1)])),default:r((()=>[d(i(J),{columns:i(j),data:e.value},null,8,["columns","data"])])),_:2},1024)])),_:2},1024)])))),256))])),_:1})])):(l(),n("div",C,[d(i(m),{status:"404",title:"好像没有多余的请求用例了",description:"去创建几个试试吧"})]))])),_:1})):k("",!0)])),_:1}))}};export{E as default};
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/MethodTrace.9051cb05.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/MethodTrace.9051cb05.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
import{a as l}from"./index.4ac3587a.js";import{r as a,o as e,e as t,f as u,g as s,j as n,T as d,w as o,l as f,z as p,b as r,D as b}from"./vendor.08310185.js";const i=p(" asdsa "),y={setup(p){const y=a([{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"1"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"3"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"4"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"5"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"6"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"7"},{label:()=>r(b,null,{default:()=>"电灯熄灭 物换星移 泥牛入海"}),key:"8"},{label:()=>r(b,null,{default:()=>"黑暗好像 一颗巨石 按在胸口"}),key:"2"}]);return e((()=>{let a=window.location.pathname.replace("/doc.html","");a="http://127.0.0.1:8888",l({url:"http://127.0.0.1:8888/getMc",method:"get"}).then((l=>{l.data&&console.log(l.data)}))})),(l,a)=>(t(),u("div",null,[s(n(d),null,{default:o((()=>[s(n(f),{options:y.value,style:{width:"180px"},"default-value":"1"},null,8,["options"]),i])),_:1})]))}};export{y as default};
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/Models.a928c1a8.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/Models.a928c1a8.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
import{e as s,y as t,w as a,j as e,a3 as o,g as u,aq as i,t as n,z as l}from"./vendor.08310185.js";const r=l("去提个Issues催一下"),c={setup(l){let c=()=>{window.open("https://github.com/NoBugBoy/YdocLuckyUi/issues/new")};return(l,d)=>(s(),t(e(o),null,{default:a((()=>[u(e(i),{status:"500",title:"作者太懒了,这个功能并不太想做",description:"也许你真的不太需要这个东西."},{footer:a((()=>[u(e(n),{onClick:e(c)},{default:a((()=>[r])),_:1},8,["onClick"])])),_:1})])),_:1}))}};export{c as default};
 | 
			
		||||
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/Share.3315ee0c.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/Share.3315ee0c.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5
									
								
								ydoc-lucky-ui/assets/icon.a080a8a4.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								ydoc-lucky-ui/assets/icon.a080a8a4.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<svg height="16" width="8" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
 
 | 
			
		||||
<polygon points="0,0 8,8 0,16"
 | 
			
		||||
style="fill:#666;stroke:purple;stroke-width:0" />
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 156 B  | 
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/index.4ac3587a.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/index.4ac3587a.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/index.5b18e4ae.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/index.5b18e4ae.css
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ydoc-lucky-ui/assets/title.8b763cb0.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ydoc-lucky-ui/assets/title.8b763cb0.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 340 KiB  | 
							
								
								
									
										1
									
								
								ydoc-lucky-ui/assets/vendor.0513d345.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ydoc-lucky-ui/assets/vendor.0513d345.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
.jv-container{box-sizing:border-box;position:relative}.jv-container.boxed{border:1px solid #eee;border-radius:6px}.jv-container.boxed:hover{box-shadow:0 2px 7px #00000026;border-color:transparent;position:relative}.jv-container.jv-light{background:#fff;white-space:nowrap;color:#525252;font-size:14px;font-family:Consolas,Menlo,Courier,monospace}.jv-container.jv-light .jv-ellipsis{color:#999;background-color:#eee;display:inline-block;line-height:.9;font-size:.9em;padding:0 4px 2px;margin:0 4px;border-radius:3px;vertical-align:2px;cursor:pointer;user-select:none}.jv-container.jv-light .jv-button{color:#49b3ff}.jv-container.jv-light .jv-key{color:#111;margin-right:4px}.jv-container.jv-light .jv-item.jv-array{color:#111}.jv-container.jv-light .jv-item.jv-boolean{color:#fc1e70}.jv-container.jv-light .jv-item.jv-function{color:#067bca}.jv-container.jv-light .jv-item.jv-number{color:#fc1e70}.jv-container.jv-light .jv-item.jv-object{color:#111}.jv-container.jv-light .jv-item.jv-undefined{color:#e08331}.jv-container.jv-light .jv-item.jv-string{color:#42b983;word-break:break-word;white-space:normal}.jv-container.jv-light .jv-item.jv-string .jv-link{color:#0366d6}.jv-container.jv-light .jv-code .jv-toggle:before{padding:0 2px;border-radius:2px}.jv-container.jv-light .jv-code .jv-toggle:hover:before{background:#eee}.jv-container .jv-code{overflow:hidden;padding:30px 20px}.jv-container .jv-code.boxed{max-height:300px}.jv-container .jv-code.open{max-height:initial!important;overflow:visible;overflow-x:auto;padding-bottom:45px}.jv-container .jv-toggle{background-image:url(/assets/icon.a080a8a4.svg);background-repeat:no-repeat;background-size:contain;background-position:center center;cursor:pointer;width:10px;height:10px;margin-right:2px;display:inline-block;transition:transform .1s}.jv-container .jv-toggle.open{transform:rotate(90deg)}.jv-container .jv-more{position:absolute;z-index:1;bottom:0;left:0;right:0;height:40px;width:100%;text-align:center;cursor:pointer}.jv-container .jv-more .jv-toggle{position:relative;top:40%;z-index:2;color:#888;transition:all .1s;transform:rotate(90deg)}.jv-container .jv-more .jv-toggle.open{transform:rotate(-90deg)}.jv-container .jv-more:after{content:"";width:100%;height:100%;position:absolute;bottom:0;left:0;z-index:1;background:linear-gradient(to bottom,rgba(0,0,0,0) 20%,rgba(230,230,230,.3) 100%);transition:all .1s}.jv-container .jv-more:hover .jv-toggle{top:50%;color:#111}.jv-container .jv-more:hover:after{background:linear-gradient(to bottom,rgba(0,0,0,0) 20%,rgba(230,230,230,.3) 100%)}.jv-container .jv-button{position:relative;cursor:pointer;display:inline-block;padding:5px;z-index:5}.jv-container .jv-button.copied{opacity:.4;cursor:default}.jv-container .jv-tooltip{position:absolute}.jv-container .jv-tooltip.right{right:15px}.jv-container .jv-tooltip.left{left:15px}.jv-container .j-icon{font-size:12px}.jv-node{position:relative}.jv-node:after{content:","}.jv-node:last-of-type:after{content:""}.jv-node.toggle{margin-left:13px!important}.jv-node .jv-node{margin-left:25px}
 | 
			
		||||
							
								
								
									
										14
									
								
								ydoc-lucky-ui/assets/vendor.08310185.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ydoc-lucky-ui/assets/vendor.08310185.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ydoc-lucky-ui/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ydoc-lucky-ui/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.2 KiB  | 
							
								
								
									
										18
									
								
								ydoc-lucky-ui/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ydoc-lucky-ui/index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="UTF-8" />
 | 
			
		||||
    <meta http-equiv="Pragma" content="no-cache">
 | 
			
		||||
    <link rel="icon" href="{{BASE_URI}}/assets/title.8b763cb0.png" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
    <title>接口文档</title>
 | 
			
		||||
    <script type="module" crossorigin src="{{BASE_URI}}/assets/index.4ac3587a.js"></script>
 | 
			
		||||
    <link rel="modulepreload" href="{{BASE_URI}}/assets/vendor.08310185.js">
 | 
			
		||||
    <link rel="stylesheet" href="{{BASE_URI}}/assets/vendor.0513d345.css">
 | 
			
		||||
    <link rel="stylesheet" href="{{BASE_URI}}/assets/index.5b18e4ae.css">
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <div id="app"></div>
 | 
			
		||||
    
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user