info.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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. //部门选择器
  178. case "DepartmentSelector":
  179. SqlFields.Append(fmt.Sprintf("`%s` VARCHAR(300) %s DEFAULT '' COMMENT '%s'", fi.FieldName, fi.FieldDefault, fi.FieldTitle))
  180. default:
  181. return gerror.New("不能识别字段类型")
  182. }
  183. typeUnique := garray.NewStrArrayFrom([]string{"switch", "text", "number", "datetime", "date", "selecttext", "selectnumber", "checkbox"})
  184. if typeUnique.Contains(fi.FieldType) && rules.Contains("unique") {
  185. SqlUniqueKey.Append(fmt.Sprintf("UNIQUE KEY %s (%s)", fi.FieldName, fi.FieldName))
  186. }
  187. }
  188. //普通索引
  189. if modelInfo.ModelIndexes != "" {
  190. modelIndexes := gstr.Split(modelInfo.ModelIndexes, ",")
  191. for _, ind := range modelIndexes {
  192. SqlKey.Append(fmt.Sprintf("INDEX IX_%s (%s)", ind, ind))
  193. }
  194. }
  195. //替换sql占位符
  196. sqlFieldTag := ""
  197. if SqlPrimaryKey != "" || SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0 {
  198. sqlFieldTag = ",\n"
  199. }
  200. primaryTag := ""
  201. if SqlPrimaryKey != "" && (SqlUniqueKey.Len() != 0 || SqlKey.Len() != 0) {
  202. primaryTag = ",\n"
  203. }
  204. uniqueTag := ""
  205. if SqlUniqueKey.Len() != 0 && SqlKey.Len() != 0 {
  206. uniqueTag = ",\n"
  207. }
  208. sql = gstr.ReplaceByArray(sql, []string{
  209. "%FIELDS_SQL%",
  210. SqlFields.Join(",") + sqlFieldTag,
  211. "%PRIMARY_KEY_SQL%",
  212. SqlPrimaryKey + primaryTag,
  213. "%UNIQUE_KEY_SQL%",
  214. SqlUniqueKey.Join(",") + uniqueTag,
  215. "%KEY_SQL%",
  216. SqlKey.Join(","),
  217. })
  218. _, err = g.DB().Exec(sql)
  219. if err != nil {
  220. g.Log().Error(err)
  221. return gerror.New("建表发生错误")
  222. }
  223. }
  224. return nil
  225. }
  226. //备份已存在的模型表
  227. func buildTableExists(dbPrefix, modelName string) error {
  228. //数据库名称
  229. dbName := g.Cfg().GetString("database.name")
  230. res, err := g.DB().GetAll("SHOW TABLE STATUS FROM " + dbName)
  231. if err != nil {
  232. g.Log().Error(err)
  233. return gerror.New("数据库信息获取失败")
  234. }
  235. tables := garray.New()
  236. for _, tbInfo := range res {
  237. tabName := gconv.String(tbInfo["Name"])
  238. if dbPrefix != "" && gstr.PosI(tabName, dbPrefix) == 0 {
  239. tables.Append(gstr.ToLower(gstr.SubStr(tabName, 0, len(dbPrefix))))
  240. }
  241. tables.Append(gstr.ToLower(tabName))
  242. }
  243. if tables.Contains(modelName) {
  244. //表格若已经存在则备份
  245. pathDir := g.Cfg().GetString("adminInfo.dataDir") + "/dataBak"
  246. pathDir, err := filepath.Abs(pathDir)
  247. if err != nil {
  248. g.Log().Error(err)
  249. return gerror.New("获取数据表备份路径失败")
  250. }
  251. //路径不存在则创建之
  252. err = os.MkdirAll(pathDir, os.ModeDir)
  253. if err != nil {
  254. g.Log().Error(err)
  255. return gerror.New("创建备份目录失败")
  256. }
  257. err = backupTable(pathDir, modelName, dbPrefix)
  258. if err != nil {
  259. return err
  260. }
  261. }
  262. return nil
  263. }
  264. //备份数据表操作
  265. func backupTable(pathDir, tableName, prefix string) error {
  266. switch g.Cfg().GetString("database.type") {
  267. case "mysql":
  268. rec, err := g.DB().GetOne(fmt.Sprintf("SHOW CREATE TABLE %s%s ", prefix, tableName))
  269. if err != nil {
  270. g.Log().Error(err)
  271. return gerror.New("获取备份表信息失败")
  272. }
  273. tableCreateSql := rec["Create Table"].String()
  274. res, err := g.DB().GetAll(fmt.Sprintf("SELECT * FROM %s%s", prefix, tableName))
  275. if err != nil {
  276. g.Log().Error(err)
  277. return gerror.New("获取备份表数据失败")
  278. }
  279. dataValues := garray.NewStrArray()
  280. keyValues := garray.NewStrArray()
  281. for _, v := range res {
  282. var str string
  283. vKey := garray.NewStrArray()
  284. vValues := garray.NewStrArray()
  285. for kk, vv := range v {
  286. str = strconv.Quote(gconv.String(vv))
  287. vValues.Append(str)
  288. vKey.Append(kk)
  289. }
  290. dataValues.Append("(" + vValues.Join(",") + ")")
  291. keyValues.Append("(" + vKey.Join(",") + ")")
  292. }
  293. insertDataSql := ""
  294. keyValues.Iterator(func(kk int, kv string) bool {
  295. vv, _ := dataValues.Get(kk)
  296. insertDataSql += fmt.Sprintf("INSERT INTO `%s%s` %s VALUES %s;\n", prefix, tableName, kv, vv)
  297. return true
  298. })
  299. tableCreateSql = tableCreateSql + ";\n" + insertDataSql + ";"
  300. //保存到文件中
  301. err = gfile.PutContents(fmt.Sprintf(pathDir+"/%s%s_%d.sql", prefix, tableName, gtime.Timestamp()), tableCreateSql)
  302. if err != nil {
  303. g.Log().Error(err)
  304. return gerror.New("创建备份文件失败")
  305. }
  306. }
  307. return nil
  308. }
  309. //复制模型
  310. func CopyModel(modelId int64) error {
  311. //获取要复制的模型信息
  312. modelInfo, err := GetByID(modelId)
  313. if err != nil {
  314. return err
  315. }
  316. req := &model_fields.SelectPageReq{ModelId: modelId}
  317. modelFields, err := model_fields.SelectListAll(req)
  318. if err != nil {
  319. return err
  320. }
  321. tx, err := g.DB().Begin()
  322. if err != nil {
  323. g.Log().Error(err)
  324. return gerror.New("开启事务失败")
  325. }
  326. modelInfo.ModelId = 0
  327. modelInfo.ModelName = modelInfo.ModelName + "_copy"
  328. res, err := tx.Model(model_info.Table).Insert(modelInfo)
  329. if err != nil {
  330. g.Log().Error(err)
  331. tx.Rollback()
  332. return gerror.New("复制模型信息失败")
  333. }
  334. insId, err := res.LastInsertId()
  335. if err != nil {
  336. g.Log().Error(err)
  337. tx.Rollback()
  338. return gerror.New("获取复制模型信Id失败")
  339. }
  340. newModelId := gconv.Uint(insId)
  341. for _, field := range modelFields {
  342. field.FieldId = 0
  343. field.ModelId = newModelId
  344. }
  345. if modelFields != nil {
  346. _, err = tx.BatchInsert(model_fields.Table, modelFields)
  347. if err != nil {
  348. g.Log().Error(err)
  349. tx.Rollback()
  350. return gerror.New("复制模型字段信息失败")
  351. }
  352. }
  353. tx.Commit()
  354. return nil
  355. }
  356. func GetModelsByCateIds(cateIds []int) (models []*model_info.Entity, err error) {
  357. return model_info.GetModelsByCateIds(cateIds)
  358. }