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

Merged
zhangdeman merged 5 commits from feature/upgrade into master 2025-08-23 10:54:33 +08:00
19 changed files with 214 additions and 153 deletions
Showing only changes of commit bac8242f5e - Show all commits

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

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

View File

@ -42,4 +42,5 @@ const (
SwaggerDataTypeBoolean SwaggerDataType = "boolean" SwaggerDataTypeBoolean SwaggerDataType = "boolean"
SwaggerDataTypeArray SwaggerDataType = "array" SwaggerDataTypeArray SwaggerDataType = "array"
SwaggerDataTypeObject SwaggerDataType = "object" SwaggerDataTypeObject SwaggerDataType = "object"
SwaggerDataTypeApiKey SwaggerDataType = "apikey"
) )

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

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 ...
@ -260,10 +262,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 +277,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 +293,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 +309,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,12 @@ 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/wrapper"
) )
// HandleOpenapiDocRes ... // HandleOpenapiDocRes ...

View File

@ -8,12 +8,12 @@
package swagger package swagger
import ( import (
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/util"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
"net/http" "net/http"
"strings" "strings"
"git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/gateway/api-doc/util"
"git.zhangdeman.cn/zhangdeman/wrapper"
) )
// Generate 生成文档 // Generate 生成文档
@ -288,7 +288,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,32 +119,32 @@ 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",
IsRequired: false, IsRequired: false,
},
},
},
}, },
}, },
},
},
},
}, },
}) })
byteData, _ := json.MarshalIndent(res, "", "\t") byteData, _ := json.MarshalIndent(res, "", "\t")

View File

@ -10,16 +10,18 @@ package api_doc
import ( import (
"embed" "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/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/* //go:embed ydoc-lucky-ui/*
@ -29,11 +31,7 @@ var ydocUIFiles embed.FS
var redocFreeIndexContent string 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,
@ -41,26 +39,18 @@ 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 +70,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 +82,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 +90,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 +108,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, _ := 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 +123,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 +141,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 : 这部分数据支持外部传参替换
@ -188,7 +158,7 @@ func (su *SwaggerUI) HandleRedocFreeUI() func(ctx *gin.Context) {
for k, v := range replaceTable { for k, v := range replaceTable {
redocFreeIndexContent = strings.ReplaceAll(redocFreeIndexContent, k, v) redocFreeIndexContent = strings.ReplaceAll(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, redocFreeIndexContent)
ctx.Abort() ctx.Abort()
} }

View File

@ -8,7 +8,6 @@
package util package util
import ( import (
"git.zhangdeman.cn/zhangdeman/consts"
"net/http" "net/http"
"strings" "strings"
) )

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)