commit
This commit is contained in:
+96
-24
@@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.event.role.RoleEventMsg;
|
||||
@@ -50,6 +51,8 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
@IocBean
|
||||
public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService {
|
||||
private static final int BATCH_SIZE = 500;
|
||||
private static final int ROLE_DELETE_BATCH_SIZE = 50;
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@@ -180,6 +183,21 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
List<Sys_user_history> histories = new CopyOnWriteArrayList<>();
|
||||
List<String> addMemberUserIds = Collections.synchronizedList(new ArrayList<>());
|
||||
List<String> removeMemberUserIds = Collections.synchronizedList(new ArrayList<>());
|
||||
Set<String> sourceLoginNames = sources.stream()
|
||||
.map(Sys_user_source::getLoginname)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
List<String> leaveUserIds = sysUsers.stream()
|
||||
.filter(user -> StrUtil.isNotBlank(user.getLoginname()))
|
||||
.filter(user -> !sourceLoginNames.contains(user.getLoginname()))
|
||||
.map(Sys_user::getId)
|
||||
.toList();
|
||||
List<String> leaveMemberUserIds = sysUsers.stream()
|
||||
.filter(user -> StrUtil.isNotBlank(user.getLoginname()))
|
||||
.filter(user -> !sourceLoginNames.contains(user.getLoginname()))
|
||||
.filter(user -> Boolean.TRUE.equals(user.getMember()))
|
||||
.map(Sys_user::getId)
|
||||
.toList();
|
||||
|
||||
// 处理每条数据
|
||||
for (Sys_user_source source : sources) {
|
||||
@@ -235,7 +253,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
CompletableFuture<Void> insertTask = CompletableFuture.runAsync(() -> {
|
||||
log.info("新增用户: {} 个", needInitUserList.size());
|
||||
// 分批处理,每批200条
|
||||
List<List<Sys_user>> batches = ListUtil.split(needInitUserList, 500);
|
||||
List<List<Sys_user>> batches = ListUtil.split(needInitUserList, BATCH_SIZE);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
dao.fastInsert(batch);
|
||||
@@ -260,7 +278,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
|
||||
if (!roleList.isEmpty()) {
|
||||
// 分批处理角色分配
|
||||
List<List<Sys_user_role>> roleBatches = ListUtil.split(roleList, 500);
|
||||
List<List<Sys_user_role>> roleBatches = ListUtil.split(roleList, BATCH_SIZE);
|
||||
roleBatches.forEach(batch -> {
|
||||
try {
|
||||
dao.fastInsert(batch);
|
||||
@@ -282,7 +300,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
CompletableFuture<Void> updateTask = CompletableFuture.runAsync(() -> {
|
||||
log.info("更新用户: {} 个", needDoUpdateList.size());
|
||||
// 分批处理,每批200条
|
||||
List<List<Sys_user>> batches = ListUtil.split(needDoUpdateList, 500);
|
||||
List<List<Sys_user>> batches = ListUtil.split(needDoUpdateList, BATCH_SIZE);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
dao.updateIgnoreNull(batch);
|
||||
@@ -294,6 +312,65 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
updateTasks.add(updateTask);
|
||||
}
|
||||
|
||||
if (Lang.isNotEmpty(leaveUserIds)) {
|
||||
CompletableFuture<Void> leaveTask = CompletableFuture.runAsync(() -> {
|
||||
log.info("数据源缺失用户转为不在岗并取消会员: {} 个", leaveUserIds.size());
|
||||
List<List<String>> batches = ListUtil.split(leaveUserIds, BATCH_SIZE);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
/*
|
||||
* 本次拉取批次中没有出现、但系统用户表仍存在的人员,按离岗处理:
|
||||
* 1. userState 写为“不在岗”,用于后续人员状态筛选和业务判断;
|
||||
* 2. member 写为 false,避免仍按会员身份参与后续业务判断。
|
||||
*/
|
||||
dao.update(Sys_user.class, Chain.make("userState", "不在岗").add("member", false), Cnd.where("id", "in", batch));
|
||||
} catch (Exception e) {
|
||||
log.error("批量更新数据源缺失用户状态异常", e);
|
||||
}
|
||||
});
|
||||
}, executorService);
|
||||
updateTasks.add(leaveTask);
|
||||
}
|
||||
|
||||
if (Lang.isNotEmpty(leaveMemberUserIds)) {
|
||||
CompletableFuture<Void> leaveMemberRoleTask = CompletableFuture.runAsync(() -> {
|
||||
log.info("数据源缺失会员移除会员角色: {} 个", leaveMemberUserIds.size());
|
||||
List<List<String>> batches = ListUtil.split(leaveMemberUserIds, ROLE_DELETE_BATCH_SIZE);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
/*
|
||||
* 只对原本是会员的缺失人员移除会员角色,并缩小删除批次,
|
||||
* 降低 sys_user_role 大批量 DELETE 时的锁等待概率。
|
||||
*/
|
||||
dao.clear(Sys_user_role.class, Cnd.where("userId", "in", batch).and("roleId", "=", memberRole.getId()));
|
||||
} catch (Exception e) {
|
||||
log.error("批量移除数据源缺失会员角色异常", e);
|
||||
}
|
||||
});
|
||||
}, executorService);
|
||||
updateTasks.add(leaveMemberRoleTask);
|
||||
}
|
||||
|
||||
if (Lang.isNotEmpty(histories)) {
|
||||
CompletableFuture<Void> historyTask = CompletableFuture.runAsync(() -> {
|
||||
log.info("添加历史记录: {} 条", histories.size());
|
||||
/*
|
||||
* 历史记录基于更新前的 sys_user 与 sys_user_source 生成,必须纳入本次更新等待范围。
|
||||
* 继续使用线程池和批量插入,避免主线程逐条写入拖慢更新接口。
|
||||
*/
|
||||
List<List<Sys_user_history>> batches = ListUtil.split(histories, 500);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
dao.fastInsert(batch);
|
||||
} catch (Exception e) {
|
||||
log.error("批量添加历史记录异常", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}, executorService);
|
||||
updateTasks.add(historyTask);
|
||||
}
|
||||
|
||||
// 等待用户数据更新完成
|
||||
try {
|
||||
// 设置超时时间,避免无限等待
|
||||
@@ -307,22 +384,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
return "更新失败: " + e.getMessage();
|
||||
}
|
||||
|
||||
// 3. 异步添加历史记录 - 不等待完成
|
||||
if (Lang.isNotEmpty(histories)) {
|
||||
executorService.execute(() -> {
|
||||
log.info("添加历史记录: {} 条", histories.size());
|
||||
// 分批处理历史记录
|
||||
List<List<Sys_user_history>> batches = ListUtil.split(histories, 500);
|
||||
batches.forEach(batch -> {
|
||||
try {
|
||||
dao.fastInsert(batch);
|
||||
} catch (Exception e) {
|
||||
log.error("批量添加历史记录异常", e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* // 4. 异步添加会员角色 - 不等待完成
|
||||
if (Lang.isNotEmpty(addMemberUserIds)) {
|
||||
executorService.execute(() -> {
|
||||
@@ -384,7 +445,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime));
|
||||
|
||||
return "更新完成: 新增用户 " + needInitUserList.size() + " 个, 更新用户 " + needDoUpdateList.size()
|
||||
+ " 个, 待添加会员 " + addMemberUserIds.size() + " 个, 待移除会员 " + removeMemberUserIds.size() + " 个";
|
||||
+ " 个, 数据源缺失转不在岗 " + leaveUserIds.size() + " 个, 待添加会员 " + addMemberUserIds.size() + " 个, 待移除会员 " + removeMemberUserIds.size() + " 个";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -453,8 +514,8 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
NutMap change = NutMap.NEW();
|
||||
change.put("fieldName", "单位");
|
||||
change.put("field", "unitId");
|
||||
change.put("sourceValue", unitIdNameMap.get(user.getUnitId()));
|
||||
change.put("newValue", unitIdNameMap.get(user.getUnitId()));
|
||||
change.put("sourceValue", getUnitChangeValue(user.getUnitId()));
|
||||
change.put("newValue", getUnitChangeValue(source.getUnitId()));
|
||||
changeList.add(change);
|
||||
|
||||
// 单位异动发送订阅消息,清空原单位的所有角色
|
||||
@@ -470,8 +531,8 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
// 生成变更信息描述
|
||||
String changeInfos = changeList.stream()
|
||||
.map(v -> v.getString("fieldName") + ":" +
|
||||
HtmlUtil.cleanHtmlTag(v.getString("sourceValue")) + "→" +
|
||||
HtmlUtil.cleanHtmlTag(v.getString("newValue")))
|
||||
HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(v.getString("sourceValue"), "")) + "→" +
|
||||
HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(v.getString("newValue"), "")))
|
||||
.collect(Collectors.joining(";"));
|
||||
|
||||
// 设置历史记录信息
|
||||
@@ -481,4 +542,15 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位变更记录展示值。
|
||||
* 入参 unitId 为系统用户旧单位或数据源新单位ID;返回值优先使用单位名称,查不到名称时保留单位ID,避免变更记录为空导致更新中断。
|
||||
*/
|
||||
private String getUnitChangeValue(String unitId) {
|
||||
if (StrUtil.isBlank(unitId)) {
|
||||
return "";
|
||||
}
|
||||
return StrUtil.blankToDefault(unitIdNameMap.get(unitId), unitId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +159,8 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
} catch (Exception e) {
|
||||
sysUser.setBirthday(null);
|
||||
}
|
||||
} else if ("LXNY".equals(mapping.key)) {
|
||||
mapping.field.set(sysUser, normalizeArrivalAtSchoolDate(raw.getStr(mapping.key)));
|
||||
} else {
|
||||
mapping.field.set(sysUser, raw.getStr(mapping.key));
|
||||
}
|
||||
@@ -203,6 +205,27 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化信息中心返回的来校时间。
|
||||
* 入参 arrivalAtSchoolDate 对应信息中心 LXNY 字段,允许 yyyy-MM-dd 或 yyyy-MM;
|
||||
* 返回值用于 sys_user_source.arrivalAtSchoolDate 和后续 sys_user.arrivalAtSchoolDate,年月格式统一补为当月 01 日。
|
||||
*/
|
||||
private String normalizeArrivalAtSchoolDate(String arrivalAtSchoolDate) {
|
||||
String dateText = StrUtil.trim(arrivalAtSchoolDate);
|
||||
if (StrUtil.isBlank(dateText)) {
|
||||
return dateText;
|
||||
}
|
||||
if (dateText.matches("\\d{4}-\\d{1,2}-\\d{1,2}")) {
|
||||
String[] parts = dateText.split("-");
|
||||
return parts[0] + "-" + StrUtil.padPre(parts[1], 2, '0') + "-" + StrUtil.padPre(parts[2], 2, '0');
|
||||
}
|
||||
if (dateText.matches("\\d{4}-\\d{1,2}")) {
|
||||
String[] parts = dateText.split("-");
|
||||
return parts[0] + "-" + StrUtil.padPre(parts[1], 2, '0') + "-01";
|
||||
}
|
||||
return dateText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取信息中心开放平台访问令牌。
|
||||
* 返回值为接口后续调用使用的 access_token 字符串。
|
||||
|
||||
+5
@@ -63,6 +63,11 @@ public class AidFundMemberHistory extends BaseModel {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String personType;
|
||||
|
||||
@Column
|
||||
@Comment("人员属性")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String userAttribute;
|
||||
|
||||
@Column
|
||||
@Comment("在职状态")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||
|
||||
+5
@@ -64,4 +64,9 @@ public class AidFundMemberPay extends BaseModel {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||
private String userState;
|
||||
|
||||
@Column
|
||||
@Comment("人员属性")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String userAttribute;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user