| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- package model_service
- import (
- "fmt"
- "gfast/app/model/admin/model_fields"
- "gfast/app/model/admin/model_info"
- "github.com/gogf/gf/container/garray"
- "github.com/gogf/gf/errors/gerror"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/os/gfile"
- "github.com/gogf/gf/os/gtime"
- "github.com/gogf/gf/text/gstr"
- "github.com/gogf/gf/util/gconv"
- "os"
- "path/filepath"
- "strconv"
- )
- // 添加
- func AddSave(req *model_info.AddReq) error {
- return model_info.AddSave(req)
- }
- // 删除
- func DeleteByIds(Ids []int) error {
- tx, err := g.DB().Begin()
- if err != nil {
- g.Log().Error(err)
- return gerror.New("事务开启失败")
- }
- //删除模型信息
- err = model_info.DeleteByIds(Ids, tx)
- if err != nil {
- tx.Rollback()
- return err
- }
- //删除模型字段信息
- err = model_fields.DeleteByModelIds(Ids, tx)
- if err != nil {
- tx.Rollback()
- return err
- }
- tx.Commit()
- return nil
- }
- //修改
- func EditSave(editReq *model_info.EditReq) error {
- return model_info.EditSave(editReq)
- }
- // 根据ID查询
- func GetByID(id int64) (*model_info.Entity, error) {
- return model_info.GetByID(id)
- }
- // 分页查询
- func SelectListByPage(req *model_info.SelectPageReq) (total int, page int, list []*model_info.ListEntity, err error) {
- return model_info.SelectListByPage(req)
- }
- func SetInfoStatus(req *model_info.StatusSetReq) error {
- return model_info.SetStatus(req)
- }
- //模型生成操作
- func CreateModel(modelId int64) error {
- //表前缀
- dbPrefix := g.DB().GetPrefix()
- //模型信息
- modelInfo, err := model_info.GetByID(modelId)
- if err != nil {
- return err
- }
- //字段信息
- args := &model_fields.SelectPageReq{
- ModelId: modelId,
- }
- modelFields, err := model_fields.SelectListAll(args)
- if err != nil {
- return err
- }
- if modelFields == nil {
- return gerror.New("请设置模型字段")
- }
- if modelInfo.ModelPk == "" {
- return gerror.New("请设置主键")
- }
- if modelInfo.ModelEngine == "" {
- modelInfo.ModelEngine = "MyISAM"
- }
- //备份旧模型表数据
- err = buildTableExists(dbPrefix, modelInfo.ModelName)
- if err != nil {
- return err
- }
- //重建表操作
- //1、删除旧表
- sql := fmt.Sprintf("DROP TABLE IF EXISTS `%s%s`;", dbPrefix, modelInfo.ModelName)
- _, err = g.DB().Exec(sql)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("删除旧模型数据失败")
- }
- //重建表格
- switch g.Cfg().GetString("database.type") {
- case "mysql":
- sql := "CREATE TABLE `" + dbPrefix + modelInfo.ModelName + "` (" +
- "`" + modelInfo.ModelPk + "` INT UNSIGNED NOT NULL AUTO_INCREMENT," +
- "%FIELDS_SQL%" +
- "%PRIMARY_KEY_SQL%" +
- "%UNIQUE_KEY_SQL%" +
- "%KEY_SQL%" +
- ")ENGINE=" + modelInfo.ModelEngine + " AUTO_INCREMENT=1 DEFAULT CHARACTER SET utf8mb4 COLLATE = utf8mb4_general_ci;"
- SqlFields := garray.NewStrArray()
- SqlPrimaryKey := "PRIMARY KEY (`" + modelInfo.ModelPk + "`)"
- SqlUniqueKey := garray.NewStrArray()
- SqlKey := garray.NewStrArray()
- for _, fi := range modelFields {
- if fi.FieldName == modelInfo.ModelPk {
- continue
- }
- rules := garray.NewStrArrayFrom(gstr.Split(gstr.Replace(fi.FieldRules, " ", ""), ","))
- switch fi.FieldType {
- //百度地图字段,双精度型
- case "baidu_map":
- defal := gstr.Split(fi.FieldDefault, ",")
- if len(defal) == 2 {
- SqlFields.Append(fmt.Sprintf("`%s_lng` DOUBLE NOT NULL DEFAULT %s COMMENT %s", fi.FieldName, defal[0], fi.FieldTitle))
- SqlFields.Append(fmt.Sprintf("`%s_lat` DOUBLE NOT NULL DEFAULT %s COMMENT %s", fi.FieldName, defal[1], fi.FieldTitle))
- } else {
- SqlFields.Append(fmt.Sprintf("`%s_lng` DOUBLE NOT NULL DEFAULT 0 COMMENT %s", fi.FieldName, fi.FieldTitle))
- SqlFields.Append(fmt.Sprintf("`%s_lat` DOUBLE NOT NULL DEFAULT 0 COMMENT %s", fi.FieldName, fi.FieldTitle))
- }
- //变长或固定字符串型
- case "text", "imagefile", "file", "selecttext", "checkbox":
- if fi.FieldLength == "" {
- fi.FieldLength = "200"
- }
- fType := "VARCHAR"
- //固定长度
- if rules.Contains("lengthfixed") {
- fType = "CHAR"
- }
- fNull := ""
- //非空
- if rules.Contains("required") {
- fNull = "NOT NULL"
- }
- SqlFields.Append(fmt.Sprintf("`%s` %s(%s) %s DEFAULT '%s' COMMENT '%s'", fi.FieldName, fType, fi.FieldLength, fNull, fi.FieldDefault, fi.FieldTitle))
- //bigint型
- case "currency", "large_number", "datetime", "date":
- fUnsigned := ""
- //非负数
- if rules.Contains("unsigned") || fi.FieldType == "date" || fi.FieldType == "datetime" {
- fUnsigned = "UNSIGNED"
- }
- fNull := "NOT NULL"
- if fi.FieldDefault == "" {
- fi.FieldDefault = "0"
- }
- SqlFields.Append(fmt.Sprintf("`%s` BIGINT %s %s DEFAULT %s COMMENT '%s' ", fi.FieldName, fUnsigned, fNull, fi.FieldDefault, fi.FieldTitle))
- //整数型
- case "number", "selectnumber":
- fUnsigned := ""
- //非负数
- if rules.Contains("unsigned") {
- fUnsigned = "UNSIGNED"
- }
- fNull := "NOT NULL"
- if fi.FieldDefault == "" {
- fi.FieldDefault = "0"
- }
- SqlFields.Append(fmt.Sprintf("`%s` INT %s %s DEFAULT %s COMMENT '%s' ", fi.FieldName, fUnsigned, fNull, fi.FieldDefault, fi.FieldTitle))
- //text型
- case "richtext", "bigtext", "images", "files":
- SqlFields.Append(fmt.Sprintf("`%s` TEXT COMMENT '%s'", fi.FieldName, fi.FieldTitle))
- //TINYINT型
- case "switch":
- if fi.FieldDefault == "" {
- fi.FieldDefault = "0"
- }
- SqlFields.Append(fmt.Sprintf("`%s` TINYINT UNSIGNED NOT NULL DEFAULT %s COMMENT '%s'",
- fi.FieldName, fi.FieldDefault, fi.FieldTitle))
- //部门选择器
- case "DepartmentSelector":
- SqlFields.Append(fmt.Sprintf("`%s` VARCHAR(300) %s DEFAULT '' COMMENT '%s'", fi.FieldName, fi.FieldDefault, fi.FieldTitle))
- default:
- return gerror.New("不能识别字段类型")
- }
- typeUnique := garray.NewStrArrayFrom([]string{"switch", "text", "number", "datetime", "date", "selecttext", "selectnumber", "checkbox"})
- if typeUnique.Contains(fi.FieldType) && rules.Contains("unique") {
- SqlUniqueKey.Append(fmt.Sprintf("UNIQUE KEY %s (%s)", fi.FieldName, fi.FieldName))
- }
- }
- //普通索引
- if modelInfo.ModelIndexes != "" {
- modelIndexes := gstr.Split(modelInfo.ModelIndexes, ",")
- for _, ind := range modelIndexes {
- SqlKey.Append(fmt.Sprintf("INDEX IX_%s (%s)", ind, ind))
- }
- }
- //替换sql占位符
- sqlFieldTag := ""
- if SqlPrimaryKey != "" || SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0 {
- sqlFieldTag = ",\n"
- }
- primaryTag := ""
- if SqlPrimaryKey != "" && (SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0) {
- primaryTag = ",\n"
- }
- uniqueTag := ""
- if SqlUniqueKey.Len() != 0 && SqlKey.Len() != 0 {
- uniqueTag = ",\n"
- }
- sql = gstr.ReplaceByArray(sql, []string{
- "%FIELDS_SQL%",
- SqlFields.Join(",") + sqlFieldTag,
- "%PRIMARY_KEY_SQL%",
- SqlPrimaryKey + primaryTag,
- "%UNIQUE_KEY_SQL%",
- SqlUniqueKey.Join(",") + uniqueTag,
- "%KEY_SQL%",
- SqlKey.Join(","),
- })
- _, err = g.DB().Exec(sql)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("建表发生错误")
- }
- }
- return nil
- }
- //备份已存在的模型表
- func buildTableExists(dbPrefix, modelName string) error {
- //数据库名称
- dbName := g.Cfg().GetString("database.name")
- res, err := g.DB().GetAll("SHOW TABLE STATUS FROM " + dbName)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("数据库信息获取失败")
- }
- tables := garray.New()
- for _, tbInfo := range res {
- tabName := gconv.String(tbInfo["Name"])
- if dbPrefix != "" && gstr.PosI(tabName, dbPrefix) == 0 {
- tables.Append(gstr.ToLower(gstr.SubStr(tabName, 0, len(dbPrefix))))
- }
- tables.Append(gstr.ToLower(tabName))
- }
- if tables.Contains(modelName) {
- //表格若已经存在则备份
- pathDir := g.Cfg().GetString("adminInfo.dataDir") + "/dataBak"
- pathDir, err := filepath.Abs(pathDir)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("获取数据表备份路径失败")
- }
- //路径不存在则创建之
- err = os.MkdirAll(pathDir, os.ModeDir)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("创建备份目录失败")
- }
- err = backupTable(pathDir, modelName, dbPrefix)
- if err != nil {
- return err
- }
- }
- return nil
- }
- //备份数据表操作
- func backupTable(pathDir, tableName, prefix string) error {
- switch g.Cfg().GetString("database.type") {
- case "mysql":
- rec, err := g.DB().GetOne(fmt.Sprintf("SHOW CREATE TABLE %s%s ", prefix, tableName))
- if err != nil {
- g.Log().Error(err)
- return gerror.New("获取备份表信息失败")
- }
- tableCreateSql := rec["Create Table"].String()
- res, err := g.DB().GetAll(fmt.Sprintf("SELECT * FROM %s%s", prefix, tableName))
- if err != nil {
- g.Log().Error(err)
- return gerror.New("获取备份表数据失败")
- }
- dataValues := garray.NewStrArray()
- keyValues := garray.NewStrArray()
- for _, v := range res {
- var str string
- vKey := garray.NewStrArray()
- vValues := garray.NewStrArray()
- for kk, vv := range v {
- str = strconv.Quote(gconv.String(vv))
- vValues.Append(str)
- vKey.Append(kk)
- }
- dataValues.Append("(" + vValues.Join(",") + ")")
- keyValues.Append("(" + vKey.Join(",") + ")")
- }
- insertDataSql := ""
- keyValues.Iterator(func(kk int, kv string) bool {
- vv, _ := dataValues.Get(kk)
- insertDataSql += fmt.Sprintf("INSERT INTO `%s%s` %s VALUES %s;\n", prefix, tableName, kv, vv)
- return true
- })
- tableCreateSql = tableCreateSql + ";\n" + insertDataSql + ";"
- //保存到文件中
- err = gfile.PutContents(fmt.Sprintf(pathDir+"/%s%s_%d.sql", prefix, tableName, gtime.Timestamp()), tableCreateSql)
- if err != nil {
- g.Log().Error(err)
- return gerror.New("创建备份文件失败")
- }
- }
- return nil
- }
- //复制模型
- func CopyModel(modelId int64) error {
- //获取要复制的模型信息
- modelInfo, err := GetByID(modelId)
- if err != nil {
- return err
- }
- req := &model_fields.SelectPageReq{ModelId: modelId}
- modelFields, err := model_fields.SelectListAll(req)
- if err != nil {
- return err
- }
- tx, err := g.DB().Begin()
- if err != nil {
- g.Log().Error(err)
- return gerror.New("开启事务失败")
- }
- modelInfo.ModelId = 0
- modelInfo.ModelName = modelInfo.ModelName + "_copy"
- res, err := tx.Model(model_info.Table).Insert(modelInfo)
- if err != nil {
- g.Log().Error(err)
- tx.Rollback()
- return gerror.New("复制模型信息失败")
- }
- insId, err := res.LastInsertId()
- if err != nil {
- g.Log().Error(err)
- tx.Rollback()
- return gerror.New("获取复制模型信Id失败")
- }
- newModelId := gconv.Uint(insId)
- for _, field := range modelFields {
- field.FieldId = 0
- field.ModelId = newModelId
- }
- if modelFields != nil {
- _, err = tx.BatchInsert(model_fields.Table, modelFields)
- if err != nil {
- g.Log().Error(err)
- tx.Rollback()
- return gerror.New("复制模型字段信息失败")
- }
- }
- tx.Commit()
- return nil
- }
- func GetModelsByCateIds(cateIds []int) (models []*model_info.Entity, err error) {
- return model_info.GetModelsByCateIds(cateIds)
- }
|