| | |
| | | import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; |
| | | import cn.iocoder.yudao.module.infra.api.config.ConfigApi; |
| | | import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; |
| | |
| | | import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| | | import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper; |
| | |
| | | if (CollUtil.isEmpty(importUsers)) { |
| | | throw exception(USER_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | // 1.2 åå§åå¯ç ä¸è½ä¸ºç©º |
| | | // 1.2 åå§åå¯ç ï¼Excel çãåå§å¯ç ãåç空æ¶ï¼ä½¿ç¨ç³»ç»é
ç½®çåå§å¯ç |
| | | String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY); |
| | | if (StrUtil.isEmpty(initPassword)) { |
| | | throw exception(USER_IMPORT_INIT_PASSWORD); |
| | | } |
| | | // 1.3 é¢å è½½é¨é¨ãå²ä½ï¼ç¨äºæ Excel éå¡«åçãåç§°ãç¿»è¯æç¼å· |
| | | List<DeptDO> deptList = DataPermissionUtils.executeIgnore(() -> deptService.getDeptList(new DeptListReqVO())); |
| | | List<PostDO> postList = postService.getPostList(null, null); |
| | | |
| | | // 2. éåï¼é个å建 or æ´æ° |
| | | UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>()) |
| | |
| | | AtomicInteger index = new AtomicInteger(1); |
| | | importUsers.forEach(importUser -> { |
| | | int currentIndex = index.getAndIncrement(); |
| | | // 2.1.1 æ ¡éªå段æ¯å¦ç¬¦åè¦æ± |
| | | String username = StrUtil.trim(importUser.getUsername()); |
| | | // 失败æç»ç key å®ä½å°å
·ä½çè¡ï¼å¹¶å¸¦ä¸ç¨æ·è´¦å·ï¼ï¼æ¹ä¾¿ç¨æ·å¨ Excel 䏿¾å°è¿ä¸è¡ |
| | | String rowKey = StrUtil.format("第 {} è¡{}", currentIndex, |
| | | StrUtil.isEmpty(username) ? "" : StrUtil.format("ã{}ã", username)); |
| | | try { |
| | | ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword)); |
| | | } catch (ConstraintViolationException ex) { |
| | | String key = StrUtil.blankToDefault(importUser.getUsername(), "第 " + currentIndex + " è¡"); |
| | | respVO.getFailureUsernames().put(key, ex.getMessage()); |
| | | return; |
| | | } |
| | | // 2.1.2 æ ¡éªï¼å¤ææ¯å¦æä¸ç¬¦åçåå |
| | | try { |
| | | validateUserForCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(), |
| | | importUser.getDeptId(), null); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage()); |
| | | return; |
| | | } |
| | | // 2.1.1 è§£æé¨é¨ãå²ä½ï¼æ¯æå¡«åç§°ï¼é¨é¨å
¼å®¹å¡«ç¼å·ï¼ |
| | | Long deptId = parseDeptId(importUser.getDept(), deptList); |
| | | Set<Long> postIds = parsePostIds(importUser.getPost(), postList); |
| | | // 2.1.2 æ ¡éªå段æ¯å¦ç¬¦åè¦æ±ãå¯ç ä¼å
å Excel çãåå§å¯ç ãï¼ä¸ºç©ºæ¶åç³»ç»é
ç½® |
| | | String password = StrUtil.blankToDefault(StrUtil.trim(importUser.getPassword()), initPassword); |
| | | UserSaveReqVO saveReqVO = BeanUtils.toBean(importUser, UserSaveReqVO.class) |
| | | .setUsername(username).setDeptId(deptId).setPostIds(postIds).setPassword(password); |
| | | validateUserImportRow(saveReqVO, password); |
| | | // 2.1.3 æ ¡éªç¨æ·è´¦å·ãææºå·ãé®ç®±å¯ä¸ï¼ä»¥åé¨é¨ãå²ä½å¯ç¨ |
| | | validateUserForCreateOrUpdate(null, username, saveReqVO.getMobile(), saveReqVO.getEmail(), |
| | | deptId, postIds); |
| | | |
| | | // 2.2.1 夿妿ä¸åå¨ï¼å¨è¿è¡æå
¥ |
| | | AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); |
| | | AdminUserDO existUser = userMapper.selectByUsername(username); |
| | | if (existUser == null) { |
| | | userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) |
| | | .setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置é»è®¤å¯ç å空å²ä½ç¼å·æ°ç» |
| | | respVO.getCreateUsernames().add(importUser.getUsername()); |
| | | AdminUserDO user = BeanUtils.toBean(saveReqVO, AdminUserDO.class) |
| | | .setPassword(encodePassword(password)) |
| | | .setStatus(ObjUtil.defaultIfNull(importUser.getStatus(), |
| | | CommonStatusEnum.ENABLE.getStatus())); //ãè´¦å·ç¶æãç空æ¶é»è®¤å¼å¯ |
| | | userMapper.insert(user); |
| | | insertUserPost(user.getId(), postIds); // 忥å²ä½å
³èï¼é¿å
导å
¥åºæ¥çç¨æ·æ²¡æå²ä½ |
| | | respVO.getCreateUsernames().add(username); |
| | | return; |
| | | } |
| | | // 2.2.2 妿åå¨ï¼å¤ææ¯å¦å
è®¸æ´æ° |
| | | if (!isUpdateSupport) { |
| | | respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg()); |
| | | return; |
| | | throw new ServiceException(USER_USERNAME_EXISTS.getCode(), |
| | | "ç¨æ·è´¦å·å·²åå¨ãå¦éè¦çè¿ä¸ªç¨æ·ï¼è¯·å¾éãæ¯å¦è¦çãå鿰坼å
¥ï¼å¦åè¯·ä¿®æ¹ Excel ä¸çç¨æ·è´¦å·"); |
| | | } |
| | | AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class); |
| | | updateUser.setId(existUser.getId()); |
| | | AdminUserDO updateUser = BeanUtils.toBean(saveReqVO, AdminUserDO.class) |
| | | .setId(existUser.getId()).setPassword(null) // è¦çæ¶ä¸æ¹å¯ç ï¼é¿å
æå¨ç¨è´¦å·çå¯ç æ¹æ |
| | | .setStatus(importUser.getStatus()); //ãè´¦å·ç¶æãç空æ¶ä¿æåç¶æ |
| | | userMapper.updateById(updateUser); |
| | | respVO.getUpdateUsernames().add(importUser.getUsername()); |
| | | userPostMapper.deleteByUserId(existUser.getId()); |
| | | insertUserPost(existUser.getId(), postIds); |
| | | respVO.getUpdateUsernames().add(username); |
| | | } catch (ConstraintViolationException ex) { |
| | | respVO.getFailureUsernames().put(rowKey, buildConstraintFailureMessage(ex)); |
| | | } catch (ServiceException ex) { |
| | | respVO.getFailureUsernames().put(rowKey, buildImportFailureMessage(ex, importUser)); |
| | | } |
| | | }); |
| | | // è®°å½å¯¼å
¥ç»ææ±æ»ï¼ä¾ @LogRecord ç success ææ¡å¼ç¨ |
| | | OperateLogUtils.putImportSummary(respVO.getCreateUsernames(), respVO.getUpdateUsernames(), |
| | |
| | | return respVO; |
| | | } |
| | | |
| | | /** Bean æ ¡éªå¤±è´¥æ¶çåæ®µå -> ç»ç¨æ·çä¿®æ¹å»ºè®® */ |
| | | private static final Map<String, String> USER_IMPORT_FIELD_HINTS = Map.of( |
| | | "username", "ãç¨æ·è´¦å·ãå¿
须填åï¼ä¸åªè½ç± 4-30 使°åãåæ¯ç»æï¼ä¾å¦ zhangsanï¼", |
| | | "nickname", "ãç¨æ·æµç§°ãæå¤ 30 个å符", |
| | | "password", "ãåå§å¯ç ãé¿åº¦ä¸º 4-16 ä½", |
| | | "email", "ãç¨æ·é®ç®±ãæ ¼å¼ä¸æ£ç¡®ï¼è¯·å¡«åå½¢å¦ zhangsan@example.com çé®ç®±ï¼æç空该å", |
| | | "mobile", "ãææºå·ç ãæ ¼å¼ä¸æ£ç¡®ï¼è¯·å¡«å 11 使æºå·ï¼ä¾å¦ 13800000000ï¼ï¼æç空该å"); |
| | | |
| | | /** |
| | | * æ ¡éªåè¡çè´¦å·ãæµç§°ãå¯ç çåæ®µæ¯å¦ç¬¦åè¦æ± |
| | | * |
| | | * @param saveReqVO Excel è¡è½¬æ¢åºçç¨æ·ä¿¡æ¯ |
| | | * @param password è¯¥è¡æç»ä½¿ç¨çå¯ç |
| | | */ |
| | | private void validateUserImportRow(UserSaveReqVO saveReqVO, String password) { |
| | | if (StrUtil.isEmpty(password)) { |
| | | throw new ServiceException(USER_IMPORT_INIT_PASSWORD.getCode(), |
| | | "æªå¡«åãåå§å¯ç ãï¼ä¸ç³»ç»æ²¡æé
ç½®é»è®¤çåå§å¯ç ãè¯·å¨ Excel çãåå§å¯ç ãåå¡«å 4-16 ä½å¯ç ï¼" |
| | | + "æè®©ç®¡çåå¨ãåºç¡è®¾æ½ â é
置管çãä¸é
ç½® system.user.init-password"); |
| | | } |
| | | ValidationUtils.validate(saveReqVO); |
| | | } |
| | | |
| | | /** æ Bean æ ¡éªç»ææ´çæãåªä¸ªå段ãæä¹æ¹ã */ |
| | | private static String buildConstraintFailureMessage(ConstraintViolationException ex) { |
| | | List<String> messages = new ArrayList<>(); |
| | | ex.getConstraintViolations().forEach(violation -> { |
| | | // æ ¡éªçæ¯ Bean æ¬èº«ï¼å±æ§è·¯å¾å°±æ¯å段åï¼å¦ usernameï¼ï¼å
¼å®¹å¸¦åç¼çåæ³ |
| | | String path = violation.getPropertyPath().toString(); |
| | | String field = StrUtil.contains(path, '.') ? StrUtil.subAfter(path, '.', true) : path; |
| | | messages.add(StrUtil.blankToDefault(USER_IMPORT_FIELD_HINTS.get(field), violation.getMessage())); |
| | | }); |
| | | return String.join("ï¼", messages); |
| | | } |
| | | |
| | | /** æç³»ç»å
ç½®çæ ¡éªå¼å¸¸ï¼è¡¥å
æç¨æ·ç徿ãç¥éæä¹æ¹çæç¤º */ |
| | | private static String buildImportFailureMessage(ServiceException ex, UserImportExcelVO importUser) { |
| | | if (ObjUtil.equal(ex.getCode(), USER_USERNAME_EXISTS.getCode())) { |
| | | return "ç¨æ·è´¦å·å·²åå¨ï¼å¦éè¦ç请å¾éãæ¯å¦è¦çãå鿰坼å
¥ï¼å¦åè¯·ä¿®æ¹ Excel ä¸çç¨æ·è´¦å·"; |
| | | } |
| | | if (ObjUtil.equal(ex.getCode(), USER_MOBILE_EXISTS.getCode())) { |
| | | return StrUtil.format("ææºå·ç ã{}ã已被å
¶ä»ç¨æ·ä½¿ç¨ï¼è¯·æ´æ¢ææºå·ï¼æçç©ºãææºå·ç ãå", importUser.getMobile()); |
| | | } |
| | | if (ObjUtil.equal(ex.getCode(), USER_EMAIL_EXISTS.getCode())) { |
| | | return StrUtil.format("é®ç®±ã{}ã已被å
¶ä»ç¨æ·ä½¿ç¨ï¼è¯·æ´æ¢é®ç®±ï¼æç空ãç¨æ·é®ç®±ãå", importUser.getEmail()); |
| | | } |
| | | return ex.getMessage(); |
| | | } |
| | | |
| | | /** |
| | | * è§£æ Excelãé¨é¨ãåï¼æ¯æå¡«åé¨é¨åç§°ï¼ä¹å
¼å®¹å¡«åé¨é¨ç¼å· |
| | | * |
| | | * @param deptText Excel ä¸å¡«åçå
容ï¼å
许为空ï¼è¡¨ç¤ºæä¸å½å±é¨é¨ï¼ |
| | | * @return é¨é¨ç¼å· |
| | | */ |
| | | private Long parseDeptId(String deptText, List<DeptDO> deptList) { |
| | | if (StrUtil.isEmpty(deptText)) { |
| | | return null; |
| | | } |
| | | String text = StrUtil.trim(deptText); |
| | | // æ
åµä¸ï¼å¡«åçæ¯é¨é¨ç¼å· |
| | | if (StrUtil.isNumeric(text) && text.length() <= 18) { |
| | | long deptId = Long.parseLong(text); |
| | | DeptDO dept = deptList.stream().filter(item -> ObjUtil.equal(item.getId(), deptId)) |
| | | .findFirst().orElse(null); |
| | | if (dept == null) { |
| | | throw new ServiceException(USER_IMPORT_DEPT_NOT_EXISTS.getCode(), StrUtil.format( |
| | | "ãé¨é¨ãåå¡«åçé¨é¨ç¼å·ã{}ãä¸åå¨ï¼è¯·å¨ãç³»ç»ç®¡ç â é¨é¨ã䏿¥çæ£ç¡®çé¨é¨ç¼å·ï¼æç´æ¥å¡«åé¨é¨åç§°", text)); |
| | | } |
| | | validateMasterDataEnabled(dept.getStatus(), StrUtil.format("é¨é¨ã{}ãå·²åç¨", dept.getName()), |
| | | "请å
å¨ãç³»ç»ç®¡ç â é¨é¨ãä¸å¯ç¨è¯¥é¨é¨"); |
| | | return deptId; |
| | | } |
| | | // æ
åµäºï¼å¡«åçæ¯é¨é¨åç§° |
| | | List<DeptDO> matched = deptList.stream() |
| | | .filter(item -> StrUtil.equals(text, StrUtil.trim(item.getName()))).toList(); |
| | | if (matched.isEmpty()) { |
| | | throw new ServiceException(USER_IMPORT_DEPT_NOT_EXISTS.getCode(), StrUtil.format( |
| | | "ãé¨é¨ãåå¡«åçé¨é¨ã{}ãä¸åå¨ï¼è¯·å
å¨ãç³»ç»ç®¡ç â é¨é¨ãä¸åå»ºï¼ææ¹æå·²åå¨çé¨é¨åç§°/ç¼å·", text)); |
| | | } |
| | | if (matched.size() > 1) { |
| | | throw new ServiceException(USER_IMPORT_DEPT_NAME_DUPLICATE.getCode(), StrUtil.format( |
| | | "é¨é¨åç§°ã{}ãå¨ç³»ç»éæ {} 个ååé¨é¨ï¼è¯·æ¹å¡«ãé¨é¨ç¼å·ãï¼å¯å¨ãç³»ç»ç®¡ç â é¨é¨ã䏿¥çï¼", text, matched.size())); |
| | | } |
| | | DeptDO dept = matched.get(0); |
| | | validateMasterDataEnabled(dept.getStatus(), StrUtil.format("é¨é¨ã{}ãå·²åç¨", dept.getName()), |
| | | "请å
å¨ãç³»ç»ç®¡ç â é¨é¨ãä¸å¯ç¨è¯¥é¨é¨"); |
| | | return dept.getId(); |
| | | } |
| | | |
| | | /** |
| | | * è§£æ Excelãå²ä½ãåï¼å¡«åå²ä½åç§°ï¼å¤ä¸ªå²ä½ç¨ãããã,ãã;ãåé |
| | | * |
| | | * @return å²ä½ç¼å·éåï¼è³å°ä¸ä¸ª |
| | | */ |
| | | private Set<Long> parsePostIds(String postText, List<PostDO> postList) { |
| | | if (StrUtil.isEmpty(postText)) { |
| | | throw new ServiceException(USER_IMPORT_POST_EMPTY.getCode(), |
| | | "æªå¡«åãå²ä½ãï¼è¯·å¡«åå²ä½åç§°ï¼å¤ä¸ªå²ä½ç¨ãããåéï¼ä¾å¦ï¼æ®å·¥ãçç»é¿"); |
| | | } |
| | | Set<Long> postIds = new HashSet<>(); |
| | | List<String> notExistsNames = new ArrayList<>(); |
| | | for (String part : postText.split("[ã,ï¼;ï¼/\\s]+")) { |
| | | String name = StrUtil.trim(part); |
| | | if (StrUtil.isEmpty(name)) { |
| | | continue; |
| | | } |
| | | PostDO post = postList.stream().filter(item -> StrUtil.equals(name, StrUtil.trim(item.getName()))) |
| | | .findFirst().orElse(null); |
| | | if (post == null) { |
| | | notExistsNames.add(name); |
| | | continue; |
| | | } |
| | | validateMasterDataEnabled(post.getStatus(), StrUtil.format("å²ä½ã{}ãå·²åç¨", post.getName()), |
| | | "请å
å¨ãç³»ç»ç®¡ç â å²ä½ãä¸å¯ç¨è¯¥å²ä½"); |
| | | postIds.add(post.getId()); |
| | | } |
| | | if (!notExistsNames.isEmpty()) { |
| | | throw new ServiceException(USER_IMPORT_POST_NOT_EXISTS.getCode(), StrUtil.format( |
| | | "ãå²ä½ãåå¡«åçå²ä½ã{}ãä¸åå¨ï¼è¯·å
å¨ãç³»ç»ç®¡ç â å²ä½ãä¸ç»´æ¤ï¼ææ¹æå·²åå¨çå²ä½åç§°", |
| | | String.join("ã", notExistsNames))); |
| | | } |
| | | if (postIds.isEmpty()) { // ä¾å¦åªå¡«äºåé符 |
| | | throw new ServiceException(USER_IMPORT_POST_EMPTY.getCode(), |
| | | "æªå¡«åãå²ä½ãï¼è¯·å¡«åå²ä½åç§°ï¼å¤ä¸ªå²ä½ç¨ãããåéï¼ä¾å¦ï¼æ®å·¥ãçç»é¿"); |
| | | } |
| | | return postIds; |
| | | } |
| | | |
| | | /** æ ¡éªé¨é¨ãå²ä½æ¯å¦å¤äºå¼å¯ç¶æ */ |
| | | private static void validateMasterDataEnabled(Integer status, String disabledTip, String actionTip) { |
| | | if (ObjUtil.equal(status, CommonStatusEnum.DISABLE.getStatus())) { |
| | | throw new ServiceException(USER_IMPORT_MASTER_DATA_DISABLED.getCode(), |
| | | StrUtil.format("{}ï¼{}", disabledTip, actionTip)); |
| | | } |
| | | } |
| | | |
| | | /** åå
¥ç¨æ·ä¸å²ä½çå
³èï¼å¯¼å
¥åºæ¥çç¨æ·åæ ·è¦æå²ä½ï¼å¦åå¨é¡µé¢ä¸ç¼è¾ä¿åä¸äºï¼ */ |
| | | private void insertUserPost(Long userId, Set<Long> postIds) { |
| | | if (CollUtil.isEmpty(postIds)) { |
| | | return; |
| | | } |
| | | userPostMapper.insertBatch(convertList(postIds, |
| | | postId -> new UserPostDO().setUserId(userId).setPostId(postId))); |
| | | } |
| | | |
| | | @Override |
| | | public List<AdminUserDO> getUserListByStatus(Integer status) { |
| | | return userMapper.selectListByStatus(status); |