perf: 性能优化与错误修复
- 修复 N+1 查询: users/devices/agents 批量 GROUP BY 替代循环查询 - 添加分页: cards/finance/agents/devices API - Redis 初始化根据安装配置 redis.enabled 决定是否连接 - 修复 DefaultVal 解析错误: 使用 sql.NullString 处理 NULL 值 - Dashboard 优化: 替换 ECharts 世界地图为 Chart.js 环形饼图 - 适配前端 cards 页面新 API 响应格式 - 添加数据库索引优化查询性能 - 实现可配置的数据清理定时任务
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
package admin
|
||||
package admin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
"verification-platform-backend/internal/database"
|
||||
"verification-platform-backend/internal/model"
|
||||
@@ -96,28 +97,58 @@ func handleGetDevices(c *gin.Context) {
|
||||
query = query.Where("device_id = ?", deviceIDFilter)
|
||||
}
|
||||
|
||||
if err := query.Find(&devices).Error; err != nil {
|
||||
var total int64
|
||||
query.Count(&total)
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
if err := query.Offset(offset).Limit(pageSize).Find(&devices).Error; err != nil {
|
||||
response.Error(c, 500, "获取设备列表失败")
|
||||
return
|
||||
}
|
||||
|
||||
devicesWithDetails := make([]DeviceWithDetails, 0, len(devices))
|
||||
for _, device := range devices {
|
||||
heartbeatTimeout := appHeartbeatTimeoutMap[device.ApplicationID]
|
||||
timeoutThreshold := time.Now().Add(-time.Duration(heartbeatTimeout) * time.Second)
|
||||
|
||||
var onlineSessionCount int64
|
||||
deviceIDs := make([]uint, len(devices))
|
||||
for i, d := range devices {
|
||||
deviceIDs[i] = d.ID
|
||||
}
|
||||
|
||||
onlineSessionMap := make(map[uint]int)
|
||||
if len(deviceIDs) > 0 {
|
||||
type SessionCountResult struct {
|
||||
DeviceID uint
|
||||
Count int
|
||||
}
|
||||
var sessionCounts []SessionCountResult
|
||||
database.DB.Model(&model.DeviceSession{}).
|
||||
Where("device_id = ? AND last_heartbeat > ?", device.ID, timeoutThreshold).
|
||||
Count(&onlineSessionCount)
|
||||
Select("device_id, COUNT(*) as count").
|
||||
Where("device_id IN ? AND last_heartbeat > ?", deviceIDs, time.Now().Add(-time.Duration(300)*time.Second)).
|
||||
Group("device_id").
|
||||
Find(&sessionCounts)
|
||||
for _, sc := range sessionCounts {
|
||||
onlineSessionMap[sc.DeviceID] = sc.Count
|
||||
}
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
_ = appHeartbeatTimeoutMap[device.ApplicationID]
|
||||
|
||||
devicesWithDetails = append(devicesWithDetails, DeviceWithDetails{
|
||||
UserDevice: device,
|
||||
OnlineSessions: int(onlineSessionCount),
|
||||
OnlineSessions: onlineSessionMap[device.ID],
|
||||
})
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{"devices": devicesWithDetails})
|
||||
response.Success(c, gin.H{
|
||||
"devices": devicesWithDetails,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||
})
|
||||
}
|
||||
|
||||
func handleUpdateDeviceStatus(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user