This commit is contained in:
solosw
2026-01-05 14:11:34 +08:00
parent 35ef825371
commit 99b11b04e4
658 changed files with 99266 additions and 0 deletions
+372
View File
@@ -0,0 +1,372 @@
package handlers
import (
"awesomeProject/internal/common"
"awesomeProject/internal/models"
"awesomeProject/internal/services"
jwtutil "awesomeProject/pkg/utils"
"crypto/md5"
"fmt"
"github.com/google/uuid"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// AuthHandler 认证处理器
type AuthHandler struct{}
// LoginRequest 登录请求结构
type LoginRequest struct {
Phone string `json:"phone" binding:"required"`
Password string `json:"password" binding:"required"`
}
// LoginResponse 登录响应结构
type LoginResponse struct {
Token string `json:"token"`
User models.User `json:"user"`
}
type TokenGen struct {
UserID uint `json:"user_id"`
Phone string `json:"phone"`
SystemRole int8 `json:"system_role"`
}
// Login 用户登录
func (h *AuthHandler) Login(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 查询用户
var user models.User
err := common.GetDB().Where("phone = ?", req.Phone).First(&user).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusOK, common.Error(401, "手机号或密码错误"))
} else {
c.JSON(http.StatusOK, common.Error(500, "登录失败"))
}
return
}
// 验证密码(这里简单使用MD5,实际应该使用bcrypt)
hashedPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.Password)))
fmt.Println(hashedPassword)
if user.Password != hashedPassword {
c.JSON(http.StatusOK, common.Error(404, "手机号或密码错误"))
return
}
// 检查用户状态
if user.Status != 1 {
c.JSON(http.StatusOK, common.Error(404, "用户已被禁用,请联系管理员"))
return
}
// 生成JWT token
claims := TokenGen{
UserID: user.ID,
Phone: user.Phone,
SystemRole: int8(user.SystemRole),
}
token, err := jwtutil.GenerateToken(claims)
if err != nil {
c.JSON(http.StatusOK, common.Error(500, "生成token失败"))
return
}
// 返回登录结果
response := LoginResponse{
Token: token,
User: user,
}
c.JSON(http.StatusOK, common.Success(response))
}
// RegisterRequest 注册请求结构体
type RegisterRequest struct {
models.User
SMSCode string `json:"sms_code"` // 短信验证码
}
// Register 用户注册
func (h *AuthHandler) Register(c *gin.Context) {
var req RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 验证短信验证码(必填)
if req.SMSCode == "" {
c.JSON(http.StatusOK, common.Error(400, "请输入短信验证码"))
return
}
// 验证短信验证码
smsService := services.GetSMSService()
if !smsService.VerifyCode(req.Phone, req.SMSCode) {
c.JSON(http.StatusOK, common.Error(400, "短信验证码错误或已过期"))
return
}
// 检查手机号是否已存在
var existUser models.User
if err := common.GetDB().Where("phone = ?", req.Phone).First(&existUser).Error; err == nil {
c.JSON(http.StatusOK, common.Error(400, "手机号已被注册"))
return
}
user := req.User
// 生成身份码(简单实现,实际应该使用更复杂的算法)
user.IdentityCode = fmt.Sprintf("U%v", uuid.New().String()[:8])
// 密码加密(这里简单使用MD5,实际应该使用bcrypt)
hashedPassword := fmt.Sprintf("%x", md5.Sum([]byte(user.Password)))
user.Password = hashedPassword
// 默认为普通用户
if user.SystemRole == 0 {
user.SystemRole = 2
}
user.Status = 0
// 保存用户
if err := common.GetDB().Create(&user).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "注册失败"))
return
}
common.GetDB().Model(&user).Update("status", 0)
c.JSON(http.StatusOK, common.Success(user))
}
// GetCurrentUser 获取当前用户信息
func (h *AuthHandler) GetCurrentUser(c *gin.Context) {
// 从token中获取用户信息
tokenMap, exists := c.Get("tokenMap")
if !exists {
c.JSON(http.StatusOK, common.Error(401, "未授权访问"))
return
}
claims := tokenMap.(map[string]interface{})
userIDFloat, ok := claims["user_id"].(float64)
if !ok {
c.JSON(http.StatusOK, common.Error(401, "用户信息无效"))
return
}
userID := uint(userIDFloat)
// 查询用户信息
var user models.User
if err := common.GetDB().First(&user, userID).Error; err != nil {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
return
}
c.JSON(http.StatusOK, common.Success(user))
}
// UpdateProfileRequest 更新个人信息请求结构体
type UpdateProfileRequest struct {
CustomerName string `json:"customer_name" binding:"required"`
RealName string `json:"real_name" binding:"required"`
Avatar string `json:"avatar"`
CompanyName string `json:"company_name"`
PersonalIntro string `json:"personal_intro"`
BusinessLicense string `json:"business_license"`
IDCardFront string `json:"id_card_front"`
IDCardBack string `json:"id_card_back"`
MainPaymentCode string `json:"main_payment_code"`
BackupPaymentCode string `json:"backup_payment_code"`
Phone string `json:"phone"`
}
// UpdateProfile 更新个人信息
func (h *AuthHandler) UpdateProfile(c *gin.Context) {
// 从token中获取用户信息
tokenMap, exists := c.Get("tokenMap")
if !exists {
c.JSON(http.StatusOK, common.Error(401, "未授权访问"))
return
}
claims := tokenMap.(map[string]interface{})
userIDFloat, ok := claims["user_id"].(float64)
if !ok {
c.JSON(http.StatusOK, common.Error(401, "用户信息无效"))
return
}
userID := uint(userIDFloat)
var req UpdateProfileRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 查询当前用户
var user models.User
if err := common.GetDB().First(&user, userID).Error; err != nil {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
return
}
// 更新用户信息
updateData := models.User{
CustomerName: req.CustomerName,
RealName: req.RealName,
Avatar: req.Avatar,
CompanyName: req.CompanyName,
PersonalIntro: req.PersonalIntro,
BusinessLicenseImage: req.BusinessLicense,
IdCardFrontImage: req.IDCardFront,
IdCardBackImage: req.IDCardBack,
MainPaymentQrImage: &req.MainPaymentCode,
SubPaymentQrImage: &req.BackupPaymentCode,
Phone: req.Phone,
}
updateData.ID = userID
if err := common.GetDB().Model(&user).Updates(&updateData).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "更新个人信息失败"))
return
}
// 返回更新后的用户信息
var updatedUser models.User
common.GetDB().First(&updatedUser, userID)
c.JSON(http.StatusOK, common.Success(updatedUser))
}
// ChangePasswordRequest 修改密码请求结构体
type ChangePasswordRequest struct {
CurrentPassword string `json:"current_password" binding:"required"`
NewPassword string `json:"new_password" binding:"required"`
}
// ChangePassword 修改密码
func (h *AuthHandler) ChangePassword(c *gin.Context) {
// 从token中获取用户信息
tokenMap, exists := c.Get("tokenMap")
if !exists {
c.JSON(http.StatusOK, common.Error(401, "未授权访问"))
return
}
claims := tokenMap.(map[string]interface{})
userIDFloat, ok := claims["user_id"].(float64)
if !ok {
c.JSON(http.StatusOK, common.Error(401, "用户信息无效"))
return
}
userID := uint(userIDFloat)
var req ChangePasswordRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 查询当前用户
var user models.User
if err := common.GetDB().First(&user, userID).Error; err != nil {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
return
}
// 验证当前密码
hashedCurrentPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.CurrentPassword)))
if hashedCurrentPassword != user.Password {
c.JSON(http.StatusOK, common.Error(400, "当前密码错误"))
return
}
// 加密新密码
hashedNewPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.NewPassword)))
// 更新密码
if err := common.GetDB().Model(&user).Update("password", hashedNewPassword).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "修改密码失败"))
return
}
c.JSON(http.StatusOK, common.Success(nil))
}
// SendSMSRequest 发送短信验证码请求结构体
type SendSMSRequest struct {
Phone string `json:"phone" binding:"required"`
}
// SendSMS 发送短信验证码
func (h *AuthHandler) SendSMS(c *gin.Context) {
var req SendSMSRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 获取客户端IP地址
clientIP := getClientIP(c)
// 调用短信服务发送验证码
smsService := services.GetSMSService()
code, err := smsService.SendSMS(req.Phone, clientIP)
if err != nil {
c.JSON(http.StatusOK, common.Error(400, err.Error()))
return
}
// 根据环境决定是否返回验证码(开发环境返回,生产环境不返回)
config := common.MineConfig
response := map[string]interface{}{
"message": "验证码已发送",
}
// 仅在开发环境返回验证码,方便测试
if config != nil && config.App.Env == "development" {
response["code"] = code
}
c.JSON(http.StatusOK, common.Success(response))
}
// getClientIP 获取客户端真实IP地址
func getClientIP(c *gin.Context) string {
// 优先从 X-Forwarded-For 获取(经过代理时)
ip := c.GetHeader("X-Forwarded-For")
if ip != "" {
// X-Forwarded-For 可能包含多个IP,取第一个
ips := strings.Split(ip, ",")
if len(ips) > 0 {
return strings.TrimSpace(ips[0])
}
}
// 从 X-Real-IP 获取
ip = c.GetHeader("X-Real-IP")
if ip != "" {
return strings.TrimSpace(ip)
}
// 最后从 RemoteAddr 获取
ip = c.ClientIP()
return ip
}