package handler import ( "strconv" "gotest/internal/model" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // AccessLogHandler 访问日志处理器 type AccessLogHandler struct { db *gorm.DB } // NewAccessLogHandler 创建访问日志处理器 func NewAccessLogHandler(db *gorm.DB) *AccessLogHandler { return &AccessLogHandler{db: db} } // ListLogs 获取访问日志列表 GET /api/v1/admin/access-logs func (h *AccessLogHandler) ListLogs(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) ip := c.Query("ip") path := c.Query("path") if page < 1 { page = 1 } if pageSize < 1 || pageSize > 100 { pageSize = 20 } offset := (page - 1) * pageSize query := h.db.Model(&model.AccessLog{}) if ip != "" { query = query.Where("ip LIKE ?", "%"+ip+"%") } if path != "" { query = query.Where("path LIKE ?", "%"+path+"%") } var total int64 query.Count(&total) var logs []model.AccessLog if err := query.Order("id DESC").Offset(offset).Limit(pageSize).Find(&logs).Error; err != nil { FailInternal(c, "查询失败: "+err.Error()) return } Success(c, gin.H{ "list": logs, "total": total, "page": page, "page_size": pageSize, }) } // GetStats 获取访问统计 GET /api/v1/admin/access-logs/stats func (h *AccessLogHandler) GetStats(c *gin.Context) { var totalVisits int64 h.db.Model(&model.AccessLog{}).Count(&totalVisits) var todayVisits int64 h.db.Model(&model.AccessLog{}).Where("created_at >= date('now')").Count(&todayVisits) var uniqueIPs int64 h.db.Model(&model.AccessLog{}).Distinct("ip").Count(&uniqueIPs) // 最近 24 小时每小时访问量 type hourlyCount struct { Hour string `json:"hour"` Count int64 `json:"count"` } var hourly []hourlyCount h.db.Model(&model.AccessLog{}). Select("strftime('%Y-%m-%d %H:00', created_at) as hour, count(*) as count"). Where("created_at >= datetime('now', '-24 hours')"). Group("hour"). Order("hour ASC"). Scan(&hourly) // 最近 10 条日志 var recent []model.AccessLog h.db.Order("id DESC").Limit(10).Find(&recent) Success(c, gin.H{ "total_visits": totalVisits, "today_visits": todayVisits, "unique_ips": uniqueIPs, "hourly": hourly, "recent": recent, }) } // DeleteLogs 清空访问日志 DELETE /api/v1/admin/access-logs func (h *AccessLogHandler) DeleteLogs(c *gin.Context) { if err := h.db.Where("1 = 1").Delete(&model.AccessLog{}).Error; err != nil { FailInternal(c, "清空失败: "+err.Error()) return } SuccessMsg(c, "清空成功") }