sys_export_template.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package system
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/xuri/excelize/v2"
  7. "gorm.io/gorm"
  8. "mime/multipart"
  9. "net/url"
  10. "server/global"
  11. "server/model/common/request"
  12. "server/model/system"
  13. systemReq "server/model/system/request"
  14. "server/utils"
  15. "strconv"
  16. "strings"
  17. )
  18. type SysExportTemplateService struct {
  19. }
  20. // CreateSysExportTemplate 创建导出模板记录
  21. // Author [piexlmax](https://github.com/piexlmax)
  22. func (sysExportTemplateService *SysExportTemplateService) CreateSysExportTemplate(sysExportTemplate *system.SysExportTemplate) (err error) {
  23. err = global.GVA_DB.Create(sysExportTemplate).Error
  24. return err
  25. }
  26. // DeleteSysExportTemplate 删除导出模板记录
  27. // Author [piexlmax](https://github.com/piexlmax)
  28. func (sysExportTemplateService *SysExportTemplateService) DeleteSysExportTemplate(sysExportTemplate system.SysExportTemplate) (err error) {
  29. err = global.GVA_DB.Delete(&sysExportTemplate).Error
  30. return err
  31. }
  32. // DeleteSysExportTemplateByIds 批量删除导出模板记录
  33. // Author [piexlmax](https://github.com/piexlmax)
  34. func (sysExportTemplateService *SysExportTemplateService) DeleteSysExportTemplateByIds(ids request.IdsReq) (err error) {
  35. err = global.GVA_DB.Delete(&[]system.SysExportTemplate{}, "id in ?", ids.Ids).Error
  36. return err
  37. }
  38. // UpdateSysExportTemplate 更新导出模板记录
  39. // Author [piexlmax](https://github.com/piexlmax)
  40. func (sysExportTemplateService *SysExportTemplateService) UpdateSysExportTemplate(sysExportTemplate system.SysExportTemplate) (err error) {
  41. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  42. conditions := sysExportTemplate.Conditions
  43. e := tx.Delete(&[]system.Condition{}, "template_id = ?", sysExportTemplate.TemplateID).Error
  44. if e != nil {
  45. return e
  46. }
  47. sysExportTemplate.Conditions = nil
  48. joins := sysExportTemplate.JoinTemplate
  49. e = tx.Delete(&[]system.JoinTemplate{}, "template_id = ?", sysExportTemplate.TemplateID).Error
  50. if e != nil {
  51. return e
  52. }
  53. sysExportTemplate.JoinTemplate = nil
  54. e = tx.Updates(&sysExportTemplate).Error
  55. if e != nil {
  56. return e
  57. }
  58. if len(conditions) > 0 {
  59. for i := range conditions {
  60. conditions[i].ID = 0
  61. }
  62. e = tx.Create(&conditions).Error
  63. }
  64. if len(joins) > 0 {
  65. for i := range joins {
  66. joins[i].ID = 0
  67. }
  68. e = tx.Create(&joins).Error
  69. }
  70. return e
  71. })
  72. }
  73. // GetSysExportTemplate 根据id获取导出模板记录
  74. // Author [piexlmax](https://github.com/piexlmax)
  75. func (sysExportTemplateService *SysExportTemplateService) GetSysExportTemplate(id uint) (sysExportTemplate system.SysExportTemplate, err error) {
  76. err = global.GVA_DB.Where("id = ?", id).Preload("JoinTemplate").Preload("Conditions").First(&sysExportTemplate).Error
  77. return
  78. }
  79. // GetSysExportTemplateInfoList 分页获取导出模板记录
  80. // Author [piexlmax](https://github.com/piexlmax)
  81. func (sysExportTemplateService *SysExportTemplateService) GetSysExportTemplateInfoList(info systemReq.SysExportTemplateSearch) (list []system.SysExportTemplate, total int64, err error) {
  82. limit := info.PageSize
  83. offset := info.PageSize * (info.Page - 1)
  84. // 创建db
  85. db := global.GVA_DB.Model(&system.SysExportTemplate{})
  86. var sysExportTemplates []system.SysExportTemplate
  87. // 如果有条件搜索 下方会自动创建搜索语句
  88. if info.StartCreatedAt != nil && info.EndCreatedAt != nil {
  89. db = db.Where("created_at BETWEEN ? AND ?", info.StartCreatedAt, info.EndCreatedAt)
  90. }
  91. if info.Name != "" {
  92. db = db.Where("name LIKE ?", "%"+info.Name+"%")
  93. }
  94. if info.TableName != "" {
  95. db = db.Where("table_name = ?", info.TableName)
  96. }
  97. if info.TemplateID != "" {
  98. db = db.Where("template_id = ?", info.TemplateID)
  99. }
  100. err = db.Count(&total).Error
  101. if err != nil {
  102. return
  103. }
  104. if limit != 0 {
  105. db = db.Limit(limit).Offset(offset)
  106. }
  107. err = db.Find(&sysExportTemplates).Error
  108. return sysExportTemplates, total, err
  109. }
  110. // ExportExcel 导出Excel
  111. // Author [piexlmax](https://github.com/piexlmax)
  112. func (sysExportTemplateService *SysExportTemplateService) ExportExcel(templateID string, values url.Values) (dept *bytes.Buffer, name string, err error) {
  113. var template system.SysExportTemplate
  114. err = global.GVA_DB.Preload("Conditions").Preload("JoinTemplate").First(&template, "template_id = ?", templateID).Error
  115. if err != nil {
  116. return nil, "", err
  117. }
  118. f := excelize.NewFile()
  119. defer func() {
  120. if err := f.Close(); err != nil {
  121. fmt.Println(err)
  122. }
  123. }()
  124. // Create a new sheet.
  125. index, err := f.NewSheet("Sheet1")
  126. if err != nil {
  127. fmt.Println(err)
  128. return
  129. }
  130. var templateInfoMap = make(map[string]string)
  131. columns, err := utils.GetJSONKeys(template.TemplateInfo)
  132. if err != nil {
  133. return nil, "", err
  134. }
  135. err = json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap)
  136. if err != nil {
  137. return nil, "", err
  138. }
  139. var tableTitle []string
  140. for _, key := range columns {
  141. tableTitle = append(tableTitle, templateInfoMap[key])
  142. }
  143. selects := strings.Join(columns, ", ")
  144. var tableMap []map[string]interface{}
  145. db := global.GVA_DB
  146. if template.DBName != "" {
  147. db = global.MustGetGlobalDBByDBName(template.DBName)
  148. }
  149. if len(template.JoinTemplate) > 0 {
  150. for _, join := range template.JoinTemplate {
  151. db = db.Joins(join.JOINS + "`" + join.Table + "`" + " ON " + join.ON)
  152. }
  153. }
  154. db = db.Select(selects).Table(template.TableName)
  155. if len(template.Conditions) > 0 {
  156. for _, condition := range template.Conditions {
  157. sql := fmt.Sprintf("%s %s ?", condition.Column, condition.Operator)
  158. value := values.Get(condition.From)
  159. if value != "" {
  160. if condition.Operator == "LIKE" {
  161. value = "%" + value + "%"
  162. }
  163. db = db.Where(sql, value)
  164. }
  165. }
  166. }
  167. // 通过参数传入limit
  168. limit := values.Get("limit")
  169. if limit != "" {
  170. l, e := strconv.Atoi(limit)
  171. if e == nil {
  172. db = db.Limit(l)
  173. }
  174. }
  175. // 模板的默认limit
  176. if limit == "" && template.Limit != 0 {
  177. db = db.Limit(template.Limit)
  178. }
  179. // 通过参数传入offset
  180. offset := values.Get("offset")
  181. if offset != "" {
  182. o, e := strconv.Atoi(offset)
  183. if e == nil {
  184. db = db.Offset(o)
  185. }
  186. }
  187. // 通过参数传入order
  188. order := values.Get("order")
  189. if order != "" {
  190. db = db.Order(order)
  191. }
  192. // 模板的默认order
  193. if order == "" && template.Order != "" {
  194. db = db.Order(template.Order)
  195. }
  196. err = db.Debug().Find(&tableMap).Error
  197. if err != nil {
  198. return nil, "", err
  199. }
  200. var rows [][]string
  201. rows = append(rows, tableTitle)
  202. for _, table := range tableMap {
  203. var row []string
  204. for _, column := range columns {
  205. if len(template.JoinTemplate) > 0 {
  206. columnArr := strings.Split(column, ".")
  207. if len(columnArr) > 1 {
  208. column = strings.Split(column, ".")[1]
  209. }
  210. }
  211. row = append(row, fmt.Sprintf("%v", table[column]))
  212. }
  213. rows = append(rows, row)
  214. }
  215. for i, row := range rows {
  216. for j, colCell := range row {
  217. err := f.SetCellValue("Sheet1", fmt.Sprintf("%s%d", getColumnName(j+1), i+1), colCell)
  218. if err != nil {
  219. return nil, "", err
  220. }
  221. }
  222. }
  223. f.SetActiveSheet(index)
  224. dept, err = f.WriteToBuffer()
  225. if err != nil {
  226. return nil, "", err
  227. }
  228. return dept, template.Name, nil
  229. }
  230. // ExportTemplate 导出Excel模板
  231. // Author [piexlmax](https://github.com/piexlmax)
  232. func (sysExportTemplateService *SysExportTemplateService) ExportTemplate(templateID string) (dept *bytes.Buffer, name string, err error) {
  233. var template system.SysExportTemplate
  234. err = global.GVA_DB.First(&template, "template_id = ?", templateID).Error
  235. if err != nil {
  236. return nil, "", err
  237. }
  238. f := excelize.NewFile()
  239. defer func() {
  240. if err := f.Close(); err != nil {
  241. fmt.Println(err)
  242. }
  243. }()
  244. // Create a new sheet.
  245. index, err := f.NewSheet("Sheet1")
  246. if err != nil {
  247. fmt.Println(err)
  248. return
  249. }
  250. var templateInfoMap = make(map[string]string)
  251. err = json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap)
  252. if err != nil {
  253. return nil, "", err
  254. }
  255. var tableTitle []string
  256. for key := range templateInfoMap {
  257. tableTitle = append(tableTitle, templateInfoMap[key])
  258. }
  259. for i := range tableTitle {
  260. fErr := f.SetCellValue("Sheet1", fmt.Sprintf("%s%d", getColumnName(i+1), 1), tableTitle[i])
  261. if fErr != nil {
  262. return nil, "", fErr
  263. }
  264. }
  265. f.SetActiveSheet(index)
  266. dept, err = f.WriteToBuffer()
  267. if err != nil {
  268. return nil, "", err
  269. }
  270. return dept, template.Name, nil
  271. }
  272. // ImportExcel 导入Excel
  273. // Author [piexlmax](https://github.com/piexlmax)
  274. func (sysExportTemplateService *SysExportTemplateService) ImportExcel(templateID string, dept *multipart.FileHeader) (err error) {
  275. var template system.SysExportTemplate
  276. err = global.GVA_DB.First(&template, "template_id = ?", templateID).Error
  277. if err != nil {
  278. return err
  279. }
  280. src, err := dept.Open()
  281. if err != nil {
  282. return err
  283. }
  284. defer src.Close()
  285. f, err := excelize.OpenReader(src)
  286. if err != nil {
  287. return err
  288. }
  289. rows, err := f.GetRows("Sheet1")
  290. if err != nil {
  291. return err
  292. }
  293. var templateInfoMap = make(map[string]string)
  294. err = json.Unmarshal([]byte(template.TemplateInfo), &templateInfoMap)
  295. if err != nil {
  296. return err
  297. }
  298. var titleKeyMap = make(map[string]string)
  299. for key, title := range templateInfoMap {
  300. titleKeyMap[title] = key
  301. }
  302. db := global.GVA_DB
  303. if template.DBName != "" {
  304. db = global.MustGetGlobalDBByDBName(template.DBName)
  305. }
  306. return db.Transaction(func(tx *gorm.DB) error {
  307. excelTitle := rows[0]
  308. values := rows[1:]
  309. items := make([]map[string]interface{}, 0, len(values))
  310. for _, row := range values {
  311. var item = make(map[string]interface{})
  312. for ii, value := range row {
  313. key := titleKeyMap[excelTitle[ii]]
  314. item[key] = value
  315. }
  316. // 此处需要等待gorm修复HasColumn中的painc问题
  317. //needCreated := tx.Migrator().HasColumn(template.TableName, "created_at")
  318. //needUpdated := tx.Migrator().HasColumn(template.TableName, "updated_at")
  319. //
  320. //if item["created_at"] == nil && needCreated {
  321. // item["created_at"] = time.Now()
  322. //}
  323. //if item["updated_at"] == nil && needUpdated {
  324. // item["updated_at"] = time.Now()
  325. //}
  326. items = append(items, item)
  327. }
  328. cErr := tx.Table(template.TableName).CreateInBatches(&items, 1000).Error
  329. return cErr
  330. })
  331. }
  332. func getColumnName(n int) string {
  333. columnName := ""
  334. for n > 0 {
  335. n--
  336. columnName = string(rune('A'+n%26)) + columnName
  337. n /= 26
  338. }
  339. return columnName
  340. }