代码推送
This commit is contained in:
107
internal/handler/access_log.go
Normal file
107
internal/handler/access_log.go
Normal file
@@ -0,0 +1,107 @@
|
||||
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, "清空成功")
|
||||
}
|
||||
Reference in New Issue
Block a user