fix: 添加分类名称唯一约束,防止重复名称

This commit is contained in:
2026-05-25 17:38:11 +08:00
parent 4b03e593bc
commit 2cb86d1b38
6 changed files with 249 additions and 47 deletions
-13
View File
@@ -5,7 +5,6 @@ import (
"net/http"
"strconv"
"sale/internal/crawler"
"sale/internal/models"
"sale/internal/schemas"
"sale/internal/utils"
@@ -164,15 +163,3 @@ func (h *ArticleHandler) TogglePin(c *gin.Context) {
utils.DB.First(&article, id)
c.JSON(http.StatusOK, gin.H{"data": article})
}
// CrawlRibenyan 采集 ribenyan.com 文章
func (h *ArticleHandler) CrawlRibenyan(c *gin.Context) {
crawler := crawler.NewRibenyanCrawler(utils.DB)
if err := crawler.CrawlArticles(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Crawl completed successfully"})
}
+14
View File
@@ -34,6 +34,12 @@ func (h *CategoryHandler) Create(c *gin.Context) {
return
}
var existing models.Category
if err := utils.DB.Where("name = ?", req.Name).First(&existing).Error; err == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "分类名称已存在"})
return
}
category := models.Category{
Name: req.Name,
Description: req.Description,
@@ -69,6 +75,14 @@ func (h *CategoryHandler) Update(c *gin.Context) {
return
}
if req.Name != nil && *req.Name != category.Name {
var existing models.Category
if err := utils.DB.Where("name = ? AND id != ?", *req.Name, id).First(&existing).Error; err == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "分类名称已存在"})
return
}
}
updates := make(map[string]interface{})
if req.Name != nil {
updates["name"] = *req.Name
+2 -25
View File
@@ -1,8 +1,6 @@
package routes
import (
"net/http"
"sale/internal/api/handlers"
"sale/internal/api/middlewares"
@@ -28,6 +26,8 @@ func SetupRoutes(r *gin.Engine) {
r.Use(middlewares.CORSMiddleware())
r.Static("/uploads", "./uploads")
api := r.Group("/api")
{
api.GET("/installed", authHandler.CheckInstalled)
@@ -46,8 +46,6 @@ func SetupRoutes(r *gin.Engine) {
{
articles.GET("", articleHandler.List)
articles.GET("/:id", articleHandler.GetByID)
// 采集 API(管理员权限)
articles.POST("/crawl-ribenyan", articleHandler.CrawlRibenyan)
}
api.GET("/banners", bannerHandler.List)
@@ -217,25 +215,4 @@ func SetupRoutes(r *gin.Engine) {
}
}
}
// Serve uploads
r.Static("/uploads", "./uploads")
// Serve frontend static assets (CSS, JS, images, etc.)
r.StaticFS("/assets", http.Dir("./static/assets"))
// SPA fallback - serve index.html for all other routes (Vue Router History Mode)
// This must be the last route to catch all unmatched paths
r.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
// For root and SPA routes, serve index.html
// API requests will return 404 if not found
if path == "/" || path == "/favicon.ico" || path == "/icons.svg" || path == "/favicon.svg" ||
len(path) > 4 && path[:4] != "/api/" {
c.File("/app/static/index.html")
} else {
// API routes - let them return 404 if not found
c.AbortWithStatus(404)
}
})
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
type Category struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:100;not null" json:"name"`
Name string `gorm:"size:100;not null;uniqueIndex" json:"name"`
Description string `json:"description"`
ParentID *uint `json:"parent_id"`
MinAmount *float64 `json:"min_amount"`