Files
x_admin/server/app/service/generatorService/service.go
T
2025-12-18 22:23:09 +08:00

424 lines
13 KiB
Go

package generatorService
import (
"archive/zip"
"bytes"
"x_admin/app/schema/generatorSchema"
"x_admin/app/service/generatorService/tpl_utils"
"x_admin/config"
"x_admin/core"
"x_admin/core/request"
"x_admin/core/response"
"x_admin/model/gen_model"
"x_admin/util/convert_util"
"strings"
"x_admin/util"
"gorm.io/gorm"
)
var GenerateService = NewGenerateService()
// NewGenerateService 初始化
func NewGenerateService() *generateService {
db := core.GetDB()
return &generateService{db: db}
}
// GenerateService 代码生成服务实现类
type generateService struct {
db *gorm.DB
}
// DbTables 库表列表
func (genSrv generateService) DbTables(page request.PageReq, dbReq generatorSchema.DbTablesReq) (res response.PageResp, e error) {
// 分页信息
limit := page.PageSize
offset := page.PageSize * (page.PageNo - 1)
tbModel := tpl_utils.GenUtil.GetDbTablesQuery(genSrv.db, dbReq.TableName, dbReq.TableComment)
// 总数
var count int64
err := tbModel.Count(&count).Error
if e = response.CheckErr(err, "DbTables Count err"); e != nil {
return
}
// 数据
var tbResp []generatorSchema.DbTableResp
err = tbModel.Limit(limit).Offset(offset).Find(&tbResp).Error
if e = response.CheckErr(err, "DbTables Find err"); e != nil {
return
}
return response.PageResp{
PageNo: page.PageNo,
PageSize: page.PageSize,
Count: count,
Lists: tbResp,
}, nil
}
// List 生成列表
func (genSrv generateService) List(page request.PageReq, listReq generatorSchema.ListTableReq) (res response.PageResp, e error) {
// 分页信息
limit := page.PageSize
offset := page.PageSize * (page.PageNo - 1)
genModel := genSrv.db.Model(&gen_model.GenTable{})
if listReq.TableName != "" {
genModel = genModel.Where("table_name like ?", "%"+listReq.TableName+"%")
}
if listReq.TableComment != "" {
genModel = genModel.Where("table_comment like ?", "%"+listReq.TableComment+"%")
}
if !listReq.StartTime.IsZero() {
genModel = genModel.Where("create_time >= ?", listReq.StartTime)
}
if !listReq.EndTime.IsZero() {
genModel = genModel.Where("create_time <= ?", listReq.EndTime)
}
// 总数
var count int64
err := genModel.Count(&count).Error
if e = response.CheckErr(err, "列表总数获取失败"); e != nil {
return
}
// 数据
var genResp []generatorSchema.GenTableResp
err = genModel.Limit(limit).Offset(offset).Order("id desc").Find(&genResp).Error
if e = response.CheckErr(err, "列表获取失败"); e != nil {
return
}
return response.PageResp{
PageNo: page.PageNo,
PageSize: page.PageSize,
Count: count,
Lists: genResp,
}, nil
}
// Detail 生成详情
func (genSrv generateService) Detail(id string) (res generatorSchema.GenTableDetailResp, e error) {
var genTb gen_model.GenTable
err := genSrv.db.Where("id = ?", id).Limit(1).First(&genTb).Error
if e = response.CheckErrDBNotRecord(err, "查询的数据不存在!"); e != nil {
return
}
if e = response.CheckErr(err, "Detail Find err"); e != nil {
return
}
var columns []gen_model.GenTableColumn
err = genSrv.db.Where("table_id = ?", id).Order("sort").Find(&columns).Error
if e = response.CheckErr(err, "Detail Find err"); e != nil {
return
}
var base generatorSchema.GenTableBaseResp
convert_util.Copy(&base, genTb)
var gen generatorSchema.GenTableGenResp
convert_util.Copy(&gen, genTb)
var colResp []generatorSchema.GenColumnResp
convert_util.Copy(&colResp, columns)
return generatorSchema.GenTableDetailResp{
Base: base,
Gen: gen,
Column: colResp,
}, e
}
// ImportTable 导入表结构
func (genSrv generateService) ImportTable(tableNames []string) (e error) {
var dbTbs []generatorSchema.DbTableResp
err := tpl_utils.GenUtil.GetDbTablesQueryByNames(genSrv.db, tableNames).Find(&dbTbs).Error
if e = response.CheckErr(err, "ImportTable Find tables err"); e != nil {
return
}
var tables []gen_model.GenTable
convert_util.Copy(&tables, dbTbs)
if len(tables) == 0 {
e = response.AssertArgumentError.SetMessage("表不存在!")
return
}
err = genSrv.db.Transaction(func(tx *gorm.DB) error {
for i := 0; i < len(tables); i++ {
//生成表信息
genTable := tpl_utils.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_model.GenTableColumn
txErr = tpl_utils.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 := tpl_utils.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 e
}
// SyncTable 同步表结构
func (genSrv generateService) SyncTable(id string) (e error) {
//旧数据
var genTable gen_model.GenTable
err := genSrv.db.Where("id = ?", id).Limit(1).First(&genTable).Error
if e = response.CheckErrDBNotRecord(err, "生成数据不存在!"); e != nil {
return
}
if e = response.CheckErr(err, "SyncTable First err"); e != nil {
return
}
var genTableCols []gen_model.GenTableColumn
err = genSrv.db.Where("table_id = ?", id).Order("sort").Find(&genTableCols).Error
if e = response.CheckErr(err, "SyncTable Find err"); e != nil {
return
}
if len(genTableCols) <= 0 {
e = response.AssertArgumentError.SetMessage("旧数据异常!")
return
}
prevColMap := make(map[string]gen_model.GenTableColumn)
for i := 0; i < len(genTableCols); i++ {
prevColMap[genTableCols[i].ColumnName] = genTableCols[i]
}
//新数据
var columns []gen_model.GenTableColumn
err = tpl_utils.GenUtil.GetDbTableColumnsQueryByName(genSrv.db, genTable.TableName).Find(&columns).Error
if e = response.CheckErr(err, "SyncTable Find new err"); e != nil {
return
}
if len(columns) <= 0 {
e = response.AssertArgumentError.SetMessage("同步结构失败,原表结构不存在!")
return
}
//事务处理
err = genSrv.db.Transaction(func(tx *gorm.DB) error {
//处理新增和更新
for i := 0; i < len(columns); i++ {
col := tpl_utils.GenUtil.InitColumn(id, columns[i])
if prevCol, ok := prevColMap[columns[i].ColumnName]; ok {
//更新
col.ID = prevCol.ID
if col.IsList == 0 {
col.DictType = prevCol.DictType
col.ListAllApi = prevCol.ListAllApi
col.QueryType = prevCol.QueryType
}
if prevCol.IsRequired == 1 && prevCol.IsPk == 0 && prevCol.IsInsert == 1 || prevCol.IsEdit == 1 {
col.HtmlType = prevCol.HtmlType
col.IsRequired = prevCol.IsRequired
}
txErr := tx.Save(&col).Error
if te := response.CheckErr(txErr, "SyncTable Save err"); te != nil {
return te
}
} else {
//新增
txErr := tx.Create(&col).Error
if te := response.CheckErr(txErr, "SyncTable Create err"); te != nil {
return te
}
}
}
//处理删除
colNames := make([]string, len(columns))
for i := 0; i < len(columns); i++ {
colNames[i] = columns[i].ColumnName
}
delColIds := make([]string, 0)
for _, prevCol := range prevColMap {
if !util.ToolsUtil.Contains(colNames, prevCol.ColumnName) {
delColIds = append(delColIds, prevCol.ID)
}
}
if len(delColIds) > 0 {
txErr := tx.Delete(&gen_model.GenTableColumn{}, "id in ?", delColIds).Error
if te := response.CheckErr(txErr, "SyncTable Delete err"); te != nil {
return te
}
}
return nil
})
e = response.CheckErr(err, "SyncTable Transaction err")
return e
}
// EditTable 编辑表结构
func (genSrv generateService) EditTable(editReq generatorSchema.EditTableReq) (e error) {
if editReq.GenTpl == tpl_utils.GenConstants.TplTree {
if editReq.TreePrimary == "" {
e = response.AssertArgumentError.SetMessage("树主ID不能为空!")
return
}
if editReq.TreeParent == "" {
e = response.AssertArgumentError.SetMessage("树父ID不能为空!")
return
}
}
var genTable gen_model.GenTable
err := genSrv.db.Where("id = ?", editReq.ID).Limit(1).First(&genTable).Error
if e = response.CheckErrDBNotRecord(err, "数据已丢失!"); e != nil {
return
}
if e = response.CheckErr(err, "查找数据失败"); e != nil {
return
}
convert_util.Copy(&genTable, editReq)
err = genSrv.db.Transaction(func(tx *gorm.DB) error {
genTable.SubTableName = strings.Replace(editReq.SubTableName, config.DBConfig.TablePrefix, "", 1)
txErr := tx.Save(&genTable).Error
if te := response.CheckErr(txErr, "更新失败"); te != nil {
return te
}
for i := 0; i < len(editReq.Columns); i++ {
var col gen_model.GenTableColumn
convert_util.Copy(&col, editReq.Columns[i])
txErr = tx.Save(&col).Error
if te := response.CheckErr(txErr, "更新失败"); te != nil {
return te
}
}
return nil
})
e = response.CheckErr(err, "EditTable Transaction err")
return
}
// DelTable 删除表结构
func (genSrv generateService) DelTable(ids []string) (e error) {
err := genSrv.db.Transaction(func(tx *gorm.DB) error {
txErr := tx.Delete(&gen_model.GenTable{}, "id in ?", ids).Error
if te := response.CheckErr(txErr, "DelTable Delete GenTable err"); te != nil {
return te
}
txErr = tx.Delete(&gen_model.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
}
// getSubTableInfo 根据主表获取子表主键和列信息
func (genSrv generateService) getSubTableInfo(genTable gen_model.GenTable) (pkCol gen_model.GenTableColumn, cols []gen_model.GenTableColumn, e error) {
if genTable.SubTableName == "" || genTable.SubTableFk == "" {
return
}
var table gen_model.GenTable
err := genSrv.db.Where("table_name = ?", genTable.SubTableName).Limit(1).First(&table).Error
if e = response.CheckErrDBNotRecord(err, "子表记录丢失!"); e != nil {
return
}
if e = response.CheckErr(err, "getSubTableInfo First err"); e != nil {
return
}
err = tpl_utils.GenUtil.GetDbTableColumnsQueryByName(genSrv.db, genTable.SubTableName).Find(&cols).Error
if e = response.CheckErr(err, "getSubTableInfo Find err"); e != nil {
return
}
pkCol = tpl_utils.GenUtil.InitColumn(table.ID, tpl_utils.GenUtil.GetTablePriCol(cols))
return
}
// renderCodeByTable 根据主表和模板文件渲染模板代码
func (genSrv generateService) renderCodeByTable(genTable gen_model.GenTable) (res map[string]string, e error) {
var columns []gen_model.GenTableColumn
err := genSrv.db.Where("table_id = ?", genTable.ID).Order("sort").Find(&columns).Error
if e = response.CheckErr(err, "获取表信息失败"); e != nil {
return
}
//获取子表信息
pkCol, cols, err := genSrv.getSubTableInfo(genTable)
if e = response.CheckErr(err, "获取子表信息失败"); e != nil {
return
}
//获取模板变量信息
vars := tpl_utils.TemplateUtil.PrepareVars(genTable, columns, pkCol, cols)
//生成模板内容
res = make(map[string]string)
tplPaths := tpl_utils.TemplateUtil.GetTemplatePaths(genTable.GenTpl)
for _, tplPath := range tplPaths {
res[tplPath], err = tpl_utils.TemplateUtil.Render(tplPath, vars)
if e = response.CheckErr(err, "渲染模板失败"); e != nil {
return
}
}
return
}
// PreviewCode 预览代码
func (genSrv generateService) PreviewCode(id string) (res map[string]string, e error) {
var genTable gen_model.GenTable
err := genSrv.db.Where("id = ?", id).Limit(1).First(&genTable).Error
if e = response.CheckErrDBNotRecord(err, "记录丢失!"); e != nil {
return
}
if e = response.CheckErr(err, "PreviewCode First err"); e != nil {
return
}
//获取模板内容
tplCodeMap, err := genSrv.renderCodeByTable(genTable)
if e = response.CheckErr(err, "PreviewCode renderCodeByTable err"); e != nil {
return
}
// res = make(map[string]string)
// for tplPath, tplCode := range tplCodeMap {
// res[strings.ReplaceAll(tplPath, ".tpl", "")] = tplCode
// }
res = tpl_utils.TemplateUtil.GetFilePaths(tplCodeMap, genTable.ModuleName)
return
}
// genZipCode 生成代码 (压缩包下载)
func (genSrv generateService) genZipCode(zipWriter *zip.Writer, tableName string) (e error) {
var genTable gen_model.GenTable
err := genSrv.db.Where("table_name = ?", tableName).Order("id desc").Limit(1).First(&genTable).Error
if e = response.CheckErrDBNotRecord(err, "记录丢失!"); e != nil {
return
}
if e = response.CheckErr(err, "genZipCode First err"); e != nil {
return
}
//获取模板内容
tplCodeMap, err := genSrv.renderCodeByTable(genTable)
if e = response.CheckErr(err, "genZipCode renderCodeByTable err"); e != nil {
return
}
//压缩文件
err = tpl_utils.TemplateUtil.GenZip(zipWriter, tplCodeMap, genTable.ModuleName)
if e = response.CheckErr(err, "genZipCode GenZip err"); e != nil {
return
}
return
}
// DownloadCode 下载代码
func (genSrv generateService) DownloadCode(tableNames []string) ([]byte, error) {
buf := new(bytes.Buffer)
zipWriter := zip.NewWriter(buf)
for _, tableName := range tableNames {
err := genSrv.genZipCode(zipWriter, tableName)
if err != nil {
return nil, response.CheckErr(err, "DownloadCode genZipCode for %s err", tableName)
}
}
err := zipWriter.Close()
if err != nil {
return nil, response.CheckErr(err, "DownloadCode zipWriter.Close err")
}
return buf.Bytes(), nil
}