Files
soul-yongping/soul-api/internal/handler/admin_distribution.go

128 lines
5.9 KiB
Go
Raw Normal View History

package handler
import (
"fmt"
"net/http"
"time"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// AdminDistributionOverview GET /api/admin/distribution/overview全部使用 GORM无 Raw SQL
func AdminDistributionOverview(c *gin.Context) {
now := time.Now()
todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
todayEnd := todayStart.Add(24 * time.Hour)
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
db := database.DB()
overview := gin.H{
"todayClicks": 0, "todayBindings": 0, "todayConversions": 0, "todayEarnings": 0,
"monthClicks": 0, "monthBindings": 0, "monthConversions": 0, "monthEarnings": 0,
"totalClicks": 0, "totalBindings": 0, "totalConversions": 0, "totalEarnings": 0,
"expiringBindings": 0, "pendingWithdrawals": 0, "pendingWithdrawAmount": 0,
"conversionRate": "0.00", "totalDistributors": 0, "activeDistributors": 0,
}
// 订单:仅用 Where + Count / Select(Sum) 参数化
var totalOrders int64
db.Model(&model.Order{}).Where("status = ?", "paid").Count(&totalOrders)
var totalAmount float64
db.Model(&model.Order{}).Where("status = ?", "paid").Select("COALESCE(SUM(amount),0)").Scan(&totalAmount)
var todayOrders int64
db.Model(&model.Order{}).Where("status = ? AND created_at >= ? AND created_at < ?", "paid", todayStart, todayEnd).Count(&todayOrders)
var todayAmount float64
db.Model(&model.Order{}).Where("status = ? AND created_at >= ? AND created_at < ?", "paid", todayStart, todayEnd).Select("COALESCE(SUM(amount),0)").Scan(&todayAmount)
var monthOrders int64
db.Model(&model.Order{}).Where("status = ? AND created_at >= ?", "paid", monthStart).Count(&monthOrders)
var monthAmount float64
db.Model(&model.Order{}).Where("status = ? AND created_at >= ?", "paid", monthStart).Select("COALESCE(SUM(amount),0)").Scan(&monthAmount)
overview["totalEarnings"] = totalAmount
overview["todayEarnings"] = todayAmount
overview["monthEarnings"] = monthAmount
// 绑定:全部 GORM Where
var totalBindings int64
db.Model(&model.ReferralBinding{}).Count(&totalBindings)
var converted int64
db.Model(&model.ReferralBinding{}).Where("status = ?", "converted").Count(&converted)
var todayBindings int64
db.Model(&model.ReferralBinding{}).Where("binding_date >= ? AND binding_date < ?", todayStart, todayEnd).Count(&todayBindings)
var todayConv int64
db.Model(&model.ReferralBinding{}).Where("status = ? AND binding_date >= ? AND binding_date < ?", "converted", todayStart, todayEnd).Count(&todayConv)
var monthBindings int64
db.Model(&model.ReferralBinding{}).Where("binding_date >= ?", monthStart).Count(&monthBindings)
var monthConv int64
db.Model(&model.ReferralBinding{}).Where("status = ? AND binding_date >= ?", "converted", monthStart).Count(&monthConv)
expiringEnd := now.Add(7 * 24 * time.Hour)
var expiring int64
db.Model(&model.ReferralBinding{}).Where("status = ? AND expiry_date > ? AND expiry_date <= ?", "active", now, expiringEnd).Count(&expiring)
overview["totalBindings"] = totalBindings
overview["totalConversions"] = converted
overview["todayBindings"] = todayBindings
overview["todayConversions"] = todayConv
overview["monthBindings"] = monthBindings
overview["monthConversions"] = monthConv
overview["expiringBindings"] = expiring
// 访问数(点击量):总 / 今日 / 本月
var visitTotal int64
db.Model(&model.ReferralVisit{}).Count(&visitTotal)
var todayClicks int64
db.Model(&model.ReferralVisit{}).Where("created_at >= ? AND created_at < ?", todayStart, todayEnd).Count(&todayClicks)
var monthClicks int64
db.Model(&model.ReferralVisit{}).Where("created_at >= ?", monthStart).Count(&monthClicks)
overview["totalClicks"] = visitTotal
overview["todayClicks"] = todayClicks
overview["monthClicks"] = monthClicks
if visitTotal > 0 && converted > 0 {
overview["conversionRate"] = formatPercent(float64(converted)/float64(visitTotal)*100)
}
// 今日独立访客数(按 visitor_id 或 visitor_openid 去重,空则用 id 占位)
var todayUniqueVisitors int64
db.Raw("SELECT COUNT(DISTINCT COALESCE(visitor_id, visitor_openid, CONCAT('_', id))) FROM referral_visits WHERE created_at >= ? AND created_at < ?", todayStart, todayEnd).Scan(&todayUniqueVisitors)
overview["todayUniqueVisitors"] = todayUniqueVisitors
// 今日总文章点击率:今日总点击 / 今日独立访客(人均点击),无访客时为 0
todayClickRate := 0.0
if todayUniqueVisitors > 0 && todayClicks > 0 {
todayClickRate = float64(todayClicks) / float64(todayUniqueVisitors)
}
overview["todayClickRate"] = todayClickRate
// 每篇文章今日点击量(按 page 分组)
var pageClicks []struct {
Page string `gorm:"column:page"`
Clicks int64 `gorm:"column:clicks"`
}
db.Raw("SELECT COALESCE(page, '') AS page, COUNT(*) AS clicks FROM referral_visits WHERE created_at >= ? AND created_at < ? GROUP BY COALESCE(page, '')", todayStart, todayEnd).Scan(&pageClicks)
byPage := make([]gin.H, 0, len(pageClicks))
for _, r := range pageClicks {
byPage = append(byPage, gin.H{"page": r.Page, "clicks": r.Clicks})
}
overview["todayClicksByPage"] = byPage
// 提现待处理
var pendCount int64
db.Model(&model.Withdrawal{}).Where("status = ?", "pending").Count(&pendCount)
var pendSum float64
db.Model(&model.Withdrawal{}).Where("status = ?", "pending").Select("COALESCE(SUM(amount),0)").Scan(&pendSum)
overview["pendingWithdrawals"] = pendCount
overview["pendingWithdrawAmount"] = pendSum
// 分销商
var distTotal int64
db.Model(&model.User{}).Where("referral_code IS NOT NULL AND referral_code != ?", "").Count(&distTotal)
var distActive int64
db.Model(&model.User{}).Where("referral_code IS NOT NULL AND referral_code != ? AND earnings > ?", "", 0).Count(&distActive)
overview["totalDistributors"] = distTotal
overview["activeDistributors"] = distActive
c.JSON(http.StatusOK, gin.H{"success": true, "overview": overview})
}
func formatPercent(v float64) string {
return fmt.Sprintf("%.2f", v) + "%"
}