content: 
  package com.platform.modules.system.service.impl;
  
  import cn.hutool.core.collection.CollUtil;
  import cn.hutool.core.util.ArrayUtil;
  import cn.hutool.core.util.StrUtil;
  import com.platform.modules.system.domain.Menu;
  import com.platform.modules.system.domain.UserInfo;
  import com.platform.modules.system.repository.MenuRepository;
  import lombok.RequiredArgsConstructor;
  import com.platform.config.FileProperties;
  import com.platform.exception.BadRequestException;
  import com.platform.modules.security.service.OnlineUserService;
  import com.platform.modules.security.service.UserCacheManager;
  import com.platform.modules.system.domain.User;
  import com.platform.exception.EntityExistException;
  import com.platform.exception.EntityNotFoundException;
  import com.platform.modules.system.repository.UserRepository;
  import com.platform.modules.system.service.UserService;
  import com.platform.modules.system.service.dto.*;
  import com.platform.modules.system.service.mapstruct.UserLoginMapper;
  import com.platform.modules.system.service.mapstruct.UserMapper;
  import com.platform.utils.*;
  import org.springframework.cache.annotation.CacheConfig;
  import org.springframework.cache.annotation.Cacheable;
  import org.springframework.data.domain.Page;
  import org.springframework.data.domain.Pageable;
  import org.springframework.stereotype.Service;
  import org.springframework.transaction.annotation.Transactional;
  import org.springframework.web.multipart.MultipartFile;
  import javax.servlet.http.HttpServletResponse;
  import javax.validation.constraints.NotBlank;
  import java.io.File;
  import java.io.IOException;
  import java.util.*;
  import java.util.stream.Collectors;
  
  /**
   * @author AllDataDC
   * @date 2023-01-27
   */
  @Service
  @RequiredArgsConstructor
  @CacheConfig(cacheNames = "user")
  public class UserServiceImpl implements UserService {
  
      private final UserRepository userRepository;
      private final UserMapper userMapper;
      private final FileProperties properties;
      private final RedisUtils redisUtils;
      private final UserCacheManager userCacheManager;
      private final OnlineUserService onlineUserService;
      private final UserLoginMapper userLoginMapper;
  
      private final MenuRepository menuMapper;
  
      @Override
      public Object queryAll(UserQueryCriteria criteria, Pageable pageable) {
          Page<User> page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
          return PageUtil.toPage(page.map(userMapper::toDto));
      }
  
      @Override
      public List<UserDto> queryAll(UserQueryCriteria criteria) {
          List<User> users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder));
          return userMapper.toDto(users);
      }
  
      @Override
      @Cacheable(key = "'id:' + #p0")
      @Transactional(rollbackFor = Exception.class)
      public UserDto findById(long id) {
          User user = userRepository.findById(id).orElseGet(User::new);
          ValidationUtil.isNull(user.getId(), "User", "id", id);
          return userMapper.toDto(user);
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void create(User resources) {
          if (userRepository.findByUsername(resources.getUsername()) != null) {
              throw new EntityExistException(User.class, "username", resources.getUsername());
          }
          if (userRepository.findByEmail(resources.getEmail()) != null) {
              throw new EntityExistException(User.class, "email", resources.getEmail());
          }
          if (userRepository.findByPhone(resources.getPhone()) != null) {
              throw new EntityExistException(User.class, "phone", resources.getPhone());
          }
          userRepository.save(resources);
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void update(User resources) throws Exception {
          User user = userRepository.findById(resources.getId()).orElseGet(User::new);
          ValidationUtil.isNull(user.getId(), "User", "id", resources.getId());
          User user1 = userRepository.findByUsername(resources.getUsername());
          User user2 = userRepository.findByEmail(resources.getEmail());
          User user3 = userRepository.findByPhone(resources.getPhone());
          if (user1 != null && !user.getId().equals(user1.getId())) {
              throw new EntityExistException(User.class, "username", resources.getUsername());
          }
          if (user2 != null && !user.getId().equals(user2.getId())) {
              throw new EntityExistException(User.class, "email", resources.getEmail());
          }
          if (user3 != null && !user.getId().equals(user3.getId())) {
              throw new EntityExistException(User.class, "phone", resources.getPhone());
          }
          // 如果用户的角色改变
          if (!resources.getRoles().equals(user.getRoles())) {
              redisUtils.del(CacheKey.DATA_USER + resources.getId());
              redisUtils.del(CacheKey.MENU_USER + resources.getId());
              redisUtils.del(CacheKey.ROLE_AUTH + resources.getId());
          }
          // 修改部门会影响 数据权限
          if (!Objects.equals(resources.getDept(),user.getDept())) {
              redisUtils.del(CacheKey.DATA_USER + resources.getId());
          }
          // 如果用户被禁用，则清除用户登录信息
          if(!resources.getEnabled()){
              onlineUserService.kickOutForUsername(resources.getUsername());
          }
          user.setUsername(resources.getUsername());
          user.setEmail(resources.getEmail());
          user.setEnabled(resources.getEnabled());
          user.setRoles(resources.getRoles());
          user.setDept(resources.getDept());
          user.setJobs(resources.getJobs());
          user.setPhone(resources.getPhone());
          user.setNickName(resources.getNickName());
          user.setGender(resources.getGender());
          userRepository.save(user);
          // 清除缓存
          delCaches(user.getId(), user.getUsername());
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void updateCenter(User resources) {
          User user = userRepository.findById(resources.getId()).orElseGet(User::new);
          User user1 = userRepository.findByPhone(resources.getPhone());
          if (user1 != null && !user.getId().equals(user1.getId())) {
              throw new EntityExistException(User.class, "phone", resources.getPhone());
          }
          user.setNickName(resources.getNickName());
          user.setPhone(resources.getPhone());
          user.setGender(resources.getGender());
          userRepository.save(user);
          // 清理缓存
          delCaches(user.getId(), user.getUsername());
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void delete(Set<Long> ids) {
          for (Long id : ids) {
              // 清理缓存
              UserDto user = findById(id);
              delCaches(user.getId(), user.getUsername());
          }
          userRepository.deleteAllByIdIn(ids);
      }
  
      @Override
      public UserDto findByName(String userName) {
          User user = userRepository.findByUsername(userName);
          if (user == null) {
              throw new EntityNotFoundException(User.class, "name", userName);
          } else {
              return userMapper.toDto(user);
          }
      }
  
      @Override
      public UserLoginDto getLoginData(String userName) {
          User user = userRepository.findByUsername(userName);
          if (user == null) {
              throw new EntityNotFoundException(User.class, "name", userName);
          } else {
              return userLoginMapper.toDto(user);
          }
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void updatePass(String username, String pass) {
          userRepository.updatePass(username, pass, new Date());
          flushCache(username);
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public Map<String, String> updateAvatar(MultipartFile multipartFile) {
          // 文件大小验证
          FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize());
          // 验证文件上传的格式
          String image = "gif jpg png jpeg";
          String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
          if(fileType != null && !image.contains(fileType)){
              throw new BadRequestException("文件格式错误！, 仅支持 " + image +" 格式");
          }
          User user = userRepository.findByUsername(SecurityUtils.getCurrentUsername());
          String oldPath = user.getAvatarPath();
          File file = FileUtil.upload(multipartFile, properties.getPath().getAvatar());
          user.setAvatarPath(Objects.requireNonNull(file).getPath());
          user.setAvatarName(file.getName());
          userRepository.save(user);
          if (StringUtils.isNotBlank(oldPath)) {
              FileUtil.del(oldPath);
          }
          @NotBlank String username = user.getUsername();
          flushCache(username);
          return new HashMap<String, String>(1) {{
              put("avatar", file.getName());
          }};
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void updateEmail(String username, String email) {
          userRepository.updateEmail(username, email);
          flushCache(username);
      }
  
      @Override
      public void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException {
          List<Map<String, Object>> list = new ArrayList<>();
          for (UserDto userDTO : queryAll) {
              List<String> roles = userDTO.getRoles().stream().map(RoleSmallDto::getName).collect(Collectors.toList());
              Map<String, Object> map = new LinkedHashMap<>();
              map.put("用户名", userDTO.getUsername());
              map.put("角色", roles);
              map.put("部门", userDTO.getDept().getName());
              map.put("岗位", userDTO.getJobs().stream().map(JobSmallDto::getName).collect(Collectors.toList()));
              map.put("邮箱", userDTO.getEmail());
              map.put("状态", userDTO.getEnabled() ? "启用" : "禁用");
              map.put("手机号码", userDTO.getPhone());
              map.put("修改密码的时间", userDTO.getPwdResetTime());
              map.put("创建日期", userDTO.getCreateTime());
              list.add(map);
          }
          FileUtil.downloadExcel(list, response);
      }
  
      /**
       * 清理缓存
       *
       * @param id /
       */
      public void delCaches(Long id, String username) {
          redisUtils.del(CacheKey.USER_ID + id);
          flushCache(username);
      }
  
      /**
       * 清理 登陆时 用户缓存信息
       *
       * @param username /
       */
      private void flushCache(String username) {
          userCacheManager.cleanUserCache(username);
      }
  
      @Override
      public UserInfo loginByUsername(String username) {
          UserInfo userInfo = new UserInfo();
          User userEntity = userRepository.findByUsername(username);
          if(null != userEntity){
              UserDto userVo = userMapper.toDto(userEntity);
              userInfo.setUserVo(userVo);
              if(CollUtil.isNotEmpty(userVo.getRoles())){
                  Set<String> permissions = new HashSet<>();
                  List<Long> roleIds = userVo.getRoles().stream()
                          .map(RoleSmallDto::getId).collect(Collectors.toList());
                  Set<Long> roleSet = new HashSet<>();
                  roleSet.addAll(roleIds);
                  LinkedHashSet<Menu> menuEntitys = menuMapper.findByRoleIds(roleSet);
                  if(CollUtil.isNotEmpty(menuEntitys)){
                      List<String> permissionList = menuEntitys.stream()
                              .filter(menuEntity -> StrUtil.isNotBlank(menuEntity.getPermission()))
                              .map(Menu::getPermission)
                              .collect(Collectors.toList());
                      permissions.addAll(permissionList);
                      userInfo.setPerms(ArrayUtil.toArray(permissions, String.class));
                  }
              }
          }
          return userInfo;
      }
  }
  