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

157 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"net/http"
"strconv"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// DBMatchRecordsList GET /api/db/match-records 管理端-匹配记录列表(分页、按类型筛选)
// 当 ?stats=true 时返回汇总统计(总匹配数、今日匹配、按类型分布、独立用户数)
func DBMatchRecordsList(c *gin.Context) {
db := database.DB()
if c.Query("stats") == "true" {
var totalMatches int64
db.Model(&model.MatchRecord{}).Count(&totalMatches)
var todayMatches int64
db.Model(&model.MatchRecord{}).Where("created_at >= CURDATE()").Count(&todayMatches)
type TypeCount struct {
MatchType string `json:"matchType"`
Count int64 `json:"count"`
}
var byType []TypeCount
db.Model(&model.MatchRecord{}).Select("match_type as match_type, count(*) as count").Group("match_type").Scan(&byType)
var uniqueUsers int64
db.Model(&model.MatchRecord{}).Distinct("user_id").Count(&uniqueUsers)
// 匹配收益product_type=match 且 status=paid 的订单金额总和
var matchRevenue float64
db.Model(&model.Order{}).Where("product_type = ? AND status = ?", "match", "paid").
Select("COALESCE(SUM(amount), 0)").Scan(&matchRevenue)
var paidMatchCount int64
db.Model(&model.Order{}).Where("product_type = ? AND status = ?", "match", "paid").Count(&paidMatchCount)
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"totalMatches": totalMatches,
"todayMatches": todayMatches,
"byType": byType,
"uniqueUsers": uniqueUsers,
"matchRevenue": matchRevenue,
"paidMatchCount": paidMatchCount,
},
})
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
matchType := c.Query("matchType")
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
q := db.Model(&model.MatchRecord{})
if matchType != "" {
q = q.Where("match_type = ?", matchType)
}
var total int64
q.Count(&total)
var records []model.MatchRecord
if err := q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error(), "records": []interface{}{}})
return
}
userIDs := make(map[string]bool)
for _, r := range records {
userIDs[r.UserID] = true
userIDs[r.MatchedUserID] = true
}
ids := make([]string, 0, len(userIDs))
for id := range userIDs {
ids = append(ids, id)
}
var users []model.User
if len(ids) > 0 {
database.DB().Where("id IN ?", ids).Find(&users)
}
userMap := make(map[string]*model.User)
for i := range users {
userMap[users[i].ID] = &users[i]
}
getStr := func(s *string) string {
if s == nil {
return ""
}
return *s
}
out := make([]gin.H, 0, len(records))
for _, r := range records {
u := userMap[r.UserID]
mu := userMap[r.MatchedUserID]
userAvatar := ""
matchedUserAvatar := ""
if u != nil && u.Avatar != nil {
userAvatar = *u.Avatar
}
if mu != nil && mu.Avatar != nil {
matchedUserAvatar = *mu.Avatar
}
out = append(out, gin.H{
"id": r.ID, "userId": r.UserID, "matchedUserId": r.MatchedUserID,
"matchType": r.MatchType, "phone": getStr(r.Phone), "wechatId": getStr(r.WechatID),
"userNickname": getStr(u.Nickname),
"matchedNickname": getStr(mu.Nickname),
"userAvatar": userAvatar,
"matchedUserAvatar": matchedUserAvatar,
"matchScore": r.MatchScore,
"createdAt": r.CreatedAt,
})
}
totalPages := int(total) / pageSize
if int(total)%pageSize > 0 {
totalPages++
}
c.JSON(http.StatusOK, gin.H{
"success": true, "records": out,
"total": total, "page": page, "pageSize": pageSize, "totalPages": totalPages,
})
}
// DBMatchPoolCounts GET /api/db/match-pool-counts 返回各匹配池的用户人数
func DBMatchPoolCounts(c *gin.Context) {
db := database.DB()
var vipCount int64
db.Model(&model.User{}).Where("is_vip = 1 AND vip_expire_date > NOW()").Count(&vipCount)
var completeCount int64
db.Model(&model.User{}).Where(
"(phone IS NOT NULL AND phone != '') AND (nickname IS NOT NULL AND nickname != '' AND nickname != '微信用户') AND (avatar IS NOT NULL AND avatar != '')",
).Count(&completeCount)
var allCount int64
db.Model(&model.User{}).Where(
"((wechat_id IS NOT NULL AND wechat_id != '') OR (phone IS NOT NULL AND phone != ''))",
).Count(&allCount)
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"vip": vipCount,
"complete": completeCount,
"all": allCount,
},
})
}