package handler import ( "dianshang/internal/config" "dianshang/internal/model" "dianshang/internal/repository" "dianshang/internal/service" "dianshang/pkg/response" "dianshang/pkg/utils" "strconv" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // UserHandler 用户处理器 type UserHandler struct { userService *service.UserService wechatService *service.WeChatService } // NewUserHandler 创建用户处理器 func NewUserHandler(db *gorm.DB, cfg *config.Config) *UserHandler { // 创建积分相关服务 pointsRepo := repository.NewPointsRepository(db) pointsService := service.NewPointsService(pointsRepo, db) return &UserHandler{ userService: service.NewUserService(db), wechatService: service.NewWeChatService(db, pointsService, cfg.WeChat.AppID, cfg.WeChat.AppSecret), } } // LoginRequest 登录请求结构 type LoginRequest struct { Code string `json:"code" binding:"required"` } // WeChatLoginRequest 微信登录请求结构 type WeChatLoginRequest struct { Code string `json:"code" binding:"required"` UserInfo *service.WeChatUserInfo `json:"userInfo,omitempty"` } // Login 用户登录(兼容旧版本) func (h *UserHandler) Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } // 获取客户端IP和UserAgent clientIP := utils.GetClientIP( c.ClientIP(), c.GetHeader("X-Forwarded-For"), c.GetHeader("X-Real-IP"), ) userAgent := c.Request.UserAgent() // 调用新的微信登录服务 user, token, err := h.wechatService.Login(req.Code, clientIP, userAgent) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, gin.H{ "user": user, "token": token, }) } // WeChatLogin 微信登录 func (h *UserHandler) WeChatLogin(c *gin.Context) { var req WeChatLoginRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误: "+err.Error()) return } // 验证必要参数 if req.Code == "" { response.BadRequest(c, "微信登录code不能为空") return } // 获取客户端IP和UserAgent clientIP := utils.GetClientIP( c.ClientIP(), c.GetHeader("X-Forwarded-For"), c.GetHeader("X-Real-IP"), ) userAgent := c.Request.UserAgent() var user *model.User var token string var err error if req.UserInfo != nil { // 带用户信息的登录 user, token, err = h.wechatService.LoginWithUserInfo(req.Code, *req.UserInfo, clientIP, userAgent) } else { // 基本登录 user, token, err = h.wechatService.Login(req.Code, clientIP, userAgent) } if err != nil { // 根据错误类型返回不同的错误码 if err.Error() == "用户已被禁用,请联系客服" { response.ErrorWithMessage(c, response.ERROR_USER_DISABLED, err.Error()) } else { response.ErrorWithMessage(c, response.ERROR, err.Error()) } return } // 确保用户信息完整 if user == nil { response.ErrorWithMessage(c, response.ERROR, "用户信息获取失败") return } response.Success(c, gin.H{ "user": user, "token": token, "message": "登录成功", }) } // GetWeChatSession 获取微信会话信息 func (h *UserHandler) GetWeChatSession(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } session, err := h.wechatService.GetUserSession(userID.(uint)) if err != nil { response.ErrorWithMessage(c, response.ERROR, "获取会话信息失败") return } response.Success(c, session) } // RegisterRequest 注册请求结构 type RegisterRequest struct { OpenID string `json:"openid" binding:"required"` Nickname string `json:"nickname"` Avatar string `json:"avatar"` Gender uint8 `json:"gender"` } // Register 用户注册 func (h *UserHandler) Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } user := &model.User{ OpenID: req.OpenID, Nickname: req.Nickname, Avatar: req.Avatar, Gender: int(req.Gender), } if err := h.userService.CreateUser(user); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, user) } // GetProfile 获取用户信息 func (h *UserHandler) GetProfile(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } user, err := h.userService.GetUserByID(userID.(uint)) if err != nil { response.ErrorWithMessage(c, response.ERROR_USER_NOT_FOUND, "用户不存在") return } response.Success(c, user) } // UpdateProfileRequest 更新用户信息请求结构 type UpdateProfileRequest struct { Nickname string `json:"nickname"` Avatar string `json:"avatar"` Gender uint8 `json:"gender"` Phone string `json:"phone"` Email string `json:"email"` } // UpdateProfile 更新用户信息 func (h *UserHandler) UpdateProfile(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } // 获取原始JSON数据来判断哪些字段被明确提供 var rawData map[string]interface{} if err := c.ShouldBindJSON(&rawData); err != nil { response.BadRequest(c, "参数错误") return } // 只更新明确提供的字段 updates := make(map[string]interface{}) // 检查每个字段是否在请求中被明确提供,并转换为正确的类型 if nickname, exists := rawData["nickname"]; exists { if str, ok := nickname.(string); ok { updates["nickname"] = str } } if avatar, exists := rawData["avatar"]; exists { if str, ok := avatar.(string); ok { updates["avatar"] = str } } if gender, exists := rawData["gender"]; exists { if num, ok := gender.(float64); ok { updates["gender"] = uint8(num) } } if phone, exists := rawData["phone"]; exists { if str, ok := phone.(string); ok { updates["phone"] = str } } if email, exists := rawData["email"]; exists { if str, ok := email.(string); ok { updates["email"] = str } } // 如果没有任何字段需要更新,返回成功 if len(updates) == 0 { response.Success(c, nil) return } if err := h.userService.UpdateUser(userID.(uint), updates); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // GetFavorites 获取用户收藏列表 func (h *UserHandler) GetFavorites(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10")) favorites, total, err := h.userService.GetFavorites(userID.(uint), page, limit) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, gin.H{ "list": favorites, "total": total, "page": page, "limit": limit, }) } // AddToFavorite 添加收藏 func (h *UserHandler) AddToFavorite(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } productID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "商品ID无效") return } if err := h.userService.AddToFavorite(userID.(uint), uint(productID)); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // RemoveFromFavorite 取消收藏 func (h *UserHandler) RemoveFromFavorite(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } productID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "商品ID无效") return } if err := h.userService.RemoveFromFavorite(userID.(uint), uint(productID)); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // GetFavoriteStatus 获取收藏状态 func (h *UserHandler) GetFavoriteStatus(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } productID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "商品ID无效") return } isFavorite := h.userService.IsFavorite(userID.(uint), uint(productID)) response.Success(c, gin.H{ "is_favorite": isFavorite, }) } // GetAddresses 获取用户地址列表 func (h *UserHandler) GetAddresses(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } addresses, err := h.userService.GetUserAddresses(userID.(uint)) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, addresses) } // CreateAddressRequest 创建地址请求结构 type CreateAddressRequest struct { Name string `json:"name" binding:"required"` Phone string `json:"phone" binding:"required"` Province string `json:"province" binding:"required"` City string `json:"city" binding:"required"` District string `json:"district" binding:"required"` Detail string `json:"detail" binding:"required"` IsDefault uint8 `json:"is_default"` } // CreateAddress 创建用户地址 func (h *UserHandler) CreateAddress(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } var req CreateAddressRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } address := &model.UserAddress{ UserID: userID.(uint), Name: req.Name, Phone: req.Phone, ProvinceName: req.Province, CityName: req.City, DistrictName: req.District, DetailAddress: req.Detail, IsDefault: req.IsDefault == 1, } if err := h.userService.CreateAddress(address); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, address) } // UpdateAddress 更新用户地址 func (h *UserHandler) UpdateAddress(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } addressID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "地址ID无效") return } var req CreateAddressRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误") return } updates := map[string]interface{}{ "name": req.Name, "phone": req.Phone, "province_name": req.Province, "city_name": req.City, "district_name": req.District, "detail_address": req.Detail, "is_default": req.IsDefault, } if err := h.userService.UpdateAddress(userID.(uint), uint(addressID), updates); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } // 获取更新后的地址数据并返回 updatedAddress := &model.UserAddress{ ID: uint(addressID), UserID: userID.(uint), Name: req.Name, Phone: req.Phone, ProvinceName: req.Province, CityName: req.City, DistrictName: req.District, DetailAddress: req.Detail, IsDefault: req.IsDefault == 1, } response.Success(c, updatedAddress) } // DeleteAddress 删除用户地址 func (h *UserHandler) DeleteAddress(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } addressID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "地址ID无效") return } if err := h.userService.DeleteAddress(userID.(uint), uint(addressID)); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // SetDefaultAddress 设置默认地址 func (h *UserHandler) SetDefaultAddress(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } addressID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { response.BadRequest(c, "地址ID无效") return } if err := h.userService.SetDefaultAddress(userID.(uint), uint(addressID)); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) }