陈昶聿
3 天以前 3d047130b059efd46f56be37465a751ab16ee8cb
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -18,6 +18,7 @@
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.common.core.service.IUserExtInfoService;
import com.ruoyi.common.core.service.ISatisfactionCategoryService;
import com.ruoyi.system.mapper.SysUserDeptMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -84,6 +85,10 @@
    @Value("${isAdmin}")
    private List<Long> isAdmin;
    @Value("${spring.profiles.active}")
    private String active;
    /**
     * 根据条件分页查询用户列表
     *
@@ -141,7 +146,10 @@
            deptIds.add(sysDept.getDeptId());
        }
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(sysUser.getUserId());
        // 管理员:不按用户过滤(sys_user_dept 里没有 admin 的数据),直接取本机构全部科室/病区
        if (!isAdminUser(sysUser)) {
            sysUserDept.setUserId(sysUser.getUserId());
        }
        sysUserDept.setDeptType(sysUser.getSearchscope());
        sysUserDept.setOrgid(sysUser.getOrgid());
        List<SysUserDept> sysUserDeptKSs = null;
@@ -196,7 +204,7 @@
        if (sysUser.getUserType().equals("患者") && StringUtils.isNotEmpty(split[3]) && !split[3].equals("null") && !sysUser.getUserType().equals(split[3].trim()))
            throw new BaseException("当前用户类型与登录用户类型不一致");
        boolean isAdmin = StringUtils.isNotEmpty(split[0]) && "admin".equals(split[0]);
        boolean isAdmin = isAdminUser(sysUser);
        IUserExtInfoService userExtInfoService = SpringUtils.getBean(IUserExtInfoService.class);
        Executor executor = SpringUtils.getBean("threadPoolTaskExecutor");
@@ -215,7 +223,7 @@
        // 等待机构信息
        Map<String, String> userOrgInfo = new HashMap<>();
        try {
            userOrgInfo = orgInfoFuture.get(5, TimeUnit.SECONDS);
            userOrgInfo = orgInfoFuture.get(50, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.warn("获取用户机构信息超时或异常", e);
        }
@@ -253,8 +261,8 @@
                    CompletableFuture<List<SysDept>> ksFuture = CompletableFuture.supplyAsync(() -> selectLeafSysDeptForAdmin(deptKS), executor);
                    CompletableFuture<List<SysDept>> bqFuture = CompletableFuture.supplyAsync(() -> selectLeafSysDeptForAdmin(deptBQ), executor);
                    try {
                        sysUserDeptKSs = distinctByDeptCode(DtoConversionUtils.sourceToTarget(ksFuture.get(5, TimeUnit.SECONDS), SysUserDept.class));
                        sysUserDeptBQs = distinctByDeptCode(DtoConversionUtils.sourceToTarget(bqFuture.get(5, TimeUnit.SECONDS), SysUserDept.class));
                        sysUserDeptKSs = distinctByDeptCode(DtoConversionUtils.sourceToTarget(ksFuture.get(50, TimeUnit.SECONDS), SysUserDept.class));
                        sysUserDeptBQs = distinctByDeptCode(DtoConversionUtils.sourceToTarget(bqFuture.get(50, TimeUnit.SECONDS), SysUserDept.class));
                    } catch (Exception e) {
                        log.warn("获取admin科室/病区信息超时或异常", e);
                    }
@@ -319,9 +327,57 @@
            }
            sysUser.setBelongDepts(list);
            // 设置满意度分类(走缓存)
            sysUser.setSatisfactionCategories(userExtInfoService.getSatisfactionCategories(sysUser.getOrgid()));
            // 满意度模块化后:不再经由 smartor 的 IUserExtInfoService,
            // 改为按 ruoyi-common 的 ISatisfactionCategoryService 接口查找实现
            // (实现在 ruoyi-satisfaction,由常驻门面保证"模块关闭/缺失时返回空 Map")
            sysUser.setSatisfactionCategories(loadSatisfactionCategories(sysUser.getOrgid()));
        }
        return sysUser;
    }
    /**
     * 安全地获取满意度分类。
     * <p>
     * 满意度模块可以被配置关闭({@code sys_config} 参数 {@code satisfaction.enabled=false}),也可以整体不在依赖里;
     * 这两种情况下都必须<b>不影响登录主流程</b>,因此这里:
     * <ul>
     *   <li>容器里没有 {@code ISatisfactionCategoryService} 实现时返回空 Map;</li>
     *   <li>调用过程中抛任何异常也只记日志并返回空 Map。</li>
     * </ul>
     *
     * @param orgid 机构ID
     * @return 满意度分类;不可用时返回空 Map(不会返回 null)
     */
    private Map<String, Object> loadSatisfactionCategories(String orgid) {
        try {
            ISatisfactionCategoryService satisfactionCategoryService =
                    SpringUtils.getBean(ISatisfactionCategoryService.class);
            if (satisfactionCategoryService == null) {
                return Collections.emptyMap();
            }
            Map<String, Object> categories = satisfactionCategoryService.getSatisfactionCategories(orgid);
            return categories == null ? Collections.emptyMap() : categories;
        } catch (Exception e) {
            log.warn("获取满意度分类失败,已降级为空结果(不影响登录)。orgid={}", orgid, e);
            return Collections.emptyMap();
        }
    }
    /**
     * 是否管理员:账号名为 admin,或用户ID命中配置项 isAdmin。
     * <p>
     * 管理员取科室/病区时不按 sys_user_dept 过滤——HIS 采集写该表时明确排除了 admin
     * (CollectHISMapper 的 yhyksxx/yhybfxx 都有 {@code ud.user_id != 'admin'}),
     * 走关联查询会得到空列表,表现为「登录成功但创建任务时选不到科室病区」。
     */
    private boolean isAdminUser(SysUser sysUser) {
        if (sysUser == null) {
            return false;
        }
        if ("admin".equalsIgnoreCase(sysUser.getUserName())) {
            return true;
        }
        return sysUser.getUserId() != null && isAdmin != null && isAdmin.contains(sysUser.getUserId());
    }
    /**
@@ -346,7 +402,8 @@
    @Override
    public SysUser selectUserByUserNameAndDeptId(String userName) {
        String[] split = userName.split("&");
        if (split[2].contains("null")) {
        //南华附一也不验证dept_id了
        if (split[2].contains("null") || active.equals("nhfy")) {
            split[2] = null;
        }
        SysUser sysUser = userMapper.selectUserByUserNameByCondition(split[0], split[1], split[2]);
@@ -985,8 +1042,11 @@
    public List<SysUserDept> selectLeafSysDeptList(SysUserDept sysUserDept){
        List<SysDept> list =  sysDeptMapper.selectSysDeptListBySysUserDept(sysUserDept);
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
            list = TreeUtils.getLeafDepts(list);
        // userId 为空 = 管理员取本机构全量:要「所有科室病区」,不能再按叶子节点过滤
        if (sysUserDept == null || sysUserDept.getUserId() != null) {
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
                list = TreeUtils.getLeafDepts(list);
            }
        }
        List<SysUserDept> list1 = DtoConversionUtils.sourceToTarget(list, SysUserDept.class);
        return list1;
@@ -994,11 +1054,9 @@
    public List<SysDept> selectLeafSysDeptForAdmin(SysDept sysDept){
        SysUserDept sysUserDept = DtoConversionUtils.sourceToTarget(sysDept, SysUserDept.class);
        List<SysDept> list =  sysDeptMapper.selectSysDeptListBySysUserDept(sysUserDept);
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
            list = TreeUtils.getLeafDepts(list);
        }
        return list;
        // 管理员分支:sysUserDept 不带 userId,mapper 会直接查 sys_dept(不关联 sys_user_dept),
        // 返回本机构全部科室/病区;这里不再做叶子过滤,否则「所有科室病区」会被砍掉父级部门。
        return sysDeptMapper.selectSysDeptListBySysUserDept(sysUserDept);
    }
    /**