用户修改头像、昵称、绑定手机号、获取用户详细信息

This commit is contained in:
chy
2025-06-06 15:48:05 +08:00
parent 01b898163a
commit e40f9987db
12 changed files with 280 additions and 19 deletions

View File

@ -12,4 +12,8 @@ import (
type IUserV1 interface { type IUserV1 interface {
List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error) List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error)
Info(ctx context.Context, req *v1.InfoReq) (res *v1.InfoRes, err error)
Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error)
BindPhone(ctx context.Context, req *v1.BindPhoneReq) (res *v1.BindPhoneRes, err error)
GetPhoneCode(ctx context.Context, req *v1.GetPhoneCodeReq) (res *v1.GetPhoneCodeRes, err error)
} }

View File

@ -11,3 +11,50 @@ type ListRes struct {
List interface{} `json:"list"` List interface{} `json:"list"`
Total int `json:"total"` Total int `json:"total"`
} }
type InfoReq struct {
g.Meta `path:"/user/info" method:"get" tags:"User" summary:"获取用户信息"`
OpenId string `json:"openId" v:"required#OpenId不能为空" dc:"OpenId"`
}
type InfoRes struct {
Id int `json:"id"`
WxOpenId string `json:"wxOpenId"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Email string `json:"email"`
PhoneNumber string `json:"phoneNumber"`
WxPopenId string `json:"wxPopenId"`
QQPopenId string `json:"qqPopenId"`
RoleId int `json:"roleId"`
}
type UpdateReq struct {
g.Meta `path:"/user" method:"put" tags:"User" summary:"更新用户头像,昵称"`
Avatar string `json:"avatar" v:"required#头像不能为空" dc:"头像"`
Nickname string `json:"nickname" v:"required#昵称不能为空" dc:"昵称"`
}
type UpdateRes struct {
Success bool `json:"success" dc:"是否成功"`
}
type BindPhoneReq struct {
g.Meta `path:"/user/bindPhone" method:"post" tags:"User" summary:"绑定手机号"`
Phone string `json:"phone" v:"required#手机号不能为空" dc:"手机号"`
Code string `json:"code" v:"required#验证码不能为空" dc:"验证码"`
}
type BindPhoneRes struct {
Success bool `json:"success" dc:"是否成功"`
}
type GetPhoneCodeReq struct {
g.Meta `path:"/user/getPhoneCode" method:"post" tags:"User" summary:"获取手机验证码"`
Phone string `json:"phone" v:"required#手机号不能为空" dc:"手机号"`
}
type GetPhoneCodeRes struct {
Success bool `json:"success" dc:"是否成功"`
}

View File

@ -12,6 +12,7 @@ import (
"server/internal/controller/rewardType" "server/internal/controller/rewardType"
"server/internal/controller/role" "server/internal/controller/role"
"server/internal/controller/upload" "server/internal/controller/upload"
"server/internal/controller/user"
"server/internal/controller/wx" "server/internal/controller/wx"
"server/internal/middleware" "server/internal/middleware"
) )
@ -40,6 +41,7 @@ var (
merchant.NewV1(), merchant.NewV1(),
rewardType.NewV1(), rewardType.NewV1(),
feedback.NewV1(), feedback.NewV1(),
user.NewV1(),
) )
}) })
}) })

View File

@ -1,13 +1,7 @@
package consts package consts
// Redis key 前缀 // 用户
const ( const (
// 用户相关 UserBindPhoneKey = "user:bindPhone:%d"
UserCode = "user:code:" // 用户验证码 UserCodeExpire = 5 * 60
UserToken = "user:token:" // 用户token
UserInfo = "user:info:" // 用户信息
// 系统相关
SystemConfig = "system:config" // 系统配置
SystemCache = "system:cache:" // 系统缓存
) )

View File

@ -0,0 +1,26 @@
package user
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"server/internal/model"
"server/internal/service"
"server/api/user/v1"
)
func (c *ControllerV1) BindPhone(ctx context.Context, req *v1.BindPhoneReq) (res *v1.BindPhoneRes, err error) {
id := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
out, err := service.User().BindPhone(ctx, &model.UserBindPhoneIn{
PhoneCode: req.Code,
Phone: req.Phone,
Id: id,
})
if err != nil {
return nil, err
}
return &v1.BindPhoneRes{Success: out.Success}, nil
}

View File

@ -0,0 +1,24 @@
package user
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"server/internal/model"
"server/internal/service"
"server/api/user/v1"
)
func (c *ControllerV1) GetPhoneCode(ctx context.Context, req *v1.GetPhoneCodeReq) (res *v1.GetPhoneCodeRes, err error) {
id := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
out, err := service.User().Code(ctx, &model.GetPhoneCodeIn{
Phone: req.Phone,
Id: id,
})
if err != nil {
return nil, err
}
return &v1.GetPhoneCodeRes{Success: out.Success}, nil
}

View File

@ -0,0 +1,35 @@
package user
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"server/internal/model"
"server/internal/service"
"server/api/user/v1"
)
func (c *ControllerV1) Info(ctx context.Context, req *v1.InfoReq) (res *v1.InfoRes, err error) {
id := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
out, err := service.User().Info(ctx, &model.UserInfoIn{
OpenId: req.OpenId,
Id: int(id),
})
if err != nil {
return nil, err
}
return &v1.InfoRes{
Avatar: out.Avatar,
Email: out.Email,
Id: int(out.Id),
Nickname: out.Nickname,
PhoneNumber: out.PhoneNumber,
QQPopenId: out.QQPopenId,
RoleId: int(out.RoleId),
Username: out.Username,
WxOpenId: out.WxOpenId,
WxPopenId: out.WxPopenId,
}, nil
}

View File

@ -0,0 +1,24 @@
package user
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"server/internal/model"
"server/internal/service"
"server/api/user/v1"
)
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
id := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
out, err := service.User().Update(ctx, &model.UserUpdateIn{
Id: id,
Nickname: req.Nickname,
Avatar: req.Avatar,
})
if err != nil {
return nil, err
}
return &v1.UpdateRes{Success: out.Success}, nil
}

View File

@ -2,6 +2,8 @@ package internal
import ( import (
"context" "context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"server/internal/consts" "server/internal/consts"
"server/internal/dao" "server/internal/dao"
"server/internal/model" "server/internal/model"
@ -116,20 +118,82 @@ func (s *sUser) Info(ctx context.Context, in *model.UserInfoIn) (out *model.User
} }
out = &model.UserInfoOut{ out = &model.UserInfoOut{
Id: user.Id, Id: user.Id,
WxOpenId: user.WxOpenId,
Username: user.Username,
Nickname: user.Nickname,
Avatar: user.Avatar,
Email: user.Email,
PhoneNumber: user.PhoneNumber,
WxPopenId: user.WxPopenId,
QQPopenId: user.QqPopenId,
RoleId: user.RoleId,
} }
return return out, nil
} }
func (s *sUser) Code(ctx context.Context, in *model.UserCodeIn) (out *model.UserCodeOut, err error) { func (s *sUser) Code(ctx context.Context, in *model.GetPhoneCodeIn) (out *model.GetPhoneCodeOut, err error) {
return // TODO 短信平台获取验证码
code := "9999"
// 存入 redis
err = g.Redis().SetEX(ctx, fmt.Sprintf(consts.UserBindPhoneKey, in.Id), code, consts.UserCodeExpire)
if err != nil {
return nil, ecode.Fail.Sub("设置验证码失败")
}
return &model.GetPhoneCodeOut{
Success: true,
}, nil
} }
func (s *sUser) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) { func (s *sUser) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) {
return
exist, err := dao.Users.Ctx(ctx).Where(do.Users{Id: in.Id}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("该用户不存在")
}
if !exist {
return nil, ecode.Params.Sub("用户不存在")
}
_, err = dao.Users.Ctx(ctx).Where(do.Users{Id: in.Id}).Update(do.Users{
Nickname: in.Nickname,
Avatar: in.Avatar,
})
if err != nil {
return nil, ecode.Fail.Sub("更新用户信息失败")
}
return &model.UpdateOut{
Success: true,
}, nil
} }
func (s *sUser) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error) { func (s *sUser) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UserBindPhoneOut, err error) {
// 绑定手机号,需要验证入参和缓存中的验证码时候相同 // 绑定手机号,需要验证入参和缓存中的验证码时候相同
return value, err := g.Redis().Get(ctx, fmt.Sprintf(consts.UserBindPhoneKey, in.Id))
if err != nil {
return nil, ecode.Fail.Sub("获取失败")
}
if value.IsEmpty() {
return nil, ecode.Fail.Sub("验证码已过期")
}
if value.String() != in.PhoneCode {
return nil, ecode.Fail.Sub("验证码错误")
}
_, err = dao.Users.Ctx(ctx).Where(do.Users{Id: in.Id}).Update(do.Users{
PhoneNumber: in.Phone,
})
if err != nil {
return nil, ecode.Fail.Sub("绑定手机号失败")
}
return &model.UserBindPhoneOut{
Success: true,
}, nil
} }
func (s *sUser) List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error) { func (s *sUser) List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error) {

View File

@ -74,9 +74,25 @@ type UserInfoIn struct {
} }
type UserInfoOut struct { type UserInfoOut struct {
Id int64 Id int64
WxOpenId string
Username string
Nickname string
Avatar string
Email string
PhoneNumber string
WxPopenId string
QQPopenId string
RoleId int64
} }
type UserBindPhoneIn struct { type UserBindPhoneIn struct {
Id int64
Phone string
PhoneCode string
}
type UserBindPhoneOut struct {
Success bool
} }
type UserListIn struct { type UserListIn struct {
@ -98,3 +114,22 @@ type UserCodeIn struct {
type UserCodeOut struct { type UserCodeOut struct {
} }
type UserUpdateImgIn struct {
Id int64
Nickname string
Avatar string
}
type UserUpdateImgOut struct {
Success bool
}
type GetPhoneCodeIn struct {
Id int64
Phone string
}
type GetPhoneCodeOut struct {
Success bool
}

View File

@ -15,9 +15,9 @@ type (
Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error) Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error)
WeChatLogin(ctx context.Context, in *model.WeChatLogin) (out *model.WeChatLoginOut, err error) WeChatLogin(ctx context.Context, in *model.WeChatLogin) (out *model.WeChatLoginOut, err error)
Info(ctx context.Context, in *model.UserInfoIn) (out *model.UserInfoOut, err error) Info(ctx context.Context, in *model.UserInfoIn) (out *model.UserInfoOut, err error)
Code(ctx context.Context, in *model.UserCodeIn) (out *model.UserCodeOut, err error) Code(ctx context.Context, in *model.GetPhoneCodeIn) (out *model.GetPhoneCodeOut, err error)
Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error)
BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UserBindPhoneOut, err error)
List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error) List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error)
} }
) )

View File

@ -47,6 +47,12 @@ func init() {
// 上传图片 // 上传图片
enforcer.AddPolicy("user", "/x/upload/image", "POST", "上传图片") enforcer.AddPolicy("user", "/x/upload/image", "POST", "上传图片")
//
enforcer.AddPolicy("user", "/x/user", "PUT", "修改个人信息")
enforcer.AddPolicy("user", "/x/user/getPhoneCode", "POST", "获取验证码")
enforcer.AddPolicy("user", "/x/user/bindPhone", "POST", "绑定手机号")
enforcer.AddPolicy("user", "/x/user/info", "GET", "查询用户个人信息")
// 反馈信息 // 反馈信息
enforcer.AddPolicy("user", "/x/feedback", "GET", "获取反馈信息列表") enforcer.AddPolicy("user", "/x/feedback", "GET", "获取反馈信息列表")
enforcer.AddPolicy("user", "/x/feedback", "POST", "添加反馈信息") enforcer.AddPolicy("user", "/x/feedback", "POST", "添加反馈信息")