feat(msgcenter): 列表筛选参数透传 + summary 聚合 UserMsg 分类计数(消息对接 2026-09-30)

- MessageCenterController.msgCenter/list:可选参数 msgType(0/1/2)/appKey/isRead(0/1)/keyword 透传代理,不传与现状一致(Header 回归无影响)
- MsgCenterProxyService.list:非空才下发 query(旧 UserMsg 收到未知参数会被忽略——UserMsg 部署前线上筛选静默失效,属预期过渡,待人工清单含 UserMsg 部署)
- MsgCenterProxyService.summary:优先调 UserMsg /oapi/msg/summary(新端点:unreadCount/sysUnread/bizUnread/approvalUnread/total/readCount 一次喂饱左栏);旧版无该端点(404/异常)自动降级 unreadCount 单查,分类字段缺省由前端兜底
- 单测:list_filtersPassedThrough(透传+空值不下发)、summary_prefersSummaryEndpoint、summary_legacyUserMsg_fallsBackToUnreadCount;既有 28 用例回归全绿(31 run 0 fail)
This commit is contained in:
chenxing
2026-09-30 12:37:55 +08:00
parent 9f10d8d4eb
commit 29f6c30309
3 changed files with 129 additions and 18 deletions
@@ -82,8 +82,13 @@ public class MsgCenterProxyService {
return openCall.post(TARGET_USERMSG, path, query, body, JsonNode.class);
}
/** 消息分页列表(已过滤删除/过期):{total, list[]},元素含改写后的 jumpUrl 与 showJump 判权出参 */
public Map<String, Object> list(Integer userId, Integer pageIndex, Integer pageSize, Boolean onlyUnread) {
/**
* 消息分页列表(已过滤删除/过期):{total, list[]},元素含改写后的 jumpUrl 与 showJump 判权出参。
* 可选筛选(null/空白不透传,旧 UserMsg 收到未知参数会忽略——不传时行为与历史版本一致):
* msgType 0/1/2、appKey 精确、isRead 0/1、keyword 标题/内容模糊。
*/
public Map<String, Object> list(Integer userId, Integer pageIndex, Integer pageSize, Boolean onlyUnread,
Integer msgType, String appKey, Integer isRead, String keyword) {
Map<String, Object> empty = emptyPage();
if (!enabled()) {
return empty;
@@ -95,6 +100,14 @@ public class MsgCenterProxyService {
query.put("pageIndex", String.valueOf(pageIndex == null || pageIndex < 1 ? 1 : pageIndex));
query.put("pageSize", String.valueOf(pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 100)));
query.put("onlyUnread", String.valueOf(Boolean.TRUE.equals(onlyUnread)));
if (msgType != null) {
query.put("msgType", String.valueOf(msgType));
}
putIfText(query, "appKey", appKey);
if (isRead != null) {
query.put("isRead", String.valueOf(isRead));
}
putIfText(query, "keyword", keyword);
JsonNode data = get("/oapi/msg/list", query);
List<Map<String, Object>> rows = new ArrayList<>();
if (data != null && data.path("content").isArray()) {
@@ -112,7 +125,11 @@ public class MsgCenterProxyService {
}
}
/** 铃铛摘要:未读数 + 各应用待办角标(停机各自降级 0/空) */
/**
* 铃铛摘要:未读数 + 各应用待办角标 + 分类计数(停机各自降级 0/空)。
* 分类计数(sysUnread/bizUnread/approvalUnread/total/readCount)来自 UserMsg /oapi/msg/summary
* (消息中心左栏一次喂饱);旧版 UserMsg 无该端点 → 字段缺省不出现,前端按降级处理。
*/
public Map<String, Object> summary(Integer userId, Integer schId) {
Map<String, Object> out = new HashMap<>();
out.put("unreadCount", 0L);
@@ -120,13 +137,33 @@ public class MsgCenterProxyService {
if (!enabled()) {
return out;
}
boolean summaryFetched = false;
try {
Map<String, String> q = new LinkedHashMap<>();
q.put("userId", String.valueOf(userId));
JsonNode unread = get("/oapi/msg/unreadCount", q);
out.put("unreadCount", unread == null || !unread.isNumber() ? 0L : unread.asLong());
JsonNode vo = get("/oapi/msg/summary", q);
if (vo != null && vo.has("unreadCount")) {
out.put("unreadCount", vo.get("unreadCount").asLong());
out.put("sysUnread", vo.path("sysUnread").asLong(0));
out.put("bizUnread", vo.path("bizUnread").asLong(0));
out.put("approvalUnread", vo.path("approvalUnread").asLong(0));
out.put("total", vo.path("total").asLong(0));
out.put("readCount", vo.path("readCount").asLong(0));
summaryFetched = true;
}
} catch (Exception e) {
log.warn("[msgcenter] UserMsg 未读数不可达(降级 0)userId={}:{}", userId, e.toString());
// 旧版 UserMsg 无 summary 端点:降级走 unreadCount 单查,字段缺省由前端兜底
log.debug("[msgcenter] UserMsg 摘要端点不可用(降级未读单查)userId={}:{}", userId, e.toString());
}
if (!summaryFetched) {
try {
Map<String, String> q = new LinkedHashMap<>();
q.put("userId", String.valueOf(userId));
JsonNode unread = get("/oapi/msg/unreadCount", q);
out.put("unreadCount", unread == null || !unread.isNumber() ? 0L : unread.asLong());
} catch (Exception e) {
log.warn("[msgcenter] UserMsg 未读数不可达(降级 0)userId={}:{}", userId, e.toString());
}
}
try {
Map<String, String> q = new LinkedHashMap<>();
@@ -400,6 +437,13 @@ public class MsgCenterProxyService {
return out;
}
/** 有值(非空白)才进 query——空串不透传,保持与不传一致 */
private static void putIfText(Map<String, String> query, String key, String value) {
if (StringUtils.hasText(value)) {
query.put(key, value.trim());
}
}
private static String text(JsonNode node, String field) {
return node != null && node.has(field) && !node.get(field).isNull() ? node.get(field).asText() : null;
}