Files
soul-yongping/soul-api/internal/handler/admin_dashboard.go
2026-03-07 22:58:43 +08:00

125 lines
3.5 KiB
Go

package handler
import (
"net/http"
"time"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// AdminDashboardOverview GET /api/admin/dashboard/overview
// 数据概览:总用户、订单数(仅已付款)、转化率(有付款行为的用户数/总用户数)、总收入;最近订单与新注册用户均为实时查询。
func AdminDashboardOverview(c *gin.Context) {
db := database.DB()
var totalUsers int64
db.Model(&model.User{}).Count(&totalUsers)
var paidOrderCount int64
db.Model(&model.Order{}).Where("status IN ?", []string{"paid", "completed", "success"}).Count(&paidOrderCount)
var paidUserCount int64
db.Model(&model.Order{}).Where("status IN ?", []string{"paid", "completed", "success"}).Distinct("user_id").Count(&paidUserCount)
var totalRevenue float64
db.Model(&model.Order{}).Where("status IN ?", []string{"paid", "completed", "success"}).Select("COALESCE(SUM(amount),0)").Scan(&totalRevenue)
conversionRate := 0.0
if totalUsers > 0 && paidUserCount > 0 {
conversionRate = float64(paidUserCount) / float64(totalUsers) * 100
}
var recentOrders []model.Order
db.Where("status IN ?", []string{"paid", "completed", "success"}).Order("created_at DESC").Limit(5).Find(&recentOrders)
userIDs := make(map[string]bool)
for _, o := range recentOrders {
userIDs[o.UserID] = true
if o.ReferrerID != nil && *o.ReferrerID != "" {
userIDs[*o.ReferrerID] = true
}
}
ids := make([]string, 0, len(userIDs))
for id := range userIDs {
ids = append(ids, id)
}
var orderUsers []model.User
if len(ids) > 0 {
db.Where("id IN ?", ids).Find(&orderUsers)
}
userMap := make(map[string]*model.User)
for i := range orderUsers {
userMap[orderUsers[i].ID] = &orderUsers[i]
}
recentOut := make([]gin.H, 0, len(recentOrders))
for _, o := range recentOrders {
u := userMap[o.UserID]
nickname := ""
phone := ""
avatar := ""
if u != nil {
if u.Nickname != nil {
nickname = *u.Nickname
}
if u.Phone != nil {
phone = *u.Phone
}
if u.Avatar != nil {
avatar = *u.Avatar
}
}
referrerCode := ""
if o.ReferralCode != nil {
referrerCode = *o.ReferralCode
} else if o.ReferrerID != nil && *o.ReferrerID != "" {
if ru := userMap[*o.ReferrerID]; ru != nil && ru.ReferralCode != nil {
referrerCode = *ru.ReferralCode
}
}
recentOut = append(recentOut, gin.H{
"id": o.ID, "orderSn": o.OrderSN, "userId": o.UserID, "userNickname": nickname, "userAvatar": avatar,
"amount": o.Amount, "status": ptrStr(o.Status), "productType": o.ProductType, "productId": o.ProductID, "description": o.Description,
"referrerId": o.ReferrerID, "referralCode": referrerCode, "createdAt": o.CreatedAt, "paymentMethod": "微信",
})
}
var newUsers []model.User
db.Order("created_at DESC").Limit(5).Find(&newUsers)
newUsersOut := make([]gin.H, 0, len(newUsers))
for _, u := range newUsers {
nickname := ""
if u.Nickname != nil {
nickname = *u.Nickname
}
phone := ""
if u.Phone != nil {
phone = *u.Phone
}
newUsersOut = append(newUsersOut, gin.H{
"id": u.ID, "nickname": nickname, "phone": phone, "referralCode": u.ReferralCode, "createdAt": u.CreatedAt,
})
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"totalUsers": totalUsers,
"paidOrderCount": paidOrderCount,
"paidUserCount": paidUserCount,
"totalRevenue": totalRevenue,
"conversionRate": conversionRate,
"recentOrders": recentOut,
"newUsers": newUsersOut,
})
}
func ptrStr(s *string) string {
if s == nil {
return ""
}
return *s
}