golang-yitisheng-server/server/modules/system/service/sys_user_service.go

324 lines
8.1 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.

// Package service 业务逻辑层
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"time"
"server/common"
"server/config"
"server/modules/system/dto"
"server/modules/system/entity"
"server/modules/system/mapper"
"server/modules/system/vo"
"github.com/google/uuid"
)
type SysUserService struct {
*common.BaseService[entity.SysUser]
mapper *mapper.SysUserMapper
}
func NewSysUserService() *SysUserService {
mapper := mapper.NewSysUserMapper()
return &SysUserService{
BaseService: common.NewBaseService[entity.SysUser](),
mapper: mapper,
}
}
// CreateUser 创建用户并返回 VO
func (s *SysUserService) CreateUser(req *dto.CreateUserRequest, createBy string) (*vo.SysUserVO, error) {
// DTO 转 Entity
entityItem := &entity.SysUser{
Username: req.Username,
Realname: req.Realname,
Password: req.Password,
Email: req.Email,
Phone: req.Phone,
Avatar: req.Avatar,
Sex: 0, // 默认值
OrgCode: req.OrgCode,
DelFlag: 0,
Status: 1,
CreateBy: createBy,
}
if req.Sex != nil {
entityItem.Sex = *req.Sex
}
if req.Birthday != "" {
birthday, err := time.Parse("2006-01-02", req.Birthday)
if err == nil {
entityItem.Birthday = &birthday
}
}
// 保存到数据库
if err := s.Create(entityItem); err != nil {
return nil, err
}
// Entity 转 VO
return s.convertToVO(*entityItem), nil
}
// UpdateUser 更新用户并返回 VO
func (s *SysUserService) UpdateUser(id string, req *dto.UpdateUserRequest) (*vo.SysUserVO, error) {
// 获取原数据
entityItem, err := s.GetByID(id)
if err != nil {
return nil, fmt.Errorf("用户不存在: %w", err)
}
// 更新字段
updateFields := make(map[string]interface{})
if req.Realname != "" {
updateFields["realname"] = req.Realname
}
if req.Email != "" {
updateFields["email"] = req.Email
}
if req.Phone != "" {
updateFields["phone"] = req.Phone
}
if req.Avatar != "" {
updateFields["avatar"] = req.Avatar
}
if req.Sex != nil {
updateFields["sex"] = *req.Sex
}
if req.Status != nil {
updateFields["status"] = *req.Status
}
if req.OrgCode != "" {
updateFields["org_code"] = req.OrgCode
}
if req.Birthday != "" {
birthday, err := time.Parse("2006-01-02", req.Birthday)
if err == nil {
updateFields["birthday"] = birthday
}
}
if err := s.mapper.UpdateFields(id, updateFields); err != nil {
return nil, fmt.Errorf("更新用户失败: %w", err)
}
// 重新获取更新后的数据
entityItem, err = s.GetByID(id)
if err != nil {
return nil, fmt.Errorf("获取更新后数据失败: %w", err)
}
return s.convertToVO(*entityItem), nil
}
// GetUserByID 获取用户并返回 VO
func (s *SysUserService) GetUserByID(id string) (*vo.SysUserVO, error) {
entityItem, err := s.GetByID(id)
if err != nil {
return nil, err
}
return s.convertToVO(*entityItem), nil
}
// ListUsers 获取用户列表并返回 VO 列表
func (s *SysUserService) ListUsers(page, size int) ([]vo.SysUserVO, int64, error) {
entities, total, err := s.List(page, size)
if err != nil {
return nil, 0, err
}
// 批量转换 Entity 到 VO
vos := make([]vo.SysUserVO, len(entities))
for i := range entities {
vos[i] = *s.convertToVO(entities[i])
}
return vos, total, nil
}
// Login 用户登录(手机号登录)
func (s *SysUserService) Login(username, password string) (*entity.LoginUser, string, error) {
user, err := s.mapper.FindByPhone(username)
if err != nil {
return nil, "", errors.New("用户不存在")
}
if user.Status == 2 {
return nil, "", errors.New("账号已被冻结")
}
encrypted, err := common.Encrypt(user.Username, password, user.Salt)
if (user.Password != encrypted) || (err != nil) {
return nil, "", errors.New("用户名或密码错误")
}
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,
}
if err := s.saveLoginUser(token, loginUser); err != nil {
return nil, "", errors.New("登录失败,请重试")
}
return loginUser, token, nil
}
// SysLogin 用户登录(用户名登录)
func (s *SysUserService) SysLogin(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("账号已被冻结")
}
encrypted, err := common.Encrypt(username, password, user.Salt)
if (user.Password != encrypted) || (err != nil) {
return nil, "", errors.New("用户名或密码错误")
}
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,
}
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, common.RedisTokenPrefix+token).Err()
}
// GetLoginUser 根据Token获取登录用户信息
func (s *SysUserService) GetLoginUser(token string) (*entity.LoginUser, error) {
ctx := context.Background()
data, err := config.RDB.Get(ctx, common.RedisTokenPrefix+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, common.RedisTokenPrefix+token, common.RedisTokenExpire)
return &loginUser, nil
}
// RefreshToken 刷新Token过期时间
func (s *SysUserService) RefreshToken(token string) error {
ctx := context.Background()
return config.RDB.Expire(ctx, common.RedisTokenPrefix+token, common.RedisTokenExpire).Err()
}
// UpdatePassword 修改密码
func (s *SysUserService) UpdatePassword(id, oldPwd, newPwd string) error {
user, err := s.GetByID(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,
})
}
// saveLoginUser 保存登录用户到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, common.RedisTokenPrefix+token, data, common.RedisTokenExpire).Err()
}
// generateToken 生成Token
func (s *SysUserService) generateToken() string {
return uuid.New().String()
}
// Create 创建用户(添加密码加密逻辑)
func (s *SysUserService) Create(item *entity.SysUser) error {
item.ID = uuid.New().String()
item.Salt = uuid.New().String()[:8]
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)
}
// convertToVO Entity 转 VO私有方法
func (s *SysUserService) convertToVO(entity entity.SysUser) *vo.SysUserVO {
return &vo.SysUserVO{
ID: entity.ID,
Username: entity.Username,
Realname: entity.Realname,
Avatar: entity.Avatar,
Birthday: entity.Birthday,
Sex: entity.Sex,
Email: entity.Email,
Phone: entity.Phone,
OrgCode: entity.OrgCode,
Status: entity.Status,
CreateTime: entity.CreateTime,
UpdateTime: entity.UpdateTime,
// 不包含 Password、Salt 等敏感字段
}
}