package middleware import ( "bytes" "gofaster/internal/shared/model" "io" "strconv" "strings" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" "gorm.io/gorm" ) // 从 Gin 上下文中获取用户ID(假设 JWT 中间件已将用户信息存入上下文) func getUserIdFromContext(c *gin.Context) uint { // 使用安全的GetUserID函数 if userID, exists := GetUserID(c); exists { return userID } return 0 // 0 表示未登录用户或获取失败 } // 从请求路径解析操作类型(根据 RESTful 路径映射) func getActionFromPath(path string) string { // 移除查询参数和版本前缀(如 /api/v1/users -> /users) cleanPath := strings.Split(path, "?")[0] segments := strings.Split(cleanPath, "/") lastSegment := segments[len(segments)-1] // 常见 RESTful 操作映射 switch lastSegment { case "login": return "用户登录" case "logout": return "用户登出" case "users": return "用户管理" case "roles": return "角色管理" case "permissions": return "权限管理" default: // 如果是数字ID(如 /users/123),取上一级路径 if _, err := strconv.Atoi(lastSegment); err == nil && len(segments) > 1 { return getActionFromPath(strings.Join(segments[:len(segments)-1], "/")) } return "未知操作" } } func LoggerMiddleware(logger *zap.Logger, db *gorm.DB) gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() path := c.Request.URL.Path // 记录请求体 var requestBody string if c.Request.Body != nil { bodyBytes, _ := io.ReadAll(c.Request.Body) c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) requestBody = string(bodyBytes) } // 处理请求 c.Next() // 记录日志 latency := time.Since(start).Milliseconds() actionLog := model.ActionLog{ UserID: getUserIdFromContext(c), Action: getActionFromPath(path), IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), Path: path, Method: c.Request.Method, Request: requestBody, Status: c.Writer.Status(), Latency: latency, } // 异步保存日志 go func() { if err := db.Create(&actionLog).Error; err != nil { logger.Error("保存操作日志失败", zap.Error(err)) } }() } }