整改拉取人员问题

This commit is contained in:
2026-08-29 15:52:54 +08:00
parent 9e632f9e7c
commit eef0865fef
5 changed files with 112 additions and 34 deletions
@@ -67,14 +67,14 @@ public class SmsServiceImpl implements SmsService {
if (!Globals.MyConfig.getBoolean("AppSms", false)) {
String message = "消息发送配置未开启,已跳过实际发送";
log.warn(message);
logSendSkipped(sendType, resultReceivers.size(), message);
saveSendRecord(sendType, title, content, pcUrl, mobileUrl, resultReceivers.size(), false,
batchResults, message);
return false;
}
if (!Globals.sso) {
String message = "开发模式不允许发送学校消息中心通知";
log.warn(message);
logSendSkipped(sendType, resultReceivers.size(), message);
saveSendRecord(sendType, title, content, pcUrl, mobileUrl, resultReceivers.size(), false,
batchResults, message);
return false;
@@ -95,6 +95,7 @@ public class SmsServiceImpl implements SmsService {
saveSendRecord(sendType, title, content, pcUrl, mobileUrl, resultReceivers.size(), sendSuccess,
batchResults, sendMessage);
logSendSummary(sendType, resultReceivers.size(), sendSuccess, sendMessage, batchResults);
return sendSuccess;
}
@@ -161,9 +162,9 @@ public class SmsServiceImpl implements SmsService {
if (StrUtil.isBlank(receiver.getString("userId"))) {
throw new BaseException("接收人的userId不能为空");
}
if (sendType.contains("4") && StrUtil.isBlank(receiver.getString("mobile"))) {
/*if (sendType.contains("4") && StrUtil.isBlank(receiver.getString("mobile"))) {
throw new BaseException("发送短信时接收人的mobile不能为空,userId=" + receiver.getString("userId"));
}
}*/
}
/**
@@ -202,6 +203,8 @@ public class SmsServiceImpl implements SmsService {
payload.put("dingSendType", "text");
}
// 请求日志仅保留业务发送内容,接收人手机号脱敏,避免认证信息和个人信息明文写入日志。
logBatchRequest(batchNo, receivers, payload);
HttpRequest request = HttpUtil.createPost(MSG_API)
.header("appId", APP_ID)
.header("accessToken", ACCESS_TOKEN)
@@ -213,11 +216,11 @@ public class SmsServiceImpl implements SmsService {
result.put("rawBody", responseBody);
if (response.getStatus() < 200 || response.getStatus() >= 300) {
result.put("msg", "消息中心HTTP调用失败,状态码:" + response.getStatus());
return result;
return logAndReturnBatchResult(result);
}
if (!JSONUtil.isTypeJSON(responseBody)) {
result.put("msg", "消息中心返回内容不是合法JSON");
return result;
return logAndReturnBatchResult(result);
}
JSONObject responseJson = JSONUtil.parseObj(responseBody);
Integer status = responseJson.getInt("status");
@@ -225,15 +228,100 @@ public class SmsServiceImpl implements SmsService {
result.put("status", status);
result.put("msg", message);
result.put("success", Integer.valueOf(200).equals(status));
return result;
return logAndReturnBatchResult(result);
}
} catch (Exception e) {
log.error("学校消息中心第{}批发送异常", batchNo, e);
result.put("msg", "消息中心调用异常:" + e.getMessage());
return result;
log.error("\n====================【学校平台消息发送异常】====================\n批次号:{}\n异常信息:{}\n==============================================================", batchNo, e.getMessage(), e);
return logAndReturnBatchResult(result);
}
}
/**
* 在调用学校消息中心前输出当前批次的业务请求内容。
* 接收人手机号只展示前三位和后四位,sign及accessToken等认证信息不写入日志。
*
* @param batchNo 当前发送批次序号
* @param receivers 当前批次接收人列表
* @param payload 即将提交给消息中心的请求参数
*/
private void logBatchRequest(int batchNo, List<NutMap> receivers, NutMap payload) {
NutMap logPayload = NutMap.NEW();
logPayload.putAll(payload);
logPayload.remove("sign");
List<NutMap> maskedReceivers = receivers.stream()
.map(receiver -> NutMap.NEW()
.addv("userId", receiver.getString("userId"))
.addv("mobile", maskMobile(receiver.getString("mobile")))
.addv("email", receiver.getString("email"))
.addv("flag", receiver.get("flag")))
.toList();
logPayload.put("receivers", maskedReceivers);
log.info("\n====================【学校平台消息发送请求】====================\n批次号:{}\n请求地址:{}\n接收人数:{}\n发送内容:{}\n==============================================================", batchNo, MSG_API, receivers.size(), JSONUtil.toJsonStr(logPayload));
}
/**
* 输出单个批次的学校消息中心响应结果,并按成功或失败使用对应日志级别。
*
* @param result 包含批次号、HTTP状态、平台状态、平台提示及原始响应的处理结果
* @return 原样返回处理结果,便于发送流程继续汇总和入库
*/
private NutMap logAndReturnBatchResult(NutMap result) {
String message = "\n====================【学校平台消息发送%s】====================\n批次号:{}\n发送结果:{}\n==============================================================";
if (result.getBoolean("success", false)) {
log.info(message.formatted("成功"), result.getInt("batchNo"), JSONUtil.toJsonStr(result));
} else {
log.warn(message.formatted("失败"), result.getInt("batchNo"), JSONUtil.toJsonStr(result));
}
return result;
}
/**
* 输出因运行配置或环境限制而跳过的发送提示,说明本次未发起第三方接口调用。
*
* @param sendType 原计划使用的发送渠道组合
* @param receiverCount 原计划发送的接收人数量
* @param reason 跳过发送的具体原因
*/
private void logSendSkipped(String sendType, int receiverCount, String reason) {
log.warn("\n====================【学校平台消息发送跳过】====================\n发送渠道:{}\n接收人数:{}\n跳过原因:{}\n说明:本次未调用学校消息中心接口。\n==============================================================", sendType, receiverCount, reason);
}
/**
* 输出整次学校消息中心发送的最终汇总结果,便于从控制台快速确认全部批次状态。
*
* @param sendType 发送渠道组合
* @param receiverCount 本次待发送接收人数量
* @param success 是否所有批次均发送成功
* @param message 最终处理说明
* @param batchResults 已完成批次的响应结果
*/
private void logSendSummary(String sendType, int receiverCount, boolean success, String message,
List<NutMap> batchResults) {
String logMessage = "\n====================【学校平台消息发送%s】====================\n发送渠道:{}\n接收人数:{}\n最终说明:{}\n批次结果:{}\n==============================================================";
if (success) {
log.info(logMessage.formatted("完成"), sendType, receiverCount, message, JSONUtil.toJsonStr(batchResults));
} else {
log.warn(logMessage.formatted("失败"), sendType, receiverCount, message, JSONUtil.toJsonStr(batchResults));
}
}
/**
* 对手机号进行日志脱敏;空手机号保持为空,长度不足七位时完全隐藏。
*
* @param mobile 接收人的原始手机号
* @return 用于日志展示的脱敏手机号
*/
private String maskMobile(String mobile) {
if (Strings.isBlank(mobile)) {
return "";
}
if (mobile.length() <= 7) {
return "****";
}
return mobile.substring(0, 3) + "****" + mobile.substring(mobile.length() - 4);
}
/**
* 生成消息中心请求签名。
*
@@ -23,7 +23,6 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
@@ -165,10 +164,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
for (Sys_user_source source : sources) {
Sys_user user = userMap.get(source.getLoginname());
source.setMember(null);
String unitId = source.getUnitId();
if (StringUtils.isNotBlank(unitId) && unitId.length() == 5) {
source.setUnitId(unitId.substring(0, 3));
}
// 创建用户对象
Sys_user u = new Sys_user();
@@ -450,6 +445,13 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
// 遍历带有DataCenterColumn注解的字段进行比较
for (FieldMapping mapping : getFieldMappings()) {
try {
/*
* 单位由下方的专门逻辑统一记录:使用单位名称展示,并同步发布单位异动事件。
* 此处跳过 unitId,避免通用比较与专门逻辑为同一次单位变更各生成一条历史明细。
*/
if ("unitId".equals(mapping.field.getName())) {
continue;
}
Object sourceValue = mapping.field.get(source);
Object userValue = mapping.field.get(user);
@@ -141,7 +141,8 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
}
}
sysUser.setUnitId(resolveSourceUnitId(raw.getStr("bmdm")));
// 人员单位编码必须与信息中心 bmdm 保持一致,不能按编码长度推断并替换为父级单位。
sysUser.setUnitId(raw.getStr("bmdm"));
sysUser.setUnitName(unitNameMap.get(sysUser.getUnitId()));
// 设置拉取时间
@@ -263,22 +264,6 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
return new ArrayList<>(userMap.values());
}
/**
* 根据接口返回的所在单位号转换数据源用户单位。
* 入参 rawUnitId 对应人员接口 bmdm:5位表示三级单位,需要写入其二级父单位;其他长度保持接口原值。
* 返回值为 sys_user_source.unitId 使用的单位ID,找不到三级单位或父级为空时保留接口原始单位号,避免人员数据丢失。
*/
private String resolveSourceUnitId(String rawUnitId) {
if (StrUtil.isBlank(rawUnitId) || rawUnitId.length() != 5) {
return rawUnitId;
}
Sys_unit unit = dao().fetch(Sys_unit.class, rawUnitId);
if (unit == null || StrUtil.isBlank(unit.getParentId())) {
return rawUnitId;
}
return unit.getParentId();
}
@Override
public NutMap searchOptions() {
Sql sql = Sqls.create("""
@@ -112,14 +112,17 @@ public class SysMsgServiceImpl extends BaseServiceImpl<Sys_msg> implements SysMs
.addv("flag", 0))
.toList();
if (receivers.isEmpty()) {
log.warn("学校平台消息没有符合要求的接收人,已跳过发送");
log.warnf("\n====================【学校平台消息发送跳过】====================\n消息ID%s\n消息标题:%s\n查询接收人数:%s\n跳过原因:未查询到可发送的接收人\n==============================================================", sysMsg.getId(), sysMsg.getTitle(), viewUsers.size());
return;
}
log.infof("\n====================【学校平台消息开始发送】====================\n消息ID%s\n消息标题:%s\n发送渠道:短信、钉钉\n接收人数:%s\n==============================================================", sysMsg.getId(), sysMsg.getTitle(), receivers.size());
boolean success = smsService.sendMsg("46", null, receivers, sysMsg.getTitle(), sysMsg.getNote(),
sysMsg.getUrl(), sysMsg.getUrl());
if (!success) {
log.warnf("学校平台短信和钉钉组合消息发送失败,消息ID:%s", sysMsg.getId());
log.warnf("\n====================【学校平台消息发送失败】====================\n消息ID%s\n消息标题:%s\n发送渠道:短信、钉钉\n接收人数:%s\n详细批次结果请查看前序学校平台消息日志或全局消息发送记录。\n==============================================================", sysMsg.getId(), sysMsg.getTitle(), receivers.size());
return;
}
log.infof("\n====================【学校平台消息发送成功】====================\n消息ID%s\n消息标题:%s\n发送渠道:短信、钉钉\n接收人数:%s\n==============================================================", sysMsg.getId(), sysMsg.getTitle(), receivers.size());
});
return sysMsg;