From c3b0503f8e2ecf955d0e8e4ca9294e6cd5199c0b Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期四, 27 八月 2026 11:02:30 +0800
Subject: [PATCH] HRM: 员工台账岗位支持多选并同步系统用户岗位

---
 yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java |  206 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 196 insertions(+), 10 deletions(-)

diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
index 58632cf..c326a89 100644
--- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
+++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -3,10 +3,14 @@
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeEducationSaveReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeEmergencyContactSaveReqVO;
+import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportExcelVO;
+import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportReqVO;
+import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeImportRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeePageReqVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeRespVO;
 import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeeSaveReqVO;
@@ -29,13 +33,18 @@
 import cn.iocoder.yudao.module.system.api.permission.dto.RoleRespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserCreateReqDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserUpdateReqDTO;
 import jakarta.annotation.Resource;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -43,12 +52,13 @@
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*;
 
 /**
  * 鍛樺伐淇℃伅 Service 瀹炵幇绫�
  *
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
  */
 @Service
 @Validated
@@ -72,6 +82,9 @@
     private AdminUserApi adminUserApi;
     @Resource
     private RoleApi roleApi;
+    @Resource
+    @Lazy // 鑷敞鍏ラ渶寤惰繜鍔犺浇锛屽惁鍒� bean 琚唬鐞嗗寘瑁呭悗娉ㄥ叆鍘熷鐗堟湰瀵艰嚧鍚姩澶辫触
+    private HrmEmployeeService self;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -79,7 +92,7 @@
         // 1. 鏍¢獙閮ㄩ棬
         deptApi.validateDeptList(Collections.singleton(createReqVO.getDeptId()));
         // 2. 鏍¢獙宀椾綅
-        postApi.validPostList(Collections.singleton(createReqVO.getPostId()));
+        postApi.validPostList(createReqVO.getPostIds());
         // 3. 鏍¢獙鎵嬫満鍙锋槸鍚﹀凡瀛樺湪
         if (employeeMapper.selectByPhone(createReqVO.getPhone()) != null) {
             throw exception(EMPLOYEE_PHONE_EXISTS);
@@ -89,7 +102,7 @@
         userCreateReqDTO.setUsername(createReqVO.getPhone());
         userCreateReqDTO.setNickname(createReqVO.getName());
         userCreateReqDTO.setDeptId(createReqVO.getDeptId());
-        userCreateReqDTO.setPostIds(Collections.singleton(createReqVO.getPostId()));
+        userCreateReqDTO.setPostIds(new LinkedHashSet<>(createReqVO.getPostIds()));
         userCreateReqDTO.setMobile(createReqVO.getPhone());
         userCreateReqDTO.setPassword(createReqVO.getPhone());
         userCreateReqDTO.setSex(createReqVO.getGender());
@@ -109,6 +122,10 @@
         // roleIds 瀛樺偍涓� JSON
         if (CollUtil.isNotEmpty(createReqVO.getRoleIds())) {
             employee.setRoleIds(JSONUtil.toJsonStr(createReqVO.getRoleIds()));
+        }
+        // postIds 瀛樺偍涓� JSON
+        if (CollUtil.isNotEmpty(createReqVO.getPostIds())) {
+            employee.setPostIds(JSONUtil.toJsonStr(createReqVO.getPostIds()));
         }
         employeeMapper.insert(employee);
         Long employeeId = employee.getId();
@@ -155,7 +172,7 @@
         // 鏍¢獙閮ㄩ棬
         deptApi.validateDeptList(Collections.singleton(updateReqVO.getDeptId()));
         // 鏍¢獙宀椾綅
-        postApi.validPostList(Collections.singleton(updateReqVO.getPostId()));
+        postApi.validPostList(updateReqVO.getPostIds());
         // 鏍¢獙鎵嬫満鍙锋槸鍚﹀凡瀛樺湪锛堝鏋滄墜鏈哄彿鏈夊彉鏇达級
         if (!Objects.equals(employee.getPhone(), updateReqVO.getPhone())
                 && employeeMapper.selectByPhone(updateReqVO.getPhone()) != null) {
@@ -167,7 +184,24 @@
         if (CollUtil.isNotEmpty(updateReqVO.getRoleIds())) {
             updateObj.setRoleIds(JSONUtil.toJsonStr(updateReqVO.getRoleIds()));
         }
+        // postIds 瀛樺偍涓� JSON
+        if (CollUtil.isNotEmpty(updateReqVO.getPostIds())) {
+            updateObj.setPostIds(JSONUtil.toJsonStr(updateReqVO.getPostIds()));
+        }
         employeeMapper.updateById(updateObj);
+        // 鍚屾鏇存柊鍏宠仈绯荤粺鐢ㄦ埛锛堝矖浣�/閮ㄩ棬/鏄电О/瑙掕壊/閭/澶囨敞锛夛紝淇濇寔涓庣敤鎴风鐞嗕竴鑷�
+        if (employee.getUserId() != null) {
+            AdminUserUpdateReqDTO userUpdateReqDTO = new AdminUserUpdateReqDTO();
+            userUpdateReqDTO.setId(employee.getUserId());
+            userUpdateReqDTO.setNickname(updateReqVO.getName());
+            userUpdateReqDTO.setDeptId(updateReqVO.getDeptId());
+            userUpdateReqDTO.setPostIds(new LinkedHashSet<>(updateReqVO.getPostIds()));
+            userUpdateReqDTO.setRoleIds(CollUtil.isEmpty(updateReqVO.getRoleIds()) ? null
+                    : new LinkedHashSet<>(updateReqVO.getRoleIds()));
+            userUpdateReqDTO.setEmail(updateReqVO.getEmail());
+            userUpdateReqDTO.setRemark(updateReqVO.getRemark());
+            adminUserApi.updateUser(userUpdateReqDTO);
+        }
         Long employeeId = updateReqVO.getId();
 
         // 鍚屾鏁欒偛缁忓巻
@@ -258,12 +292,16 @@
                 respVO.setDeptName(dept.getName());
             }
         }
-        // 濉厖宀椾綅鍚嶇О
-        if (employee.getPostId() != null) {
-            Map<Long, PostRespDTO> postMap = postApi.getPostMap(Collections.singleton(employee.getPostId()));
-            PostRespDTO post = postMap.get(employee.getPostId());
-            if (post != null) {
-                respVO.setPostName(post.getName());
+        // 濉厖宀椾綅淇℃伅
+        if (StrUtil.isNotBlank(employee.getPostIds())) {
+            List<Long> postIds = JSONUtil.toList(employee.getPostIds(), Long.class);
+            respVO.setPostIds(postIds);
+            if (CollUtil.isNotEmpty(postIds)) {
+                Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
+                respVO.setPostNames(postIds.stream()
+                        .filter(postMap::containsKey)
+                        .map(postId -> postMap.get(postId).getName())
+                        .collect(Collectors.joining(",")));
             }
         }
         // 濉厖瑙掕壊鍚嶇О
@@ -322,4 +360,152 @@
         return employeeMapper.selectByUserId(userId);
     }
 
+    @Override
+    public HrmEmployeeDO getEmployeeByName(String name) {
+        return employeeMapper.selectByName(name);
+    }
+
+    @Override
+    public List<HrmEmployeeDO> getEmployeeListByName(String name) {
+        return employeeMapper.selectListByName(name);
+    }
+
+    @Override
+    public HrmEmployeeImportRespVO importEmployeeList(List<HrmEmployeeImportExcelVO> importEmployees,
+                                                      HrmEmployeeImportReqVO importReqVO) {
+        // 1. 鏍¢獙闈炵┖
+        importEmployees = filterList(importEmployees, item -> Objects.nonNull(item.getName()));
+        if (CollUtil.isEmpty(importEmployees)) {
+            throw exception(EMPLOYEE_IMPORT_LIST_IS_EMPTY);
+        }
+        // 2. 棰勫姞杞介儴闂�/宀椾綅/瑙掕壊 鍚嶇О -> 瀹炰綋 鏄犲皠
+        Map<String, DeptRespDTO> deptMap = deptApi.getDeptList().stream()
+                .collect(Collectors.toMap(DeptRespDTO::getName, dept -> dept, (v1, v2) -> v1));
+        Map<String, PostRespDTO> postMap = postApi.getPostList().stream()
+                .collect(Collectors.toMap(PostRespDTO::getName, post -> post, (v1, v2) -> v1));
+        Map<String, RoleRespDTO> roleMap = roleApi.getRoleList().stream()
+                .collect(Collectors.toMap(RoleRespDTO::getName, role -> role, (v1, v2) -> v1));
+        // 3. 閫愭潯澶勭悊
+        HrmEmployeeImportRespVO respVO = HrmEmployeeImportRespVO.builder()
+                .createNames(new ArrayList<>())
+                .updateNames(new ArrayList<>())
+                .failureNames(new LinkedHashMap<>())
+                .build();
+        for (HrmEmployeeImportExcelVO importEmployee : importEmployees) {
+            String name = importEmployee.getName();
+            try {
+                // 3.1 鍚嶇О杞� ID
+                Long deptId = parseDeptId(importEmployee.getDeptName(), deptMap);
+                Set<Long> postIds = parsePostIds(importEmployee.getPostName(), postMap);
+                Set<Long> roleIds = parseRoleIds(importEmployee.getRoleNames(), roleMap);
+                // 3.2 鏋勫缓淇濆瓨璇锋眰
+                HrmEmployeeSaveReqVO saveReqVO = buildImportSaveReqVO(importEmployee, deptId, postIds, roleIds);
+                // 3.3 鍒ゆ柇瀛樺湪鎬э細鎸夋墜鏈哄彿
+                HrmEmployeeDO existEmployee = employeeMapper.selectByPhone(importEmployee.getPhone());
+                if (existEmployee == null) {
+                    self.createEmployee(saveReqVO);
+                    respVO.getCreateNames().add(name);
+                } else {
+                    if (!Boolean.TRUE.equals(importReqVO.getUpdateSupport())) {
+                        respVO.getFailureNames().put(name, EMPLOYEE_PHONE_EXISTS.getMsg());
+                        continue;
+                    }
+                    saveReqVO.setId(existEmployee.getId());
+                    self.updateEmployee(saveReqVO);
+                    respVO.getUpdateNames().add(name);
+                }
+            } catch (ServiceException ex) {
+                respVO.getFailureNames().put(name, ex.getMessage());
+            } catch (Exception ex) {
+                respVO.getFailureNames().put(name, ex.getMessage());
+            }
+        }
+        return respVO;
+    }
+
+    private HrmEmployeeSaveReqVO buildImportSaveReqVO(HrmEmployeeImportExcelVO importEmployee,
+                                                      Long deptId, Set<Long> postIds, Set<Long> roleIds) {
+        if (StrUtil.isBlank(importEmployee.getName())) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鍛樺伐濮撳悕");
+        }
+        if (StrUtil.isBlank(importEmployee.getPhone())) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鎵嬫満鍙�");
+        }
+        if (importEmployee.getHireDate() == null) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "鍏ヨ亴鏃ユ湡");
+        }
+        HrmEmployeeSaveReqVO reqVO = new HrmEmployeeSaveReqVO();
+        reqVO.setName(importEmployee.getName());
+        reqVO.setGender(importEmployee.getGender() != null ? importEmployee.getGender() : 1); // 榛樿鐢�
+        reqVO.setPhone(importEmployee.getPhone());
+        reqVO.setDeptId(deptId);
+        reqVO.setPostIds(CollUtil.isEmpty(postIds) ? null : new ArrayList<>(postIds));
+        reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds));
+        reqVO.setHireDate(importEmployee.getHireDate());
+        reqVO.setEmployeeStatus(importEmployee.getEmployeeStatus() != null
+                ? importEmployee.getEmployeeStatus() : 1); // 榛樿鍦ㄨ亴
+        reqVO.setEmail(importEmployee.getEmail());
+        reqVO.setBirthday(importEmployee.getBirthday());
+        reqVO.setIdCard(importEmployee.getIdCard());
+        reqVO.setNation(importEmployee.getNation());
+        reqVO.setMarriageStatus(importEmployee.getMarriageStatus());
+        reqVO.setAge(importEmployee.getAge());
+        reqVO.setEducation(importEmployee.getEducation());
+        reqVO.setPoliticalStatus(importEmployee.getPoliticalStatus());
+        reqVO.setRemark(importEmployee.getRemark());
+        return reqVO;
+    }
+
+    private Long parseDeptId(String deptName, Map<String, DeptRespDTO> deptMap) {
+        if (StrUtil.isBlank(deptName)) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "閮ㄩ棬鍚嶇О");
+        }
+        DeptRespDTO dept = deptMap.get(deptName.trim());
+        if (dept == null) {
+            throw exception(EMPLOYEE_DEPT_NAME_NOT_EXISTS, deptName.trim());
+        }
+        return dept.getId();
+    }
+
+    private Set<Long> parsePostIds(String postNames, Map<String, PostRespDTO> postMap) {
+        if (StrUtil.isBlank(postNames)) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "宀椾綅鍚嶇О");
+        }
+        Set<Long> postIds = new LinkedHashSet<>();
+        for (String postName : postNames.split("[,锛宂")) {
+            String trimmed = postName.trim();
+            if (StrUtil.isBlank(trimmed)) {
+                continue;
+            }
+            PostRespDTO post = postMap.get(trimmed);
+            if (post == null) {
+                throw exception(EMPLOYEE_POST_NAME_NOT_EXISTS, trimmed);
+            }
+            postIds.add(post.getId());
+        }
+        if (CollUtil.isEmpty(postIds)) {
+            throw exception(EMPLOYEE_IMPORT_FIELD_REQUIRED, "宀椾綅鍚嶇О");
+        }
+        return postIds;
+    }
+
+    private Set<Long> parseRoleIds(String roleNames, Map<String, RoleRespDTO> roleMap) {
+        if (StrUtil.isBlank(roleNames)) {
+            return Collections.emptySet();
+        }
+        Set<Long> roleIds = new LinkedHashSet<>();
+        for (String roleName : roleNames.split("[,锛宂")) {
+            String trimmed = roleName.trim();
+            if (StrUtil.isBlank(trimmed)) {
+                continue;
+            }
+            RoleRespDTO role = roleMap.get(trimmed);
+            if (role == null) {
+                throw exception(EMPLOYEE_ROLE_NAME_NOT_EXISTS, trimmed);
+            }
+            roleIds.add(role.getId());
+        }
+        return roleIds;
+    }
+
 }
\ No newline at end of file

--
Gitblit v1.9.3