feat: 整合elements主题
This commit is contained in:
8
go.mod
8
go.mod
@@ -6,7 +6,7 @@ toolchain go1.24.2
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee
|
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260106015608-42e268aea545
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260108031051-bf46e2083c84
|
||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708
|
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708
|
||||||
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab
|
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab
|
||||||
git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4
|
git.zhangdeman.cn/zhangdeman/graceful v0.0.0-20250529070945-92833db6f3a4
|
||||||
@@ -22,8 +22,11 @@ require (
|
|||||||
github.com/gin-contrib/timeout v1.1.0
|
github.com/gin-contrib/timeout v1.1.0
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
github.com/go-playground/validator/v10 v10.30.1
|
github.com/go-playground/validator/v10 v10.30.1
|
||||||
|
github.com/go-webtools/knife4go v1.0.4
|
||||||
github.com/jedib0t/go-pretty/v6 v6.7.8
|
github.com/jedib0t/go-pretty/v6 v6.7.8
|
||||||
github.com/mcuadros/go-defaults v1.2.0
|
github.com/mcuadros/go-defaults v1.2.0
|
||||||
|
github.com/swaggo/files v1.0.1
|
||||||
|
github.com/swaggo/gin-swagger v1.6.1
|
||||||
go.uber.org/zap v1.27.1
|
go.uber.org/zap v1.27.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,7 +60,6 @@ require (
|
|||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-redis/redis_rate/v10 v10.0.1 // indirect
|
github.com/go-redis/redis_rate/v10 v10.0.1 // indirect
|
||||||
github.com/go-webtools/knife4go v1.0.4 // indirect
|
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/goccy/go-yaml v1.19.1 // indirect
|
github.com/goccy/go-yaml v1.19.1 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
@@ -87,8 +89,6 @@ require (
|
|||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sbabiv/xml2map v1.2.1 // indirect
|
github.com/sbabiv/xml2map v1.2.1 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
github.com/swaggo/files v1.0.1 // indirect
|
|
||||||
github.com/swaggo/gin-swagger v1.6.1 // indirect
|
|
||||||
github.com/swaggo/swag v1.16.6 // indirect
|
github.com/swaggo/swag v1.16.6 // indirect
|
||||||
github.com/tidwall/gjson v1.18.0 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
github.com/tidwall/match v1.2.0 // indirect
|
github.com/tidwall/match v1.2.0 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,7 +1,7 @@
|
|||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee h1:cUrlM+87fQW8StLbGBA8EB+Ke3ZR1QslWyZqbXyD5C0=
|
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee h1:cUrlM+87fQW8StLbGBA8EB+Ke3ZR1QslWyZqbXyD5C0=
|
||||||
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee/go.mod h1:EO06OJ2rIS+s3CaXoGiX6yTuyhKFeSrgHukOY7FofHw=
|
git.zhangdeman.cn/zhangdeman/api-doc v1.0.3-0.20260107152122-a877079712ee/go.mod h1:EO06OJ2rIS+s3CaXoGiX6yTuyhKFeSrgHukOY7FofHw=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260106015608-42e268aea545 h1:A6UeeMcSqAlHUmA2coWIuiCS/W9ySylhZMa/0HbFDcQ=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260108031051-bf46e2083c84 h1:1+erCrsFvz5QuHKdraVuH7KmokUoqJULaKpWXMT6m3Y=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260106015608-42e268aea545/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20260108031051-bf46e2083c84/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
|
||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708 h1:yVr38JAgPwS/6JeYdHLDa8PXU3fTa2dnENL1JGdu3ns=
|
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708 h1:yVr38JAgPwS/6JeYdHLDa8PXU3fTa2dnENL1JGdu3ns=
|
||||||
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708/go.mod h1:iwegDT/6mX2INyxMAYxsL9pZdpEixiu1GdpHIG2It1k=
|
git.zhangdeman.cn/zhangdeman/dynamic-struct v0.0.0-20251207071238-9aa24be3d708/go.mod h1:iwegDT/6mX2INyxMAYxsL9pZdpEixiu1GdpHIG2It1k=
|
||||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
|
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
apiDocDefine "git.zhangdeman.cn/zhangdeman/api-doc/define"
|
apiDocDefine "git.zhangdeman.cn/zhangdeman/api-doc/define"
|
||||||
"git.zhangdeman.cn/zhangdeman/api-doc/enums"
|
"git.zhangdeman.cn/zhangdeman/api-doc/enums"
|
||||||
"git.zhangdeman.cn/zhangdeman/api-doc/openapi"
|
"git.zhangdeman.cn/zhangdeman/api-doc/openapi"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/consts"
|
||||||
"git.zhangdeman.cn/zhangdeman/gin/define"
|
"git.zhangdeman.cn/zhangdeman/gin/define"
|
||||||
"git.zhangdeman.cn/zhangdeman/graceful"
|
"git.zhangdeman.cn/zhangdeman/graceful"
|
||||||
"github.com/jedib0t/go-pretty/v6/table"
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
@@ -172,7 +173,7 @@ func (s *server) RegisterDocHandler() {
|
|||||||
})
|
})
|
||||||
ctx.Abort()
|
ctx.Abort()
|
||||||
}
|
}
|
||||||
}, NewSwaggerUI(fmt.Sprintf("[%v]接口文档", s.option.docConfig.Flag), s.option.docConfig.BaseUri, enums.SwaggerUITheme(s.option.docConfig.UiTheme)).Handler())
|
}, NewSwaggerUI(fmt.Sprintf("[%v]接口文档", s.option.docConfig.Flag), s.option.docConfig.BaseUri, consts.SwaggerUITheme(s.option.docConfig.UiTheme)).Handler())
|
||||||
s.router.GET("/swagger-resources", func(ctx *gin.Context) { // lucky UI获取分组信息
|
s.router.GET("/swagger-resources", func(ctx *gin.Context) { // lucky UI获取分组信息
|
||||||
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域
|
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域
|
||||||
ctx.JSON(http.StatusOK, []map[string]any{
|
ctx.JSON(http.StatusOK, []map[string]any{
|
||||||
|
|||||||
@@ -9,25 +9,17 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.zhangdeman.cn/zhangdeman/rate_limit"
|
"git.zhangdeman.cn/zhangdeman/rate_limit"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testCommon struct {
|
|
||||||
UserID uint `json:"user_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type testForm struct {
|
|
||||||
Meta `json:"-" method:"get" path:"test" rate-limit:"1/5/60" tag:"测试,验证" summary:"本地调试"`
|
|
||||||
testCommon
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewServer(t *testing.T) {
|
func TestNewServer(t *testing.T) {
|
||||||
|
|
||||||
s := NewServer(9087, WithRateLimitInstance(rate_limit.MemoryClient), WithDocConfig(&DocConfig{
|
s := NewServer(9087, WithRateLimitInstance(rate_limit.MemoryClient), WithDocConfig(&DocConfig{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
UiTheme: "ydoc-lucky-ui",
|
UiTheme: "elements",
|
||||||
BaseUri: "",
|
BaseUri: "",
|
||||||
Flag: "test-server",
|
Flag: "test-server",
|
||||||
ServerList: nil,
|
ServerList: nil,
|
||||||
@@ -42,9 +34,27 @@ func TestNewServer(t *testing.T) {
|
|||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testCategory struct {
|
||||||
|
Meta `json:"-" method:"get" path:"test" rate-limit:"1/5/60" tag:"测试,验证" summary:"本地调试"`
|
||||||
|
ID int64 `json:"id" description:"分类ID" eg:"123" binding:"required,min=10,max=100"`
|
||||||
|
Sex string `json:"sex" dc:"性别" binding:"required,oneof=man woman" enum-desc:"man:男||woman:女"`
|
||||||
|
Name string `json:"name" description:"分类名称" eg:"baichaqinghuan" binding:"required,min=8"`
|
||||||
|
}
|
||||||
|
type testProduct struct {
|
||||||
|
ID int64 `json:"id,omitempty" description:"产品ID" example:"1001" required:"true" binding:"required"`
|
||||||
|
Name string `json:"name" description:"产品名称" example:"iPhone 13" minLength:"2" maxLength:"100" required:"true"`
|
||||||
|
Price float64 `json:"price" description:"价格" example:"6999.99" min:"0"`
|
||||||
|
Stock int `json:"stock" description:"库存" example:"100" min:"0"`
|
||||||
|
Tags []string `json:"tags" description:"标签"`
|
||||||
|
Attributes map[string]string `json:"attributes" description:"属性"`
|
||||||
|
CreatedAt time.Time `json:"created_at" description:"创建时间"`
|
||||||
|
UpdatedAt *time.Time `json:"updated_at,omitempty" description:"更新时间"`
|
||||||
|
Category *testCategory `json:"category,omitempty" description:"分类"`
|
||||||
|
}
|
||||||
|
|
||||||
type testController struct {
|
type testController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc testController) Test(ctx *gin.Context, requestData *testForm) (*testCommon, error) {
|
func (tc testController) Test(ctx *gin.Context, requestData *testCategory) (*testProduct, error) {
|
||||||
return &testCommon{UserID: requestData.UserID}, nil
|
return &testProduct{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.zhangdeman.cn/zhangdeman/api-doc/enums"
|
"git.zhangdeman.cn/zhangdeman/api-doc/enums"
|
||||||
"git.zhangdeman.cn/zhangdeman/api-doc/theme"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/consts"
|
"git.zhangdeman.cn/zhangdeman/consts"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/gin/router/theme"
|
||||||
"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"
|
||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewSwaggerUI ...
|
// NewSwaggerUI ...
|
||||||
func NewSwaggerUI(docTitle string, docBaseUri string, uiTheme enums.SwaggerUITheme) *SwaggerUI {
|
func NewSwaggerUI(docTitle string, docBaseUri string, uiTheme consts.SwaggerUITheme) *SwaggerUI {
|
||||||
return &SwaggerUI{
|
return &SwaggerUI{
|
||||||
baseUri: docBaseUri,
|
baseUri: docBaseUri,
|
||||||
docTitle: docTitle,
|
docTitle: docTitle,
|
||||||
@@ -34,27 +34,55 @@ func NewSwaggerUI(docTitle string, docBaseUri string, uiTheme enums.SwaggerUIThe
|
|||||||
type SwaggerUI struct {
|
type SwaggerUI struct {
|
||||||
baseUri string
|
baseUri string
|
||||||
docTitle string
|
docTitle string
|
||||||
uiTheme enums.SwaggerUITheme // 文档主题, swaggerUI / knife4go, 默认 knife4go
|
uiTheme consts.SwaggerUITheme // 文档主题, swaggerUI / knife4go, 默认 knife4go
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler 访问文档的接口处理
|
// Handler 访问文档的接口处理
|
||||||
func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
|
func (su *SwaggerUI) Handler() func(ctx *gin.Context) {
|
||||||
switch su.uiTheme {
|
switch su.uiTheme {
|
||||||
case enums.SwaggerUIThemeKnife4go:
|
case consts.SwaggerUIThemeKnife4go:
|
||||||
return su.HandleKnife4goUI()
|
return su.HandleKnife4goUI()
|
||||||
case enums.SwaggerUIThemeYDocLucky:
|
case consts.SwaggerUIThemeYDocLucky:
|
||||||
// YDoc-Lucky-UI 主题处理
|
// YDoc-Lucky-UI 主题处理
|
||||||
return su.HandleLuckyUI()
|
return su.HandleLuckyUI()
|
||||||
case enums.SwaggerUIThemeDefault:
|
case consts.SwaggerUIThemeDefault:
|
||||||
return su.HandleSwaggerUI()
|
return su.HandleSwaggerUI()
|
||||||
case enums.SwaggerUIThemeRedocFree:
|
case consts.SwaggerUIThemeRedocFree:
|
||||||
// redoc免费版
|
// redoc免费版
|
||||||
return su.HandleRedocFreeUI()
|
return su.HandleRedocFreeUI()
|
||||||
|
case consts.SwaggerUIThemeElements:
|
||||||
|
return su.HandleElements()
|
||||||
default:
|
default:
|
||||||
return su.HandleSwaggerUI()
|
return su.HandleSwaggerUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (su *SwaggerUI) HandleElements() gin.HandlerFunc {
|
||||||
|
return func(ctx *gin.Context) {
|
||||||
|
fileRealPath := strings.TrimPrefix(ctx.Request.RequestURI, su.baseUri)
|
||||||
|
byteData, _ := theme.ElementsFiles.ReadFile(filepath.Join("elements", fileRealPath))
|
||||||
|
if strings.Contains(ctx.Request.RequestURI, ".html") {
|
||||||
|
byteData = []byte(strings.ReplaceAll(string(byteData), "{{BASE_URI}}", su.baseUri))
|
||||||
|
byteData = []byte(strings.ReplaceAll(string(byteData), "{{DOC_TITLE}}", su.docTitle))
|
||||||
|
byteData = []byte(strings.ReplaceAll(string(byteData), "{{DOC_PATH}}", "doc.json"))
|
||||||
|
ctx.Header(consts.HeaderKeyContentType.String(), "text/html; charset=utf-8")
|
||||||
|
ctx.String(http.StatusOK, string(byteData))
|
||||||
|
ctx.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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(consts.HeaderKeyContentType.String(), contentType)
|
||||||
|
ctx.String(http.StatusOK, string(byteData))
|
||||||
|
ctx.Abort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HandleLuckyUI ...
|
// HandleLuckyUI ...
|
||||||
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))
|
||||||
|
|||||||
16
router/theme/elements/index.html
Normal file
16
router/theme/elements/index.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
|
||||||
|
<title>{{DOC_TITLE}}</title>
|
||||||
|
<!-- Embed elements Elements via Web Component -->
|
||||||
|
<script src="web-components.min.js"></script>
|
||||||
|
<link href="styles.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!--github 地址: https://github.com/stoplightio/elements-->
|
||||||
|
<elements-api apiDescriptionUrl="{{DOC_PATH}}" layout="sidebar" router="hash"/>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
router/theme/elements/styles.min.css
vendored
Normal file
1
router/theme/elements/styles.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
router/theme/elements/web-components.min.js
vendored
Normal file
2
router/theme/elements/web-components.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,16 +1,19 @@
|
|||||||
// Package router ...
|
// Package theme ...
|
||||||
//
|
//
|
||||||
// Description : theme ...
|
// Description : theme ...
|
||||||
//
|
//
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
//
|
//
|
||||||
// Date : 2025-08-23 09:23
|
// Date : 2025-08-23 09:23
|
||||||
package router
|
package theme
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
||||||
//go:embed theme/ydoc-lucky-ui/*
|
//go:embed ydoc-lucky-ui/*
|
||||||
var YdocUIFiles embed.FS
|
var YdocUIFiles embed.FS
|
||||||
|
|
||||||
//go:embed theme/redoc-free/index.html
|
//go:embed redoc-free/index.html
|
||||||
var RedocFreeIndexContent string
|
var RedocFreeIndexContent string
|
||||||
|
|
||||||
|
//go:embed elements/*
|
||||||
|
var ElementsFiles embed.FS
|
||||||
Reference in New Issue
Block a user