info.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package model_service
  2. import (
  3. "fmt"
  4. "gfast/app/model/admin/model_fields"
  5. "gfast/app/model/admin/model_info"
  6. "github.com/gogf/gf/container/garray"
  7. "github.com/gogf/gf/errors/gerror"
  8. "github.com/gogf/gf/frame/g"
  9. "github.com/gogf/gf/os/gfile"
  10. "github.com/gogf/gf/os/gtime"
  11. "github.com/gogf/gf/text/gstr"
  12. "github.com/gogf/gf/util/gconv"
  13. "os"
  14. "path/filepath"
  15. "strconv"
  16. )
  17. // 添加
  18. func AddSave(req *model_info.AddReq) error {
  19. return model_info.AddSave(req)
  20. }
  21. // 删除
  22. func DeleteByIds(Ids []int) error {
  23. tx, err := g.DB().Begin()
  24. if err != nil {
  25. g.Log().Error(err)
  26. return gerror.New("事务开启失败")
  27. }
  28. //删除模型信息
  29. err = model_info.DeleteByIds(Ids, tx)
  30. if err != nil {
  31. tx.Rollback()
  32. return err
  33. }
  34. //删除模型字段信息
  35. err = model_fields.DeleteByModelIds(Ids, tx)
  36. if err != nil {
  37. tx.Rollback()
  38. return err
  39. }
  40. tx.Commit()
  41. return nil
  42. }
  43. //修改
  44. func EditSave(editReq *model_info.EditReq) error {
  45. return model_info.EditSave(editReq)
  46. }
  47. // 根据ID查询
  48. func GetByID(id int64) (*model_info.Entity, error) {
  49. return model_info.GetByID(id)
  50. }
  51. // 分页查询
  52. func SelectListByPage(req *model_info.SelectPageReq) (total int, page int, list []*model_info.ListEntity, err error) {
  53. return model_info.SelectListByPage(req)
  54. }
  55. func SetInfoStatus(req *model_info.StatusSetReq) error {
  56. return model_info.SetStatus(req)
  57. }
  58. //模型生成操作
  59. func CreateModel(modelId int64) error {
  60. //表前缀
  61. dbPrefix := g.DB().GetPrefix()
  62. //模型信息
  63. modelInfo, err := model_info.GetByID(modelId)
  64. if err != nil {
  65. return err
  66. }
  67. //字段信息
  68. args := &model_fields.SelectPageReq{
  69. ModelId: modelId,
  70. }
  71. modelFields, err := model_fields.SelectListAll(args)
  72. if err != nil {
  73. return err
  74. }
  75. if modelFields == nil {
  76. return gerror.New("请设置模型字段")
  77. }
  78. if modelInfo.ModelPk == "" {
  79. return gerror.New("请设置主键")
  80. }
  81. if modelInfo.ModelEngine == "" {
  82. modelInfo.ModelEngine = "MyISAM"
  83. }
  84. //备份旧模型表数据
  85. err = buildTableExists(dbPrefix, modelInfo.ModelName)
  86. if err != nil {
  87. return err
  88. }
  89. //重建表操作
  90. //1、删除旧表
  91. sql := fmt.Sprintf("DROP TABLE IF EXISTS `%s%s`;", dbPrefix, modelInfo.ModelName)
  92. _, err = g.DB().Exec(sql)
  93. if err != nil {
  94. g.Log().Error(err)
  95. return gerror.New("删除旧模型数据失败")
  96. }
  97. //重建表格
  98. switch g.Cfg().GetString("database.type") {
  99. case "mysql":
  100. sql := "CREATE TABLE `" + dbPrefix + modelInfo.ModelName + "` (" +
  101. "`" + modelInfo.ModelPk + "` INT UNSIGNED NOT NULL AUTO_INCREMENT," +
  102. "%FIELDS_SQL%" +
  103. "%PRIMARY_KEY_SQL%" +
  104. "%UNIQUE_KEY_SQL%" +
  105. "%KEY_SQL%" +
  106. ")ENGINE=" + modelInfo.ModelEngine + " AUTO_INCREMENT=1 DEFAULT CHARACTER SET utf8mb4 COLLATE = utf8mb4_general_ci;"
  107. SqlFields := garray.NewStrArray()
  108. SqlPrimaryKey := "PRIMARY KEY (`" + modelInfo.ModelPk + "`)"
  109. SqlUniqueKey := garray.NewStrArray()
  110. SqlKey := garray.NewStrArray()
  111. for _, fi := range modelFields {
  112. if fi.FieldName == modelInfo.ModelPk {
  113. continue
  114. }
  115. rules := garray.NewStrArrayFrom(gstr.Split(gstr.Replace(fi.FieldRules, " ", ""), ","))
  116. switch fi.FieldType {
  117. //百度地图字段,双精度型
  118. case "baidu_map":
  119. defal := gstr.Split(fi.FieldDefault, ",")
  120. if len(defal) == 2 {
  121. SqlFields.Append(fmt.Sprintf("`%s_lng` DOUBLE NOT NULL DEFAULT %s COMMENT %s", fi.FieldName, defal[0], fi.FieldTitle))
  122. SqlFields.Append(fmt.Sprintf("`%s_lat` DOUBLE NOT NULL DEFAULT %s COMMENT %s", fi.FieldName, defal[1], fi.FieldTitle))
  123. } else {
  124. SqlFields.Append(fmt.Sprintf("`%s_lng` DOUBLE NOT NULL DEFAULT 0 COMMENT %s", fi.FieldName, fi.FieldTitle))
  125. SqlFields.Append(fmt.Sprintf("`%s_lat` DOUBLE NOT NULL DEFAULT 0 COMMENT %s", fi.FieldName, fi.FieldTitle))
  126. }
  127. //变长或固定字符串型
  128. case "text", "imagefile", "file", "selecttext", "checkbox":
  129. if fi.FieldLength == "" {
  130. fi.FieldLength = "200"
  131. }
  132. fType := "VARCHAR"
  133. //固定长度
  134. if rules.Contains("lengthfixed") {
  135. fType = "CHAR"
  136. }
  137. fNull := ""
  138. //非空
  139. if rules.Contains("required") {
  140. fNull = "NOT NULL"
  141. }
  142. SqlFields.Append(fmt.Sprintf("`%s` %s(%s) %s DEFAULT '%s' COMMENT '%s'", fi.FieldName, fType, fi.FieldLength, fNull, fi.FieldDefault, fi.FieldTitle))
  143. //bigint型
  144. case "currency", "large_number", "datetime", "date":
  145. fUnsigned := ""
  146. //非负数
  147. if rules.Contains("unsigned") || fi.FieldType == "date" || fi.FieldType == "datetime" {
  148. fUnsigned = "UNSIGNED"
  149. }
  150. fNull := "NOT NULL"
  151. if fi.FieldDefault == "" {
  152. fi.FieldDefault = "0"
  153. }
  154. SqlFields.Append(fmt.Sprintf("`%s` BIGINT %s %s DEFAULT %s COMMENT '%s' ", fi.FieldName, fUnsigned, fNull, fi.FieldDefault, fi.FieldTitle))
  155. //整数型
  156. case "number", "selectnumber":
  157. fUnsigned := ""
  158. //非负数
  159. if rules.Contains("unsigned") {
  160. fUnsigned = "UNSIGNED"
  161. }
  162. fNull := "NOT NULL"
  163. if fi.FieldDefault == "" {
  164. fi.FieldDefault = "0"
  165. }
  166. SqlFields.Append(fmt.Sprintf("`%s` INT %s %s DEFAULT %s COMMENT '%s' ", fi.FieldName, fUnsigned, fNull, fi.FieldDefault, fi.FieldTitle))
  167. //text型
  168. case "richtext", "bigtext", "images", "files":
  169. SqlFields.Append(fmt.Sprintf("`%s` TEXT COMMENT '%s'", fi.FieldName, fi.FieldTitle))
  170. //TINYINT型
  171. case "switch":
  172. if fi.FieldDefault == "" {
  173. fi.FieldDefault = "0"
  174. }
  175. SqlFields.Append(fmt.Sprintf("`%s` TINYINT UNSIGNED NOT NULL DEFAULT %s COMMENT '%s'",
  176. fi.FieldName, fi.FieldDefault, fi.FieldTitle))
  177. default:
  178. return gerror.New("不能识别字段类型")
  179. }
  180. typeUnique := garray.NewStrArrayFrom([]string{"switch", "text", "number", "datetime", "date", "selecttext", "selectnumber", "checkbox"})
  181. if typeUnique.Contains(fi.FieldType) && rules.Contains("unique") {
  182. SqlUniqueKey.Append(fmt.Sprintf("UNIQUE KEY %s (%s)", fi.FieldName, fi.FieldName))
  183. }
  184. }
  185. //普通索引
  186. if modelInfo.ModelIndexes != "" {
  187. modelIndexes := gstr.Split(modelInfo.ModelIndexes, ",")
  188. for _, ind := range modelIndexes {
  189. SqlKey.Append(fmt.Sprintf("INDEX IX_%s (%s)", ind, ind))
  190. }
  191. }
  192. //替换sql占位符
  193. sqlFieldTag := ""
  194. if SqlPrimaryKey != "" || SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0 {
  195. sqlFieldTag = ",\n"
  196. }
  197. primaryTag := ""
  198. if SqlPrimaryKey != "" && (SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0) {
  199. primaryTag = ",\n"
  200. }
  201. uniqueTag := ""
  202. if SqlUniqueKey.Len() != 0 && SqlKey.Len() != 0 {
  203. uniqueTag = ",\n"
  204. }
  205. sql = gstr.ReplaceByArray(sql, []string{
  206. "%FIELDS_SQL%",
  207. SqlFields.Join(",") + sqlFieldTag,
  208. "%PRIMARY_KEY_SQL%",
  209. SqlPrimaryKey + primaryTag,
  210. "%UNIQUE_KEY_SQL%",
  211. SqlUniqueKey.Join(",") + uniqueTag,
  212. "%KEY_SQL%",
  213. SqlKey.Join(","),
  214. })
  215. _, err = g.DB().Exec(sql)
  216. if err != nil {
  217. g.Log().Error(err)
  218. return gerror.New("建表发生错误")
  219. }
  220. }
  221. return nil
  222. }
  223. //备份已存在的模型表
  224. func buildTableExists(dbPrefix, modelName string) error {
  225. //数据库名称
  226. dbName := g.Cfg().GetString("database.name")
  227. res, err := g.DB().GetAll("SHOW TABLE STATUS FROM " + dbName)
  228. if err != nil {
  229. g.Log().Error(err)
  230. return gerror.New("数据库信息获取失败")
  231. }
  232. tables := garray.New()
  233. for _, tbInfo := range res {
  234. tabName := gconv.String(tbInfo["Name"])
  235. if dbPrefix != "" && gstr.PosI(tabName, dbPrefix) == 0 {
  236. tables.Append(gstr.ToLower(gstr.SubStr(tabName, 0, len(dbPrefix))))
  237. }
  238. tables.Append(gstr.ToLower(tabName))
  239. }
  240. if tables.Contains(modelName) {
  241. //表格若已经存在则备份
  242. pathDir := g.Cfg().GetString("adminInfo.dataDir") + "/dataBak"
  243. pathDir, err := filepath.Abs(pathDir)
  244. if err != nil {
  245. g.Log().Error(err)
  246. return gerror.New("获取数据表备份路径失败")
  247. }
  248. //路径不存在则创建之
  249. err = os.MkdirAll(pathDir, os.ModeDir)
  250. if err != nil {
  251. g.Log().Error(err)
  252. return gerror.New("创建备份目录失败")
  253. }
  254. err = backupTable(pathDir, modelName, dbPrefix)
  255. if err != nil {
  256. return err
  257. }
  258. }
  259. return nil
  260. }
  261. //备份数据表操作
  262. func backupTable(pathDir, tableName, prefix string) error {
  263. switch g.Cfg().GetString("database.type") {
  264. case "mysql":
  265. rec, err := g.DB().GetOne(fmt.Sprintf("SHOW CREATE TABLE %s%s ", prefix, tableName))
  266. if err != nil {
  267. g.Log().Error(err)
  268. return gerror.New("获取备份表信息失败")
  269. }
  270. tableCreateSql := rec["Create Table"].String()
  271. res, err := g.DB().GetAll(fmt.Sprintf("SELECT * FROM %s%s", prefix, tableName))
  272. if err != nil {
  273. g.Log().Error(err)
  274. return gerror.New("获取备份表数据失败")
  275. }
  276. dataValues := garray.NewStrArray()
  277. keyValues := garray.NewStrArray()
  278. for _, v := range res {
  279. var str string
  280. vKey := garray.NewStrArray()
  281. vValues := garray.NewStrArray()
  282. for kk, vv := range v {
  283. str = strconv.Quote(gconv.String(vv))
  284. vValues.Append(str)
  285. vKey.Append(kk)
  286. }
  287. dataValues.Append("(" + vValues.Join(",") + ")")
  288. keyValues.Append("(" + vKey.Join(",") + ")")
  289. }
  290. insertDataSql := ""
  291. keyValues.Iterator(func(kk int, kv string) bool {
  292. vv, _ := dataValues.Get(kk)
  293. insertDataSql += fmt.Sprintf("INSERT INTO `%s%s` %s VALUES %s;\n", prefix, tableName, kv, vv)
  294. return true
  295. })
  296. tableCreateSql = tableCreateSql + ";\n" + insertDataSql + ";"
  297. //保存到文件中
  298. err = gfile.PutContents(fmt.Sprintf(pathDir+"/%s%s_%d.sql", prefix, tableName, gtime.Timestamp()), tableCreateSql)
  299. if err != nil {
  300. g.Log().Error(err)
  301. return gerror.New("创建备份文件失败")
  302. }
  303. }
  304. return nil
  305. }
  306. //复制模型
  307. func CopyModel(modelId int64) error {
  308. //获取要复制的模型信息
  309. modelInfo, err := GetByID(modelId)
  310. if err != nil {
  311. return err
  312. }
  313. req := &model_fields.SelectPageReq{ModelId: modelId}
  314. modelFields, err := model_fields.SelectListAll(req)
  315. if err != nil {
  316. return err
  317. }
  318. tx, err := g.DB().Begin()
  319. if err != nil {
  320. g.Log().Error(err)
  321. return gerror.New("开启事务失败")
  322. }
  323. modelInfo.ModelId = 0
  324. modelInfo.ModelName = modelInfo.ModelName + "_copy"
  325. res, err := tx.Model(model_info.Table).Insert(modelInfo)
  326. if err != nil {
  327. g.Log().Error(err)
  328. tx.Rollback()
  329. return gerror.New("复制模型信息失败")
  330. }
  331. insId, err := res.LastInsertId()
  332. if err != nil {
  333. g.Log().Error(err)
  334. tx.Rollback()
  335. return gerror.New("获取复制模型信Id失败")
  336. }
  337. newModelId := gconv.Uint(insId)
  338. for _, field := range modelFields {
  339. field.FieldId = 0
  340. field.ModelId = newModelId
  341. }
  342. if modelFields != nil {
  343. _, err = tx.BatchInsert(model_fields.Table, modelFields)
  344. if err != nil {
  345. g.Log().Error(err)
  346. tx.Rollback()
  347. return gerror.New("复制模型字段信息失败")
  348. }
  349. }
  350. tx.Commit()
  351. return nil
  352. }
  353. func GetModelsByCateIds(cateIds []int) (models []*model_info.Entity, err error) {
  354. return model_info.GetModelsByCateIds(cateIds)
  355. }