添加模块
This commit is contained in:
parent
041ed5ff46
commit
d96179b0c8
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.-]+$");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue