// Package service 业务逻辑层 package service import ( "context" "encoding/json" "errors" "fmt" "log" "time" "server/common" "server/config" "server/modules/system/entity" "server/modules/system/mapper" "github.com/google/uuid" ) const ( TokenPrefix = "login:token:" // Redis中Token前缀 TokenExpire = 24 * time.Hour // Token过期时间 ) type SysUserService struct { mapper *mapper.SysUserMapper } func NewSysUserService() *SysUserService { return &SysUserService{mapper: mapper.NewSysUserMapper()} } // Login 用户登录 // 密码验证方式与 Java JeecgBoot 兼容: PBEWithMD5AndDES(username, password, salt) func (s *SysUserService) Login(username, password string) (*entity.LoginUser, string, error) { // 查询用户 user, err := s.mapper.FindByUsername(username) if err != nil { return nil, "", errors.New("用户不存在") } // 验证状态 if user.Status == 2 { return nil, "", errors.New("账号已被冻结") } // 验证密码 (与Java兼容: encrypt(username, password, salt)) encrypted, err := common.Encrypt(username, password, user.Salt) if (user.Password != encrypted) || (err != nil) { return nil, "", errors.New("用户名或密码错误") } // 生成Token token := s.generateToken() // 构建登录用户信息 loginUser := &entity.LoginUser{ ID: user.ID, Username: user.Username, Realname: user.Realname, Avatar: user.Avatar, Phone: user.Phone, Email: user.Email, Token: token, } // 存储到Redis if err := s.saveLoginUser(token, loginUser); err != nil { return nil, "", errors.New("登录失败,请重试") } return loginUser, token, nil } // Logout 用户登出 func (s *SysUserService) Logout(token string) error { ctx := context.Background() return config.RDB.Del(ctx, TokenPrefix+token).Err() } // GetLoginUser 根据Token获取登录用户信息 func (s *SysUserService) GetLoginUser(token string) (*entity.LoginUser, error) { ctx := context.Background() data, err := config.RDB.Get(ctx, TokenPrefix+token).Result() if err != nil { return nil, errors.New("未登录或登录已过期") } var loginUser entity.LoginUser if err := json.Unmarshal([]byte(data), &loginUser); err != nil { return nil, errors.New("登录信息异常") } // 刷新过期时间 config.RDB.Expire(ctx, TokenPrefix+token, TokenExpire) return &loginUser, nil } // RefreshToken 刷新Token过期时间 func (s *SysUserService) RefreshToken(token string) error { ctx := context.Background() return config.RDB.Expire(ctx, TokenPrefix+token, TokenExpire).Err() } // 保存登录用户到Redis func (s *SysUserService) saveLoginUser(token string, user *entity.LoginUser) error { ctx := context.Background() data, err := json.Marshal(user) if err != nil { return err } return config.RDB.Set(ctx, TokenPrefix+token, data, TokenExpire).Err() } // 生成Token func (s *SysUserService) generateToken() string { return uuid.New().String() } // ========== 用户管理 ========== func (s *SysUserService) List(page, size int) ([]entity.SysUser, int64, error) { return s.mapper.FindAll(page, size) } func (s *SysUserService) GetByID(id string) (*entity.SysUser, error) { return s.mapper.FindByID(id) } func (s *SysUserService) Create(item *entity.SysUser) error { item.ID = uuid.New().String() // 生成盐值 (8字节) item.Salt = uuid.New().String()[:8] // 加密密码 (与Java兼容) encrypted, err := common.Encrypt(item.Username, item.Password, item.Salt) if err != nil { log.Printf("密码加密失败: %v", err) return fmt.Errorf("密码加密失败: %w,请联系管理员", err) // 仍然返回错误 } item.Password = encrypted item.DelFlag = 0 item.Status = 1 now := time.Now() item.CreateTime = &now return s.mapper.Create(item) } func (s *SysUserService) Update(item *entity.SysUser) error { now := time.Now() item.UpdateTime = &now return s.mapper.Update(item) } func (s *SysUserService) UpdateFields(id string, fields map[string]interface{}) error { return s.mapper.UpdateFields(id, fields) } func (s *SysUserService) Delete(id string) error { return s.mapper.Delete(id) } // UpdatePassword 修改密码 func (s *SysUserService) UpdatePassword(id, oldPwd, newPwd string) error { user, err := s.mapper.FindByID(id) if err != nil { return errors.New("用户不存在") } // 验证旧密码 encrypted, err := common.Encrypt(user.Username, oldPwd, user.Salt) if err != nil { log.Printf("密码加密失败: %v", err) return fmt.Errorf("密码加密失败: %w,请联系管理员", err) // 仍然返回错误 } if encrypted != user.Password { return errors.New("原密码错误") } // 生成新密码 newEncrypted, err := common.Encrypt(user.Username, newPwd, user.Salt) if err != nil { log.Printf("密码加密失败: %v", err) return fmt.Errorf("密码加密失败: %w,请联系管理员", err) // 仍然返回错误 } return s.mapper.UpdateFields(id, map[string]interface{}{ "password": newEncrypted, }) }