feater: 可对自动化代码增加空方法 (#1834)

* feature:自动化代码可从自动化代码管理中增加空方法,用户不用自行组织其中的关系。
This commit is contained in:
PiexlMax(奇淼
2024-07-25 21:29:20 +08:00
committed by GitHub
parent 0fc1edf895
commit 7f9194f475
10 changed files with 379 additions and 29 deletions
@@ -81,3 +81,28 @@ func (a *AutoCodeTemplateApi) Create(c *gin.Context) {
response.OkWithMessage("创建成功", c)
}
}
// Create
// @Tags AddFunc
// @Summary 增加方法
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.AutoCode true "增加方法"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /autoCode/addFunc [post]
func (a *AutoCodeTemplateApi) AddFunc(c *gin.Context) {
var info request.AutoFunc
err := c.ShouldBindJSON(&info)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
err = autoCodeTemplateService.AddFunc(info)
if err != nil {
global.GVA_LOG.Error("注入失败!", zap.Error(err))
response.FailWithMessage("注入失败", c)
} else {
response.OkWithMessage("注入成功", c)
}
}
-1
View File
@@ -8,7 +8,6 @@ import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/utils/request"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
@@ -225,3 +225,16 @@ type AutoCodeField struct {
CheckDataSource bool `json:"checkDataSource"` // 是否检查数据源
FieldIndexType string `json:"fieldIndexType"` // 索引类型
}
type AutoFunc struct {
Package string `json:"package"`
FuncName string `json:"funcName"` // 方法名称
BusinessDB string `json:"businessDB"` // 业务库
StructName string `json:"structName"` // Struct名称
PackageName string `json:"packageName"` // 文件名称
Description string `json:"description"` // Struct中文名称
Abbreviation string `json:"abbreviation"` // Struct简称
HumpPackageName string `json:"humpPackageName"` // go文件名称
Method string `json:"method"` // 方法
IsPlugin bool `json:"isPlugin"` // 是否插件
}
+40
View File
@@ -0,0 +1,40 @@
{{if .IsPlugin}}
// {{.FuncName}} 等待开发的的{{.Description}}接口
// @Tags {{.StructName}}
// @Summary 等待开发的的{{.Description}}接口
// @accept application/json
// @Produce application/json
// @Param data query request.{{.StructName}}Search true "分页获取{{.Description}}列表"
// @Success 200 {object} response.Response{data=object,msg=string} "获取成功"
// @Router /{{.Abbreviation}}/{{.FuncName}} [{{.Method}}]
func (a *{{.Abbreviation}}) {{.FuncName}}(c *gin.Context) {
//
err := service{{ .StructName }}.{{.FuncName}}()
if err != nil {
global.GVA_LOG.Error("失败!", zap.Error(err))
response.FailWithMessage("失败", c)
return
}
response.OkWithData("返回数据",c)
}
{{- else -}}
// {{.FuncName}} 等待开发的的{{.Description}}接口
// @Tags {{.StructName}}
// @Summary 等待开发的的{{.Description}}接口
// @accept application/json
// @Produce application/json
// @Param data query {{.Package}}Req.{{.StructName}}Search true "成功"
// @Success 200 {object} response.Response{data=object,msg=string} "成功"
// @Router /{{.Abbreviation}}/{{.FuncName}} [{{.Method}}]
func ({{.Abbreviation}}Api *{{.StructName}}Api){{.FuncName}}(c *gin.Context) {
//
if err := {{.Abbreviation}}Service.{{.FuncName}}(); err != nil {
global.GVA_LOG.Error("失败!", zap.Error(err))
response.FailWithMessage("失败", c)
} else {
response.OkWithData("返回数据",c)
}
}
{{end}}
+25
View File
@@ -0,0 +1,25 @@
{{- $db := "" }}
{{- if eq .BusinessDB "" }}
{{- $db = "global.GVA_DB" }}
{{- else}}
{{- $db = printf "global.MustGetGlobalDBByDBName(\"%s\")" .BusinessDB }}
{{- end}}
{{if .IsPlugin}}
// {{.FuncName}} 请实现方法
// Author [yourname](https://github.com/yourname)
func (s *{{.Abbreviation}}) {{.FuncName}}() (err error) {
db := {{$db}}.Model(&model.{{.StructName}}{})
return db.Error
}
{{- else -}}
// {{.FuncName}} 请实现方法
// Author [yourname](https://github.com/yourname)
func ({{.Abbreviation}}Service *{{.StructName}}Service){{.FuncName}}() (err error) {
//
db := {{$db}}.Model(&{{.Package}}.{{.StructName}}{})
return db.Error
}
{{end}}
+1
View File
@@ -17,6 +17,7 @@ func (s *AutoCodeRouter) InitAutoCodeRouter(Router *gin.RouterGroup, RouterPubli
{
autoCodeRouter.POST("preview", autoCodeTemplateApi.Preview) // 获取自动创建代码预览
autoCodeRouter.POST("createTemp", autoCodeTemplateApi.Create) // 创建自动化代码
autoCodeRouter.POST("addFunc", autoCodeTemplateApi.AddFunc) // 为代码插入方法
}
{
autoCodeRouter.POST("getPackage", autoCodePackageApi.All) // 获取package包
@@ -137,6 +137,9 @@ func (s *autoCodePackage) Templates(ctx context.Context) ([]string, error) {
if entries[i].Name() == "page" {
continue
} // page 为表单生成器
if entries[i].Name() == "function" {
continue
} // function 为函数生成器
if entries[i].Name() == "preview" {
continue
} // preview 为预览代码生成器的代码
+125 -4
View File
@@ -7,8 +7,12 @@ import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
model "github.com/flipped-aurora/gin-vue-admin/server/model/system"
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
"github.com/flipped-aurora/gin-vue-admin/server/utils/ast"
utilsAst "github.com/flipped-aurora/gin-vue-admin/server/utils/ast"
"github.com/pkg/errors"
"go/ast"
"go/format"
"go/parser"
"go/token"
"gorm.io/gorm"
"os"
"path/filepath"
@@ -132,7 +136,7 @@ func (s *autoCodeTemplate) Preview(ctx context.Context, info request.AutoCode) (
return preview, nil
}
func (s *autoCodeTemplate) generate(ctx context.Context, info request.AutoCode, entity model.SysAutoCodePackage) (map[string]strings.Builder, map[string]string, map[string]ast.Ast, error) {
func (s *autoCodeTemplate) generate(ctx context.Context, info request.AutoCode, entity model.SysAutoCodePackage) (map[string]strings.Builder, map[string]string, map[string]utilsAst.Ast, error) {
templates, asts, _, err := AutoCodePackage.templates(ctx, entity, info)
if err != nil {
return nil, nil, nil, err
@@ -151,12 +155,12 @@ func (s *autoCodeTemplate) generate(ctx context.Context, info request.AutoCode,
}
code[create] = builder
} // 生成文件
injections := make(map[string]ast.Ast, len(asts))
injections := make(map[string]utilsAst.Ast, len(asts))
if info.AutoMigrate {
for key, value := range asts {
keys := strings.Split(key, "=>")
if len(keys) == 2 {
if keys[1] == ast.TypePluginInitializeV2 {
if keys[1] == utilsAst.TypePluginInitializeV2 {
continue
}
var builder strings.Builder
@@ -176,3 +180,120 @@ func (s *autoCodeTemplate) generate(ctx context.Context, info request.AutoCode,
} // 注入代码
return code, templates, injections, nil
}
func (s *autoCodeTemplate) AddFunc(info request.AutoFunc) error {
autoPkg := model.SysAutoCodePackage{}
err := global.GVA_DB.First(&autoPkg, "package_name = ?", info.Package).Error
if err != nil {
return err
}
if autoPkg.Template != "package" {
info.IsPlugin = true
}
err = s.addTemplateToFile("api", info)
if err != nil {
return err
}
err = s.addTemplateToFile("server", info)
if err != nil {
return err
}
err = s.addTemplateToAst("router", info)
return nil
}
func (s *autoCodeTemplate) getTemplateStr(t string, info request.AutoFunc) (string, error) {
tempPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "resource", "function", t+".go.tpl")
files, err := template.ParseFiles(tempPath)
if err != nil {
return "", errors.Wrapf(err, "[filepath:%s]读取模版文件失败!", tempPath)
}
var builder strings.Builder
err = files.Execute(&builder, info)
if err != nil {
fmt.Println(err.Error())
return "", errors.Wrapf(err, "[filpath:%s]生成文件失败!", tempPath)
}
return builder.String(), nil
}
func (s *autoCodeTemplate) addTemplateToAst(t string, info request.AutoFunc) error {
tPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "router", info.Package, info.HumpPackageName+".go")
funcName := fmt.Sprintf("Init%sRouter", info.StructName)
stmtStr := fmt.Sprintf("%sRouterWithoutAuth.%s(\"%s\", %sApi.%s)", info.Abbreviation, info.Method, info.FuncName, info.Abbreviation, info.FuncName)
if info.IsPlugin {
tPath = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", info.Package, "router", info.HumpPackageName+".go")
stmtStr = fmt.Sprintf("group.%s(\"%s\", api%s.%s)", info.Method, info.FuncName, info.StructName, info.FuncName)
funcName = "Init"
}
src, err := os.ReadFile(tPath)
fileSet := token.NewFileSet()
astFile, err := parser.ParseFile(fileSet, "", src, 0)
if err != nil {
fmt.Println(err)
}
funcDecl := utilsAst.FindFunction(astFile, funcName)
stmtNode := utilsAst.CreateStmt(stmtStr)
for i := len(funcDecl.Body.List) - 1; i >= 0; i-- {
st := funcDecl.Body.List[i]
// 使用类型断言来检查stmt是否是一个块语句
if blockStmt, ok := st.(*ast.BlockStmt); ok {
// 如果是,插入代码 跳出
blockStmt.List = append(blockStmt.List, stmtNode)
break
}
}
// 创建一个新的文件
f, err := os.Create(tPath)
if err != nil {
return err
}
defer f.Close()
if err := format.Node(f, fileSet, astFile); err != nil {
return err
}
return err
}
func (s *autoCodeTemplate) addTemplateToFile(t string, info request.AutoFunc) error {
getTemplateStr, err := s.getTemplateStr(t, info)
if err != nil {
return err
}
var target string
switch t {
case "api":
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", info.Package, info.HumpPackageName+".go")
case "server":
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", info.Package, info.HumpPackageName+".go")
}
if info.IsPlugin {
switch t {
case "api":
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", info.Package, "api", info.HumpPackageName+".go")
case "server":
target = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", info.Package, "service", info.HumpPackageName+".go")
}
}
// 打开文件,如果不存在则返回错误
file, err := os.OpenFile(target, os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return err
}
defer file.Close()
// 写入内容
_, err = fmt.Fprintln(file, getTemplateStr)
if err != nil {
fmt.Printf("写入文件失败: %s\n", err.Error())
return err
}
return nil
}