Initial commit
This commit is contained in:
509
server/internal/handler/user.go
Normal file
509
server/internal/handler/user.go
Normal file
@@ -0,0 +1,509 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user