| | |
| | | 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.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; |
| | |
| | | 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; |
| | |
| | | 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); |
| | |
| | | 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<Map<String, String>> orgInfoFuture = CompletableFuture.supplyAsync(() -> userExtInfoService.getUserOrgInfo(sysUser.getUserId().toString(), split[1], split[2]), executor); |
| | | |
| | | CompletableFuture<List<SysDept>> deptsFuture; |
| | | if (isAdmin) { |
| | |
| | | SysDept deptBQ = new SysDept(); |
| | | deptBQ.setOrgid(split[1]); |
| | | deptBQ.setDeptType("2"); |
| | | CompletableFuture<List<SysDept>> ksFuture = CompletableFuture.supplyAsync(() -> sysDeptMapper.selectDeptList(deptKS), executor); |
| | | CompletableFuture<List<SysDept>> bqFuture = CompletableFuture.supplyAsync(() -> sysDeptMapper.selectDeptList(deptBQ), executor); |
| | | 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)); |
| | |
| | | queryBQ.setUserId(sysUser.getUserId()); |
| | | queryBQ.setDeptType("2"); |
| | | queryBQ.setOrgid(split[1]); |
| | | CompletableFuture<List<SysUserDept>> ksFuture = CompletableFuture.supplyAsync(() -> sysUserDeptMapper.selectSysUserDeptList(queryKS), executor); |
| | | CompletableFuture<List<SysUserDept>> bqFuture = CompletableFuture.supplyAsync(() -> sysUserDeptMapper.selectSysUserDeptList(queryBQ), executor); |
| | | 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); |
| | |
| | | queryKS.setUserId(sysUser.getUserId()); |
| | | queryKS.setDeptType("1"); |
| | | queryKS.setOrgid(split[1]); |
| | | sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(queryKS); |
| | | 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 = sysUserDeptMapper.selectSysUserDeptList(queryBQ); |
| | | sysUserDeptBQs = selectLeafSysDeptList(queryBQ); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | //获取当前登陆人的机构和院�? |
| | | IUserExtInfoService userExtInfoService2 = SpringUtils.getBean(IUserExtInfoService.class); |
| | | Map<String, String> userOrgInfo2 = userExtInfoService2.getUserOrgInfo( |
| | | sysUser.getUserId().toString(), |
| | | split[1], |
| | | split[3]); |
| | | 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")); |
| | |
| | | sysUserDept.setUserId(null); |
| | | } |
| | | sysUserDept.setDeptType("1"); |
| | | sysUserDeptKSs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept); |
| | | sysUserDeptKSs = selectLeafSysDeptList(sysUserDept); |
| | | sysUserDept.setDeptType("2"); |
| | | sysUserDeptBQs = sysUserDeptMapper.selectSysUserDeptList(sysUserDept); |
| | | 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 = sysDeptMapper.selectDeptList(dept); |
| | | sysDepts = selectLeafSysDeptForAdmin(dept); |
| | | sysUserDeptKSs = DtoConversionUtils.sourceToTarget(sysDepts, SysUserDept.class); |
| | | |
| | | dept.setDeptType("2"); |
| | | sysDepts = sysDeptMapper.selectDeptList(dept); |
| | | sysDepts = selectLeafSysDeptForAdmin(dept); |
| | | sysUserDeptBQs = DtoConversionUtils.sourceToTarget(sysDepts, SysUserDept.class); |
| | | |
| | | List<SysUserDept> distinctUserDepts = new ArrayList<>(); |
| | |
| | | // 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); |
| | |
| | | sysUserDept.setOrgid(user.getOrgid()); |
| | | sysUserDept.setDeptCode(deptCode); |
| | | sysUserDept.setDeptId(sysDept.getDeptId()); |
| | | List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectSysUserDeptList(sysUserDept); |
| | | sysUserDept.setDelFlag(0L); |
| | | sysUserDept.setDeptType("1"); |
| | | sysUserDept.setDeptName(sysDept.getDeptName()); |
| | | sysUserDept.setUpdateTime(new Date()); |
| | | if (!CollectionUtils.isEmpty(sysUserDepts)) { |
| | | sysUserDept.setId(sysUserDepts.get(0).getId()); |
| | | sysUserDeptMapper.updateSysUserDept(sysUserDept); |
| | | continue; |
| | | } |
| | | 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); |
| | |
| | | sysUserDept.setDeptCode(wardCode); |
| | | sysUserDept.setDeptId(sysDept.getDeptId()); |
| | | sysUserDept.setOrgid(user.getOrgid()); |
| | | List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectSysUserDeptList(sysUserDept); |
| | | sysUserDept.setDelFlag(0L); |
| | | sysUserDept.setDeptType("2"); |
| | | sysUserDept.setOrgid(user.getOrgid()); |
| | | sysUserDept.setDeptName(sysDept.getDeptName()); |
| | | sysUserDept.setUpdateTime(new Date()); |
| | | if (!CollectionUtils.isEmpty(sysUserDepts)) { |
| | | sysUserDeptMapper.updateSysUserDept(sysUserDept); |
| | | continue; |
| | | } |
| | | sysUserDept.setCreateTime(new Date()); |
| | | sysUserDeptMapper.insertSysUserDept(sysUserDept); |
| | | } |
| | |
| | | } |
| | | 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<List<String>> 生成, |
| | | * 每个元素形如 [["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<List<String>>,格式如 [["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); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |