up
This commit is contained in:
@@ -1,45 +1,33 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"licserver/internal/model"
|
||||
"licserver/internal/service"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DashboardHandler struct {
|
||||
db *gorm.DB
|
||||
dashboardService *service.DashboardService
|
||||
}
|
||||
|
||||
func NewDashboardHandler(db *gorm.DB) *DashboardHandler {
|
||||
return &DashboardHandler{db: db}
|
||||
func NewDashboardHandler(dashboardService *service.DashboardService) *DashboardHandler {
|
||||
return &DashboardHandler{dashboardService: dashboardService}
|
||||
}
|
||||
|
||||
func (h *DashboardHandler) GetStats(c *gin.Context) {
|
||||
var stats struct {
|
||||
TotalDevices int64 `json:"total_devices"`
|
||||
TotalLicenses int64 `json:"total_licenses"`
|
||||
TodayNew int64 `json:"today_new"`
|
||||
OnlineDevices int64 `json:"online_devices"`
|
||||
// GetDashboardStats 获取仪表盘统计数据
|
||||
func (h *DashboardHandler) GetDashboardStats(c *gin.Context) {
|
||||
stats, err := h.dashboardService.GetDashboardStats()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取设备总数
|
||||
h.db.Model(&model.Device{}).Count(&stats.TotalDevices)
|
||||
|
||||
// 获取授权码总数
|
||||
h.db.Model(&model.LicenseCode{}).Count(&stats.TotalLicenses)
|
||||
|
||||
// 获取今日新增设备数
|
||||
today := time.Now().Format("2006-01-02")
|
||||
h.db.Model(&model.Device{}).Where("DATE(created_at) = ?", today).Count(&stats.TodayNew)
|
||||
|
||||
// 获取在线设备数(最近30分钟内有活动的设备)
|
||||
thirtyMinutesAgo := time.Now().Add(-30 * time.Minute)
|
||||
h.db.Model(&model.Device{}).
|
||||
Where("last_active_at > ?", thirtyMinutesAgo).
|
||||
Count(&stats.OnlineDevices)
|
||||
|
||||
c.JSON(http.StatusOK, stats)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"data": stats,
|
||||
})
|
||||
}
|
||||
|
@@ -3,22 +3,25 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"strconv"
|
||||
|
||||
"licserver/internal/model"
|
||||
"licserver/internal/service"
|
||||
"licserver/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type DeviceHandler struct {
|
||||
deviceService *service.DeviceService
|
||||
config *utils.Config
|
||||
}
|
||||
|
||||
func NewDeviceHandler(deviceService *service.DeviceService) *DeviceHandler {
|
||||
func NewDeviceHandler(deviceService *service.DeviceService, config *utils.Config) *DeviceHandler {
|
||||
|
||||
return &DeviceHandler{deviceService: deviceService}
|
||||
return &DeviceHandler{deviceService: deviceService, config: config}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ func (h *DeviceHandler) GetDevices(c *gin.Context) {
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
||||
|
||||
params := &service.DeviceQueryParams{
|
||||
|
||||
@@ -89,19 +92,37 @@ func (h *DeviceHandler) GetDevices(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *DeviceHandler) UpdateStartCount(c *gin.Context) {
|
||||
|
||||
uid := c.Param("uid")
|
||||
|
||||
if err := h.deviceService.UpdateStartCount(uid); err != nil {
|
||||
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
// 更新启动次数
|
||||
err := h.deviceService.UpdateStartCount(uid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "启动次数更新成功"})
|
||||
// 获取更新后的设备信息
|
||||
device, err := h.deviceService.GetDevice(uid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "启动次数更新成功",
|
||||
"data": gin.H{
|
||||
"start_count": device.StartCount,
|
||||
"status": device.Status,
|
||||
"last_active_at": device.LastActiveAt,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (h *DeviceHandler) UpdateDevice(c *gin.Context) {
|
||||
@@ -207,19 +228,50 @@ func (h *DeviceHandler) RegisterDevice(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *DeviceHandler) ValidateDevice(c *gin.Context) {
|
||||
|
||||
uid := c.Param("uid")
|
||||
|
||||
if err := h.deviceService.ValidateDevice(uid); err != nil {
|
||||
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
|
||||
device, err := h.deviceService.GetDevice(uid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "设备验证通过"})
|
||||
// 验证设备状态
|
||||
if err := h.deviceService.ValidateDevice(uid); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 准备加密响应数据
|
||||
response := utils.DeviceValidateResponse{
|
||||
Status: device.Status,
|
||||
LicenseType: device.LicenseType,
|
||||
ExpireTime: device.ExpireTime.Format(time.RFC3339),
|
||||
StartCount: device.StartCount,
|
||||
MaxUses: device.MaxUses,
|
||||
Timestamp: time.Now().Unix(),
|
||||
}
|
||||
|
||||
// 加密响应
|
||||
encrypted, err := utils.EncryptResponse(response, []byte(h.config.Security.EncryptKey))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"code": -1,
|
||||
"error": "加密响应失败: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"data": encrypted,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *DeviceHandler) BindLicense(c *gin.Context) {
|
||||
@@ -360,14 +412,17 @@ func (h *DeviceHandler) UpdateDeviceModel(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var model model.DeviceModel
|
||||
if err := c.ShouldBindJSON(&model); err != nil {
|
||||
var input model.DeviceModel
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.deviceService.UpdateDeviceModel(uint(id), &model); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
if err := h.deviceService.UpdateDeviceModel(uint(id), &input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": -1,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -455,17 +510,3 @@ func (h *DeviceHandler) GetDeviceLogs(c *gin.Context) {
|
||||
"data": logs,
|
||||
})
|
||||
}
|
||||
|
||||
// GetDashboardStats 获取仪表盘统计数据
|
||||
func (h *DeviceHandler) GetDashboardStats(c *gin.Context) {
|
||||
stats, err := h.deviceService.GetDashboardStats()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"data": stats,
|
||||
})
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ func SetupRouter(
|
||||
siteHandler *SiteHandler,
|
||||
tokenHandler *TokenHandler,
|
||||
licenseHandler *LicenseHandler,
|
||||
dashboardHandler *DashboardHandler,
|
||||
) *gin.Engine {
|
||||
r := gin.Default()
|
||||
|
||||
@@ -63,6 +64,8 @@ func SetupRouter(
|
||||
api.POST("/captcha/reset-password", userHandler.SendResetPasswordCaptcha)
|
||||
api.POST("/validate-token", tokenHandler.ValidateToken)
|
||||
api.POST("/devices/register", deviceHandler.RegisterDevice)
|
||||
api.POST("/devices/:uid/start", deviceHandler.UpdateStartCount)
|
||||
api.GET("/devices/:uid/validate", deviceHandler.ValidateDevice)
|
||||
|
||||
// 需要认证的API
|
||||
authorized := api.Group("")
|
||||
@@ -76,7 +79,6 @@ func SetupRouter(
|
||||
authorized.POST("/devices/models/batch", middleware.AdminRequired(), deviceHandler.BatchDeleteDeviceModels)
|
||||
|
||||
// 设备管理
|
||||
authorized.POST("/devices/register", deviceHandler.RegisterDevice)
|
||||
authorized.GET("/devices/registered", deviceHandler.GetRegisteredDevices)
|
||||
authorized.POST("/devices/:uid/license", middleware.AdminRequired(), deviceHandler.BindLicense)
|
||||
authorized.DELETE("/devices/:uid/license", middleware.AdminRequired(), deviceHandler.UnbindLicense)
|
||||
@@ -113,7 +115,7 @@ func SetupRouter(
|
||||
authorized.POST("/licenses/use", licenseHandler.UseLicense)
|
||||
|
||||
// 仪表盘统计
|
||||
authorized.GET("/dashboard/stats", deviceHandler.GetDashboardStats)
|
||||
authorized.GET("/dashboard/stats", dashboardHandler.GetDashboardStats)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,44 +21,45 @@ func NewUserHandler(userService *service.UserService) *UserHandler {
|
||||
|
||||
func (h *UserHandler) Login(c *gin.Context) {
|
||||
|
||||
var input struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
|
||||
Password string `json:"password" binding:"required"`
|
||||
|
||||
Captcha string `json:"captcha" binding:"required"`
|
||||
|
||||
CaptchaId string `json:"captchaId" binding:"required"`
|
||||
}
|
||||
|
||||
var input service.LoginInput
|
||||
if err := c.ShouldBindJSON(&input); err != nil {
|
||||
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// 验证验证码
|
||||
if !h.userService.GetCaptchaService().VerifyImageCaptcha(input.CaptchaId, input.Captcha) {
|
||||
if !h.userService.VerifyCaptcha(input.CaptchaId, input.Captcha) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := h.userService.Login(input.Username, input.Password)
|
||||
|
||||
// 验证用户名密码
|
||||
user, err := h.userService.ValidateUser(input.Username, input.Password)
|
||||
if err != nil {
|
||||
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// 设置 cookie
|
||||
// c.SetCookie("token", token, 86400, "/", "", false, true) // 24小时过期,httpOnly=true
|
||||
// 生成 JWT token
|
||||
token, err := h.userService.GenerateToken(user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "生成token失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"token": token})
|
||||
// 返回token和用户信息
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"data": gin.H{
|
||||
"token": token,
|
||||
"user": gin.H{
|
||||
"id": user.ID,
|
||||
"username": user.Username,
|
||||
"email": user.Email,
|
||||
"role": user.Role,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ func (h *UserHandler) ResetPassword(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "重置密码邮件已发送"})
|
||||
c.JSON(http.StatusOK, gin.H{"message": "重置密邮件已发送"})
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user