This commit is contained in:
JiXieShi
2024-11-16 23:59:15 +08:00
parent f722153536
commit 87859c7bb8
42 changed files with 2018 additions and 485 deletions

View File

@@ -0,0 +1,94 @@
package service
import (
"licserver/internal/model"
"time"
"gorm.io/gorm"
)
type DashboardService struct {
db *gorm.DB
}
func NewDashboardService(db *gorm.DB) *DashboardService {
return &DashboardService{db: db}
}
type DashboardStats struct {
TotalDevices int64 `json:"total_devices"` // 设备总数
TotalLicenses int64 `json:"total_licenses"` // 授权码总数
TodayNew int64 `json:"today_new"` // 今日新增
OnlineDevices int64 `json:"online_devices"` // 在线设备
ActiveDevices int64 `json:"active_devices"` // 激活设备
ExpiredDevices int64 `json:"expired_devices"` // 过期设备
DeviceTypes []DeviceTypeStats `json:"device_types"` // 设备类型分布
TrendData []DailyRegistration `json:"trend_data"` // 注册趋势
LicenseStats LicenseStatistics `json:"license_stats"` // 授权码统计
}
type DeviceTypeStats struct {
Type string `json:"type"`
Count int64 `json:"count"`
}
type DailyRegistration struct {
Date string `json:"date"`
Count int64 `json:"count"`
}
type LicenseStatistics struct {
Unused int64 `json:"unused"` // 未使用
Used int64 `json:"used"` // 已使用
Expired int64 `json:"expired"` // 已过期
Revoked int64 `json:"revoked"` // 已撤销
}
func (s *DashboardService) GetDashboardStats() (*DashboardStats, error) {
stats := &DashboardStats{}
// 获取设备总数
s.db.Model(&model.Device{}).Count(&stats.TotalDevices)
// 获取授权码总数
s.db.Model(&model.LicenseCode{}).Count(&stats.TotalLicenses)
// 获取今日新增设备数
today := time.Now().Format("2006-01-02")
s.db.Model(&model.Device{}).Where("DATE(register_time) = ?", today).Count(&stats.TodayNew)
// 获取在线设备数最近30分钟内有活动的设备
thirtyMinutesAgo := time.Now().Add(-30 * time.Minute)
s.db.Model(&model.Device{}).Where("last_active_at > ?", thirtyMinutesAgo).Count(&stats.OnlineDevices)
// 获取激活和过期设备数
s.db.Model(&model.Device{}).Where("status = ?", "active").Count(&stats.ActiveDevices)
s.db.Model(&model.Device{}).Where("status = ?", "expired").Count(&stats.ExpiredDevices)
// 获取设备类型分布
var deviceTypes []DeviceTypeStats
s.db.Model(&model.Device{}).
Select("device_type as type, count(*) as count").
Group("device_type").
Scan(&deviceTypes)
stats.DeviceTypes = deviceTypes
// 获取最近7天的注册趋势
var trendData []DailyRegistration
sevenDaysAgo := time.Now().AddDate(0, 0, -7)
s.db.Model(&model.Device{}).
Select("DATE(register_time) as date, count(*) as count").
Where("register_time >= ?", sevenDaysAgo).
Group("DATE(register_time)").
Order("date ASC").
Scan(&trendData)
stats.TrendData = trendData
// 获取授权码统计
s.db.Model(&model.LicenseCode{}).Where("status = ?", "unused").Count(&stats.LicenseStats.Unused)
s.db.Model(&model.LicenseCode{}).Where("status = ?", "used").Count(&stats.LicenseStats.Used)
s.db.Model(&model.LicenseCode{}).Where("status = ?", "expired").Count(&stats.LicenseStats.Expired)
s.db.Model(&model.LicenseCode{}).Where("status = ?", "revoked").Count(&stats.LicenseStats.Revoked)
return stats, nil
}

View File

@@ -31,7 +31,7 @@ func NewDeviceService(db *gorm.DB, licenseService *LicenseService) *DeviceServic
type DeviceRegisterInput struct {
UID string `json:"uid" binding:"required"`
DeviceModel string `json:"device_model" binding:"required"`
LicenseCode string `json:"license_code"`
LicenseCode string `json:"license_code,omitempty"`
}
func (s *DeviceService) RegisterDevice(input *DeviceRegisterInput, ip string) error {
@@ -104,15 +104,12 @@ func (s *DeviceService) RegisterDevice(input *DeviceRegisterInput, ip string) er
}
// 记录设备日志
logMsg := "设备注册成功"
if device.LicenseCode != "" {
logMsg += fmt.Sprintf(",使用授权码: %s", device.LicenseCode)
}
log := model.DeviceLog{
DeviceUID: input.UID,
Action: "register",
Message: logMsg,
Message: fmt.Sprintf("设备注册成功,状态:%s", device.Status),
Status: "success",
IP: ip,
}
if err := tx.Create(&log).Error; err != nil {
return err
@@ -337,7 +334,7 @@ type DeviceCreateInput struct {
}
func (s *DeviceService) CreateDevice(input *DeviceCreateInput) error {
// 检查设备UID否已存在
// 检查设备UID<EFBFBD><EFBFBD><EFBFBD>否已存在
var count int64
if err := s.db.Model(&model.Device{}).Where("uid = ?", input.UID).Count(&count).Error; err != nil {
return err
@@ -408,15 +405,49 @@ func (s *DeviceService) CreateDeviceModel(model_ *model.DeviceModel) error {
}
// UpdateDeviceModel 更新设备型号
func (s *DeviceService) UpdateDeviceModel(id uint, model_ *model.DeviceModel) error {
// 检查型号名称是否被其他型号使用
var count int64
s.db.Model(&model.DeviceModel{}).Where("model_name = ? AND id != ?", model_.ModelName, id).Count(&count)
if count > 0 {
return errors.New("设备型号已存在")
func (s *DeviceService) UpdateDeviceModel(id uint, input *model.DeviceModel) error {
// 检查设备型号是否存在
var existingModel model.DeviceModel
if err := s.db.First(&existingModel, id).Error; err != nil {
return errors.New("设备型号不存在")
}
return s.db.Model(&model.DeviceModel{}).Where("id = ?", id).Updates(model_).Error
// 如果型号名称发生变更,需要检查是否存在冲突
if input.ModelName != existingModel.ModelName {
// 检查新的型号名称是否与其他型号冲突(排除自身)
var count int64
s.db.Model(&model.DeviceModel{}).
Where("model_name = ? AND id != ?", input.ModelName, id).
Count(&count)
if count > 0 {
return fmt.Errorf("设备型号[%d]:%s已存在", id, input.ModelName)
}
// 检查是否有设备正在使用此型号
var deviceCount int64
s.db.Model(&model.Device{}).
Where("device_model = ?", existingModel.ModelName).
Count(&deviceCount)
if deviceCount > 0 {
return errors.New("该型号下存在设备,无法修改型号名称")
}
}
// 更新设备型号信息
updates := map[string]interface{}{
"device_type": input.DeviceType,
"company": input.Company,
"status": input.Status,
"remark": input.Remark,
}
// 只有当型号名称变更时才更新
if input.ModelName != existingModel.ModelName {
updates["model_name"] = input.ModelName
}
return s.db.Model(&existingModel).Updates(updates).Error
}
// DeleteDeviceModel 删除设备型号
@@ -448,7 +479,7 @@ func (s *DeviceService) GetDeviceModels(modelName, deviceType, company string, p
query = query.Where("company LIKE ?", "%"+company+"%")
}
// 取总数
// 取总数
query.Count(&total)
// 分页查询
@@ -683,39 +714,10 @@ func (s *DeviceService) GetDeviceLogs(uid string, page, pageSize int) ([]model.D
return logs, total, err
}
// DashboardStats 仪表盘统计数据
type DashboardStats struct {
TotalDevices int64 `json:"total_devices"` // 设备总数
TotalLicenses int64 `json:"total_licenses"` // 授权码总数
TodayNew int64 `json:"today_new"` // 今日新增
OnlineDevices int64 `json:"online_devices"` // 在线设备
ActiveDevices int64 `json:"active_devices"` // 激活设备
ExpiredDevices int64 `json:"expired_devices"` // 过期设备
}
// GetDashboardStats 获取仪表盘统计数据
func (s *DeviceService) GetDashboardStats() (*DashboardStats, error) {
var stats DashboardStats
// 获取设备总数
s.db.Model(&model.Device{}).Count(&stats.TotalDevices)
// 获取授权码总数
s.db.Model(&model.LicenseCode{}).Count(&stats.TotalLicenses)
// 获取今日新增设备数
today := time.Now().Format("2006-01-02")
s.db.Model(&model.Device{}).Where("DATE(register_time) = ?", today).Count(&stats.TodayNew)
// 获取在线设备数最近30分钟内有活动的设备
thirtyMinutesAgo := time.Now().Add(-30 * time.Minute)
s.db.Model(&model.Device{}).Where("last_active_at > ?", thirtyMinutesAgo).Count(&stats.OnlineDevices)
// 获取激活设备数
s.db.Model(&model.Device{}).Where("status = ?", "active").Count(&stats.ActiveDevices)
// 获取过期设备数
s.db.Model(&model.Device{}).Where("status = ?", "expired").Count(&stats.ExpiredDevices)
return &stats, nil
func (s *DeviceService) GetDevice(uid string) (*model.Device, error) {
var device model.Device
if err := s.db.Where("uid = ?", uid).First(&device).Error; err != nil {
return nil, errors.New("设备不存在")
}
return &device, nil
}

View File

@@ -14,6 +14,10 @@ import (
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"github.com/golang-jwt/jwt/v5"
"github.com/mojocn/base64Captcha"
)
type UserService struct {
@@ -29,6 +33,14 @@ type UserProfile struct {
Role string `json:"role"`
}
// LoginInput 登录输入
type LoginInput struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
CaptchaId string `json:"captchaId" binding:"required"`
Captcha string `json:"captcha" binding:"required"`
}
func NewUserService(db *gorm.DB, config *utils.Config) *UserService {
return &UserService{
db: db,
@@ -359,3 +371,36 @@ func (s *UserService) DeleteUser(id uint) error {
return s.db.Delete(&model.User{}, id).Error
}
// ValidateUser 验证用户名密码
func (s *UserService) ValidateUser(username, password string) (*model.User, error) {
var user model.User
if err := s.db.Where("username = ?", username).First(&user).Error; err != nil {
return nil, errors.New("用户不存在")
}
// 使用 bcrypt 比较密码
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
return nil, errors.New("密码错误")
}
return &user, nil
}
// GenerateToken 生成JWT token
func (s *UserService) GenerateToken(user *model.User) (string, error) {
claims := jwt.MapClaims{
"user_id": user.ID,
"username": user.Username,
"role": user.Role,
"exp": time.Now().Add(time.Hour * 24).Unix(), // 24小时过期
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(s.config.JWT.Secret))
}
// VerifyCaptcha 验证验证码
func (s *UserService) VerifyCaptcha(captchaId, captcha string) bool {
return base64Captcha.DefaultMemStore.Verify(captchaId, captcha, true)
}