Compare commits
1 Commits
master
...
feature/fi
Author | SHA1 | Date | |
---|---|---|---|
c35ddad807 |
@ -119,29 +119,21 @@ 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 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 string `json:"type,omitempty"` // 类型
|
||||
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"` // 默认值
|
||||
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"` // 格式化类型
|
||||
}
|
||||
|
||||
// Property 是从 JSON Schema 提取出来的,但是做了一些调整以适应 OpenAPI Specification。
|
||||
@ -153,14 +145,8 @@ type Property struct {
|
||||
Type string `json:"type,omitempty"` // 数据类型, 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 指向对象描述
|
||||
@ -176,12 +162,7 @@ type Property struct {
|
||||
//
|
||||
// Date : 17:13 2024/7/19
|
||||
type PropertyXOf struct {
|
||||
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"` // 数据每一项已用类型
|
||||
Ref string `json:"$ref"` // 引用的结构描述
|
||||
}
|
||||
|
||||
// SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验
|
||||
|
@ -1,15 +0,0 @@
|
||||
// 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,31 +8,26 @@
|
||||
package define
|
||||
|
||||
const (
|
||||
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
|
||||
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"
|
||||
)
|
||||
|
389
generate.go
389
generate.go
@ -270,7 +270,7 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
|
||||
Summary: baseCfg.Summary,
|
||||
Description: baseCfg.Description,
|
||||
ExternalDocs: nil,
|
||||
OperationID: baseCfg.Summary + "(" + baseCfg.Method + "-" + strings.ReplaceAll(strings.TrimLeft(baseCfg.Uri, "/"), "/", "-") + ")",
|
||||
OperationID: baseCfg.Method + "-" + baseCfg.Uri,
|
||||
Parameters: make([]*define.PathConfigParameter, 0),
|
||||
RequestBody: &define.RequestBody{
|
||||
Required: true,
|
||||
@ -326,12 +326,7 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
|
||||
baseReqCfg.Parameters = make([]*define.PathConfigParameter, 0)
|
||||
}
|
||||
for i := 0; i < inputType.NumField(); i++ {
|
||||
if inputType.Field(i).Anonymous {
|
||||
// 匿名字段, 直接对齐到当前的父级
|
||||
g.ParseReadConfigParam(requestCfg, baseReqCfg, inputType.Field(i).Type)
|
||||
continue
|
||||
}
|
||||
propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
|
||||
propertyName := ParseStructField.GetParamName(inputType.Field(i))
|
||||
if propertyName == "-" {
|
||||
continue
|
||||
}
|
||||
@ -339,46 +334,11 @@ 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 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 {
|
||||
fieldType = inputType.Field(i).Type.Elem()
|
||||
}*/
|
||||
if inputType.Field(i).Type.Kind() == reflect.Ptr {
|
||||
// 处理指针
|
||||
if inputType.Field(i).Type.Elem().Kind() == reflect.Struct {
|
||||
@ -387,9 +347,9 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
|
||||
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
|
||||
Name: propertyName,
|
||||
In: consts.SwaggerParameterInQuery,
|
||||
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
|
||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||
Required: ValidateRule.IsRequired(inputType.Field(i)),
|
||||
Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)),
|
||||
Deprecated: ParseStructField.Deprecated(inputType.Field(i)),
|
||||
Schema: &define.Schema{
|
||||
// Format: realInputTypeFormat,
|
||||
Ref: g.getSchemaRef(schemaNameNext),
|
||||
@ -399,7 +359,22 @@ 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
|
||||
}
|
||||
@ -407,20 +382,19 @@ 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: ParseStructFieldTag.GetParamName(inputType.Field(i)),
|
||||
Name: ParseStructField.GetParamName(inputType.Field(i)),
|
||||
In: consts.SwaggerParameterInQuery,
|
||||
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
|
||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||
Required: ValidateRule.IsRequired(inputType.Field(i)),
|
||||
Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)),
|
||||
Deprecated: ParseStructField.Deprecated(inputType.Field(i)),
|
||||
Schema: &define.Schema{
|
||||
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)),
|
||||
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
|
||||
Items: nil,
|
||||
Ref: "",
|
||||
Format: realInputTypeFormat,
|
||||
},
|
||||
AllowEmptyValue: false,
|
||||
Style: "",
|
||||
@ -456,7 +430,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
|
||||
@ -487,66 +461,45 @@ 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
|
||||
g.docData.Components.Schemas[schemaName].Items = propertyXOf
|
||||
sliceItemType := g.parseSliceItem(schemaName, inputType)
|
||||
g.docData.Components.Schemas[schemaName].Items = &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)}
|
||||
} else {
|
||||
sliceItemType := g.parseSliceItem(schemaName, inputType)
|
||||
g.docData.Components.Schemas[rootSchemaName].Properties[schemaName] = &define.Property{
|
||||
Type: consts.SwaggerDataTypeArray,
|
||||
Format: inputType.String(),
|
||||
Items: propertyXOf,
|
||||
Items: &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)},
|
||||
}
|
||||
}
|
||||
|
||||
return schemaName
|
||||
}
|
||||
// 结构体
|
||||
if inputType.Kind() == reflect.Struct {
|
||||
for i := 0; i < inputType.NumField(); i++ {
|
||||
propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
|
||||
propertyName := ParseStructField.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: convertBaseType,
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
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)),
|
||||
}
|
||||
}
|
||||
// 设置参数各种属性
|
||||
g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
|
||||
continue
|
||||
}
|
||||
if inputType.Field(i).Type.Kind() == reflect.Struct ||
|
||||
@ -556,45 +509,36 @@ 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(),
|
||||
Properties: map[string]*define.Property{},
|
||||
Type: consts.SwaggerDataTypeObject,
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||
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(),
|
||||
Items: propertyXOf,
|
||||
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{},
|
||||
}
|
||||
} else {
|
||||
g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type)
|
||||
}
|
||||
|
||||
} else {
|
||||
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.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)),
|
||||
}
|
||||
}
|
||||
// 设置参数各种属性
|
||||
g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
|
||||
g.setStructFieldProperty(schemaName, inputType.Field(i))
|
||||
}
|
||||
return schemaName
|
||||
}
|
||||
@ -604,7 +548,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(),
|
||||
@ -615,79 +559,26 @@ 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, bool) {
|
||||
func (g *Generate) parseSliceItem(rootSchemaName string, inputType reflect.Type) string {
|
||||
if inputType.Kind() != reflect.Slice && inputType.Kind() != reflect.Array {
|
||||
// 不是数组
|
||||
return "", false
|
||||
return ""
|
||||
}
|
||||
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 realSliceItemType, false
|
||||
return sliceItemType.String()
|
||||
}
|
||||
return sliceItemType.PkgPath() + "." + sliceItemType.Name(), false
|
||||
return sliceItemType.PkgPath() + "." + sliceItemType.Name()
|
||||
}
|
||||
|
||||
// getSchemaRef 获取引用的类型
|
||||
@ -700,11 +591,7 @@ func (g *Generate) getSchemaRef(schemaName string) string {
|
||||
return ""
|
||||
}
|
||||
schemaName = strings.ReplaceAll(schemaName, "*", "") // 去除指针类型 *
|
||||
convertType, isBaseType := g.realBaseType2SwaggerType(schemaName)
|
||||
if isBaseType {
|
||||
return convertType
|
||||
}
|
||||
return "#/components/schemas/" + strings.ReplaceAll(convertType, "/", ".")
|
||||
return "#/components/schemas/" + strings.ReplaceAll(schemaName, "/", "-")
|
||||
}
|
||||
|
||||
// realType2SwaggerType golang 真实数据类型转换为golang数据类型
|
||||
@ -712,75 +599,48 @@ 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, bool) {
|
||||
func (g *Generate) realBaseType2SwaggerType(realType string) string {
|
||||
switch realType {
|
||||
case "bool", "*bool":
|
||||
return consts.SwaggerDataTypeBoolean, true
|
||||
return consts.SwaggerDataTypeBoolean
|
||||
case "string", "*string":
|
||||
return consts.SwaggerDataTypeString, true
|
||||
return consts.SwaggerDataTypeString
|
||||
case "byte", "*byte":
|
||||
return consts.SwaggerDataTypeByte, true
|
||||
return consts.SwaggerDataTypeByte
|
||||
case "float32", "*float32", "float64", "*float64":
|
||||
return consts.SwaggerDataTypeDouble, true
|
||||
return consts.SwaggerDataTypeDouble
|
||||
case "int", "*int", "uint", "*uint", "int64", "*int64", "uint64", "*uint64":
|
||||
return consts.SwaggerDataTypeInteger, true
|
||||
return consts.SwaggerDataTypeInteger
|
||||
case "int8", "*int8", "uint8", "*uint8", "int16", "*int16", "uint16", "*uint16", "int32", "*int32", "uint32", "*uint32":
|
||||
return consts.SwaggerDataTypeInteger, true
|
||||
return consts.SwaggerDataTypeInteger
|
||||
default:
|
||||
if strings.HasPrefix(realType, "[]") {
|
||||
return consts.SwaggerDataTypeArray, true
|
||||
}
|
||||
return realType, false
|
||||
return realType
|
||||
}
|
||||
}
|
||||
|
||||
// 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(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
|
||||
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)
|
||||
}
|
||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
|
||||
}
|
||||
|
||||
// parseBaseUriConfig 通过Meta字段解析Uri基础配置信息
|
||||
@ -837,75 +697,12 @@ func (g *Generate) parseBaseUriConfig(uriPrefix string, paramType reflect.Type)
|
||||
responseContentType = consts.MimeTypeJson
|
||||
}
|
||||
res.OutputContentType = strings.Split(responseContentType, ",")
|
||||
res.Summary = ParseStructFieldTag.Summary(metaField)
|
||||
if len(res.Summary) == 0 {
|
||||
res.Summary = wrapper.String(strings.ReplaceAll(strings.TrimLeft(res.Uri, "/"), "/", "_")).SnakeCaseToCamel()
|
||||
}
|
||||
res.Summary = ParseStructField.Summary(metaField)
|
||||
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",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
41
go.mod
41
go.mod
@ -6,10 +6,6 @@ require (
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250208020330-a50062af46a1
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9
|
||||
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
|
||||
)
|
||||
|
||||
@ -17,47 +13,10 @@ 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/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.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.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // 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.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // 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.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // 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.2 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/swaggo/swag v1.8.12 // 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.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
161
go.sum
161
go.sum
@ -10,116 +10,20 @@ git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9 h1:yF770
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250124091620-c757e551a8c9/go.mod h1:I76wxEsWq7KnMQ84elpwTjEqq4I49QFw60tp5h7iGBs=
|
||||
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/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/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/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
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/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/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-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/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/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
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-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-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/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/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/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/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/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/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=
|
||||
@ -127,70 +31,7 @@ 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=
|
||||
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/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/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/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/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/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/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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
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=
|
||||
|
@ -25,18 +25,10 @@ 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"`
|
||||
IDList []int64 `json:"id_list" dc:"id_list...." binding:"required"`
|
||||
IDPtrList []*int64 `json:"id_ptr_list" dc:"id_ptr_list...." binding:"required"`
|
||||
UserExt
|
||||
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"`
|
||||
}
|
||||
type UserDelete struct {
|
||||
Meta `json:"-" deprecated:"false" path:"/user/detail" method:"DELETE" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`
|
||||
|
@ -1,29 +0,0 @@
|
||||
<!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 (
|
||||
ParseStructFieldTag = parseStructFieldTag{}
|
||||
ParseStructField = parseStructField{}
|
||||
)
|
||||
|
||||
type parseStructFieldTag struct {
|
||||
type parseStructField struct {
|
||||
}
|
||||
|
||||
// GetParamName 获取参数名称
|
||||
@ -26,7 +26,7 @@ type parseStructFieldTag struct {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:58 2025/2/11
|
||||
func (psf parseStructFieldTag) GetParamName(structField reflect.StructField) string {
|
||||
func (psf parseStructField) GetParamName(structField reflect.StructField) string {
|
||||
paramNameTagList := []string{
|
||||
define.TagJson, define.TagForm,
|
||||
define.TagXml, define.TagYaml,
|
||||
@ -34,9 +34,7 @@ func (psf parseStructFieldTag) GetParamName(structField reflect.StructField) str
|
||||
}
|
||||
for _, tag := range paramNameTagList {
|
||||
tagVal := structField.Tag.Get(tag)
|
||||
tagVal = strings.TrimSuffix(strings.TrimPrefix(tagVal, define.TagNameOmitempty+","), ","+define.TagNameOmitempty)
|
||||
tagVal = strings.Trim(tagVal, ",")
|
||||
if tagVal != "" && tagVal != define.TagNameOmitempty {
|
||||
if tagVal != "" {
|
||||
return tagVal
|
||||
}
|
||||
}
|
||||
@ -49,12 +47,12 @@ func (psf parseStructFieldTag) GetParamName(structField reflect.StructField) str
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 22:01 2025/2/11
|
||||
func (psf parseStructFieldTag) GetParamDesc(structField reflect.StructField) string {
|
||||
descTagList := []string{define.TagDc, define.TagDesc, define.TagDescription}
|
||||
func (psf parseStructField) GetParamDesc(structField reflect.StructField) string {
|
||||
descTagList := []string{define.TagDesc, define.TagDescription}
|
||||
for _, tag := range descTagList {
|
||||
tagVal := structField.Tag.Get(tag)
|
||||
if tagVal != "" {
|
||||
return strings.ReplaceAll(tagVal, "###", "`")
|
||||
return tagVal
|
||||
}
|
||||
}
|
||||
// 没有显示的设置参数描述, 则使用参数名作为参数描述
|
||||
@ -66,38 +64,35 @@ func (psf parseStructFieldTag) GetParamDesc(structField reflect.StructField) str
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 22:05 2025/2/11
|
||||
func (psf parseStructFieldTag) GetDefaultValue(structField reflect.StructField) any {
|
||||
func (psf parseStructField) GetDefaultValue(structField reflect.StructField) any {
|
||||
defaultTagList := []string{define.TagD, define.TagDefault}
|
||||
fieldType := structField.Type.Kind().String()
|
||||
for _, tag := range defaultTagList {
|
||||
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") {
|
||||
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
|
||||
}
|
||||
}
|
||||
return val
|
||||
}
|
||||
if strings.HasPrefix(fieldType, "bool") {
|
||||
if val == "true" {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -107,7 +102,7 @@ func (psf parseStructFieldTag) GetDefaultValue(structField reflect.StructField)
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:30 2025/2/13
|
||||
func (psf parseStructFieldTag) GetValidateRule(structField reflect.StructField) string {
|
||||
func (psf parseStructField) 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 {
|
||||
@ -122,7 +117,7 @@ func (psf parseStructFieldTag) GetValidateRule(structField reflect.StructField)
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:12 2025/2/13
|
||||
func (psf parseStructFieldTag) Deprecated(structField reflect.StructField) bool {
|
||||
func (psf parseStructField) 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") {
|
||||
@ -137,7 +132,7 @@ func (psf parseStructFieldTag) Deprecated(structField reflect.StructField) bool
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:15 2025/2/14
|
||||
func (psf parseStructFieldTag) Summary(structField reflect.StructField) string {
|
||||
func (psf parseStructField) Summary(structField reflect.StructField) string {
|
||||
defaultTagList := []string{define.TagSummary}
|
||||
for _, tag := range defaultTagList {
|
||||
if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {
|
||||
@ -150,71 +145,3 @@ func (psf parseStructFieldTag) 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
|
||||
}
|
||||
|
194
swagger_ui.go
194
swagger_ui.go
@ -1,194 +0,0 @@
|
||||
// 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,84 +78,6 @@ 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<白茶清欢>
|
||||
@ -163,7 +85,7 @@ func (r validateRule) Maximum(structField reflect.StructField) *int64 {
|
||||
// Date : 15:29 2025/2/13
|
||||
func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string {
|
||||
res := map[string]string{}
|
||||
ruleStr := ParseStructFieldTag.GetValidateRule(structField)
|
||||
ruleStr := ParseStructField.GetValidateRule(structField)
|
||||
if len(ruleStr) == 0 {
|
||||
return res
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
#titleDoc[data-v-bf5b8710]{font-size:21px}[data-v-bf5b8710] .too-old td{color:#ff231e!important}
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
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 +0,0 @@
|
||||
#typeCount{font-size:24px}
|
@ -1 +0,0 @@
|
||||
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 +0,0 @@
|
||||
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 +0,0 @@
|
||||
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};
|
File diff suppressed because one or more lines are too long
@ -1,5 +0,0 @@
|
||||
<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>
|
Before Width: | Height: | Size: 156 B |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 340 KiB |
@ -1 +0,0 @@
|
||||
.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}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
@ -1,18 +0,0 @@
|
||||
<!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>
|
Loading…
x
Reference in New Issue
Block a user