提交 2a1235a9 编写于 作者: L LeonardWang

添加代码生成中route和gorm的自动注入

上级 9c942891
...@@ -68,6 +68,22 @@ mysql: ...@@ -68,6 +68,22 @@ mysql:
local: local:
path: 'uploads/file' path: 'uploads/file'
# autocode configuration
autocode:
root: ""
server: /server
server-api: /api/v1
server-initialize: /initialize
server-model: /model
server-request: /model/request/
server-router: /router
server-service: /service
web: /web/src
web-api: /api
web-flow: /view
web-form: /view
web-table: /view
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket �?域名地址) # qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket �?域名地址)
qiniu: qiniu:
zone: 'ZoneHuadong' zone: 'ZoneHuadong'
......
package config package config
type Autocode struct { type Autocode struct {
Root string `mapstructure:"root" json:"root" yaml:"root"` Root string `mapstructure:"root" json:"root" yaml:"root"`
Server string `mapstructure:"server" json:"server" yaml:"server"` Server string `mapstructure:"server" json:"server" yaml:"server"`
SApi string `mapstructure:"server-api" json:"serverApi" yaml:"server-api"` SApi string `mapstructure:"server-api" json:"serverApi" yaml:"server-api"`
SModel string `mapstructure:"server-model" json:"serverModel" yaml:"server-model"` SInitialize string `mapstructure:"server-initialize" json:"serverInitialize" yaml:"server-initialize"`
SRequest string `mapstructure:"server-request" json:"serverRequest" yaml:"server-request"` SModel string `mapstructure:"server-model" json:"serverModel" yaml:"server-model"`
SRouter string `mapstructure:"server-router" json:"serverRouter" yaml:"server-router"` SRequest string `mapstructure:"server-request" json:"serverRequest" yaml:"server-request"`
SService string `mapstructure:"server-service" json:"serverService" yaml:"server-service"` SRouter string `mapstructure:"server-router" json:"serverRouter" yaml:"server-router"`
Web string `mapstructure:"web" json:"web" yaml:"web"` SService string `mapstructure:"server-service" json:"serverService" yaml:"server-service"`
WApi string `mapstructure:"web-api" json:"webApi" yaml:"web-api"` Web string `mapstructure:"web" json:"web" yaml:"web"`
WForm string `mapstructure:"web-form" json:"webForm" yaml:"web-form"` WApi string `mapstructure:"web-api" json:"webApi" yaml:"web-api"`
WTable string `mapstructure:"web-table" json:"webTable" yaml:"web-table"` WForm string `mapstructure:"web-form" json:"webForm" yaml:"web-form"`
WFlow string `mapstructure:"web-flow" json:"webFlow" yaml:"web-flow"` WTable string `mapstructure:"web-table" json:"webTable" yaml:"web-table"`
WFlow string `mapstructure:"web-flow" json:"webFlow" yaml:"web-flow"`
} }
...@@ -8,7 +8,7 @@ type Server struct { ...@@ -8,7 +8,7 @@ type Server struct {
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`
System System `mapstructure:"system" json:"system" yaml:"system"` System System `mapstructure:"system" json:"system" yaml:"system"`
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
// aoto // auto
AutoCode Autocode `mapstructure:"autoCode" json:"autoCode" yaml:"autoCode"` AutoCode Autocode `mapstructure:"autoCode" json:"autoCode" yaml:"autoCode"`
// gorm // gorm
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"` Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
......
...@@ -48,6 +48,9 @@ func MysqlTables(db *gorm.DB) { ...@@ -48,6 +48,9 @@ func MysqlTables(db *gorm.DB) {
model.ExaSimpleUploader{}, model.ExaSimpleUploader{},
model.ExaCustomer{}, model.ExaCustomer{},
model.SysOperationRecord{}, model.SysOperationRecord{},
// Code generated by gin-vue-admin Begin; DO NOT EDIT.
// Code generated by gin-vue-admin End; DO NOT EDIT.
) )
if err != nil { if err != nil {
global.GVA_LOG.Error("register table failed", zap.Any("err", err)) global.GVA_LOG.Error("register table failed", zap.Any("err", err))
......
...@@ -49,6 +49,9 @@ func Routers() *gin.Engine { ...@@ -49,6 +49,9 @@ func Routers() *gin.Engine {
router.InitSysDictionaryDetailRouter(PrivateGroup) // 字典详情管理 router.InitSysDictionaryDetailRouter(PrivateGroup) // 字典详情管理
router.InitFileUploadAndDownloadRouter(PrivateGroup) // 文件上传下载功能路由 router.InitFileUploadAndDownloadRouter(PrivateGroup) // 文件上传下载功能路由
router.InitExcelRouter(PrivateGroup) // 表格导入导出 router.InitExcelRouter(PrivateGroup) // 表格导入导出
// Code generated by gin-vue-admin Begin; DO NOT EDIT.
// Code generated by gin-vue-admin End; DO NOT EDIT.
} }
global.GVA_LOG.Info("router register success") global.GVA_LOG.Info("router register success")
return Router return Router
......
...@@ -134,6 +134,18 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) { ...@@ -134,6 +134,18 @@ func CreateTemp(autoCode model.AutoCodeStruct) (err error) {
return err return err
} }
} }
initializeGormFilePath := filepath.Join(global.GVA_CONFIG.AutoCode.Root,
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SInitialize, "gorm.go")
initializeRouterFilePath := filepath.Join(global.GVA_CONFIG.AutoCode.Root,
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SInitialize, "router.go")
err = utils.AutoInjectionCode(initializeGormFilePath, "MysqlTables", "model."+autoCode.StructName+"{},")
if err != nil {
return err
}
err = utils.AutoInjectionCode(initializeRouterFilePath, "Routers", "router.Init"+autoCode.StructName+"Router(PrivateGroup)")
if err != nil {
return err
}
return errors.New("创建代码成功并移动文件成功") return errors.New("创建代码成功并移动文件成功")
} else { // 打包 } else { // 打包
if err := utils.ZipFiles("./ginvueadmin.zip", fileList, ".", "."); err != nil { if err := utils.ZipFiles("./ginvueadmin.zip", fileList, ".", "."); err != nil {
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"path/filepath"
) )
//@author: [songzhibin97](https://github.com/songzhibin97) //@author: [songzhibin97](https://github.com/songzhibin97)
...@@ -154,5 +155,6 @@ func InitDB(conf request.InitDB) error { ...@@ -154,5 +155,6 @@ func InitDB(conf request.InitDB) error {
_ = writeConfig(global.GVA_VP, baseSetting) _ = writeConfig(global.GVA_VP, baseSetting)
return err return err
} }
global.GVA_CONFIG.AutoCode.Root, _ = filepath.Abs("..")
return nil return nil
} }
package utils
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"strings"
)
//@author: [LeonardWang](https://github.com/WangLeonard)
//@function: AutoInjectionCode
//@description: 向文件中固定注释位置写入代码
//@param: filepath string, funcName string, codeData string
//@return: err error
func AutoInjectionCode(filepath string, funcName string, codeData string) error {
startComment := "Code generated by gin-vue-admin Begin; DO NOT EDIT."
endComment := "Code generated by gin-vue-admin End; DO NOT EDIT."
srcData, err := ioutil.ReadFile(filepath)
if err != nil {
return err
}
srcDataLen := len(srcData)
fset := token.NewFileSet()
fparser, err := parser.ParseFile(fset, filepath, srcData, parser.ParseComments)
if err != nil {
return err
}
codeData = strings.TrimSpace(codeData)
var codeStartPos = -1
var codeEndPos = srcDataLen
var expectedFunction *ast.FuncDecl
var startCommentPos = -1
var endCommentPos = srcDataLen
// 如果指定了函数名,先寻找对应函数
if funcName != "" {
for _, decl := range fparser.Decls {
if funDecl, ok := decl.(*ast.FuncDecl); ok && funDecl.Name.Name == funcName {
expectedFunction = funDecl
codeStartPos = int(funDecl.Body.Lbrace)
codeEndPos = int(funDecl.Body.Rbrace)
break
}
}
}
// 遍历所有注释
for _, comment := range fparser.Comments {
if int(comment.Pos()) > codeStartPos && int(comment.End()) <= codeEndPos {
if startComment != "" && strings.Contains(comment.Text(), startComment) {
startCommentPos = int(comment.Pos()) // Note: Pos is the second '/'
}
if endComment != "" && strings.Contains(comment.Text(), endComment) {
endCommentPos = int(comment.Pos()) // Note: Pos is the second '/'
}
}
}
if endCommentPos == srcDataLen {
return fmt.Errorf("comment:%s not found", endComment)
}
// 在指定函数名,且函数中startComment和endComment都存在时,进行区间查重
if (codeStartPos != -1 && codeEndPos != srcDataLen) && (startCommentPos != -1 && endCommentPos != srcDataLen) && expectedFunction != nil {
if exist := checkExist(&srcData, startCommentPos, endCommentPos, expectedFunction.Body, codeData); exist {
fmt.Println("已存在")
return nil // 这里不需要返回错误?
}
}
// 两行注释中间没有换行时,会被认为是一条Comment
if startCommentPos == endCommentPos {
endCommentPos = startCommentPos + strings.Index(string(srcData[startCommentPos:]), endComment)
for srcData[endCommentPos] != '/' {
endCommentPos--
}
}
// 记录"//"之前的空字符,保持写入后的格式一致
tmpSpace := make([]byte, 0, 10)
for tmp := endCommentPos - 2; tmp >= 0; tmp-- {
if srcData[tmp] != '\n' {
tmpSpace = append(tmpSpace, srcData[tmp])
} else {
break
}
}
reverseSpace := make([]byte, 0, len(tmpSpace))
for index := len(tmpSpace) - 1; index >= 0; index-- {
reverseSpace = append(reverseSpace, tmpSpace[index])
}
// 插入数据
indexPos := endCommentPos - 1
insertData := []byte(append([]byte(codeData+"\n"), reverseSpace...))
remainData := append([]byte{}, srcData[indexPos:]...)
srcData = append(append(srcData[:indexPos], insertData...), remainData...)
// 写回数据
return ioutil.WriteFile(filepath, srcData, 0600)
}
func checkExist(srcData *[]byte, startPos int, endPos int, blockStmt *ast.BlockStmt, target string) bool {
for _, list := range blockStmt.List {
switch stmt := list.(type) {
case *ast.ExprStmt:
if callExpr, ok := stmt.X.(*ast.CallExpr); ok &&
int(callExpr.Pos()) > startPos && int(callExpr.End()) < endPos {
text := string((*srcData)[int(callExpr.Pos()-1):int(callExpr.End())])
key := strings.TrimSpace(text)
if key == target {
return true
}
}
case *ast.BlockStmt:
if checkExist(srcData, startPos, endPos, stmt, target) {
return true
}
}
}
return false
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册