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:
2026-05-06 19:19:02 +08:00
parent 98986b0eb7
commit 086c5c6573
27 changed files with 843 additions and 467 deletions
+23 -6
View File
@@ -443,7 +443,14 @@ func handleGetCards(c *gin.Context) {
query = query.Where("cards.created_at <= ?", endDate+" 23:59:59")
}
if err := query.Order("cards.created_at DESC").Find(&cards).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.Order("cards.created_at DESC").Offset(offset).Limit(pageSize).Find(&cards).Error; err != nil {
fmt.Printf("[DEBUG] Error fetching cards: %v\n", err)
response.Error(c, 500, "获取卡密列表失败")
return
@@ -451,7 +458,13 @@ func handleGetCards(c *gin.Context) {
fmt.Printf("[DEBUG] Found %d cards for user %d\n", len(cards), userID)
response.Success(c, cards)
response.Success(c, gin.H{
"cards": cards,
"total": total,
"page": page,
"page_size": pageSize,
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
})
}
func handleCreateCards(c *gin.Context) {
@@ -742,10 +755,8 @@ func handleBatchGenerateCards(c *gin.Context) {
}
totalCost := float64(req.Count) * cardType.Price
fmt.Printf("[DEBUG] Total cost: %f, Balance: %f\n", totalCost, agentUser.Balance)
if agentUser.Balance < totalCost {
fmt.Printf("[DEBUG] Insufficient balance\n")
response.Error(c, 400, "余额不足")
return
}
@@ -757,12 +768,18 @@ func handleBatchGenerateCards(c *gin.Context) {
}
}()
if err := tx.Model(&agentUser).Update("balance", agentUser.Balance-totalCost).Error; err != nil {
result := tx.Model(&model.User{}).Where("id = ? AND balance >= ?", agentUser.ID, totalCost).
Update("balance", gorm.Expr("balance - ?", totalCost))
if result.Error != nil {
tx.Rollback()
fmt.Printf("[DEBUG] Update balance error: %v\n", err)
response.Error(c, 500, "扣款失败")
return
}
if result.RowsAffected == 0 {
tx.Rollback()
response.Error(c, 400, "余额不足")
return
}
cards := make([]model.Card, 0, req.Count)
for i := 0; i < req.Count; i++ {