96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package handler
|
||
|
||
import (
|
||
"net/http"
|
||
"strings"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
|
||
"infogenie-backend/internal/database"
|
||
"infogenie-backend/internal/model"
|
||
)
|
||
|
||
var featureCardSections = map[string]struct{}{
|
||
"60sapi": {},
|
||
"smallgame": {},
|
||
"toolbox": {},
|
||
"aimodel": {},
|
||
}
|
||
|
||
func normalizeFeatureSection(s string) (string, bool) {
|
||
key := strings.ToLower(strings.TrimSpace(s))
|
||
if key == "" {
|
||
return "", false
|
||
}
|
||
if _, ok := featureCardSections[key]; !ok {
|
||
return "", false
|
||
}
|
||
return key, true
|
||
}
|
||
|
||
func sanitizeFeatureItemID(raw string) (string, bool) {
|
||
id := strings.TrimSpace(raw)
|
||
if id == "" || len(id) > 128 {
|
||
return "", false
|
||
}
|
||
return id, true
|
||
}
|
||
|
||
// GetFeatureCardClicks 公开:按板块返回各功能 id 的点击次数(未出现过的 id 前端视为 0)
|
||
func (h *SiteConfigHandler) GetFeatureCardClicks(c *gin.Context) {
|
||
section, ok := normalizeFeatureSection(c.Query("section"))
|
||
if !ok {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_section"})
|
||
return
|
||
}
|
||
var rows []model.SiteFeatureCardClick
|
||
if err := database.DB.Where("section = ?", section).Find(&rows).Error; err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
|
||
return
|
||
}
|
||
counts := make(map[string]uint64, len(rows))
|
||
for _, r := range rows {
|
||
counts[r.ItemID] = r.ClickCount
|
||
}
|
||
c.JSON(http.StatusOK, gin.H{"section": section, "counts": counts})
|
||
}
|
||
|
||
type postFeatureCardClickBody struct {
|
||
Section string `json:"section"`
|
||
ItemID string `json:"item_id"`
|
||
}
|
||
|
||
// PostFeatureCardClickIncrement 公开:记录一次卡片点击并返回最新计数
|
||
func (h *SiteConfigHandler) PostFeatureCardClickIncrement(c *gin.Context) {
|
||
var body postFeatureCardClickBody
|
||
if err := c.ShouldBindJSON(&body); err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_json"})
|
||
return
|
||
}
|
||
section, ok := normalizeFeatureSection(body.Section)
|
||
if !ok {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_section"})
|
||
return
|
||
}
|
||
itemID, ok := sanitizeFeatureItemID(body.ItemID)
|
||
if !ok {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_item_id"})
|
||
return
|
||
}
|
||
|
||
const q = `INSERT INTO site_feature_card_clicks (section, item_id, click_count, updated_at)
|
||
VALUES (?, ?, 1, NOW())
|
||
ON DUPLICATE KEY UPDATE click_count = click_count + 1, updated_at = NOW()`
|
||
if err := database.DB.Exec(q, section, itemID).Error; err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
|
||
return
|
||
}
|
||
|
||
var row model.SiteFeatureCardClick
|
||
if err := database.DB.Where("section = ? AND item_id = ?", section, itemID).First(&row).Error; err != nil {
|
||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db_error"})
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, gin.H{"section": section, "item_id": itemID, "count": row.ClickCount})
|
||
}
|