| | |
| | | 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; |
| | |
| | | @Service |
| | | 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; |
| | |
| | | } |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |