backup.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package handler
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "time"
  6. "spider/internal/model"
  7. "spider/internal/store"
  8. "github.com/gin-gonic/gin"
  9. )
  10. // BackupHandler handles database backup/export.
  11. type BackupHandler struct {
  12. store *store.Store
  13. }
  14. // ExportJSON handles GET /backup/export — exports all core data as JSON.
  15. func (h *BackupHandler) ExportJSON(c *gin.Context) {
  16. db := h.store.DB
  17. var merchants []model.MerchantClean
  18. db.Find(&merchants)
  19. var merchantsRaw []model.MerchantRaw
  20. db.Find(&merchantsRaw)
  21. var keywords []model.Keyword
  22. db.Find(&keywords)
  23. var channels []model.Channel
  24. db.Find(&channels)
  25. var schedules []model.ScheduleJob
  26. db.Find(&schedules)
  27. var users []model.User
  28. db.Find(&users)
  29. // Clear passwords from export
  30. for i := range users {
  31. users[i].Password = ""
  32. }
  33. var notes []model.MerchantNote
  34. db.Find(&notes)
  35. var permissions []model.RolePermission
  36. db.Find(&permissions)
  37. backup := map[string]interface{}{
  38. "exported_at": time.Now().Format(time.RFC3339),
  39. "merchants_clean": merchants,
  40. "merchants_raw": merchantsRaw,
  41. "keywords": keywords,
  42. "channels": channels,
  43. "schedules": schedules,
  44. "users": users,
  45. "merchant_notes": notes,
  46. "role_permissions": permissions,
  47. }
  48. data, _ := json.MarshalIndent(backup, "", " ")
  49. filename := fmt.Sprintf("spider-backup-%s.json", time.Now().Format("2006-01-02"))
  50. c.Header("Content-Type", "application/json")
  51. c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
  52. c.Writer.Write(data)
  53. LogAudit(h.store, c, "export", "backup", "", nil)
  54. }
  55. // Stats handles GET /backup/stats — returns table row counts for backup estimation.
  56. func (h *BackupHandler) Stats(c *gin.Context) {
  57. db := h.store.DB
  58. tables := []struct {
  59. Name string
  60. Model interface{}
  61. }{
  62. {"merchants_clean", &model.MerchantClean{}},
  63. {"merchants_raw", &model.MerchantRaw{}},
  64. {"keywords", &model.Keyword{}},
  65. {"channels", &model.Channel{}},
  66. {"task_logs", &model.TaskLog{}},
  67. {"task_details", &model.TaskDetail{}},
  68. {"audit_logs", &model.AuditLog{}},
  69. {"merchant_notes", &model.MerchantNote{}},
  70. {"users", &model.User{}},
  71. {"schedules", &model.ScheduleJob{}},
  72. }
  73. result := make([]gin.H, 0, len(tables))
  74. for _, t := range tables {
  75. var count int64
  76. db.Model(t.Model).Count(&count)
  77. result = append(result, gin.H{"table": t.Name, "rows": count})
  78. }
  79. OK(c, result)
  80. }