fix 适配pg数据库,代码生成支持excel导入

This commit is contained in:
yxh 2023-12-13 17:34:36 +08:00
parent da1bece186
commit 79440bf6fe
24 changed files with 17304 additions and 72 deletions

View File

@ -67,7 +67,7 @@ type ToolsGenTableEditRes struct {
// ToolsGenRelationTableReq 获取关联表数据
type ToolsGenRelationTableReq struct {
g.Meta `path:"/tools/gen/relationTable" tags:"代码生成" method:"get" summary:"获取关联表数据"`
g.Meta `path:"/tools/gen/relationTable" tags:"代码生成" method:"get" summary:"获取关联表数据"`
TableName string `p:"tableName"` //表名称
TableComment string `p:"tableComment"` //表描述
commonApi.PageReq
@ -78,7 +78,7 @@ type ToolsGenRelationTableReq struct {
type ToolsGenRelationTableRes struct {
g.Meta `mime:"application/json"`
commonApi.ListRes
Data []*model.ToolsGenTableColumnsData `json:"data"`
Data []*model.ToolsGenTableColumnsData `json:"data"`
}
// ToolsGenTableColumnsEditReq 生成信息修改参数
@ -106,6 +106,7 @@ type ToolsGenTableColumnsEditReq struct {
TreeParentCode string `p:"tree_parent_code"`
TreeName string `p:"tree_name"`
ExcelPort string `p:"excelPort"`
ExcelImp string `p:"excelImp"`
UseSnowId string `p:"useSnowId"`
UseVirtual string `p:"useVirtual"`
}

2
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/apache/rocketmq-client-go/v2 v2.1.1
github.com/casbin/casbin/v2 v2.42.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.4
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.4
github.com/gogf/gf/v2 v2.5.7
github.com/gorilla/websocket v1.5.0
@ -47,6 +48,7 @@ require (
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect

4
go.sum
View File

@ -54,6 +54,8 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.4 h1:xAmYQZEDBDoce/q5s7UTibYHHW0DSTApfmXVC/i0/zI=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.4/go.mod h1:lEgzJw5PLBOEJ4gZHgs1GwsbjyBLBttN2sN63rYRNhk=
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6 h1:0WHVzqITqIBu/NNPXt3tN2eiWAGiNjs9sg6wh+WbUvY=
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6/go.mod h1:qZCTNQ0n2gHcuBwM9wUl3pelync3xK0gTnChJZD6f0I=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.4 h1:t4Ls/E022VMk5hc3a4IgWO3xGNEQRXicCTOrFymZdDg=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.4/go.mod h1:1P7id3OWFb3lkp1zBKdGqRoVXgYAjATzky++tGh2vxc=
github.com/gogf/gf/v2 v2.5.7 h1:h+JSoD6z3d2q0uGszvtahrSm4DiM2ECyNjyTwKIo8wE=
@ -96,6 +98,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=

View File

@ -38,7 +38,8 @@ type ToolsGenTableColumns struct {
SortColumn string // 排序字段名
SortType string // 排序方式 (asc顺序 desc倒序)
ShowDetail string // 是否有查看详情功能
ExcelPort string // 是否有导入导出excel功能
ExcelPort string // 是否有导出excel功能
ExcelImp string // 是否有导入excel功能
UseSnowId string //主键是否使用雪花ID
UseVirtual string // 树表是否使用虚拟表
}
@ -64,6 +65,7 @@ var toolsGenTableColumns = ToolsGenTableColumns{
SortType: "sort_type",
ShowDetail: "show_detail",
ExcelPort: "excel_port",
ExcelImp: "excel_imp",
UseSnowId: "use_snow_id",
UseVirtual: "use_virtual",
}

View File

@ -66,8 +66,8 @@ func (s *sSysRole) GetRoleListSearch(ctx context.Context, req *system.RoleListRe
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
model = model.LeftJoin("casbin_rule", "b", "b.v1 = a.id ")
model = model.LeftJoin("sys_user", "u", "CONCAT('u_',u.id) = b.v0")
model = model.LeftJoin("casbin_rule", "b", "b.v1 = cast(a.id AS char) ")
model = model.LeftJoin("sys_user", "u", "CONCAT('u_',u.id) = cast(b.v0 AS char)")
model = model.Group("a.id")
err = model.Page(res.CurrentPage, req.PageSize).Order("id asc").Fields("a.*, count(u.id) user_cnt").Scan(&res.List)
liberr.ErrIsNil(ctx, err, "获取数据失败")

View File

@ -85,59 +85,107 @@ func (s *sToolsGenTable) SelectDbTableList(ctx context.Context, req *system.Tool
res = new(system.ToolsGenTableSearchRes)
db := g.DB()
err = g.Try(ctx, func(ctx context.Context) {
if s.getDbDriver() != "mysql" {
liberr.ErrIsNil(ctx, gerror.New("代码生成暂时只支持mysql数据库"))
if !s.IsMysql() && !s.IsPg() {
liberr.ErrIsNil(ctx, gerror.New("代码生成暂时只支持mysql及postgresql数据库"))
}
sql := " from information_schema.tables where table_schema = (select database())" +
" and table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%' and table_name NOT IN (select table_name from " + dao.ToolsGenTable.Table() + ") "
if req != nil {
if req.TableName != "" {
sql += gdb.FormatSqlWithArgs(" and lower(table_name) like lower(?)", []interface{}{"%" + req.TableName + "%"})
}
var sqlStr string
if s.IsMysql() {
sqlStr = " from information_schema.tables where table_schema = (select database())" +
" and table_name table_name NOT LIKE 'tools_gen_%' and table_name NOT IN (select table_name from " + dao.ToolsGenTable.Table() + ") "
if req != nil {
if req.TableName != "" {
sqlStr += gdb.FormatSqlWithArgs(" and lower(table_name) like lower(?)", []interface{}{"%" + req.TableName + "%"})
}
if req.TableComment != "" {
sql += gdb.FormatSqlWithArgs(" and lower(table_comment) like lower(?)", []interface{}{"%" + req.TableComment + "%"})
if req.TableComment != "" {
sqlStr += gdb.FormatSqlWithArgs(" and lower(table_comment) like lower(?)", []interface{}{"%" + req.TableComment + "%"})
}
if len(req.DateRange) > 0 {
sqlStr += gdb.FormatSqlWithArgs(" and date_format(create_time,'%y%m%d') >= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[0]})
sqlStr += gdb.FormatSqlWithArgs(" and date_format(create_time,'%y%m%d') <= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[1]})
}
}
if len(req.DateRange) > 0 {
sql += gdb.FormatSqlWithArgs(" and date_format(create_time,'%y%m%d') >= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[0]})
sql += gdb.FormatSqlWithArgs(" and date_format(create_time,'%y%m%d') <= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[1]})
countSql := "select count(1) " + sqlStr
res.Total, err = db.GetCount(ctx, countSql)
liberr.ErrIsNil(ctx, err, "读取总表数失败")
sqlStr = "table_name, table_comment, create_time, update_time " + sqlStr
if req.PageNum == 0 {
req.PageNum = 1
}
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
page := (req.PageNum - 1) * req.PageSize
sqlStr += " order by create_time desc,table_name asc limit " + gconv.String(page) + "," + gconv.String(req.PageSize)
g.Log().Debug(ctx, "select "+sqlStr)
err = db.GetScan(ctx, &res.List, "select "+sqlStr)
liberr.ErrIsNil(ctx, err, "读取数据失败")
} else if s.IsPg() {
sqlStr = " from information_schema.tables JOIN pg_class ON pg_class.relname = table_name " +
" WHERE table_schema = current_schema() AND table_name NOT LIKE 'tools_gen_%' and table_name NOT IN (select table_name from " + dao.ToolsGenTable.Table() + ") "
if req != nil {
if req.TableName != "" {
sqlStr += gdb.FormatSqlWithArgs(" and lower(table_name) like lower(?)", []interface{}{"%" + req.TableName + "%"})
}
if req.TableComment != "" {
sqlStr += gdb.FormatSqlWithArgs(" and lower(obj_description(pg_class.oid)) like lower(?)", []interface{}{"%" + req.TableComment + "%"})
}
if len(req.DateRange) > 0 {
sqlStr += gdb.FormatSqlWithArgs(" and pg_stat_get_last_analyze_time(pg_class.oid) >= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[0]})
sqlStr += gdb.FormatSqlWithArgs(" and pg_stat_get_last_analyze_time(pg_class.oid) <= date_format(?,'%y%m%d') ", []interface{}{req.DateRange[1]})
}
}
countSql := "select count(1) " + sqlStr
res.Total, err = db.GetCount(ctx, countSql)
liberr.ErrIsNil(ctx, err, "读取总表数失败")
sqlStr = "table_name, obj_description(pg_class.oid) AS table_comment, " +
"pg_stat_get_last_analyze_time(pg_class.oid) AS create_time, " +
"pg_stat_get_last_autoanalyze_time(pg_class.oid) AS update_time " + sqlStr
if req.PageNum == 0 {
req.PageNum = 1
}
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
page := (req.PageNum - 1) * req.PageSize
sqlStr += " order by pg_stat_get_last_analyze_time(pg_class.oid) desc,table_name asc LIMIT " + gconv.String(req.PageSize) + " OFFSET " + gconv.String(page)
err = db.GetScan(ctx, &res.List, "select "+sqlStr)
liberr.ErrIsNil(ctx, err, "读取数据失败")
}
countSql := "select count(1) " + sql
res.Total, err = db.GetCount(ctx, countSql)
liberr.ErrIsNil(ctx, err, "读取总表数失败")
sql = "table_name, table_comment, create_time, update_time " + sql
if req.PageNum == 0 {
req.PageNum = 1
}
if req.PageSize == 0 {
req.PageSize = consts.PageSize
}
page := (req.PageNum - 1) * req.PageSize
sql += " order by create_time desc,table_name asc limit " + gconv.String(page) + "," + gconv.String(req.PageSize)
err = db.GetScan(ctx, &res.List, "select "+sql)
liberr.ErrIsNil(ctx, err, "读取数据失败")
})
return
}
// SelectDbTableListByNames 查询数据库中对应的表数据
func (s *sToolsGenTable) SelectDbTableListByNames(ctx context.Context, tableNames []string) ([]*entity.ToolsGenTable, error) {
var result []*entity.ToolsGenTable
err := g.Try(ctx, func(ctx context.Context) {
if s.getDbDriver() != "mysql" {
liberr.ErrIsNil(ctx, gerror.New("代码生成只支持mysql数据库"))
if !s.IsMysql() && !s.IsPg() {
liberr.ErrIsNil(ctx, gerror.New("代码生成暂时只支持mysql及postgresql数据库"))
}
db := g.DB()
var sqlStr string
if s.IsMysql() {
sqlStr = "select * from information_schema.tables where table_name NOT LIKE 'tools_gen_%' " +
" and table_schema = (select database()) "
if len(tableNames) > 0 {
in := gstr.TrimRight(gstr.Repeat("?,", len(tableNames)), ",")
sqlStr += " and " + gdb.FormatSqlWithArgs("table_name in ("+in+")", gconv.SliceAny(tableNames))
}
err := db.GetScan(ctx, &result, sqlStr)
liberr.ErrIsNil(ctx, err, "获取表格信息失败")
} else if s.IsPg() {
sqlStr = "select * from information_schema.tables WHERE table_schema = current_schema() " +
"AND table_name NOT LIKE 'tools_gen_%' "
if len(tableNames) > 0 {
in := gstr.TrimRight(gstr.Repeat("?,", len(tableNames)), ",")
sqlStr += " and " + gdb.FormatSqlWithArgs("table_name in ("+in+")", gconv.SliceAny(tableNames))
}
err := db.GetScan(ctx, &result, sqlStr)
liberr.ErrIsNil(ctx, err, "获取表格信息失败")
}
})
db := g.DB()
sql := "select * from information_schema.tables where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' " +
" and table_schema = (select database()) "
if len(tableNames) > 0 {
in := gstr.TrimRight(gstr.Repeat("?,", len(tableNames)), ",")
sql += " and " + gdb.FormatSqlWithArgs("table_name in ("+in+")", gconv.SliceAny(tableNames))
}
var result []*entity.ToolsGenTable
err = db.GetScan(ctx, &result, sql)
liberr.ErrIsNil(ctx, err, "获取表格信息失败")
return result, err
}
@ -156,7 +204,8 @@ func (s *sToolsGenTable) ImportGenTable(ctx context.Context, tableList []*entity
}
err = s.InitTable(ctx, table, genTableColumns)
liberr.ErrIsNil(ctx, err)
result, err1 := tx.Model(dao.ToolsGenTable.Table()).Insert(table)
result, err1 := tx.Model(dao.ToolsGenTable.Table()).FieldsEx("table_id").
Insert(table)
liberr.ErrIsNil(ctx, err1)
tmpId, err2 := result.LastInsertId()
liberr.ErrIsNil(ctx, err2, "保存数据失败")
@ -166,7 +215,8 @@ func (s *sToolsGenTable) ImportGenTable(ctx context.Context, tableList []*entity
table.TableId = tmpId
for _, column := range genTableColumns {
service.ToolsGenTableColumn().InitColumnField(column, table)
_, err3 := tx.Model(dao.ToolsGenTableColumn.Table()).Insert(column)
_, err3 := tx.Model(dao.ToolsGenTableColumn.Table()).FieldsEx("column_id").
Insert(column)
liberr.ErrIsNil(ctx, err3, "保存列数据失败")
}
}
@ -242,6 +292,14 @@ func (s *sToolsGenTable) getDbDriver() string {
return gstr.ToLower(config.Type)
}
func (s *sToolsGenTable) IsPg() bool {
return s.getDbDriver() == "pgsql"
}
func (s *sToolsGenTable) IsMysql() bool {
return s.getDbDriver() == "mysql"
}
// DeleteTable 删除表信息
func (s *sToolsGenTable) DeleteTable(ctx context.Context, req *system.ToolsGenTableDeleteReq) error {
err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
@ -385,6 +443,9 @@ func (s *sToolsGenTable) SaveEdit(ctx context.Context, req *system.ToolsGenTable
if req.ExcelPort != "" {
table.ExcelPort = gconv.Bool(req.ExcelPort)
}
if req.ExcelImp != "" {
table.ExcelImp = gconv.Bool(req.ExcelImp)
}
if req.UseSnowId != "" {
table.UseSnowId = gconv.Bool(req.UseSnowId)
}
@ -413,7 +474,9 @@ func (s *sToolsGenTable) SaveEdit(ctx context.Context, req *system.ToolsGenTable
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
_, err = tx.Model(dao.ToolsGenTable.Table()).Save(table)
_, err = tx.Model(dao.ToolsGenTable.Table()).
WherePri(table.TableId).
Update(table)
liberr.ErrIsNil(ctx, err, "保存表数据失败")
//保存列数据
if req.Columns != nil {
@ -475,7 +538,9 @@ func (s *sToolsGenTable) SaveEdit(ctx context.Context, req *system.ToolsGenTable
dbColumn.LinkLabelId = ""
dbColumn.LinkLabelName = ""
}
_, err = tx.Model(dao.ToolsGenTableColumn.Table()).Save(dbColumn)
_, err = tx.Model(dao.ToolsGenTableColumn.Table()).
WherePri(dbColumn.ColumnId).
Update(dbColumn)
liberr.ErrIsNil(ctx, err, "保存列:"+dbColumn.ColumnName+",数据失败")
}
}
@ -659,7 +724,13 @@ func (s *sToolsGenTable) GenData(ctx context.Context, tableId int64) (data g.Map
sqlKey := "sql"
sqlValue := ""
var tmpSql string
if tmpSql, err = view.Parse(ctx, "sql/sql.template", tplData); err == nil {
var tmpSqlPath string
if s.IsPg() {
tmpSqlPath = "sql/pgsql.template"
} else {
tmpSqlPath = "sql/mysql.template"
}
if tmpSql, err = view.Parse(ctx, tmpSqlPath, tplData); err == nil {
sqlValue = tmpSql
sqlValue, err = s.trimBreak(sqlValue)
} else {
@ -1068,7 +1139,12 @@ func (s *sToolsGenTable) GenCode(ctx context.Context, ids []int) (err error) {
liberr.ErrIsNil(ctx, err)
if !hasSql || extendData.Overwrite {
//第一次生成则向数据库写入菜单数据
err = s.writeDb(ctx, path)
if s.IsPg() {
content := gfile.GetContents(path)
_, err = g.DB().Exec(ctx, content)
} else {
err = s.writeDb(ctx, path)
}
liberr.ErrIsNil(ctx, err)
//清除菜单缓存
commonService.Cache().Remove(ctx, consts.CacheSysAuthMenu)

View File

@ -9,6 +9,7 @@ package toolsGenTableColumn
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
@ -48,16 +49,40 @@ type sToolsGenTableColumn struct {
ColumnNameNotQuery []string //页面不需要查询字段
}
// 自定义错误类型
type MyError struct {
Code int
Message string
}
// 实现 error 接口的 Error() 方法
func (e MyError) Error() string {
return fmt.Sprintf("错误代码:%d错误信息%s", e.Code, e.Message)
}
// SelectDbTableColumnsByName 根据表名称查询列信息
func (s *sToolsGenTableColumn) SelectDbTableColumnsByName(ctx context.Context, tableName string) ([]*entity.ToolsGenTableColumn, error) {
var res []*entity.ToolsGenTableColumn
err := g.Try(ctx, func(ctx context.Context) {
db := g.DB()
sql := " select column_name, (case when (is_nullable = 'YES' || is_nullable = 'NO' && column_default is not null) then '0' else '1' end) as is_required, " +
var sql string
if service.ToolsGenTable().IsPg() {
sql = " select c.column_name,(case when c.is_nullable='YES' || k.column_name is not null then '1' else '0' end) as is_required," +
"(case when k.column_name is not null then '1' else '0' end) as is_pk,c.ordinal_position as sort_order_edit,d.description column_comment," +
"(case when c.column_default like 'nextval%' then '1' else '0' end) as is_increment,c.udt_name as column_type " +
"from information_schema.columns c " +
"left join pg_description d on d.objsubid=c.ordinal_position and d.objoid=c.table_name :: regclass " +
"left join information_schema.key_column_usage k on c.table_name=k.table_name and c.column_name=k.column_name and c.table_catalog=k.table_catalog and c.table_schema=k.table_schema "
sql += "where " + gdb.FormatSqlWithArgs(" c.table_name=? ", []interface{}{tableName}) + " order by c.ordinal_position"
} else {
sql = " select column_name, (case when (is_nullable = 'YES' || is_nullable = 'NO' && column_default is not null) then '0' else '1' end) as is_required, " +
"(case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort_order_edit, column_comment," +
" (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type from information_schema.columns" +
" where table_schema = (select database()) "
sql += " and " + gdb.FormatSqlWithArgs(" table_name=? ", []interface{}{tableName}) + " order by ordinal_position ASC "
}
err := db.GetScan(ctx, &res, sql)
liberr.ErrIsNil(ctx, err, "查询列信息失败")
})

View File

@ -30,7 +30,8 @@ type ToolsGenTable struct {
SortColumn interface{} // 排序字段名
SortType interface{} // 排序方式 (asc顺序 desc倒序)
ShowDetail interface{} // 是否有查看详情功能
ExcelPort interface{} // 是否有导入导出excel功能
ExcelPort interface{} // 是否有导出excel功能
ExcelImp interface{} // 是否有导入excel功能
UseSnowId interface{} //主键是否使用雪花ID
UseVirtual interface{} //树表是否使用虚拟表
}

View File

@ -28,7 +28,8 @@ type ToolsGenTable struct {
SortColumn string `json:"sortColumn" description:"排序字段名"`
SortType string `json:"sortType" description:"排序方式 (asc顺序 desc倒序)"`
ShowDetail bool `json:"showDetail" description:"是否有查看详情功能"`
ExcelPort bool `json:"excelPort" description:"是否有excel导入导出功能"`
ExcelPort bool `json:"excelPort" description:"是否有excel导出功能"`
ExcelImp bool `json:"excelImp" description:"是否有excel导入功能"`
UseSnowId bool `json:"useSnowId" description:"主键是否使用雪花ID"`
UseVirtual bool `json:"useVirtual" orm:"use_virtual" description:"树表是否使用虚拟表"`
}

View File

@ -35,7 +35,8 @@ type ToolsGenTableEx struct {
SortColumn string // 缺省排序字段
SortType string // 缺省排序方式 (asc顺序 desc倒序)
ShowDetail bool // 是否有查看详情功能
ExcelPort bool // 是否有导入导出excel功能
ExcelPort bool // 是否有导出excel功能
ExcelImp bool // 是否有导入excel功能
UseSnowId bool // 主键是否使用雪花ID
UseVirtual bool // 树表是否使用虚拟表
TreeCode string // 树编码字段

View File

@ -32,6 +32,8 @@ type (
SelectRecordById(ctx context.Context, tableId int64) (tableEx *model.ToolsGenTableEx, err error)
GenCode(ctx context.Context, ids []int) (err error)
SyncTable(ctx context.Context, tableId int64) (err error)
IsPg()bool
IsMysql()bool
}
)

View File

@ -9,5 +9,5 @@ package consts
const (
Logo = `CiAgIF9fX19fX19fX19fXyAgICAgICAgICAgX18gCiAgLyBfX19fLyBfX19fL19fXyBfX19fX18vIC9fCiAvIC8gX18vIC9fICAvIF9fIGAvIF9fXy8gX18vCi8gL18vIC8gX18vIC8gL18vIChfXyAgKSAvXyAgClxfX19fL18vICAgIFxfXyxfL19fX18vXF9fLyAg`
Version = "3.2.13"
Version = "3.2.14"
)

View File

@ -2,10 +2,10 @@ package main
import (
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
_ "github.com/tiger1103/gfast/v3/internal/app/boot"
"github.com/gogf/gf/v2/os/gctx"
_ "github.com/tiger1103/gfast/v3/internal/app/boot"
_ "github.com/tiger1103/gfast/v3/internal/app/system/packed"
"github.com/tiger1103/gfast/v3/internal/cmd"
_ "github.com/tiger1103/gfast/v3/task"

16821
resource/data/gfast-v32-pg.sql Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,13 +5,13 @@
Source Server Type : MySQL
Source Server Version : 50736
Source Host : localhost:3306
Source Schema : gfast-v32
Source Schema : gfast-v32mandate
Target Server Type : MySQL
Target Server Version : 50736
File Encoding : 65001
Date: 10/11/2023 12:08:21
Date: 13/12/2023 17:27:21
*/
SET NAMES utf8mb4;
@ -4015,7 +4015,7 @@ CREATE TABLE `demo_snow_id` (
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '姓名',
`age` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '雪花ID测试' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '雪花ID测试' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of demo_snow_id
@ -4352,7 +4352,7 @@ CREATE TABLE `sys_job_log` (
`created_at` datetime NULL DEFAULT NULL COMMENT '执行日期',
`result` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行结果',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2379 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '任务日志表' ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB AUTO_INCREMENT = 2386 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '任务日志表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_job_log
@ -6185,6 +6185,13 @@ INSERT INTO `sys_job_log` VALUES (2375, 'checkUserOnline', '2023-11-03 18:10:06'
INSERT INTO `sys_job_log` VALUES (2376, 'checkUserOnline', '2023-11-03 18:30:05', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2377, 'checkUserOnline', '2023-11-06 09:00:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2378, 'checkUserOnline', '2023-11-06 09:10:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2379, 'checkUserOnline', '2023-12-07 09:40:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2380, 'checkUserOnline', '2023-12-07 09:50:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2381, 'checkUserOnline', '2023-12-07 10:00:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2382, 'checkUserOnline', '2023-12-07 10:10:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2383, 'checkUserOnline', '2023-12-07 10:20:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2384, 'checkUserOnline', '2023-12-07 10:30:06', '在线用户定时更新,执行成功');
INSERT INTO `sys_job_log` VALUES (2385, 'checkUserOnline', '2023-12-07 10:40:06', '在线用户定时更新,执行成功');
-- ----------------------------
-- Table structure for sys_login_log
@ -6417,7 +6424,7 @@ CREATE TABLE `sys_oper_log` (
`error_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '错误消息',
`oper_time` datetime NULL DEFAULT NULL COMMENT '操作时间',
PRIMARY KEY (`oper_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8959 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = COMPACT;
) ENGINE = InnoDB AUTO_INCREMENT = 8970 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = COMPACT;
-- ----------------------------
-- Records of sys_oper_log
@ -15380,6 +15387,17 @@ INSERT INTO `sys_oper_log` VALUES (8955, '部门管理', 0, '/api/v1/system/dept
INSERT INTO `sys_oper_log` VALUES (8956, '部门管理', 0, '/api/v1/system/dept/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dept/list?pageNum=1&pageSize=10&deptName=&status=', '::1', '内网IP', '{\"deptName\":\"\",\"pageNum\":\"1\",\"pageSize\":\"10\",\"status\":\"\"}', '', '2023-11-06 09:02:20');
INSERT INTO `sys_oper_log` VALUES (8957, '部门管理', 0, '/api/v1/system/dept/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dept/list?pageNum=1&pageSize=10&deptName=&status=', '::1', '内网IP', '{\"deptName\":\"\",\"pageNum\":\"1\",\"pageSize\":\"10\",\"status\":\"\"}', '', '2023-11-06 09:02:47');
INSERT INTO `sys_oper_log` VALUES (8958, '部门管理', 0, '/api/v1/system/dept/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dept/list?pageNum=1&pageSize=10&deptName=&status=', '::1', '内网IP', '{\"deptName\":\"\",\"pageNum\":\"1\",\"pageSize\":\"10\",\"status\":\"\"}', '', '2023-11-06 09:03:03');
INSERT INTO `sys_oper_log` VALUES (8959, '', 0, '/api/v1/system/cache/remove', 'DELETE', 1, 'demo', '财务部门', '/api/v1/system/cache/remove', '::1', '内网IP', '{}', NULL, '2023-12-07 09:40:11');
INSERT INTO `sys_oper_log` VALUES (8960, '', 0, '/api/v1/system/user/getUserMenus', 'GET', 1, 'demo', '财务部门', '/api/v1/system/user/getUserMenus', '::1', '内网IP', '{}', NULL, '2023-12-07 09:40:12');
INSERT INTO `sys_oper_log` VALUES (8961, '部门管理', 0, '/api/v1/system/dept/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dept/list?pageNum=1&pageSize=10&deptName=&status=', '::1', '内网IP', '{\"deptName\":\"\",\"pageNum\":\"1\",\"pageSize\":\"10\",\"status\":\"\"}', NULL, '2023-12-07 09:40:12');
INSERT INTO `sys_oper_log` VALUES (8962, '岗位管理', 0, '/api/v1/system/post/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/post/list?postName=&status=&postCode=&pageNum=1&pageSize=10', '::1', '内网IP', '{\"pageNum\":\"1\",\"pageSize\":\"10\",\"postCode\":\"\",\"postName\":\"\",\"status\":\"\"}', NULL, '2023-12-07 09:40:14');
INSERT INTO `sys_oper_log` VALUES (8963, '', 0, '/api/v1/system/dict/data/getDictData', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dict/data/getDictData?dictType=sys_user_sex&defaultValue=', '::1', '内网IP', '{\"defaultValue\":\"\",\"dictType\":\"sys_user_sex\"}', NULL, '2023-12-07 09:40:15');
INSERT INTO `sys_oper_log` VALUES (8964, '', 0, '/api/v1/system/dept/treeSelect', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dept/treeSelect', '::1', '内网IP', '{}', NULL, '2023-12-07 09:40:15');
INSERT INTO `sys_oper_log` VALUES (8965, '', 0, '/api/v1/system/user/params', 'GET', 1, 'demo', '财务部门', '/api/v1/system/user/params', '::1', '内网IP', '{}', NULL, '2023-12-07 09:40:15');
INSERT INTO `sys_oper_log` VALUES (8966, '', 0, '/api/v1/system/dict/data/getDictData', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dict/data/getDictData?dictType=sys_user_sex&defaultValue=', '::1', '内网IP', '{\"defaultValue\":\"\",\"dictType\":\"sys_user_sex\"}', NULL, '2023-12-07 09:40:15');
INSERT INTO `sys_oper_log` VALUES (8967, '用户管理', 0, '/api/v1/system/user/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/user/list?pageNum=1&pageSize=10&deptId=&mobile=&status=&keyWords=', '::1', '内网IP', '{\"deptId\":\"\",\"keyWords\":\"\",\"mobile\":\"\",\"pageNum\":\"1\",\"pageSize\":\"10\",\"status\":\"\"}', NULL, '2023-12-07 09:40:15');
INSERT INTO `sys_oper_log` VALUES (8968, '', 0, '/api/v1/system/dict/data/getDictData', 'GET', 1, 'demo', '财务部门', '/api/v1/system/dict/data/getDictData?dictType=sys_user_sex&defaultValue=', '::1', '内网IP', '{\"defaultValue\":\"\",\"dictType\":\"sys_user_sex\"}', NULL, '2023-12-07 09:40:16');
INSERT INTO `sys_oper_log` VALUES (8969, '角色管理', 0, '/api/v1/system/role/list', 'GET', 1, 'demo', '财务部门', '/api/v1/system/role/list?roleName=&roleStatus=&pageNum=1&pageSize=10', '::1', '内网IP', '{\"pageNum\":\"1\",\"pageSize\":\"10\",\"roleName\":\"\",\"roleStatus\":\"\"}', NULL, '2023-12-07 09:40:16');
-- ----------------------------
-- Table structure for sys_post
@ -15550,12 +15568,11 @@ CREATE TABLE `sys_user_online` (
`os` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作系统',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uni_token`(`token`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 97 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户在线状态表' ROW_FORMAT = COMPACT;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户在线状态表' ROW_FORMAT = COMPACT;
-- ----------------------------
-- Records of sys_user_online
-- ----------------------------
INSERT INTO `sys_user_online` VALUES (96, '59d1a58da5c68fe40701cd63ffd2d280', '7ZUSfVIf2HyYjcv86SKPPs29v003ECPEScsdYsYYqO0OiU00EEIGqI/BsXSMHMj7l8nHeCOGjQR+Ad17Jc6sqpyMaYf+LQn/d1lCwmRg6MsxBDfns4cuGLRn4wZQx0eQdam0n5XylY5Y7OOiARUldg==', '2023-11-06 08:57:18', 'demo', '::1', 'Chrome', 'Windows 10');
-- ----------------------------
-- Table structure for sys_user_post
@ -15624,18 +15641,19 @@ CREATE TABLE `tools_gen_table` (
`excel_port` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否有导出excel功能',
`use_snow_id` bit(1) NOT NULL DEFAULT b'0' COMMENT '主键是否雪花ID',
`use_virtual` bit(1) NOT NULL DEFAULT b'0' COMMENT '树表是否使用虚拟表',
`excel_imp` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否导入excel',
PRIMARY KEY (`table_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 97 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '代码生成业务表' ROW_FORMAT = COMPACT;
-- ----------------------------
-- Records of tools_gen_table
-- ----------------------------
INSERT INTO `tools_gen_table` VALUES (91, 'demo_gen', '代码生成测试表', 'DemoGen', 'crud', 'internal/app/demo', 'demo', 'demo_gen', '代码生成测试', 'gfast', '', '2022-11-01 17:27:43', '2023-08-22 11:46:58', '', b'1', 'id', 'asc', b'1', b'1', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (92, 'demo_gen_class', '代码生成关联测试表', 'DemoGenClass', 'crud', 'internal/app/demo', 'demo', 'demo_gen_class', '分类信息', 'gfast', '', '2022-11-03 06:36:57', '2023-08-18 15:33:30', '分类', b'1', 'id', 'asc', b'1', b'1', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (93, 'demo_gen_tree', '代码生成树形结构测试表', 'DemoGenTree', 'tree', 'internal/app/demo', 'demo', 'demo_gen_tree', '代码生成树形结构测试', 'gfast', '{\"treeCode\":\"id\",\"treeName\":\"demoName\",\"treeParentCode\":\"parentId\"}', '2022-11-29 15:11:34', '2023-11-02 18:16:23', '', b'1', 'id', 'asc', b'1', b'0', b'0', b'1');
INSERT INTO `tools_gen_table` VALUES (94, 'demo_data_auth', '数据权限测试', 'DemoDataAuth', 'crud', 'internal/app/demo', 'de_mo', 'demo_data_auth', '数据权限测试', 'gfast', '', '2023-02-12 11:18:42', '2023-07-18 15:22:28', '', b'1', 'id', 'asc', b'0', b'0', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (95, 'demo_snow_id', '雪花ID测试', 'DemoSnowId', 'crud', 'internal/app/demo', 'demo', 'demo_snow_id', '雪花ID测试', 'gfast', '', '2023-09-19 15:34:46', '2023-09-20 14:48:07', '', b'1', 'id', 'asc', b'1', b'1', b'1', b'0');
INSERT INTO `tools_gen_table` VALUES (96, 'demo_city_code', '省市区县和天气预报编码', 'DemoCityCode', 'tree', 'internal/app/demo', 'demo', 'demo_city_code', '省市区县', 'gfast', '{\"treeCode\":\"id\",\"treeName\":\"name\",\"treeParentCode\":\"pid\"}', '2023-11-02 10:38:51', '2023-11-03 09:39:49', '', b'1', 'id', 'asc', b'1', b'0', b'0', b'1');
INSERT INTO `tools_gen_table` VALUES (91, 'demo_gen', '代码生成测试表', 'DemoGen', 'crud', 'internal/app/demo', 'demo', 'demo_gen', '代码生成测试', 'gfast', '', '2022-11-01 17:27:43', '2023-08-22 11:46:58', '', b'1', 'id', 'asc', b'1', b'1', b'0', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (92, 'demo_gen_class', '代码生成关联测试表', 'DemoGenClass', 'crud', 'internal/app/demo', 'demo', 'demo_gen_class', '分类信息', 'gfast', '', '2022-11-03 06:36:57', '2023-08-18 15:33:30', '分类', b'1', 'id', 'asc', b'1', b'1', b'0', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (93, 'demo_gen_tree', '代码生成树形结构测试表', 'DemoGenTree', 'tree', 'internal/app/demo', 'demo', 'demo_gen_tree', '代码生成树形结构测试', 'gfast', '{\"treeCode\":\"id\",\"treeName\":\"demoName\",\"treeParentCode\":\"parentId\"}', '2022-11-29 15:11:34', '2023-11-02 18:16:23', '', b'1', 'id', 'asc', b'1', b'0', b'0', b'1', b'0');
INSERT INTO `tools_gen_table` VALUES (94, 'demo_data_auth', '数据权限测试', 'DemoDataAuth', 'crud', 'internal/app/demo', 'de_mo', 'demo_data_auth', '数据权限测试', 'gfast', '', '2023-02-12 11:18:42', '2023-07-18 15:22:28', '', b'1', 'id', 'asc', b'0', b'0', b'0', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (95, 'demo_snow_id', '雪花ID测试', 'DemoSnowId', 'crud', 'internal/app/demo', 'demo', 'demo_snow_id', '雪花ID测试', 'gfast', '', '2023-09-19 15:34:46', '2023-09-20 14:48:07', '', b'1', 'id', 'asc', b'1', b'1', b'1', b'0', b'0');
INSERT INTO `tools_gen_table` VALUES (96, 'demo_city_code', '省市区县和天气预报编码', 'DemoCityCode', 'tree', 'internal/app/demo', 'demo', 'demo_city_code', '省市区县', 'gfast', '{\"treeCode\":\"id\",\"treeName\":\"name\",\"treeParentCode\":\"pid\"}', '2023-11-02 10:38:51', '2023-11-03 09:39:49', '', b'1', 'id', 'asc', b'1', b'0', b'0', b'1', b'0');
-- ----------------------------
-- Table structure for tools_gen_table_column

View File

@ -11,6 +11,9 @@ package {{.table.ModuleName }}
////
import (
"github.com/gogf/gf/v2/frame/g"
{{if .table.ExcelImp}}
"github.com/gogf/gf/v2/net/ghttp"
{{end}}
commonApi "{{.goModName}}/api/v1/common"
"{{.goModName}}/{{.table.PackageName}}/model"
)
@ -44,6 +47,27 @@ type {{.table.ClassName}}ExportRes struct {
{{end}}
{{if .table.ExcelImp}}
type {{.table.ClassName}}ExcelTemplateReq struct {
g.Meta `path:"/excelTemplate" tags:"{{$.table.FunctionName}}" method:"get" summary:"导出模板文件"`
commonApi.Author
}
type {{.table.ClassName}}ExcelTemplateRes struct {
commonApi.EmptyRes
}
type {{.table.ClassName}}ImportReq struct {
g.Meta `path:"/import" tags:"{{$.table.FunctionName}}" method:"post" summary:"{{$.table.FunctionName}}导入"`
commonApi.Author
File *ghttp.UploadFile `p:"file" type:"file" dc:"选择上传文件" v:"required#上传文件必须"`
}
type {{.table.ClassName}}ImportRes struct {
commonApi.EmptyRes
}
{{end}}
{{if gt (len .table.LinkedTables) 0}}
//相关连表查询数据
type Linked{{$.table.ClassName}}DataSearchReq struct{

View File

@ -18,6 +18,10 @@ package controller
{{$hasGconv:=false}}
{{$hasSystemApi:=false}}
{{$hasCommonService:=false}}
{{$excel :=false}}
{{if or .table.ExcelPort .table.ExcelImp}}
{{$excel = true}}
{{end}}
{{if .table.ExcelPort}}
{{range $index, $column := .table.Columns}}
{{if ne $column.DictType ""}}
@ -69,6 +73,8 @@ import (
commonService "github.com/tiger1103/gfast/v3/internal/app/common/service"
{{end}}
"{{$.goModName}}/{{$.table.PackageName}}/model"
{{end}}
{{if $excel}}
"{{$.goModName}}/library/libUtils"
"github.com/xuri/excelize/v2"
{{end}}
@ -269,6 +275,45 @@ func (c *{{$structName}}Controller) Export(ctx context.Context, req *{{.table.Mo
}
{{end}}
{{if .table.ExcelImp}}
func (c *{{$structName}}Controller) ExcelTemplate(ctx context.Context,req *{{.table.ModuleName}}.{{.table.ClassName}}ExcelTemplateReq)(res *{{.table.ModuleName}}.{{.table.ClassName}}ExcelTemplateRes,err error){
var(
r = ghttp.RequestFromCtx(ctx)
//表头
{{$tableHeader := ""}}
{{range $index, $column := .table.Columns}}
{{if and (or (ne $column.IsPk true) $.table.IsPkInsertable) (ne $column.HtmlType "imagefile") (ne $column.HtmlType "images") (ne $column.HtmlType "file") (ne $column.HtmlType "files")}}
{{$tableHeader = concat $tableHeader `"` $column.ColumnComment `"` "," }}
{{end}}
{{end}}
tableHead = []interface{}{ {{$tableHeader}} }
excelData = [][]interface{}{tableHead}
)
//创建excel处理对象
excel := new(libUtils.ExcelHelper).CreateFile()
excel.ArrToExcel("Sheet1", "A1", excelData)
col, _ := excelize.ColumnNumberToName(len(tableHead))
row := len(excelData)
cr, _ := excelize.JoinCellName(col, row)
excel.SetCellBorder("Sheet1", "A1", cr)
_, err = excel.WriteTo(r.Response.Writer)
if err != nil {
return
}
r.Response.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
r.Response.Header().Set("Accept-Ranges", "bytes")
r.Response.Header().Set("Access-Control-Expose-Headers", "*")
r.Response.Header().Set("Content-Disposition", "attachment; filename="+gurl.Encode("代码生成测试表模板")+".xlsx")
r.Response.Buffer()
r.Exit()
return
}
func(c *{{$structName}}Controller)Import(ctx context.Context,req *{{.table.ModuleName}}.{{.table.ClassName}}ImportReq)(res *{{.table.ModuleName}}.{{.table.ClassName}}ImportRes,err error){
err = service.DemoGen().Import(ctx,req.File)
return
}
{{end}}
{{if gt (len .table.LinkedTables) 0}}
// Linked{{$.table.ClassName}}DataSearch 相关连表查询数据
@ -314,4 +359,5 @@ func (c *{{$structName}}Controller) Edit(ctx context.Context, req *{{.table.Modu
func (c *{{$structName}}Controller) Delete(ctx context.Context, req *{{.table.ModuleName}}.{{.table.ClassName}}DeleteReq) (res *{{.table.ModuleName}}.{{.table.ClassName}}DeleteRes, err error) {
err = service.{{.table.ClassName}}().Delete(ctx, req.{{$.table.PkColumn.GoField}}s)
return
}
}

View File

@ -37,9 +37,15 @@ package logic
{{if and .table.UseSnowId (not .table.IsPkInsertable)}}
{{$useCommonService = true}}
{{end}}
import (
"context"
"github.com/gogf/gf/v2/frame/g"
{{if .table.ExcelImp}}
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/database/gdb"
"github.com/xuri/excelize/v2"
{{end}}
{{if $gstr}}
"github.com/gogf/gf/v2/text/gstr"
{{end}}
@ -319,6 +325,77 @@ func (s *s{{.table.ClassName}})GetExportData(ctx context.Context, req *model.{{.
}
{{end}}
{{if .table.ExcelImp}}
////
func(s *s{{.table.ClassName}})Import(ctx context.Context,file *ghttp.UploadFile)(err error){
if file == nil {
err = errors.New("请上传数据文件")
return
}
var data []do.{{.table.ClassName}}
err = g.Try(ctx, func(ctx context.Context) {
f,err:=file.Open()
liberr.ErrIsNil(ctx,err)
defer f.Close()
exFile,err := excelize.OpenReader(f)
liberr.ErrIsNil(ctx,err)
defer exFile.Close()
rows, err := exFile.GetRows("Sheet1")
liberr.ErrIsNil(ctx,err)
if len(rows)==0{
liberr.ErrIsNil(ctx,errors.New("表格内容不能为空"))
}
d:=make([]interface{}, len(rows[0]))
data=make([]do.{{.table.ClassName}},len(rows)-1)
for k,v:=range rows{
if k==0{
continue
}
for kv,vv:=range v{
d[kv] = vv
}
data[k-1] = do.{{.table.ClassName}}{
{{$i:=0}}
{{range $index, $column := .table.Columns}}
{{$add:=false}}
{{if $.table.IsPkInsertable}}
{{$.table.PkColumn.GoField}}:d[{{$i}}],
{{$add = true}}
{{else if $.table.UseSnowId}}
var {{$.table.PkColumn.HtmlField}} uint64
{{$.table.PkColumn.HtmlField}}, err = commonService.SnowID().GenID()
liberr.ErrIsNil(ctx, err)
{{$.table.PkColumn.GoField}}:{{$.table.PkColumn.HtmlField}},
{{else if and (ne $column.IsPk true) (ne $column.HtmlType "imagefile") (ne $column.HtmlType "images") (ne $column.HtmlType "file") (ne $column.HtmlType "files")}}
{{$add = true}}
{{if eq $column.GoType "int" "uint" "int64" "uint64" "bool" }}
{{$column.GoField}}:gconv.Int64(d[{{$i}}]),
{{else if eq $column.GoType "float64"}}
{{$column.GoField}}:gconv.Float64(d[{{$i}}]),
{{else if eq $column.GoType "Time"}}
{{$column.GoField}}:gconv.GTime(d[{{$i}}]),
{{else}}
{{$column.GoField}}:d[{{$i}}],
{{end}}
{{end}}
{{if $add}}
{{$i = plus $i 1}}
{{end}}
{{end}}
}
}
if len(data)>0{
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
_,err = dao.{{.table.ClassName}}.Ctx(ctx).Batch(500).Insert(data)
return err
})
liberr.ErrIsNil(ctx,err)
}
})
return
}
{{end}}
////
{{if gt (len .table.LinkedTables) 0}}
// LinkedDataSearch 相关连表查询数据
@ -397,7 +474,11 @@ func (s *s{{.table.ClassName}})Add(ctx context.Context, req *model.{{.table.Clas
{{end}}
{{end}}
{{if .table.HasCreatedBy}}
{{if $usedSystemModule}}
CreatedBy:systemService.Context().GetUserId(ctx),
{{else}}
CreatedBy:service.Context().GetUserId(ctx),
{{end}}
{{end}}
})
liberr.ErrIsNil(ctx, err, "添加失败")
@ -430,7 +511,11 @@ func (s *s{{.table.ClassName}})Edit(ctx context.Context, req *model.{{.table.Cla
{{end}}
{{end}}
{{if .table.HasUpdatedBy}}
{{if $usedSystemModule}}
UpdatedBy:systemService.Context().GetUserId(ctx),
{{else}}
UpdatedBy:service.Context().GetUserId(ctx),
{{end}}
{{end}}
})
liberr.ErrIsNil(ctx, err, "修改失败")

View File

@ -22,6 +22,9 @@ package service
import (
"context"
{{if .table.ExcelImp}}
"github.com/gogf/gf/v2/net/ghttp"
{{end}}
"{{.goModName}}/{{.table.PackageName}}/model"
{{if or .table.HasConversion (eq .table.TplCategory "tree")}}
{{end}}
@ -33,6 +36,9 @@ type I{{.table.ClassName}} interface {
{{if .table.ExcelPort }}
GetExportData(ctx context.Context, req *model.{{.table.ClassName}}SearchReq) (listRes []*model.{{.table.ClassName}}InfoRes, err error)
{{end}}
{{if .table.ExcelPort }}
Import(ctx context.Context,file *ghttp.UploadFile)(err error)
{{end}}
GetBy{{.table.PkColumn.GoField}}(ctx context.Context, {{.table.PkColumn.GoField}} {{$.table.PkColumn.GoType}}) (res *model.{{.table.ClassName}}InfoRes,err error)
Add(ctx context.Context, req *model.{{.table.ClassName}}AddReq) (err error)
Edit(ctx context.Context, req *model.{{.table.ClassName}}EditReq) (err error)

View File

@ -17,6 +17,7 @@ DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{.t
DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/edit';
DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/delete';
DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/export';
DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/import';
{{range $index,$column:= .table.Columns}}
{{if and $column.IsStatus $column.IsList}}
DELETE FROM `sys_auth_rule` WHERE `name` = '{{.apiVersion}}/{{.modulePath}}/{{$.table.BusinessName | CaseCamelLower}}/change{{$column.GoField}}';
@ -58,6 +59,11 @@ INSERT INTO `sys_auth_rule` (`pid`,`name`,`title`,`icon`,`condition`,`remark`,`m
VALUES(@parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/export','{{.table.FunctionName}}导出','','','{{.table.FunctionName}}导出',2,0,1,0,'','','',0,'sys_admin',0,@now,@now);
{{end}}
{{if .table.ExcelImp}}
INSERT INTO `sys_auth_rule` (`pid`,`name`,`title`,`icon`,`condition`,`remark`,`menu_type`,`weigh`,`is_cached`,`is_hide`,`path`,`link_url`,`component`,`is_iframe`,`module_type`,`model_id`,`created_at`,`updated_at`)
VALUES(@parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/import','{{.table.FunctionName}}导入','','','{{.table.FunctionName}}导入',2,0,1,0,'','','',0,'sys_admin',0,@now,@now);
{{end}}
{{range $index,$column:= .table.Columns}}
{{if and $column.IsStatus $column.IsList}}
INSERT INTO `sys_auth_rule` (`pid`,`name`,`title`,`icon`,`condition`,`remark`,`menu_type`,`weigh`,`is_cached`,`is_hide`,`path`,`link_url`,`component`,`is_iframe`,`module_type`,`model_id`,`created_at`,`updated_at`)

View File

@ -0,0 +1,71 @@
/*
==========================================================================
GFast自动生成菜单SQL
生成日期:{{date "Y-m-d H:i:s"}}
生成路径: resource/data/gen_sql/{{.table.ModuleName}}/{{.table.BusinessName}}_menu.sql
生成人:{{.table.FunctionAuthor}}
==========================================================================
*/
////
DO $$
DECLARE
v_time timestamp := now();
parentId integer;
BEGIN
-- 删除原有数据
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/list';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/get';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/add';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/edit';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/delete';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/export';
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/import';
{{range $index,$column:= .table.Columns}}
{{if and $column.IsStatus $column.IsList}}
DELETE FROM sys_auth_rule WHERE name = '{{.apiVersion}}/{{.modulePath}}/{{$.table.BusinessName | CaseCamelLower}}/change{{$column.GoField}}';
{{end}}
{{end}}
-- 目录 SQL
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at )
VALUES(0,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}','{{.table.FunctionName}}管理','iconfont icon-fuwenbenkuang','','{{.table.FunctionName}}管理',0,0,1,0,'/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}','','layout/routerView/parent',0,'sys_admin',0,v_time,v_time) RETURNING id INTO parentId;
-- 菜单 SQL
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/list','{{.table.FunctionName}}列表','ele-Fold','','{{.table.FunctionName}}列表',1,0,1,0,'/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/list','','{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/list/index',0,'sys_admin',0,v_time,v_time) RETURNING id INTO parentId;
-- 按钮 SQL
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/get','{{.table.FunctionName}}查询','','','{{.table.FunctionName}}查询',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/add','{{.table.FunctionName}}添加','','','{{.table.FunctionName}}添加',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/edit','{{.table.FunctionName}}修改','','','{{.table.FunctionName}}修改',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/delete','{{.table.FunctionName}}删除','','','{{.table.FunctionName}}删除',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
{{if .table.ExcelPort}}
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/export','{{.table.FunctionName}}导出','','','{{.table.FunctionName}}导出',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
{{end}}
{{if .table.ExcelImp}}
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{.table.BusinessName | CaseCamelLower}}/import','{{.table.FunctionName}}导入','','','{{.table.FunctionName}}导入',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
{{end}}
{{range $index,$column:= .table.Columns}}
{{if and $column.IsStatus $column.IsList}}
INSERT INTO sys_auth_rule (pid,name,title,icon,condition,remark,menu_type,weigh,is_cached,is_hide,path,link_url,component,is_iframe,module_type,model_id,created_at,updated_at)
VALUES(parentId,'{{.apiVersion}}/{{.modulePath}}/{{$.table.BusinessName | CaseCamelLower}}/change{{$column.GoField}}','{{$.table.FunctionName}}{{$column.ColumnComment}}修改','','','{{$.table.FunctionName}}{{$column.ColumnComment}}修改',2,0,1,0,'','','',0,'sys_admin',0,v_time,v_time);
{{end}}
{{end}}
END;
$$;

View File

@ -41,7 +41,7 @@
</el-tag>
</el-form-item>
{{else}}
<el-form-item label="{{$column.ColumnComment}}">{{"{{"}} proxy.getOptionValue(formData.{{$column.HtmlField}}, {{$column.HtmlField}}Options,'value','label') {{"}}"}}</el-form-item>
<el-form-item label="{{$column.ColumnComment}}">{{"{{"}} proxy.getOptionValue({{if eq $column.TsType "boolean"}}formData.{{$column.HtmlField}}?'1':'0'{{else}}formData.{{$column.HtmlField}}{{end}}, {{$column.HtmlField}}Options,'value','label') {{"}}"}}</el-form-item>
{{end}}
{{else}}
<el-form-item label="{{$column.ColumnComment}}">{{"{{"}} formData.{{$column.HtmlField}} {{"}}"}}</el-form-item>

View File

@ -32,6 +32,10 @@
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-input v-model="formData.{{$column.HtmlField}}" placeholder="请输入{{$column.ColumnComment}}" {{if $column.IsPk}}v-bind:disabled="this.currentOp === 'edit'" {{end}}/>
</el-form-item>
{{else if eq $column.HtmlType "inputNumber"}}
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
<el-input-number v-model="formData.{{$column.HtmlField}}" placeholder="请输入{{$column.ColumnComment}}" {{if $column.IsPk}}v-bind:disabled="this.currentOp === 'edit'" {{end}} />
</el-form-item>
{{else if eq $column.HtmlType "select" "selects"}}
{{if ne $column.LinkTableName ""}}
<el-form-item label="{{$column.ColumnComment}}" prop="{{$column.HtmlField}}">
@ -405,7 +409,11 @@ export default defineComponent({
data.{{$column.HtmlField}} = data.{{$column.HtmlField}}.split(",")
{{end}}
{{else if and (eq $column.HtmlType "radio" "select") (ne $column.DictType "")}}
{{if eq $column.TsType "boolean"}}
data.{{$column.HtmlField}} = data.{{$column.HtmlField}}?'1':'0'
{{else}}
data.{{$column.HtmlField}} = ''+data.{{$column.HtmlField}}
{{end}}
{{else if eq $column.HtmlType "radio" "select" }}
{{if eq $column.TsType "number"}}
data.{{$column.HtmlField}} = parseInt(data.{{$column.HtmlField}})

View File

@ -229,6 +229,15 @@
><el-icon><ele-Download /></el-icon>导出Excel</el-button>
</el-col>
{{end}}
{{if .table.ExcelImp }}
<el-col :span="1.5">
<el-button
type="success"
@click="handleImport()"
v-auth="'{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/import'"
><el-icon><ele-Upload /></el-icon>导入Excel</el-button>
</el-col>
{{end}}
</el-row>
</div>
<el-table v-loading="loading" :data="tableData.data" @selection-change="handleSelectionChange">
@ -393,6 +402,11 @@
{{end}}
@{{$businessName}}List="{{$businessName}}List"
></{{.apiVersion|replace "/" "_"|CaseCamel}}{{.modulePath|replace "/" "_"|CaseCamel}}{{.table.ClassName}}Detail>
{{if .table.ExcelImp}}
<loadExcel ref="loadExcel{{.table.ClassName}}Ref" @getList="{{$businessName}}List"
upUrl="{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/import"
tplUrl="/{{.apiVersion}}/{{.table.ModuleName}}/{{$businessName}}/excelTemplate"></loadExcel>
{{end}}
</div>
</template>
@ -451,9 +465,15 @@ import {{.apiVersion|replace "/" "_"|CaseCamel}}{{.modulePath|replace "/" "_"|Ca
{{if .table.ExcelPort }}
import {downLoadXml} from "/@/utils/zipdownload";
{{end}}
{{if .table.ExcelImp}}
import loadExcel from "/@/components/loadExcel/index.vue"
{{end}}
export default defineComponent({
name: "{{.apiVersion|replace "/" "_"|CaseCamel}}{{.modulePath|replace "/" "_"|CaseCamel}}{{.table.ClassName}}List",
components:{
{{if .table.ExcelImp}}
loadExcel,
{{end}}
{{.apiVersion|replace "/" "_"|CaseCamel}}{{.modulePath|replace "/" "_"|CaseCamel}}{{.table.ClassName}}Edit,
{{.apiVersion|replace "/" "_"|CaseCamel}}{{.modulePath|replace "/" "_"|CaseCamel}}{{.table.ClassName}}Detail
},
@ -463,6 +483,9 @@ export default defineComponent({
const queryRef = ref()
const editRef = ref();
const detailRef = ref();
{{if .table.ExcelImp}}
const loadExcel{{.table.ClassName}}Ref = ref();
{{end}}
// 是否显示所有搜索选项
const showAll = ref(false)
// 非单个禁用
@ -659,6 +682,11 @@ export default defineComponent({
downLoadXml('/{{.apiVersion}}/{{.modulePath}}/{{$businessName}}/export',state.tableData.param,'get')
}
{{end}}
{{if .table.ExcelImp}}
const handleImport=()=>{
loadExcel{{$.table.ClassName}}Ref.value.open()
}
{{end}}
return {
proxy,
editRef,
@ -696,6 +724,10 @@ export default defineComponent({
{{if .table.ExcelPort }}
handleExport,
{{end}}
{{if .table.ExcelPort }}
handleImport,
loadExcel{{.table.ClassName}}Ref,
{{end}}
...toRefs(state),
}
}