324 lines
8.1 KiB
Go
324 lines
8.1 KiB
Go
// 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 等敏感字段
|
||
}
|
||
}
|