package handler import ( "carrotskin/internal/container" "carrotskin/internal/service" "carrotskin/internal/types" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // UserHandler 用户处理器(依赖注入版本) type UserHandler struct { container *container.Container logger *zap.Logger } // NewUserHandler 创建UserHandler实例 func NewUserHandler(c *container.Container) *UserHandler { return &UserHandler{ container: c, logger: c.Logger, } } // GetProfile 获取用户信息 func (h *UserHandler) GetProfile(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } user, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || user == nil { h.logger.Error("获取用户信息失败", zap.Int64("user_id", userID), zap.Error(err), ) RespondNotFound(c, "用户不存在") return } RespondSuccess(c, UserToUserInfo(user)) } // UpdateProfile 更新用户信息 func (h *UserHandler) UpdateProfile(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } var req types.UpdateUserRequest if err := c.ShouldBindJSON(&req); err != nil { RespondBadRequest(c, "请求参数错误", err) return } user, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || user == nil { RespondNotFound(c, "用户不存在") return } // 处理密码修改 if req.NewPassword != "" { if req.OldPassword == "" { RespondBadRequest(c, "修改密码需要提供原密码", nil) return } if err := h.container.UserService.ChangePassword(c.Request.Context(), userID, req.OldPassword, req.NewPassword); err != nil { h.logger.Error("修改密码失败", zap.Int64("user_id", userID), zap.Error(err)) RespondBadRequest(c, err.Error(), nil) return } h.logger.Info("用户修改密码成功", zap.Int64("user_id", userID)) } // 更新头像 if req.Avatar != "" { if err := h.container.UserService.ValidateAvatarURL(c.Request.Context(), req.Avatar); err != nil { RespondBadRequest(c, err.Error(), nil) return } user.Avatar = req.Avatar if err := h.container.UserService.UpdateInfo(c.Request.Context(), user); err != nil { h.logger.Error("更新用户信息失败", zap.Int64("user_id", user.ID), zap.Error(err)) RespondServerError(c, "更新失败", err) return } } // 重新获取更新后的用户信息 updatedUser, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || updatedUser == nil { RespondNotFound(c, "用户不存在") return } RespondSuccess(c, UserToUserInfo(updatedUser)) } // UploadAvatar 直接上传头像文件 func (h *UserHandler) UploadAvatar(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } // 解析multipart表单 if err := c.Request.ParseMultipartForm(10 << 20); err != nil { // 10MB RespondBadRequest(c, "解析表单失败", err) return } // 获取文件 file, err := c.FormFile("file") if err != nil { RespondBadRequest(c, "获取文件失败", err) return } // 读取文件内容 src, err := file.Open() if err != nil { RespondBadRequest(c, "打开文件失败", err) return } defer src.Close() fileData := make([]byte, file.Size) if _, err := src.Read(fileData); err != nil { RespondBadRequest(c, "读取文件失败", err) return } // 调用服务上传头像 avatarURL, err := h.container.UserService.UploadAvatar(c.Request.Context(), userID, fileData, file.Filename) if err != nil { h.logger.Error("上传头像失败", zap.Int64("user_id", userID), zap.String("file_name", file.Filename), zap.Error(err), ) RespondBadRequest(c, err.Error(), nil) return } // 获取更新后的用户信息 user, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || user == nil { RespondNotFound(c, "用户不存在") return } RespondSuccess(c, gin.H{ "avatar_url": avatarURL, "user": UserToUserInfo(user), }) } // UpdateAvatar 更新头像URL(保留用于外部URL) func (h *UserHandler) UpdateAvatar(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } avatarURL := c.Query("avatar_url") if avatarURL == "" { RespondBadRequest(c, "头像URL不能为空", nil) return } if err := h.container.UserService.ValidateAvatarURL(c.Request.Context(), avatarURL); err != nil { RespondBadRequest(c, err.Error(), nil) return } if err := h.container.UserService.UpdateAvatar(c.Request.Context(), userID, avatarURL); err != nil { h.logger.Error("更新头像失败", zap.Int64("user_id", userID), zap.String("avatar_url", avatarURL), zap.Error(err), ) RespondServerError(c, "更新头像失败", err) return } user, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || user == nil { RespondNotFound(c, "用户不存在") return } RespondSuccess(c, UserToUserInfo(user)) } // ChangeEmail 更换邮箱 func (h *UserHandler) ChangeEmail(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } var req types.ChangeEmailRequest if err := c.ShouldBindJSON(&req); err != nil { RespondBadRequest(c, "请求参数错误", err) return } if err := h.container.VerificationService.VerifyCode(c.Request.Context(), req.NewEmail, req.VerificationCode, service.VerificationTypeChangeEmail); err != nil { h.logger.Warn("验证码验证失败", zap.String("new_email", req.NewEmail), zap.Error(err)) RespondBadRequest(c, err.Error(), nil) return } if err := h.container.UserService.ChangeEmail(c.Request.Context(), userID, req.NewEmail); err != nil { h.logger.Error("更换邮箱失败", zap.Int64("user_id", userID), zap.String("new_email", req.NewEmail), zap.Error(err), ) RespondBadRequest(c, err.Error(), nil) return } user, err := h.container.UserService.GetByID(c.Request.Context(), userID) if err != nil || user == nil { RespondNotFound(c, "用户不存在") return } RespondSuccess(c, UserToUserInfo(user)) } // ResetYggdrasilPassword 重置Yggdrasil密码 func (h *UserHandler) ResetYggdrasilPassword(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } newPassword, err := h.container.YggdrasilService.ResetYggdrasilPassword(c.Request.Context(), userID) if err != nil { h.logger.Error("重置Yggdrasil密码失败", zap.Error(err), zap.Int64("userId", userID)) RespondServerError(c, "重置Yggdrasil密码失败", nil) return } h.logger.Info("Yggdrasil密码重置成功", zap.Int64("userId", userID)) RespondSuccess(c, gin.H{"password": newPassword}) }