diff --git a/src/api/BaseApi.ts b/src/api/BaseApi.ts index ca374b5..5d4b084 100644 --- a/src/api/BaseApi.ts +++ b/src/api/BaseApi.ts @@ -107,18 +107,18 @@ class Base extends Abstract { // ===== 消息中心代理(§3.5:经后端签名代理 UserMsg,前端不直连)===== /** - * 消息中心分页列表({total, list[]};元素含改写后的绝对 jumpUrl)。 - * 可选服务端筛选:msgType 0/1/2、appKey、isRead 0/1、keyword 标题/内容模糊。 + * 消息中心分页列表({total, list[]};元素含改写后的绝对 jumpUrl、appId/appName)。 + * 可选服务端筛选:msgType 0/1/2、appId(注册表应用 id)、isRead 0/1、keyword 标题/内容模糊。 * @memberof Basic */ - getMsgCenterList(params: PageParams & { msgType?: number; appKey?: string; isRead?: number; keyword?: string }) { + getMsgCenterList(params: PageParams & { msgType?: number; appId?: string; isRead?: number; keyword?: string }) { const url = path + "/msgCenter/list"; return this.getRequest({ url, params }); } /** - * 铃铛摘要:未读数 + 各应用待办角标 + 分类计数(sysUnread/bizUnread/approvalUnread/total/readCount, - * 旧版 UserMsg 无 summary 端点时这些字段缺省,前端按降级处理) + * 铃铛摘要:未读数 + 各应用待办角标 + 分类计数(sysUnread/bizUnread/approvalUnread 为未读口径, + * sysTotal/bizTotal/approvalTotal/total/readCount 为总数口径;旧版 UserMsg 无这些端点字段时缺省,前端按降级处理) * @memberof Basic */ getMsgCenterSummary() { @@ -129,18 +129,22 @@ class Base extends Abstract { sysUnread?: number; bizUnread?: number; approvalUnread?: number; + sysTotal?: number; + bizTotal?: number; + approvalTotal?: number; total?: number; readCount?: number; }>({ url }); } /** - * 消息中心:按来源应用未读数映射(「按应用」清单角标):{appKey: 未读数},无未读的 appKey 不出现 + * 消息中心:按来源应用消息计数(「按应用」清单角标):[{appId, appName, total, unread}], + * total 含已读;无消息的应用不出现 * @memberof Basic */ - getMsgCenterUnreadCountByApp() { - const url = path + "/msgCenter/unreadCountByApp"; - return this.getRequest>({ url }); + getMsgCenterCountByApp() { + const url = path + "/msgCenter/countByApp"; + return this.getRequest<{ appId: number | null; appName: string | null; total: number; unread: number }[]>({ url }); } /** diff --git a/src/views/msg/index.vue b/src/views/msg/index.vue index f6c8f2b..829e613 100644 --- a/src/views/msg/index.vue +++ b/src/views/msg/index.vue @@ -23,7 +23,7 @@ - +
全部应用
@@ -32,9 +32,9 @@
{{ a.name }}{{ a.cnt }}
@@ -129,7 +129,7 @@ interface MsgRow { content: string; msgType: number; // 0 系统通知 / 1 业务提醒 / 2 审批待办 appName?: string | null; - appKey?: string | null; + appId?: number | null; // 注册表应用 id(appKey 不下发前端) sendTime?: string; // yyyy-MM-dd HH:mm:ss isRead: number; // 1=已读 jumpUrl?: string | null; @@ -158,39 +158,40 @@ const loadError = ref(false); const hasMore = computed(() => rows.value.length < total.value); const refMsgBody = ref(null); -/** summary 左栏计数(旧版 UserMsg 无 summary 端点时分类字段缺省 → 显示 —) */ -const catCounts = ref<{ sysUnread?: number; bizUnread?: number; approvalUnread?: number; total?: number; readCount?: number }>({}); +/** summary 左栏计数(分类总数口径;旧版 UserMsg 无字段时缺省 → 显示 —) */ +const catCounts = ref<{ sysTotal?: number; bizTotal?: number; approvalTotal?: number; total?: number; readCount?: number }>({}); const summaryTotalHint = computed(() => (catCounts.value.total == null ? "—" : String(catCounts.value.total))); function isUnread(m: MsgRow) { return m.isRead !== 1; } -/** appName 缺失降级:按 appKey 匹配用户应用清单(与桌面网格同源),再退类型标签 */ +/** appName 缺失降级:按 appId 匹配用户应用清单(与桌面网格同源),再退类型标签 */ function typeAppName(m: MsgRow) { - if (m.appKey) { - const hit = userApps.value.find(a => a.appKey === String(m.appKey)); + if (m.appId != null) { + const hit = userApps.value.find(a => a.appId === m.appId); if (hit && hit.name) return hit.name; } return typeName(m.msgType); } -/** 分类导航(计数走 summary:分类未读数;「已读」= 已读总数) */ +/** 分类导航(计数=分类消息总数含已读,与列表内容对齐;「全部」=全部总数、「已读」=已读总数) */ const catList = computed(() => [ { key: "all", name: "全部消息", color: "#5979ea", cnt: catCounts.value.total == null ? "—" : catCounts.value.total }, - { key: "sys", name: "系统通知", color: "#5979ea", cnt: catCounts.value.sysUnread == null ? "—" : catCounts.value.sysUnread }, - { key: "biz", name: "业务提醒", color: "#e9b954", cnt: catCounts.value.bizUnread == null ? "—" : catCounts.value.bizUnread }, - { key: "appr", name: "审批待办", color: "#e8684a", cnt: catCounts.value.approvalUnread == null ? "—" : catCounts.value.approvalUnread }, + { key: "sys", name: "系统通知", color: "#5979ea", cnt: catCounts.value.sysTotal == null ? "—" : catCounts.value.sysTotal }, + { key: "biz", name: "业务提醒", color: "#e9b954", cnt: catCounts.value.bizTotal == null ? "—" : catCounts.value.bizTotal }, + { key: "appr", name: "审批待办", color: "#e8684a", cnt: catCounts.value.approvalTotal == null ? "—" : catCounts.value.approvalTotal }, { key: "read", name: "已读", color: "#c0c6ce", cnt: catCounts.value.readCount == null ? "—" : catCounts.value.readCount }, ]); -/** 应用导航:清单=用户应用全集(GetUserApp,BoaApp 自带 appKey/name,与桌面网格同源);角标=按应用未读数 */ -const userApps = ref<{ appKey: string; name: string }[]>([]); -const unreadByApp = ref>({}); +/** 应用导航:清单=用户应用全集(GetUserApp);角标=countByApp 按应用消息总数(含已读),0 不显示 */ +const userApps = ref<{ appId: number; name: string }[]>([]); +const appCountByAppId = ref>({}); const appList = computed(() => userApps.value - .map(a => ({ appKey: a.appKey, name: a.name, cnt: unreadByApp.value[a.appKey] || 0 })) - .sort((x, y) => y.cnt - x.cnt) // 未读多的排前(稳定排序,同计数保持注册表顺序) + .map(a => ({ appId: a.appId, name: a.name, cnt: appCountByAppId.value[a.appId]?.total || 0 })) + .filter(a => a.cnt > 0) + .sort((x, y) => y.cnt - x.cnt) // 总数多的排前(稳定排序,同计数保持注册表顺序) ); /** 应用清单一次拉齐(GetUserApp;失败降级空,不打扰列表) */ @@ -199,8 +200,8 @@ async function loadApps() { const groups: any[] = await BaseApi.getUserApp(store.getCurUserId, store.getCurSchId); userApps.value = (groups || []) .flatMap((g: any) => (g && Array.isArray(g.apps) ? g.apps : [])) - .filter((a: any) => a && a.appKey != null) - .map((a: any) => ({ appKey: String(a.appKey), name: a.name })); + .filter((a: any) => a && a.id != null) + .map((a: any) => ({ appId: Number(a.id), name: a.name })); } catch (e) { /* 应用清单失败降级空 */ } @@ -213,13 +214,13 @@ const curTitle = computed(() => { return hit ? hit.name : "全部消息"; } if (curApp.value === "all") return "全部应用消息"; - const hit = appList.value.find(a => a.appKey === curApp.value); + const hit = appList.value.find(a => String(a.appId) === curApp.value); return hit ? hit.name : "全部应用消息"; }); -/** 当前筛选条件 → 服务端参数(筛选语义归服务端,本地不过滤) */ +/** 当前筛选条件 → 服务端参数(筛选语义归服务端,本地不过滤;应用筛选传注册表 appId) */ function currentParams(extra: { page: number }) { - const params: { page: number; count: number; msgType?: number; appKey?: string; isRead?: number; keyword?: string } = { + const params: { page: number; count: number; msgType?: number; appId?: string; isRead?: number; keyword?: string } = { page: extra.page, count: PAGE_SIZE, }; @@ -229,7 +230,7 @@ function currentParams(extra: { page: number }) { else if (curCat.value === "appr") params.msgType = 2; else if (curCat.value === "read") params.isRead = 1; } else if (curApp.value !== "all") { - params.appKey = curApp.value; + params.appId = curApp.value; } const kw = searchText.value.trim(); if (kw) params.keyword = kw; @@ -270,28 +271,28 @@ function onScroll() { } } -/** 左栏计数一次拉齐(未读总数进 store 与铃铛同源;按应用未读数一并拉取) */ +/** 左栏计数一次拉齐(未读总数进 store 与铃铛同源;按应用消息计数一并拉取) */ async function loadSummary() { try { const [s, byApp] = await Promise.all([ BaseApi.getMsgCenterSummary(), - BaseApi.getMsgCenterUnreadCountByApp().catch(() => null), + BaseApi.getMsgCenterCountByApp().catch(() => null), ]); if (s) { store.setUnreadCount(s.unreadCount); catCounts.value = { - sysUnread: (s as any).sysUnread, - bizUnread: (s as any).bizUnread, - approvalUnread: (s as any).approvalUnread, + sysTotal: (s as any).sysTotal, + bizTotal: (s as any).bizTotal, + approvalTotal: (s as any).approvalTotal, total: (s as any).total, readCount: (s as any).readCount, }; } - const map: Record = {}; - if (byApp && typeof byApp === "object") { - Object.entries(byApp).forEach(([k, v]) => (map[k] = Number(v) || 0)); - } - unreadByApp.value = map; + const map: Record = {}; + ((byApp as any) || []).forEach((e: any) => { + if (e && e.appId != null) map[Number(e.appId)] = { total: Number(e.total) || 0, unread: Number(e.unread) || 0 }; + }); + appCountByAppId.value = map; } catch (e) { /* 摘要失败不打扰列表 */ }