陈昶聿
3 天以前 1958e8bad428b94aa457734f7f047fe373eafd83
Merge branch 'smartor_ls_261103' into smartor_ls_merge
已修改5个文件
已添加1个文件
189 ■■■■■ 文件已修改
.gitignore 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
# ==================== æž„建产物 ====================
target/
out/
*.class
# ==================== IDE / ç¼–辑器 ====================
.idea/
*.iml
*.ipr
*.iws
.vscode/
.settings/
.project
.classpath
# ==================== ä¸´æ—¶ç›®å½• ====================
tmp/
.tmp/
_backups/
recovered/
__pycache__/
*.pyc
# ==================== å¤‡ä»½ä¸Žä¸´æ—¶æ–‡ä»¶ ====================
*.bak
*.bak[0-9]
*.bak-*
*.bak[0-9]-*
*.orig
*.rej
*~
# ==================== ä¸€æ¬¡æ€§æŽ’查脚本 / æŽ¢é’ˆ / æ—¥å¿—(不入库) ====================
# sql/ ä¸‹çš„一次性修复、排查、开关配置脚本仅本地留存,不入库;
# ä»…保留包内基线脚本与新库初始化脚本。
/sql/*.sql
!/sql/quartz.sql
!/sql/ry_20220822.sql
!/sql/pat_specific_archive_generate_config_lishui_mch_20261104.sql
sql/_probe/
*.log
_dbcheck.txt
package-lock.json
# ==================== æœ¬åœ°ä¸´æ—¶é…ç½® ====================
ruoyi-admin/src/main/resources/tempfile_*.yml
ruoyi-admin/src/main/resources/logback-backup.xml
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -63,6 +63,12 @@
    @Value("${spring.profiles.active}")
    private String active;
    /**
     * ç®¡ç†å‘˜ç”¨æˆ·ID列表(配置项 isAdmin)。管理员不受「用户-部门关系表」限制,直接看本机构全部科室/病区。
     */
    @Value("${isAdmin:1}")
    private List<Long> isAdmin;
//    @Value("${wx_appid}")
//    private String wxAppid;
//
@@ -240,23 +246,43 @@
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        List<SysDept> sysDeptKSs = null;
        List<SysDept> sysDeptBQs = null;
        // ç§‘室/病区下拉的数据源:
        //   Â· ç®¡ç†å‘˜ï¼ˆè´¦å· admin,或命中配置 isAdmin çš„用户ID):直接查 sys_dept å–本机构全部科室/病区,
        //     ä¸å†å…³è” sys_user_dept,也不按院区过滤——管理员天然拥有全部科室权限;
        //   Â· æ™®é€šç”¨æˆ·ï¼šä»ç„¶æŒ‰ã€Œç”¨æˆ·-部门关系表」只返回自己名下的科室/病区(保持原逻辑)。
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(user.getUserId());
        sysUserDept.setDeptType("1");
        sysUserDept.setOrgid(user.getOrgid());
        if (!isAdminUser(user)) {
            sysUserDept.setUserId(user.getUserId());
        sysUserDept.setCampusid(user.getCampusid());
        sysDeptKSs = sysDeptService.selectLeafSysDeptListBySysUserDept(sysUserDept);
        }
        sysUserDept.setDeptType("1");
        List<SysDept> sysDeptKSs = sysDeptService.selectLeafSysDeptListBySysUserDept(sysUserDept);
        ajax.put("belongDepts", sysDeptKSs);
        sysUserDept.setDeptType("2");
        sysDeptBQs = sysDeptService.selectLeafSysDeptListBySysUserDept(sysUserDept);
        List<SysDept> sysDeptBQs = sysDeptService.selectLeafSysDeptListBySysUserDept(sysUserDept);
        ajax.put("belongWards", sysDeptBQs);
        return ajax;
    }
    /**
     * æ˜¯å¦ç®¡ç†å‘˜ï¼šè´¦å·åä¸º admin,或用户ID命中配置项 isAdmin。
     * <p>
     * ç®¡ç†å‘˜å–科室/病区时不走 sys_user_dept(HIS é‡‡é›†æ˜Žç¡®æŽ’除 admin,该表里管理员没有数据),
     * å¦åˆ™ä¼šå‡ºçŽ°ã€Œç™»å½•æˆåŠŸä½†ç§‘å®¤/病区下拉为空」。
     */
    private boolean isAdminUser(SysUser user) {
        if (user == null) {
            return false;
        }
        if ("admin".equalsIgnoreCase(user.getUserName())) {
            return true;
        }
        return user.getUserId() != null && isAdmin != null && isAdmin.contains(user.getUserId());
    }
    /**
     * èŽ·å–è·¯ç”±ä¿¡æ¯
     *
     * @return è·¯ç”±ä¿¡æ¯
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -334,6 +334,10 @@
    public List<SysDept> selectLeafSysDeptListBySysUserDept(SysUserDept sysUserDept){
        List<SysDept> list =  deptMapper.selectSysDeptListBySysUserDept(sysUserDept);
        // userId ä¸ºç©º = ç®¡ç†å‘˜å–本机构全量科室/病区:要「全部」,不能再按叶子节点过滤掉父级部门
        if (sysUserDept != null && sysUserDept.getUserId() == null) {
            return list == null ? new ArrayList<>() : list;
        }
        if(CollectionUtils.isNotEmpty(list)){
            list = TreeUtils.getLeafDepts(list);
        }
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -146,7 +146,10 @@
            deptIds.add(sysDept.getDeptId());
        }
        SysUserDept sysUserDept = new SysUserDept();
        // ç®¡ç†å‘˜ï¼šä¸æŒ‰ç”¨æˆ·è¿‡æ»¤ï¼ˆsys_user_dept é‡Œæ²¡æœ‰ admin çš„æ•°æ®ï¼‰ï¼Œç›´æŽ¥å–本机构全部科室/病区
        if (!isAdminUser(sysUser)) {
        sysUserDept.setUserId(sysUser.getUserId());
        }
        sysUserDept.setDeptType(sysUser.getSearchscope());
        sysUserDept.setOrgid(sysUser.getOrgid());
        List<SysUserDept> sysUserDeptKSs = null;
@@ -201,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");
@@ -220,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);
        }
@@ -258,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);
                    }
@@ -358,6 +361,23 @@
            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());
    }
    /**
@@ -1022,8 +1042,11 @@
    public List<SysUserDept> selectLeafSysDeptList(SysUserDept sysUserDept){
        List<SysDept> list =  sysDeptMapper.selectSysDeptListBySysUserDept(sysUserDept);
        // 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;
@@ -1031,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);
    }
    /**
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -283,8 +283,19 @@
        where dept_id = #{deptId}
    </delete>
    <!--
        æŸ¥è¯¢ç§‘室/病区:
          Â· userId æœ‰å€¼ï¼ˆæ™®é€šç”¨æˆ· / ç”¨æˆ·ç¼–辑页:查某个用户名下的部门)→ å…³è” sys_user_dept;
          Â· userId ä¸ºç©ºï¼ˆç®¡ç†å‘˜ï¼šçœ‹æœ¬æœºæž„全部科室/病区)→ åªæŸ¥ sys_dept,不关联关系表。
        ä¸ºä»€ä¹ˆè¦åˆ†æ”¯ï¼šHIS é‡‡é›†å†™ sys_user_dept æ—¶æ˜Žç¡®æŽ’除了 admin(CollectHISMapper çš„
        yhyksxx/yhybfxx éƒ½æœ‰ ud.user_id != 'admin'),管理员在关系表里没有数据,走 inner join
        ä¼šå¾—到空列表,表现就是「登录成功但创建任务时选不到科室病区」。
        å¦å¤–不做院区过滤(管理员跨院区),院区隔离只对普通用户生效。
    -->
    <select id="selectSysDeptListBySysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
            resultMap="SysDeptResult">
        <choose>
            <when test="userId != null">
        <include refid="selectDeptVo"/>
        inner join sys_user_dept ud
        on d.dept_code = ud.dept_code
@@ -293,7 +304,15 @@
        and ud.del_flag = 0
        <if test="orgid != null">and d.orgid = #{orgid} and ud.orgid = #{orgid}</if>
        <if test="campusid != null">and d.campusid = #{campusid}</if>
        <if test="userId != null">and ud.user_id = #{userId}</if>
        <if test="deptType != null and deptType != ''">and d.dept_type = #{deptType}</if>
                and ud.user_id = #{userId}
            </when>
            <otherwise>
                <include refid="selectDeptVo"/>
                where d.del_flag = 0
                <if test="orgid != null">and d.orgid = #{orgid}</if>
                <if test="deptType != null and deptType != ''">and d.dept_type = #{deptType}</if>
            </otherwise>
        </choose>
    </select>
</mapper>
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml
@@ -384,16 +384,34 @@
    <sql id="filterLeaveDimAnd">
        /* f-v3 */
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            AND (
            leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
                #{lvWardCodeItem}
            </foreach>
            <!-- å»¶ç»­æŠ¤ç†ä»»åŠ¡ï¼ˆservice_type='99')可以在患者还没出院时生成:
                 è¿™ç±»è®°å½•只有「在院维度」(hospitaldistrictcode / deptcode),出院维度是 NULL。
                 NULL ä¸åŒ¹é…ä»»ä½• IN,任务会「提示生成成功、列表里却查不到」,
                 æ‰€ä»¥å‡ºé™¢ç»´åº¦ä¸ºç©ºæ—¶ç”¨åŒä¸€å¥—编码体系的在院维度兜底。 -->
            OR (service_type = '99' AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '')
                AND hospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
                    #{lvWardCodeItem}
                </foreach>)
            )
        </if>
        <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
            AND leaveldeptcode IN
            AND (
            leaveldeptcode IN
            <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
                #{lvDeptCodeItem}
            </foreach>
            OR (service_type = '99' AND (leaveldeptcode IS NULL OR leaveldeptcode = '')
                AND deptcode IN
                <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
                    #{lvDeptCodeItem}
                </foreach>)
            )
        </if>
    </sql>
@@ -434,20 +452,38 @@
                  or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
            AND (
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                (
                leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
                    #{lvWardCodeItem}
                </foreach>
                <!-- å»¶ç»­æŠ¤ç†ä»»åŠ¡ï¼ˆservice_type='99')可以在患者还没出院时生成:
                     è¿™ç±»è®°å½•只有「在院维度」(hospitaldistrictcode / deptcode),出院维度是 NULL。
                     NULL ä¸åŒ¹é…ä»»ä½• IN,任务会「提示生成成功、列表里却查不到」,
                     æ‰€ä»¥å‡ºé™¢ç»´åº¦ä¸ºç©ºæ—¶ç”¨åŒä¸€å¥—编码体系的在院维度兜底。 -->
                OR (service_type = '99' AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '')
                    AND hospitaldistrictcode IN
                    <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")">
                        #{lvWardCodeItem}
                    </foreach>)
                )
            </if>
            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
                      and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
                OR
            </if>
            <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0">
                (
                leaveldeptcode IN
                <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
                    #{lvDeptCodeItem}
                </foreach>
                OR (service_type = '99' AND (leaveldeptcode IS NULL OR leaveldeptcode = '')
                    AND deptcode IN
                    <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")">
                        #{lvDeptCodeItem}
                    </foreach>)
                )
            </if>
            )
        </if>