feat(hrm): 调岗申请新增「调岗人」选择并自动带出原部门/原岗位;修复部门名称与调岗人为空

- 员工精简接口补充 deptId / postIds / postName(供调岗等场景自动带出原岗位)
- 调岗申请创建时 userId 按「员工ID」处理,修正原先用系统用户校验导致被回退为登录用户的 bug
- 调岗申请列表/详情的 userName 改按员工表填充(原按系统用户,显示成错误的人)
- 部门 getDeptList 禁用数据权限过滤(部门是组织架构基础数据),修复非超管部门下拉只有1条、deptName 全空的问题
已修改4个文件
96 ■■■■■ 文件已修改
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSimpleRespVO.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSimpleRespVO.java
@@ -3,6 +3,8 @@
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 员工简单信息 Response VO")
@Data
public class HrmEmployeeSimpleRespVO {
@@ -16,9 +18,18 @@
    @Schema(description = "员工姓名")
    private String name;
    @Schema(description = "部门ID")
    private Long deptId;
    @Schema(description = "部门名称")
    private String deptName;
    @Schema(description = "岗位ID列表")
    private List<Long> postIds;
    @Schema(description = "岗位名称(多个用逗号分隔)")
    private String postName;
    @Schema(description = "员工状态")
    private Integer employeeStatus;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/approval/HrmTransferApplicationServiceImpl.java
@@ -13,7 +13,9 @@
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationRespVO;
import cn.iocoder.yudao.module.hrm.controller.admin.approval.vo.HrmTransferApplicationSaveReqVO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.approval.HrmTransferApplicationDO;
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.approval.HrmTransferApplicationMapper;
import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService;
import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum;
import cn.iocoder.yudao.module.hrm.enums.HrmTransferTypeEnum;
@@ -66,6 +68,8 @@
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private HrmEmployeeService employeeService;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource
    private BpmCategoryService bpmCategoryService;
@@ -87,14 +91,14 @@
        }
        // 3. 生成申请单号
        String no = generateUniqueNo();
        // 4. 设置申请人信息
        // 4. 设置调岗人(员工ID):为空时取当前登录用户对应的员工
        Long userId = createReqVO.getUserId();
        if (userId == null) {
            userId = getCurrentUserId();
            HrmEmployeeDO currentEmployee = employeeService.getEmployeeByUserId(getCurrentUserId());
            userId = currentEmployee != null ? currentEmployee.getId() : null;
        }
        AdminUserRespDTO user = adminUserApi.getUser(userId);
        if (user == null) {
            userId = getCurrentUserId();
        if (userId != null && employeeService.getEmployee(userId) == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        // 5. 插入
        HrmTransferApplicationDO application = BeanUtils.toBean(createReqVO, HrmTransferApplicationDO.class);
@@ -168,9 +172,9 @@
        }
        HrmTransferApplicationRespVO respVO = BeanUtils.toBean(application, HrmTransferApplicationRespVO.class);
        if (application.getUserId() != null) {
            AdminUserRespDTO user = adminUserApi.getUser(application.getUserId());
            if (user != null) {
                respVO.setUserName(user.getNickname());
            HrmEmployeeDO employee = employeeService.getEmployee(application.getUserId());
            if (employee != null) {
                respVO.setUserName(employee.getName());
            }
        }
        fillDeptNames(respVO, application);
@@ -215,7 +219,14 @@
                .map(HrmTransferApplicationDO::getUserId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
        // userId 存的是员工ID,按员工表查询姓名
        Map<Long, String> employeeNameMap = new HashMap<>();
        for (Long userId : userIds) {
            HrmEmployeeDO employee = employeeService.getEmployee(userId);
            if (employee != null) {
                employeeNameMap.put(userId, employee.getName());
            }
        }
        Set<Long> deptIds = pageResult.getList().stream()
                .flatMap(app -> Stream.of(app.getCurrentDeptId(), app.getTargetDeptId()))
                .filter(Objects::nonNull)
@@ -228,8 +239,8 @@
        Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
        List<HrmTransferApplicationRespVO> list = pageResult.getList().stream().map(app -> {
            HrmTransferApplicationRespVO vo = BeanUtils.toBean(app, HrmTransferApplicationRespVO.class);
            if (app.getUserId() != null && userMap.containsKey(app.getUserId())) {
                vo.setUserName(userMap.get(app.getUserId()).getNickname());
            if (app.getUserId() != null && employeeNameMap.containsKey(app.getUserId())) {
                vo.setUserName(employeeNameMap.get(app.getUserId()));
            }
            if (app.getCurrentDeptId() != null && deptMap.containsKey(app.getCurrentDeptId())) {
                vo.setCurrentDeptName(deptMap.get(app.getCurrentDeptId()).getName());
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -48,6 +48,7 @@
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -370,19 +371,68 @@
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds);
        // 解析岗位ID(post_ids 存的是 JSON 数组字符串,如 [38]),并批量加载岗位名称
        Map<Long, List<Long>> empPostIdsMap = new LinkedHashMap<>();
        Set<Long> allPostIds = new LinkedHashSet<>();
        for (HrmEmployeeDO emp : list) {
            List<Long> postIdList = parseEmployeePostIds(emp.getPostIds());
            empPostIdsMap.put(emp.getId(), postIdList);
            allPostIds.addAll(postIdList);
        }
        Map<Long, PostRespDTO> postMap = CollUtil.isEmpty(allPostIds)
                ? Collections.emptyMap() : postApi.getPostMap(allPostIds);
        return list.stream().map(emp -> {
            HrmEmployeeSimpleRespVO vo = new HrmEmployeeSimpleRespVO();
            vo.setId(emp.getId());
            vo.setEmployeeNo(emp.getEmployeeNo());
            vo.setName(emp.getName());
            vo.setEmployeeStatus(emp.getEmployeeStatus());
            vo.setDeptId(emp.getDeptId());
            if (emp.getDeptId() != null && deptMap.containsKey(emp.getDeptId())) {
                vo.setDeptName(deptMap.get(emp.getDeptId()).getName());
            }
            // 岗位信息(用于调岗等场景自动带出原岗位)
            List<Long> postIdList = empPostIdsMap.getOrDefault(emp.getId(), Collections.emptyList());
            vo.setPostIds(postIdList);
            if (CollUtil.isNotEmpty(postIdList)) {
                vo.setPostName(postIdList.stream()
                        .map(postMap::get)
                        .filter(Objects::nonNull)
                        .map(PostRespDTO::getName)
                        .collect(Collectors.joining(",")));
            }
            return vo;
        }).collect(Collectors.toList());
    }
    /**
     * 解析员工的岗位ID字符串(JSON 数组格式,如 [38] 或 [1,2])
     */
    /**
     * 解析员工岗位ID字符串(post_ids 存 JSON 数组,如 [38] 或 [1,2])
     */
    private java.util.List<Long> parseEmployeePostIds(String postIds) {
        if (StrUtil.isBlank(postIds)) {
            return Collections.emptyList();
        }
        // post_ids 形如 "[38]" 或 "[1,2]":去掉中括号后按逗号解析
        return Arrays.stream(postIds.replace("[", "").replace("]", "").split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .map(s -> {
                    try {
                        return Long.valueOf(s);
                    } catch (NumberFormatException ex) {
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
    @Override
    public HrmEmployeeDO getEmployeeByUserId(Long userId) {
        return employeeMapper.selectByUserId(userId);
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
@@ -174,6 +174,7 @@
    }
    @Override
    @DataPermission(enable = false) // 部门属于组织架构基础数据,供下拉/名称回显使用,不做数据权限过滤
    public List<DeptDO> getDeptList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
@@ -182,6 +183,7 @@
    }
    @Override
    @DataPermission(enable = false) // 同上:避免非超管只能看到本部门,导致部门下拉/名称展示缺失
    public List<DeptDO> getDeptList(DeptListReqVO reqVO) {
        List<DeptDO> list = deptMapper.selectList(reqVO);
        list.sort(Comparator.comparing(DeptDO::getSort));