diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/convert/UserConvert.java b/blade-service/blade-system/src/main/java/org/springblade/system/convert/UserConvert.java index abf59acf..2dabbf04 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/convert/UserConvert.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/convert/UserConvert.java @@ -148,7 +148,7 @@ public interface UserConvert { /** * oa人员转本系统用户部门 * @param person - * @param userMap 所有用户手机号与id map + * @param userMap OA登录名与用户id * @return */ default UserDept person2userDept(OAPersonResponse person, Map userMap) { @@ -162,8 +162,9 @@ public interface UserConvert { userDept.setStatus(status); // 排序 userDept.setSort(OAUtils.parseInt(person.getDsporder())); - // 用户id - userDept.setUserId(userMap.get(resolveAccount(person))); + // 用户id,按 OA 登录名关联本批已新增或更新的用户 + String oaLoginId = person == null ? null : StringUtils.trimToNull(person.getLoginid()); + userDept.setUserId(oaLoginId == null ? null : userMap.get(oaLoginId)); userDept.setSyncTime(new Date()); return userDept; } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java index 87e3cd50..46f8af2b 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/OaUserListSyncHelper.java @@ -403,70 +403,37 @@ public class OaUserListSyncHelper { Map uniquePersonMap = new LinkedHashMap<>(); int skippedCount = 0; for (OAPersonResponse oaPerson : oaPersons) { - String account = userConvert.resolveAccount(oaPerson); - if (StringUtils.isBlank(account)) { + String oaLoginId = resolveOaLoginId(oaPerson); + if (StringUtils.isBlank(oaLoginId)) { skippedCount++; continue; } - uniquePersonMap.putIfAbsent(account, oaPerson); + uniquePersonMap.put(oaLoginId, oaPerson); } if (uniquePersonMap.isEmpty()) { - ComposeLogUtil.getLastLog().warn("OA人员均缺少loginid/工号/手机号,跳过人员同步"); + ComposeLogUtil.getLastLog().warn("OA人员均缺少登录名,跳过人员同步"); return new PersonSyncCount(0, skippedCount); } String tenantId = resolveTenantId(); String defaultPassword = DigestUtil.encrypt(ParamCache.getValue(DEFAULT_PARAM_PASSWORD)); - List users = uniquePersonMap.values().stream() - .map(person -> { - User user = userConvert.person2user(person, defaultPassword); + List users = uniquePersonMap.entrySet().stream() + .map(entry -> { + User user = userConvert.person2user(entry.getValue(), defaultPassword); user.setTenantId(tenantId); + user.setOaLoginId(entry.getKey()); + user.setAccount(entry.getKey()); return user; }) .toList(); - List accounts = users.stream() - .map(User::getAccount) - .filter(StringUtils::isNotBlank) - .distinct() - .toList(); - List phones = users.stream() - .map(User::getPhone) - .filter(StringUtils::isNotBlank) - .distinct() - .toList(); - Map existingByAccount = new HashMap<>(); - Map existingByPhone = new HashMap<>(); - userService.list(Wrappers.lambdaQuery() - .and(wrapper -> { - wrapper.in(User::getAccount, accounts); - if (CollectionUtil.isNotEmpty(phones)) { - wrapper.or().in(User::getPhone, phones); - } - }) - ).stream() - .peek(userService::decryptPhone) - .forEach(user -> { - if (StringUtils.isNotBlank(user.getAccount())) { - existingByAccount.put(user.getAccount(), user); - } - if (StringUtils.isNotBlank(user.getPhone())) { - existingByPhone.put(user.getPhone(), user); - } - }); + Map existingByOaLoginId = this.loadUsersByOaLoginId(tenantId, uniquePersonMap.keySet()); Map userMap = new HashMap<>(); Set existsUserIds = new HashSet<>(); - Set unchangedUserIds = new HashSet<>(); users.forEach(user -> { - User existingUser = existingByAccount.get(user.getAccount()); - if (existingUser == null && StringUtils.isNotBlank(user.getPhone())) { - existingUser = existingByPhone.get(user.getPhone()); - } + User existingUser = existingByOaLoginId.get(user.getOaLoginId()); if (existingUser != null) { user.setId(existingUser.getId()); user.setPassword(null); existsUserIds.add(existingUser.getId()); - if (shouldSkipOaUpdate(existingUser, user)) { - unchangedUserIds.add(existingUser.getId()); - } } else { user.setId(DefaultIdentifierGenerator.getInstance().nextId(null)); user.setPostId("-1"); @@ -474,9 +441,9 @@ public class OaUserListSyncHelper { user.setDataScopeRange(1); user.setDataLevelRange(1); user.setIncludeNewCustomer(0); - userService.encryptPhone(user); } - userMap.put(user.getAccount(), user.getId()); + userService.encryptPhone(user); + userMap.put(user.getOaLoginId(), user.getId()); }); List addUsers = users.stream() @@ -488,18 +455,13 @@ public class OaUserListSyncHelper { } List updateUsers = users.stream() .filter(user -> existsUserIds.contains(user.getId())) - .filter(user -> !unchangedUserIds.contains(user.getId())) .toList(); if (CollectionUtil.isNotEmpty(updateUsers)) { ComposeLogUtil.getLastLog().info("批量修改用户:{}", updateUsers.size()); userService.updateBatchById(updateUsers); } - if (!unchangedUserIds.isEmpty()) { - ComposeLogUtil.getLastLog().info("跳过未变更用户:{}", unchangedUserIds.size()); - } - ComposeLogUtil.getLastLog().info("缺少账号已跳过的人员:{}", skippedCount); + ComposeLogUtil.getLastLog().info("缺少OA登录名已跳过的人员:{}", skippedCount); int syncedCount = addUsers.size() + updateUsers.size(); - skippedCount += unchangedUserIds.size(); if (userMap.isEmpty()) { return new PersonSyncCount(0, skippedCount); } @@ -511,11 +473,8 @@ public class OaUserListSyncHelper { Set existsUserDeptIds = new HashSet<>(userDeptMap.values()); List userDeptList = oaPersons.stream() .filter(oaPerson -> { - String account = userConvert.resolveAccount(oaPerson); - if (!userMap.containsKey(account)) { - return false; - } - return !unchangedUserIds.contains(userMap.get(account)); + String oaLoginId = resolveOaLoginId(oaPerson); + return StringUtils.isNotBlank(oaLoginId) && userMap.containsKey(oaLoginId); }) .map(oaPerson -> this.buildUserDept(oaPerson, userMap, orgIndex)) .filter(Objects::nonNull) @@ -554,7 +513,6 @@ public class OaUserListSyncHelper { .collect(Collectors.toSet()); String defaultRoleId = getDefaultRoleId(); List updateUserParams = list.stream() - .filter(userDeptIds -> !unchangedUserIds.contains(userDeptIds.getUserId())) .filter(userDeptIds -> { if (StringUtils.isBlank(userDeptIds.getDeptIds())) { return false; @@ -586,18 +544,51 @@ public class OaUserListSyncHelper { } /** - * oaModified 一致则跳过更新;任一侧为空无法确认一致,执行更新以补齐字段 + * 按 OA 登录名加载已有用户。同一登录名有多条时保留较早的一条,后续同步都更新这一条。 */ - private boolean shouldSkipOaUpdate(User existing, User incoming) { - if (existing == null) { - return false; + private Map loadUsersByOaLoginId(String tenantId, Collection oaLoginIds) { + Map existingByOaLoginId = new HashMap<>(); + if (CollectionUtil.isEmpty(oaLoginIds)) { + return existingByOaLoginId; } - String localModified = StringUtils.trimToEmpty(existing.getOaModified()); - String remoteModified = StringUtils.trimToEmpty(incoming == null ? null : incoming.getOaModified()); - if (localModified.isEmpty() || remoteModified.isEmpty()) { - return false; + List oaLoginIdList = oaLoginIds.stream() + .filter(StringUtils::isNotBlank) + .distinct() + .toList(); + int batchSize = 500; + for (int fromIndex = 0; fromIndex < oaLoginIdList.size(); fromIndex += batchSize) { + List oaLoginIdBatch = oaLoginIdList.subList(fromIndex, Math.min(fromIndex + batchSize, oaLoginIdList.size())); + userService.list(Wrappers.lambdaQuery() + .eq(User::getTenantId, tenantId) + .in(User::getOaLoginId, oaLoginIdBatch)) + .forEach(user -> { + String oaLoginId = StringUtils.trimToNull(user.getOaLoginId()); + if (oaLoginId == null) { + return; + } + User previous = existingByOaLoginId.get(oaLoginId); + if (previous == null) { + existingByOaLoginId.put(oaLoginId, user); + return; + } + if (user.getId() != null && previous.getId() != null && user.getId() < previous.getId()) { + ComposeLogUtil.getLastLog().warn("OA登录名重复,保留较早用户 oaLoginId={} keepUserId={} dropUserId={}", + oaLoginId, user.getId(), previous.getId()); + existingByOaLoginId.put(oaLoginId, user); + return; + } + ComposeLogUtil.getLastLog().warn("OA登录名重复,保留较早用户 oaLoginId={} keepUserId={} dropUserId={}", + oaLoginId, previous.getId(), user.getId()); + }); } - return localModified.equals(remoteModified); + return existingByOaLoginId; + } + + private String resolveOaLoginId(OAPersonResponse oaPerson) { + if (oaPerson == null) { + return null; + } + return StringUtils.trimToNull(oaPerson.getLoginid()); } private boolean isPersonBypassCode(String deptCode, DeptCategory deptCategory) { @@ -638,8 +629,8 @@ public class OaUserListSyncHelper { Dept department = orgIndex.findDept(oaPerson); if (department == null || department.getId() == null) { ComposeLogUtil.getLastLog().warn( - "人员未匹配到已有部门,请先同步组织架构 account={} departmentid={} departmentname={} subcompanyid1={}", - userConvert.resolveAccount(oaPerson), oaPerson.getDepartmentid(), oaPerson.getDepartmentname(), + "人员未匹配到已有部门,请先同步组织架构 oaLoginId={} departmentid={} departmentname={} subcompanyid1={}", + resolveOaLoginId(oaPerson), oaPerson.getDepartmentid(), oaPerson.getDepartmentname(), oaPerson.getSubcompanyid1()); return null; }