509 lines
12 KiB
Go
509 lines
12 KiB
Go
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)
|
|
} |