feat: 数据概览简化 + 用户管理增加余额/提现列
- 数据概览:去掉代付统计独立卡片,总收入中以小标签显示代付金额 - 数据概览:移除余额统计区块(余额改在用户管理中展示) - 数据概览:恢复转化率卡片(唯一付费用户/总用户) - 用户管理:用户列表新增「余额/提现」列,显示钱包余额和已提现金额 - 后端:DBUsersList 增加 user_balances 查询,返回 walletBalance 字段 - 后端:User model 添加 WalletBalance 非数据库字段 - 包含之前的小程序埋点和管理后台点击统计面板 Made-with: Cursor
This commit is contained in:
93
soul-api/internal/handler/admin_track.go
Normal file
93
soul-api/internal/handler/admin_track.go
Normal file
@@ -0,0 +1,93 @@
|
||||
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,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user