Files
IUQT/acquaintances/biz/handler/user/user_service.go
2025-08-22 13:47:52 +08:00

364 lines
9.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}