364 lines
9.2 KiB
Go
364 lines
9.2 KiB
Go
// Code generated by hertz generator.
|
||
|
||
package user
|
||
|
||
import (
|
||
"acquaintances/biz/dal/mysql"
|
||
"acquaintances/biz/model"
|
||
user "acquaintances/biz/model/user"
|
||
"acquaintances/biz/utils"
|
||
"context"
|
||
"fmt"
|
||
"github.com/cloudwego/hertz/pkg/app"
|
||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||
"github.com/cloudwego/hertz/pkg/protocol/consts"
|
||
"log"
|
||
"regexp"
|
||
"strconv"
|
||
"time"
|
||
)
|
||
|
||
// UpdateUser .
|
||
// @router /v1/user/update/ [PUT]
|
||
func UpdateUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.UpdateUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
if err = mysql.UpdatesUser(&req); err != nil {
|
||
hlog.Error(err.Error())
|
||
c.JSON(consts.StatusInternalServerError, &user.CreateUserResponse{Code: user.Code_DBErr, Msg: err.Error()})
|
||
return
|
||
}
|
||
resp := new(user.UpdateUserResponse)
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// DeleteUser .
|
||
// @router /v1/user/delete/ [delete]
|
||
func DeleteUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.DeleteUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
if err = mysql.DeleteUser(req.UserID); err != nil {
|
||
c.JSON(consts.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
resp := new(user.DeleteUserResponse)
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// QueryUser .
|
||
// @router /v1/user/[GET]
|
||
func InfoUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.InfoUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
hlog.Infof("InfoUser(%+v)", req)
|
||
data, err := mysql.InfoUser(req.UserID)
|
||
if err != nil {
|
||
c.JSON(consts.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
resData := new(user.UserInfoReq)
|
||
resData.UserName = data.UserName
|
||
resData.Gender = data.Gender
|
||
resData.Age = int64(data.Age)
|
||
resData.Introduce = data.Introduce
|
||
resData.AvatarImageURL = data.AvatarImageURL
|
||
if data.Birthday != nil {
|
||
resData.Birthday = data.Birthday.String()
|
||
}
|
||
|
||
resData.Area = int64(data.Area)
|
||
resData.Mobile = data.Mobile
|
||
resData.Email = data.UserEmail
|
||
resData.Alias = data.Alias
|
||
resData.Address = data.Address
|
||
resData.UserID = data.UserID
|
||
|
||
resp := new(user.QueryUserResponse)
|
||
resp.UserInfo = resData
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// CreateUser .
|
||
// @router /v1/user/ [POST]
|
||
func CreateUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.CreateUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
userId, err := utils.GetID()
|
||
if err != nil {
|
||
c.JSON(consts.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
if err = mysql.CreateUser([]*model.User{
|
||
{
|
||
UserID: strconv.FormatInt(userId, 10),
|
||
UserName: req.Name,
|
||
Gender: req.Gender,
|
||
Age: uint8(req.Age),
|
||
Mobile: req.Mobile,
|
||
Area: uint8(req.Area),
|
||
UserPassword: req.UserPassword,
|
||
AvatarImageURL: req.AvatarImageURL,
|
||
},
|
||
}); err != nil {
|
||
c.JSON(consts.StatusInternalServerError, &user.CreateUserResponse{Code: user.Code_DBErr, Msg: err.Error()})
|
||
return
|
||
}
|
||
resp := new(user.CreateUserResponse)
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// FindUser .
|
||
// @router /v1/user/find/ [GET]
|
||
func FindUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.FindUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.String(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
data, err := mysql.FindUser(&req.Keyword)
|
||
if err != nil {
|
||
c.JSON(consts.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
resp := new(user.FindUserResponse)
|
||
resp.UserInfo = data
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// LoginUser .
|
||
// @router /v1/user/login/ [POST]
|
||
func LoginUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.LoginUserRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
data, err := mysql.CheckLogin(req.UserName, req.Password, c.ClientIP())
|
||
if err != nil {
|
||
c.JSON(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
resp := new(user.LoginUserResponse)
|
||
resData := new(user.UserInfoReq)
|
||
resData.UserName = data.UserName
|
||
resData.Gender = data.Gender
|
||
resData.Age = int64(data.Age)
|
||
resData.Introduce = data.Introduce
|
||
resData.AvatarImageURL = data.AvatarImageURL
|
||
if data.Birthday != nil {
|
||
resData.Birthday = data.Birthday.String()
|
||
}
|
||
|
||
resData.Area = int64(data.Area)
|
||
resData.Mobile = data.Mobile
|
||
resData.Email = data.UserEmail
|
||
resData.Alias = data.Alias
|
||
resData.Address = data.Address
|
||
resData.UserID = data.UserID
|
||
resp.UserInfo = resData
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// SmsUser 处理用户短信请求(注册、登录等场景的验证码发送)
|
||
// @router /v1/user/sms/ [POST]
|
||
func SmsUser(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.SmsRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.String(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
|
||
// 验证手机号格式
|
||
if !utils.IsValidPhone(req.Phone) {
|
||
c.String(consts.StatusBadRequest, "无效的手机号格式")
|
||
return
|
||
}
|
||
|
||
// 生成6位数字验证码
|
||
code := utils.GenerateVerificationCode()
|
||
|
||
// 根据短信类型处理不同业务逻辑
|
||
var message string
|
||
switch req.Type {
|
||
case model.SmsRegister:
|
||
// 注册场景:检查手机号是否已注册
|
||
exists, err := mysql.CheckPhone(req.Phone)
|
||
if err != nil {
|
||
c.String(consts.StatusInternalServerError, "查询用户信息失败")
|
||
return
|
||
}
|
||
if exists {
|
||
c.String(consts.StatusBadRequest, "该手机号已注册")
|
||
return
|
||
}
|
||
message = fmt.Sprintf("您的注册验证码是:%s,有效期5分钟。", code)
|
||
|
||
case model.SmsLongin:
|
||
// 登录场景:可以不需要检查手机号是否存在
|
||
message = fmt.Sprintf("您的登录验证码是:%s,有效期5分钟。", code)
|
||
|
||
default:
|
||
c.String(consts.StatusBadRequest, "不支持的短信类型")
|
||
return
|
||
}
|
||
|
||
// 存储验证码到缓存(如Redis),设置5分钟过期
|
||
err = storeVerificationCode(req.Phone, req.Type, code, 5*time.Minute)
|
||
if err != nil {
|
||
c.String(consts.StatusInternalServerError, "存储验证码失败")
|
||
return
|
||
}
|
||
|
||
// 调用短信发送服务
|
||
err = utils.SendSms(req.Phone, message)
|
||
if err != nil {
|
||
// 发送失败时删除已存储的验证码
|
||
deleteVerificationCode(req.Phone, req.Type)
|
||
c.String(consts.StatusInternalServerError, "发送短信失败:"+err.Error())
|
||
return
|
||
}
|
||
|
||
resp := &user.SmsResponse{
|
||
Msg: "验证码已发送",
|
||
}
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
func storeVerificationCode(phone, typ, code string, expiration time.Duration) error {
|
||
// TODO实现存储验证码到缓存的逻辑
|
||
return nil
|
||
}
|
||
|
||
func deleteVerificationCode(phone, typ string) error {
|
||
// TODO实现删除验证码的逻辑
|
||
return nil
|
||
}
|
||
|
||
// CheckOtp 校验验证码是否正确
|
||
// @router /v1/user/check_otp/ [POST]
|
||
func CheckOtp(ctx context.Context, c *app.RequestContext) {
|
||
var err error
|
||
var req user.CheckOtpRequest
|
||
err = c.BindAndValidate(&req)
|
||
if err != nil {
|
||
c.String(consts.StatusBadRequest, err.Error())
|
||
return
|
||
}
|
||
|
||
// 验证手机号格式
|
||
if !utils.IsValidPhone(req.Phone) {
|
||
c.String(consts.StatusBadRequest, "无效的手机号格式")
|
||
return
|
||
}
|
||
|
||
// 验证验证码格式(通常是6位数字)
|
||
//if !isValidOtp(req.Otp) {
|
||
// c.String(consts.StatusBadRequest, "验证码格式不正确")
|
||
// return
|
||
//}
|
||
|
||
// 验证验证码类型
|
||
if !isValidOtpType(req.Type) {
|
||
c.String(consts.StatusBadRequest, "不支持的验证码类型")
|
||
return
|
||
}
|
||
|
||
// 从缓存中获取存储的验证码
|
||
//storedOtp, err := getStoredVerificationCode(req.Phone, req.Type)
|
||
//if err != nil {
|
||
// c.String(consts.StatusInternalServerError, "获取验证码信息失败")
|
||
// return
|
||
//}
|
||
|
||
// 检查验证码是否存在(可能已过期或未发送)
|
||
//if storedOtp == "" {
|
||
// c.String(consts.StatusBadRequest, "验证码不存在或已过期")
|
||
// return
|
||
//}
|
||
|
||
// 验证验证码是否匹配
|
||
//if req.Otp != storedOtp {
|
||
// resp := &user.CheckOtpResponse{
|
||
// Code: consts.StatusBadRequest,
|
||
// Msg: "验证码不正确",
|
||
// }
|
||
// c.JSON(consts.StatusOK, resp)
|
||
// return
|
||
//}
|
||
|
||
// 验证码验证成功后,根据类型执行不同业务逻辑
|
||
switch req.Type {
|
||
case model.SmsRegister:
|
||
|
||
case model.SmsLongin:
|
||
|
||
}
|
||
|
||
// 验证成功后删除已使用的验证码,防止重复使用
|
||
err = deleteVerificationCode(req.Phone, req.Type)
|
||
if err != nil {
|
||
// 这里只记录警告,不影响主流程
|
||
log.Printf("删除验证码失败: %v, 手机号: %s, 类型: %s", err, req.Phone, req.Type)
|
||
}
|
||
|
||
resp := &user.CheckOtpResponse{
|
||
Msg: "验证码验证成功",
|
||
}
|
||
|
||
c.JSON(consts.StatusOK, resp)
|
||
}
|
||
|
||
// 辅助函数:验证验证码格式(6位数字)
|
||
func isValidOtp(otp string) bool {
|
||
pattern := `^\d{6}$`
|
||
return regexp.MustCompile(pattern).MatchString(otp)
|
||
}
|
||
|
||
// 辅助函数:验证验证码类型是否合法
|
||
func isValidOtpType(typ string) bool {
|
||
switch typ {
|
||
case model.SmsRegister, model.SmsLongin:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 以下是需要根据实际项目实现的函数
|
||
func getStoredVerificationCode(phone, typ string) (string, error) {
|
||
// 从缓存中获取验证码的逻辑
|
||
// 例如: return redisClient.Get(ctx, getOtpCacheKey(phone, typ)).Result()
|
||
return "", nil
|
||
}
|