- 按分类计数改分类总数(sysTotal/bizTotal/approvalTotal,与列表内容对齐),已读=已读总数、全部=全部总数 - 按应用角标改 countByApp 按应用消息总数(含已读,已读后不清零),总数>0 才显示、总数降序 - 应用匹配/筛选全面改 appId:行与计数出参带 appId、筛选传 appId,appKey 不再出现在消息中心前端
This commit is contained in:
+13
-9
@@ -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<PageData>({ 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<Record<string, number>>({ url });
|
||||
getMsgCenterCountByApp() {
|
||||
const url = path + "/msgCenter/countByApp";
|
||||
return this.getRequest<{ appId: number | null; appName: string | null; total: number; unread: number }[]>({ url });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+36
-35
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 模式二:按应用(应用清单=GetUserApp 用户应用全集;角标=unreadCountByApp 按应用未读数) -->
|
||||
<!-- 模式二:按应用(应用清单=GetUserApp 用户应用全集;角标=countByApp 消息总数,0 不显示) -->
|
||||
<div v-show="mode === 'app'">
|
||||
<div class="side-title">全部应用</div>
|
||||
<div :class="['cat', { active: curApp === 'all' }]" @click="onClickApp('all')">
|
||||
@@ -32,9 +32,9 @@
|
||||
<div class="side-sep"></div>
|
||||
<div
|
||||
v-for="a in appList"
|
||||
:key="a.appKey"
|
||||
:class="['cat', { active: curApp === a.appKey }]"
|
||||
@click="onClickApp(a.appKey)"
|
||||
:key="a.appId"
|
||||
:class="['cat', { active: curApp === String(a.appId) }]"
|
||||
@click="onClickApp(String(a.appId))"
|
||||
>
|
||||
<span class="dot dot-primary"></span>{{ a.name }}<span class="cnt">{{ a.cnt }}</span>
|
||||
</div>
|
||||
@@ -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<HTMLElement | null>(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<Record<string, number>>({});
|
||||
/** 应用导航:清单=用户应用全集(GetUserApp);角标=countByApp 按应用消息总数(含已读),0 不显示 */
|
||||
const userApps = ref<{ appId: number; name: string }[]>([]);
|
||||
const appCountByAppId = ref<Record<number, { total: number; unread: number }>>({});
|
||||
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<string, number> = {};
|
||||
if (byApp && typeof byApp === "object") {
|
||||
Object.entries(byApp).forEach(([k, v]) => (map[k] = Number(v) || 0));
|
||||
}
|
||||
unreadByApp.value = map;
|
||||
const map: Record<number, { total: number; unread: number }> = {};
|
||||
((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) {
|
||||
/* 摘要失败不打扰列表 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user