优化平台运营概览并对齐管理端布局

统一管理端侧栏与顶栏 56px 高度;运营概览按 P2-08 重做 KPI、增长趋势、套餐分布与操作日志。
This commit is contained in:
yml2213
2026-07-15 13:45:38 +08:00
parent f6f7fd478e
commit 425cd1f0e2
5 changed files with 426 additions and 134 deletions
+50 -14
View File
@@ -17,32 +17,50 @@ type AdminHandler struct{}
func NewAdminHandler() *AdminHandler { return &AdminHandler{} }
func (h *AdminHandler) Stats(c *gin.Context) {
var tenantTotal, activeTotal, suspendedTotal, expiringTotal int64
var tenantTotal, activeTotal, suspendedTotal, expiringTotal, newThisMonth int64
model.DB.Model(&model.Tenant{}).Count(&tenantTotal)
model.DB.Model(&model.Tenant{}).Where("status = ?", "normal").Count(&activeTotal)
model.DB.Model(&model.Tenant{}).Where("status = ?", "suspended").Count(&suspendedTotal)
model.DB.Model(&model.Tenant{}).Where("status = ?", "expiring").Count(&expiringTotal)
now := time.Now()
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
model.DB.Model(&model.Tenant{}).Where("created_at >= ?", monthStart).Count(&newThisMonth)
// 估算月收入:正常/即将到期租户 × 套餐月费
type planCount struct {
PlanID uint
Count int64
}
var counts []planCount
var incomeCounts []planCount
model.DB.Model(&model.Tenant{}).
Select("plan_id, count(*) as count").
Where("status IN ? AND plan_id IS NOT NULL", []string{"normal", "expiring"}).
Group("plan_id").
Scan(&counts)
Scan(&incomeCounts)
var monthlyIncome int64
planDist := make([]gin.H, 0)
for _, item := range counts {
for _, item := range incomeCounts {
var plan model.Plan
if err := model.DB.First(&plan, item.PlanID).Error; err != nil {
continue
}
monthlyIncome += int64(plan.PriceMonthly) * item.Count
}
// 套餐分布:全部已绑定套餐的租户
var distCounts []planCount
model.DB.Model(&model.Tenant{}).
Select("plan_id, count(*) as count").
Where("plan_id IS NOT NULL").
Group("plan_id").
Scan(&distCounts)
planDist := make([]gin.H, 0, len(distCounts))
for _, item := range distCounts {
var plan model.Plan
if err := model.DB.First(&plan, item.PlanID).Error; err != nil {
continue
}
planDist = append(planDist, gin.H{
"plan_id": plan.ID,
"name": plan.Name,
@@ -50,18 +68,36 @@ func (h *AdminHandler) Stats(c *gin.Context) {
})
}
// 近 6 个月租户增长
growth := make([]gin.H, 0, 6)
for offset := 5; offset >= 0; offset-- {
mStart := time.Date(now.Year(), now.Month()-time.Month(offset), 1, 0, 0, 0, 0, now.Location())
mEnd := mStart.AddDate(0, 1, 0)
var newCnt, totalCnt int64
model.DB.Model(&model.Tenant{}).Where("created_at >= ? AND created_at < ?", mStart, mEnd).Count(&newCnt)
model.DB.Model(&model.Tenant{}).Where("created_at < ?", mEnd).Count(&totalCnt)
growth = append(growth, gin.H{
"month": mStart.Format("1月"),
"month_key": mStart.Format("2006-01"),
"new_count": newCnt,
"total_count": totalCnt,
})
}
var recentLogs []model.OperationLog
model.DB.Order("created_at desc").Limit(10).Find(&recentLogs)
model.DB.Order("created_at desc").Limit(12).Find(&recentLogs)
middleware.JSON(c, gin.H{
"tenant_total": tenantTotal,
"active_tenant": activeTotal,
"suspended_tenant": suspendedTotal,
"expiring_tenant": expiringTotal,
"monthly_income": monthlyIncome,
"system_uptime": "99.95%",
"plan_distribution": planDist,
"recent_logs": recentLogs,
"tenant_total": tenantTotal,
"active_tenant": activeTotal,
"suspended_tenant": suspendedTotal,
"expiring_tenant": expiringTotal,
"new_tenants_month": newThisMonth,
"monthly_income": monthlyIncome,
"system_uptime": "99.95%",
"plan_distribution": planDist,
"tenant_growth": growth,
"recent_logs": recentLogs,
})
}