feat: 初步完成"导入表结构"和"删除表结构"接口

This commit is contained in:
geeknonerd
2023-04-13 08:59:22 +08:00
parent 42d98ea046
commit 3d2e99e704
9 changed files with 449 additions and 19 deletions

23
server/config/gen.go Normal file
View File

@@ -0,0 +1,23 @@
package config
//GenConfig 代码生成器公共配置
var GenConfig = genConfig{
// 基础包名
PackageName: "like",
// 后台包名
AdminPackage: "like.admin",
// 实体包名
ModelsPackage: "like.models",
// 是否去除表前缀
IsRemoveTablePrefix: true,
// 生成代码根路径
GenRootPath: "target",
}
type genConfig struct {
PackageName string
AdminPackage string
ModelsPackage string
IsRemoveTablePrefix bool
GenRootPath string
}

View File

@@ -0,0 +1,93 @@
package generator
//GenConstants 代码生成常量
var GenConstants = genConstants{
UTF8: "utf-8", //编码
TplCrud: "crud", //单表 (增删改查)
TplTree: "tree", //树表 (增删改查)
QueryLike: "LIKE", //模糊查询
QueryEq: "=", //相等查询
Require: 1, //需要的
}
//GoConstants Go相关常量
var GoConstants = goConstants{
TypeString: "string", //字符串类型
TypeFloat: "float64", //浮点型
TypeInt: "int", //整型
TypeDate: "time.Time", //时间类型
}
//SqlConstants 数据库相关常量
var SqlConstants = sqlConstants{
//数据库字符串类型
ColumnTypeStr: []string{"char", "varchar", "nvarchar", "varchar2"},
//数据库文本类型
ColumnTypeText: []string{"tinytext", "text", "mediumtext", "longtext"},
//数据库时间类型
ColumnTypeTime: []string{"datetime", "time", "date", "timestamp"},
//数据库数字类型
ColumnTypeNumber: []string{"tinyint", "smallint", "mediumint", "int", "integer", "bit", "bigint",
"float", "double", "decimal"},
//时间日期字段名
ColumnTimeName: []string{"create_time", "update_time", "delete_time", "start_time", "end_time"},
//页面不需要插入字段
ColumnNameNotAdd: []string{"id", "is_delete", "create_time", "update_time", "delete_time"},
//页面不需要编辑字段
ColumnNameNotEdit: []string{"is_delete", "create_time", "update_time", "delete_time"},
//页面不需要列表字段
ColumnNameNotList: []string{"id", "intro", "content", "is_delete", "delete_time"},
//页面不需要查询字段
ColumnNameNotQuery: []string{"is_delete", "create_time", "update_time", "delete_time"},
}
//HtmlConstants HTML相关常量
var HtmlConstants = htmlConstants{
HtmlInput: "input", //文本框
HtmlTextarea: "textarea", //文本域
HtmlSelect: "select", //下拉框
HtmlRadio: "radio", //单选框
HtmlDatetime: "datetime", //日期控件
HtmlImageUpload: "imageUpload", //图片上传控件
HtmlFileUpload: "fileUpload", //文件上传控件
HtmlEditor: "editor", //富文本控件
}
type genConstants struct {
UTF8 string
TplCrud string
TplTree string
QueryLike string
QueryEq string
Require uint8
}
type goConstants struct {
TypeString string
TypeFloat string
TypeInt string
TypeDate string
}
type sqlConstants struct {
ColumnTypeStr []string
ColumnTypeText []string
ColumnTypeTime []string
ColumnTypeNumber []string
ColumnTimeName []string
ColumnNameNotAdd []string
ColumnNameNotEdit []string
ColumnNameNotList []string
ColumnNameNotQuery []string
}
type htmlConstants struct {
HtmlInput string
HtmlTextarea string
HtmlSelect string
HtmlRadio string
HtmlDatetime string
HtmlImageUpload string
HtmlFileUpload string
HtmlEditor string
}

View File

@@ -9,6 +9,7 @@ import (
"likeadmin/generator/service/gen"
"likeadmin/middleware"
"likeadmin/util"
"strings"
)
var GenGroup = core.Group("/gen", newGenHandler, regGen, middleware.TokenAuth())
@@ -20,8 +21,10 @@ func newGenHandler(srv gen.IGenerateService) *genHandler {
func regGen(rg *gin.RouterGroup, group *core.GroupBase) error {
return group.Reg(func(handle *genHandler) {
rg.GET("/db", handle.dbTables)
rg.GET("/list", handle.List)
rg.GET("/detail", handle.Detail)
rg.GET("/list", handle.list)
rg.GET("/detail", handle.detail)
rg.POST("/importTable", handle.importTable)
rg.POST("/delTable", handle.delTable)
})
}
@@ -44,7 +47,7 @@ func (gh genHandler) dbTables(c *gin.Context) {
}
//List 生成列表
func (gh genHandler) List(c *gin.Context) {
func (gh genHandler) list(c *gin.Context) {
var page request.PageReq
var listReq req.ListTableReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &page)) {
@@ -58,7 +61,7 @@ func (gh genHandler) List(c *gin.Context) {
}
//Detail 生成详情
func (gh genHandler) Detail(c *gin.Context) {
func (gh genHandler) detail(c *gin.Context) {
var detailReq req.DetailTableReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &detailReq)) {
return
@@ -66,3 +69,23 @@ func (gh genHandler) Detail(c *gin.Context) {
res, err := gh.srv.Detail(detailReq.ID)
response.CheckAndRespWithData(c, res, err)
}
//ImportTable 导入表结构
func (gh genHandler) importTable(c *gin.Context) {
var importReq req.ImportTableReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &importReq)) {
return
}
err := gh.srv.ImportTable(strings.Split(importReq.Tables, ","))
response.CheckAndResp(c, err)
}
//DelTable 删除表结构
func (gh genHandler) delTable(c *gin.Context) {
var delReq req.DelTableReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &delReq)) {
return
}
err := gh.srv.DelTable(delReq.Ids)
response.CheckAndResp(c, err)
}

View File

@@ -20,3 +20,13 @@ type ListTableReq struct {
type DetailTableReq struct {
ID uint `form:"id" binding:"required,gt=0"` // 主键
}
//ImportTableReq 导入表结构参数
type ImportTableReq struct {
Tables string `form:"tables" binding:"required"` // 导入的表, 用","分隔
}
//DelTableReq 删除表结构参数
type DelTableReq struct {
Ids []uint `form:"ids" binding:"required"` // 主键
}

View File

@@ -4,8 +4,8 @@ import (
"likeadmin/core"
)
//DbTablesResp 数据表返回信息
type DbTablesResp struct {
//DbTableResp 数据表返回信息
type DbTableResp struct {
TableName string `json:"tableName" structs:"tableName"` // 表的名称
TableComment string `json:"tableComment" structs:"tableComment"` // 表的描述
CreateTime core.OnlyRespTsTime `json:"createTime" structs:"createTime"` // 创建时间

View File

@@ -14,10 +14,10 @@ type IGenerateService interface {
DbTables(page request.PageReq, req req.DbTablesReq) (res response.PageResp, e error)
List(page request.PageReq, listReq req.ListTableReq) (res response.PageResp, e error)
Detail(id uint) (res resp.GenTableDetailResp, e error)
//ImportTable
ImportTable(tableNames []string) (e error)
DelTable(ids []uint) (e error)
//SyncTable
//EditTable
//DelTable
//PreviewCode
//DownloadCode
//GenCode
@@ -47,7 +47,7 @@ func (genSrv generateService) DbTables(page request.PageReq, dbReq req.DbTablesR
return
}
// 数据
var tbResp []resp.DbTablesResp
var tbResp []resp.DbTableResp
err = tbModel.Limit(limit).Offset(offset).Find(&tbResp).Error
if e = response.CheckErr(err, "DbTables Find err"); e != nil {
return
@@ -125,3 +125,61 @@ func (genSrv generateService) Detail(id uint) (res resp.GenTableDetailResp, e er
Columns: colResp,
}, e
}
//ImportTable 导入表结构
func (genSrv generateService) ImportTable(tableNames []string) (e error) {
var dbTbs []resp.DbTableResp
err := generator.GenUtil.GetDbTablesQueryByNames(genSrv.db, tableNames).Find(&dbTbs).Error
if e = response.CheckErr(err, "ImportTable Find tables err"); e != nil {
return
}
var tables []gen.GenTable
response.Copy(&tables, dbTbs)
if len(tables) == 0 {
e = response.AssertArgumentError.Make("表不存在!")
return
}
err = genSrv.db.Transaction(func(tx *gorm.DB) error {
for i := 0; i < len(tables); i++ {
//生成表信息
genTable := generator.GenUtil.InitTable(tables[i])
txErr := tx.Create(&genTable).Error
if te := response.CheckErr(txErr, "ImportTable Create table err"); te != nil {
return te
}
// 生成列信息
var columns []gen.GenTableColumn
txErr = generator.GenUtil.GetDbTableColumnsQueryByName(genSrv.db, tables[i].TableName).Find(&columns).Error
if te := response.CheckErr(txErr, "ImportTable Find columns err"); te != nil {
return te
}
for j := 0; j < len(columns); j++ {
column := generator.GenUtil.InitColumn(genTable.ID, columns[j])
txErr = tx.Create(&column).Error
if te := response.CheckErr(txErr, "ImportTable Create column err"); te != nil {
return te
}
}
}
return nil
})
e = response.CheckErr(err, "ImportTable Transaction err")
return nil
}
//DelTable 删除表结构
func (genSrv generateService) DelTable(ids []uint) (e error) {
err := genSrv.db.Transaction(func(tx *gorm.DB) error {
txErr := tx.Delete(&gen.GenTable{}, "id in ?", ids).Error
if te := response.CheckErr(txErr, "DelTable Delete GenTable err"); te != nil {
return te
}
txErr = tx.Delete(&gen.GenTableColumn{}, "table_id in ?", ids).Error
if te := response.CheckErr(txErr, "DelTable Delete GenTableColumn err"); te != nil {
return te
}
return nil
})
e = response.CheckErr(err, "DelTable Transaction err")
return
}

View File

@@ -2,6 +2,12 @@ package generator
import (
"gorm.io/gorm"
"likeadmin/config"
"likeadmin/model/gen"
"likeadmin/util"
"strconv"
"strings"
"time"
)
var GenUtil = genUtil{}
@@ -26,3 +32,186 @@ func (gu genUtil) GetDbTablesQuery(db *gorm.DB, tableName string, tableComment s
"table_name, table_comment, create_time, update_time")
return query
}
//GetDbTablesQueryByNames 根据表名集查询表
func (gu genUtil) GetDbTablesQueryByNames(db *gorm.DB, tableNames []string) *gorm.DB {
query := db.Table("information_schema.tables").Where(
`table_schema = (SELECT database())
AND table_name NOT LIKE "qrtz_%"
AND table_name NOT LIKE "gen_%"
AND table_name IN ?`, tableNames).Select(
"table_name, table_comment, create_time, update_time")
return query
}
//GetDbTableColumnsQueryByName 根据表名查询列信息
func (gu genUtil) GetDbTableColumnsQueryByName(db *gorm.DB, tableName string) *gorm.DB {
query := db.Table("information_schema.columns").Where(
`table_schema = (SELECT database())
AND table_name = ?`, tableName).Order("ordinal_position").Select(
`column_name,
(CASE WHEN (is_nullable = "no" && column_key != "PRI") THEN "1" ELSE NULL END) AS is_required,
(CASE WHEN column_key = "PRI" THEN "1" ELSE "0" END) AS is_pk,
ordinal_position AS sort, column_comment,
(CASE WHEN extra = "auto_increment" THEN "1" ELSE "0" END) AS is_increment, column_type`)
return query
}
//InitTable 初始化表
func (gu genUtil) InitTable(table gen.GenTable) gen.GenTable {
return gen.GenTable{
TableName: table.TableName,
TableComment: table.TableComment,
AuthorName: "",
EntityName: gu.ToClassName(table.TableName),
ModuleName: gu.ToModuleName(table.TableName),
FunctionName: strings.Replace(table.TableComment, "表", "", -1),
CreateTime: time.Now().Unix(),
UpdateTime: time.Now().Unix(),
}
}
//InitColumn 初始化字段列
func (gu genUtil) InitColumn(tableId uint, column gen.GenTableColumn) gen.GenTableColumn {
columnType := gu.GetDbType(column.ColumnType)
columnLen := gu.GetColumnLength(column.ColumnType)
col := gen.GenTableColumn{
TableID: tableId,
ColumnName: column.ColumnName,
ColumnComment: column.ColumnComment,
ColumnType: columnType,
ColumnLength: columnLen,
JavaField: column.ColumnName,
JavaType: GoConstants.TypeString,
QueryType: GenConstants.QueryEq,
Sort: column.Sort,
IsPk: column.IsPk,
IsIncrement: column.IsIncrement,
IsRequired: column.IsRequired,
//IsInsert: "1",
//IsEdit: "1",
//IsList: "1",
//IsQuery: "1",
//QueryType: "EQ",
//HtmlType: "input",
CreateTime: time.Now().Unix(),
UpdateTime: time.Now().Unix(),
}
if util.ToolsUtil.Contains(append(SqlConstants.ColumnTypeStr, SqlConstants.ColumnTypeText...), columnType) {
//文本域组
if columnLen >= 500 || util.ToolsUtil.Contains(SqlConstants.ColumnTypeText, columnType) {
col.HtmlType = HtmlConstants.HtmlTextarea
} else {
col.HtmlType = HtmlConstants.HtmlInput
}
} else if util.ToolsUtil.Contains(SqlConstants.ColumnTypeTime, columnType) {
//日期字段
col.JavaType = GoConstants.TypeDate
col.HtmlType = HtmlConstants.HtmlDatetime
} else if util.ToolsUtil.Contains(SqlConstants.ColumnTimeName, columnType) {
//时间字段
col.JavaType = GoConstants.TypeInt
col.HtmlType = HtmlConstants.HtmlDatetime
} else if util.ToolsUtil.Contains(SqlConstants.ColumnTypeNumber, columnType) {
//数字字段
col.HtmlType = HtmlConstants.HtmlInput
if strings.Contains(columnType, ",") {
col.JavaType = GoConstants.TypeFloat
} else {
col.JavaType = GoConstants.TypeInt
}
}
//非必填字段
if util.ToolsUtil.Contains(SqlConstants.ColumnNameNotEdit, col.ColumnName) {
col.IsRequired = 0
}
//需插入字段
if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotAdd, col.ColumnName) {
col.IsInsert = GenConstants.Require
}
//需编辑字段
if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotEdit, col.ColumnName) {
col.IsEdit = GenConstants.Require
col.IsRequired = GenConstants.Require
}
//需列表字段
if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotList, col.ColumnName) && col.IsPk == 0 {
col.IsList = GenConstants.Require
}
//需查询字段
if !util.ToolsUtil.Contains(SqlConstants.ColumnNameNotQuery, col.ColumnName) && col.IsPk == 0 {
col.IsQuery = GenConstants.Require
}
lowerColName := strings.ToLower(col.ColumnName)
//模糊查字段
if strings.HasSuffix(lowerColName, "name") || util.ToolsUtil.Contains([]string{"title", "mobile"}, lowerColName) {
col.QueryType = GenConstants.QueryLike
}
//根据字段设置
if strings.HasSuffix(lowerColName, "status") || util.ToolsUtil.Contains([]string{"is_show", "is_disable"}, lowerColName) {
//状态字段设置单选框
col.HtmlType = HtmlConstants.HtmlRadio
} else if strings.HasSuffix(lowerColName, "type") || strings.HasSuffix(lowerColName, "sex") {
//类型&性别字段设置下拉框
col.HtmlType = HtmlConstants.HtmlSelect
} else if strings.HasSuffix(lowerColName, "image") {
//图片字段设置图片上传
col.HtmlType = HtmlConstants.HtmlImageUpload
} else if strings.HasSuffix(lowerColName, "file") {
//文件字段设置文件上传
col.HtmlType = HtmlConstants.HtmlFileUpload
} else if strings.HasSuffix(lowerColName, "content") {
//富文本字段设置富文本编辑器
col.HtmlType = HtmlConstants.HtmlEditor
}
return col
}
//ToModuleName 表名转业务名
func (gu genUtil) ToModuleName(name string) string {
names := strings.Split(name, "_")
return names[len(names)-1]
}
//ToClassName 表名转类名
func (gu genUtil) ToClassName(name string) string {
tablePrefix := config.Config.DbTablePrefix
if config.GenConfig.IsRemoveTablePrefix && tablePrefix != "" {
if strings.HasPrefix(name, tablePrefix) {
name = name[len(tablePrefix):]
}
}
return util.StringUtil.ToCamelCase(name)
}
//GetDbType 获取数据库类型字段
func (gu genUtil) GetDbType(columnType string) string {
index := strings.IndexRune(columnType, '(')
if index < 0 {
return columnType
}
return columnType[:index]
}
//GetColumnLength 获取字段长度
func (gu genUtil) GetColumnLength(columnType string) int {
index := strings.IndexRune(columnType, '(')
if index < 0 {
return 0
}
length, err := strconv.Atoi(columnType[index+1 : strings.IndexRune(columnType, ')')])
if err != nil {
return 0
}
return length
}
//GetTablePriCol 获取主键列名称
func (gu genUtil) GetTablePriCol(columns []gen.GenTableColumn) string {
for _, col := range columns {
if col.IsPk == 1 {
return col.ColumnName
}
}
return ""
}

View File

@@ -28,19 +28,19 @@ type GenTableColumn struct {
TableID uint `gorm:"not null;default:0;comment:'表外键'"`
ColumnName string `gorm:"not null;default:'';comment:'列名称'"`
ColumnComment string `gorm:"not null;default:'';comment:'列描述'"`
ColumnLength string `gorm:"not null;default:0;comment:'列长度'"`
ColumnLength int `gorm:"not null;default:0;comment:'列长度'"`
ColumnType string `gorm:"not null;default:'';comment:'列类型'"`
JavaType string `gorm:"not null;default:'';comment:'类型'"`
JavaField string `gorm:"not null;default:'';comment:'字段名'"`
IsPk string `gorm:"not null;default:'0';comment:'是否主键: [1=是, 0=否]'"`
IsIncrement string `gorm:"not null;default:'0';comment:'是否自增: [1=是, 0=否]'"`
IsRequired string `gorm:"not null;default:'0';comment:'是否必填: [1=是, 0=否]'"`
IsInsert string `gorm:"not null;default:'0';comment:'是否为插入字段: [1=是, 0=否]'"`
IsEdit string `gorm:"not null;default:'0';comment:'是否编辑字段: [1=是, 0=否]'"`
IsList string `gorm:"not null;default:'0';comment:'是否列表字段: [1=是, 0=否]'"`
IsQuery string `gorm:"not null;default:'0';comment:'是否查询字段: [1=是, 0=否]'"`
QueryType string `gorm:"not null;default:'0';comment:'查询方式: [等于、不等于、大于、小于、范围]'"`
HtmlType string `gorm:"not null;default:'0';comment:'显示类型: [文本框、文本域、下拉框、复选框、单选框、日期控件]'"`
IsPk uint8 `gorm:"not null;default:0;comment:'是否主键: [1=是, 0=否]'"`
IsIncrement uint8 `gorm:"not null;default:0;comment:'是否自增: [1=是, 0=否]'"`
IsRequired uint8 `gorm:"not null;default:0;comment:'是否必填: [1=是, 0=否]'"`
IsInsert uint8 `gorm:"not null;default:0;comment:'是否为插入字段: [1=是, 0=否]'"`
IsEdit uint8 `gorm:"not null;default:0;comment:'是否编辑字段: [1=是, 0=否]'"`
IsList uint8 `gorm:"not null;default:0;comment:'是否列表字段: [1=是, 0=否]'"`
IsQuery uint8 `gorm:"not null;default:0;comment:'是否查询字段: [1=是, 0=否]'"`
QueryType string `gorm:"not null;default:'=';comment:'查询方式: [等于、不等于、大于、小于、范围]'"`
HtmlType string `gorm:"not null;default:'';comment:'显示类型: [文本框、文本域、下拉框、复选框、单选框、日期控件]'"`
DictType string `gorm:"not null;default:'';comment:'字典类型'"`
Sort int `gorm:"not null;default:0;comment:'排序编号'"`
CreateTime int64 `gorm:"autoCreateTime;not null;comment:'创建时间'"`

34
server/util/string.go Normal file
View File

@@ -0,0 +1,34 @@
package util
import (
"bytes"
"strings"
"unicode"
)
var StringUtil = stringUtil{}
//arrayUtil 数组工具类
type stringUtil struct{}
func (su stringUtil) ToSnakeCase(s string) string {
buf := bytes.Buffer{}
for i, r := range s {
if unicode.IsUpper(r) {
if i > 0 {
buf.WriteRune('_')
}
buf.WriteRune(unicode.ToLower(r))
} else {
buf.WriteRune(r)
}
}
return buf.String()
}
func (su stringUtil) ToCamelCase(s string) string {
words := strings.Split(s, "_")
for i := 1; i < len(words); i++ {
words[i] = strings.Title(words[i])
}
return strings.Join(words, "")
}