diff --git a/soul-api/internal/handler/admin_rfm.go b/soul-api/internal/handler/admin_rfm.go index 2ee4860d..f7041c2d 100644 --- a/soul-api/internal/handler/admin_rfm.go +++ b/soul-api/internal/handler/admin_rfm.go @@ -264,3 +264,43 @@ func DBUserRFMSingle(c *gin.Context) { }) } +// DBUsersJourneyStats GET /api/db/users/journey-stats — 各旅程阶段人数 +func DBUsersJourneyStats(c *gin.Context) { + db := database.DB() + stats := make(map[string]int64) + + var reg int64 + db.Table("users").Count(®) + stats["register"] = reg + + var browse int64 + db.Table("user_tracks").Where("action = ?", "view_chapter").Distinct("user_id").Count(&browse) + stats["browse"] = browse + + var bindPhone int64 + db.Table("users").Where("phone IS NOT NULL AND phone != ''").Count(&bindPhone) + stats["bind_phone"] = bindPhone + + var firstPay int64 + db.Table("orders").Where("status IN ?", []string{"paid", "success", "completed"}).Distinct("user_id").Count(&firstPay) + stats["first_pay"] = firstPay + + var fillProfile int64 + db.Table("users").Where("mbti IS NOT NULL OR industry IS NOT NULL").Count(&fillProfile) + stats["fill_profile"] = fillProfile + + var match int64 + db.Table("user_tracks").Where("action = ?", "match").Distinct("user_id").Count(&match) + stats["match"] = match + + var vip int64 + db.Table("users").Where("is_vip = 1").Count(&vip) + stats["vip"] = vip + + var dist int64 + db.Table("users").Where("referral_code IS NOT NULL AND referral_code != '' AND earnings > 0").Count(&dist) + stats["distribution"] = dist + + c.JSON(http.StatusOK, gin.H{"success": true, "stats": stats}) +} +