ea8ffb6c74
- 修复订阅模式登录时错误检查余额的问题 - 区分无限余额和永久订阅两种永久会员类型 - 修复动态代码HTTP请求返回值在JS中无法正确访问的问题 - 添加侧边栏滚动位置保持功能 - 移除developer角色相关代码,统一使用admin - 添加缺失的i18n翻译key
297 lines
7.2 KiB
Go
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(¬ifications).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(¬ification).Error; err != nil {
|
|
response.Error(c, 404, "通知不存在")
|
|
return
|
|
}
|
|
|
|
notification.IsRead = true
|
|
if err := database.DB.Save(¬ification).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,
|
|
})
|
|
}
|