package handler import ( "encoding/json" "net/http" "time" "soul-api/internal/database" "github.com/gin-gonic/gin" ) // AdminTrackStats GET /api/admin/track/stats 管理端-按钮/标签点击统计(按模块+action聚合) // 查询参数:period=today|week|month|all(默认 today) func AdminTrackStats(c *gin.Context) { period := c.DefaultQuery("period", "today") db := database.DB() now := time.Now() var since time.Time switch period { case "today": since = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) case "week": since = now.AddDate(0, 0, -7) case "month": since = now.AddDate(0, -1, 0) default: since = time.Time{} } type trackRow struct { Action string `gorm:"column:action"` Target string `gorm:"column:target"` ExtraData []byte `gorm:"column:extra_data"` Count int64 `gorm:"column:count"` } query := db.Table("user_tracks"). Select("action, COALESCE(target, '') as target, extra_data, COUNT(*) as count"). Group("action, COALESCE(target, ''), extra_data"). Order("count DESC") if !since.IsZero() { query = query.Where("created_at >= ?", since) } var rows []trackRow query.Find(&rows) type statItem struct { Action string `json:"action"` Target string `json:"target"` Module string `json:"module"` Page string `json:"page"` Count int64 `json:"count"` } byModule := make(map[string][]statItem) total := int64(0) for _, r := range rows { module := "other" page := "" if len(r.ExtraData) > 0 { var extra map[string]interface{} if json.Unmarshal(r.ExtraData, &extra) == nil { if m, ok := extra["module"].(string); ok && m != "" { module = m } if p, ok := extra["page"].(string); ok && p != "" { page = p } } } item := statItem{ Action: r.Action, Target: r.Target, Module: module, Page: page, Count: r.Count, } byModule[module] = append(byModule[module], item) total += r.Count } c.JSON(http.StatusOK, gin.H{ "success": true, "period": period, "total": total, "byModule": byModule, }) }