陈昶聿
5 天以前 1c82e21ac936241bf56109e7fff87446b0b6a131
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -4,21 +4,27 @@
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.*;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DtoConversionUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.SysUserPost;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.smartor.domain.SvyTaskVO;
import com.smartor.mapper.SysUserDeptMapper;
import com.ruoyi.common.core.service.IUserExtInfoService;
import com.ruoyi.system.mapper.SysUserDeptMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -27,10 +33,13 @@
import javax.validation.Validator;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * 用户 业务层处理
 * 用户 业务层处�?
 *
 * @author ruoyi
 */
@@ -38,14 +47,21 @@
public class SysUserServiceImpl implements ISysUserService {
    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    @Qualifier("sysUserDeptSystemMapper")
    private SysUserDeptMapper sysUserDeptMapper;
    @Autowired
    private SysRoleMapper roleMapper;
@@ -78,10 +94,16 @@
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUser user) {
        return userMapper.selectUserList(user);
    }
    @Override
    public List<SysUser> getUserList(SysUser user) {
        return userMapper.getUserList(user);
    }
    /**
     * 根据条件分页查询已分配用户角色列表
     * 根据条件分页查询已分配用户角色列�?
     *
     * @param user 用户信息
     * @return 用户信息集合信息
@@ -93,7 +115,7 @@
    }
    /**
     * 根据条件分页查询未分配用户角色列表
     * 根据条件分页查询未分配用户角色列�?
     *
     * @param user 用户信息
     * @return 用户信息集合信息
@@ -105,9 +127,9 @@
    }
    /**
     * 通过用户名查询用户
     * 通过用户名查询用�?
     *
     * @param userName 用户名
     * @param userName 用户�?
     * @return 用户对象信息
     */
    @Override
@@ -121,19 +143,20 @@
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(sysUser.getUserId());
        sysUserDept.setDeptType(sysUser.getSearchscope());
        sysUserDept.setOrgid(sysUser.getOrgid());
        List<SysUserDept> sysUserDeptKSs = null;
        List<SysUserDept> sysUserDeptBQs = null;
        if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("0")) {
            sysUserDept.setDeptType("1");
            sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
            sysUserDeptKSs = selectLeafSysDeptList(sysUserDept);
            sysUserDept.setDeptType("2");
            sysUserDeptBQs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
            sysUserDeptBQs = selectLeafSysDeptList(sysUserDept);
        } else if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("1")) {
            sysUserDept.setDeptType("1");
            sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
            sysUserDeptKSs = selectLeafSysDeptList(sysUserDept);
        } else if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("2")) {
            sysUserDept.setDeptType("2");
            sysUserDeptBQs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
            sysUserDeptBQs = selectLeafSysDeptList(sysUserDept);
        }
        sysUser.setDepts(deptIds);
@@ -166,239 +189,278 @@
    @Override
    public SysUser selectUserByUserName2(String userName) {
        log.debug("开始查询用户信息,用户名: {}", userName);
        try {
            // 参数校验
            if (StringUtils.isEmpty(userName)) {
                log.warn("用户名参数为空");
                return null;
            }
            // 解析用户名和机构ID
            String[] userInfo = parseUserName(userName);
            if (userInfo == null) {
                log.warn("用户名格式不正确: {}", userName);
                return null;
            }
            String username = userInfo[0];
            String orgId = userInfo[1];
            // 查询用户基本信息
            SysUser sysUser = userMapper.selectUserByUserNameByCondition(username, orgId);
            if (Objects.isNull(sysUser)) {
                log.warn("未找到用户信息: username={}, orgId={}", username, orgId);
                return null;
            }
            // 查询用户部门信息
            List<SysDept> sysDepts = getUserDepts(sysUser, username, orgId);
            List<Long> deptIds = extractDeptIds(sysDepts);
            sysUser.setDepts(deptIds);
            // 根据搜索范围处理科室和病区信息
            processUserDeptInfo(sysUser, username, orgId);
            log.debug("用户信息查询完成: userId={}", sysUser.getUserId());
            return sysUser;
        } catch (Exception e) {
            log.error("查询用户信息时发生异常: userName={}", userName, e);
            return null;
        }
    }
    /**
     * 解析用户名,提取用户名和机构ID
     */
    private String[] parseUserName(String userName) {
        if (StringUtils.isEmpty(userName) || !userName.contains("&")) {
            return null;
        }
        return userName.split("&");
    }
    /**
     * 获取用户部门信息
     */
    private List<SysDept> getUserDepts(SysUser sysUser, String username, String orgId) {
        if ("admin".equals(username)) {
        String[] split = userName.split("&");
        SysUser sysUser = userMapper.selectUserByUserNameByCondition(split[0], split[1], null);
        if (Objects.isNull(sysUser)) return sysUser;
        //这里只卡用户类型为“患者”的
        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]);
        IUserExtInfoService userExtInfoService = SpringUtils.getBean(IUserExtInfoService.class);
        Executor executor = SpringUtils.getBean("threadPoolTaskExecutor");
        // === 并行查询: 用户机构信息 + 部门列表 ===
        CompletableFuture<Map<String, String>> orgInfoFuture = CompletableFuture.supplyAsync(() -> userExtInfoService.getUserOrgInfo(sysUser.getUserId().toString(), split[1], split[2]), executor);
        CompletableFuture<List<SysDept>> deptsFuture;
        if (isAdmin) {
            SysDept dept = new SysDept();
            dept.setOrgid(orgId);
            return sysDeptMapper.selectDeptList(dept);
            dept.setOrgid(split[1]);
            deptsFuture = CompletableFuture.supplyAsync(() -> sysDeptMapper.selectDeptList(dept), executor);
        } else {
            return sysUserDeptMapper.selectDeptListByUserId(sysUser.getUserId());
            deptsFuture = CompletableFuture.supplyAsync(() -> sysUserDeptMapper.selectDeptListByUserId(sysUser.getUserId()), executor);
        }
    }
    /**
     * 提取部门ID列表
     */
    private List<Long> extractDeptIds(List<SysDept> sysDepts) {
        if (CollectionUtils.isEmpty(sysDepts)) {
            return new ArrayList<>();
        // 等待机构信息
        Map<String, String> userOrgInfo = new HashMap<>();
        try {
            userOrgInfo = orgInfoFuture.get(5, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.warn("获取用户机构信息超时或异常", e);
        }
        return sysDepts.stream()
                .map(SysDept::getDeptId)
                .collect(Collectors.toList());
    }
    /**
     * 处理用户科室和病区信息
     */
    private void processUserDeptInfo(SysUser sysUser, String username, String orgId) {
        String searchScope = sysUser.getSearchscope();
        if (StringUtils.isEmpty(searchScope)) {
            return;
        if (!userOrgInfo.isEmpty()) {
            sysUser.setOrgid(userOrgInfo.get("orgid"));
            sysUser.setCampusid(userOrgInfo.get("campusid"));
        }
        switch (searchScope) {
            case "0": // 全部范围
                processFullScopeDeptInfo(sysUser, username, orgId);
                break;
            case "1": // 科室范围
                processDeptScopeInfo(sysUser, orgId, "1");
                break;
            case "2": // 病区范围
                processDeptScopeInfo(sysUser, orgId, "2");
                break;
            default:
                log.warn("未知的搜索范围: {}", searchScope);
        // 等待部门列表
        List<SysDept> sysDepts = new ArrayList<>();
        try {
            sysDepts = deptsFuture.get(5, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.warn("获取部门列表超时或异常", e);
        }
    }
    /**
     * 处理全部范围的部门信息
     */
    private void processFullScopeDeptInfo(SysUser sysUser, String username, String orgId) {
        SysUserDept sysUserDept = createSysUserDept(sysUser, orgId);
        List<Long> deptIds = new ArrayList<>();
        for (SysDept sysDept : sysDepts) {
            deptIds.add(sysDept.getDeptId());
        }
        // === 查询科室和病区信息 ===
        List<SysUserDept> sysUserDeptKSs = null;
        List<SysUserDept> sysUserDeptBQs = null;
        if ("admin".equals(username)) {
            // admin用户特殊处理
            sysUserDept.setUserId(null);
            sysUserDeptKSs = getAdminDeptList(orgId, "1");
            sysUserDeptBQs = getAdminDeptList(orgId, "2");
            // 去重处理
            sysUserDeptKSs = removeDuplicateDepts(sysUserDeptKSs);
            sysUserDeptBQs = removeDuplicateDepts(sysUserDeptBQs);
        } else {
            // 普通用户处理
            sysUserDept.setDeptType("1");
            sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
            sysUserDept.setDeptType("2");
            sysUserDeptBQs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
        if (StringUtils.isNotEmpty(sysUser.getSearchscope())) {
            if ("0".equals(sysUser.getSearchscope())) {
                if (isAdmin) {
                    // admin直接从sys_dept查询,跳过无意义的selectSysUserDeptList
                    SysDept deptKS = new SysDept();
                    deptKS.setOrgid(split[1]);
                    deptKS.setDeptType("1");
                    SysDept deptBQ = new SysDept();
                    deptBQ.setOrgid(split[1]);
                    deptBQ.setDeptType("2");
                    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));
                    } catch (Exception e) {
                        log.warn("获取admin科室/病区信息超时或异常", e);
                    }
                } else {
                    // 并行查询科室和病区
                    SysUserDept queryKS = new SysUserDept();
                    queryKS.setUserId(sysUser.getUserId());
                    queryKS.setDeptType("1");
                    queryKS.setOrgid(split[1]);
                    SysUserDept queryBQ = new SysUserDept();
                    queryBQ.setUserId(sysUser.getUserId());
                    queryBQ.setDeptType("2");
                    queryBQ.setOrgid(split[1]);
                    CompletableFuture<List<SysUserDept>> ksFuture = CompletableFuture.supplyAsync(() -> selectLeafSysDeptList(queryKS), executor);
                    CompletableFuture<List<SysUserDept>> bqFuture = CompletableFuture.supplyAsync(() -> selectLeafSysDeptList(queryBQ), executor);
                    try {
                        sysUserDeptKSs = ksFuture.get(5, TimeUnit.SECONDS);
                        sysUserDeptBQs = bqFuture.get(5, TimeUnit.SECONDS);
                    } catch (Exception e) {
                        log.warn("获取科室/病区信息超时或异常", e);
                    }
                }
            } else if ("1".equals(sysUser.getSearchscope())) {
                SysUserDept queryKS = new SysUserDept();
                queryKS.setUserId(sysUser.getUserId());
                queryKS.setDeptType("1");
                queryKS.setOrgid(split[1]);
                sysUserDeptKSs = selectLeafSysDeptList(queryKS);
            } else if ("2".equals(sysUser.getSearchscope())) {
                SysUserDept queryBQ = new SysUserDept();
                queryBQ.setUserId(sysUser.getUserId());
                queryBQ.setDeptType("2");
                queryBQ.setOrgid(split[1]);
                sysUserDeptBQs = selectLeafSysDeptList(queryBQ);
            }
        }
        // 设置科室和病区信息
        setBelongWards(sysUser, sysUserDeptBQs);
        setBelongDepts(sysUser, sysUserDeptKSs);
    }
    /**
     * 处理指定范围的部门信息
     */
    private void processDeptScopeInfo(SysUser sysUser, String orgId, String deptType) {
        SysUserDept sysUserDept = createSysUserDept(sysUser, orgId);
        sysUserDept.setDeptType(deptType);
        List<SysUserDept> deptList = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
        if ("1".equals(deptType)) {
            setBelongDepts(sysUser, deptList);
        } else if ("2".equals(deptType)) {
            setBelongWards(sysUser, deptList);
        sysUser.setDepts(deptIds);
        if (!CollectionUtils.isEmpty(sysUserDeptBQs)) {
            List<Map<String, Object>> list = new ArrayList<>();
            for (SysUserDept sud : sysUserDeptBQs) {
                Map<String, Object> map = new HashMap<>();
                map.put("districtCode", "");
                if (StringUtils.isNotEmpty(sud.getDeptCode())) map.put("districtCode", sud.getDeptCode());
                else continue;
                map.put("districtName", "");
                if (StringUtils.isNotEmpty(sud.getDeptName())) map.put("districtName", sud.getDeptName());
                list.add(map);
            }
            sysUser.setBelongWards(list);
        }
    }
    /**
     * 创建SysUserDept对象
     */
    private SysUserDept createSysUserDept(SysUser sysUser, String orgId) {
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(sysUser.getUserId());
        sysUserDept.setDeptType(sysUser.getSearchscope());
        sysUserDept.setOrgid(orgId);
        return sysUserDept;
    }
    /**
     * 获取admin用户的部门列表
     */
    private List<SysUserDept> getAdminDeptList(String orgId, String deptType) {
        SysDept dept = new SysDept();
        dept.setOrgid(orgId);
        dept.setDeptType(deptType);
        List<SysDept> sysDepts = sysDeptMapper.selectDeptList(dept);
        return DtoConversionUtils.sourceToTarget(sysDepts, SysUserDept.class);
    }
    /**
     * 去除重复的部门信息
     */
    private List<SysUserDept> removeDuplicateDepts(List<SysUserDept> deptList) {
        if (CollectionUtils.isEmpty(deptList)) {
            return new ArrayList<>();
        if (!CollectionUtils.isEmpty(sysUserDeptKSs)) {
            List<Map<String, Object>> list = new ArrayList<>();
            for (SysUserDept sud : sysUserDeptKSs) {
                Map<String, Object> map = new HashMap<>();
                map.put("deptCode", "");
                if (StringUtils.isNotEmpty(sud.getDeptCode())) map.put("deptCode", sud.getDeptCode());
                else continue;
                map.put("deptName", "");
                if (StringUtils.isNotEmpty(sud.getDeptName())) map.put("deptName", sud.getDeptName());
                list.add(map);
            }
            sysUser.setBelongDepts(list);
            // 设置满意度分类(走缓存)
            sysUser.setSatisfactionCategories(userExtInfoService.getSatisfactionCategories(sysUser.getOrgid()));
        }
        List<SysUserDept> distinctDepts = new ArrayList<>();
        return sysUser;
    }
    /**
     * 按deptCode去重
     */
    private List<SysUserDept> distinctByDeptCode(List<SysUserDept> list) {
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        List<SysUserDept> result = new ArrayList<>();
        Set<String> uniqueCodes = new HashSet<>();
        for (SysUserDept dept : deptList) {
            String deptCode = dept.getDeptCode();
        for (SysUserDept item : list) {
            String deptCode = item.getDeptCode();
            if (StringUtils.isNotEmpty(deptCode) && !uniqueCodes.contains(deptCode)) {
                distinctDepts.add(dept);
                result.add(item);
                uniqueCodes.add(deptCode);
            }
        }
        return distinctDepts;
        return result;
    }
    /**
     * 设置病区信息
     */
    private void setBelongWards(SysUser sysUser, List<SysUserDept> sysUserDeptBQs) {
        if (CollectionUtils.isEmpty(sysUserDeptBQs)) {
            return;
    @Override
    public SysUser selectUserByUserNameAndDeptId(String userName) {
        String[] split = userName.split("&");
        if (split[2].contains("null")) {
            split[2] = null;
        }
        List<Map<String, Object>> wardList = sysUserDeptBQs.stream()
                .filter(sud -> StringUtils.isNotEmpty(sud.getDeptCode()))
                .map(sud -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("districtCode", StringUtils.defaultString(sud.getDeptCode(), ""));
                    map.put("districtName", StringUtils.defaultString(sud.getDeptName(), ""));
                    return map;
                })
                .collect(Collectors.toList());
        sysUser.setBelongWards(wardList);
    }
    /**
     * 设置科室信息
     */
    private void setBelongDepts(SysUser sysUser, List<SysUserDept> sysUserDeptKSs) {
        if (CollectionUtils.isEmpty(sysUserDeptKSs)) {
            return;
        SysUser sysUser = userMapper.selectUserByUserNameByCondition(split[0], split[1], split[2]);
        //获取当前登陆人的机构和院�?
        IUserExtInfoService userExtInfoService2 = SpringUtils.getBean(IUserExtInfoService.class);
        Map<String, String> userOrgInfo2 = userExtInfoService2.getUserOrgInfo(sysUser.getUserId().toString(), split[1], split[3]);
        if (!userOrgInfo2.isEmpty()) {
            sysUser.setOrgid(userOrgInfo2.get("orgid"));
            sysUser.setCampusid(userOrgInfo2.get("campusid"));
        }
        List<Map<String, Object>> deptList = sysUserDeptKSs.stream()
                .filter(sud -> StringUtils.isNotEmpty(sud.getDeptCode()))
                .map(sud -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("deptCode", StringUtils.defaultString(sud.getDeptCode(), ""));
                    map.put("deptName", StringUtils.defaultString(sud.getDeptName(), ""));
                    return map;
                })
                .collect(Collectors.toList());
        sysUser.setBelongDepts(deptList);
        log.info("selectUserByUserNameAndDeptId的sysUser的值为:{}", sysUser);
        if (Objects.isNull(sysUser)) return sysUser;
        List<SysDept> sysDepts = null;
        if (StringUtils.isNotEmpty(split[0]) && split[0].equals("admin")) {
            SysDept dept = new SysDept();
            dept.setOrgid(split[1]);
            sysDepts = sysDeptMapper.selectDeptList(dept);
        } else {
            sysDepts = sysUserDeptMapper.selectDeptListByUserId(sysUser.getUserId());
        }
        List<Long> deptIds = new ArrayList<>();
        for (SysDept sysDept : sysDepts) {
            deptIds.add(sysDept.getDeptId());
        }
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(sysUser.getUserId());
        sysUserDept.setDeptType(sysUser.getSearchscope());
        sysUserDept.setOrgid(split[1]);
        List<SysUserDept> sysUserDeptKSs = null;
        List<SysUserDept> sysUserDeptBQs = null;
        if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("0")) {
            if (StringUtils.isNotEmpty(split[0]) && split[0].equals("admin")) {
                sysUserDept.setUserId(null);
            }
            sysUserDept.setDeptType("1");
            sysUserDeptKSs = selectLeafSysDeptList(sysUserDept);
            sysUserDept.setDeptType("2");
            sysUserDeptBQs = selectLeafSysDeptList(sysUserDept);
            //如果是admin,需要对sysUserDeptBQs,sysUserDeptBQs去重
            if (StringUtils.isNotEmpty(split[0]) && split[0].equals("admin")) {
                //如果是admin,只能去sys_dept去取数据
                SysDept dept = new SysDept();
                dept.setOrgid(split[1]);
                dept.setDeptType("1");
                sysDepts = selectLeafSysDeptForAdmin(dept);
                sysUserDeptKSs = DtoConversionUtils.sourceToTarget(sysDepts, SysUserDept.class);
                dept.setDeptType("2");
                sysDepts = selectLeafSysDeptForAdmin(dept);
                sysUserDeptBQs = DtoConversionUtils.sourceToTarget(sysDepts, SysUserDept.class);
                List<SysUserDept> distinctUserDepts = new ArrayList<>();
                Set<String> uniqueDeptCodes = new HashSet<>();
                for (SysUserDept userDept : sysUserDeptKSs) {
                    String deptCode = userDept.getDeptCode();
                    if (StringUtils.isNotEmpty(deptCode) && !uniqueDeptCodes.contains(deptCode)) {
                        distinctUserDepts.add(userDept);
                        uniqueDeptCodes.add(deptCode);
                    }
                }
                List<SysUserDept> distinctUserBQs = new ArrayList<>();
                Set<String> uniqueBQCodes = new HashSet<>();
                for (SysUserDept userDept : sysUserDeptBQs) {
                    String deptCode = userDept.getDeptCode();
                    if (StringUtils.isNotEmpty(deptCode) && !uniqueBQCodes.contains(deptCode)) {
                        distinctUserBQs.add(userDept);
                        uniqueBQCodes.add(deptCode);
                    }
                }
                sysUserDeptKSs = distinctUserDepts;
                sysUserDeptBQs = distinctUserBQs;
            }
        } else if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("1")) {
            sysUserDept.setDeptType("1");
            sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
        } else if (StringUtils.isNotEmpty(sysUser.getSearchscope()) && sysUser.getSearchscope().equals("2")) {
            sysUserDept.setDeptType("2");
            sysUserDeptBQs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept);
        }
        sysUser.setDepts(deptIds);
        if (!CollectionUtils.isEmpty(sysUserDeptBQs)) {
            List<Map<String, Object>> list = new ArrayList<>();
            for (SysUserDept sud : sysUserDeptBQs) {
                Map<String, Object> map = new HashMap<>();
                map.put("districtCode", "");
                if (StringUtils.isNotEmpty(sud.getDeptCode())) map.put("districtCode", sud.getDeptCode());
                else continue;
                map.put("districtName", "");
                if (StringUtils.isNotEmpty(sud.getDeptName())) map.put("districtName", sud.getDeptName());
                list.add(map);
            }
            sysUser.setBelongWards(list);
        }
        if (!CollectionUtils.isEmpty(sysUserDeptKSs)) {
            List<Map<String, Object>> list = new ArrayList<>();
            for (SysUserDept sud : sysUserDeptKSs) {
                Map<String, Object> map = new HashMap<>();
                map.put("deptCode", "");
                if (StringUtils.isNotEmpty(sud.getDeptCode())) map.put("deptCode", sud.getDeptCode());
                else continue;
                map.put("deptName", "");
                if (StringUtils.isNotEmpty(sud.getDeptName())) map.put("deptName", sud.getDeptName());
                list.add(map);
            }
            sysUser.setBelongDepts(list);
        }
        return sysUser;
    }
    /**
     * 通过用户ID查询用户
@@ -421,7 +483,7 @@
    /**
     * 查询用户所属角色组
     *
     * @param userName 用户名
     * @param userName 用户�?
     * @return 结果
     */
    @Override
@@ -436,7 +498,7 @@
    /**
     * 查询用户所属岗位组
     *
     * @param userName 用户名
     * @param userName 用户�?
     * @return 结果
     */
    @Override
@@ -457,7 +519,7 @@
    @Override
    public String checkUserNameUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkUserNameUnique(user.getUserName());
        SysUser info = userMapper.checkUserNameUnique(user);
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
@@ -509,7 +571,7 @@
    }
    /**
     * 校验用户是否有数据权限
     * 校验用户是否有数据权�?
     *
     * @param userId 用户id
     */
@@ -520,7 +582,7 @@
            user.setUserId(userId);
            List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
            if (StringUtils.isEmpty(users)) {
                throw new ServiceException("没有权限访问用户数据!");
                throw new ServiceException("没有权限访问用户数据");
            }
        }
    }
@@ -536,79 +598,21 @@
    public int insertUser(SysUser user) {
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        //新增用户与部门关联
        if (!CollectionUtils.isEmpty(user.getDepts())) {
            for (Long deptId : user.getDepts()) {
                SysUserDept sysUserDep = new SysUserDept();
                sysUserDep.setUserId(user.getUserId());
                sysUserDep.setDeptId(deptId);
                sysUserDep.setCreateTime(new Date());
                sysUserDep.setUpdateTime(new Date());
                sysUserDep.setOrgid(user.getOrgid());
                sysUserDeptMapper.insertSysUserDept(sysUserDep);
            }
        }
        // 新增用户岗位关联
        insertUserPost(user);
        // 新增用户与角色管理
        insertUserRole(user);
        return rows;
    }
    /**
     * 注册用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean registerUser(SysUser user) {
        return userMapper.insertUser(user) > 0;
    }
    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateUser(SysUser user) {
        Long userId = user.getUserId();
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 新增用户与角色管理
        insertUserRole(user);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostByUserId(userId);
        // 新增用户与岗位管理
        insertUserPost(user);
        //删除用户与部门的关联
        Long[] ids = {user.getUserId()};
        //新增用户与部门关联
//        sysUserDeptMapper.deleteSysUserDeptByIds(ids);
        //新增用户与部门关�?
//        if (!CollectionUtils.isEmpty(user.getDepts())) {
//            for (Long deptId : user.getDepts()) {
//                SysUserDept sysUserDep = new SysUserDept();
//                sysUserDep.setUserId(user.getUserId());
//                sysUserDep.setDeptId(deptId);
//                //查询是否 已经关联该部门
//                List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectSysUserDeptList(sysUserDep);
//                if (!CollectionUtils.isEmpty(sysUserDepts)) {
//                    SysUserDept sysUserDept = sysUserDepts.get(0);
//                    sysUserDept.setDelFlag(0L);
//                    sysUserDeptMapper.updateSysUserDept(sysUserDept);
//                    continue;
//                }
//                sysUserDep.setCreateTime(new Date());
//                sysUserDep.setUpdateTime(new Date());
//                sysUserDep.setOrgid(user.getOrgid());
//                sysUserDeptMapper.insertSysUserDept(sysUserDep);
//            }
//        }
        if (!CollectionUtils.isEmpty(user.getDeptCodes())) {
            for (String deptCode : user.getDeptCodes()) {
                SysDept sysDept = sysDeptMapper.selectDeptByCode(deptCode);
                SysDept sysDept = sysDeptMapper.selectDeptByCode("1", user.getOrgid(), deptCode);
                if (ObjectUtils.isEmpty(sysDept)) {
                    continue;
                }
@@ -634,7 +638,7 @@
        }
        if (!CollectionUtils.isEmpty(user.getWardCodes())) {
            for (String wardCode : user.getWardCodes()) {
                SysDept sysDept = sysDeptMapper.selectDeptByCode(wardCode);
                SysDept sysDept = sysDeptMapper.selectDeptByCode("2", user.getOrgid(), wardCode);
                if (ObjectUtils.isEmpty(sysDept)) {
                    continue;
                }
@@ -657,6 +661,111 @@
                sysUserDeptMapper.insertSysUserDept(sysUserDept);
            }
        }
        // 新增用户岗位关联
        insertUserPost(user);
        // 新增用户与角色管�?
        insertUserRole(user);
        return rows;
    }
    /**
     * 注册用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean registerUser(SysUser user) {
        return userMapper.insertUser(user) > 0;
    }
    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateUser(SysUser user) {
        Long userId = user.getUserId();
        // 删除用户与角色关�?
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 新增用户与角色管�?
        insertUserRole(user);
        // 删除用户与岗位关�?
        userPostMapper.deleteUserPostByUserId(userId);
        // 新增用户与岗位管�?
        insertUserPost(user);
        //删除用户与部门的关联
        Long[] ids = {user.getUserId()};
        //新增用户与部门关�?
//        sysUserDeptMapper.deleteSysUserDeptByIds(ids);
//        if (!CollectionUtils.isEmpty(user.getDepts())) {
//            for (Long deptId : user.getDepts()) {
//                SysUserDept sysUserDep = new SysUserDept();
//                sysUserDep.setUserId(user.getUserId());
//                sysUserDep.setDeptId(deptId);
//                //查询是否 已经关联该部�?
//                List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectSysUserDeptList(sysUserDep);
//                if (!CollectionUtils.isEmpty(sysUserDepts)) {
//                    SysUserDept sysUserDept = sysUserDepts.get(0);
//                    sysUserDept.setDelFlag(0L);
//                    sysUserDeptMapper.updateSysUserDept(sysUserDept);
//                    continue;
//                }
//                sysUserDep.setCreateTime(new Date());
//                sysUserDep.setUpdateTime(new Date());
//                sysUserDeptMapper.insertSysUserDept(sysUserDep);
//            }
//        }
        //删除原有关系
        SysUserDept delSysUserDept = new SysUserDept();
        delSysUserDept.setUserId(user.getUserId());
        delSysUserDept.setOrgid(user.getOrgid());
        sysUserDeptMapper.deleteSysUserDeptByUserId(delSysUserDept);
        if (!CollectionUtils.isEmpty(user.getDeptCodes())) {
            for (String deptCode : user.getDeptCodes()) {
                SysDept sysDept = sysDeptMapper.selectDeptByCode("1", user.getOrgid(), deptCode);
                if (ObjectUtils.isEmpty(sysDept)) {
                    continue;
                }
                SysUserDept sysUserDept = new SysUserDept();
                sysUserDept.setUserId(user.getUserId());
                sysUserDept.setOrgid(user.getOrgid());
                sysUserDept.setDeptCode(deptCode);
                sysUserDept.setDeptId(sysDept.getDeptId());
                sysUserDept.setDelFlag(0L);
                sysUserDept.setDeptType("1");
                sysUserDept.setDeptName(sysDept.getDeptName());
                sysUserDept.setUpdateTime(new Date());
                sysUserDept.setCreateTime(new Date());
                sysUserDeptMapper.insertSysUserDept(sysUserDept);
            }
        }
        if (!CollectionUtils.isEmpty(user.getWardCodes())) {
            for (String wardCode : user.getWardCodes()) {
                SysDept sysDept = sysDeptMapper.selectDeptByCode("2", user.getOrgid(), wardCode);
                if (ObjectUtils.isEmpty(sysDept)) {
                    continue;
                }
                SysUserDept sysUserDept = new SysUserDept();
                sysUserDept.setUserId(user.getUserId());
                sysUserDept.setDeptCode(wardCode);
                sysUserDept.setDeptId(sysDept.getDeptId());
                sysUserDept.setOrgid(user.getOrgid());
                sysUserDept.setDelFlag(0L);
                sysUserDept.setDeptType("2");
                sysUserDept.setOrgid(user.getOrgid());
                sysUserDept.setDeptName(sysDept.getDeptName());
                sysUserDept.setUpdateTime(new Date());
                sysUserDept.setCreateTime(new Date());
                sysUserDeptMapper.insertSysUserDept(sysUserDept);
            }
        }
        return userMapper.updateUser(user);
    }
@@ -664,7 +773,7 @@
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     * @param roleIds 角色�?
     */
    @Override
    @Transactional
@@ -674,7 +783,7 @@
    }
    /**
     * 修改用户状态
     * 修改用户状�?
     *
     * @param user 用户信息
     * @return 结果
@@ -698,7 +807,7 @@
    /**
     * 修改用户头像
     *
     * @param userName 用户名
     * @param userName 用户�?
     * @param avatar   头像地址
     * @return 结果
     */
@@ -721,7 +830,7 @@
    /**
     * 重置用户密码
     *
     * @param userName 用户名
     * @param userName 用户�?
     * @param password 密码
     * @return 结果
     */
@@ -747,7 +856,7 @@
    public void insertUserPost(SysUser user) {
        Long[] posts = user.getPostIds();
        if (StringUtils.isNotEmpty(posts)) {
            // 新增用户与岗位管理
            // 新增用户与岗位管�?
            List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
            for (Long postId : posts) {
                SysUserPost up = new SysUserPost();
@@ -764,11 +873,11 @@
     * 新增用户角色信息
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     * @param roleIds 角色�?
     */
    public void insertUserRole(Long userId, Long[] roleIds, String orgid) {
        if (StringUtils.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            // 新增用户与角色管�?
            List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
            for (Long roleId : roleIds) {
                SysUserRole ur = new SysUserRole();
@@ -790,7 +899,7 @@
    @Override
    @Transactional
    public int deleteUserById(Long userId) {
        // 删除用户与角色关联
        // 删除用户与角色关�?
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 删除用户与岗位表
        userPostMapper.deleteUserPostByUserId(userId);
@@ -810,9 +919,9 @@
            checkUserAllowed(new SysUser(userId));
            checkUserDataScope(userId);
        }
        // 删除用户与角色关联
        // 删除用户与角色关�?
        userRoleMapper.deleteUserRole(userIds);
        // 删除用户与岗位关联
        // 删除用户与岗位关�?
        userPostMapper.deleteUserPost(userIds);
        return userMapper.deleteUserByIds(userIds);
    }
@@ -828,7 +937,7 @@
    @Override
    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空!");
            throw new ServiceException("导入用户数据不能为空");
        }
        int successNum = 0;
        int failureNum = 0;
@@ -845,7 +954,7 @@
                    user.setCreateBy(operName);
                    this.insertUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
                    successMsg.append("<br/>" + successNum + "、账�?" + user.getUserName() + " 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, user);
                    checkUserAllowed(user);
@@ -853,14 +962,14 @@
                    user.setUpdateBy(operName);
                    this.updateUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
                    successMsg.append("<br/>" + successNum + "账号?" + user.getUserName() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
                    failureMsg.append("<br/>" + failureNum + "账号" + user.getUserName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
                String msg = "<br/>" + failureNum + "账号" + user.getUserName() + " 导入失败";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
@@ -869,8 +978,214 @@
            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
            successMsg.insert(0, "恭喜您,数据已全部导入成功!共" + successNum + "条,数据如下:");
        }
        return successMsg.toString();
    }
    public List<SysUserDept> selectLeafSysDeptList(SysUserDept sysUserDept){
        List<SysDept> list =  sysDeptMapper.selectSysDeptListBySysUserDept(sysUserDept);
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
            list = TreeUtils.getLeafDepts(list);
        }
        List<SysUserDept> list1 = DtoConversionUtils.sourceToTarget(list, SysUserDept.class);
        return list1;
    }
    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;
    }
    /**
     * 根据 sys_user.hosp_info(科室)和 sys_user.dept_info(病区)补全 sys_user_dept 数据
     *
     * @param orgid  机构ID,为空时处理全部机构
     * @param userId 用户ID,为空时处理全部用户
     * @return 处理结果统计
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> repairUserDeptByHospAndDeptInfo(String orgid, Long userId) {
        List<SysUser> users = userMapper.selectUsersForRepairUserDept(orgid, userId);
        int processedUsers = 0;
        int inserted = 0;
        int updated = 0;
        int restored = 0;
        int deptNotFound = 0;
        Set<String> missingDeptCodes = new LinkedHashSet<>();
        for (SysUser user : users) {
            if (user.getUserId() == null) {
                continue;
            }
            List<String> hospCodes = parseDeptCodes(user.getHospInfo());
            List<String> wardCodes = parseDeptCodes(user.getDeptInfo());
            if (hospCodes.isEmpty() && wardCodes.isEmpty()) {
                continue;
            }
            processedUsers++;
            int[] hospStat = repairUserDept(user, hospCodes, "1", missingDeptCodes);
            int[] wardStat = repairUserDept(user, wardCodes, "2", missingDeptCodes);
            inserted += hospStat[0] + wardStat[0];
            updated += hospStat[1] + wardStat[1];
            restored += hospStat[2] + wardStat[2];
            deptNotFound += hospStat[3] + wardStat[3];
        }
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("scannedUsers", users.size());
        result.put("processedUsers", processedUsers);
        result.put("inserted", inserted);
        result.put("updated", updated);
        result.put("restored", restored);
        result.put("deptMetaNotFound", deptNotFound);
        result.put("missingDeptCodes", missingDeptCodes);
        log.info("根据hosp_info/dept_info补全用户部门关系完成,结果:{}", result);
        return result;
    }
    /**
     * 补全单个用户指定类型的部门关系。
     * hosp_info / dept_info 由 Gson 序列化 List&lt;List&lt;String&gt;&gt; 生成,
     * 每个元素形如 [["code"]],因此以部门编码作为补全依据,与原始采集逻辑一致。
     *
     * @param user             用户
     * @param deptCodes        部门编码集合
     * @param expectedDeptType 部门类型(1科室 2病区,对应 hosp_info / dept_info)
     * @param missingDeptCodes sys_dept 中未匹配到的部门编码
     * @return [新增数, 更新数, 恢复数, sys_dept未匹配数]
     */
    private int[] repairUserDept(SysUser user, List<String> deptCodes, String expectedDeptType, Set<String> missingDeptCodes) {
        int[] stat = new int[4];
        for (String deptCode : deptCodes) {
            // sys_dept 只用于补充 dept_id、dept_name 等信息,查不到也继续按编码补全
            SysDept sysDept = sysDeptMapper.selectDeptByCode(expectedDeptType, user.getOrgid(), deptCode);
            if (ObjectUtils.isEmpty(sysDept)) {
                // dept_type 可能存在历史脏数据,按编码兜底再查一次
                sysDept = sysDeptMapper.selectDeptByCode(null, user.getOrgid(), deptCode);
            }
            if (ObjectUtils.isEmpty(sysDept)) {
                stat[3]++;
                if (missingDeptCodes.size() < 100) {
                    missingDeptCodes.add(deptCode);
                }
            }
            String userDeptOrgid = StringUtils.isNotEmpty(user.getOrgid()) ? user.getOrgid()
                    : (sysDept == null ? null : sysDept.getOrgid());
            String campusid = sysDept != null && StringUtils.isNotEmpty(sysDept.getCampusid())
                    ? sysDept.getCampusid() : user.getCampusid();
            Date now = new Date();
            // 与原始生成逻辑保持一致,user_id + dept_code + orgid 作为业务唯一键
            SysUserDept sysUserDept = sysUserDeptMapper.selectSysUserDeptByUserAndCode(user.getUserId(), deptCode, user.getOrgid());
            if (ObjectUtils.isEmpty(sysUserDept)) {
                sysUserDept = new SysUserDept();
                sysUserDept.setUserId(user.getUserId());
                sysUserDept.setDeptCode(deptCode);
                sysUserDept.setDeptType(expectedDeptType);
                sysUserDept.setOrgid(userDeptOrgid);
                sysUserDept.setCampusid(campusid);
                if (sysDept != null) {
                    sysUserDept.setDeptId(sysDept.getDeptId());
                    sysUserDept.setDeptName(sysDept.getDeptName());
                }
                sysUserDept.setDelFlag(0L);
                sysUserDept.setCreateTime(now);
                sysUserDept.setUpdateTime(now);
                sysUserDeptMapper.insertSysUserDept(sysUserDept);
                stat[0]++;
                continue;
            }
            boolean wasDeleted = !Long.valueOf(0L).equals(sysUserDept.getDelFlag());
            sysUserDept.setDeptCode(deptCode);
            sysUserDept.setDeptType(expectedDeptType);
            sysUserDept.setOrgid(userDeptOrgid);
            sysUserDept.setCampusid(campusid);
            if (sysDept != null) {
                sysUserDept.setDeptId(sysDept.getDeptId());
                sysUserDept.setDeptName(sysDept.getDeptName());
            }
            sysUserDept.setDelFlag(0L);
            sysUserDept.setUpdateTime(now);
            sysUserDeptMapper.updateSysUserDept(sysUserDept);
            if (wasDeleted) {
                stat[2]++;
            } else {
                stat[1]++;
            }
        }
        return stat;
    }
    /**
     * 解析 hosp_info / dept_info 中的部门编码。
     * 原始生成逻辑使用 Gson 序列化 List&lt;List&lt;String&gt;&gt;,格式如 [["code1"],["code2"]];
     * 这里兼容该格式,同时兼容 ["code"]、[{"deptCode":"code"}] 等历史格式。
     */
    private List<String> parseDeptCodes(String json) {
        if (StringUtils.isEmpty(json)) {
            return Collections.emptyList();
        }
        List<String> codes = new ArrayList<>();
        try {
            collectDeptCodes(OBJECT_MAPPER.readTree(json), codes);
        } catch (Exception e) {
            log.warn("解析用户科室/病区信息失败,内容:{}", json, e);
        }
        return codes.stream().filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
    }
    private void collectDeptCodes(JsonNode node, List<String> codes) {
        if (node == null || node.isNull()) {
            return;
        }
        if (node.isArray()) {
            for (JsonNode item : node) {
                collectDeptCodes(item, codes);
            }
            return;
        }
        if (node.isObject()) {
            JsonNode codeNode = node.get("deptCode");
            if (codeNode == null) {
                codeNode = node.get("code");
            }
            if (codeNode == null) {
                codeNode = node.get("deptId");
            }
            if (codeNode == null) {
                codeNode = node.get("hisDeptId");
            }
            if (codeNode != null) {
                collectDeptCodes(codeNode, codes);
                return;
            }
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            while (fields.hasNext()) {
                JsonNode value = fields.next().getValue();
                if (value != null && value.isValueNode() && !value.isNull()) {
                    collectDeptCodes(value, codes);
                    return;
                }
            }
            return;
        }
        if (node.isValueNode()) {
            String code = node.asText();
            if (StringUtils.isNotEmpty(code)) {
                code = code.trim();
                if (StringUtils.isNotEmpty(code) && !"null".equalsIgnoreCase(code)) {
                    codes.add(code);
                }
            }
        }
    }
}