2025-12-19 22:36:48 +08:00
|
|
|
|
package controller
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"ai_xhs/common"
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"ai_xhs/config"
|
2025-12-19 22:36:48 +08:00
|
|
|
|
"ai_xhs/service"
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"ai_xhs/utils"
|
|
|
|
|
|
"context"
|
2025-12-19 22:36:48 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type AuthController struct {
|
|
|
|
|
|
authService *service.AuthService
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewAuthController() *AuthController {
|
|
|
|
|
|
return &AuthController{
|
|
|
|
|
|
authService: service.NewAuthService(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// WechatLogin 微信小程序登录
|
|
|
|
|
|
func (ctrl *AuthController) WechatLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Code string `json:"code" binding:"required"`
|
|
|
|
|
|
Phone string `json:"phone"` // 可选,员工手机号(直接传明文)
|
|
|
|
|
|
PhoneCode string `json:"phone_code"` // 可选,微信手机号加密code
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用登录服务
|
|
|
|
|
|
token, employee, err := ctrl.authService.WechatLogin(req.Code, req.Phone, req.PhoneCode)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户显示名称(优先使用真实姓名,其次用户名)
|
|
|
|
|
|
displayName := employee.RealName
|
|
|
|
|
|
if displayName == "" {
|
|
|
|
|
|
displayName = employee.Username
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "登录成功", gin.H{
|
|
|
|
|
|
"token": token,
|
|
|
|
|
|
"employee": gin.H{
|
|
|
|
|
|
"id": employee.ID,
|
|
|
|
|
|
"name": displayName,
|
|
|
|
|
|
"username": employee.Username,
|
|
|
|
|
|
"real_name": employee.RealName,
|
|
|
|
|
|
"phone": employee.Phone,
|
|
|
|
|
|
"role": employee.Role,
|
|
|
|
|
|
"enterprise_id": employee.EnterpriseID,
|
|
|
|
|
|
"enterprise_name": employee.EnterpriseName,
|
|
|
|
|
|
"is_bound_xhs": employee.IsBoundXHS,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// PhoneLogin 手机号登录(用于测试)
|
|
|
|
|
|
func (ctrl *AuthController) PhoneLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Phone string `json:"phone" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用手机号登录服务
|
|
|
|
|
|
token, employee, err := ctrl.authService.PhoneLogin(req.Phone)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户显示名称(优先使用真实姓名,其次用户名)
|
|
|
|
|
|
displayName := employee.RealName
|
|
|
|
|
|
if displayName == "" {
|
|
|
|
|
|
displayName = employee.Username
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "登录成功", gin.H{
|
|
|
|
|
|
"token": token,
|
|
|
|
|
|
"employee": gin.H{
|
|
|
|
|
|
"id": employee.ID,
|
|
|
|
|
|
"name": displayName,
|
|
|
|
|
|
"username": employee.Username,
|
|
|
|
|
|
"real_name": employee.RealName,
|
|
|
|
|
|
"phone": employee.Phone,
|
|
|
|
|
|
"role": employee.Role,
|
|
|
|
|
|
"enterprise_id": employee.EnterpriseID,
|
|
|
|
|
|
"enterprise_name": employee.EnterpriseName,
|
|
|
|
|
|
"is_bound_xhs": employee.IsBoundXHS,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-01-06 19:36:42 +08:00
|
|
|
|
|
|
|
|
|
|
// PhonePasswordLogin 手机号密码登录
|
|
|
|
|
|
func (ctrl *AuthController) PhonePasswordLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Phone string `json:"phone" binding:"required"`
|
|
|
|
|
|
Password string `json:"password" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用手机号密码登录服务
|
|
|
|
|
|
token, employee, err := ctrl.authService.PhonePasswordLogin(req.Phone, req.Password)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户显示名称(优先使用真实姓名,其次用户名)
|
|
|
|
|
|
displayName := employee.RealName
|
|
|
|
|
|
if displayName == "" {
|
|
|
|
|
|
displayName = employee.Username
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "登录成功", gin.H{
|
|
|
|
|
|
"token": token,
|
|
|
|
|
|
"employee": gin.H{
|
|
|
|
|
|
"id": employee.ID,
|
|
|
|
|
|
"name": displayName,
|
|
|
|
|
|
"username": employee.Username,
|
|
|
|
|
|
"real_name": employee.RealName,
|
|
|
|
|
|
"phone": employee.Phone,
|
|
|
|
|
|
"role": employee.Role,
|
|
|
|
|
|
"enterprise_id": employee.EnterpriseID,
|
|
|
|
|
|
"enterprise_name": employee.EnterpriseName,
|
|
|
|
|
|
"is_bound_xhs": employee.IsBoundXHS,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// XHSPhoneCodeLogin 小红书手机号验证码登录
|
|
|
|
|
|
func (ctrl *AuthController) XHSPhoneCodeLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Phone string `json:"phone" binding:"required"`
|
|
|
|
|
|
Code string `json:"code" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用手机号验证码登录服务
|
|
|
|
|
|
token, employee, err := ctrl.authService.XHSPhoneCodeLogin(req.Phone, req.Code)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户显示名称(优先使用真实姓名,其次用户名)
|
|
|
|
|
|
displayName := employee.RealName
|
|
|
|
|
|
if displayName == "" {
|
|
|
|
|
|
displayName = employee.Username
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "登录成功", gin.H{
|
|
|
|
|
|
"token": token,
|
|
|
|
|
|
"employee": gin.H{
|
|
|
|
|
|
"id": employee.ID,
|
|
|
|
|
|
"name": displayName,
|
|
|
|
|
|
"username": employee.Username,
|
|
|
|
|
|
"real_name": employee.RealName,
|
|
|
|
|
|
"phone": employee.Phone,
|
|
|
|
|
|
"role": employee.Role,
|
|
|
|
|
|
"enterprise_id": employee.EnterpriseID,
|
|
|
|
|
|
"enterprise_name": employee.EnterpriseName,
|
|
|
|
|
|
"is_bound_xhs": employee.IsBoundXHS,
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SendXHSVerificationCode 发送小红书手机号验证码
|
|
|
|
|
|
func (ctrl *AuthController) SendXHSVerificationCode(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Phone string `json:"phone" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 预检查:验证手机号是否存在于user表中
|
|
|
|
|
|
if err := ctrl.authService.CheckPhoneExists(req.Phone); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用短信服务发送验证码
|
|
|
|
|
|
smsService := service.GetSmsService()
|
|
|
|
|
|
code, err := smsService.SendVerificationCode(req.Phone)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeServerError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开发环境返回验证码,生产环境不返回
|
|
|
|
|
|
response := gin.H{
|
|
|
|
|
|
"message": "验证码已发送,5分钟内有效",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if config.AppConfig.Server.Mode == "debug" {
|
|
|
|
|
|
response["code"] = code // 仅开发环境返回
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "验证码已发送", response)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Logout 退出登录(删除Redis中的Token)
|
|
|
|
|
|
func (ctrl *AuthController) Logout(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
// 从Redis删除token
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
if err := utils.RevokeToken(ctx, employeeID); err != nil {
|
|
|
|
|
|
// 即使删除失败也返回成功,因为token有过期时间
|
|
|
|
|
|
common.SuccessWithMessage(c, "退出成功", nil)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "退出成功", nil)
|
|
|
|
|
|
}
|