package service import ( "ego/internal/model" "ego/internal/serializer" "ego/internal/types" "ego/internal/util" "ego/pkg/logger" "fmt" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) const ( // PassWordCost 密码加密难度 PassWordCost = 12 // Suspend 被封禁用户 Suspend = "-1" // Active 未激活用户 Active = "1" // Inactive 激活用户 Inactive = "0" ) // SysUserService 管理用户登录的服务 type SysUserService struct { Db *gorm.DB } // NewSysUserService 构建用户登录服务 func NewSysUserService(db *gorm.DB) *SysUserService { return &SysUserService{ Db: db, } } type UserLoginRequest struct { Account string `form:"account" json:"account" binding:"required,min=5,max=30"` PassWord string `form:"password" json:"password" binding:"required,min=8,max=40"` Checked *bool `form:"checked" json:"checked" binding:"required"` Phone string `form:"phone" json:"phone"` VerifyCode string `form:"verifyCode" json:"verifyCode"` } // UserRegisterRequest 用户注册表单验证 type UserRegisterRequest struct { NickName string `form:"nickName" json:"nickName" binding:"required,min=2,max=30"` UserName string `form:"userName" json:"userName" binding:"required,min=5,max=30"` PassWord string `form:"passWord" json:"passWord" binding:"required,min=8,max=40"` PasswordConfirm string `form:"passWordConfirm" json:"passWordConfirm" binding:"required,min=8,max=40"` } // Login 用户登录函数 func (s *SysUserService) Login(c *gin.Context) serializer.Response { var user model.SysUser u := UserLoginRequest{} if err := c.ShouldBind(&u); err != nil { logger.Error(c, "参数绑定错误!", zap.Error(err)) c.Set("msg", "参数绑定错误!") return serializer.Err(serializer.CodeParamErr, "参数绑定错误!", err) } c.Set("account", u.Account) if err := s.Db.Where("user_name = ?", u.Account).First(&user).Error; err != nil { logger.Error(c, "账号或密码错误!") c.Set("msg", "账号或密码错误!") return serializer.ParamErr("账号或密码错误!", nil) } if user.Status == Suspend { logger.Error(c, "账号已封禁!") c.Set("msg", "账号已封禁!") return serializer.ParamErr("账号已封禁!", nil) } if user.Status == Inactive { logger.Error(c, "账号未激活!") c.Set("msg", "账号未激活!") return serializer.ParamErr("账号未激活!", nil) } if !CheckPassWord(u.PassWord, user.PassWord) { logger.Error(c, "账号或密码错误!") c.Set("msg", "账号或密码错误!") return serializer.ParamErr("账号或密码错误!", nil) } if token, err := util.GenerateToken(user.UserId, user.UserName); err == nil { logger.Info(c, "用户登录", zap.String("redisKey", util.TokenGroup+user.UserName)) // 删除key del := util.Del(c, util.TokenGroup+user.UserName) if del != nil { logger.Error(c, "redis 删除失败!", zap.Error(del)) c.Set("msg", "redis 删除失败!") return serializer.ParamErr("系统繁忙稍后重试!", nil) } // 结果放入redis set := util.Set(c, util.TokenGroup+user.UserName, token, time.Hour*24) if set != nil { logger.Error(c, "redis 放入失败!", zap.Error(set)) c.Set("msg", "redis 放入失败!") return serializer.ParamErr("系统繁忙稍后重试!", nil) } c.Set("status", Active) return types.BuildUserResponseHasToken(user, token) } return serializer.ParamErr("系统繁忙稍后重试!", nil) } // UserLogout 退出登录 func (s *SysUserService) UserLogout(c *gin.Context) serializer.Response { // 退出登录 go func() { tokenString := c.GetHeader("Authorization") token, err := util.ParseToken(tokenString[8:]) if err == nil { username := token["username"].(string) // 删除key if err := util.Del(c, util.TokenGroup+username); err != nil { logger.Error(c, "退出登录失败!", zap.Error(err)) } else { logger.Info(c, "用户退出登录成功!", zap.String("redisKey", util.TokenGroup+username)) } } }() return serializer.Succ("退出登录成功!", true) } // GetUser 用ID获取用户 func GetUser(id string, d *gorm.DB) (model.SysUser, error) { var user model.SysUser result := d.Where("user_id = ?", id).First(&user) if result.Error == nil { user.PassWord = "" // 清除密码 } return user, result.Error } // SetPassWord 设置密码 func SetPassWord(passWord string, sysUser *model.SysUser) error { bytes, err := bcrypt.GenerateFromPassword([]byte(passWord), PassWordCost) if err != nil { return err } sysUser.PassWord = string(bytes) return nil } // CheckPassWord 校验密码 func CheckPassWord(password string, passwordDigest string) bool { err := bcrypt.CompareHashAndPassword([]byte(passwordDigest), []byte(password)) return err == nil } // valid 验证表单 func (s *SysUserService) valid(u *UserRegisterRequest) *serializer.Response { if u.PasswordConfirm != u.PassWord { return &serializer.Response{ Code: 40001, Msg: "两次输入的密码不相同", } } count := int64(0) s.Db.Model(&model.SysUser{}).Where("nick_name = ?", u.NickName).Count(&count) if count > 0 { return &serializer.Response{ Code: 40001, Msg: "昵称被占用", } } count = 0 s.Db.Model(&model.SysUser{}).Where("user_name = ?", u.UserName).Count(&count) if count > 0 { return &serializer.Response{ Code: 40001, Msg: "用户名已经注册", } } return nil } // Register 用户注册 func (s *SysUserService) Register(c *gin.Context) serializer.Response { u := UserRegisterRequest{} if err := c.ShouldBind(&u); err != nil { return serializer.Err(serializer.CodeParamErr, "参数绑定错误!", err) } now := time.Now() user := model.SysUser{ NickName: u.NickName, UserName: u.UserName, Status: Active, CreateTime: &now, } // 生成ID if id, err := SysSequenceServiceBuilder(user.TableName()).GenerateId(); err == nil { user.UserId = id } else { return serializer.DBErr("序列生成失败!", err) } // 表单验证 if err := s.valid(&u); err != nil { logger.Error(c, err.Msg, zap.String("NickName", u.NickName), zap.String("UserName", u.UserName)) return *err } // 密码加密 if err := SetPassWord(u.PassWord, &user); err != nil { logger.Error(c, "密码加密失败!") return serializer.Err(serializer.CodeEncryptError, "密码加密失败!", err) } // 使用事务封装数据库操作 err := s.Db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(&user).Error; err != nil { return err } return nil }) if err != nil { logger.Error(c, "注册失败!") return serializer.ParamErr("注册失败", err) } return types.BuildUserResponse(user) } // Create 创建用户 func (s *SysUserService) Create(c *gin.Context) serializer.Response { var user model.SysUser if err := c.ShouldBind(&user); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } if user.Status == "" { user.Status = Active } now := time.Now() user.CreateTime = &now createBy := c.GetString("id") user.CreateBy = createBy id, err := SysSequenceServiceBuilder(user.TableName()).GenerateId() if err != nil { return serializer.DBErr("创建用户失败!", err) } user.UserId = id if err := s.Db.Create(&user).Error; err != nil { logger.Error(c, "创建用户失败!") return serializer.DBErr("创建用户失败!", err) } return serializer.Succ("创建用户成功!", user) } // DeleteByID 根据ID删除用户 func (s *SysUserService) DeleteByID(c *gin.Context) serializer.Response { id := c.Param("id") if id == "" { logger.Error(c, "id 不可为空!") } // 删除逻辑 data := map[string]any{ "del_flag": "1", "update_time": time.Now(), "update_by": c.GetString("id"), } var user model.SysUser if err := s.Db.Model(&user).Where("user_id = ?", id).Updates(data).Error; err != nil { logger.Error(c, "未查询用户信息!") return serializer.DBErr("删除用户失败!", err) } return serializer.Succ("删除用户成功!", user) } // UpdateByID 根据ID更新用户 func (s *SysUserService) UpdateByID(c *gin.Context) serializer.Response { var user model.SysUser if err := c.ShouldBind(&user); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } id := user.UserId if id == "" { logger.Error(c, "id 不可为空!") return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空")) } if err := s.Db.Model(&user).Where("user_id = ?", id).Updates(&user).Error; err != nil { logger.Error(c, "更新用户信息失败!") return serializer.DBErr("更新用户信息失败!", err) } return serializer.Succ("更新用户信息成功!", user) } // GetByID 根据ID获取用户 func (s *SysUserService) GetByID(c *gin.Context) serializer.Response { var user model.SysUser if err := s.Db.Where("user_id = ?", c.Param("id")).First(&user).Error; err != nil { logger.Error(c, "获取用户信息失败!") return serializer.DBErr("获取用户信息失败!", err) } user.PassWord = "" // 清除密码 return serializer.Succ("查询成功!", user) } // DeleteByIDs 批量删除用户 func (s *SysUserService) DeleteByIDs(c *gin.Context) serializer.Response { var ids types.Payload if err := c.ShouldBind(&ids); err != nil { return serializer.ParamErr("参数绑定失败!", err) } // 删除逻辑 data := map[string]any{ "del_flag": "1", "update_time": time.Now(), "update_by": c.GetString("id"), } if err := s.Db.Model(&model.SysUser{}).Where("user_id in (?)", ids.Ids).Updates(data).Error; err != nil { logger.Error(c, "批量删除用户失败!") return serializer.DBErr("批量删除用户失败!", err) } return serializer.Succ("批量删除用户成功!", nil) } // GetByCondition 条件查询用户 func (s *SysUserService) GetByCondition(c *gin.Context) serializer.Response { var p types.Params if err := c.ShouldBind(&p); err != nil { return serializer.ParamErr("参数绑定失败!", err) } queryStr, args, err := p.ConvertToGormConditions() if err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } var total int64 var users []model.SysUser offset := (p.Page - 1) * p.Limit // 构建基础查询 db := s.Db.Model(&model.SysUser{}) // 如果有查询条件,添加条件 if queryStr != "" { db = db.Where(queryStr, args...) } // 排序 if p.Sort != "" { db = db.Order(p.Sort) } // 执行分页查询 if err := db.Where("del_flag = ?", "0").Offset(offset).Limit(p.Limit).Find(&users).Error; err != nil { logger.Error(c, "获取用户信息失败!") return serializer.DBErr("获取用户信息失败!", err) } // 清除所有用户的密码 for i := range users { users[i].PassWord = "" } // 执行总数查询 if err := db.Where("del_flag = ?", "0").Count(&total).Error; err != nil { logger.Error(c, "获取用户总数失败!") return serializer.DBErr("获取用户总数失败!", err) } return serializer.Succ("查询成功!", gin.H{ "total": total, "items": users, "page": p.Page, "limit": p.Limit, }) } // ListByIDs 根据ID列表获取用户 func (s *SysUserService) ListByIDs(c *gin.Context) serializer.Response { var ids types.Payload if err := c.ShouldBind(&ids); err != nil { return serializer.ParamErr("参数绑定失败!", err) } var users []model.SysUser if err := s.Db.Where("user_id in (?)", ids.Ids).Find(&users).Error; err != nil { logger.Error(c, "获取用户信息失败!") return serializer.DBErr("获取用户信息失败!", err) } // 清除所有用户的密码 for i := range users { users[i].PassWord = "" } return serializer.Succ("查询成功!", users) } // CurrentUser 获取当前用户 func (s *SysUserService) CurrentUser(c *gin.Context) (*model.SysUser, error) { tokenString := c.GetHeader("Authorization") var user model.SysUser token, err := util.ParseToken(tokenString[8:]) if err != nil { return nil, fmt.Errorf("获取当前用户失败! %v", err) } id := token["id"].(string) if err := s.Db.Model(&user).Where("user_id = ?", id).First(&user).Error; err != nil { logger.Error(c, "获取当前用户失败!", zap.Error(err)) return nil, err } // 清除密码 user.PassWord = "" return &user, nil }