Files
verify/backend/internal/router/admin/usage.go
T
admin ea8ffb6c74 fix: 订阅模式登录验证、永久会员类型区分、动态代码HTTP返回值修复、侧边栏滚动位置保持
- 修复订阅模式登录时错误检查余额的问题
- 区分无限余额和永久订阅两种永久会员类型
- 修复动态代码HTTP请求返回值在JS中无法正确访问的问题
- 添加侧边栏滚动位置保持功能
- 移除developer角色相关代码,统一使用admin
- 添加缺失的i18n翻译key
2026-05-01 16:39:31 +08:00

297 lines
7.2 KiB
Go

package admin
import (
"fmt"
"time"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
"verification-platform-backend/internal/service"
"verification-platform-backend/pkg/response"
"github.com/gin-gonic/gin"
)
func SetupUsageRoutes(r *gin.RouterGroup) {
usage := r.Group("/usage")
{
usage.GET("/stats", handleGetUsageStats)
usage.GET("/api-history", handleGetApiUsageHistory)
usage.GET("/storage-history", handleGetStorageUsageHistory)
usage.GET("/alerts", handleGetUsageAlerts)
usage.GET("/notifications", handleGetNotifications)
usage.PUT("/notifications/:id/read", handleMarkNotificationAsRead)
usage.GET("/notifications/unread-count", handleGetUnreadNotificationCount)
}
}
func handleGetUsageStats(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
var user model.User
if err := database.DB.Preload("CurrentPackage").First(&user, userID).Error; err != nil {
response.Error(c, 500, "获取用户信息失败")
return
}
var permission *model.PackagePermission
if user.CurrentPackageID != nil {
var perm model.PackagePermission
if err := database.DB.Where("package_id = ?", user.CurrentPackageID).First(&perm).Error; err == nil {
permission = &perm
}
}
now := time.Now()
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
var todayApiCalls int64
database.DB.Model(&model.ApiUsage{}).
Where("user_id = ? AND created_at >= ?", userID, today).
Count(&todayApiCalls)
var last30DaysApiCalls int64
database.DB.Model(&model.ApiUsage{}).
Where("user_id = ? AND created_at >= ?", userID, now.AddDate(0, 0, -30)).
Count(&last30DaysApiCalls)
var totalApiCalls int64
database.DB.Model(&model.ApiUsage{}).
Where("user_id = ?", userID).
Count(&totalApiCalls)
storageUsedMB := float64(user.StorageUsed) / 1024 / 1024
maxStorageMB := 0.0
if permission != nil {
maxStorageMB = float64(permission.MaxStorage)
}
usageData := gin.H{
"api_calls": gin.H{
"today": todayApiCalls,
"last_30_days": last30DaysApiCalls,
"total": totalApiCalls,
"limit": 0,
"used_today": user.ApiCallsUsed,
"reset_at": user.ApiCallsResetAt,
},
"storage": gin.H{
"used_mb": storageUsedMB,
"max_mb": maxStorageMB,
"used_bytes": user.StorageUsed,
"max_bytes": int64(maxStorageMB * 1024 * 1024),
"usage_percent": 0.0,
},
"package": gin.H{
"id": nil,
"name": nil,
"expired_at": nil,
},
}
if permission != nil {
usageData["api_calls"].(gin.H)["limit"] = permission.MaxApiCalls
if maxStorageMB > 0 {
usageData["storage"].(gin.H)["usage_percent"] = (storageUsedMB / maxStorageMB) * 100
}
}
if user.CurrentPackage != nil {
usageData["package"].(gin.H)["id"] = user.CurrentPackage.ID
usageData["package"].(gin.H)["name"] = user.CurrentPackage.Name
var userPackage model.UserPackage
if err := database.DB.Where("user_id = ? AND package_id = ? AND status = ?",
userID, user.CurrentPackageID, "active").
First(&userPackage).Error; err == nil {
usageData["package"].(gin.H)["expired_at"] = userPackage.ExpiredAt
}
}
response.Success(c, usageData)
}
func handleGetApiUsageHistory(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
page := 1
pageSize := 20
if p, ok := c.GetQuery("page"); ok {
fmt.Sscanf(p, "%d", &page)
}
if ps, ok := c.GetQuery("page_size"); ok {
fmt.Sscanf(ps, "%d", &pageSize)
}
var total int64
database.DB.Model(&model.ApiUsage{}).Where("user_id = ?", userID).Count(&total)
var usages []model.ApiUsage
offset := (page - 1) * pageSize
if err := database.DB.Where("user_id = ?", userID).
Order("created_at DESC").
Limit(pageSize).
Offset(offset).
Find(&usages).Error; err != nil {
response.Error(c, 500, "获取API调用历史失败")
return
}
response.Success(c, gin.H{
"list": usages,
"total": total,
"page": page,
"page_size": pageSize,
})
}
func handleGetUsageAlerts(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
alertService := service.NewUsageAlertService()
alerts, err := alertService.CheckAndCreateAlerts(userID.(uint))
if err != nil {
response.Error(c, 500, "检查用量告警失败")
return
}
history, err := alertService.GetUserAlerts(userID.(uint), 20)
if err != nil {
response.Error(c, 500, "获取告警历史失败")
return
}
response.Success(c, gin.H{
"current_alerts": alerts,
"history": history,
})
}
func handleGetNotifications(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
page := 1
pageSize := 20
if p, ok := c.GetQuery("page"); ok {
fmt.Sscanf(p, "%d", &page)
}
if ps, ok := c.GetQuery("page_size"); ok {
fmt.Sscanf(ps, "%d", &pageSize)
}
var total int64
database.DB.Model(&model.Notification{}).Where("user_id = ?", userID).Count(&total)
var notifications []model.Notification
offset := (page - 1) * pageSize
if err := database.DB.Where("user_id = ?", userID).
Order("created_at DESC").
Limit(pageSize).
Offset(offset).
Find(&notifications).Error; err != nil {
response.Error(c, 500, "获取通知失败")
return
}
response.Success(c, gin.H{
"list": notifications,
"total": total,
"page": page,
"page_size": pageSize,
})
}
func handleMarkNotificationAsRead(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
notificationID := c.Param("id")
var notification model.Notification
if err := database.DB.Where("id = ? AND user_id = ?", notificationID, userID).First(&notification).Error; err != nil {
response.Error(c, 404, "通知不存在")
return
}
notification.IsRead = true
if err := database.DB.Save(&notification).Error; err != nil {
response.Error(c, 500, "标记通知失败")
return
}
response.Success(c, nil)
}
func handleGetUnreadNotificationCount(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
var count int64
database.DB.Model(&model.Notification{}).
Where("user_id = ? AND is_read = ?", userID, false).
Count(&count)
response.Success(c, gin.H{
"count": count,
})
}
func handleGetStorageUsageHistory(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, 401, "未授权")
return
}
page := 1
pageSize := 20
if p, ok := c.GetQuery("page"); ok {
fmt.Sscanf(p, "%d", &page)
}
if ps, ok := c.GetQuery("page_size"); ok {
fmt.Sscanf(ps, "%d", &pageSize)
}
var total int64
database.DB.Model(&model.StorageUsage{}).Where("user_id = ?", userID).Count(&total)
var usages []model.StorageUsage
offset := (page - 1) * pageSize
if err := database.DB.Where("user_id = ?", userID).
Order("created_at DESC").
Limit(pageSize).
Offset(offset).
Find(&usages).Error; err != nil {
response.Error(c, 500, "获取存储使用历史失败")
return
}
response.Success(c, gin.H{
"list": usages,
"total": total,
"page": page,
"page_size": pageSize,
})
}