基本功能复刻完成
This commit is contained in:
169
internal/handler/admin_stat_api.go
Normal file
169
internal/handler/admin_stat_api.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
"xboard-go/internal/database"
|
||||
"xboard-go/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AdminGetTrafficRank returns traffic ranking for nodes or users.
|
||||
func AdminGetTrafficRank(c *gin.Context) {
|
||||
rankType := c.Query("type") // node or user
|
||||
startTimeStr := c.Query("start_time")
|
||||
endTimeStr := c.Query("end_time")
|
||||
|
||||
startTime, _ := strconv.ParseInt(startTimeStr, 10, 64)
|
||||
endTime, _ := strconv.ParseInt(endTimeStr, 10, 64)
|
||||
|
||||
if startTime == 0 {
|
||||
startTime = time.Now().AddDate(0, 0, -7).Unix()
|
||||
}
|
||||
if endTime == 0 {
|
||||
endTime = time.Now().Unix()
|
||||
}
|
||||
|
||||
var result []gin.H
|
||||
if rankType == "user" {
|
||||
type userRank struct {
|
||||
ID int `json:"id"`
|
||||
Value int64 `json:"value"`
|
||||
Email string `json:"name"`
|
||||
}
|
||||
var ranks []userRank
|
||||
database.DB.Model(&model.StatUser{}).
|
||||
Select("user_id as id, SUM(u + d) as value").
|
||||
Where("record_at >= ? AND record_at <= ?", startTime, endTime).
|
||||
Group("user_id").
|
||||
Order("value DESC").
|
||||
Limit(10).
|
||||
Scan(&ranks)
|
||||
|
||||
var userIDs []int
|
||||
for _, r := range ranks {
|
||||
userIDs = append(userIDs, r.ID)
|
||||
}
|
||||
userEmails := loadUserEmailMap(userIDs)
|
||||
for _, r := range ranks {
|
||||
result = append(result, gin.H{
|
||||
"id": fmt.Sprintf("%d", r.ID),
|
||||
"name": userEmails[r.ID],
|
||||
"value": r.Value,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Default to node
|
||||
type nodeRank struct {
|
||||
ID int `json:"id"`
|
||||
Value int64 `json:"value"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
var ranks []nodeRank
|
||||
database.DB.Model(&model.StatServer{}).
|
||||
Select("server_id as id, SUM(u + d) as value").
|
||||
Where("record_at >= ? AND record_at <= ?", startTime, endTime).
|
||||
Group("server_id").
|
||||
Order("value DESC").
|
||||
Limit(10).
|
||||
Scan(&ranks)
|
||||
|
||||
var nodeIDs []int
|
||||
for _, r := range ranks {
|
||||
nodeIDs = append(nodeIDs, r.ID)
|
||||
}
|
||||
nodeNames := loadNodeNameMap(nodeIDs)
|
||||
for _, r := range ranks {
|
||||
result = append(result, gin.H{
|
||||
"id": fmt.Sprintf("%d", r.ID),
|
||||
"name": nodeNames[r.ID],
|
||||
"value": r.Value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Success(c, result)
|
||||
}
|
||||
|
||||
// AdminGetOrderStats returns order-related statistics for charts.
|
||||
func AdminGetOrderStats(c *gin.Context) {
|
||||
startDateStr := c.Query("start_date")
|
||||
endDateStr := c.Query("end_date")
|
||||
statType := c.Query("type") // paid_total, paid_count, etc.
|
||||
|
||||
var startDate int64
|
||||
var endDate int64
|
||||
|
||||
if startDateStr != "" {
|
||||
t, _ := time.Parse("2006-01-02", startDateStr)
|
||||
startDate = t.Unix()
|
||||
} else {
|
||||
startDate = time.Now().AddDate(0, 0, -30).Truncate(24 * time.Hour).Unix()
|
||||
}
|
||||
|
||||
if endDateStr != "" {
|
||||
t, _ := time.Parse("2006-01-02", endDateStr)
|
||||
endDate = t.Unix() + 86399
|
||||
} else {
|
||||
endDate = time.Now().Unix()
|
||||
}
|
||||
|
||||
var stats []model.Stat
|
||||
database.DB.Where("record_at >= ? AND record_at <= ? AND record_type = ?", startDate, endDate, "d").
|
||||
Order("record_at ASC").
|
||||
Find(&stats)
|
||||
|
||||
var list []gin.H
|
||||
for _, s := range stats {
|
||||
dateStr := time.Unix(s.RecordAt, 0).Format("2006-01-02")
|
||||
item := gin.H{
|
||||
"date": dateStr,
|
||||
}
|
||||
if statType != "" {
|
||||
item["value"] = getStatFieldValue(s, statType)
|
||||
} else {
|
||||
item["paid_total"] = s.PaidTotal
|
||||
item["paid_count"] = s.PaidCount
|
||||
item["commission_total"] = s.CommissionTotal
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
Success(c, gin.H{
|
||||
"list": list,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
func loadNodeNameMap(ids []int) map[int]string {
|
||||
result := make(map[int]string)
|
||||
if len(ids) == 0 {
|
||||
return result
|
||||
}
|
||||
var servers []model.Server
|
||||
database.DB.Select("id", "name").Where("id IN ?", ids).Find(&servers)
|
||||
for _, s := range servers {
|
||||
result[s.ID] = s.Name
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getStatFieldValue(s model.Stat, field string) any {
|
||||
switch field {
|
||||
case "paid_total":
|
||||
return s.PaidTotal
|
||||
case "paid_count":
|
||||
return s.PaidCount
|
||||
case "commission_total":
|
||||
return s.CommissionTotal
|
||||
case "commission_count":
|
||||
return s.CommissionCount
|
||||
case "register_count":
|
||||
return s.RegisterCount
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user