升级文档基础配置项处理, 固定值配置化 #22

Merged
zhangdeman merged 5 commits from feature/upgrade into master 2025-08-23 10:54:33 +08:00
40 changed files with 478 additions and 356 deletions

View File

@ -9,9 +9,11 @@ package api_doc
import ( import (
"fmt" "fmt"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"strings" "strings"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/enums"
"git.zhangdeman.cn/zhangdeman/consts"
) )
// GetUriPathParamList 获取uri参数列表 // GetUriPathParamList 获取uri参数列表
@ -60,22 +62,22 @@ func GetDataType(docParamType string, formatType string) string {
// format type 和内置的支持数据类型不一致, 根据文档类型进行转换 // format type 和内置的支持数据类型不一致, 根据文档类型进行转换
switch docParamType { switch docParamType {
case consts.SwaggerDataTypeInteger: case enums.SwaggerDataTypeInteger.String():
if formatType == consts.DataTypeInt.String() { if formatType == consts.DataTypeInt.String() {
return consts.DataTypeInt.String() return consts.DataTypeInt.String()
} }
return consts.DataTypeInt.String() return consts.DataTypeInt.String()
case "string", "apikey": case enums.SwaggerDataTypeString.String(), enums.SwaggerDataTypeString.String():
return consts.DataTypeString.String() return consts.DataTypeString.String()
case "object": case enums.SwaggerDataTypeObject.String():
return consts.DataTypeMapStrAny.String() return consts.DataTypeMapStrAny.String()
case "boolean": case enums.SwaggerDataTypeObject.String():
return consts.DataTypeBool.String() return consts.DataTypeBool.String()
case "number", "float", "double", "float64": case enums.SwaggerDataTypeNumber.String(), "float", "double", "float64":
return consts.DataTypeFloat64.String() return consts.DataTypeFloat64.String()
case "float32": case "float32":
return consts.DataTypeFloat32.String() return consts.DataTypeFloat32.String()
case "array": case enums.SwaggerDataTypeArray.String():
if formatType == "integer" { if formatType == "integer" {
return consts.DataTypeSliceInt.String() return consts.DataTypeSliceInt.String()
} else if formatType == "string" { } else if formatType == "string" {
@ -89,22 +91,18 @@ func GetDataType(docParamType string, formatType string) string {
} }
// GetParamLocation 获取参数位置 // GetParamLocation 获取参数位置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:02 2024/12/24
func GetParamLocation(docParamLocation string) consts.RequestDataLocation { func GetParamLocation(docParamLocation string) consts.RequestDataLocation {
docParamLocation = strings.ToLower(docParamLocation) docParamLocation = strings.ToLower(docParamLocation)
switch docParamLocation { switch docParamLocation {
case "query": case enums.DocParamLocationQuery.String():
return consts.RequestDataLocationQuery return consts.RequestDataLocationQuery
case "header": case enums.DocParamLocationHeader.String():
return consts.RequestDataLocationHeader return consts.RequestDataLocationHeader
case "cookie": case enums.DocParamLocationCookie.String():
return consts.RequestDataLocationCookie return consts.RequestDataLocationCookie
case "body": case enums.DocParamLocationBody.String():
return consts.RequestDataLocationBody return consts.RequestDataLocationBody
case "path": case enums.DocParamLocationPath.String():
return consts.RequestDataLocationUriPath return consts.RequestDataLocationUriPath
default: default:
return consts.RequestDataLocationQuery return consts.RequestDataLocationQuery
@ -113,12 +111,12 @@ func GetParamLocation(docParamLocation string) consts.RequestDataLocation {
// GetRealDefinitionsKey 通过schema下的 $ref 获取真实的 definitions key // GetRealDefinitionsKey 通过schema下的 $ref 获取真实的 definitions key
func GetRealDefinitionsKey(ref string) string { func GetRealDefinitionsKey(ref string) string {
return strings.TrimPrefix(ref, "#/definitions/") return strings.TrimPrefix(ref, enums.RefPrefixSchemaDefinition.String())
} }
// GetRealResponseKey 通过schema下的 $ref 获取真实的 response key // GetRealResponseKey 通过schema下的 $ref 获取真实的 response key
func GetRealResponseKey(ref string) string { func GetRealResponseKey(ref string) string {
return strings.TrimPrefix(ref, "#/responses/") return strings.TrimPrefix(ref, enums.RefPrefixSchemaResponse.String())
} }
// GetSuccessResponseConfig 获取成功的响应配置 // GetSuccessResponseConfig 获取成功的响应配置
@ -133,7 +131,7 @@ func GetSuccessResponseConfig(resultConfig map[string]*define.SwaggerPathConfigR
// DataTypeIsArray 判断数据类型是否为数组 // DataTypeIsArray 判断数据类型是否为数组
func DataTypeIsArray(docDataType string) bool { func DataTypeIsArray(docDataType string) bool {
return strings.ToLower(docDataType) == "array" return strings.ToLower(docDataType) == enums.SwaggerDataTypeArray.String()
} }
// ExpandArrayParam 展开详细的数组配置 // ExpandArrayParam 展开详细的数组配置

View File

@ -7,11 +7,9 @@
// Date : 2024-04-23 22:16 // Date : 2024-04-23 22:16
package define package define
import "git.zhangdeman.cn/gateway/api-doc/enums"
// OpenapiDoc openapi文档结构, 文档规范参见 : https://openapi.apifox.cn/ // OpenapiDoc openapi文档结构, 文档规范参见 : https://openapi.apifox.cn/
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:16 2024/7/19
type OpenapiDoc struct { type OpenapiDoc struct {
Openapi string `json:"openapi" required:"true"` // 必选. 这个字符串必须是开放 API 规范版本号提到的符合语义化版本号规范的版本号。openapi字段应该被工具或者客户端用来解释 OpenAPI 文档. Openapi string `json:"openapi" required:"true"` // 必选. 这个字符串必须是开放 API 规范版本号提到的符合语义化版本号规范的版本号。openapi字段应该被工具或者客户端用来解释 OpenAPI 文档.
Info *Info `json:"info,omitempty" required:"true"` // 必选。此字段提供 API 相关的元数据。相关工具可能需要这个字段。 Info *Info `json:"info,omitempty" required:"true"` // 必选。此字段提供 API 相关的元数据。相关工具可能需要这个字段。
@ -22,19 +20,11 @@ type OpenapiDoc struct {
} }
// Components 数据结构定义 // Components 数据结构定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:22 2024/7/19
type Components struct { type Components struct {
Schemas map[string]*Schema `json:"schemas"` // 数据结构定义 Schemas map[string]*Schema `json:"schemas"` // 数据结构定义
} }
// PathConfig ... // PathConfig ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:06 2024/7/19
type PathConfig struct { type PathConfig struct {
Get *PathItemOperationConfig `json:"get,omitempty"` // 定义适用于此路径的 GET 操作。 Get *PathItemOperationConfig `json:"get,omitempty"` // 定义适用于此路径的 GET 操作。
Put *PathItemOperationConfig `json:"put,omitempty"` // 定义适用于此路径的 PUT 操作。 Put *PathItemOperationConfig `json:"put,omitempty"` // 定义适用于此路径的 PUT 操作。
@ -51,10 +41,6 @@ type PathConfig struct {
// 描述对一个路径可执行的有效操作。 // 描述对一个路径可执行的有效操作。
// 依赖与 ACL constraints 的设置一个Path Item可以是一个空对象 // 依赖与 ACL constraints 的设置一个Path Item可以是一个空对象
// 文档的读者仍然可以看到这个路径,但是他们将无法了解到对这个路径可用的任何操作和参数。 // 文档的读者仍然可以看到这个路径,但是他们将无法了解到对这个路径可用的任何操作和参数。
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:22 2024/7/19
type PathItemConfig struct { type PathItemConfig struct {
Ref string `json:"$ref"` // 指定对此路径的外部定义的引用,引用的格式必须符合 Path Item 对象 的格式,如果引用的外部定义和此对象内的其他定义有冲突,该如何处理冲突尚未被定义。 Ref string `json:"$ref"` // 指定对此路径的外部定义的引用,引用的格式必须符合 Path Item 对象 的格式,如果引用的外部定义和此对象内的其他定义有冲突,该如何处理冲突尚未被定义。
Summary string `json:"summary"` // 一个可选的简要总结字符串,用来描述此路径内包含的所有操作。 Summary string `json:"summary"` // 一个可选的简要总结字符串,用来描述此路径内包含的所有操作。
@ -65,10 +51,6 @@ type PathItemConfig struct {
} }
// PathItemOperationConfig 描述对路径的某个操作。 // PathItemOperationConfig 描述对路径的某个操作。
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:20 2024/7/19
type PathItemOperationConfig struct { type PathItemOperationConfig struct {
Tags []string `json:"tags"` // 用于控制API文档的标签列表标签可以用于在逻辑上分组对资源的操作或作为其它用途的先决条件。 Tags []string `json:"tags"` // 用于控制API文档的标签列表标签可以用于在逻辑上分组对资源的操作或作为其它用途的先决条件。
Summary string `json:"summary"` // 对此操作行为的简短描述。 Summary string `json:"summary"` // 对此操作行为的简短描述。
@ -85,20 +67,12 @@ type PathItemOperationConfig struct {
} }
// ExternalDocs 外部文档配置 // ExternalDocs 外部文档配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:30 2024/7/19
type ExternalDocs struct { type ExternalDocs struct {
Url string `json:"url"` // 必选. 外部文档的URL地址这个值必须是URL地址格式。 Url string `json:"url"` // 必选. 外部文档的URL地址这个值必须是URL地址格式。
Description string `json:"description"` // 对引用的外部文档的简短描述。CommonMark syntax可以被用来呈现富文本格式. Description string `json:"description"` // 对引用的外部文档的简短描述。CommonMark syntax可以被用来呈现富文本格式.
} }
// PathConfigParameter 参数配置 // PathConfigParameter 参数配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:29 2024/7/19
type PathConfigParameter struct { type PathConfigParameter struct {
Name string `json:"name"` // 参数名称 Name string `json:"name"` // 参数名称
In string `json:"in"` // 必选. 参数的位置,可能的值有 "query", "header", "path" 或 "cookie"。 In string `json:"in"` // 必选. 参数的位置,可能的值有 "query", "header", "path" 或 "cookie"。
@ -114,10 +88,6 @@ type PathConfigParameter struct {
} }
// Schema ... // Schema ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:32 2024/7/19
type Schema struct { type Schema struct {
Nullable bool `json:"nullable,omitempty"` // 对于定义的schema允许发送 null 值。默认值是 false. Nullable bool `json:"nullable,omitempty"` // 对于定义的schema允许发送 null 值。默认值是 false.
Discriminator *SchemaDiscriminator `json:"discriminator,omitempty"` // 说白了, 就是一个字段可能是不同的数据结构。。。 Discriminator *SchemaDiscriminator `json:"discriminator,omitempty"` // 说白了, 就是一个字段可能是不同的数据结构。。。
@ -145,10 +115,6 @@ type Schema struct {
} }
// Property 是从 JSON Schema 提取出来的,但是做了一些调整以适应 OpenAPI Specification。 // Property 是从 JSON Schema 提取出来的,但是做了一些调整以适应 OpenAPI Specification。
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:05 2024/7/19
type Property struct { type Property struct {
Type any `json:"type,omitempty"` // 数据类型(string | []string), swagger本身的定义 Type any `json:"type,omitempty"` // 数据类型(string | []string), swagger本身的定义
Format string `json:"format,omitempty"` // 对应编程语言中的数据类型描述 Format string `json:"format,omitempty"` // 对应编程语言中的数据类型描述
@ -171,10 +137,6 @@ type Property struct {
} }
// PropertyXOf ... // PropertyXOf ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:13 2024/7/19
type PropertyXOf struct { type PropertyXOf struct {
Type string `json:"type,omitempty"` // 基础类型 Type string `json:"type,omitempty"` // 基础类型
Format string `json:"format,omitempty"` // 真实类型 Format string `json:"format,omitempty"` // 真实类型
@ -186,20 +148,12 @@ type PropertyXOf struct {
// SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验 // SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验
// discriminator 属性仅在与 oneOf, anyOf, allOf 这几个复合关键字之一一起使用时才合法. // discriminator 属性仅在与 oneOf, anyOf, allOf 这几个复合关键字之一一起使用时才合法.
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:48 2024/7/19
type SchemaDiscriminator struct { type SchemaDiscriminator struct {
PropertyName string `json:"propertyName"` // 必选. 在 payload 中表示 discriminator 值的属性的名称。 PropertyName string `json:"propertyName"` // 必选. 在 payload 中表示 discriminator 值的属性的名称。
Mapping map[string]string `json:"mapping"` // 一个映射 payload 中的值和 schema 名称或引用的对象。 Mapping map[string]string `json:"mapping"` // 一个映射 payload 中的值和 schema 名称或引用的对象。
} }
// XML 一个为 XML 模型定义微调过的元数据对象。 // XML 一个为 XML 模型定义微调过的元数据对象。
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:56 2024/7/19
type XML struct { type XML struct {
Name string `json:"name"` // 替换用于描述元素/属性的结构特性的名称。当在 items 内定义时将会影响处于此列表中的每个元素的名称。当定义于 items 之上时将会影响它说包裹的元素且仅当 wrapped 是 true 时,如果 wrapped 是 false 时它将会被忽略 Name string `json:"name"` // 替换用于描述元素/属性的结构特性的名称。当在 items 内定义时将会影响处于此列表中的每个元素的名称。当定义于 items 之上时将会影响它说包裹的元素且仅当 wrapped 是 true 时,如果 wrapped 是 false 时它将会被忽略
Namespace string `json:"namespace"` // 命名空间定义的 URI。其值必须是绝对 URI。 Namespace string `json:"namespace"` // 命名空间定义的 URI。其值必须是绝对 URI。
@ -209,10 +163,6 @@ type XML struct {
} }
// RequestBody 定义请求体 // RequestBody 定义请求体
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:17 2024/7/19
type RequestBody struct { type RequestBody struct {
Required bool `json:"required"` // 指定请求体是不是应该被包含在请求中默认值是false。 Required bool `json:"required"` // 指定请求体是不是应该被包含在请求中默认值是false。
Description string `json:"description,omitempty"` // 对请求体的简要描述可以包含使用示例CommonMark syntax可以被用来呈现富文本格式 Description string `json:"description,omitempty"` // 对请求体的简要描述可以包含使用示例CommonMark syntax可以被用来呈现富文本格式
@ -221,10 +171,6 @@ type RequestBody struct {
} }
// Media 本质即为不一样 content_type 对应的数据结构定义 // Media 本质即为不一样 content_type 对应的数据结构定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:21 2024/7/19
type Media struct { type Media struct {
Schema *Schema `json:"schema,omitempty"` // 定义此媒体类型的结构。 Schema *Schema `json:"schema,omitempty"` // 定义此媒体类型的结构。
Example map[string]any `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提供的示例。
@ -233,10 +179,6 @@ type Media struct {
} }
// Encoding 一个编码定义仅适用于一个结构属性 // Encoding 一个编码定义仅适用于一个结构属性
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:28 2024/7/19
type Encoding struct { type Encoding struct {
ContentType string `json:"content_type,omitempty"` // 对具体属性的 Content-Type的编码。默认值取决于属性的类型application/octet-stream编码适用于binary格式的stringtext/plain适用于其他原始值application/json适用于object对于array值类型的默认值取决于数组内元素的类型默认值可以是明确的媒体类型(比如application/json), 或者通配符类型的媒体类型(比如image/*), 又或者是用分号分隔的两种媒体类型。 ContentType string `json:"content_type,omitempty"` // 对具体属性的 Content-Type的编码。默认值取决于属性的类型application/octet-stream编码适用于binary格式的stringtext/plain适用于其他原始值application/json适用于object对于array值类型的默认值取决于数组内元素的类型默认值可以是明确的媒体类型(比如application/json), 或者通配符类型的媒体类型(比如image/*), 又或者是用分号分隔的两种媒体类型。
Headers map[string]*Header `json:"headers,omitempty"` // 提供附加信息的请求头键值对映射。比如Content-Disposition、Content-Type各自描述了不同的信息而且在这里将会被忽略如果请求体的媒体类型不是multipart这个属性将会被忽略。 Headers map[string]*Header `json:"headers,omitempty"` // 提供附加信息的请求头键值对映射。比如Content-Disposition、Content-Type各自描述了不同的信息而且在这里将会被忽略如果请求体的媒体类型不是multipart这个属性将会被忽略。
@ -257,10 +199,6 @@ type Encoding struct {
type Header PathConfigParameter type Header PathConfigParameter
// Example ... // Example ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:24 2024/7/19
type Example struct { type Example struct {
Summary string `json:"summary,omitempty"` // example 的简要描述。 Summary string `json:"summary,omitempty"` // example 的简要描述。
Description string `json:"description,omitempty"` // example 的详细描述。CommonMark syntax可以被用来呈现富文本格式. Description string `json:"description,omitempty"` // example 的详细描述。CommonMark syntax可以被用来呈现富文本格式.
@ -269,10 +207,6 @@ type Example struct {
} }
// Response 响应的数据结构 // Response 响应的数据结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:38 2024/7/19
type Response struct { type Response struct {
Description string `json:"description" required:"true"` // 必选. 对响应的简短描述。CommonMark syntax可以被用来呈现富文本格式. Description string `json:"description" required:"true"` // 必选. 对响应的简短描述。CommonMark syntax可以被用来呈现富文本格式.
Headers map[string]*Header `json:"headers,omitempty"` // 映射HTTP头名称到其定义。RFC7230 规定了HTTP头名称不区分大小写。如果一个响应头使用"Content-Type"作为HTTP头名称它会被忽略。 Headers map[string]*Header `json:"headers,omitempty"` // 映射HTTP头名称到其定义。RFC7230 规定了HTTP头名称不区分大小写。如果一个响应头使用"Content-Type"作为HTTP头名称它会被忽略。
@ -281,10 +215,6 @@ type Response struct {
} }
// Info 信息 // Info 信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:10 2024/4/19
type Info struct { type Info struct {
Description string `json:"description,omitempty"` // 对应用的简短描述。 CommonMark syntax 可以被用来表示富文本呈现。 Description string `json:"description,omitempty"` // 对应用的简短描述。 CommonMark syntax 可以被用来表示富文本呈现。
Title string `json:"title,omitempty" required:"true"` // 必选. 应用的名称。 Title string `json:"title,omitempty" required:"true"` // 必选. 应用的名称。
@ -295,10 +225,6 @@ type Info struct {
} }
// Contact 联系人信息 // Contact 联系人信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:08 2024/4/19
type Contact struct { type Contact struct {
Name string `json:"name,omitempty"` // 人或组织的名称。 Name string `json:"name,omitempty"` // 人或组织的名称。
Url string `json:"url,omitempty"` // 指向联系人信息的 URL 地址,必须是 URL 地址格式。 Url string `json:"url,omitempty"` // 指向联系人信息的 URL 地址,必须是 URL 地址格式。
@ -306,20 +232,12 @@ type Contact struct {
} }
// License 开源协议 // License 开源协议
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:09 2024/4/19
type License struct { type License struct {
Name string `json:"name,omitempty"` // 开源协议名 Name enums.License `json:"name,omitempty"` // 开源协议名
Url string `json:"url,omitempty"` // 开源协议地址 Url string `json:"url,omitempty"` // 开源协议地址
} }
// ServerItem server 对象结构 // ServerItem server 对象结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:18 2024/7/19
type ServerItem struct { type ServerItem struct {
Url string `json:"url,omitempty" required:"true"` // 必选. 指向目标主机的 URL 地址。这个 URL 地址支持服务器变量而且可能是相对路径,表示主机路径是相对于本文档所在的路径。当一个变量被命名为类似{brackets}时需要替换此变量。 Url string `json:"url,omitempty" required:"true"` // 必选. 指向目标主机的 URL 地址。这个 URL 地址支持服务器变量而且可能是相对路径,表示主机路径是相对于本文档所在的路径。当一个变量被命名为类似{brackets}时需要替换此变量。
Description string `json:"description,omitempty"` // 一个可选的字符串,用来描述此 URL 地址。CommonMark syntax可以被用来呈现富文本格式. Description string `json:"description,omitempty"` // 一个可选的字符串,用来描述此 URL 地址。CommonMark syntax可以被用来呈现富文本格式.
@ -327,10 +245,6 @@ type ServerItem struct {
} }
// ServerItemVariable ... // ServerItemVariable ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:22 2024/7/19
type ServerItemVariable struct { type ServerItemVariable struct {
Default string `json:"default,omitempty"` // 变量默认值 Default string `json:"default,omitempty"` // 变量默认值
Description string `json:"description,omitempty"` // 变量描述 Description string `json:"description,omitempty"` // 变量描述
@ -338,10 +252,6 @@ type ServerItemVariable struct {
} }
// TagItem 每一个标签数据结构 // TagItem 每一个标签数据结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:18 2024/7/19
type TagItem struct { type TagItem struct {
Name string `json:"name,omitempty"` // 标签名称 Name string `json:"name,omitempty"` // 标签名称
Description string `json:"description,omitempty"` // 标签描述 Description string `json:"description,omitempty"` // 标签描述

View File

@ -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
)

22
enums/data_location.go Normal file
View File

@ -0,0 +1,22 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 00:34
package enums
type DocParamLocation string
func (dpl DocParamLocation) String() string {
return string(dpl)
}
const (
DocParamLocationQuery DocParamLocation = "query"
DocParamLocationHeader DocParamLocation = "header"
DocParamLocationCookie DocParamLocation = "cookie"
DocParamLocationBody DocParamLocation = "body"
DocParamLocationPath DocParamLocation = "path"
)

46
enums/data_type.go Normal file
View File

@ -0,0 +1,46 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-22 23:58
package enums
import (
"strings"
)
type SwaggerDataType string
func (sdt SwaggerDataType) String() string {
return string(sdt)
}
// MarshalJSON 支持序列化
func (sdt SwaggerDataType) MarshalJSON() ([]byte, error) {
return []byte(`"` + sdt.String() + `"`), nil
}
// UnmarshalJSON 支持反序列化
func (sdt *SwaggerDataType) UnmarshalJSON(d []byte) error {
*sdt = SwaggerDataType(strings.Trim(string(d), `"`))
return nil
}
const (
SwaggerDataTypeInteger SwaggerDataType = "integer" // 32 位有符号
SwaggerDataTypeLong SwaggerDataType = "long" // 64 位有符号
SwaggerDataTypeFloat SwaggerDataType = "number"
SwaggerDataTypeDouble SwaggerDataType = "number"
SwaggerDataTypeNumber SwaggerDataType = "number"
SwaggerDataTypeByte SwaggerDataType = "string"
SwaggerDataTypeBinary SwaggerDataType = "binary" // 任意 8 进制序列
SwaggerDataTypeString SwaggerDataType = "string"
SwaggerDataTypeDate SwaggerDataType = "string"
SwaggerDataTypePassword SwaggerDataType = "password"
SwaggerDataTypeBoolean SwaggerDataType = "boolean"
SwaggerDataTypeArray SwaggerDataType = "array"
SwaggerDataTypeObject SwaggerDataType = "object"
SwaggerDataTypeApiKey SwaggerDataType = "apikey"
)

116
enums/license.go Normal file
View File

@ -0,0 +1,116 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 09:40
package enums
import (
"strings"
)
type License string
func (l License) String() string {
return string(l)
}
// MarshalJSON 支持序列化
func (l License) MarshalJSON() ([]byte, error) {
return []byte(`"` + l.String() + `"`), nil
}
// UnmarshalJSON 支持反序列化
func (l *License) UnmarshalJSON(d []byte) error {
*l = License(strings.Trim(string(d), `"`))
return nil
}
const (
LicenseAfl30 License = "AFL-3.0"
LicenseAgpl30 License = "AGPL-3.0"
LicenseApache10 License = "Apache-1.0"
LicenseApache11 License = "Apache-1.1"
LicenseApache20 License = "Apache-2.0"
LicenseArtistic20 License = "Artistic-2.0"
LicenseBsd2Clause License = "BSD-2-Clause"
LicenseBsd3Clause License = "BSD-3-Clause"
LicenseBsd4Clause License = "BSD-4-Clause"
LicenseBsl10 License = "BSL-1.0"
LicenseCcBy40 License = "CC-BY-4.0"
LicenseCcBySa40 License = "CC-BY-SA-4.0"
LicenseCc010 License = "CC0-1.0"
LicenseEcl20 License = "ECL-2.0"
LicenseEpl10 License = "EPL-1.0"
LicenseEpl20 License = "EPL-2.0"
LicenseEupl11 License = "EUPL-1.1"
LicenseEupl12 License = "EUPL-1.2"
LicenseGpl20 License = "GPL-2.0"
LicenseGpl30 License = "GPL-3.0"
LicenseIsc License = "ISC"
LicenseLgpl21 License = "LGPL-2.1"
LicenseLgpl30 License = "LGPL-3.0"
LicenseLppl13c License = "LPPL-1.3c"
LicenseMit License = "MIT"
LicenseMpl20 License = "MPL-2.0"
LicenseMsPl License = "MS-PL"
LicenseMsRl License = "MS-RL"
LicenseMulanpsl10 License = "MulanPSL-1.0"
LicenseMulanpubl10 License = "MulanPubL-1.0"
LicenseMulanpubl20 License = "MulanPubL-2.0"
LicenseNcsa License = "NCSA"
LicenseOfl11 License = "OFL-1.1"
LicenseOsl30 License = "OSL-3.0"
LicensePostgresql License = "PostgreSQL"
LicenseUpl10 License = "UPL-1.0"
LicenseUnlicense License = "Unlicense"
LicenseWtfpl License = "WTFPL"
LicenseZlib License = "Zlib"
)
var (
// LicenseUrlTable 洗衣链接表
LicenseUrlTable = map[License]string{
LicenseAfl30: "https://spdx.org/licenses/AFL-3.0",
LicenseAgpl30: "https://www.gnu.org/licenses/agpl-3.0.txt",
LicenseApache10: "https://www.apache.org/licenses/LICENSE-1.0",
LicenseApache11: "https://www.apache.org/licenses/LICENSE-1.1",
LicenseApache20: "https://www.apache.org/licenses/LICENSE-2.0.txt",
LicenseArtistic20: "https://spdx.org/licenses/Artistic-2.0",
LicenseBsd2Clause: "https://opensource.org/license/BSD-2-Clause",
LicenseBsd3Clause: "https://opensource.org/license/BSD-3-Clause",
LicenseBsd4Clause: "https://directory.fsf.org/wiki/License:BSD-4-Clause",
LicenseBsl10: "https://www.boost.org/LICENSE_1_0.txt",
LicenseCcBy40: "https://creativecommons.org/licenses/by/4.0/legalcode.txt",
LicenseCcBySa40: "https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt",
LicenseCc010: "https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt",
LicenseEcl20: "https://opensource.org/license/ecl-2-0",
LicenseEpl10: "https://www.eclipse.org/org/documents/epl-1.0/EPL-1.0.txt",
LicenseEpl20: "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt",
LicenseEupl11: "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf",
LicenseEupl12: "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf",
LicenseGpl20: "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC1",
LicenseGpl30: "https://www.gnu.org/licenses/gpl-3.0.html#license-text",
LicenseIsc: "https://spdx.org/licenses/ISC",
LicenseLgpl21: "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
LicenseLgpl30: "https://www.gnu.org/licenses/lgpl-3.0-standalone.html",
LicenseLppl13c: "https://www.latex-project.org/lppl/lppl-1-3c.txt",
LicenseMit: "https://spdx.org/licenses/MIT",
LicenseMpl20: "https://www.mozilla.org/en-US/MPL/2.0/",
LicenseMsPl: "https://opensource.org/license/ms-pl-html",
LicenseMsRl: "https://opensource.org/license/ms-rl-html",
LicenseMulanpsl10: "http://license.coscl.org.cn/MulanPSL",
LicenseMulanpubl10: "http://license.coscl.org.cn/MulanPubL-1.0",
LicenseMulanpubl20: "http://license.coscl.org.cn/MulanPubL-2.0",
LicenseNcsa: "https://spdx.org/licenses/NCSA",
LicenseOfl11: "https://openfontlicense.org/documents/OFL.txt",
LicenseOsl30: "https://opensource.org/license/osl-3-0-php",
LicensePostgresql: "https://www.postgresql.org/about/licence/",
LicenseUpl10: "https://spdx.org/licenses/UPL-1.0",
LicenseUnlicense: "https://unlicense.org/",
LicenseWtfpl: "https://spdx.org/licenses/WTFPL",
LicenseZlib: "https://www.zlib.net/zlib_license.html",
}
)

20
enums/ref.go Normal file
View File

@ -0,0 +1,20 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 00:40
package enums
// RefPrefix 各种ref引用的前缀定义
type RefPrefix string
func (rp RefPrefix) String() string {
return string(rp)
}
const (
RefPrefixSchemaDefinition RefPrefix = "#/definitions/" // schema下的 $ref 下 definitions 的前缀
RefPrefixSchemaResponse RefPrefix = "#/responses/" // schema下的 $ref 下 response 的前缀
)

21
enums/ui_theme.go Normal file
View File

@ -0,0 +1,21 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 01:03
package enums
type SwaggerUITheme string
func (sut SwaggerUITheme) String() string {
return string(sut)
}
const (
SwaggerUIThemeDefault SwaggerUITheme = "swaggerUI" // 文档默认主题
SwaggerUIThemeKnife4go SwaggerUITheme = "knife4go" // knife4go 主题
SwaggerUIThemeYDocLucky SwaggerUITheme = "ydoc-lucky-ui" // YDoc Lucky UI 主题: https://github.com/NoBugBoy/LuckyUI
SwaggerUIThemeRedocFree SwaggerUITheme = "redoc-free" // redoc UI 主题, 开源免费版: https://github.com/Redocly/redoc
)

19
enums/version.go Normal file
View File

@ -0,0 +1,19 @@
// Package enums ...
//
// Description : enums ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 00:50
package enums
type SwaggerVersion string
func (sv SwaggerVersion) String() string {
return string(sv)
}
const (
SwaggerDocVersion2 SwaggerVersion = "2.0"
SwaggerDocVersion3 SwaggerVersion = "3.0.0"
)

95
geerate_option.go Normal file
View File

@ -0,0 +1,95 @@
// Package api_doc ...
//
// Description : api_doc ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 09:30
package api_doc
import (
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/enums"
)
// SetGenerateOption 设置文档生成选项
type SetGenerateOption func(opt *define.OpenapiDoc)
// generateOption 生成文档的一些配置选项
type generateOption struct {
license enums.License // 文档的license
description string // 文档的描述
title string // 文档的标题
}
// WithDocLicense 设置文档协议名称 + 协议链接
func WithDocLicense(l enums.License) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
if l == "" {
return
}
opt.Info.License.Name = l
opt.Info.License.Url = enums.LicenseUrlTable[l]
}
}
// WithDocDescription 设置文档描述
func WithDocDescription(desc string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
if desc == "" {
return
}
opt.Info.Description = desc
}
}
// WithDocTitle 设置文档标题
func WithDocTitle(title string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
if len(title) == 0 {
return
}
opt.Info.Title = title
}
}
// WithDocVersion 设置文档版本
func WithDocVersion(version string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
opt.Info.Version = version
}
}
// WithDocContactName 设置文档联系人名称
func WithDocContactName(name string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
if name == "" {
return
}
opt.Info.Contact.Name = name
}
}
// WithDocContactEmail 设置文档联系人邮箱
func WithDocContactEmail(email string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
opt.Info.Contact.Email = email
}
}
// WithDocContactHomePage 设置文档联系人主页
func WithDocContactHomePage(url string) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
opt.Info.Contact.Url = url
}
}
// WithDocServers 设置文档服务器列表
func WithDocServers(serverList []*define.ServerItem) SetGenerateOption {
return func(opt *define.OpenapiDoc) {
if len(serverList) == 0 {
return
}
opt.Servers = serverList
}
}

View File

@ -10,12 +10,14 @@ package api_doc
import ( import (
"errors" "errors"
"fmt" "fmt"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
"net/http" "net/http"
"reflect" "reflect"
"strings" "strings"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/enums"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
) )
// NewOpenapiDoc ... // NewOpenapiDoc ...
@ -23,48 +25,39 @@ import (
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 15:56 2024/7/22 // Date : 15:56 2024/7/22
func NewOpenapiDoc(info *define.Info, servers []*define.ServerItem) *Generate { func NewOpenapiDoc(ofs ...SetGenerateOption) *Generate {
if nil == info { // 初始默认值
info = &define.Info{ docCfg := &define.OpenapiDoc{
Openapi: consts.SwaggerDocVersion3,
Info: &define.Info{
Description: "openapi接口文档", Description: "openapi接口文档",
Title: "openapi接口文档", Title: "openapi接口文档",
TermsOfService: "", TermsOfService: "",
Contact: nil, Contact: &define.Contact{
License: nil,
Version: "0.0.1",
}
}
if len(info.Version) == 0 {
info.Version = "0.0.1"
}
if nil == info.License {
info.License = &define.License{
Name: consts.LicenseApache20,
Url: consts.LicenseUrlTable[consts.LicenseApache20],
}
}
if nil == info.Contact {
info.Contact = &define.Contact{
Name: "研发人员(developer)", Name: "研发人员(developer)",
Url: "", Url: "",
Email: "", Email: "",
},
License: &define.License{
Name: enums.LicenseApache20,
Url: enums.LicenseUrlTable[consts.LicenseApache20],
},
Version: "0.0.1",
},
Servers: []*define.ServerItem{},
Components: &define.Components{Schemas: map[string]*define.Schema{}},
Tags: make([]*define.TagItem, 0),
Paths: make(map[string]*define.PathConfig),
} }
}
if nil == servers { for _, option := range ofs {
servers = []*define.ServerItem{} option(docCfg)
} }
return &Generate{ return &Generate{
readMethodList: []string{ readMethodList: []string{
http.MethodGet, http.MethodHead, http.MethodConnect, http.MethodOptions, http.MethodTrace, http.MethodGet, http.MethodHead, http.MethodConnect, http.MethodOptions, http.MethodTrace,
}, },
docData: &define.OpenapiDoc{ docData: docCfg,
Openapi: consts.SwaggerDocVersion3,
Info: info,
Servers: servers,
Components: &define.Components{Schemas: map[string]*define.Schema{}},
Tags: make([]*define.TagItem, 0),
Paths: make(map[string]*define.PathConfig),
},
} }
} }
@ -82,45 +75,7 @@ func (g *Generate) Doc() *define.OpenapiDoc {
return g.docData return g.docData
} }
// SetLicense 设置文档协议
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:56 2024/8/14
func (g *Generate) SetLicense(name string, url string) {
g.docData.Info.License.Name = name
g.docData.Info.License.Url = url
}
// AddTag 新增tag
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:23 2024/8/14
func (g *Generate) AddTag(tagName string, tagDesc string) {
isHasTag := false
for _, item := range g.docData.Tags {
if item.Name == tagName {
if len(tagDesc) > 0 {
item.Description = tagDesc
}
isHasTag = true
break
}
}
if !isHasTag {
g.docData.Tags = append(g.docData.Tags, &define.TagItem{
Name: tagName,
Description: tagDesc,
})
}
}
// AddServer 添加server // AddServer 添加server
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:45 2024/8/14
func (g *Generate) AddServer(serverDomain string, serverDesc string, serverVariable map[string]*define.ServerItemVariable) { func (g *Generate) AddServer(serverDomain string, serverDesc string, serverVariable map[string]*define.ServerItemVariable) {
if nil == serverVariable { if nil == serverVariable {
serverVariable = make(map[string]*define.ServerItemVariable) serverVariable = make(map[string]*define.ServerItemVariable)
@ -149,35 +104,7 @@ func (g *Generate) AddServer(serverDomain string, serverDesc string, serverVaria
} }
} }
// AddApi 新增Api
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:04 2024/8/14
//
// baseCfg : 接口基础配置, 示例数据
//
// &define.UriBaseConfig{
// Uri: "/foo/bar",
// Method: http.MethodPost,
// ContentType: ["application/json"],
// TagList: []string{"测试标签"},
// Summary: "这是一份示例基础配置",
// Description: "这是一份示例基础配置",
// }
//
// paramList : 参数列表
//
// resultList : 返回值列表
func (g *Generate) AddApi(baseCfg *define.UriBaseConfig, paramList []*define.ParamConfig, resultList []*define.ResultConfig) error {
return nil
}
// AddApiFromInAndOut 通过请求参数的 // AddApiFromInAndOut 通过请求参数的
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:22 2025/2/9
func (g *Generate) AddApiFromInAndOut(uriPrefix string, paramType reflect.Type, resultType reflect.Type) error { func (g *Generate) AddApiFromInAndOut(uriPrefix string, paramType reflect.Type, resultType reflect.Type) error {
if paramType.Kind() == reflect.Ptr { if paramType.Kind() == reflect.Ptr {
paramType = paramType.Elem() paramType = paramType.Elem()
@ -260,10 +187,6 @@ func (g *Generate) setApiDoc(baseCfg *define.UriBaseConfig, apiDocCfg *define.Pa
} }
// getApiDocBaseCfg 获取接口文档的基础配置 // getApiDocBaseCfg 获取接口文档的基础配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:10 2025/2/14
func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType reflect.Type) *define.PathItemOperationConfig { func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType reflect.Type) *define.PathItemOperationConfig {
cfg := &define.PathItemOperationConfig{ cfg := &define.PathItemOperationConfig{
Tags: baseCfg.TagList, Tags: baseCfg.TagList,
@ -279,7 +202,7 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
Ref: "", Ref: "",
}, },
Responses: map[string]*define.Response{ Responses: map[string]*define.Response{
fmt.Sprintf("%v", http.StatusOK): &define.Response{ fmt.Sprintf("%v", http.StatusOK): {
Content: map[string]*define.Media{}, Content: map[string]*define.Media{},
}, },
}, },
@ -295,12 +218,12 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
param = strings.TrimSuffix(param, "}") param = strings.TrimSuffix(param, "}")
cfg.Parameters = append(cfg.Parameters, &define.PathConfigParameter{ cfg.Parameters = append(cfg.Parameters, &define.PathConfigParameter{
Name: param, Name: param,
In: consts.SwaggerParameterInPath, In: enums.DocParamLocationPath.String(),
Description: param, Description: param,
Required: true, Required: true,
Deprecated: false, Deprecated: false,
Schema: &define.Schema{ Schema: &define.Schema{
Type: consts.SwaggerDataTypeString, Type: enums.SwaggerDataTypeString.String(),
Format: consts.DataTypeString.String(), Format: consts.DataTypeString.String(),
}, },
AllowEmptyValue: false, AllowEmptyValue: false,
@ -311,10 +234,6 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
} }
// ParseReadConfigParam 解析get类请求参数 // ParseReadConfigParam 解析get类请求参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:55 2025/2/14
func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseReqCfg *define.PathItemOperationConfig, inputType reflect.Type) { func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseReqCfg *define.PathItemOperationConfig, inputType reflect.Type) {
if inputType.Kind() == reflect.Ptr { if inputType.Kind() == reflect.Ptr {
inputType = inputType.Elem() inputType = inputType.Elem()

1
go.mod
View File

@ -5,7 +5,6 @@ go 1.23.0
toolchain go1.24.1 toolchain go1.24.1
require ( require (
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
github.com/gin-gonic/gin v1.10.1 github.com/gin-gonic/gin v1.10.1

4
go.sum
View File

@ -1,5 +1,5 @@
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995 h1:LmPRAf0AsxRVFPibdpZR89ajlsz8hof2IvMMyTqiEq4= git.zhangdeman.cn/zhangdeman/api-doc/enums v0.0.0-20250425024726-cc17224cb995 h1:LmPRAf0AsxRVFPibdpZR89ajlsz8hof2IvMMyTqiEq4=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc= git.zhangdeman.cn/zhangdeman/api-doc/enums v0.0.0-20250425024726-cc17224cb995/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
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 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI= git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 h1:/GLQaFoLb+ciHOtAS2BIyPNnf4O5ME3AC5PUaJY9kfs= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 h1:/GLQaFoLb+ciHOtAS2BIyPNnf4O5ME3AC5PUaJY9kfs=

View File

@ -9,6 +9,7 @@ package api_doc
import ( import (
"errors" "errors"
"git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/serialize"
) )

View File

@ -8,10 +8,11 @@
package api_doc package api_doc
import ( import (
"git.zhangdeman.cn/gateway/api-doc/define"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"git.zhangdeman.cn/gateway/api-doc/define"
) )
var ( var (

View File

@ -9,11 +9,12 @@ package api_doc
import ( import (
"errors" "errors"
"net/http"
"strings"
"git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/serialize"
"net/http"
"strings"
) )
// ParseSwagger2 解析swagger2.0版本文档 // ParseSwagger2 解析swagger2.0版本文档

View File

@ -10,12 +10,13 @@ package swagger
import ( import (
"errors" "errors"
"fmt" "fmt"
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
"net/http" "net/http"
"sort" "sort"
"strings" "strings"
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
) )
// HandleOpenapiDocRes ... // HandleOpenapiDocRes ...

View File

@ -8,12 +8,14 @@
package swagger package swagger
import ( import (
"net/http"
"strings"
"git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/enums"
"git.zhangdeman.cn/gateway/api-doc/util" "git.zhangdeman.cn/gateway/api-doc/util"
"git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper" "git.zhangdeman.cn/zhangdeman/wrapper"
"net/http"
"strings"
) )
// Generate 生成文档 // Generate 生成文档
@ -25,7 +27,7 @@ func Generate(docConfig *define.SwaggerInput) (*define.Swagger, error) {
formatDocConfig(docConfig) formatDocConfig(docConfig)
swaggerInfo := &define.Swagger{ swaggerInfo := &define.Swagger{
Schemes: docConfig.Schemes, Schemes: docConfig.Schemes,
Swagger: consts.SwaggerDocVersion2, Swagger: enums.SwaggerDocVersion2.String(),
Host: docConfig.Host, Host: docConfig.Host,
BasePath: docConfig.BasePath, BasePath: docConfig.BasePath,
Info: docConfig.Info, Info: docConfig.Info,
@ -228,7 +230,7 @@ func generateParameterDefinitions(swaggerInfo *define.Swagger, uri string, paren
if subPathArr[1] == "[]" { if subPathArr[1] == "[]" {
swaggerInfo.Definitions[parentPath].Properties[subPathArr[0]] = &define.SwaggerDefinitionProperty{ swaggerInfo.Definitions[parentPath].Properties[subPathArr[0]] = &define.SwaggerDefinitionProperty{
Description: paramConfig.Description, Description: paramConfig.Description,
Type: consts.SwaggerDataTypeArray, Type: enums.SwaggerDataTypeArray.String(),
Items: &define.SwaggerDefinitionPropertyItem{ Items: &define.SwaggerDefinitionPropertyItem{
Type: util.GetSwaggerType(paramConfig.Type), Type: util.GetSwaggerType(paramConfig.Type),
Ref: "", Ref: "",
@ -242,7 +244,7 @@ func generateParameterDefinitions(swaggerInfo *define.Swagger, uri string, paren
} else { } else {
swaggerInfo.Definitions[parentPath].Properties[subPathArr[0]] = &define.SwaggerDefinitionProperty{ swaggerInfo.Definitions[parentPath].Properties[subPathArr[0]] = &define.SwaggerDefinitionProperty{
Description: "参数描述", Description: "参数描述",
Type: consts.SwaggerDataTypeObject, Type: enums.SwaggerDataTypeObject.String(),
AllOf: []map[string]string{ AllOf: []map[string]string{
{ {
consts.SwaggerRefKey: getRefValue(parentPath + "." + subPathArr[0]), consts.SwaggerRefKey: getRefValue(parentPath + "." + subPathArr[0]),
@ -288,7 +290,7 @@ func generateParameterDefinitions(swaggerInfo *define.Swagger, uri string, paren
AllOf: nil, AllOf: nil,
} }
if itemSwaggerDefinition.Type == consts.SwaggerDataTypeObject { if itemSwaggerDefinition.Type == consts.SwaggerDataTypeObject {
itemSwaggerDefinition.AllOf = []map[string]string{map[string]string{ itemSwaggerDefinition.AllOf = []map[string]string{{
consts.SwaggerRefKey: getRefValue(parentPath + "." + subPathArr[0]), consts.SwaggerRefKey: getRefValue(parentPath + "." + subPathArr[0]),
}} }}
} else if itemSwaggerDefinition.Type == consts.SwaggerDataTypeArray { } else if itemSwaggerDefinition.Type == consts.SwaggerDataTypeArray {

View File

@ -10,10 +10,10 @@ package swagger
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"net/http" "net/http"
"testing" "testing"
"git.zhangdeman.cn/gateway/api-doc/define"
) )
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
@ -37,7 +37,7 @@ func TestGenerate(t *testing.T) {
Version: "", Version: "",
}, },
PathConfigList: []*define.SwaggerPathInput{ PathConfigList: []*define.SwaggerPathInput{
&define.SwaggerPathInput{ {
Uri: "/test", Uri: "/test",
Method: http.MethodPost, Method: http.MethodPost,
ContentType: consts.MimeTypeJson, ContentType: consts.MimeTypeJson,
@ -45,7 +45,7 @@ func TestGenerate(t *testing.T) {
Description: "测试接口", Description: "测试接口",
TagList: []string{"测试接口生成"}, TagList: []string{"测试接口生成"},
ParameterList: []*define.SwaggerParameterInput{ ParameterList: []*define.SwaggerParameterInput{
&define.SwaggerParameterInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "姓名", Description: "姓名",
Name: "name", Name: "name",
@ -53,7 +53,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: []interface{}{"zhang", "de", "man"}, EnumList: []interface{}{"zhang", "de", "man"},
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "性别", Description: "性别",
Name: "person.sex", Name: "person.sex",
@ -61,7 +61,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: []interface{}{"man", "woman", "other"}, EnumList: []interface{}{"man", "woman", "other"},
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "性别", Description: "性别",
Name: "person.job.list.[]", Name: "person.job.list.[]",
@ -69,7 +69,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: nil, EnumList: nil,
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeInt.String(), Type: consts.DataTypeInt.String(),
Description: "年份", Description: "年份",
Name: "person.job.year.[]", Name: "person.job.year.[]",
@ -77,7 +77,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: nil, EnumList: nil,
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeInt.String(), Type: consts.DataTypeInt.String(),
Description: "测试工作", Description: "测试工作",
Name: "person.job.test", Name: "person.job.test",
@ -85,7 +85,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: nil, EnumList: nil,
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeInt.String(), Type: consts.DataTypeInt.String(),
Description: "年龄", Description: "年龄",
Name: "age", Name: "age",
@ -93,7 +93,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: []interface{}{18, 19, 20}, EnumList: []interface{}{18, 19, 20},
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeInt.String(), Type: consts.DataTypeInt.String(),
Description: "年龄", Description: "年龄",
Name: "test_list.[].age", Name: "test_list.[].age",
@ -101,7 +101,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: []interface{}{18, 19, 20}, EnumList: []interface{}{18, 19, 20},
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "年龄", Description: "年龄",
Name: "test_list.[].name", Name: "test_list.[].name",
@ -109,7 +109,7 @@ func TestGenerate(t *testing.T) {
Required: true, Required: true,
EnumList: nil, EnumList: nil,
}, },
&define.SwaggerParameterInput{ {
Type: consts.DataTypeMapAnyAny.String(), Type: consts.DataTypeMapAnyAny.String(),
Description: "测试global_map", Description: "测试global_map",
Name: "obj", Name: "obj",
@ -119,23 +119,23 @@ func TestGenerate(t *testing.T) {
}, },
}, },
ResponseList: []*define.SwaggerResponseInput{ ResponseList: []*define.SwaggerResponseInput{
&define.SwaggerResponseInput{ {
Code: "200", Code: "200",
Description: "成功", Description: "成功",
List: []*define.SwaggerResponseItemInput{ List: []*define.SwaggerResponseItemInput{
&define.SwaggerResponseItemInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "姓名", Description: "姓名",
Field: "nick_name", Field: "nick_name",
IsRequired: false, IsRequired: false,
}, },
&define.SwaggerResponseItemInput{ {
Type: consts.DataTypeString.String(), Type: consts.DataTypeString.String(),
Description: "昵称", Description: "昵称",
Field: "person.nick_name", Field: "person.nick_name",
IsRequired: false, IsRequired: false,
}, },
&define.SwaggerResponseItemInput{ {
Type: consts.DataTypeMapAnyAny.String(), Type: consts.DataTypeMapAnyAny.String(),
Description: "测试返回生成map", Description: "测试返回生成map",
Field: "obj", Field: "obj",

View File

@ -8,32 +8,24 @@
package api_doc package api_doc
import ( import (
"embed"
"fmt" "fmt"
"net/http"
"path/filepath"
"strings"
"git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/enums"
"git.zhangdeman.cn/gateway/api-doc/theme"
"git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/consts"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
knife4goFiles "github.com/go-webtools/knife4go" knife4goFiles "github.com/go-webtools/knife4go"
knife4goGin "github.com/go-webtools/knife4go/gin" knife4goGin "github.com/go-webtools/knife4go/gin"
swaggerFiles "github.com/swaggo/files" swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
"net/http"
"path/filepath"
"strings"
) )
//go:embed ydoc-lucky-ui/*
var ydocUIFiles embed.FS
//go:embed redoc-free/index.html
var redocFreeIndexContent string
// NewSwaggerUI ... // NewSwaggerUI ...
// func NewSwaggerUI(info *define.Info, servers []*define.ServerItem, uiTheme enums.SwaggerUITheme) *SwaggerUI {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:21 2025/2/15
func NewSwaggerUI(info *define.Info, servers []*define.ServerItem, uiTheme string) *SwaggerUI {
return &SwaggerUI{ return &SwaggerUI{
docInstance: NewOpenapiDoc(info, servers), docInstance: NewOpenapiDoc(info, servers),
uiTheme: uiTheme, uiTheme: uiTheme,
@ -42,25 +34,17 @@ func NewSwaggerUI(info *define.Info, servers []*define.ServerItem, uiTheme strin
type SwaggerUI struct { type SwaggerUI struct {
docInstance *Generate // 文档实例 docInstance *Generate // 文档实例
uiTheme string // 文档主题, swaggerUI / knife4go, 默认 knife4go uiTheme enums.SwaggerUITheme // 文档主题, swaggerUI / knife4go, 默认 knife4go
router *gin.Engine router *gin.Engine
baseUri string baseUri string
} }
// DocInstance 文档实例 // DocInstance 文档实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 13:23 2025/2/16
func (su *SwaggerUI) DocInstance() *Generate { func (su *SwaggerUI) DocInstance() *Generate {
return su.docInstance return su.docInstance
} }
// RegisterHandler ... // RegisterHandler ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:00 2025/2/16
func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) { func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
su.router = router su.router = router
baseUri = strings.TrimRight(baseUri, "/") baseUri = strings.TrimRight(baseUri, "/")
@ -80,7 +64,7 @@ func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
{ {
"name": "服务文档", "name": "服务文档",
"url": "doc.json", "url": "doc.json",
"swaggerVersion": consts.SwaggerDocVersion3, "swaggerVersion": enums.SwaggerDocVersion3.String(),
}, },
}) })
ctx.Abort() ctx.Abort()
@ -92,7 +76,7 @@ func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
{ {
"name": "服务文档", "name": "服务文档",
"url": baseUri + "/doc.json", "url": baseUri + "/doc.json",
"swaggerVersion": consts.SwaggerDocVersion3, "swaggerVersion": enums.SwaggerDocVersion3.String(),
}, },
}) })
// ctx.JSON(http.StatusOK, swaggerInstance.docInstance.Data()) // ctx.JSON(http.StatusOK, swaggerInstance.docInstance.Data())
@ -100,20 +84,16 @@ func (su *SwaggerUI) RegisterHandler(router *gin.Engine, baseUri string) {
} }
// Handler 访问文档的接口处理 // Handler 访问文档的接口处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:34 2025/2/15
func (su *SwaggerUI) Handler() func(ctx *gin.Context) { func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
switch su.uiTheme { switch su.uiTheme {
case define.SwaggerUIThemeKnife4go: case enums.SwaggerUIThemeKnife4go:
return su.HandleKnife4goUI() return su.HandleKnife4goUI()
case define.SwaggerUIThemeYDocLucky: case enums.SwaggerUIThemeYDocLucky:
// YDoc-Lucky-UI 主题处理 // YDoc-Lucky-UI 主题处理
return su.HandleLuckyUI() return su.HandleLuckyUI()
case define.SwaggerUIThemeDefault: case enums.SwaggerUIThemeDefault:
return su.HandleSwaggerUI() return su.HandleSwaggerUI()
case define.SwaggerUIThemeRedocFree: case enums.SwaggerUIThemeRedocFree:
// redoc免费版 // redoc免费版
return su.HandleRedocFreeUI() return su.HandleRedocFreeUI()
default: default:
@ -122,15 +102,11 @@ func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
} }
// HandleLuckyUI ... // HandleLuckyUI ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:04 2025/2/16
func (su *SwaggerUI) HandleLuckyUI() func(ctx *gin.Context) { func (su *SwaggerUI) HandleLuckyUI() func(ctx *gin.Context) {
// su.router.StaticFS(su.baseUri+"/assets", http.FS(ydocUIFiles)) // su.router.StaticFS(su.baseUri+"/assets", http.FS(ydocUIFiles))
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, su.baseUri) fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, su.baseUri)
byteData, _ := ydocUIFiles.ReadFile(filepath.Join(define.SwaggerUIThemeYDocLucky, fileRealPath)) byteData, _ := theme.YdocUIFiles.ReadFile(filepath.Join(enums.SwaggerUIThemeYDocLucky.String(), fileRealPath))
if strings.HasSuffix(ctx.Request.RequestURI, "html") { if strings.HasSuffix(ctx.Request.RequestURI, "html") {
byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", su.baseUri)) byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", su.baseUri))
} }
@ -141,17 +117,13 @@ func (su *SwaggerUI) HandleLuckyUI() func(ctx *gin.Context) {
} else if strings.HasSuffix(ctx.Request.RequestURI, "js") { } else if strings.HasSuffix(ctx.Request.RequestURI, "js") {
contentType = "application/javascript" contentType = "application/javascript"
} }
ctx.Header("Content-Type", contentType) ctx.Header(consts.HeaderKeyContentType.String(), contentType)
ctx.String(http.StatusOK, string(byteData)) ctx.String(http.StatusOK, string(byteData))
ctx.Abort() ctx.Abort()
} }
} }
// HandleKnife4goUI ... // HandleKnife4goUI ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:38 2025/2/15
func (su *SwaggerUI) HandleKnife4goUI() func(ctx *gin.Context) { func (su *SwaggerUI) HandleKnife4goUI() func(ctx *gin.Context) {
resetOption := func(cfg *knife4goGin.Config) { resetOption := func(cfg *knife4goGin.Config) {
if nil == cfg { if nil == cfg {
@ -163,19 +135,11 @@ func (su *SwaggerUI) HandleKnife4goUI() func(ctx *gin.Context) {
} }
// HandleSwaggerUI ... // HandleSwaggerUI ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:41 2025/2/15
func (su *SwaggerUI) HandleSwaggerUI() func(ctx *gin.Context) { func (su *SwaggerUI) HandleSwaggerUI() func(ctx *gin.Context) {
return ginSwagger.WrapHandler(swaggerFiles.Handler) return ginSwagger.WrapHandler(swaggerFiles.Handler)
} }
// HandleRedocFreeUI 处理redoc_free主题 // HandleRedocFreeUI 处理redoc_free主题
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:40 2025/2/18
func (su *SwaggerUI) HandleRedocFreeUI() func(ctx *gin.Context) { func (su *SwaggerUI) HandleRedocFreeUI() func(ctx *gin.Context) {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
// TODO : 这部分数据支持外部传参替换 // TODO : 这部分数据支持外部传参替换
@ -186,10 +150,10 @@ func (su *SwaggerUI) HandleRedocFreeUI() func(ctx *gin.Context) {
"{{REDOC_STANDALONE_JS}}": "https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js", "{{REDOC_STANDALONE_JS}}": "https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js",
} }
for k, v := range replaceTable { for k, v := range replaceTable {
redocFreeIndexContent = strings.ReplaceAll(redocFreeIndexContent, k, v) theme.RedocFreeIndexContent = strings.ReplaceAll(theme.RedocFreeIndexContent, k, v)
} }
ctx.Header("Content-Type", "text/html; charset=utf-8") ctx.Header(consts.HeaderKeyContentType.String(), "text/html; charset=utf-8")
ctx.String(http.StatusOK, redocFreeIndexContent) ctx.String(http.StatusOK, theme.RedocFreeIndexContent)
ctx.Abort() ctx.Abort()
} }
} }

16
theme/embed.go Normal file
View File

@ -0,0 +1,16 @@
// Package theme ...
//
// Description : theme ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-08-23 09:23
package theme
import "embed"
//go:embed ydoc-lucky-ui/*
var YdocUIFiles embed.FS
//go:embed redoc-free/index.html
var RedocFreeIndexContent string

View File

Before

Width:  |  Height:  |  Size: 156 B

After

Width:  |  Height:  |  Size: 156 B

View File

Before

Width:  |  Height:  |  Size: 340 KiB

After

Width:  |  Height:  |  Size: 340 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -8,9 +8,10 @@
package util package util
import ( import (
"git.zhangdeman.cn/zhangdeman/consts"
"net/http" "net/http"
"strings" "strings"
"git.zhangdeman.cn/zhangdeman/consts"
) )
// GetParameterDefaultLocation 获取参数的默认位置 // GetParameterDefaultLocation 获取参数的默认位置

View File

@ -8,10 +8,11 @@
package api_doc package api_doc
import ( import (
"git.zhangdeman.cn/zhangdeman/consts"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"git.zhangdeman.cn/zhangdeman/consts"
) )
var ( var (
@ -33,10 +34,6 @@ func (r validateRule) IsRequired(structField reflect.StructField) bool {
} }
// Enum 获取枚举值 // Enum 获取枚举值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:23 2025/2/13
func (r validateRule) Enum(structField reflect.StructField) []any { func (r validateRule) Enum(structField reflect.StructField) []any {
ruleTable := r.getValidateRuleTable(structField) ruleTable := r.getValidateRuleTable(structField)
oneOfValue, _ := ruleTable[consts.ValidatorRuleCommonOneOf.String()] oneOfValue, _ := ruleTable[consts.ValidatorRuleCommonOneOf.String()]
@ -79,10 +76,6 @@ func (r validateRule) Enum(structField reflect.StructField) []any {
} }
// Minimum 最小值 // Minimum 最小值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:51 2025/2/18
func (r validateRule) Minimum(structField reflect.StructField) *int64 { func (r validateRule) Minimum(structField reflect.StructField) *int64 {
ruleTable := r.getValidateRuleTable(structField) ruleTable := r.getValidateRuleTable(structField)
var ( var (
@ -118,10 +111,6 @@ func (r validateRule) Minimum(structField reflect.StructField) *int64 {
} }
// Maximum 最大值 // Maximum 最大值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:00 2025/2/18
func (r validateRule) Maximum(structField reflect.StructField) *int64 { func (r validateRule) Maximum(structField reflect.StructField) *int64 {
ruleTable := r.getValidateRuleTable(structField) ruleTable := r.getValidateRuleTable(structField)
var ( var (
@ -157,10 +146,6 @@ func (r validateRule) Maximum(structField reflect.StructField) *int64 {
} }
// getValidateRuleTable 解析验证规则表 // getValidateRuleTable 解析验证规则表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:29 2025/2/13
func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string { func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string {
res := map[string]string{} res := map[string]string{}
ruleStr := ParseStructFieldTag.GetValidateRule(structField) ruleStr := ParseStructFieldTag.GetValidateRule(structField)