keyword.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package handler
  2. import (
  3. "net/http"
  4. "strconv"
  5. "spider/internal/model"
  6. "github.com/gin-gonic/gin"
  7. "gorm.io/gorm"
  8. )
  9. // KeywordHandler handles managed keyword CRUD.
  10. type KeywordHandler struct {
  11. db *gorm.DB
  12. }
  13. // List returns keywords with optional filters and pagination.
  14. // GET /keywords?page=1&page_size=20&category=&status=
  15. func (h *KeywordHandler) List(c *gin.Context) {
  16. page, pageSize, offset := parsePage(c)
  17. query := h.db.Model(&model.ManagedKeyword{})
  18. if category := c.Query("category"); category != "" {
  19. query = query.Where("category = ?", category)
  20. }
  21. if status := c.Query("status"); status != "" {
  22. query = query.Where("status = ?", status)
  23. }
  24. var total int64
  25. if err := query.Count(&total).Error; err != nil {
  26. Fail(c, 500, err.Error())
  27. return
  28. }
  29. var keywords []model.ManagedKeyword
  30. if err := query.Order("id DESC").Limit(pageSize).Offset(offset).Find(&keywords).Error; err != nil {
  31. Fail(c, 500, err.Error())
  32. return
  33. }
  34. PageOK(c, keywords, total, page, pageSize)
  35. }
  36. // Create creates one or more keywords in batch.
  37. // POST /keywords body: {keywords:["k1","k2"], category:"机场"}
  38. func (h *KeywordHandler) Create(c *gin.Context) {
  39. var body struct {
  40. Keywords []string `json:"keywords" binding:"required,min=1"`
  41. Category string `json:"category"`
  42. }
  43. if err := c.ShouldBindJSON(&body); err != nil {
  44. Fail(c, http.StatusBadRequest, err.Error())
  45. return
  46. }
  47. var created []model.ManagedKeyword
  48. for _, kw := range body.Keywords {
  49. if kw == "" {
  50. continue
  51. }
  52. k := model.ManagedKeyword{
  53. Keyword: kw,
  54. Category: body.Category,
  55. Status: "active",
  56. }
  57. // Use FirstOrCreate to avoid duplicate errors.
  58. if err := h.db.Where(model.ManagedKeyword{Keyword: kw}).FirstOrCreate(&k).Error; err != nil {
  59. Fail(c, 500, err.Error())
  60. return
  61. }
  62. created = append(created, k)
  63. }
  64. OK(c, created)
  65. }
  66. // Update modifies a keyword.
  67. // PUT /keywords/:id
  68. func (h *KeywordHandler) Update(c *gin.Context) {
  69. id, err := strconv.ParseUint(c.Param("id"), 10, 64)
  70. if err != nil {
  71. Fail(c, http.StatusBadRequest, "invalid id")
  72. return
  73. }
  74. var body struct {
  75. Keyword string `json:"keyword"`
  76. Category string `json:"category"`
  77. Status string `json:"status"`
  78. }
  79. if err := c.ShouldBindJSON(&body); err != nil {
  80. Fail(c, http.StatusBadRequest, err.Error())
  81. return
  82. }
  83. var kw model.ManagedKeyword
  84. if err := h.db.First(&kw, id).Error; err != nil {
  85. Fail(c, 404, "keyword not found")
  86. return
  87. }
  88. updates := map[string]interface{}{}
  89. if body.Keyword != "" {
  90. updates["keyword"] = body.Keyword
  91. }
  92. if body.Category != "" {
  93. updates["category"] = body.Category
  94. }
  95. if body.Status != "" {
  96. updates["status"] = body.Status
  97. }
  98. if err := h.db.Model(&kw).Updates(updates).Error; err != nil {
  99. Fail(c, 500, err.Error())
  100. return
  101. }
  102. h.db.First(&kw, id)
  103. OK(c, kw)
  104. }
  105. // Delete removes a keyword by ID.
  106. // DELETE /keywords/:id
  107. func (h *KeywordHandler) Delete(c *gin.Context) {
  108. id, err := strconv.ParseUint(c.Param("id"), 10, 64)
  109. if err != nil {
  110. Fail(c, http.StatusBadRequest, "invalid id")
  111. return
  112. }
  113. if err := h.db.Delete(&model.ManagedKeyword{}, id).Error; err != nil {
  114. Fail(c, 500, err.Error())
  115. return
  116. }
  117. OK(c, nil)
  118. }