添加模块

This commit is contained in:
孙小云 2025-12-20 15:07:45 +08:00
parent 041ed5ff46
commit d96179b0c8
19 changed files with 1612 additions and 0 deletions

View File

@ -0,0 +1,86 @@
package com.tuoheng.airport.uaa.application.assembler;
import com.tuoheng.airport.uaa.application.dto.UserDTO;
import com.tuoheng.airport.uaa.domain.model.user.User;
import com.tuoheng.airport.uaa.domain.model.user.UserId;
import com.tuoheng.airport.uaa.domain.model.user.UserProfile;
import com.tuoheng.airport.uaa.domain.model.user.UserStatus;
/**
* 用户DTO-DO转换器
*
* @author Tuoheng Team
*/
public class UserDTOAssembler {
/**
* DTO转DO
*/
public static User toDomain(UserDTO dto) {
if (dto == null) {
return null;
}
User user = new User();
if (dto.getUserId() != null) {
user.setUserId(UserId.of(dto.getUserId()));
}
user.setUsername(dto.getUsername());
// 转换用户资料
UserProfile profile = new UserProfile();
profile.setRealName(dto.getRealName());
profile.setNickname(dto.getNickname());
profile.setMobile(dto.getMobile());
profile.setEmail(dto.getEmail());
profile.setAvatar(dto.getAvatar());
profile.setGender(dto.getGender());
profile.setDeptId(dto.getDeptId());
profile.setPositionId(dto.getPositionId());
user.setProfile(profile);
user.setStatus(UserStatus.of(dto.getStatus()));
user.setTenantId(dto.getTenantId());
user.setCreateTime(dto.getCreateTime());
user.setUpdateTime(dto.getUpdateTime());
return user;
}
/**
* DO转DTO
*/
public static UserDTO toDTO(User user) {
if (user == null) {
return null;
}
UserDTO dto = new UserDTO();
if (user.getUserId() != null) {
dto.setUserId(user.getUserId().getId());
}
dto.setUsername(user.getUsername());
// 转换用户资料
if (user.getProfile() != null) {
UserProfile profile = user.getProfile();
dto.setRealName(profile.getRealName());
dto.setNickname(profile.getNickname());
dto.setMobile(profile.getMobile());
dto.setEmail(profile.getEmail());
dto.setAvatar(profile.getAvatar());
dto.setGender(profile.getGender());
dto.setDeptId(profile.getDeptId());
dto.setPositionId(profile.getPositionId());
}
if (user.getStatus() != null) {
dto.setStatus(user.getStatus().getCode());
}
dto.setTenantId(user.getTenantId());
dto.setCreateTime(user.getCreateTime());
dto.setUpdateTime(user.getUpdateTime());
return dto;
}
}

View File

@ -0,0 +1,84 @@
package com.tuoheng.airport.uaa.application.dto;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户DTO
*
* @author Tuoheng Team
*/
@Data
public class UserDTO {
/**
* 用户ID
*/
private Long userId;
/**
* 用户名
*/
private String username;
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
/**
* 用户状态0-正常1-锁定2-禁用
*/
private Integer status;
/**
* 租户ID
*/
private Long tenantId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,193 @@
package com.tuoheng.airport.uaa.application.service;
import com.tuoheng.airport.uaa.application.assembler.UserDTOAssembler;
import com.tuoheng.airport.uaa.application.dto.UserDTO;
import com.tuoheng.airport.uaa.domain.model.user.User;
import com.tuoheng.airport.uaa.domain.model.user.UserId;
import com.tuoheng.airport.uaa.domain.model.user.UserProfile;
import com.tuoheng.airport.uaa.domain.repository.UserRepository;
import com.tuoheng.airport.common.exception.BusinessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户应用服务
*
* @author Tuoheng Team
*/
@Service
public class UserApplicationService {
@Resource
private UserRepository userRepository;
/**
* 创建用户
*/
@Transactional(rollbackFor = Exception.class)
public UserDTO createUser(UserDTO userDTO, String password) {
// 检查用户名是否已存在
if (userRepository.existsByUsername(userDTO.getUsername())) {
throw new BusinessException("用户名已存在");
}
// 检查手机号是否已存在
if (userDTO.getMobile() != null && userRepository.existsByMobile(userDTO.getMobile())) {
throw new BusinessException("手机号已存在");
}
// 检查邮箱是否已存在
if (userDTO.getEmail() != null && userRepository.existsByEmail(userDTO.getEmail())) {
throw new BusinessException("邮箱已存在");
}
// 创建用户资料
UserProfile profile = new UserProfile();
profile.setRealName(userDTO.getRealName());
profile.setNickname(userDTO.getNickname());
profile.setMobile(userDTO.getMobile());
profile.setEmail(userDTO.getEmail());
profile.setAvatar(userDTO.getAvatar());
profile.setGender(userDTO.getGender());
profile.setDeptId(userDTO.getDeptId());
profile.setPositionId(userDTO.getPositionId());
// 创建用户使用工厂方法
User user = User.create(
userDTO.getUsername(),
password, // 密码应该在这里加密
profile,
userDTO.getTenantId()
);
// 保存用户
User savedUser = userRepository.save(user);
// 发布用户创建事件这里可以通过事件总线发布
// eventPublisher.publish(UserCreatedEvent.create(...));
return UserDTOAssembler.toDTO(savedUser);
}
/**
* 更新用户
*/
@Transactional(rollbackFor = Exception.class)
public UserDTO updateUser(Long userId, UserDTO userDTO) {
// 查找用户
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
// 更新用户资料
UserProfile profile = new UserProfile();
profile.setRealName(userDTO.getRealName());
profile.setNickname(userDTO.getNickname());
profile.setMobile(userDTO.getMobile());
profile.setEmail(userDTO.getEmail());
profile.setAvatar(userDTO.getAvatar());
profile.setGender(userDTO.getGender());
profile.setDeptId(userDTO.getDeptId());
profile.setPositionId(userDTO.getPositionId());
user.updateProfile(profile);
// 保存用户
User updatedUser = userRepository.save(user);
return UserDTOAssembler.toDTO(updatedUser);
}
/**
* 删除用户
*/
@Transactional(rollbackFor = Exception.class)
public void deleteUser(Long userId) {
userRepository.delete(UserId.of(userId));
}
/**
* 根据ID查询用户
*/
public UserDTO getUserById(Long userId) {
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
return UserDTOAssembler.toDTO(user);
}
/**
* 根据用户名查询用户
*/
public UserDTO getUserByUsername(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new BusinessException("用户不存在"));
return UserDTOAssembler.toDTO(user);
}
/**
* 查询所有用户
*/
public List<UserDTO> getAllUsers() {
List<User> users = userRepository.findAll();
return users.stream()
.map(UserDTOAssembler::toDTO)
.collect(Collectors.toList());
}
/**
* 分页查询用户
*/
public List<UserDTO> getUsersByPage(int pageNum, int pageSize) {
List<User> users = userRepository.findByPage(pageNum, pageSize);
return users.stream()
.map(UserDTOAssembler::toDTO)
.collect(Collectors.toList());
}
/**
* 锁定用户
*/
@Transactional(rollbackFor = Exception.class)
public void lockUser(Long userId) {
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
user.lock();
userRepository.save(user);
}
/**
* 解锁用户
*/
@Transactional(rollbackFor = Exception.class)
public void unlockUser(Long userId) {
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
user.unlock();
userRepository.save(user);
}
/**
* 禁用用户
*/
@Transactional(rollbackFor = Exception.class)
public void disableUser(Long userId) {
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
user.disable();
userRepository.save(user);
}
/**
* 启用用户
*/
@Transactional(rollbackFor = Exception.class)
public void enableUser(Long userId) {
User user = userRepository.findById(UserId.of(userId))
.orElseThrow(() -> new BusinessException("用户不存在"));
user.enable();
userRepository.save(user);
}
}

View File

@ -0,0 +1,56 @@
package com.tuoheng.airport.uaa.domain.event;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 用户创建事件
*
* @author Tuoheng Team
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserCreatedEvent {
/**
* 事件ID
*/
private String eventId;
/**
* 用户ID
*/
private Long userId;
/**
* 用户名
*/
private String username;
/**
* 租户ID
*/
private Long tenantId;
/**
* 事件时间
*/
private LocalDateTime eventTime;
/**
* 创建事件
*/
public static UserCreatedEvent create(Long userId, String username, Long tenantId) {
UserCreatedEvent event = new UserCreatedEvent();
event.setEventId(java.util.UUID.randomUUID().toString());
event.setUserId(userId);
event.setUsername(username);
event.setTenantId(tenantId);
event.setEventTime(LocalDateTime.now());
return event;
}
}

View File

@ -0,0 +1,132 @@
package com.tuoheng.airport.uaa.domain.model.user;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 用户聚合根
*
* @author Tuoheng Team
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
/**
* 用户ID聚合根标识
*/
private UserId userId;
/**
* 用户名
*/
private String username;
/**
* 密码加密后
*/
private String password;
/**
* 用户资料
*/
private UserProfile profile;
/**
* 用户状态
*/
private UserStatus status;
/**
* 租户ID
*/
private Long tenantId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 创建用户工厂方法
*/
public static User create(String username, String password, UserProfile profile, Long tenantId) {
User user = new User();
user.setUserId(UserId.generate());
user.setUsername(username);
user.setPassword(password);
user.setProfile(profile);
user.setStatus(UserStatus.NORMAL);
user.setTenantId(tenantId);
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
return user;
}
/**
* 修改密码
*/
public void changePassword(String oldPassword, String newPassword) {
if (!this.password.equals(oldPassword)) {
throw new IllegalArgumentException("原密码错误");
}
this.password = newPassword;
this.updateTime = LocalDateTime.now();
}
/**
* 锁定用户
*/
public void lock() {
this.status = UserStatus.LOCKED;
this.updateTime = LocalDateTime.now();
}
/**
* 解锁用户
*/
public void unlock() {
this.status = UserStatus.NORMAL;
this.updateTime = LocalDateTime.now();
}
/**
* 禁用用户
*/
public void disable() {
this.status = UserStatus.DISABLED;
this.updateTime = LocalDateTime.now();
}
/**
* 启用用户
*/
public void enable() {
this.status = UserStatus.NORMAL;
this.updateTime = LocalDateTime.now();
}
/**
* 更新用户资料
*/
public void updateProfile(UserProfile profile) {
this.profile = profile;
this.updateTime = LocalDateTime.now();
}
/**
* 检查用户是否可用
*/
public boolean isAvailable() {
return this.status == UserStatus.NORMAL;
}
}

View File

@ -0,0 +1,35 @@
package com.tuoheng.airport.uaa.domain.model.user;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.UUID;
/**
* 用户ID值对象
*
* @author Tuoheng Team
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserId {
private Long id;
/**
* 生成新的用户ID
*/
public static UserId generate() {
// 实际项目中可以使用雪花算法等分布式ID生成策略
return new UserId(System.currentTimeMillis());
}
/**
* 从Long创建UserId
*/
public static UserId of(Long id) {
return new UserId(id);
}
}

View File

@ -0,0 +1,76 @@
package com.tuoheng.airport.uaa.domain.model.user;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户资料值对象
*
* @author Tuoheng Team
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserProfile {
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像URL
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
/**
* 验证手机号格式
*/
public boolean isValidMobile() {
if (mobile == null || mobile.isEmpty()) {
return false;
}
return mobile.matches("^1[3-9]\\d{9}$");
}
/**
* 验证邮箱格式
*/
public boolean isValidEmail() {
if (email == null || email.isEmpty()) {
return false;
}
return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$");
}
}

View File

@ -0,0 +1,30 @@
package com.tuoheng.airport.uaa.domain.model.user;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 用户状态枚举
*
* @author Tuoheng Team
*/
@Getter
@AllArgsConstructor
public enum UserStatus {
NORMAL(0, "正常"),
LOCKED(1, "锁定"),
DISABLED(2, "禁用");
private final Integer code;
private final String desc;
public static UserStatus of(Integer code) {
for (UserStatus status : values()) {
if (status.getCode().equals(code)) {
return status;
}
}
return NORMAL;
}
}

View File

@ -0,0 +1,75 @@
package com.tuoheng.airport.uaa.domain.repository;
import com.tuoheng.airport.uaa.domain.model.user.User;
import com.tuoheng.airport.uaa.domain.model.user.UserId;
import java.util.List;
import java.util.Optional;
/**
* 用户仓储接口
*
* @author Tuoheng Team
*/
public interface UserRepository {
/**
* 保存用户
*/
User save(User user);
/**
* 根据ID查找用户
*/
Optional<User> findById(UserId userId);
/**
* 根据用户名查找用户
*/
Optional<User> findByUsername(String username);
/**
* 根据手机号查找用户
*/
Optional<User> findByMobile(String mobile);
/**
* 根据邮箱查找用户
*/
Optional<User> findByEmail(String email);
/**
* 查询所有用户
*/
List<User> findAll();
/**
* 分页查询用户
*/
List<User> findByPage(int pageNum, int pageSize);
/**
* 根据租户ID查询用户
*/
List<User> findByTenantId(Long tenantId);
/**
* 删除用户
*/
void delete(UserId userId);
/**
* 检查用户名是否存在
*/
boolean existsByUsername(String username);
/**
* 检查手机号是否存在
*/
boolean existsByMobile(String mobile);
/**
* 检查邮箱是否存在
*/
boolean existsByEmail(String email);
}

View File

@ -0,0 +1,41 @@
package com.tuoheng.airport.uaa.domain.service;
import com.tuoheng.airport.uaa.domain.model.user.User;
/**
* 认证领域服务接口
*
* @author Tuoheng Team
*/
public interface AuthDomainService {
/**
* 用户登录
*/
String login(String username, String password);
/**
* 验证Token
*/
boolean validateToken(String token);
/**
* 刷新Token
*/
String refreshToken(String token);
/**
* 用户登出
*/
void logout(String token);
/**
* 验证密码
*/
boolean validatePassword(User user, String password);
/**
* 加密密码
*/
String encryptPassword(String password);
}

View File

@ -0,0 +1,86 @@
package com.tuoheng.airport.uaa.infrastructure.persistence.converter;
import com.tuoheng.airport.uaa.domain.model.user.User;
import com.tuoheng.airport.uaa.domain.model.user.UserId;
import com.tuoheng.airport.uaa.domain.model.user.UserProfile;
import com.tuoheng.airport.uaa.domain.model.user.UserStatus;
import com.tuoheng.airport.uaa.infrastructure.persistence.entity.UserPO;
/**
* 用户PO-DO转换器
*
* @author Tuoheng Team
*/
public class UserConverter {
/**
* PO转DO
*/
public static User toDomain(UserPO po) {
if (po == null) {
return null;
}
User user = new User();
user.setUserId(UserId.of(po.getId()));
user.setUsername(po.getUsername());
user.setPassword(po.getPassword());
// 转换用户资料
UserProfile profile = new UserProfile();
profile.setRealName(po.getRealName());
profile.setNickname(po.getNickname());
profile.setMobile(po.getMobile());
profile.setEmail(po.getEmail());
profile.setAvatar(po.getAvatar());
profile.setGender(po.getGender());
profile.setDeptId(po.getDeptId());
profile.setPositionId(po.getPositionId());
user.setProfile(profile);
user.setStatus(UserStatus.of(po.getStatus()));
user.setTenantId(po.getTenantId());
user.setCreateTime(po.getCreateTime());
user.setUpdateTime(po.getUpdateTime());
return user;
}
/**
* DO转PO
*/
public static UserPO toPO(User user) {
if (user == null) {
return null;
}
UserPO po = new UserPO();
if (user.getUserId() != null) {
po.setId(user.getUserId().getId());
}
po.setUsername(user.getUsername());
po.setPassword(user.getPassword());
// 转换用户资料
if (user.getProfile() != null) {
UserProfile profile = user.getProfile();
po.setRealName(profile.getRealName());
po.setNickname(profile.getNickname());
po.setMobile(profile.getMobile());
po.setEmail(profile.getEmail());
po.setAvatar(profile.getAvatar());
po.setGender(profile.getGender());
po.setDeptId(profile.getDeptId());
po.setPositionId(profile.getPositionId());
}
if (user.getStatus() != null) {
po.setStatus(user.getStatus().getCode());
}
po.setTenantId(user.getTenantId());
po.setCreateTime(user.getCreateTime());
po.setUpdateTime(user.getUpdateTime());
return po;
}
}

View File

@ -0,0 +1,109 @@
package com.tuoheng.airport.uaa.infrastructure.persistence.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户数据库实体
*
* @author Tuoheng Team
*/
@Data
@TableName("sys_user")
public class UserPO {
/**
* 用户ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
/**
* 用户状态0-正常1-锁定2-禁用
*/
private Integer status;
/**
* 租户ID
*/
private Long tenantId;
/**
* 删除标记0-未删除1-已删除
*/
private Integer mark;
/**
* 创建人
*/
private Long createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人
*/
private Long updateUser;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,30 @@
package com.tuoheng.airport.uaa.infrastructure.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tuoheng.airport.uaa.infrastructure.persistence.entity.UserPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 用户Mapper接口
*
* @author Tuoheng Team
*/
@Mapper
public interface UserMapper extends BaseMapper<UserPO> {
/**
* 根据用户名查询用户
*/
UserPO selectByUsername(@Param("username") String username);
/**
* 根据手机号查询用户
*/
UserPO selectByMobile(@Param("mobile") String mobile);
/**
* 根据邮箱查询用户
*/
UserPO selectByEmail(@Param("email") String email);
}

View File

@ -0,0 +1,120 @@
package com.tuoheng.airport.uaa.infrastructure.persistence.repository;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tuoheng.airport.uaa.domain.model.user.User;
import com.tuoheng.airport.uaa.domain.model.user.UserId;
import com.tuoheng.airport.uaa.domain.repository.UserRepository;
import com.tuoheng.airport.uaa.infrastructure.persistence.converter.UserConverter;
import com.tuoheng.airport.uaa.infrastructure.persistence.entity.UserPO;
import com.tuoheng.airport.uaa.infrastructure.persistence.mapper.UserMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 用户仓储实现
*
* @author Tuoheng Team
*/
@Repository
public class UserRepositoryImpl implements UserRepository {
@Resource
private UserMapper userMapper;
@Override
public User save(User user) {
UserPO po = UserConverter.toPO(user);
if (po.getId() == null) {
// 新增
userMapper.insert(po);
} else {
// 更新
userMapper.updateById(po);
}
return UserConverter.toDomain(po);
}
@Override
public Optional<User> findById(UserId userId) {
UserPO po = userMapper.selectById(userId.getId());
return Optional.ofNullable(UserConverter.toDomain(po));
}
@Override
public Optional<User> findByUsername(String username) {
UserPO po = userMapper.selectByUsername(username);
return Optional.ofNullable(UserConverter.toDomain(po));
}
@Override
public Optional<User> findByMobile(String mobile) {
UserPO po = userMapper.selectByMobile(mobile);
return Optional.ofNullable(UserConverter.toDomain(po));
}
@Override
public Optional<User> findByEmail(String email) {
UserPO po = userMapper.selectByEmail(email);
return Optional.ofNullable(UserConverter.toDomain(po));
}
@Override
public List<User> findAll() {
List<UserPO> poList = userMapper.selectList(null);
return poList.stream()
.map(UserConverter::toDomain)
.collect(Collectors.toList());
}
@Override
public List<User> findByPage(int pageNum, int pageSize) {
// 使用MyBatis-Plus分页
int offset = (pageNum - 1) * pageSize;
LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
wrapper.last("LIMIT " + offset + "," + pageSize);
List<UserPO> poList = userMapper.selectList(wrapper);
return poList.stream()
.map(UserConverter::toDomain)
.collect(Collectors.toList());
}
@Override
public List<User> findByTenantId(Long tenantId) {
LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserPO::getTenantId, tenantId);
List<UserPO> poList = userMapper.selectList(wrapper);
return poList.stream()
.map(UserConverter::toDomain)
.collect(Collectors.toList());
}
@Override
public void delete(UserId userId) {
userMapper.deleteById(userId.getId());
}
@Override
public boolean existsByUsername(String username) {
LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserPO::getUsername, username);
return userMapper.selectCount(wrapper) > 0;
}
@Override
public boolean existsByMobile(String mobile) {
LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserPO::getMobile, mobile);
return userMapper.selectCount(wrapper) > 0;
}
@Override
public boolean existsByEmail(String email) {
LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(UserPO::getEmail, email);
return userMapper.selectCount(wrapper) > 0;
}
}

View File

@ -0,0 +1,94 @@
package com.tuoheng.airport.uaa.presentation.assembler;
import com.tuoheng.airport.uaa.application.dto.UserDTO;
import com.tuoheng.airport.uaa.domain.model.user.UserStatus;
import com.tuoheng.airport.uaa.presentation.vo.request.UserCreateRequest;
import com.tuoheng.airport.uaa.presentation.vo.request.UserUpdateRequest;
import com.tuoheng.airport.uaa.presentation.vo.response.UserVO;
/**
* 用户VO-DTO转换器
*
* @author Tuoheng Team
*/
public class UserAssembler {
/**
* CreateRequest转DTO
*/
public static UserDTO toDTO(UserCreateRequest request) {
if (request == null) {
return null;
}
UserDTO dto = new UserDTO();
dto.setUsername(request.getUsername());
dto.setRealName(request.getRealName());
dto.setNickname(request.getNickname());
dto.setMobile(request.getMobile());
dto.setEmail(request.getEmail());
dto.setAvatar(request.getAvatar());
dto.setGender(request.getGender());
dto.setDeptId(request.getDeptId());
dto.setPositionId(request.getPositionId());
dto.setTenantId(request.getTenantId());
return dto;
}
/**
* UpdateRequest转DTO
*/
public static UserDTO toDTO(UserUpdateRequest request) {
if (request == null) {
return null;
}
UserDTO dto = new UserDTO();
dto.setUserId(request.getUserId());
dto.setRealName(request.getRealName());
dto.setNickname(request.getNickname());
dto.setMobile(request.getMobile());
dto.setEmail(request.getEmail());
dto.setAvatar(request.getAvatar());
dto.setGender(request.getGender());
dto.setDeptId(request.getDeptId());
dto.setPositionId(request.getPositionId());
return dto;
}
/**
* DTO转VO
*/
public static UserVO toVO(UserDTO dto) {
if (dto == null) {
return null;
}
UserVO vo = new UserVO();
vo.setUserId(dto.getUserId());
vo.setUsername(dto.getUsername());
vo.setRealName(dto.getRealName());
vo.setNickname(dto.getNickname());
vo.setMobile(dto.getMobile());
vo.setEmail(dto.getEmail());
vo.setAvatar(dto.getAvatar());
vo.setGender(dto.getGender());
vo.setDeptId(dto.getDeptId());
vo.setPositionId(dto.getPositionId());
vo.setStatus(dto.getStatus());
// 设置状态描述
if (dto.getStatus() != null) {
UserStatus status = UserStatus.of(dto.getStatus());
vo.setStatusDesc(status.getDesc());
}
vo.setTenantId(dto.getTenantId());
vo.setCreateTime(dto.getCreateTime());
vo.setUpdateTime(dto.getUpdateTime());
return vo;
}
}

View File

@ -0,0 +1,145 @@
package com.tuoheng.airport.uaa.presentation.controller;
import com.tuoheng.airport.common.response.Result;
import com.tuoheng.airport.uaa.application.dto.UserDTO;
import com.tuoheng.airport.uaa.application.service.UserApplicationService;
import com.tuoheng.airport.uaa.presentation.assembler.UserAssembler;
import com.tuoheng.airport.uaa.presentation.vo.request.UserCreateRequest;
import com.tuoheng.airport.uaa.presentation.vo.request.UserUpdateRequest;
import com.tuoheng.airport.uaa.presentation.vo.response.UserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户控制器
*
* @author Tuoheng Team
*/
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/uaa/users")
public class UserController {
@Resource
private UserApplicationService userApplicationService;
/**
* 创建用户
*/
@ApiOperation("创建用户")
@PostMapping
public Result<UserVO> createUser(@Validated @RequestBody UserCreateRequest request) {
UserDTO userDTO = UserAssembler.toDTO(request);
UserDTO createdUser = userApplicationService.createUser(userDTO, request.getPassword());
UserVO userVO = UserAssembler.toVO(createdUser);
return Result.success(userVO);
}
/**
* 更新用户
*/
@ApiOperation("更新用户")
@PutMapping("/{id}")
public Result<UserVO> updateUser(@PathVariable("id") Long id,
@Validated @RequestBody UserUpdateRequest request) {
request.setUserId(id);
UserDTO userDTO = UserAssembler.toDTO(request);
UserDTO updatedUser = userApplicationService.updateUser(id, userDTO);
UserVO userVO = UserAssembler.toVO(updatedUser);
return Result.success(userVO);
}
/**
* 删除用户
*/
@ApiOperation("删除用户")
@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable("id") Long id) {
userApplicationService.deleteUser(id);
return Result.success();
}
/**
* 根据ID查询用户
*/
@ApiOperation("根据ID查询用户")
@GetMapping("/{id}")
public Result<UserVO> getUserById(@PathVariable("id") Long id) {
UserDTO userDTO = userApplicationService.getUserById(id);
UserVO userVO = UserAssembler.toVO(userDTO);
return Result.success(userVO);
}
/**
* 查询所有用户
*/
@ApiOperation("查询所有用户")
@GetMapping
public Result<List<UserVO>> getAllUsers() {
List<UserDTO> userDTOs = userApplicationService.getAllUsers();
List<UserVO> userVOs = userDTOs.stream()
.map(UserAssembler::toVO)
.collect(Collectors.toList());
return Result.success(userVOs);
}
/**
* 分页查询用户
*/
@ApiOperation("分页查询用户")
@GetMapping("/page")
public Result<List<UserVO>> getUsersByPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
List<UserDTO> userDTOs = userApplicationService.getUsersByPage(pageNum, pageSize);
List<UserVO> userVOs = userDTOs.stream()
.map(UserAssembler::toVO)
.collect(Collectors.toList());
return Result.success(userVOs);
}
/**
* 锁定用户
*/
@ApiOperation("锁定用户")
@PutMapping("/{id}/lock")
public Result<Void> lockUser(@PathVariable("id") Long id) {
userApplicationService.lockUser(id);
return Result.success();
}
/**
* 解锁用户
*/
@ApiOperation("解锁用户")
@PutMapping("/{id}/unlock")
public Result<Void> unlockUser(@PathVariable("id") Long id) {
userApplicationService.unlockUser(id);
return Result.success();
}
/**
* 禁用用户
*/
@ApiOperation("禁用用户")
@PutMapping("/{id}/disable")
public Result<Void> disableUser(@PathVariable("id") Long id) {
userApplicationService.disableUser(id);
return Result.success();
}
/**
* 启用用户
*/
@ApiOperation("启用用户")
@PutMapping("/{id}/enable")
public Result<Void> enableUser(@PathVariable("id") Long id) {
userApplicationService.enableUser(id);
return Result.success();
}
}

View File

@ -0,0 +1,71 @@
package com.tuoheng.airport.uaa.presentation.vo.request;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 用户创建请求VO
*
* @author Tuoheng Team
*/
@Data
public class UserCreateRequest {
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
private String username;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
private String password;
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
/**
* 租户ID
*/
private Long tenantId;
}

View File

@ -0,0 +1,60 @@
package com.tuoheng.airport.uaa.presentation.vo.request;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 用户更新请求VO
*
* @author Tuoheng Team
*/
@Data
public class UserUpdateRequest {
/**
* 用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
}

View File

@ -0,0 +1,89 @@
package com.tuoheng.airport.uaa.presentation.vo.response;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户响应VO
*
* @author Tuoheng Team
*/
@Data
public class UserVO {
/**
* 用户ID
*/
private Long userId;
/**
* 用户名
*/
private String username;
/**
* 真实姓名
*/
private String realName;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别0-未知1-2-
*/
private Integer gender;
/**
* 部门ID
*/
private Long deptId;
/**
* 职位ID
*/
private Long positionId;
/**
* 用户状态0-正常1-锁定2-禁用
*/
private Integer status;
/**
* 用户状态描述
*/
private String statusDesc;
/**
* 租户ID
*/
private Long tenantId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}