diff --git a/pom.xml b/pom.xml
index f7dc410..147ed86 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
jar
com.budwk
- zhgh_cug_v4
+ zhgh_zjvtit_v4
5.6.0-plus
2.6.0-SNAPSHOT
diff --git a/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java
index 475245c..5eb114c 100644
--- a/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java
+++ b/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java
@@ -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 receivers, NutMap payload) {
+ NutMap logPayload = NutMap.NEW();
+ logPayload.putAll(payload);
+ logPayload.remove("sign");
+ List 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 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);
+ }
+
/**
* 生成消息中心请求签名。
*
diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java
index b51d08b..d0a9bfd 100644
--- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java
+++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java
@@ -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);
diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java
index 18899c5..fe021d6 100644
--- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java
+++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java
@@ -141,7 +141,8 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl
}
}
- 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
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("""
diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java
index d4e568b..5dabe49 100644
--- a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java
+++ b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java
@@ -112,14 +112,17 @@ public class SysMsgServiceImpl extends BaseServiceImpl 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;