package handlers import ( "strconv" "github.com/gin-gonic/gin" "go.uber.org/zap" "tyapi-server/internal/domains/user/dto" "tyapi-server/internal/domains/user/services" "tyapi-server/internal/shared/interfaces" "tyapi-server/internal/shared/middleware" ) // UserHandler 用户HTTP处理器 type UserHandler struct { userService *services.UserService response interfaces.ResponseBuilder validator interfaces.RequestValidator logger *zap.Logger jwtAuth *middleware.JWTAuthMiddleware } // NewUserHandler 创建用户处理器 func NewUserHandler( userService *services.UserService, response interfaces.ResponseBuilder, validator interfaces.RequestValidator, logger *zap.Logger, jwtAuth *middleware.JWTAuthMiddleware, ) *UserHandler { return &UserHandler{ userService: userService, response: response, validator: validator, logger: logger, jwtAuth: jwtAuth, } } // GetPath 返回处理器路径 func (h *UserHandler) GetPath() string { return "/users" } // GetMethod 返回HTTP方法 func (h *UserHandler) GetMethod() string { return "GET" // 主要用于列表,具体方法在路由注册时指定 } // GetMiddlewares 返回中间件 func (h *UserHandler) GetMiddlewares() []gin.HandlerFunc { return []gin.HandlerFunc{ // 这里可以添加特定的中间件 } } // Handle 主处理函数(用于列表) func (h *UserHandler) Handle(c *gin.Context) { h.List(c) } // RequiresAuth 是否需要认证 func (h *UserHandler) RequiresAuth() bool { return true } // GetPermissions 获取所需权限 func (h *UserHandler) GetPermissions() []string { return []string{"user:read"} } // REST操作实现 // Create 创建用户 func (h *UserHandler) Create(c *gin.Context) { var req dto.CreateUserRequest // 验证请求体 if err := h.validator.BindAndValidate(c, &req); err != nil { return // 响应已在验证器中处理 } // 创建用户 user, err := h.userService.Create(c.Request.Context(), &req) if err != nil { h.logger.Error("Failed to create user", zap.Error(err)) h.response.BadRequest(c, err.Error()) return } // 返回响应 response := dto.FromEntity(user) h.response.Created(c, response, "User created successfully") } // GetByID 根据ID获取用户 func (h *UserHandler) GetByID(c *gin.Context) { id := c.Param("id") if id == "" { h.response.BadRequest(c, "User ID is required") return } // 获取用户 user, err := h.userService.GetByID(c.Request.Context(), id) if err != nil { h.logger.Error("Failed to get user", zap.Error(err)) h.response.NotFound(c, "User not found") return } // 返回响应 response := dto.FromEntity(user) h.response.Success(c, response) } // Update 更新用户 func (h *UserHandler) Update(c *gin.Context) { id := c.Param("id") if id == "" { h.response.BadRequest(c, "User ID is required") return } var req dto.UpdateUserRequest // 验证请求体 if err := h.validator.BindAndValidate(c, &req); err != nil { return } // 更新用户 user, err := h.userService.Update(c.Request.Context(), id, &req) if err != nil { h.logger.Error("Failed to update user", zap.Error(err)) h.response.BadRequest(c, err.Error()) return } // 返回响应 response := dto.FromEntity(user) h.response.Success(c, response, "User updated successfully") } // Delete 删除用户 func (h *UserHandler) Delete(c *gin.Context) { id := c.Param("id") if id == "" { h.response.BadRequest(c, "User ID is required") return } // 删除用户 if err := h.userService.Delete(c.Request.Context(), id); err != nil { h.logger.Error("Failed to delete user", zap.Error(err)) h.response.BadRequest(c, err.Error()) return } // 返回响应 h.response.Success(c, nil, "User deleted successfully") } // List 获取用户列表 func (h *UserHandler) List(c *gin.Context) { var req dto.UserListRequest // 验证查询参数 if err := h.validator.ValidateQuery(c, &req); err != nil { return } // 设置默认值 if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 { req.PageSize = 20 } // 构建查询选项 options := interfaces.ListOptions{ Page: req.Page, PageSize: req.PageSize, Sort: req.Sort, Order: req.Order, Search: req.Search, Filters: req.Filters, } // 获取用户列表 users, err := h.userService.List(c.Request.Context(), options) if err != nil { h.logger.Error("Failed to get user list", zap.Error(err)) h.response.InternalError(c, "Failed to get user list") return } // 获取总数 countOptions := interfaces.CountOptions{ Search: req.Search, Filters: req.Filters, } total, err := h.userService.Count(c.Request.Context(), countOptions) if err != nil { h.logger.Error("Failed to count users", zap.Error(err)) h.response.InternalError(c, "Failed to count users") return } // 构建响应 userResponses := dto.FromEntities(users) pagination := buildPagination(req.Page, req.PageSize, total) h.response.Paginated(c, userResponses, pagination) } // Login 用户登录 func (h *UserHandler) Login(c *gin.Context) { var req dto.LoginRequest // 验证请求体 if err := h.validator.BindAndValidate(c, &req); err != nil { return } // 用户登录 user, err := h.userService.Login(c.Request.Context(), &req) if err != nil { h.logger.Error("Login failed", zap.Error(err)) h.response.Unauthorized(c, "Invalid credentials") return } // 生成JWT token accessToken, err := h.jwtAuth.GenerateToken(user.ID, user.Username, user.Email) if err != nil { h.logger.Error("Failed to generate token", zap.Error(err)) h.response.InternalError(c, "Failed to generate access token") return } // 构建登录响应 loginResponse := &dto.LoginResponse{ User: dto.FromEntity(user), AccessToken: accessToken, TokenType: "Bearer", ExpiresIn: 86400, // 24小时,从配置获取 } h.response.Success(c, loginResponse, "Login successful") } // Logout 用户登出 func (h *UserHandler) Logout(c *gin.Context) { // 简单实现,客户端删除token即可 // 如果需要服务端黑名单,可以在这里实现 h.response.Success(c, nil, "Logout successful") } // GetProfile 获取当前用户信息 func (h *UserHandler) GetProfile(c *gin.Context) { userID := h.getCurrentUserID(c) if userID == "" { h.response.Unauthorized(c, "User not authenticated") return } // 获取用户信息 user, err := h.userService.GetByID(c.Request.Context(), userID) if err != nil { h.logger.Error("Failed to get user profile", zap.Error(err)) h.response.NotFound(c, "User not found") return } // 返回响应 response := dto.FromEntity(user) h.response.Success(c, response) } // UpdateProfile 更新当前用户信息 func (h *UserHandler) UpdateProfile(c *gin.Context) { userID := h.getCurrentUserID(c) if userID == "" { h.response.Unauthorized(c, "User not authenticated") return } var req dto.UpdateUserRequest // 验证请求体 if err := h.validator.BindAndValidate(c, &req); err != nil { return } // 更新用户 user, err := h.userService.Update(c.Request.Context(), userID, &req) if err != nil { h.logger.Error("Failed to update profile", zap.Error(err)) h.response.BadRequest(c, err.Error()) return } // 返回响应 response := dto.FromEntity(user) h.response.Success(c, response, "Profile updated successfully") } // ChangePassword 修改密码 func (h *UserHandler) ChangePassword(c *gin.Context) { userID := h.getCurrentUserID(c) if userID == "" { h.response.Unauthorized(c, "User not authenticated") return } var req dto.ChangePasswordRequest // 验证请求体 if err := h.validator.BindAndValidate(c, &req); err != nil { return } // 修改密码 if err := h.userService.ChangePassword(c.Request.Context(), userID, &req); err != nil { h.logger.Error("Failed to change password", zap.Error(err)) h.response.BadRequest(c, err.Error()) return } h.response.Success(c, nil, "Password changed successfully") } // Search 搜索用户 func (h *UserHandler) Search(c *gin.Context) { var req dto.UserSearchRequest // 验证查询参数 if err := h.validator.ValidateQuery(c, &req); err != nil { return } // 设置默认值 if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 { req.PageSize = 10 } // 构建查询选项 options := interfaces.ListOptions{ Page: req.Page, PageSize: req.PageSize, Search: req.Query, } // 搜索用户 users, err := h.userService.Search(c.Request.Context(), req.Query, options) if err != nil { h.logger.Error("Failed to search users", zap.Error(err)) h.response.InternalError(c, "Failed to search users") return } // 获取搜索结果总数 countOptions := interfaces.CountOptions{ Search: req.Query, } total, err := h.userService.Count(c.Request.Context(), countOptions) if err != nil { h.logger.Error("Failed to count search results", zap.Error(err)) h.response.InternalError(c, "Failed to count search results") return } // 构建响应 userResponses := dto.FromEntities(users) pagination := buildPagination(req.Page, req.PageSize, total) h.response.Paginated(c, userResponses, pagination) } // GetStats 获取用户统计 func (h *UserHandler) GetStats(c *gin.Context) { stats, err := h.userService.GetStats(c.Request.Context()) if err != nil { h.logger.Error("Failed to get user stats", zap.Error(err)) h.response.InternalError(c, "Failed to get user statistics") return } h.response.Success(c, stats) } // 私有方法 // getCurrentUserID 获取当前用户ID func (h *UserHandler) getCurrentUserID(c *gin.Context) string { if userID, exists := c.Get("user_id"); exists { if id, ok := userID.(string); ok { return id } } return "" } // parsePageSize 解析页面大小 func (h *UserHandler) parsePageSize(str string, defaultValue int) int { if str == "" { return defaultValue } if size, err := strconv.Atoi(str); err == nil && size > 0 && size <= 100 { return size } return defaultValue } // parsePage 解析页码 func (h *UserHandler) parsePage(str string, defaultValue int) int { if str == "" { return defaultValue } if page, err := strconv.Atoi(str); err == nil && page > 0 { return page } return defaultValue } // buildPagination 构建分页元数据 func buildPagination(page, pageSize int, total int64) interfaces.PaginationMeta { totalPages := int(float64(total) / float64(pageSize)) if float64(total)/float64(pageSize) > float64(totalPages) { totalPages++ } if totalPages < 1 { totalPages = 1 } return interfaces.PaginationMeta{ Page: page, PageSize: pageSize, Total: total, TotalPages: totalPages, HasNext: page < totalPages, HasPrev: page > 1, } }