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
+18 -18
View File
@@ -280,12 +280,12 @@ type CardType struct {
// Card 卡密模型
type Card struct {
ID uint `gorm:"primaryKey" json:"id"`
ApplicationID uint `json:"application_id"` // 所属应用ID
CardTypeID uint `json:"card_type_id"`
ApplicationID uint `gorm:"index;not null" json:"application_id"`
CardTypeID uint `gorm:"index;not null" json:"card_type_id"`
CardKey string `gorm:"uniqueIndex;size:100" json:"card_key"`
CreatorID uint `json:"creator_id"` // 创建人ID
AppUserID *uint `json:"app_user_id"` // 使用者ID
Status string `gorm:"size:20;default:unused" json:"status"` // unused, used, banned
CreatorID uint `gorm:"index" json:"creator_id"`
AppUserID *uint `gorm:"index" json:"app_user_id"`
Status string `gorm:"size:20;default:unused;index" json:"status"`
UsedAt *time.Time `json:"used_at"`
ExpireAt *time.Time `json:"expire_at"`
CreatedAt time.Time `json:"created_at"`
@@ -301,7 +301,7 @@ type Card struct {
// Announcement 公告模型
type Announcement struct {
ID uint `gorm:"primaryKey" json:"id"`
ApplicationID uint `json:"application_id"`
ApplicationID uint `gorm:"index" json:"application_id"`
Title string `gorm:"size:255" json:"title"`
Content string `gorm:"type:text" json:"content"`
Type string `gorm:"size:20;default:info" json:"type"` // info, warning, urgent
@@ -318,8 +318,8 @@ type Announcement struct {
type Order struct {
ID uint `gorm:"primaryKey" json:"id"`
OrderNo string `gorm:"uniqueIndex;size:100" json:"order_no"`
UserID uint `json:"user_id"`
ApplicationID *uint `json:"application_id"`
UserID uint `gorm:"index" json:"user_id"`
ApplicationID *uint `gorm:"index" json:"application_id"`
PackageID *uint `json:"package_id"`
OrderType string `gorm:"size:50;not null" json:"order_type"` // card_recharge, agent_auth, user_recharge, user_deduct, package
Title string `gorm:"size:200" json:"title"`
@@ -371,7 +371,7 @@ type Log struct {
// RechargeRecord 充值记录模型
type RechargeRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID uint `json:"user_id"`
UserID uint `gorm:"index" json:"user_id"`
OrderNo string `gorm:"size:50;uniqueIndex" json:"order_no"`
CardID *uint `json:"card_id"`
CardCode string `gorm:"size:100" json:"card_code"`
@@ -390,8 +390,8 @@ type RechargeRecord struct {
// ConsumptionRecord 消费记录模型
type ConsumptionRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID uint `json:"user_id"`
ApplicationID uint `json:"application_id"`
UserID uint `gorm:"index" json:"user_id"`
ApplicationID uint `gorm:"index" json:"application_id"`
OrderNo string `gorm:"size:50;uniqueIndex" json:"order_no"`
Type string `gorm:"size:50" json:"type"` // verification, card_purchase, subscription, feature, manual_deduct
Content string `gorm:"type:text" json:"content"`
@@ -895,11 +895,11 @@ type WebhookLog struct {
RequestData string `gorm:"type:text" json:"request_data"`
ResponseCode int `json:"response_code"`
ResponseData string `gorm:"type:text" json:"response_data"`
Status string `gorm:"size:20" json:"status"` // success, failed, retrying
Status string `gorm:"size:20;index" json:"status"`
RetryCount int `json:"retry_count"`
ErrorMessage string `gorm:"type:text" json:"error_message"`
Duration int `json:"duration"` // 请求耗时(毫秒)
CreatedAt time.Time `json:"created_at"`
Duration int `json:"duration"`
CreatedAt time.Time `gorm:"index" json:"created_at"`
WebhookConfig WebhookConfig `gorm:"foreignKey:WebhookID" json:"webhook,omitempty"`
}
@@ -925,17 +925,17 @@ type ExtensionAPIKey struct {
// ApiUsage API调用统计模型
type ApiUsage struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID uint `json:"user_id"`
ApplicationID uint `json:"application_id"`
UserID uint `gorm:"index" json:"user_id"`
ApplicationID uint `gorm:"index" json:"application_id"`
Endpoint string `gorm:"size:255" json:"endpoint"`
Method string `gorm:"size:10" json:"method"`
IPAddress string `gorm:"size:50" json:"ip_address"`
UserAgent string `gorm:"size:500" json:"user_agent"`
ResponseTime int `json:"response_time"` // 响应时间(毫秒)
ResponseTime int `json:"response_time"`
StatusCode int `json:"status_code"`
Success bool `json:"success"`
ErrorMessage string `gorm:"type:text" json:"error_message"`
CreatedAt time.Time `json:"created_at"`
CreatedAt time.Time `gorm:"index" json:"created_at"`
User User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Application Application `gorm:"foreignKey:ApplicationID" json:"application,omitempty"`