- 在插件助手中新增 ValidateParams 函数,用于验证传入参数是否符合定义,确保参数的完整性和正确性。 - 更新 ExecuteAction 方法,集成参数验证逻辑,提升插件执行的安全性和可靠性。 - 示例程序中添加新的选项,展示如何生成插件API文档和OpenAPI/Swagger文档,增强用户体验。 此更新提升了插件系统的健壮性,便于开发者更好地管理和使用插件功能。
768 lines
21 KiB
Go
768 lines
21 KiB
Go
package plugin
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
)
|
||
|
||
// OpenAPIGenerator 用于生成符合OpenAPI 3.0规范的API文档
|
||
type OpenAPIGenerator struct {
|
||
pm *PluginManager // 插件管理器
|
||
outputPath string // 输出路径
|
||
info map[string]interface{}
|
||
}
|
||
|
||
// NewOpenAPIGenerator 创建一个新的OpenAPI生成器
|
||
func NewOpenAPIGenerator(pm *PluginManager, outputPath string) *OpenAPIGenerator {
|
||
return &OpenAPIGenerator{
|
||
pm: pm,
|
||
outputPath: outputPath,
|
||
info: map[string]interface{}{
|
||
"title": "插件系统API",
|
||
"description": "插件系统提供的API接口文档",
|
||
"version": "1.0.0",
|
||
"contact": map[string]interface{}{
|
||
"name": "开发团队",
|
||
"email": "dev@example.com",
|
||
"url": "https://example.com",
|
||
},
|
||
},
|
||
}
|
||
}
|
||
|
||
// SetInfo 设置API文档的基本信息
|
||
func (g *OpenAPIGenerator) SetInfo(title, description, version string) {
|
||
g.info["title"] = title
|
||
g.info["description"] = description
|
||
g.info["version"] = version
|
||
}
|
||
|
||
// SetContact 设置联系人信息
|
||
func (g *OpenAPIGenerator) SetContact(name, email, url string) {
|
||
g.info["contact"] = map[string]interface{}{
|
||
"name": name,
|
||
"email": email,
|
||
"url": url,
|
||
}
|
||
}
|
||
|
||
// GenerateOpenAPI 生成OpenAPI文档
|
||
func (g *OpenAPIGenerator) GenerateOpenAPI() error {
|
||
// 确保输出目录存在
|
||
if err := os.MkdirAll(g.outputPath, 0755); err != nil {
|
||
return fmt.Errorf("创建输出目录失败: %v", err)
|
||
}
|
||
|
||
// 创建OpenAPI规范文档
|
||
openapiSpec := g.createOpenAPISpec()
|
||
|
||
// 将文档保存为JSON文件
|
||
jsonPath := filepath.Join(g.outputPath, "openapi.json")
|
||
jsonData, err := json.MarshalIndent(openapiSpec, "", " ")
|
||
if err != nil {
|
||
return fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
|
||
if err := os.WriteFile(jsonPath, jsonData, 0644); err != nil {
|
||
return fmt.Errorf("写入JSON文件失败: %v", err)
|
||
}
|
||
|
||
// 创建HTML查看器
|
||
htmlPath := filepath.Join(g.outputPath, "index.html")
|
||
htmlContent := g.createSwaggerUIHTML()
|
||
if err := os.WriteFile(htmlPath, []byte(htmlContent), 0644); err != nil {
|
||
return fmt.Errorf("写入HTML文件失败: %v", err)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// createOpenAPISpec 创建完整的OpenAPI规范文档
|
||
func (g *OpenAPIGenerator) createOpenAPISpec() map[string]interface{} {
|
||
// 基本结构
|
||
spec := map[string]interface{}{
|
||
"openapi": "3.0.0",
|
||
"info": g.info,
|
||
"servers": []map[string]interface{}{
|
||
{
|
||
"url": "/api",
|
||
"description": "API服务器",
|
||
},
|
||
},
|
||
"tags": []map[string]interface{}{},
|
||
"paths": map[string]interface{}{},
|
||
"components": map[string]interface{}{
|
||
"schemas": map[string]interface{}{},
|
||
"parameters": map[string]interface{}{},
|
||
},
|
||
}
|
||
|
||
// 获取所有插件
|
||
plugins := g.pm.GetAllPlugins()
|
||
|
||
// 生成标签(按插件类型分组)
|
||
pluginTypeMap := make(map[PluginType]bool)
|
||
for _, p := range plugins {
|
||
pluginTypeMap[p.Type()] = true
|
||
}
|
||
|
||
tags := make([]map[string]interface{}, 0)
|
||
for pType := range pluginTypeMap {
|
||
tags = append(tags, map[string]interface{}{
|
||
"name": string(pType),
|
||
"description": fmt.Sprintf("%s 类型的插件", pType),
|
||
})
|
||
}
|
||
spec["tags"] = tags
|
||
|
||
// 为每个插件生成路径
|
||
paths := make(map[string]interface{})
|
||
schemas := make(map[string]interface{})
|
||
|
||
for _, p := range plugins {
|
||
pluginName := p.Name()
|
||
pluginType := string(p.Type())
|
||
|
||
// 插件基本信息路径
|
||
pluginInfoPath := fmt.Sprintf("/plugins/{name}/info")
|
||
if _, exists := paths[pluginInfoPath]; !exists {
|
||
paths[pluginInfoPath] = map[string]interface{}{
|
||
"get": map[string]interface{}{
|
||
"summary": "获取插件信息",
|
||
"description": "获取指定插件的详细信息",
|
||
"operationId": "getPluginInfo",
|
||
"tags": []string{"Plugin"},
|
||
"parameters": []map[string]interface{}{
|
||
{
|
||
"name": "name",
|
||
"in": "path",
|
||
"description": "插件名称",
|
||
"required": true,
|
||
"schema": map[string]interface{}{
|
||
"type": "string",
|
||
},
|
||
},
|
||
},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"$ref": "#/components/schemas/PluginInfo",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"404": map[string]interface{}{
|
||
"description": "插件不存在",
|
||
},
|
||
},
|
||
},
|
||
}
|
||
}
|
||
|
||
// 定义插件操作的路径
|
||
operations := p.GetAllOperations()
|
||
for opName, opInfo := range operations {
|
||
pathTemplate := fmt.Sprintf("/plugins/{name}/execute/{action}")
|
||
|
||
// 如果路径不存在,创建路径
|
||
if _, exists := paths[pathTemplate]; !exists {
|
||
paths[pathTemplate] = map[string]interface{}{
|
||
"post": map[string]interface{}{
|
||
"summary": "执行插件操作",
|
||
"description": "对指定插件执行特定操作",
|
||
"operationId": "executePluginAction",
|
||
"tags": []string{"Plugin"},
|
||
"parameters": []map[string]interface{}{
|
||
{
|
||
"name": "name",
|
||
"in": "path",
|
||
"description": "插件名称",
|
||
"required": true,
|
||
"schema": map[string]interface{}{
|
||
"type": "string",
|
||
},
|
||
},
|
||
{
|
||
"name": "action",
|
||
"in": "path",
|
||
"description": "操作名称",
|
||
"required": true,
|
||
"schema": map[string]interface{}{
|
||
"type": "string",
|
||
},
|
||
},
|
||
},
|
||
"requestBody": map[string]interface{}{
|
||
"description": "操作参数",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"type": "object",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "操作成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"type": "object",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"400": map[string]interface{}{
|
||
"description": "参数错误",
|
||
},
|
||
"404": map[string]interface{}{
|
||
"description": "插件或操作不存在",
|
||
},
|
||
"500": map[string]interface{}{
|
||
"description": "服务器错误",
|
||
},
|
||
},
|
||
},
|
||
}
|
||
}
|
||
|
||
// 为每个操作创建特定的路径
|
||
opPath := fmt.Sprintf("/plugins/%s/actions/%s", pluginName, opName)
|
||
opRequestSchema := g.createRequestSchema(opName, opInfo, schemas)
|
||
opResponseSchema := g.createResponseSchema(opName, opInfo, schemas)
|
||
|
||
paths[opPath] = map[string]interface{}{
|
||
"post": map[string]interface{}{
|
||
"summary": getMapString(opInfo, "description", fmt.Sprintf("执行 %s", opName)),
|
||
"description": getMapString(opInfo, "description", fmt.Sprintf("在 %s 插件上执行 %s 操作", pluginName, opName)),
|
||
"operationId": fmt.Sprintf("%s_%s", pluginName, opName),
|
||
"tags": []string{pluginType},
|
||
"requestBody": map[string]interface{}{
|
||
"description": "操作参数",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": opRequestSchema,
|
||
},
|
||
},
|
||
"required": true,
|
||
},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "操作成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": opResponseSchema,
|
||
},
|
||
},
|
||
},
|
||
"400": map[string]interface{}{
|
||
"description": "参数错误",
|
||
},
|
||
"500": map[string]interface{}{
|
||
"description": "服务器错误",
|
||
},
|
||
},
|
||
},
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加通用路径
|
||
// 获取所有插件
|
||
paths["/plugins"] = map[string]interface{}{
|
||
"get": map[string]interface{}{
|
||
"summary": "获取所有插件",
|
||
"description": "获取系统中所有可用插件的列表",
|
||
"operationId": "getAllPlugins",
|
||
"tags": []string{"PluginSystem"},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"type": "array",
|
||
"items": map[string]interface{}{
|
||
"$ref": "#/components/schemas/PluginInfo",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|
||
|
||
// 按类型获取插件
|
||
paths["/plugins/type/{type}"] = map[string]interface{}{
|
||
"get": map[string]interface{}{
|
||
"summary": "按类型获取插件",
|
||
"description": "获取指定类型的所有插件",
|
||
"operationId": "getPluginsByType",
|
||
"tags": []string{"PluginSystem"},
|
||
"parameters": []map[string]interface{}{
|
||
{
|
||
"name": "type",
|
||
"in": "path",
|
||
"description": "插件类型",
|
||
"required": true,
|
||
"schema": map[string]interface{}{
|
||
"type": "string",
|
||
"enum": []string{
|
||
string(PluginTypeGeneral),
|
||
string(PluginTypeStorage),
|
||
string(PluginTypeUtils),
|
||
string(PluginTypeNetwork),
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"type": "array",
|
||
"items": map[string]interface{}{
|
||
"$ref": "#/components/schemas/PluginInfo",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|
||
|
||
// 获取插件所有操作
|
||
paths["/plugins/{name}/actions"] = map[string]interface{}{
|
||
"get": map[string]interface{}{
|
||
"summary": "获取插件所有操作",
|
||
"description": "获取指定插件支持的所有操作",
|
||
"operationId": "getPluginActions",
|
||
"tags": []string{"PluginSystem"},
|
||
"parameters": []map[string]interface{}{
|
||
{
|
||
"name": "name",
|
||
"in": "path",
|
||
"description": "插件名称",
|
||
"required": true,
|
||
"schema": map[string]interface{}{
|
||
"type": "string",
|
||
},
|
||
},
|
||
},
|
||
"responses": map[string]interface{}{
|
||
"200": map[string]interface{}{
|
||
"description": "成功",
|
||
"content": map[string]interface{}{
|
||
"application/json": map[string]interface{}{
|
||
"schema": map[string]interface{}{
|
||
"type": "object",
|
||
"additionalProperties": map[string]interface{}{
|
||
"type": "object",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
"404": map[string]interface{}{
|
||
"description": "插件不存在",
|
||
},
|
||
},
|
||
},
|
||
}
|
||
|
||
// 设置路径和组件
|
||
spec["paths"] = paths
|
||
|
||
// 添加基本模式
|
||
schemas["PluginInfo"] = map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"name": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "插件名称",
|
||
},
|
||
"version": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "插件版本",
|
||
},
|
||
"description": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "插件描述",
|
||
},
|
||
"author": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "插件作者",
|
||
},
|
||
"type": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "插件类型",
|
||
"enum": []string{
|
||
string(PluginTypeGeneral),
|
||
string(PluginTypeStorage),
|
||
string(PluginTypeUtils),
|
||
string(PluginTypeNetwork),
|
||
},
|
||
},
|
||
"enabled": map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": "插件是否启用",
|
||
},
|
||
},
|
||
"required": []string{"name", "version", "type", "enabled"},
|
||
}
|
||
|
||
// 更新组件模式
|
||
spec["components"].(map[string]interface{})["schemas"] = schemas
|
||
|
||
return spec
|
||
}
|
||
|
||
// createRequestSchema 创建操作请求的JSON Schema
|
||
func (g *OpenAPIGenerator) createRequestSchema(opName string, opInfo map[string]interface{}, schemas map[string]interface{}) map[string]interface{} {
|
||
schemaName := fmt.Sprintf("%sRequest", opName)
|
||
|
||
// 如果没有参数,返回空对象模式
|
||
params, ok := opInfo["parameters"].(map[string]interface{})
|
||
if !ok || len(params) == 0 {
|
||
return map[string]interface{}{
|
||
"type": "object",
|
||
}
|
||
}
|
||
|
||
// 创建请求模式
|
||
schema := map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{},
|
||
"required": []string{},
|
||
}
|
||
properties := schema["properties"].(map[string]interface{})
|
||
required := schema["required"].([]string)
|
||
|
||
// 添加参数
|
||
for paramName, paramInfo := range params {
|
||
if info, ok := paramInfo.(map[string]interface{}); ok {
|
||
paramType := getMapString(info, "type", "string")
|
||
paramDesc := getMapString(info, "description", "")
|
||
paramRequired := getMapBool(info, "required", false)
|
||
|
||
// 为不同类型创建不同的模式
|
||
var propSchema map[string]interface{}
|
||
|
||
switch paramType {
|
||
case "string":
|
||
propSchema = map[string]interface{}{
|
||
"type": "string",
|
||
"description": paramDesc,
|
||
}
|
||
case "integer":
|
||
propSchema = map[string]interface{}{
|
||
"type": "integer",
|
||
"description": paramDesc,
|
||
}
|
||
case "float":
|
||
propSchema = map[string]interface{}{
|
||
"type": "number",
|
||
"description": paramDesc,
|
||
}
|
||
case "boolean":
|
||
propSchema = map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": paramDesc,
|
||
}
|
||
case "array":
|
||
propSchema = map[string]interface{}{
|
||
"type": "array",
|
||
"description": paramDesc,
|
||
"items": map[string]interface{}{
|
||
"type": "object",
|
||
},
|
||
}
|
||
|
||
// 如果有元素类型信息,使用它
|
||
if elemType, ok := info["elemType"].(map[string]interface{}); ok {
|
||
elemTypeStr := getMapString(elemType, "type", "string")
|
||
propSchema["items"] = map[string]interface{}{
|
||
"type": g.mapTypeToOpenAPI(elemTypeStr),
|
||
}
|
||
}
|
||
case "object", "struct":
|
||
// 对于结构体和对象,创建一个引用
|
||
structName := fmt.Sprintf("%s_%s", schemaName, paramName)
|
||
propSchema = map[string]interface{}{
|
||
"$ref": fmt.Sprintf("#/components/schemas/%s", structName),
|
||
"description": paramDesc,
|
||
}
|
||
|
||
// 创建结构体模式
|
||
structSchema := map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{},
|
||
"required": []string{},
|
||
}
|
||
|
||
// 添加结构体字段
|
||
if fields, ok := info["fields"].(map[string]interface{}); ok {
|
||
structProps := structSchema["properties"].(map[string]interface{})
|
||
structReq := structSchema["required"].([]string)
|
||
|
||
for fieldName, fieldInfo := range fields {
|
||
if fi, ok := fieldInfo.(map[string]interface{}); ok {
|
||
fieldType := getMapString(fi, "type", "string")
|
||
fieldDesc := getMapString(fi, "description", "")
|
||
fieldRequired := getMapBool(fi, "required", false)
|
||
|
||
structProps[fieldName] = map[string]interface{}{
|
||
"type": g.mapTypeToOpenAPI(fieldType),
|
||
"description": fieldDesc,
|
||
}
|
||
|
||
if fieldRequired {
|
||
structReq = append(structReq, fieldName)
|
||
}
|
||
}
|
||
}
|
||
|
||
structSchema["required"] = structReq
|
||
}
|
||
|
||
// 添加到模式
|
||
schemas[structName] = structSchema
|
||
default:
|
||
propSchema = map[string]interface{}{
|
||
"type": "string",
|
||
"description": paramDesc,
|
||
}
|
||
}
|
||
|
||
properties[paramName] = propSchema
|
||
|
||
if paramRequired {
|
||
required = append(required, paramName)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有必填参数,删除required数组
|
||
if len(required) == 0 {
|
||
delete(schema, "required")
|
||
} else {
|
||
schema["required"] = required
|
||
}
|
||
|
||
// 添加到模式
|
||
schemas[schemaName] = schema
|
||
|
||
return map[string]interface{}{
|
||
"$ref": fmt.Sprintf("#/components/schemas/%s", schemaName),
|
||
}
|
||
}
|
||
|
||
// createResponseSchema 创建操作响应的JSON Schema
|
||
func (g *OpenAPIGenerator) createResponseSchema(opName string, opInfo map[string]interface{}, schemas map[string]interface{}) map[string]interface{} {
|
||
schemaName := fmt.Sprintf("%sResponse", opName)
|
||
|
||
// 如果没有返回值,返回空对象模式
|
||
returns, ok := opInfo["returns"].(map[string]interface{})
|
||
if !ok || len(returns) == 0 {
|
||
return map[string]interface{}{
|
||
"type": "object",
|
||
}
|
||
}
|
||
|
||
// 如果只有一个错误返回,使用简单响应
|
||
if len(returns) == 1 && returns["error"] != nil {
|
||
return map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"success": map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": "操作是否成功",
|
||
},
|
||
"error": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "错误信息",
|
||
"nullable": true,
|
||
},
|
||
},
|
||
}
|
||
}
|
||
|
||
// 创建响应模式
|
||
schema := map[string]interface{}{
|
||
"type": "object",
|
||
"properties": map[string]interface{}{
|
||
"success": map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": "操作是否成功",
|
||
},
|
||
},
|
||
}
|
||
properties := schema["properties"].(map[string]interface{})
|
||
|
||
// 遍历所有返回值
|
||
for retName, retInfo := range returns {
|
||
if retName == "error" {
|
||
properties["error"] = map[string]interface{}{
|
||
"type": "string",
|
||
"description": "错误信息",
|
||
"nullable": true,
|
||
}
|
||
continue
|
||
}
|
||
|
||
if info, ok := retInfo.(map[string]interface{}); ok {
|
||
retType := getMapString(info, "type", "string")
|
||
retDesc := getMapString(info, "description", "")
|
||
|
||
// 为不同类型创建不同的模式
|
||
var propSchema map[string]interface{}
|
||
|
||
switch retType {
|
||
case "string":
|
||
propSchema = map[string]interface{}{
|
||
"type": "string",
|
||
"description": retDesc,
|
||
}
|
||
case "integer":
|
||
propSchema = map[string]interface{}{
|
||
"type": "integer",
|
||
"description": retDesc,
|
||
}
|
||
case "float":
|
||
propSchema = map[string]interface{}{
|
||
"type": "number",
|
||
"description": retDesc,
|
||
}
|
||
case "boolean":
|
||
propSchema = map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": retDesc,
|
||
}
|
||
case "array":
|
||
propSchema = map[string]interface{}{
|
||
"type": "array",
|
||
"description": retDesc,
|
||
"items": map[string]interface{}{
|
||
"type": "object",
|
||
},
|
||
}
|
||
|
||
// 如果有元素类型信息,使用它
|
||
if elemType, ok := info["elemType"].(map[string]interface{}); ok {
|
||
elemTypeStr := getMapString(elemType, "type", "string")
|
||
propSchema["items"] = map[string]interface{}{
|
||
"type": g.mapTypeToOpenAPI(elemTypeStr),
|
||
}
|
||
}
|
||
case "object":
|
||
// 对于对象,创建嵌套模式
|
||
propSchema = map[string]interface{}{
|
||
"type": "object",
|
||
"description": retDesc,
|
||
"properties": map[string]interface{}{},
|
||
}
|
||
|
||
// 如果有属性信息,添加它们
|
||
if props, ok := info["properties"].(map[string]interface{}); ok {
|
||
propsMap := propSchema["properties"].(map[string]interface{})
|
||
|
||
for propName, propInfo := range props {
|
||
if pi, ok := propInfo.(map[string]interface{}); ok {
|
||
propType := getMapString(pi, "type", "string")
|
||
propDesc := getMapString(pi, "description", "")
|
||
|
||
propsMap[propName] = map[string]interface{}{
|
||
"type": g.mapTypeToOpenAPI(propType),
|
||
"description": propDesc,
|
||
}
|
||
}
|
||
}
|
||
}
|
||
default:
|
||
propSchema = map[string]interface{}{
|
||
"type": "string",
|
||
"description": retDesc,
|
||
}
|
||
}
|
||
|
||
properties[retName] = propSchema
|
||
}
|
||
}
|
||
|
||
// 添加到模式
|
||
schemas[schemaName] = schema
|
||
|
||
return map[string]interface{}{
|
||
"$ref": fmt.Sprintf("#/components/schemas/%s", schemaName),
|
||
}
|
||
}
|
||
|
||
// createSwaggerUIHTML 创建包含Swagger UI的HTML文件
|
||
func (g *OpenAPIGenerator) createSwaggerUIHTML() string {
|
||
return `<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>插件系统API文档</title>
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4.5.0/swagger-ui.css" >
|
||
<style>
|
||
html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
|
||
*, *:before, *:after { box-sizing: inherit; }
|
||
body { margin: 0; background: #fafafa; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="swagger-ui"></div>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4.5.0/swagger-ui-bundle.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4.5.0/swagger-ui-standalone-preset.js"></script>
|
||
<script>
|
||
window.onload = function() {
|
||
const ui = SwaggerUIBundle({
|
||
url: "openapi.json",
|
||
dom_id: '#swagger-ui',
|
||
deepLinking: true,
|
||
presets: [
|
||
SwaggerUIBundle.presets.apis,
|
||
SwaggerUIStandalonePreset
|
||
],
|
||
plugins: [
|
||
SwaggerUIBundle.plugins.DownloadUrl
|
||
],
|
||
layout: "StandaloneLayout"
|
||
});
|
||
window.ui = ui;
|
||
};
|
||
</script>
|
||
</body>
|
||
</html>`
|
||
}
|
||
|
||
// mapTypeToOpenAPI 将内部类型映射到OpenAPI类型
|
||
func (g *OpenAPIGenerator) mapTypeToOpenAPI(internalType string) string {
|
||
switch internalType {
|
||
case "integer":
|
||
return "integer"
|
||
case "float":
|
||
return "number"
|
||
case "boolean":
|
||
return "boolean"
|
||
case "array":
|
||
return "array"
|
||
case "object", "struct":
|
||
return "object"
|
||
default:
|
||
return "string"
|
||
}
|
||
}
|