365 lines
8.6 KiB
Go
365 lines
8.6 KiB
Go
package common
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"91porn-server/generate/tpl"
|
|
)
|
|
|
|
func NewGen(moduleName, tblComment string) *G {
|
|
rootPath := RootPath()
|
|
return &G{
|
|
AppGenerate: true,
|
|
WebGenerate: true,
|
|
RootPath: rootPath,
|
|
ModuleName: moduleName,
|
|
TableComment: tblComment,
|
|
}
|
|
}
|
|
|
|
type Field struct {
|
|
Name string
|
|
TypeName string
|
|
Tag string
|
|
BsonField string
|
|
FormTag string
|
|
UpdateTag string
|
|
Comment string
|
|
SubField []Field
|
|
SubStructName string
|
|
}
|
|
|
|
type G struct {
|
|
AppGenerate bool
|
|
WebGenerate bool
|
|
RootPath string
|
|
ModuleName string
|
|
StructName string
|
|
FileName string
|
|
TableName string
|
|
TableComment string
|
|
Fields []Field
|
|
}
|
|
|
|
// Generate 生成...
|
|
func (o *G) Generate(s interface{}) {
|
|
var err error
|
|
// 获取model结构
|
|
t := reflect.TypeOf(s)
|
|
o.Fields, err = o.explodeStruct(t)
|
|
if err != nil {
|
|
log(err.Error(), "error")
|
|
return
|
|
}
|
|
o.StructName = FirstUpper(t.Name())
|
|
if o.TableName == "" {
|
|
o.TableName = o.StructName
|
|
}
|
|
o.FileName = strings.ToLower(o.TableName)
|
|
|
|
// 生成变量表
|
|
v := make(map[string]string)
|
|
v["FileName"] = strings.ToLower(o.TableName)
|
|
v["ModuleName"] = o.ModuleName
|
|
v["TableComment"] = o.TableComment
|
|
v["TableName"] = o.TableName
|
|
v["StructName"] = o.StructName
|
|
v["PackageTableName"] = strings.ToLower(o.TableName)
|
|
v["RouterName"] = FirstLower(o.TableName)
|
|
v["StructDefine"] = o.genStructDefine(o.StructName, o.Fields)
|
|
v["AppRespStructFields"] = o.genAppRespStructFields(o.Fields)
|
|
v["AppRespTransferStatement"] = o.genAppRespTransferStatement(o.Fields)
|
|
v["CreateReqFields"] = o.genCreateStructFields(o.Fields)
|
|
v["CreateStatement"] = o.genCreateStatement(o.Fields)
|
|
v["UpdateReqFields"] = o.genUpdateStructFields(o.Fields)
|
|
v["UpdateStatement"] = o.genUpdateStatement(o.Fields)
|
|
|
|
// 循环配置进行生成
|
|
for tpDir, c := range tpl.Config {
|
|
// 判断是否生成 app web
|
|
if !o.AppGenerate && strings.HasPrefix(tpDir, "/app") {
|
|
continue
|
|
}
|
|
if !o.WebGenerate && strings.HasPrefix(tpDir, "/web") {
|
|
continue
|
|
}
|
|
// 遍历目录
|
|
tplPath := path.Join(o.RootPath, "/generate/tpl", tpDir)
|
|
var tpls []string
|
|
err := filepath.Walk(tplPath, func(path string, info os.FileInfo, err error) error {
|
|
if !info.IsDir() && strings.HasSuffix(info.Name(), ".tpl") {
|
|
tpls = append(tpls, path)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
log(err.Error(), "error")
|
|
return
|
|
}
|
|
// 创建文件
|
|
for _, tf := range tpls {
|
|
err = o.CreateFile(tpDir, tf, c, v)
|
|
if err != nil {
|
|
log(err.Error(), "error")
|
|
}
|
|
}
|
|
}
|
|
|
|
// 执行完成
|
|
log("生成完毕!", "info")
|
|
}
|
|
|
|
// CreateFile 根据模板创建文件
|
|
func (o *G) CreateFile(dir, tf string, conf tpl.Tpl, val map[string]string) (err error) {
|
|
val["VariablePrefix"] = FirstUpper(conf.VariablePrefix)
|
|
_, f := path.Split(tf)
|
|
f = strings.Replace(TplReplace(f, val), ".tpl", ".go", -1)
|
|
fPath := path.Join(o.RootPath, dir)
|
|
if conf.SplitDir {
|
|
fPath = path.Join(fPath, o.FileName+conf.DirSuffix)
|
|
}
|
|
// 创建目录
|
|
err = EnsurePath(fPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fPath = path.Join(fPath, f)
|
|
// 检查文件是否存在,存在则跳过
|
|
//_, err = os.Stat(fPath)
|
|
//if err == nil {
|
|
// log("目标文件已存在,不可覆盖!File:"+fPath, "warn")
|
|
// return nil
|
|
//}
|
|
|
|
log("准备写入目标文件:"+fPath, "info")
|
|
|
|
// 读取文件并替换内容
|
|
b, err := os.ReadFile(tf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tplContent := string(b)
|
|
tplContent = TplReplace(tplContent, val)
|
|
|
|
// 写入目标文件
|
|
if err := os.WriteFile(fPath, []byte(tplContent), 0755); err != nil {
|
|
log("写入目标文件:"+fPath+"失败!", "error")
|
|
return err
|
|
}
|
|
|
|
log("写入目标文件:"+fPath+"成功!", "error")
|
|
return nil
|
|
}
|
|
|
|
// genStructDefine 生成结构体定义语句
|
|
func (o *G) genStructDefine(structName string, fields []Field) string {
|
|
var s []string
|
|
sub := make(map[string][]Field)
|
|
for _, f := range fields {
|
|
tmp := fmt.Sprintf(" %s\t%s\t`%s`\t// %s", f.Name, f.TypeName, f.Tag, f.Comment)
|
|
s = append(s, tmp)
|
|
if len(f.SubField) > 0 {
|
|
sub[f.SubStructName] = f.SubField
|
|
}
|
|
}
|
|
|
|
ms := fmt.Sprintf("type %s struct {\n%s\n} \n\n", structName, strings.Join(s, "\n"))
|
|
if len(sub) == 0 {
|
|
return ms
|
|
}
|
|
var subs []string
|
|
for n, v := range sub {
|
|
subs = append(subs, o.genStructDefine(n, v))
|
|
}
|
|
ss := strings.Join(subs, "\n\n")
|
|
|
|
return ms + ss
|
|
}
|
|
|
|
// genAppRespStructFields 生成app返回结构
|
|
func (o *G) genAppRespStructFields(fields []Field) string {
|
|
var s []string
|
|
for _, f := range fields {
|
|
tmp := fmt.Sprintf(" %s\t%s\t`%s`\t// %s", f.Name, f.TypeName, f.UpdateTag, f.Comment)
|
|
s = append(s, tmp)
|
|
}
|
|
|
|
return strings.Join(s, "\n")
|
|
}
|
|
|
|
// genAppRespTransferStatement 生成app返回转换过程代码
|
|
func (o *G) genAppRespTransferStatement(fields []Field) string {
|
|
var s []string
|
|
for _, f := range fields {
|
|
tmp := fmt.Sprintf(" %s: item.%s,", f.Name, f.Name)
|
|
s = append(s, tmp)
|
|
}
|
|
str := strings.Join(s, "\n")
|
|
|
|
return str
|
|
}
|
|
|
|
// genCreateStructFields 生成创建数据字段定义
|
|
func (o *G) genCreateStructFields(fields []Field) string {
|
|
var s []string
|
|
for _, f := range fields {
|
|
fn := strings.ToLower(f.Name)
|
|
if fn == "id" || fn == "createdat" || fn == "updatedat" {
|
|
continue
|
|
}
|
|
|
|
tmp := fmt.Sprintf(" %s\t%s\t`%s`\t// %s", f.Name, f.TypeName, f.FormTag, f.Comment)
|
|
s = append(s, tmp)
|
|
}
|
|
|
|
return strings.Join(s, "\n")
|
|
}
|
|
|
|
// genCreateStatement 生成创建过程代码
|
|
func (o *G) genCreateStatement(fields []Field) string {
|
|
var s []string
|
|
hasCreateTime := false
|
|
hasUpdateTime := false
|
|
for _, f := range fields {
|
|
fn := strings.ToLower(f.Name)
|
|
if fn == "id" {
|
|
continue
|
|
}
|
|
if fn == "createdat" {
|
|
hasCreateTime = true
|
|
continue
|
|
}
|
|
if fn == "updatedat" {
|
|
hasUpdateTime = true
|
|
continue
|
|
}
|
|
|
|
tmp := fmt.Sprintf(" %s: p.%s,", f.Name, f.Name)
|
|
s = append(s, tmp)
|
|
}
|
|
str := strings.Join(s, "\n")
|
|
if hasCreateTime {
|
|
str += "\n CreatedAt: time.Now(),"
|
|
}
|
|
if hasUpdateTime {
|
|
str += "\n UpdatedAt: time.Now(),"
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
// genUpdateStructFields 生成更新数据字段定义
|
|
func (o *G) genUpdateStructFields(fields []Field) string {
|
|
var s []string
|
|
for _, f := range fields {
|
|
fn := strings.ToLower(f.Name)
|
|
if fn == "id" || fn == "createdat" || fn == "updatedat" {
|
|
continue
|
|
}
|
|
|
|
tmp := fmt.Sprintf(" %s\t*%s\t`%s`\t// %s", f.Name, f.TypeName, f.UpdateTag, f.Comment)
|
|
s = append(s, tmp)
|
|
}
|
|
|
|
return strings.Join(s, "\n")
|
|
}
|
|
|
|
// genUpdateStatement 生成更新过程代码
|
|
func (o *G) genUpdateStatement(fields []Field) string {
|
|
var s []string
|
|
hasUpdateTime := false
|
|
for _, f := range fields {
|
|
fn := strings.ToLower(f.Name)
|
|
if fn == "id" || fn == "createdat" {
|
|
continue
|
|
}
|
|
if fn == "updatedat" {
|
|
hasUpdateTime = true
|
|
continue
|
|
}
|
|
|
|
tmp := fmt.Sprintf(" if p.%s != nil {\n\t\tdata[\"%s\"] = *p.%s\n\t}", f.Name, f.BsonField, f.Name)
|
|
s = append(s, tmp)
|
|
}
|
|
str := strings.Join(s, "\n")
|
|
if hasUpdateTime {
|
|
str += "\n\tdata[\"updatedAt\"] = time.Now()\n"
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
// SetTableName 自定义表名
|
|
func (o *G) SetTableName(n string) {
|
|
o.TableName = FirstUpper(n)
|
|
}
|
|
|
|
// NoApp 不生成app
|
|
func (o *G) NoApp() {
|
|
o.AppGenerate = false
|
|
}
|
|
|
|
// NoWeb 不生成web
|
|
func (o *G) NoWeb() {
|
|
o.WebGenerate = false
|
|
}
|
|
|
|
// explodeStruct 解剖struct
|
|
func (o *G) explodeStruct(t reflect.Type) (f []Field, err error) {
|
|
if t.Kind() != reflect.Struct {
|
|
return nil, errors.New("不支持结构体以外的类型!")
|
|
}
|
|
|
|
// 遍历结构体的字段
|
|
for i := 0; i < t.NumField(); i++ {
|
|
field := t.Field(i)
|
|
jsonTag := field.Tag.Get("json")
|
|
if jsonTag == "" {
|
|
jsonTag = "-"
|
|
}
|
|
bsonTag := field.Tag.Get("bson")
|
|
if bsonTag == "" {
|
|
bsonTag = "-"
|
|
}
|
|
tag := fmt.Sprintf("json:\"%s\" bson:\"%s\"", jsonTag, bsonTag)
|
|
fTag := fmt.Sprintf("json:\"%s\" form:\"%s\" binding:\"required\"", jsonTag, jsonTag)
|
|
uTag := fmt.Sprintf("json:\"%s\"", jsonTag)
|
|
|
|
isDefinedType := strings.Count(field.Type.String(), "main.") > 0
|
|
typeName := strings.Replace(field.Type.String(), "main.", "", 1)
|
|
tmp := Field{
|
|
Name: field.Name,
|
|
TypeName: typeName,
|
|
Tag: tag,
|
|
BsonField: bsonTag,
|
|
FormTag: fTag,
|
|
UpdateTag: uTag,
|
|
Comment: field.Tag.Get("comment"),
|
|
}
|
|
if isDefinedType {
|
|
if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Pointer {
|
|
tmp.SubField, _ = o.explodeStruct(field.Type.Elem())
|
|
if field.Type.Kind() == reflect.Slice {
|
|
tmp.SubStructName = strings.TrimLeft(typeName, "[]")
|
|
} else {
|
|
tmp.SubStructName = strings.TrimLeft(typeName, "*")
|
|
}
|
|
} else if field.Type.Kind() == reflect.Struct {
|
|
tmp.SubField, _ = o.explodeStruct(field.Type)
|
|
tmp.SubStructName = typeName
|
|
}
|
|
}
|
|
|
|
f = append(f, tmp)
|
|
}
|
|
|
|
return
|
|
}
|