Files
nl-blogs/server/handlers/log.go
2026-06-24 17:06:22 +08:00

265 lines
6.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"fmt"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
func AdminGetRecentActivities(c *gin.Context) {
// 获取最近10条操作日志
logs, _, err := repositories.GetOperationLogs(1, 10, repositories.OperationLogFilter{})
if err != nil {
utils.ServerError(c, err)
return
}
// 构建响应
var activities []gin.H
if len(logs) > 0 {
for _, log := range logs {
// 根据HTTP方法设置图标
var icon string
switch log.Method {
case "POST":
icon = ""
case "PUT", "PATCH":
icon = "✏️"
case "DELETE":
icon = "🗑️"
case "GET":
icon = "📋"
case "OPTIONS":
icon = "⚙️"
default:
icon = "📋"
}
// 构建活动文本描述
text := fmt.Sprintf("%s %s", log.Method, log.Path)
activities = append(activities, gin.H{
"id": log.ID,
"icon": icon,
"text": text,
"time": time.Unix(log.CreatedAt, 0).Format("2006-01-02 15:04:05"),
})
}
} else {
activities = []gin.H{}
}
utils.Success(c, activities)
}
// 获取操作日志列表
func AdminGetOperationLogs(c *gin.Context) {
page := 1
pageSize := 10
if c.Query("page") != "" {
if p, err := strconv.Atoi(c.Query("page")); err == nil {
page = p
}
}
if c.Query("pageSize") != "" {
if ps, err := strconv.Atoi(c.Query("pageSize")); err == nil {
pageSize = ps
}
}
filter := repositories.OperationLogFilter{
Action: c.Query("action"),
Method: c.Query("method"),
StartDate: c.Query("startDate"),
EndDate: c.Query("endDate"),
}
if statusStr := c.Query("status"); statusStr != "" {
if s, err := strconv.Atoi(statusStr); err == nil {
filter.Status = s
}
}
if userIDStr := c.Query("userId"); userIDStr != "" {
if uid, err := strconv.ParseUint(userIDStr, 10, 32); err == nil {
filter.UserID = uint(uid)
}
}
logs, total, err := repositories.GetOperationLogs(page, pageSize, filter)
if err != nil {
utils.ServerError(c, err)
return
}
// Ensure list is not nil
logList := repositories.BuildOperationLogsResponse(logs)
// BuildOperationLogsResponse returns []models.OperationLogResponse
// If logs is empty, it might return nil or empty slice depending on implementation.
// Let's assume repositories usually return nil for empty.
if logList == nil {
// We need to define the type or use empty interface slice, but gin.H is map.
// Actually BuildOperationLogsResponse returns specific struct slice.
// Let's rely on it being correct or check length?
// Since Go nil slice serializes to null, we want []
// But we can't easily assign []interface{} to specific type variable without re-allocating.
// However, utils.Success takes interface{}.
// We can just pass empty slice if nil.
// But wait, we are constructing a map:
}
// To be safe, let's verify repositories.BuildOperationLogsResponse
// Assuming it might return nil.
// We can't change the return type easily here.
// But we can do:
// "list": logList
// If logList is nil, json is null.
// User wants [].
// So we should fix it in repository or here.
// Let's assume we can just cast or verify.
// Actually simpler:
// utils.Success(c, ...) handles the response.
// Let's look at `repositories.BuildOperationLogsResponse`.
// Since I can't see it, I will assume it returns nil.
// I will construct the map carefully.
res := gin.H{
"list": logList,
"total": total,
"page": page,
"size": pageSize,
}
if logList == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}
// AdminGetAccessLogs 获取访问日志列表
func AdminGetAccessLogs(c *gin.Context) {
// 获取分页参数
page := 1
pageSize := 10
// 从查询参数中获取分页信息
if c.Query("page") != "" {
if p, err := strconv.Atoi(c.Query("page")); err == nil {
page = p
}
}
if c.Query("pageSize") != "" {
if ps, err := strconv.Atoi(c.Query("pageSize")); err == nil {
pageSize = ps
}
}
filter := repositories.AccessLogFilter{
Path: c.Query("path"),
Region: c.Query("region"),
StartDate: c.Query("startDate"),
EndDate: c.Query("endDate"),
}
// 获取访问日志
logs, total, err := repositories.GetAccessLogs(page, pageSize, nil, filter)
if err != nil {
utils.ServerError(c, err)
return
}
// 构建响应
var logList []gin.H
for _, log := range logs {
logList = append(logList, gin.H{
"id": log.ID,
"ip": log.IP,
"userAgent": log.UserAgent,
"path": log.Path,
"method": log.Method,
"statusCode": log.StatusCode,
"responseTime": log.ResponseTime,
"region": log.Region,
"createdAt": time.Unix(log.CreatedAt, 0).Format("2006-01-02 15:04:05"),
})
}
if logList == nil {
logList = []gin.H{}
}
res := gin.H{
"list": logList,
"total": total,
"page": page,
"size": pageSize,
}
utils.Success(c, res)
}
// AdminGetPostAccessLogs 获取指定文章的访问记录
func AdminGetPostAccessLogs(c *gin.Context) {
// 获取文章ID
postIDStr := c.Param("id")
postID, err := strconv.Atoi(postIDStr)
if err != nil {
utils.Error(c, 400, "Invalid post ID")
return
}
// 获取分页参数
page := 1
pageSize := 20
if c.Query("page") != "" {
if p, err := strconv.Atoi(c.Query("page")); err == nil {
page = p
}
}
if c.Query("pageSize") != "" {
if ps, err := strconv.Atoi(c.Query("pageSize")); err == nil {
pageSize = ps
}
}
// 获取文章的访问记录(从 user_access_logs 表)
logs, total, err := repositories.GetPostAccessLogsFromUserAccessLogs(postID, page, pageSize)
if err != nil {
utils.ServerError(c, err)
return
}
// 构建响应
var logList []gin.H
for _, log := range logs {
logList = append(logList, gin.H{
"id": log.ID,
"userId": log.UserID,
"ip": log.UserIP,
"region": log.UserLocation,
"articleId": log.ArticleID,
"createdAt": time.Unix(log.AccessTime, 0).Format("2006-01-02 15:04:05"),
})
}
if logList == nil {
logList = []gin.H{}
}
res := gin.H{
"list": logList,
"total": total,
"page": page,
"size": pageSize,
}
utils.Success(c, res)
}