@robot-admin/naive-ui-components 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/C_ActionBar.cjs +1 -5
- package/dist/C_ActionBar.js +1 -4
- package/dist/C_ActionBar.js.map +1 -0
- package/dist/C_ActionBar2.js +1 -195
- package/dist/C_ActionBar2.js.map +1 -1
- package/dist/C_AntV.cjs +1 -8
- package/dist/C_AntV.js +1 -4
- package/dist/C_AntV.js.map +1 -0
- package/dist/C_AntV2.js +4 -3149
- package/dist/C_AntV2.js.map +1 -1
- package/dist/C_Barcode.cjs +1 -4
- package/dist/C_Barcode.js +1 -3
- package/dist/C_Barcode.js.map +1 -0
- package/dist/C_Barcode2.js +1 -67
- package/dist/C_Barcode2.js.map +1 -1
- package/dist/C_Captcha.cjs +1 -4
- package/dist/C_Captcha.js +1 -3
- package/dist/C_Captcha.js.map +1 -0
- package/dist/C_Captcha2.js +1 -154
- package/dist/C_Captcha2.js.map +1 -1
- package/dist/C_Cascade.cjs +1 -4
- package/dist/C_Cascade.js +1 -3
- package/dist/C_Cascade.js.map +1 -0
- package/dist/C_Cascade2.js +1 -102
- package/dist/C_Cascade2.js.map +1 -1
- package/dist/C_City.cjs +1 -4
- package/dist/C_City.js +1 -3
- package/dist/C_City.js.map +1 -0
- package/dist/C_City2.js +1 -840
- package/dist/C_City2.js.map +1 -1
- package/dist/C_Code.cjs +1 -5
- package/dist/C_Code.js +1 -4
- package/dist/C_Code.js.map +1 -0
- package/dist/C_Code2.js +1 -346
- package/dist/C_Code2.js.map +1 -1
- package/dist/C_CollapsePanel.cjs +1 -6
- package/dist/C_CollapsePanel.js +1 -4
- package/dist/C_CollapsePanel.js.map +1 -0
- package/dist/C_CollapsePanel2.js +1 -318
- package/dist/C_CollapsePanel2.js.map +1 -1
- package/dist/C_Cron.cjs +1 -15
- package/dist/C_Cron.js +1 -4
- package/dist/C_Cron.js.map +1 -0
- package/dist/C_Cron2.js +1 -1209
- package/dist/C_Cron2.js.map +1 -1
- package/dist/C_Date.cjs +1 -4
- package/dist/C_Date.js +1 -3
- package/dist/C_Date.js.map +1 -0
- package/dist/C_Date2.js +1 -218
- package/dist/C_Date2.js.map +1 -1
- package/dist/C_Draggable.cjs +1 -5
- package/dist/C_Draggable.js +1 -3
- package/dist/C_Draggable.js.map +1 -0
- package/dist/C_Draggable2.js +1 -294
- package/dist/C_Draggable2.js.map +1 -1
- package/dist/C_Editor.cjs +1 -4
- package/dist/C_Editor.js +1 -3
- package/dist/C_Editor.js.map +1 -0
- package/dist/C_Editor2.js +1 -159
- package/dist/C_Editor2.js.map +1 -1
- package/dist/C_FilePreview.cjs +1 -7
- package/dist/C_FilePreview.js +1 -4
- package/dist/C_FilePreview.js.map +1 -0
- package/dist/C_FilePreview2.js +1 -1031
- package/dist/C_FilePreview2.js.map +1 -1
- package/dist/C_Form.cjs +1 -16
- package/dist/C_Form.js +1 -5
- package/dist/C_Form.js.map +1 -0
- package/dist/C_Form2.js +1 -2569
- package/dist/C_Form2.js.map +1 -1
- package/dist/C_FormSearch.cjs +1 -6
- package/dist/C_FormSearch.js +1 -3
- package/dist/C_FormSearch.js.map +1 -0
- package/dist/C_FormSearch2.js +1 -355
- package/dist/C_FormSearch2.js.map +1 -1
- package/dist/C_FormulaEditor.cjs +1 -13
- package/dist/C_FormulaEditor.js +1 -4
- package/dist/C_FormulaEditor.js.map +1 -0
- package/dist/C_FormulaEditor2.js +1 -1432
- package/dist/C_FormulaEditor2.js.map +1 -1
- package/dist/C_FullCalendar.cjs +1 -9
- package/dist/C_FullCalendar.js +1 -3
- package/dist/C_FullCalendar.js.map +1 -0
- package/dist/C_FullCalendar2.js +1 -376
- package/dist/C_FullCalendar2.js.map +1 -1
- package/dist/C_GlobalSearch.cjs +1 -5
- package/dist/C_GlobalSearch.js +1 -3
- package/dist/C_GlobalSearch.js.map +1 -0
- package/dist/C_GlobalSearch2.js +1 -335
- package/dist/C_GlobalSearch2.js.map +1 -1
- package/dist/C_Guide.cjs +1 -5
- package/dist/C_Guide.js +1 -4
- package/dist/C_Guide.js.map +1 -0
- package/dist/C_Guide2.js +1 -60
- package/dist/C_Guide2.js.map +1 -1
- package/dist/C_Icon.cjs +1 -4
- package/dist/C_Icon.js +1 -3
- package/dist/C_Icon.js.map +1 -0
- package/dist/C_Icon2.js +1 -285
- package/dist/C_Icon2.js.map +1 -1
- package/dist/C_ImageCropper.cjs +1 -6
- package/dist/C_ImageCropper.js +1 -4
- package/dist/C_ImageCropper.js.map +1 -0
- package/dist/C_ImageCropper2.js +1 -722
- package/dist/C_ImageCropper2.js.map +1 -1
- package/dist/C_Language.cjs +1 -5
- package/dist/C_Language.js +1 -4
- package/dist/C_Language.js.map +1 -0
- package/dist/C_Language2.js +1 -78
- package/dist/C_Language2.js.map +1 -1
- package/dist/C_Map.cjs +1 -7
- package/dist/C_Map.js +1 -3
- package/dist/C_Map.js.map +1 -0
- package/dist/C_Map2.js +1 -198
- package/dist/C_Map2.js.map +1 -1
- package/dist/C_Markdown.cjs +1 -4
- package/dist/C_Markdown.js +1 -3
- package/dist/C_Markdown.js.map +1 -0
- package/dist/C_Markdown2.js +1 -185
- package/dist/C_Markdown2.js.map +1 -1
- package/dist/C_NotificationCenter.cjs +1 -20
- package/dist/C_NotificationCenter.js +1 -4
- package/dist/C_NotificationCenter.js.map +1 -0
- package/dist/C_NotificationCenter2.js +1 -1383
- package/dist/C_NotificationCenter2.js.map +1 -1
- package/dist/C_Progress.cjs +1 -4
- package/dist/C_Progress.js +1 -3
- package/dist/C_Progress.js.map +1 -0
- package/dist/C_Progress2.js +1 -102
- package/dist/C_Progress2.js.map +1 -1
- package/dist/C_QRCode.cjs +1 -5
- package/dist/C_QRCode.js +1 -3
- package/dist/C_QRCode.js.map +1 -0
- package/dist/C_QRCode2.js +1 -217
- package/dist/C_QRCode2.js.map +1 -1
- package/dist/C_Signature.cjs +1 -8
- package/dist/C_Signature.js +1 -4
- package/dist/C_Signature.js.map +1 -0
- package/dist/C_Signature2.js +1 -617
- package/dist/C_Signature2.js.map +1 -1
- package/dist/C_SplitPane.cjs +1 -6
- package/dist/C_SplitPane.js +1 -4
- package/dist/C_SplitPane.js.map +1 -0
- package/dist/C_SplitPane2.js +1 -355
- package/dist/C_SplitPane2.js.map +1 -1
- package/dist/C_Steps.cjs +1 -4
- package/dist/C_Steps.js +1 -3
- package/dist/C_Steps.js.map +1 -0
- package/dist/C_Steps2.js +1 -81
- package/dist/C_Steps2.js.map +1 -1
- package/dist/C_Table.cjs +1 -20
- package/dist/C_Table.js +1 -6
- package/dist/C_Table.js.map +1 -0
- package/dist/C_Table2.js +1 -3023
- package/dist/C_Table2.js.map +1 -1
- package/dist/C_Theme.cjs +1 -5
- package/dist/C_Theme.js +1 -4
- package/dist/C_Theme.js.map +1 -0
- package/dist/C_Theme2.js +1 -63
- package/dist/C_Theme2.js.map +1 -1
- package/dist/C_Time.cjs +1 -5
- package/dist/C_Time.js +1 -3
- package/dist/C_Time.js.map +1 -0
- package/dist/C_Time2.js +1 -198
- package/dist/C_Time2.js.map +1 -1
- package/dist/C_Tree.cjs +1 -7
- package/dist/C_Tree.js +1 -4
- package/dist/C_Tree.js.map +1 -0
- package/dist/C_Tree2.js +1 -440
- package/dist/C_Tree2.js.map +1 -1
- package/dist/C_Upload.cjs +1 -12
- package/dist/C_Upload.js +1 -4
- package/dist/C_Upload.js.map +1 -0
- package/dist/C_Upload2.js +2 -1365
- package/dist/C_Upload2.js.map +1 -1
- package/dist/C_VideoPlayer.cjs +1 -23
- package/dist/C_VideoPlayer.js +1 -3
- package/dist/C_VideoPlayer.js.map +1 -0
- package/dist/C_VideoPlayer2.js +3 -1932
- package/dist/C_VideoPlayer2.js.map +1 -1
- package/dist/C_VtableGantt.cjs +1 -6
- package/dist/C_VtableGantt.js +1 -4
- package/dist/C_VtableGantt.js.map +1 -0
- package/dist/C_VtableGantt2.js +1 -872
- package/dist/C_VtableGantt2.js.map +1 -1
- package/dist/C_WaterFall.cjs +1 -13
- package/dist/C_WaterFall.js +1 -3
- package/dist/C_WaterFall.js.map +1 -0
- package/dist/C_WaterFall2.js +1 -364
- package/dist/C_WaterFall2.js.map +1 -1
- package/dist/C_WorkFlow.cjs +1 -8
- package/dist/C_WorkFlow.js +1 -4
- package/dist/C_WorkFlow.js.map +1 -0
- package/dist/C_WorkFlow2.js +1 -1983
- package/dist/C_WorkFlow2.js.map +1 -1
- package/dist/chunk.js +1 -18
- package/dist/city.js +1 -4816
- package/dist/constants.d.ts +2 -2
- package/dist/constants2.d.ts +3 -3
- package/dist/constants3.d.ts +3 -3
- package/dist/constants4.d.ts +5 -5
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +1 -1
- package/dist/export-helper.js +1 -9
- package/dist/index.cjs +2 -413
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -231
- package/dist/index.js.map +1 -1
- package/dist/index.vue.d.ts +2 -2
- package/dist/index10.vue.d.ts +5 -5
- package/dist/index12.vue.d.ts +3 -3
- package/dist/index13.vue.d.ts +3 -3
- package/dist/index14.vue.d.ts +3 -3
- package/dist/index16.vue.d.ts +3 -3
- package/dist/index3.vue.d.ts +3 -3
- package/dist/index5.vue.d.ts +1 -1
- package/dist/index7.vue.d.ts +4 -4
- package/dist/index8.vue.d.ts +2 -2
- package/dist/resolver.cjs +2 -89
- package/dist/resolver.cjs.map +1 -0
- package/dist/resolver.js +1 -86
- package/dist/resolver.js.map +1 -1
- package/dist/storage.js +1 -30
- package/dist/storage.js.map +1 -1
- package/dist/useCollapsePanel.d.ts +2 -2
- package/dist/useCropperCore.d.ts +8 -8
- package/dist/useDraggableLayout.d.ts +4 -4
- package/dist/useDynamicFormState.d.ts +7 -7
- package/dist/useEdgeInteraction.d.ts +1 -1
- package/dist/useFullscreen.d.ts +2 -2
- package/dist/useInfiniteScroll.d.ts +1 -1
- package/dist/useModalEdit.d.ts +1 -1
- package/dist/useQRCode.d.ts +3 -3
- package/dist/useSearchState.d.ts +2 -2
- package/dist/useSignatureHistory.d.ts +1 -1
- package/dist/useSplitResize.d.ts +6 -6
- package/dist/useTimeSelection.d.ts +2 -2
- package/dist/useTreeOperations.d.ts +6 -6
- package/dist/useWorkflowValidation.d.ts +4 -4
- package/package.json +1 -2
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants2.d.ts.map +0 -1
- package/dist/constants3.d.ts.map +0 -1
- package/dist/constants4.d.ts.map +0 -1
- package/dist/constants5.d.ts.map +0 -1
- package/dist/data.d.ts.map +0 -1
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.vue.d.ts.map +0 -1
- package/dist/index10.vue.d.ts.map +0 -1
- package/dist/index11.vue.d.ts.map +0 -1
- package/dist/index12.vue.d.ts.map +0 -1
- package/dist/index13.vue.d.ts.map +0 -1
- package/dist/index14.vue.d.ts.map +0 -1
- package/dist/index15.vue.d.ts.map +0 -1
- package/dist/index16.vue.d.ts.map +0 -1
- package/dist/index2.vue.d.ts.map +0 -1
- package/dist/index3.vue.d.ts.map +0 -1
- package/dist/index4.vue.d.ts.map +0 -1
- package/dist/index5.vue.d.ts.map +0 -1
- package/dist/index6.vue.d.ts.map +0 -1
- package/dist/index7.vue.d.ts.map +0 -1
- package/dist/index8.vue.d.ts.map +0 -1
- package/dist/index9.vue.d.ts.map +0 -1
- package/dist/resolver.d.cts.map +0 -1
- package/dist/resolver.d.ts.map +0 -1
- package/dist/useCalendarEvents.d.ts.map +0 -1
- package/dist/useCollapsePanel.d.ts.map +0 -1
- package/dist/useCropperCore.d.ts.map +0 -1
- package/dist/useDraggableLayout.d.ts.map +0 -1
- package/dist/useDynamicFormState.d.ts.map +0 -1
- package/dist/useEdgeInteraction.d.ts.map +0 -1
- package/dist/useFullscreen.d.ts.map +0 -1
- package/dist/useGlobalSearch.d.ts.map +0 -1
- package/dist/useInfiniteScroll.d.ts.map +0 -1
- package/dist/useModalEdit.d.ts.map +0 -1
- package/dist/useQRCode.d.ts.map +0 -1
- package/dist/useSearchState.d.ts.map +0 -1
- package/dist/useSignatureHistory.d.ts.map +0 -1
- package/dist/useSplitResize.d.ts.map +0 -1
- package/dist/useTimeSelection.d.ts.map +0 -1
- package/dist/useTreeOperations.d.ts.map +0 -1
- package/dist/useWorkflowValidation.d.ts.map +0 -1
|
@@ -1,1384 +1,2 @@
|
|
|
1
|
-
import { t as C_Icon_default } from "./C_Icon2.js";
|
|
2
|
-
import { t as export_helper_default } from "./export-helper.js";
|
|
3
|
-
import { i as setItem, t as getItem } from "./storage.js";
|
|
4
|
-
import { NAvatar, NButton, NPopover, NScrollbar, NSkeleton, NSpin, NTag, NTooltip } from "naive-ui";
|
|
5
|
-
import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, readonly, ref, renderList, toDisplayString, unref, watch, withCtx, withModifiers } from "vue";
|
|
6
|
-
|
|
7
|
-
//#region src/components/C_NotificationCenter/constants.ts
|
|
8
|
-
/** 默认角标最大显示数 */
|
|
9
|
-
const DEFAULT_MAX_BADGE_COUNT = 99;
|
|
10
|
-
/** 默认每页条数 */
|
|
11
|
-
const DEFAULT_PAGE_SIZE = 20;
|
|
12
|
-
/** 默认轮询间隔(ms):60 秒 */
|
|
13
|
-
const DEFAULT_POLLING_INTERVAL = 6e4;
|
|
14
|
-
/** 默认缓存 key */
|
|
15
|
-
const DEFAULT_STORAGE_KEY = "notification_center";
|
|
16
|
-
/** WebSocket 默认重连间隔(ms) */
|
|
17
|
-
const DEFAULT_WS_RECONNECT_INTERVAL = 3e3;
|
|
18
|
-
/** WebSocket 默认最大重连次数 */
|
|
19
|
-
const DEFAULT_WS_MAX_RECONNECT = 5;
|
|
20
|
-
/** WebSocket 默认心跳间隔(ms) */
|
|
21
|
-
const DEFAULT_WS_HEARTBEAT_INTERVAL = 3e4;
|
|
22
|
-
/** WebSocket 默认心跳消息 */
|
|
23
|
-
const DEFAULT_WS_HEARTBEAT_MESSAGE = "ping";
|
|
24
|
-
/** 分类标签映射 */
|
|
25
|
-
const CATEGORY_MAP = {
|
|
26
|
-
system: {
|
|
27
|
-
label: "系统通知",
|
|
28
|
-
icon: "mdi:cog-outline",
|
|
29
|
-
color: "info"
|
|
30
|
-
},
|
|
31
|
-
business: {
|
|
32
|
-
label: "业务消息",
|
|
33
|
-
icon: "mdi:briefcase-outline",
|
|
34
|
-
color: "success"
|
|
35
|
-
},
|
|
36
|
-
alarm: {
|
|
37
|
-
label: "告警预警",
|
|
38
|
-
icon: "mdi:alert-outline",
|
|
39
|
-
color: "warning"
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
/** 分类 Tab 列表 */
|
|
43
|
-
const CATEGORY_TABS = [
|
|
44
|
-
{
|
|
45
|
-
key: "all",
|
|
46
|
-
label: "全部"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
key: "system",
|
|
50
|
-
label: "系统通知"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
key: "business",
|
|
54
|
-
label: "业务消息"
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
key: "alarm",
|
|
58
|
-
label: "告警预警"
|
|
59
|
-
}
|
|
60
|
-
];
|
|
61
|
-
/** 优先级标签映射 */
|
|
62
|
-
const PRIORITY_MAP = {
|
|
63
|
-
low: {
|
|
64
|
-
label: "低",
|
|
65
|
-
type: "default"
|
|
66
|
-
},
|
|
67
|
-
normal: {
|
|
68
|
-
label: "普通",
|
|
69
|
-
type: "info"
|
|
70
|
-
},
|
|
71
|
-
high: {
|
|
72
|
-
label: "重要",
|
|
73
|
-
type: "warning"
|
|
74
|
-
},
|
|
75
|
-
urgent: {
|
|
76
|
-
label: "紧急",
|
|
77
|
-
type: "error"
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
/** 模拟消息列表 */
|
|
81
|
-
const MOCK_MESSAGES = [
|
|
82
|
-
{
|
|
83
|
-
id: "msg-001",
|
|
84
|
-
title: "系统维护通知",
|
|
85
|
-
summary: "系统将于今晚 22:00-23:00 进行例行维护升级,届时部分功能可能暂时不可用。",
|
|
86
|
-
content: "<p>尊敬的用户:</p><p>为了提升系统性能和稳定性,我们计划于 <strong>2026年2月27日 22:00-23:00</strong> 对系统进行例行维护升级。</p><p>维护期间,以下功能可能暂时不可用:</p><ul><li>报表导出</li><li>数据同步</li><li>定时任务</li></ul><p>请提前保存好未完成的工作,感谢您的理解与支持!</p>",
|
|
87
|
-
category: "system",
|
|
88
|
-
priority: "high",
|
|
89
|
-
status: "unread",
|
|
90
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 15 * 6e4)).toISOString(),
|
|
91
|
-
sender: {
|
|
92
|
-
name: "系统管理员",
|
|
93
|
-
avatar: ""
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
id: "msg-002",
|
|
98
|
-
title: "审批流程待处理",
|
|
99
|
-
summary: "张三提交的《Q1 季度预算申请》需要您审批,请尽快处理。",
|
|
100
|
-
category: "business",
|
|
101
|
-
priority: "urgent",
|
|
102
|
-
status: "unread",
|
|
103
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 30 * 6e4)).toISOString(),
|
|
104
|
-
sender: {
|
|
105
|
-
name: "张三",
|
|
106
|
-
avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png"
|
|
107
|
-
},
|
|
108
|
-
actionUrl: "/workflow/approval",
|
|
109
|
-
actionText: "去审批"
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
id: "msg-003",
|
|
113
|
-
title: "服务器 CPU 使用率告警",
|
|
114
|
-
summary: "生产环境节点 prod-node-03 CPU 使用率持续超过 90%,已触发告警阈值。",
|
|
115
|
-
category: "alarm",
|
|
116
|
-
priority: "urgent",
|
|
117
|
-
status: "unread",
|
|
118
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 2 * 6e4)).toISOString(),
|
|
119
|
-
sender: { name: "监控中心" },
|
|
120
|
-
actionUrl: "/monitor/server",
|
|
121
|
-
actionText: "查看详情"
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
id: "msg-004",
|
|
125
|
-
title: "新版本发布 v1.14.0",
|
|
126
|
-
summary: "系统已升级至 v1.14.0,新增通知中心、工作流增强等多项功能。",
|
|
127
|
-
category: "system",
|
|
128
|
-
priority: "normal",
|
|
129
|
-
status: "unread",
|
|
130
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 3 * 36e5)).toISOString(),
|
|
131
|
-
sender: { name: "系统管理员" }
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
id: "msg-005",
|
|
135
|
-
title: "项目交付提醒",
|
|
136
|
-
summary: "「Robot Admin 二期」项目交付截止日期为 3月15日,当前进度 78%。",
|
|
137
|
-
category: "business",
|
|
138
|
-
priority: "high",
|
|
139
|
-
status: "read",
|
|
140
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 8 * 36e5)).toISOString(),
|
|
141
|
-
sender: { name: "项目管理系统" }
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
id: "msg-006",
|
|
145
|
-
title: "数据库连接池告警",
|
|
146
|
-
summary: "数据库连接池使用率达到 85%,建议关注并适时扩容。",
|
|
147
|
-
category: "alarm",
|
|
148
|
-
priority: "high",
|
|
149
|
-
status: "read",
|
|
150
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 12 * 36e5)).toISOString(),
|
|
151
|
-
sender: { name: "监控中心" }
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
id: "msg-007",
|
|
155
|
-
title: "周报提交提醒",
|
|
156
|
-
summary: "本周周报提交截止时间为周五 18:00,请及时提交。",
|
|
157
|
-
category: "business",
|
|
158
|
-
priority: "normal",
|
|
159
|
-
status: "read",
|
|
160
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 24 * 36e5)).toISOString(),
|
|
161
|
-
sender: { name: "OA 系统" }
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
id: "msg-008",
|
|
165
|
-
title: "账号安全提醒",
|
|
166
|
-
summary: "检测到您的账号在新设备上登录,如非本人操作请及时修改密码。",
|
|
167
|
-
category: "system",
|
|
168
|
-
priority: "high",
|
|
169
|
-
status: "unread",
|
|
170
|
-
timestamp: (/* @__PURE__ */ new Date(Date.now() - 45 * 6e4)).toISOString(),
|
|
171
|
-
sender: { name: "安全中心" }
|
|
172
|
-
}
|
|
173
|
-
];
|
|
174
|
-
|
|
175
|
-
//#endregion
|
|
176
|
-
//#region src/components/C_NotificationCenter/composables/useNotificationWS.ts
|
|
177
|
-
/**
|
|
178
|
-
* WebSocket 连接管理
|
|
179
|
-
*
|
|
180
|
-
* 管理 WebSocket 的建连、重连、心跳保活、消息解析。
|
|
181
|
-
* 支持自动重连、鉴权 token、心跳检测。
|
|
182
|
-
*/
|
|
183
|
-
function useNotificationWS(onMessage, onStatusChange) {
|
|
184
|
-
/** 连接状态 */
|
|
185
|
-
const status = ref("disconnected");
|
|
186
|
-
/** WebSocket 实例 */
|
|
187
|
-
let ws = null;
|
|
188
|
-
/** 重连计数器 */
|
|
189
|
-
let reconnectCount = 0;
|
|
190
|
-
/** 重连定时器 */
|
|
191
|
-
let reconnectTimer = null;
|
|
192
|
-
/** 心跳定时器 */
|
|
193
|
-
let heartbeatTimer = null;
|
|
194
|
-
/** 当前配置 */
|
|
195
|
-
let currentConfig = null;
|
|
196
|
-
/**
|
|
197
|
-
* 更新连接状态
|
|
198
|
-
*/
|
|
199
|
-
function setStatus(s) {
|
|
200
|
-
status.value = s;
|
|
201
|
-
onStatusChange?.(s);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* 建立连接
|
|
205
|
-
*/
|
|
206
|
-
function connect(config) {
|
|
207
|
-
currentConfig = config;
|
|
208
|
-
reconnectCount = 0;
|
|
209
|
-
createConnection(config);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* 创建 WebSocket 连接
|
|
213
|
-
*/
|
|
214
|
-
function createConnection(config) {
|
|
215
|
-
cleanup();
|
|
216
|
-
const url = buildUrl(config);
|
|
217
|
-
setStatus("connecting");
|
|
218
|
-
try {
|
|
219
|
-
ws = new WebSocket(url);
|
|
220
|
-
} catch {
|
|
221
|
-
setStatus("disconnected");
|
|
222
|
-
scheduleReconnect(config);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
ws.addEventListener("open", () => {
|
|
226
|
-
setStatus("connected");
|
|
227
|
-
reconnectCount = 0;
|
|
228
|
-
startHeartbeat(config);
|
|
229
|
-
});
|
|
230
|
-
ws.addEventListener("message", (event) => {
|
|
231
|
-
handleMessage(event.data);
|
|
232
|
-
});
|
|
233
|
-
ws.addEventListener("close", () => {
|
|
234
|
-
stopHeartbeat();
|
|
235
|
-
setStatus("disconnected");
|
|
236
|
-
if (config.autoReconnect !== false) scheduleReconnect(config);
|
|
237
|
-
});
|
|
238
|
-
ws.addEventListener("error", () => {});
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* 构建带 token 的 WebSocket URL
|
|
242
|
-
*/
|
|
243
|
-
function buildUrl(config) {
|
|
244
|
-
const token = config.getToken?.();
|
|
245
|
-
if (token) {
|
|
246
|
-
const separator = config.url.includes("?") ? "&" : "?";
|
|
247
|
-
return `${config.url}${separator}token=${encodeURIComponent(token)}`;
|
|
248
|
-
}
|
|
249
|
-
return config.url;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* 处理接收到的消息
|
|
253
|
-
*/
|
|
254
|
-
function handleMessage(raw) {
|
|
255
|
-
if (typeof raw !== "string") return;
|
|
256
|
-
if (raw === "pong") return;
|
|
257
|
-
try {
|
|
258
|
-
onMessage(JSON.parse(raw));
|
|
259
|
-
} catch {}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* 调度重连
|
|
263
|
-
*/
|
|
264
|
-
function scheduleReconnect(config) {
|
|
265
|
-
const maxAttempts = config.maxReconnectAttempts ?? DEFAULT_WS_MAX_RECONNECT;
|
|
266
|
-
if (reconnectCount >= maxAttempts) return;
|
|
267
|
-
reconnectCount++;
|
|
268
|
-
setStatus("reconnecting");
|
|
269
|
-
const interval = config.reconnectInterval ?? DEFAULT_WS_RECONNECT_INTERVAL;
|
|
270
|
-
reconnectTimer = setTimeout(() => {
|
|
271
|
-
createConnection(config);
|
|
272
|
-
}, interval);
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* 启动心跳
|
|
276
|
-
*/
|
|
277
|
-
function startHeartbeat(config) {
|
|
278
|
-
const interval = config.heartbeatInterval ?? DEFAULT_WS_HEARTBEAT_INTERVAL;
|
|
279
|
-
if (interval <= 0) return;
|
|
280
|
-
const message = config.heartbeatMessage ?? DEFAULT_WS_HEARTBEAT_MESSAGE;
|
|
281
|
-
heartbeatTimer = setInterval(() => {
|
|
282
|
-
if (ws?.readyState === WebSocket.OPEN) ws.send(message);
|
|
283
|
-
}, interval);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* 停止心跳
|
|
287
|
-
*/
|
|
288
|
-
function stopHeartbeat() {
|
|
289
|
-
if (heartbeatTimer) {
|
|
290
|
-
clearInterval(heartbeatTimer);
|
|
291
|
-
heartbeatTimer = null;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* 清理资源
|
|
296
|
-
*/
|
|
297
|
-
function cleanup() {
|
|
298
|
-
stopHeartbeat();
|
|
299
|
-
if (reconnectTimer) {
|
|
300
|
-
clearTimeout(reconnectTimer);
|
|
301
|
-
reconnectTimer = null;
|
|
302
|
-
}
|
|
303
|
-
if (ws) {
|
|
304
|
-
ws.close();
|
|
305
|
-
ws = null;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* 断开连接
|
|
310
|
-
*/
|
|
311
|
-
function disconnect() {
|
|
312
|
-
currentConfig = null;
|
|
313
|
-
reconnectCount = Infinity;
|
|
314
|
-
cleanup();
|
|
315
|
-
setStatus("disconnected");
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* 手动重新连接
|
|
319
|
-
*/
|
|
320
|
-
function reconnect() {
|
|
321
|
-
if (currentConfig) {
|
|
322
|
-
reconnectCount = 0;
|
|
323
|
-
createConnection(currentConfig);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
onBeforeUnmount(cleanup);
|
|
327
|
-
return {
|
|
328
|
-
status: readonly(status),
|
|
329
|
-
connect,
|
|
330
|
-
disconnect,
|
|
331
|
-
reconnect
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
//#endregion
|
|
336
|
-
//#region src/components/C_NotificationCenter/composables/useNotificationCore.ts
|
|
337
|
-
/** 防抖持久化延迟(ms) */
|
|
338
|
-
const PERSIST_DEBOUNCE = 300;
|
|
339
|
-
/**
|
|
340
|
-
* 通知中心核心状态管理
|
|
341
|
-
*
|
|
342
|
-
* 统一管理消息列表、未读数、分类过滤、已读标记、
|
|
343
|
-
* API 交互、WebSocket 桥接、轮询调度和本地缓存。
|
|
344
|
-
*/
|
|
345
|
-
function useNotificationCore(props) {
|
|
346
|
-
/** 消息列表 */
|
|
347
|
-
const messages = ref([]);
|
|
348
|
-
/** 当前选中分类 */
|
|
349
|
-
const activeCategory = ref("all");
|
|
350
|
-
/** 是否正在加载 */
|
|
351
|
-
const loading = ref(false);
|
|
352
|
-
/** 总条数 */
|
|
353
|
-
const total = ref(0);
|
|
354
|
-
/** 当前页码 */
|
|
355
|
-
const page = ref(1);
|
|
356
|
-
/** 选中的消息(详情展示) */
|
|
357
|
-
const selectedMessage = ref(null);
|
|
358
|
-
/** Popover 展开状态 */
|
|
359
|
-
const popoverVisible = ref(false);
|
|
360
|
-
/** WebSocket 连接状态 */
|
|
361
|
-
const wsStatus = ref("disconnected");
|
|
362
|
-
/** 未读消息总数 */
|
|
363
|
-
const unreadCount = computed(() => messages.value.filter((m) => m.status === "unread").length);
|
|
364
|
-
/** 各分类未读数 */
|
|
365
|
-
const unreadByCategory = computed(() => {
|
|
366
|
-
const counts = {
|
|
367
|
-
system: 0,
|
|
368
|
-
business: 0,
|
|
369
|
-
alarm: 0
|
|
370
|
-
};
|
|
371
|
-
for (const m of messages.value) if (m.status === "unread" && m.category in counts) counts[m.category]++;
|
|
372
|
-
return counts;
|
|
373
|
-
});
|
|
374
|
-
/** 当前分类下的消息列表 */
|
|
375
|
-
const filteredMessages = computed(() => {
|
|
376
|
-
if (activeCategory.value === "all") return messages.value;
|
|
377
|
-
return messages.value.filter((m) => m.category === activeCategory.value);
|
|
378
|
-
});
|
|
379
|
-
/** 是否有更多消息可加载 */
|
|
380
|
-
const hasMore = computed(() => messages.value.length < total.value);
|
|
381
|
-
/** 缓存 key */
|
|
382
|
-
const storageKey = computed(() => props.storageKey ?? DEFAULT_STORAGE_KEY);
|
|
383
|
-
/**
|
|
384
|
-
* 从缓存恢复未读状态
|
|
385
|
-
*/
|
|
386
|
-
function restoreFromCache() {
|
|
387
|
-
const cached = getItem(storageKey.value);
|
|
388
|
-
if (cached?.unreadIds) {
|
|
389
|
-
const idSet = new Set(cached.unreadIds);
|
|
390
|
-
for (const msg of messages.value) if (idSet.has(msg.id)) msg.status = "unread";
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
/** 防抖持久化定时器 */
|
|
394
|
-
let persistTimer = null;
|
|
395
|
-
/**
|
|
396
|
-
* 持久化未读状态到本地缓存(防抖)
|
|
397
|
-
*/
|
|
398
|
-
function persistToCache() {
|
|
399
|
-
if (persistTimer) clearTimeout(persistTimer);
|
|
400
|
-
persistTimer = setTimeout(() => {
|
|
401
|
-
const unreadIds = messages.value.filter((m) => m.status === "unread").map((m) => m.id);
|
|
402
|
-
setItem(storageKey.value, {
|
|
403
|
-
unreadIds,
|
|
404
|
-
lastFetchTime: Date.now()
|
|
405
|
-
});
|
|
406
|
-
persistTimer = null;
|
|
407
|
-
}, PERSIST_DEBOUNCE);
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* 拉取消息列表
|
|
411
|
-
*/
|
|
412
|
-
async function fetchMessages(reset = false) {
|
|
413
|
-
if (reset) page.value = 1;
|
|
414
|
-
loading.value = true;
|
|
415
|
-
try {
|
|
416
|
-
if (props.fetchNotifications) {
|
|
417
|
-
const categoryParam = activeCategory.value === "all" ? void 0 : activeCategory.value;
|
|
418
|
-
const pageSize = props.pageSize ?? DEFAULT_PAGE_SIZE;
|
|
419
|
-
const result = await props.fetchNotifications({
|
|
420
|
-
category: categoryParam,
|
|
421
|
-
page: page.value,
|
|
422
|
-
pageSize
|
|
423
|
-
});
|
|
424
|
-
if (reset) messages.value = result.list;
|
|
425
|
-
else messages.value.push(...result.list);
|
|
426
|
-
total.value = result.total;
|
|
427
|
-
} else loadMockData();
|
|
428
|
-
restoreFromCache();
|
|
429
|
-
} finally {
|
|
430
|
-
loading.value = false;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* 加载模拟数据(全量加载,filteredMessages 负责客户端过滤)
|
|
435
|
-
*/
|
|
436
|
-
function loadMockData() {
|
|
437
|
-
messages.value = MOCK_MESSAGES.map((m) => ({ ...m }));
|
|
438
|
-
total.value = MOCK_MESSAGES.length;
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* 加载更多
|
|
442
|
-
*/
|
|
443
|
-
async function loadMore() {
|
|
444
|
-
if (!hasMore.value || loading.value) return;
|
|
445
|
-
page.value++;
|
|
446
|
-
await fetchMessages();
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* 标记指定消息为已读
|
|
450
|
-
*/
|
|
451
|
-
async function markAsRead(ids) {
|
|
452
|
-
const idSet = new Set(ids);
|
|
453
|
-
for (const msg of messages.value) if (idSet.has(msg.id)) msg.status = "read";
|
|
454
|
-
persistToCache();
|
|
455
|
-
if (props.markAsRead) try {
|
|
456
|
-
await props.markAsRead(ids);
|
|
457
|
-
} catch {
|
|
458
|
-
for (const msg of messages.value) if (idSet.has(msg.id)) msg.status = "unread";
|
|
459
|
-
persistToCache();
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* 标记全部已读
|
|
464
|
-
*/
|
|
465
|
-
async function markAllAsRead(category) {
|
|
466
|
-
const targetMessages = category ? messages.value.filter((m) => m.category === category && m.status === "unread") : messages.value.filter((m) => m.status === "unread");
|
|
467
|
-
for (const msg of targetMessages) msg.status = "read";
|
|
468
|
-
persistToCache();
|
|
469
|
-
if (props.markAllRead) try {
|
|
470
|
-
await props.markAllRead(category);
|
|
471
|
-
} catch {
|
|
472
|
-
for (const msg of targetMessages) msg.status = "unread";
|
|
473
|
-
persistToCache();
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* 删除消息
|
|
478
|
-
*/
|
|
479
|
-
async function deleteMessages(ids) {
|
|
480
|
-
const idSet = new Set(ids);
|
|
481
|
-
const backup = [...messages.value];
|
|
482
|
-
messages.value = messages.value.filter((m) => !idSet.has(m.id));
|
|
483
|
-
total.value = Math.max(0, total.value - ids.length);
|
|
484
|
-
persistToCache();
|
|
485
|
-
if (props.deleteNotification) try {
|
|
486
|
-
await props.deleteNotification(ids);
|
|
487
|
-
} catch {
|
|
488
|
-
messages.value = backup;
|
|
489
|
-
total.value += ids.length;
|
|
490
|
-
persistToCache();
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* 清空消息
|
|
495
|
-
*/
|
|
496
|
-
async function clearMessages(category) {
|
|
497
|
-
const backup = [...messages.value];
|
|
498
|
-
const backupTotal = total.value;
|
|
499
|
-
if (category) messages.value = messages.value.filter((m) => m.category !== category);
|
|
500
|
-
else messages.value = [];
|
|
501
|
-
total.value = messages.value.length;
|
|
502
|
-
persistToCache();
|
|
503
|
-
if (props.clearNotifications) try {
|
|
504
|
-
await props.clearNotifications(category);
|
|
505
|
-
} catch {
|
|
506
|
-
messages.value = backup;
|
|
507
|
-
total.value = backupTotal;
|
|
508
|
-
persistToCache();
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* 处理 WebSocket 推送消息
|
|
513
|
-
*/
|
|
514
|
-
function handleWSMessage(payload) {
|
|
515
|
-
switch (payload.type) {
|
|
516
|
-
case "new_message": {
|
|
517
|
-
const msg = payload.data;
|
|
518
|
-
if (!messages.value.some((m) => m.id === msg.id)) {
|
|
519
|
-
messages.value.unshift(msg);
|
|
520
|
-
total.value++;
|
|
521
|
-
persistToCache();
|
|
522
|
-
showDesktopNotification(msg);
|
|
523
|
-
}
|
|
524
|
-
break;
|
|
525
|
-
}
|
|
526
|
-
case "read_sync": {
|
|
527
|
-
const syncMessages = payload.data;
|
|
528
|
-
const readIds = new Set(syncMessages.map((m) => m.id));
|
|
529
|
-
for (const msg of messages.value) if (readIds.has(msg.id)) msg.status = "read";
|
|
530
|
-
persistToCache();
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
case "count_update": break;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
/** WebSocket 连接状态变更回调 */
|
|
537
|
-
function handleWSStatusChange(s) {
|
|
538
|
-
wsStatus.value = s;
|
|
539
|
-
}
|
|
540
|
-
const { connect: wsConnect, disconnect: wsDisconnect } = useNotificationWS(handleWSMessage, handleWSStatusChange);
|
|
541
|
-
/**
|
|
542
|
-
* 发送桌面通知
|
|
543
|
-
*/
|
|
544
|
-
function showDesktopNotification(msg) {
|
|
545
|
-
if (!props.desktopNotification) return;
|
|
546
|
-
if (!("Notification" in window)) return;
|
|
547
|
-
if (Notification.permission === "granted") createDesktopNotification(msg);
|
|
548
|
-
else if (Notification.permission !== "denied") Notification.requestPermission().then((permission) => {
|
|
549
|
-
if (permission === "granted") createDesktopNotification(msg);
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* 创建桌面通知实例
|
|
554
|
-
*/
|
|
555
|
-
function createDesktopNotification(msg) {
|
|
556
|
-
const n = new Notification(msg.title, {
|
|
557
|
-
body: msg.summary,
|
|
558
|
-
icon: msg.sender?.avatar || "/robot-avatar.png",
|
|
559
|
-
tag: msg.id
|
|
560
|
-
});
|
|
561
|
-
n.addEventListener("click", () => {
|
|
562
|
-
window.focus();
|
|
563
|
-
selectMessage(msg);
|
|
564
|
-
n.close();
|
|
565
|
-
});
|
|
566
|
-
setTimeout(() => n.close(), 5e3);
|
|
567
|
-
}
|
|
568
|
-
let pollingTimer = null;
|
|
569
|
-
/**
|
|
570
|
-
* 启动轮询
|
|
571
|
-
*/
|
|
572
|
-
function startPolling() {
|
|
573
|
-
stopPolling();
|
|
574
|
-
const interval = props.pollingInterval ?? DEFAULT_POLLING_INTERVAL;
|
|
575
|
-
if (interval <= 0) return;
|
|
576
|
-
pollingTimer = setInterval(() => {
|
|
577
|
-
fetchMessages(true);
|
|
578
|
-
}, interval);
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* 停止轮询
|
|
582
|
-
*/
|
|
583
|
-
function stopPolling() {
|
|
584
|
-
if (pollingTimer) {
|
|
585
|
-
clearInterval(pollingTimer);
|
|
586
|
-
pollingTimer = null;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* 选中/查看消息
|
|
591
|
-
*/
|
|
592
|
-
function selectMessage(msg) {
|
|
593
|
-
selectedMessage.value = msg;
|
|
594
|
-
if (msg.status === "unread") markAsRead([msg.id]);
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* 返回列表
|
|
598
|
-
*/
|
|
599
|
-
function clearSelection() {
|
|
600
|
-
selectedMessage.value = null;
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* 切换分类
|
|
604
|
-
*
|
|
605
|
-
* 纯客户端过滤(Mock / 已加载数据)直接切换,
|
|
606
|
-
* API 模式则重新拉取对应分类数据。
|
|
607
|
-
*/
|
|
608
|
-
function switchCategory(category) {
|
|
609
|
-
activeCategory.value = category;
|
|
610
|
-
selectedMessage.value = null;
|
|
611
|
-
if (props.fetchNotifications) fetchMessages(true);
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* 初始化
|
|
615
|
-
*/
|
|
616
|
-
function init() {
|
|
617
|
-
fetchMessages(true);
|
|
618
|
-
startPolling();
|
|
619
|
-
if (props.wsConfig) wsConnect(props.wsConfig);
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* 销毁
|
|
623
|
-
*/
|
|
624
|
-
function destroy() {
|
|
625
|
-
stopPolling();
|
|
626
|
-
wsDisconnect();
|
|
627
|
-
if (persistTimer) {
|
|
628
|
-
clearTimeout(persistTimer);
|
|
629
|
-
persistTimer = null;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
onMounted(init);
|
|
633
|
-
onBeforeUnmount(destroy);
|
|
634
|
-
return {
|
|
635
|
-
messages,
|
|
636
|
-
activeCategory,
|
|
637
|
-
loading,
|
|
638
|
-
total,
|
|
639
|
-
page,
|
|
640
|
-
selectedMessage,
|
|
641
|
-
popoverVisible,
|
|
642
|
-
wsStatus,
|
|
643
|
-
unreadCount,
|
|
644
|
-
unreadByCategory,
|
|
645
|
-
filteredMessages,
|
|
646
|
-
hasMore,
|
|
647
|
-
fetchMessages,
|
|
648
|
-
loadMore,
|
|
649
|
-
markAsRead,
|
|
650
|
-
markAllAsRead,
|
|
651
|
-
deleteMessages,
|
|
652
|
-
clearMessages,
|
|
653
|
-
selectMessage,
|
|
654
|
-
clearSelection,
|
|
655
|
-
switchCategory,
|
|
656
|
-
connectWS: wsConnect,
|
|
657
|
-
disconnectWS: wsDisconnect
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
//#endregion
|
|
662
|
-
//#region src/components/C_NotificationCenter/components/NotificationBadge.vue?vue&type=script&setup=true&lang.ts
|
|
663
|
-
const _hoisted_1$4 = { class: "notification-badge" };
|
|
664
|
-
const _hoisted_2$4 = {
|
|
665
|
-
key: 0,
|
|
666
|
-
class: "notification-badge__count"
|
|
667
|
-
};
|
|
668
|
-
const _hoisted_3$4 = {
|
|
669
|
-
key: 0,
|
|
670
|
-
class: "notification-badge__pulse"
|
|
671
|
-
};
|
|
672
|
-
var NotificationBadge_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
673
|
-
__name: "NotificationBadge",
|
|
674
|
-
props: {
|
|
675
|
-
count: { default: 0 },
|
|
676
|
-
maxCount: { default: DEFAULT_MAX_BADGE_COUNT },
|
|
677
|
-
hasUrgent: {
|
|
678
|
-
type: Boolean,
|
|
679
|
-
default: false
|
|
680
|
-
}
|
|
681
|
-
},
|
|
682
|
-
emits: ["click"],
|
|
683
|
-
setup(__props) {
|
|
684
|
-
const props = __props;
|
|
685
|
-
/** 显示文本 */
|
|
686
|
-
const displayCount = computed(() => props.count > props.maxCount ? `${props.maxCount}+` : String(props.count));
|
|
687
|
-
return (_ctx, _cache) => {
|
|
688
|
-
const _component_NTooltip = NTooltip;
|
|
689
|
-
return openBlock(), createElementBlock("div", _hoisted_1$4, [createVNode(_component_NTooltip, {
|
|
690
|
-
trigger: "hover",
|
|
691
|
-
placement: "bottom"
|
|
692
|
-
}, {
|
|
693
|
-
trigger: withCtx(() => [createElementVNode("div", {
|
|
694
|
-
class: "notification-badge__trigger",
|
|
695
|
-
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click"))
|
|
696
|
-
}, [
|
|
697
|
-
createVNode(C_Icon_default, {
|
|
698
|
-
name: "mdi:bell-outline",
|
|
699
|
-
size: 18,
|
|
700
|
-
class: "notification-badge__icon"
|
|
701
|
-
}),
|
|
702
|
-
createCommentVNode(" 未读角标 "),
|
|
703
|
-
createVNode(Transition, { name: "badge-bounce" }, {
|
|
704
|
-
default: withCtx(() => [_ctx.count > 0 ? (openBlock(), createElementBlock("span", _hoisted_2$4, toDisplayString(displayCount.value), 1)) : createCommentVNode("v-if", true)]),
|
|
705
|
-
_: 1
|
|
706
|
-
}),
|
|
707
|
-
createCommentVNode(" 脉冲动画(有紧急消息时) "),
|
|
708
|
-
_ctx.hasUrgent ? (openBlock(), createElementBlock("span", _hoisted_3$4)) : createCommentVNode("v-if", true)
|
|
709
|
-
])]),
|
|
710
|
-
default: withCtx(() => [createTextVNode(" 消息通知" + toDisplayString(_ctx.count > 0 ? `(${_ctx.count} 条未读)` : ""), 1)]),
|
|
711
|
-
_: 1
|
|
712
|
-
})]);
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
|
-
});
|
|
716
|
-
|
|
717
|
-
//#endregion
|
|
718
|
-
//#region src/components/C_NotificationCenter/components/NotificationBadge.vue
|
|
719
|
-
var NotificationBadge_default = /* @__PURE__ */ export_helper_default(NotificationBadge_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-03c9c8c7"]]);
|
|
720
|
-
|
|
721
|
-
//#endregion
|
|
722
|
-
//#region src/components/C_NotificationCenter/composables/useNotificationFormat.ts
|
|
723
|
-
/** 时间单位阈值 */
|
|
724
|
-
const MINUTE = 6e4;
|
|
725
|
-
const HOUR = 36e5;
|
|
726
|
-
const DAY = 864e5;
|
|
727
|
-
const WEEK = 7 * DAY;
|
|
728
|
-
const MONTH = 30 * DAY;
|
|
729
|
-
const YEAR = 365 * DAY;
|
|
730
|
-
/** 单例缓存 */
|
|
731
|
-
let _instance = null;
|
|
732
|
-
/**
|
|
733
|
-
* 通知时间格式化(单例)
|
|
734
|
-
*
|
|
735
|
-
* 将 ISO 时间戳格式化为人类友好的相对时间描述,
|
|
736
|
-
* 如 "刚刚"、"5分钟前"、"昨天 14:30" 等。
|
|
737
|
-
*/
|
|
738
|
-
function useNotificationFormat() {
|
|
739
|
-
if (!_instance) _instance = createNotificationFormat();
|
|
740
|
-
return _instance;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* 创建格式化工具实例
|
|
744
|
-
*/
|
|
745
|
-
function createNotificationFormat() {
|
|
746
|
-
/**
|
|
747
|
-
* 格式化相对时间
|
|
748
|
-
* @param timestamp ISO 8601 时间字符串
|
|
749
|
-
*/
|
|
750
|
-
function formatRelativeTime(timestamp) {
|
|
751
|
-
const date = new Date(timestamp);
|
|
752
|
-
const diff = Date.now() - date.getTime();
|
|
753
|
-
if (diff < 0) return "刚刚";
|
|
754
|
-
if (diff < MINUTE) return "刚刚";
|
|
755
|
-
if (diff < HOUR) return `${Math.floor(diff / MINUTE)}分钟前`;
|
|
756
|
-
if (diff < DAY) return `${Math.floor(diff / HOUR)}小时前`;
|
|
757
|
-
const today = /* @__PURE__ */ new Date();
|
|
758
|
-
today.setHours(0, 0, 0, 0);
|
|
759
|
-
if (date >= new Date(today.getTime() - DAY) && date < today) return `昨天 ${padTime(date.getHours())}:${padTime(date.getMinutes())}`;
|
|
760
|
-
if (diff < WEEK) return `${Math.floor(diff / DAY)}天前`;
|
|
761
|
-
if (diff < MONTH) return `${Math.floor(diff / WEEK)}周前`;
|
|
762
|
-
if (diff < YEAR) return `${Math.floor(diff / MONTH)}个月前`;
|
|
763
|
-
return formatFullDate(date);
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* 格式化完整日期时间
|
|
767
|
-
* @param date Date 对象
|
|
768
|
-
*/
|
|
769
|
-
function formatFullDate(date) {
|
|
770
|
-
return `${date.getFullYear()}-${padTime(date.getMonth() + 1)}-${padTime(date.getDate())} ${padTime(date.getHours())}:${padTime(date.getMinutes())}`;
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* 补零
|
|
774
|
-
* @param n 数字
|
|
775
|
-
*/
|
|
776
|
-
function padTime(n) {
|
|
777
|
-
return n < 10 ? `0${n}` : String(n);
|
|
778
|
-
}
|
|
779
|
-
return {
|
|
780
|
-
formatRelativeTime,
|
|
781
|
-
formatFullDate
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
//#endregion
|
|
786
|
-
//#region src/components/C_NotificationCenter/components/NotificationItem.vue?vue&type=script&setup=true&lang.ts
|
|
787
|
-
const _hoisted_1$3 = { class: "notification-item__indicator" };
|
|
788
|
-
const _hoisted_2$3 = { class: "notification-item__avatar" };
|
|
789
|
-
const _hoisted_3$3 = { class: "notification-item__body" };
|
|
790
|
-
const _hoisted_4$3 = { class: "notification-item__header" };
|
|
791
|
-
const _hoisted_5$2 = { class: "notification-item__title" };
|
|
792
|
-
const _hoisted_6$2 = { class: "notification-item__summary" };
|
|
793
|
-
const _hoisted_7$2 = { class: "notification-item__meta" };
|
|
794
|
-
const _hoisted_8$2 = { class: "notification-item__time" };
|
|
795
|
-
const _hoisted_9$1 = {
|
|
796
|
-
key: 0,
|
|
797
|
-
class: "notification-item__sender"
|
|
798
|
-
};
|
|
799
|
-
var NotificationItem_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
800
|
-
__name: "NotificationItem",
|
|
801
|
-
props: { message: {} },
|
|
802
|
-
emits: [
|
|
803
|
-
"click",
|
|
804
|
-
"read",
|
|
805
|
-
"delete"
|
|
806
|
-
],
|
|
807
|
-
setup(__props) {
|
|
808
|
-
const props = __props;
|
|
809
|
-
const { formatRelativeTime } = useNotificationFormat();
|
|
810
|
-
/** 分类图标 */
|
|
811
|
-
const categoryIcon = computed(() => CATEGORY_MAP[props.message.category]?.icon ?? "mdi:bell-outline");
|
|
812
|
-
/** 优先级配置 */
|
|
813
|
-
const priorityConfig = computed(() => PRIORITY_MAP[props.message.priority] ?? PRIORITY_MAP.normal);
|
|
814
|
-
/** 格式化时间 */
|
|
815
|
-
const formattedTime = computed(() => formatRelativeTime(props.message.timestamp));
|
|
816
|
-
return (_ctx, _cache) => {
|
|
817
|
-
const _component_NAvatar = NAvatar;
|
|
818
|
-
const _component_NTag = NTag;
|
|
819
|
-
const _component_NTooltip = NTooltip;
|
|
820
|
-
return openBlock(), createElementBlock("div", {
|
|
821
|
-
class: normalizeClass(["notification-item", {
|
|
822
|
-
"notification-item--unread": _ctx.message.status === "unread",
|
|
823
|
-
"notification-item--urgent": _ctx.message.priority === "urgent"
|
|
824
|
-
}]),
|
|
825
|
-
onClick: _cache[3] || (_cache[3] = ($event) => _ctx.$emit("click", _ctx.message))
|
|
826
|
-
}, [
|
|
827
|
-
createCommentVNode(" 未读指示点 "),
|
|
828
|
-
createElementVNode("div", _hoisted_1$3, [_ctx.message.status === "unread" ? (openBlock(), createElementBlock("span", {
|
|
829
|
-
key: 0,
|
|
830
|
-
class: normalizeClass(["notification-item__dot", `notification-item__dot--${_ctx.message.priority}`])
|
|
831
|
-
}, null, 2)) : createCommentVNode("v-if", true)]),
|
|
832
|
-
createCommentVNode(" 头像 "),
|
|
833
|
-
createElementVNode("div", _hoisted_2$3, [_ctx.message.sender?.avatar ? (openBlock(), createBlock(_component_NAvatar, {
|
|
834
|
-
key: 0,
|
|
835
|
-
src: _ctx.message.sender.avatar,
|
|
836
|
-
size: 36,
|
|
837
|
-
round: ""
|
|
838
|
-
}, null, 8, ["src"])) : (openBlock(), createElementBlock("div", {
|
|
839
|
-
key: 1,
|
|
840
|
-
class: normalizeClass(["notification-item__avatar-placeholder", `notification-item__avatar-placeholder--${_ctx.message.category}`])
|
|
841
|
-
}, [createVNode(C_Icon_default, {
|
|
842
|
-
name: categoryIcon.value,
|
|
843
|
-
size: 16
|
|
844
|
-
}, null, 8, ["name"])], 2))]),
|
|
845
|
-
createCommentVNode(" 内容 "),
|
|
846
|
-
createElementVNode("div", _hoisted_3$3, [
|
|
847
|
-
createElementVNode("div", _hoisted_4$3, [createElementVNode("span", _hoisted_5$2, toDisplayString(_ctx.message.title), 1), _ctx.message.priority === "urgent" || _ctx.message.priority === "high" ? (openBlock(), createBlock(_component_NTag, {
|
|
848
|
-
key: 0,
|
|
849
|
-
type: priorityConfig.value.type,
|
|
850
|
-
size: "tiny",
|
|
851
|
-
bordered: false,
|
|
852
|
-
round: ""
|
|
853
|
-
}, {
|
|
854
|
-
default: withCtx(() => [createTextVNode(toDisplayString(priorityConfig.value.label), 1)]),
|
|
855
|
-
_: 1
|
|
856
|
-
}, 8, ["type"])) : createCommentVNode("v-if", true)]),
|
|
857
|
-
createElementVNode("div", _hoisted_6$2, toDisplayString(_ctx.message.summary), 1),
|
|
858
|
-
createElementVNode("div", _hoisted_7$2, [createElementVNode("span", _hoisted_8$2, toDisplayString(formattedTime.value), 1), _ctx.message.sender?.name ? (openBlock(), createElementBlock("span", _hoisted_9$1, toDisplayString(_ctx.message.sender.name), 1)) : createCommentVNode("v-if", true)])
|
|
859
|
-
]),
|
|
860
|
-
createCommentVNode(" 操作区 "),
|
|
861
|
-
createElementVNode("div", {
|
|
862
|
-
class: "notification-item__actions",
|
|
863
|
-
onClick: _cache[2] || (_cache[2] = withModifiers(() => {}, ["stop"]))
|
|
864
|
-
}, [_ctx.message.status === "unread" ? (openBlock(), createBlock(_component_NTooltip, {
|
|
865
|
-
key: 0,
|
|
866
|
-
trigger: "hover",
|
|
867
|
-
placement: "top"
|
|
868
|
-
}, {
|
|
869
|
-
trigger: withCtx(() => [createElementVNode("span", {
|
|
870
|
-
class: "notification-item__action",
|
|
871
|
-
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("read", _ctx.message.id))
|
|
872
|
-
}, [createVNode(C_Icon_default, {
|
|
873
|
-
name: "mdi:check",
|
|
874
|
-
size: 16
|
|
875
|
-
})])]),
|
|
876
|
-
default: withCtx(() => [_cache[4] || (_cache[4] = createTextVNode(" 标记已读 ", -1))]),
|
|
877
|
-
_: 1,
|
|
878
|
-
__: [4]
|
|
879
|
-
})) : createCommentVNode("v-if", true), createVNode(_component_NTooltip, {
|
|
880
|
-
trigger: "hover",
|
|
881
|
-
placement: "top"
|
|
882
|
-
}, {
|
|
883
|
-
trigger: withCtx(() => [createElementVNode("span", {
|
|
884
|
-
class: "notification-item__action",
|
|
885
|
-
onClick: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("delete", _ctx.message.id))
|
|
886
|
-
}, [createVNode(C_Icon_default, {
|
|
887
|
-
name: "mdi:delete-outline",
|
|
888
|
-
size: 16
|
|
889
|
-
})])]),
|
|
890
|
-
default: withCtx(() => [_cache[5] || (_cache[5] = createTextVNode(" 删除 ", -1))]),
|
|
891
|
-
_: 1,
|
|
892
|
-
__: [5]
|
|
893
|
-
})])
|
|
894
|
-
], 2);
|
|
895
|
-
};
|
|
896
|
-
}
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
//#endregion
|
|
900
|
-
//#region src/components/C_NotificationCenter/components/NotificationItem.vue
|
|
901
|
-
var NotificationItem_default = /* @__PURE__ */ export_helper_default(NotificationItem_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-30bf7ddc"]]);
|
|
902
|
-
|
|
903
|
-
//#endregion
|
|
904
|
-
//#region src/components/C_NotificationCenter/components/NotificationList.vue?vue&type=script&setup=true&lang.ts
|
|
905
|
-
const _hoisted_1$2 = { class: "notification-list" };
|
|
906
|
-
const _hoisted_2$2 = { class: "notification-list__tabs" };
|
|
907
|
-
const _hoisted_3$2 = ["onClick"];
|
|
908
|
-
const _hoisted_4$2 = {
|
|
909
|
-
key: 0,
|
|
910
|
-
class: "notification-list__tab-count"
|
|
911
|
-
};
|
|
912
|
-
const _hoisted_5$1 = {
|
|
913
|
-
key: 0,
|
|
914
|
-
class: "notification-list__toolbar"
|
|
915
|
-
};
|
|
916
|
-
const _hoisted_6$1 = { class: "notification-list__skeleton-text" };
|
|
917
|
-
const _hoisted_7$1 = { class: "notification-list__items" };
|
|
918
|
-
const _hoisted_8$1 = { class: "notification-list__empty" };
|
|
919
|
-
var NotificationList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
920
|
-
__name: "NotificationList",
|
|
921
|
-
props: {
|
|
922
|
-
messages: {},
|
|
923
|
-
activeCategory: {},
|
|
924
|
-
unreadByCategory: {},
|
|
925
|
-
unreadCount: {},
|
|
926
|
-
loading: { type: Boolean },
|
|
927
|
-
hasMore: { type: Boolean },
|
|
928
|
-
scrollHeight: { default: 420 }
|
|
929
|
-
},
|
|
930
|
-
emits: [
|
|
931
|
-
"switchCategory",
|
|
932
|
-
"itemClick",
|
|
933
|
-
"read",
|
|
934
|
-
"delete",
|
|
935
|
-
"markAllRead",
|
|
936
|
-
"clear",
|
|
937
|
-
"loadMore"
|
|
938
|
-
],
|
|
939
|
-
setup(__props) {
|
|
940
|
-
const props = __props;
|
|
941
|
-
/** 当前分类下的未读数 */
|
|
942
|
-
const currentUnread = computed(() => {
|
|
943
|
-
if (props.activeCategory === "all") return props.unreadCount;
|
|
944
|
-
return props.unreadByCategory[props.activeCategory] ?? 0;
|
|
945
|
-
});
|
|
946
|
-
/** 获取 Tab 的未读数 */
|
|
947
|
-
function getTabCount(key) {
|
|
948
|
-
if (key === "all") return props.unreadCount;
|
|
949
|
-
return props.unreadByCategory[key] ?? 0;
|
|
950
|
-
}
|
|
951
|
-
return (_ctx, _cache) => {
|
|
952
|
-
const _component_NButton = NButton;
|
|
953
|
-
const _component_NSkeleton = NSkeleton;
|
|
954
|
-
const _component_NSpin = NSpin;
|
|
955
|
-
const _component_NScrollbar = NScrollbar;
|
|
956
|
-
return openBlock(), createElementBlock("div", _hoisted_1$2, [
|
|
957
|
-
createCommentVNode(" 分类 Tab "),
|
|
958
|
-
createElementVNode("div", _hoisted_2$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(CATEGORY_TABS), (tab) => {
|
|
959
|
-
return openBlock(), createElementBlock("div", {
|
|
960
|
-
key: tab.key,
|
|
961
|
-
class: normalizeClass(["notification-list__tab", { "notification-list__tab--active": _ctx.activeCategory === tab.key }]),
|
|
962
|
-
onClick: ($event) => _ctx.$emit("switchCategory", tab.key)
|
|
963
|
-
}, [createElementVNode("span", null, toDisplayString(tab.label), 1), getTabCount(tab.key) > 0 ? (openBlock(), createElementBlock("span", _hoisted_4$2, toDisplayString(getTabCount(tab.key)), 1)) : createCommentVNode("v-if", true)], 10, _hoisted_3$2);
|
|
964
|
-
}), 128))]),
|
|
965
|
-
createCommentVNode(" 操作栏 "),
|
|
966
|
-
_ctx.messages.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_5$1, [createVNode(_component_NButton, {
|
|
967
|
-
text: "",
|
|
968
|
-
size: "tiny",
|
|
969
|
-
disabled: currentUnread.value === 0,
|
|
970
|
-
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("markAllRead"))
|
|
971
|
-
}, {
|
|
972
|
-
icon: withCtx(() => [createVNode(C_Icon_default, {
|
|
973
|
-
name: "mdi:check-all",
|
|
974
|
-
size: 14
|
|
975
|
-
})]),
|
|
976
|
-
default: withCtx(() => [_cache[6] || (_cache[6] = createTextVNode(" 全部已读 ", -1))]),
|
|
977
|
-
_: 1,
|
|
978
|
-
__: [6]
|
|
979
|
-
}, 8, ["disabled"]), createVNode(_component_NButton, {
|
|
980
|
-
text: "",
|
|
981
|
-
size: "tiny",
|
|
982
|
-
onClick: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("clear"))
|
|
983
|
-
}, {
|
|
984
|
-
icon: withCtx(() => [createVNode(C_Icon_default, {
|
|
985
|
-
name: "mdi:delete-sweep-outline",
|
|
986
|
-
size: 14
|
|
987
|
-
})]),
|
|
988
|
-
default: withCtx(() => [_cache[7] || (_cache[7] = createTextVNode(" 清空 ", -1))]),
|
|
989
|
-
_: 1,
|
|
990
|
-
__: [7]
|
|
991
|
-
})])) : createCommentVNode("v-if", true),
|
|
992
|
-
createCommentVNode(" 消息列表 "),
|
|
993
|
-
createVNode(_component_NScrollbar, {
|
|
994
|
-
class: "notification-list__scroll",
|
|
995
|
-
style: normalizeStyle({ maxHeight: `${_ctx.scrollHeight}px` })
|
|
996
|
-
}, {
|
|
997
|
-
default: withCtx(() => [_ctx.loading && _ctx.messages.length === 0 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createCommentVNode(" 骨架屏 "), (openBlock(), createElementBlock(Fragment, null, renderList(4, (i) => {
|
|
998
|
-
return createElementVNode("div", {
|
|
999
|
-
key: i,
|
|
1000
|
-
class: "notification-list__skeleton"
|
|
1001
|
-
}, [createVNode(_component_NSkeleton, {
|
|
1002
|
-
circle: "",
|
|
1003
|
-
width: 36,
|
|
1004
|
-
height: 36
|
|
1005
|
-
}), createElementVNode("div", _hoisted_6$1, [
|
|
1006
|
-
createVNode(_component_NSkeleton, {
|
|
1007
|
-
text: "",
|
|
1008
|
-
width: "60%",
|
|
1009
|
-
height: 14
|
|
1010
|
-
}),
|
|
1011
|
-
createVNode(_component_NSkeleton, {
|
|
1012
|
-
text: "",
|
|
1013
|
-
width: "90%",
|
|
1014
|
-
height: 12
|
|
1015
|
-
}),
|
|
1016
|
-
createVNode(_component_NSkeleton, {
|
|
1017
|
-
text: "",
|
|
1018
|
-
width: "40%",
|
|
1019
|
-
height: 10
|
|
1020
|
-
})
|
|
1021
|
-
])]);
|
|
1022
|
-
}), 64))], 64)) : _ctx.messages.length > 0 ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
1023
|
-
createElementVNode("div", _hoisted_7$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.messages, (msg) => {
|
|
1024
|
-
return openBlock(), createBlock(NotificationItem_default, {
|
|
1025
|
-
key: msg.id,
|
|
1026
|
-
message: msg,
|
|
1027
|
-
onClick: _cache[2] || (_cache[2] = ($event) => _ctx.$emit("itemClick", $event)),
|
|
1028
|
-
onRead: _cache[3] || (_cache[3] = ($event) => _ctx.$emit("read", $event)),
|
|
1029
|
-
onDelete: _cache[4] || (_cache[4] = ($event) => _ctx.$emit("delete", $event))
|
|
1030
|
-
}, null, 8, ["message"]);
|
|
1031
|
-
}), 128))]),
|
|
1032
|
-
createCommentVNode(" 加载更多 "),
|
|
1033
|
-
_ctx.hasMore ? (openBlock(), createElementBlock("div", {
|
|
1034
|
-
key: 0,
|
|
1035
|
-
class: "notification-list__load-more",
|
|
1036
|
-
onClick: _cache[5] || (_cache[5] = ($event) => _ctx.$emit("loadMore"))
|
|
1037
|
-
}, [_ctx.loading ? (openBlock(), createBlock(_component_NSpin, {
|
|
1038
|
-
key: 0,
|
|
1039
|
-
size: 14
|
|
1040
|
-
})) : createCommentVNode("v-if", true), createElementVNode("span", null, toDisplayString(_ctx.loading ? "加载中..." : "加载更多"), 1)])) : createCommentVNode("v-if", true)
|
|
1041
|
-
], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [createCommentVNode(" 空状态 "), createElementVNode("div", _hoisted_8$1, [createVNode(C_Icon_default, {
|
|
1042
|
-
name: "mdi:bell-off-outline",
|
|
1043
|
-
size: 48,
|
|
1044
|
-
class: "notification-list__empty-icon"
|
|
1045
|
-
}), _cache[8] || (_cache[8] = createElementVNode("span", { class: "notification-list__empty-text" }, "暂无消息", -1))])], 2112))]),
|
|
1046
|
-
_: 1
|
|
1047
|
-
}, 8, ["style"])
|
|
1048
|
-
]);
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
});
|
|
1052
|
-
|
|
1053
|
-
//#endregion
|
|
1054
|
-
//#region src/components/C_NotificationCenter/components/NotificationList.vue
|
|
1055
|
-
var NotificationList_default = /* @__PURE__ */ export_helper_default(NotificationList_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-3db0c5bf"]]);
|
|
1056
|
-
|
|
1057
|
-
//#endregion
|
|
1058
|
-
//#region src/components/C_NotificationCenter/components/NotificationDetail.vue?vue&type=script&setup=true&lang.ts
|
|
1059
|
-
const _hoisted_1$1 = { class: "notification-detail" };
|
|
1060
|
-
const _hoisted_2$1 = { class: "notification-detail__back" };
|
|
1061
|
-
const _hoisted_3$1 = { class: "notification-detail__header" };
|
|
1062
|
-
const _hoisted_4$1 = { class: "notification-detail__title" };
|
|
1063
|
-
const _hoisted_5 = { class: "notification-detail__meta" };
|
|
1064
|
-
const _hoisted_6 = { class: "notification-detail__time" };
|
|
1065
|
-
const _hoisted_7 = {
|
|
1066
|
-
key: 0,
|
|
1067
|
-
class: "notification-detail__sender"
|
|
1068
|
-
};
|
|
1069
|
-
const _hoisted_8 = ["innerHTML"];
|
|
1070
|
-
const _hoisted_9 = {
|
|
1071
|
-
key: 1,
|
|
1072
|
-
class: "notification-detail__body"
|
|
1073
|
-
};
|
|
1074
|
-
const _hoisted_10 = {
|
|
1075
|
-
key: 0,
|
|
1076
|
-
class: "notification-detail__footer"
|
|
1077
|
-
};
|
|
1078
|
-
var NotificationDetail_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
1079
|
-
__name: "NotificationDetail",
|
|
1080
|
-
props: {
|
|
1081
|
-
message: {},
|
|
1082
|
-
scrollHeight: { default: 320 }
|
|
1083
|
-
},
|
|
1084
|
-
emits: [
|
|
1085
|
-
"back",
|
|
1086
|
-
"action",
|
|
1087
|
-
"navigate"
|
|
1088
|
-
],
|
|
1089
|
-
setup(__props, { emit: __emit }) {
|
|
1090
|
-
const props = __props;
|
|
1091
|
-
const emit = __emit;
|
|
1092
|
-
const { formatRelativeTime } = useNotificationFormat();
|
|
1093
|
-
/** 分类标签 */
|
|
1094
|
-
const categoryTag = computed(() => CATEGORY_MAP[props.message.category] ?? CATEGORY_MAP.system);
|
|
1095
|
-
/** 优先级标签 */
|
|
1096
|
-
const priorityTag = computed(() => PRIORITY_MAP[props.message.priority] ?? PRIORITY_MAP.normal);
|
|
1097
|
-
/** 格式化时间 */
|
|
1098
|
-
const formattedTime = computed(() => formatRelativeTime(props.message.timestamp));
|
|
1099
|
-
/** 处理操作按钮点击 */
|
|
1100
|
-
function handleAction() {
|
|
1101
|
-
const url = props.message.actionUrl;
|
|
1102
|
-
if (!url) return;
|
|
1103
|
-
emit("action", url);
|
|
1104
|
-
if (url.startsWith("http")) window.open(url, "_blank");
|
|
1105
|
-
else emit("navigate", url);
|
|
1106
|
-
}
|
|
1107
|
-
return (_ctx, _cache) => {
|
|
1108
|
-
const _component_NButton = NButton;
|
|
1109
|
-
const _component_NTag = NTag;
|
|
1110
|
-
const _component_NAvatar = NAvatar;
|
|
1111
|
-
const _component_NScrollbar = NScrollbar;
|
|
1112
|
-
return openBlock(), createElementBlock("div", _hoisted_1$1, [
|
|
1113
|
-
createCommentVNode(" 返回栏 "),
|
|
1114
|
-
createElementVNode("div", _hoisted_2$1, [createVNode(_component_NButton, {
|
|
1115
|
-
text: "",
|
|
1116
|
-
size: "small",
|
|
1117
|
-
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("back"))
|
|
1118
|
-
}, {
|
|
1119
|
-
icon: withCtx(() => [createVNode(C_Icon_default, {
|
|
1120
|
-
name: "mdi:arrow-left",
|
|
1121
|
-
size: 16
|
|
1122
|
-
})]),
|
|
1123
|
-
default: withCtx(() => [_cache[1] || (_cache[1] = createTextVNode(" 返回列表 ", -1))]),
|
|
1124
|
-
_: 1,
|
|
1125
|
-
__: [1]
|
|
1126
|
-
})]),
|
|
1127
|
-
createCommentVNode(" 消息头部 "),
|
|
1128
|
-
createElementVNode("div", _hoisted_3$1, [
|
|
1129
|
-
createElementVNode("h3", _hoisted_4$1, toDisplayString(_ctx.message.title), 1),
|
|
1130
|
-
createElementVNode("div", _hoisted_5, [
|
|
1131
|
-
createVNode(_component_NTag, {
|
|
1132
|
-
type: categoryTag.value.color,
|
|
1133
|
-
size: "tiny",
|
|
1134
|
-
bordered: false,
|
|
1135
|
-
round: ""
|
|
1136
|
-
}, {
|
|
1137
|
-
icon: withCtx(() => [createVNode(C_Icon_default, {
|
|
1138
|
-
name: categoryTag.value.icon,
|
|
1139
|
-
size: 12
|
|
1140
|
-
}, null, 8, ["name"])]),
|
|
1141
|
-
default: withCtx(() => [createTextVNode(" " + toDisplayString(categoryTag.value.label), 1)]),
|
|
1142
|
-
_: 1
|
|
1143
|
-
}, 8, ["type"]),
|
|
1144
|
-
_ctx.message.priority === "urgent" || _ctx.message.priority === "high" ? (openBlock(), createBlock(_component_NTag, {
|
|
1145
|
-
key: 0,
|
|
1146
|
-
type: priorityTag.value.type,
|
|
1147
|
-
size: "tiny",
|
|
1148
|
-
bordered: false,
|
|
1149
|
-
round: ""
|
|
1150
|
-
}, {
|
|
1151
|
-
default: withCtx(() => [createTextVNode(toDisplayString(priorityTag.value.label), 1)]),
|
|
1152
|
-
_: 1
|
|
1153
|
-
}, 8, ["type"])) : createCommentVNode("v-if", true),
|
|
1154
|
-
createElementVNode("span", _hoisted_6, toDisplayString(formattedTime.value), 1)
|
|
1155
|
-
]),
|
|
1156
|
-
_ctx.message.sender ? (openBlock(), createElementBlock("div", _hoisted_7, [_ctx.message.sender.avatar ? (openBlock(), createBlock(_component_NAvatar, {
|
|
1157
|
-
key: 0,
|
|
1158
|
-
src: _ctx.message.sender.avatar,
|
|
1159
|
-
size: 20,
|
|
1160
|
-
round: ""
|
|
1161
|
-
}, null, 8, ["src"])) : createCommentVNode("v-if", true), createElementVNode("span", null, toDisplayString(_ctx.message.sender.name), 1)])) : createCommentVNode("v-if", true)
|
|
1162
|
-
]),
|
|
1163
|
-
createCommentVNode(" 消息内容 "),
|
|
1164
|
-
createVNode(_component_NScrollbar, {
|
|
1165
|
-
class: "notification-detail__content",
|
|
1166
|
-
style: normalizeStyle({ maxHeight: `${_ctx.scrollHeight}px` })
|
|
1167
|
-
}, {
|
|
1168
|
-
default: withCtx(() => [_ctx.message.content ? (openBlock(), createElementBlock("div", {
|
|
1169
|
-
key: 0,
|
|
1170
|
-
class: "notification-detail__body",
|
|
1171
|
-
innerHTML: _ctx.message.content
|
|
1172
|
-
}, null, 8, _hoisted_8)) : (openBlock(), createElementBlock("div", _hoisted_9, toDisplayString(_ctx.message.summary), 1))]),
|
|
1173
|
-
_: 1
|
|
1174
|
-
}, 8, ["style"]),
|
|
1175
|
-
createCommentVNode(" 操作区 "),
|
|
1176
|
-
_ctx.message.actionUrl ? (openBlock(), createElementBlock("div", _hoisted_10, [createVNode(_component_NButton, {
|
|
1177
|
-
type: "primary",
|
|
1178
|
-
size: "small",
|
|
1179
|
-
onClick: handleAction
|
|
1180
|
-
}, {
|
|
1181
|
-
icon: withCtx(() => [createVNode(C_Icon_default, {
|
|
1182
|
-
name: "mdi:arrow-right",
|
|
1183
|
-
size: 16
|
|
1184
|
-
})]),
|
|
1185
|
-
default: withCtx(() => [createTextVNode(toDisplayString(_ctx.message.actionText || "查看详情") + " ", 1)]),
|
|
1186
|
-
_: 1
|
|
1187
|
-
})])) : createCommentVNode("v-if", true)
|
|
1188
|
-
]);
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
});
|
|
1192
|
-
|
|
1193
|
-
//#endregion
|
|
1194
|
-
//#region src/components/C_NotificationCenter/components/NotificationDetail.vue
|
|
1195
|
-
var NotificationDetail_default = /* @__PURE__ */ export_helper_default(NotificationDetail_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-b10b0b8e"]]);
|
|
1196
|
-
|
|
1197
|
-
//#endregion
|
|
1198
|
-
//#region src/components/C_NotificationCenter/index.vue?vue&type=script&setup=true&lang.ts
|
|
1199
|
-
const _hoisted_1 = { class: "c-notification-center" };
|
|
1200
|
-
const _hoisted_2 = { class: "c-notification-center__panel" };
|
|
1201
|
-
const _hoisted_3 = { class: "c-notification-center__header" };
|
|
1202
|
-
const _hoisted_4 = { class: "c-notification-center__header-extra" };
|
|
1203
|
-
var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
1204
|
-
name: "C_NotificationCenter",
|
|
1205
|
-
__name: "index",
|
|
1206
|
-
props: {
|
|
1207
|
-
fetchNotifications: {},
|
|
1208
|
-
markAsRead: {},
|
|
1209
|
-
markAllRead: {},
|
|
1210
|
-
deleteNotification: {},
|
|
1211
|
-
clearNotifications: {},
|
|
1212
|
-
wsConfig: {},
|
|
1213
|
-
desktopNotification: {
|
|
1214
|
-
type: Boolean,
|
|
1215
|
-
default: false
|
|
1216
|
-
},
|
|
1217
|
-
maxBadgeCount: { default: 99 },
|
|
1218
|
-
pollingInterval: { default: 6e4 },
|
|
1219
|
-
pageSize: { default: 20 },
|
|
1220
|
-
storageKey: { default: "notification_center" }
|
|
1221
|
-
},
|
|
1222
|
-
emits: [
|
|
1223
|
-
"itemClick",
|
|
1224
|
-
"read",
|
|
1225
|
-
"allRead",
|
|
1226
|
-
"delete",
|
|
1227
|
-
"unreadChange",
|
|
1228
|
-
"wsStatusChange",
|
|
1229
|
-
"newMessage",
|
|
1230
|
-
"navigate"
|
|
1231
|
-
],
|
|
1232
|
-
setup(__props, { expose: __expose, emit: __emit }) {
|
|
1233
|
-
const props = __props;
|
|
1234
|
-
const emit = __emit;
|
|
1235
|
-
const core = useNotificationCore(props);
|
|
1236
|
-
/** 是否有紧急未读消息 */
|
|
1237
|
-
const hasUrgentMessage = computed(() => core.messages.value.some((m) => m.status === "unread" && m.priority === "urgent"));
|
|
1238
|
-
/** WebSocket 状态文本 */
|
|
1239
|
-
const wsStatusText = computed(() => {
|
|
1240
|
-
return {
|
|
1241
|
-
connected: "已连接",
|
|
1242
|
-
connecting: "连接中...",
|
|
1243
|
-
disconnected: "未连接",
|
|
1244
|
-
reconnecting: "重连中..."
|
|
1245
|
-
}[core.wsStatus.value] ?? "未知";
|
|
1246
|
-
});
|
|
1247
|
-
watch(() => core.unreadCount.value, (count) => {
|
|
1248
|
-
emit("unreadChange", count);
|
|
1249
|
-
});
|
|
1250
|
-
/** 角标点击 */
|
|
1251
|
-
function handleBadgeClick() {
|
|
1252
|
-
core.popoverVisible.value = !core.popoverVisible.value;
|
|
1253
|
-
}
|
|
1254
|
-
/** 点击消息 */
|
|
1255
|
-
function handleItemClick(message) {
|
|
1256
|
-
core.selectMessage(message);
|
|
1257
|
-
emit("itemClick", message);
|
|
1258
|
-
}
|
|
1259
|
-
/** 标记已读 */
|
|
1260
|
-
function handleRead(id) {
|
|
1261
|
-
core.markAsRead([id]);
|
|
1262
|
-
emit("read", [id]);
|
|
1263
|
-
}
|
|
1264
|
-
/** 删除消息 */
|
|
1265
|
-
function handleDelete(id) {
|
|
1266
|
-
core.deleteMessages([id]);
|
|
1267
|
-
emit("delete", [id]);
|
|
1268
|
-
}
|
|
1269
|
-
/** 全部已读 */
|
|
1270
|
-
function handleMarkAllRead() {
|
|
1271
|
-
const category = core.activeCategory.value === "all" ? void 0 : core.activeCategory.value;
|
|
1272
|
-
core.markAllAsRead(category);
|
|
1273
|
-
emit("allRead", category);
|
|
1274
|
-
}
|
|
1275
|
-
/** 清空 */
|
|
1276
|
-
function handleClear() {
|
|
1277
|
-
const category = core.activeCategory.value === "all" ? void 0 : core.activeCategory.value;
|
|
1278
|
-
core.clearMessages(category);
|
|
1279
|
-
}
|
|
1280
|
-
/** 操作链接跳转 */
|
|
1281
|
-
function handleAction() {
|
|
1282
|
-
core.popoverVisible.value = false;
|
|
1283
|
-
}
|
|
1284
|
-
/** Popover 关闭后重置详情 */
|
|
1285
|
-
function handlePopoverClose() {
|
|
1286
|
-
core.clearSelection();
|
|
1287
|
-
}
|
|
1288
|
-
__expose({
|
|
1289
|
-
refresh: () => core.fetchMessages(true),
|
|
1290
|
-
connectWS: () => {
|
|
1291
|
-
if (props.wsConfig) core.connectWS(props.wsConfig);
|
|
1292
|
-
},
|
|
1293
|
-
disconnectWS: core.disconnectWS,
|
|
1294
|
-
getUnreadCount: () => core.unreadCount.value,
|
|
1295
|
-
getMessages: () => core.messages.value,
|
|
1296
|
-
markRead: (ids) => core.markAsRead(ids),
|
|
1297
|
-
markAllAsRead: (category) => core.markAllAsRead(category)
|
|
1298
|
-
});
|
|
1299
|
-
return (_ctx, _cache) => {
|
|
1300
|
-
const _component_NTooltip = NTooltip;
|
|
1301
|
-
const _component_NPopover = NPopover;
|
|
1302
|
-
return openBlock(), createElementBlock("div", _hoisted_1, [createVNode(_component_NPopover, {
|
|
1303
|
-
show: unref(core).popoverVisible.value,
|
|
1304
|
-
"onUpdate:show": _cache[1] || (_cache[1] = ($event) => unref(core).popoverVisible.value = $event),
|
|
1305
|
-
width: 420,
|
|
1306
|
-
trigger: "click",
|
|
1307
|
-
placement: "bottom-end",
|
|
1308
|
-
"show-arrow": false,
|
|
1309
|
-
"content-class": "c-notification-center__popover",
|
|
1310
|
-
onAfterLeave: handlePopoverClose
|
|
1311
|
-
}, {
|
|
1312
|
-
trigger: withCtx(() => [createVNode(NotificationBadge_default, {
|
|
1313
|
-
count: unref(core).unreadCount.value,
|
|
1314
|
-
"max-count": props.maxBadgeCount,
|
|
1315
|
-
"has-urgent": hasUrgentMessage.value,
|
|
1316
|
-
onClick: handleBadgeClick
|
|
1317
|
-
}, null, 8, [
|
|
1318
|
-
"count",
|
|
1319
|
-
"max-count",
|
|
1320
|
-
"has-urgent"
|
|
1321
|
-
])]),
|
|
1322
|
-
default: withCtx(() => [createElementVNode("div", _hoisted_2, [
|
|
1323
|
-
createCommentVNode(" 头部标题 "),
|
|
1324
|
-
createElementVNode("div", _hoisted_3, [_cache[2] || (_cache[2] = createElementVNode("span", { class: "c-notification-center__title" }, "消息中心", -1)), createElementVNode("div", _hoisted_4, [createCommentVNode(" WebSocket 连接状态 "), props.wsConfig ? (openBlock(), createBlock(_component_NTooltip, {
|
|
1325
|
-
key: 0,
|
|
1326
|
-
trigger: "hover",
|
|
1327
|
-
placement: "top"
|
|
1328
|
-
}, {
|
|
1329
|
-
trigger: withCtx(() => [createElementVNode("span", { class: normalizeClass(["c-notification-center__ws-dot", `c-notification-center__ws-dot--${unref(core).wsStatus.value}`]) }, null, 2)]),
|
|
1330
|
-
default: withCtx(() => [createTextVNode(" " + toDisplayString(wsStatusText.value), 1)]),
|
|
1331
|
-
_: 1
|
|
1332
|
-
})) : createCommentVNode("v-if", true)])]),
|
|
1333
|
-
createCommentVNode(" 列表 / 详情切换 "),
|
|
1334
|
-
createVNode(Transition, {
|
|
1335
|
-
name: "slide-fade",
|
|
1336
|
-
mode: "out-in"
|
|
1337
|
-
}, {
|
|
1338
|
-
default: withCtx(() => [unref(core).selectedMessage.value ? (openBlock(), createBlock(NotificationDetail_default, {
|
|
1339
|
-
key: unref(core).selectedMessage.value.id,
|
|
1340
|
-
message: unref(core).selectedMessage.value,
|
|
1341
|
-
onBack: unref(core).clearSelection,
|
|
1342
|
-
onAction: handleAction,
|
|
1343
|
-
onNavigate: _cache[0] || (_cache[0] = (url) => emit("navigate", url))
|
|
1344
|
-
}, null, 8, ["message", "onBack"])) : (openBlock(), createBlock(NotificationList_default, {
|
|
1345
|
-
key: 1,
|
|
1346
|
-
messages: unref(core).filteredMessages.value,
|
|
1347
|
-
"active-category": unref(core).activeCategory.value,
|
|
1348
|
-
"unread-by-category": unref(core).unreadByCategory.value,
|
|
1349
|
-
"unread-count": unref(core).unreadCount.value,
|
|
1350
|
-
loading: unref(core).loading.value,
|
|
1351
|
-
"has-more": unref(core).hasMore.value,
|
|
1352
|
-
onSwitchCategory: unref(core).switchCategory,
|
|
1353
|
-
onItemClick: handleItemClick,
|
|
1354
|
-
onRead: handleRead,
|
|
1355
|
-
onDelete: handleDelete,
|
|
1356
|
-
onMarkAllRead: handleMarkAllRead,
|
|
1357
|
-
onClear: handleClear,
|
|
1358
|
-
onLoadMore: unref(core).loadMore
|
|
1359
|
-
}, null, 8, [
|
|
1360
|
-
"messages",
|
|
1361
|
-
"active-category",
|
|
1362
|
-
"unread-by-category",
|
|
1363
|
-
"unread-count",
|
|
1364
|
-
"loading",
|
|
1365
|
-
"has-more",
|
|
1366
|
-
"onSwitchCategory",
|
|
1367
|
-
"onLoadMore"
|
|
1368
|
-
]))]),
|
|
1369
|
-
_: 1
|
|
1370
|
-
})
|
|
1371
|
-
])]),
|
|
1372
|
-
_: 1
|
|
1373
|
-
}, 8, ["show"])]);
|
|
1374
|
-
};
|
|
1375
|
-
}
|
|
1376
|
-
});
|
|
1377
|
-
|
|
1378
|
-
//#endregion
|
|
1379
|
-
//#region src/components/C_NotificationCenter/index.vue
|
|
1380
|
-
var C_NotificationCenter_default = /* @__PURE__ */ export_helper_default(index_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-a60d6896"]]);
|
|
1381
|
-
|
|
1382
|
-
//#endregion
|
|
1383
|
-
export { CATEGORY_MAP as a, DEFAULT_PAGE_SIZE as c, DEFAULT_WS_HEARTBEAT_INTERVAL as d, DEFAULT_WS_HEARTBEAT_MESSAGE as f, PRIORITY_MAP as g, MOCK_MESSAGES as h, useNotificationWS as i, DEFAULT_POLLING_INTERVAL as l, DEFAULT_WS_RECONNECT_INTERVAL as m, useNotificationFormat as n, CATEGORY_TABS as o, DEFAULT_WS_MAX_RECONNECT as p, useNotificationCore as r, DEFAULT_MAX_BADGE_COUNT as s, C_NotificationCenter_default as t, DEFAULT_STORAGE_KEY as u };
|
|
1
|
+
import{t as e}from"./C_Icon2.js";import{t}from"./export-helper.js";import{i as n,t as r}from"./storage.js";import{NAvatar as i,NButton as a,NPopover as o,NScrollbar as s,NSkeleton as c,NSpin as l,NTag as u,NTooltip as d}from"naive-ui";import{Fragment as f,Transition as p,computed as m,createBlock as h,createCommentVNode as g,createElementBlock as _,createElementVNode as v,createTextVNode as y,createVNode as b,defineComponent as x,normalizeClass as S,normalizeStyle as C,onBeforeUnmount as w,onMounted as T,openBlock as E,readonly as D,ref as O,renderList as k,toDisplayString as A,unref as j,watch as M,withCtx as N,withModifiers as P}from"vue";const F=99,I=20,ee=6e4,te=`notification_center`,L=3e3,R=5,z=3e4,B=`ping`,V={system:{label:`系统通知`,icon:`mdi:cog-outline`,color:`info`},business:{label:`业务消息`,icon:`mdi:briefcase-outline`,color:`success`},alarm:{label:`告警预警`,icon:`mdi:alert-outline`,color:`warning`}},H=[{key:`all`,label:`全部`},{key:`system`,label:`系统通知`},{key:`business`,label:`业务消息`},{key:`alarm`,label:`告警预警`}],U={low:{label:`低`,type:`default`},normal:{label:`普通`,type:`info`},high:{label:`重要`,type:`warning`},urgent:{label:`紧急`,type:`error`}},W=[{id:`msg-001`,title:`系统维护通知`,summary:`系统将于今晚 22:00-23:00 进行例行维护升级,届时部分功能可能暂时不可用。`,content:`<p>尊敬的用户:</p><p>为了提升系统性能和稳定性,我们计划于 <strong>2026年2月27日 22:00-23:00</strong> 对系统进行例行维护升级。</p><p>维护期间,以下功能可能暂时不可用:</p><ul><li>报表导出</li><li>数据同步</li><li>定时任务</li></ul><p>请提前保存好未完成的工作,感谢您的理解与支持!</p>`,category:`system`,priority:`high`,status:`unread`,timestamp:new Date(Date.now()-15*6e4).toISOString(),sender:{name:`系统管理员`,avatar:``}},{id:`msg-002`,title:`审批流程待处理`,summary:`张三提交的《Q1 季度预算申请》需要您审批,请尽快处理。`,category:`business`,priority:`urgent`,status:`unread`,timestamp:new Date(Date.now()-30*6e4).toISOString(),sender:{name:`张三`,avatar:`https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png`},actionUrl:`/workflow/approval`,actionText:`去审批`},{id:`msg-003`,title:`服务器 CPU 使用率告警`,summary:`生产环境节点 prod-node-03 CPU 使用率持续超过 90%,已触发告警阈值。`,category:`alarm`,priority:`urgent`,status:`unread`,timestamp:new Date(Date.now()-2*6e4).toISOString(),sender:{name:`监控中心`},actionUrl:`/monitor/server`,actionText:`查看详情`},{id:`msg-004`,title:`新版本发布 v1.14.0`,summary:`系统已升级至 v1.14.0,新增通知中心、工作流增强等多项功能。`,category:`system`,priority:`normal`,status:`unread`,timestamp:new Date(Date.now()-3*36e5).toISOString(),sender:{name:`系统管理员`}},{id:`msg-005`,title:`项目交付提醒`,summary:`「Robot Admin 二期」项目交付截止日期为 3月15日,当前进度 78%。`,category:`business`,priority:`high`,status:`read`,timestamp:new Date(Date.now()-8*36e5).toISOString(),sender:{name:`项目管理系统`}},{id:`msg-006`,title:`数据库连接池告警`,summary:`数据库连接池使用率达到 85%,建议关注并适时扩容。`,category:`alarm`,priority:`high`,status:`read`,timestamp:new Date(Date.now()-12*36e5).toISOString(),sender:{name:`监控中心`}},{id:`msg-007`,title:`周报提交提醒`,summary:`本周周报提交截止时间为周五 18:00,请及时提交。`,category:`business`,priority:`normal`,status:`read`,timestamp:new Date(Date.now()-24*36e5).toISOString(),sender:{name:`OA 系统`}},{id:`msg-008`,title:`账号安全提醒`,summary:`检测到您的账号在新设备上登录,如非本人操作请及时修改密码。`,category:`system`,priority:`high`,status:`unread`,timestamp:new Date(Date.now()-45*6e4).toISOString(),sender:{name:`安全中心`}}];function G(e,t){let n=O(`disconnected`),r=null,i=0,a=null,o=null,s=null;function c(e){n.value=e,t?.(e)}function l(e){s=e,i=0,u(e)}function u(e){g();let t=d(e);c(`connecting`);try{r=new WebSocket(t)}catch{c(`disconnected`),p(e);return}r.addEventListener(`open`,()=>{c(`connected`),i=0,m(e)}),r.addEventListener(`message`,e=>{f(e.data)}),r.addEventListener(`close`,()=>{h(),c(`disconnected`),e.autoReconnect!==!1&&p(e)}),r.addEventListener(`error`,()=>{})}function d(e){let t=e.getToken?.();if(t){let n=e.url.includes(`?`)?`&`:`?`;return`${e.url}${n}token=${encodeURIComponent(t)}`}return e.url}function f(t){if(typeof t==`string`&&t!==`pong`)try{e(JSON.parse(t))}catch{}}function p(e){let t=e.maxReconnectAttempts??5;if(i>=t)return;i++,c(`reconnecting`);let n=e.reconnectInterval??L;a=setTimeout(()=>{u(e)},n)}function m(e){let t=e.heartbeatInterval??z;if(t<=0)return;let n=e.heartbeatMessage??B;o=setInterval(()=>{r?.readyState===WebSocket.OPEN&&r.send(n)},t)}function h(){o&&=(clearInterval(o),null)}function g(){h(),a&&=(clearTimeout(a),null),r&&=(r.close(),null)}function _(){s=null,i=1/0,g(),c(`disconnected`)}function v(){s&&(i=0,u(s))}return w(g),{status:D(n),connect:l,disconnect:_,reconnect:v}}function K(e){let t=O([]),i=O(`all`),a=O(!1),o=O(0),s=O(1),c=O(null),l=O(!1),u=O(`disconnected`),d=m(()=>t.value.filter(e=>e.status===`unread`).length),f=m(()=>{let e={system:0,business:0,alarm:0};for(let n of t.value)n.status===`unread`&&n.category in e&&e[n.category]++;return e}),p=m(()=>i.value===`all`?t.value:t.value.filter(e=>e.category===i.value)),h=m(()=>t.value.length<o.value),g=m(()=>e.storageKey??te);function _(){let e=r(g.value);if(e?.unreadIds){let n=new Set(e.unreadIds);for(let e of t.value)n.has(e.id)&&(e.status=`unread`)}}let v=null;function y(){v&&clearTimeout(v),v=setTimeout(()=>{let e=t.value.filter(e=>e.status===`unread`).map(e=>e.id);n(g.value,{unreadIds:e,lastFetchTime:Date.now()}),v=null},300)}async function b(n=!1){n&&(s.value=1),a.value=!0;try{if(e.fetchNotifications){let r=i.value===`all`?void 0:i.value,a=e.pageSize??20,c=await e.fetchNotifications({category:r,page:s.value,pageSize:a});n?t.value=c.list:t.value.push(...c.list),o.value=c.total}else x();_()}finally{a.value=!1}}function x(){t.value=W.map(e=>({...e})),o.value=W.length}async function S(){!h.value||a.value||(s.value++,await b())}async function C(n){let r=new Set(n);for(let e of t.value)r.has(e.id)&&(e.status=`read`);if(y(),e.markAsRead)try{await e.markAsRead(n)}catch{for(let e of t.value)r.has(e.id)&&(e.status=`unread`);y()}}async function E(n){let r=n?t.value.filter(e=>e.category===n&&e.status===`unread`):t.value.filter(e=>e.status===`unread`);for(let e of r)e.status=`read`;if(y(),e.markAllRead)try{await e.markAllRead(n)}catch{for(let e of r)e.status=`unread`;y()}}async function D(n){let r=new Set(n),i=[...t.value];if(t.value=t.value.filter(e=>!r.has(e.id)),o.value=Math.max(0,o.value-n.length),y(),e.deleteNotification)try{await e.deleteNotification(n)}catch{t.value=i,o.value+=n.length,y()}}async function k(n){let r=[...t.value],i=o.value;if(n?t.value=t.value.filter(e=>e.category!==n):t.value=[],o.value=t.value.length,y(),e.clearNotifications)try{await e.clearNotifications(n)}catch{t.value=r,o.value=i,y()}}function A(e){switch(e.type){case`new_message`:{let n=e.data;t.value.some(e=>e.id===n.id)||(t.value.unshift(n),o.value++,y(),P(n));break}case`read_sync`:{let n=e.data,r=new Set(n.map(e=>e.id));for(let e of t.value)r.has(e.id)&&(e.status=`read`);y();break}case`count_update`:break}}function j(e){u.value=e}let{connect:M,disconnect:N}=G(A,j);function P(t){e.desktopNotification&&`Notification`in window&&(Notification.permission===`granted`?F(t):Notification.permission!==`denied`&&Notification.requestPermission().then(e=>{e===`granted`&&F(t)}))}function F(e){let t=new Notification(e.title,{body:e.summary,icon:e.sender?.avatar||`/robot-avatar.png`,tag:e.id});t.addEventListener(`click`,()=>{window.focus(),z(e),t.close()}),setTimeout(()=>t.close(),5e3)}let I=null;function L(){R();let t=e.pollingInterval??ee;t<=0||(I=setInterval(()=>{b(!0)},t))}function R(){I&&=(clearInterval(I),null)}function z(e){c.value=e,e.status===`unread`&&C([e.id])}function B(){c.value=null}function V(t){i.value=t,c.value=null,e.fetchNotifications&&b(!0)}function H(){b(!0),L(),e.wsConfig&&M(e.wsConfig)}function U(){R(),N(),v&&=(clearTimeout(v),null)}return T(H),w(U),{messages:t,activeCategory:i,loading:a,total:o,page:s,selectedMessage:c,popoverVisible:l,wsStatus:u,unreadCount:d,unreadByCategory:f,filteredMessages:p,hasMore:h,fetchMessages:b,loadMore:S,markAsRead:C,markAllAsRead:E,deleteMessages:D,clearMessages:k,selectMessage:z,clearSelection:B,switchCategory:V,connectWS:M,disconnectWS:N}}const ne={class:`notification-badge`},re={key:0,class:`notification-badge__count`},ie={key:0,class:`notification-badge__pulse`};var ae=t(x({__name:`NotificationBadge`,props:{count:{default:0},maxCount:{default:99},hasUrgent:{type:Boolean,default:!1}},emits:[`click`],setup(t){let n=t,r=m(()=>n.count>n.maxCount?`${n.maxCount}+`:String(n.count));return(t,n)=>{let i=d;return E(),_(`div`,ne,[b(i,{trigger:`hover`,placement:`bottom`},{trigger:N(()=>[v(`div`,{class:`notification-badge__trigger`,onClick:n[0]||=e=>t.$emit(`click`)},[b(e,{name:`mdi:bell-outline`,size:18,class:`notification-badge__icon`}),g(` 未读角标 `),b(p,{name:`badge-bounce`},{default:N(()=>[t.count>0?(E(),_(`span`,re,A(r.value),1)):g(`v-if`,!0)]),_:1}),g(` 脉冲动画(有紧急消息时) `),t.hasUrgent?(E(),_(`span`,ie)):g(`v-if`,!0)])]),default:N(()=>[y(` 消息通知`+A(t.count>0?`(${t.count} 条未读)`:``),1)]),_:1})])}}}),[[`__scopeId`,`data-v-03c9c8c7`]]);const q=6e4,J=36e5,Y=864e5,X=7*Y,Z=30*Y;365*Y;let Q=null;function $(){return Q||=oe(),Q}function oe(){function e(e){let r=new Date(e),i=Date.now()-r.getTime();if(i<0||i<q)return`刚刚`;if(i<J)return`${Math.floor(i/q)}分钟前`;if(i<Y)return`${Math.floor(i/J)}小时前`;let a=new Date;return a.setHours(0,0,0,0),r>=new Date(a.getTime()-Y)&&r<a?`昨天 ${n(r.getHours())}:${n(r.getMinutes())}`:i<X?`${Math.floor(i/Y)}天前`:i<Z?`${Math.floor(i/X)}周前`:i<31536e6?`${Math.floor(i/Z)}个月前`:t(r)}function t(e){return`${e.getFullYear()}-${n(e.getMonth()+1)}-${n(e.getDate())} ${n(e.getHours())}:${n(e.getMinutes())}`}function n(e){return e<10?`0${e}`:String(e)}return{formatRelativeTime:e,formatFullDate:t}}const se={class:`notification-item__indicator`},ce={class:`notification-item__avatar`},le={class:`notification-item__body`},ue={class:`notification-item__header`},de={class:`notification-item__title`},fe={class:`notification-item__summary`},pe={class:`notification-item__meta`},me={class:`notification-item__time`},he={key:0,class:`notification-item__sender`};var ge=t(x({__name:`NotificationItem`,props:{message:{}},emits:[`click`,`read`,`delete`],setup(t){let n=t,{formatRelativeTime:r}=$(),a=m(()=>V[n.message.category]?.icon??`mdi:bell-outline`),o=m(()=>U[n.message.priority]??U.normal),s=m(()=>r(n.message.timestamp));return(t,n)=>{let r=i,c=u,l=d;return E(),_(`div`,{class:S([`notification-item`,{"notification-item--unread":t.message.status===`unread`,"notification-item--urgent":t.message.priority===`urgent`}]),onClick:n[3]||=e=>t.$emit(`click`,t.message)},[g(` 未读指示点 `),v(`div`,se,[t.message.status===`unread`?(E(),_(`span`,{key:0,class:S([`notification-item__dot`,`notification-item__dot--${t.message.priority}`])},null,2)):g(`v-if`,!0)]),g(` 头像 `),v(`div`,ce,[t.message.sender?.avatar?(E(),h(r,{key:0,src:t.message.sender.avatar,size:36,round:``},null,8,[`src`])):(E(),_(`div`,{key:1,class:S([`notification-item__avatar-placeholder`,`notification-item__avatar-placeholder--${t.message.category}`])},[b(e,{name:a.value,size:16},null,8,[`name`])],2))]),g(` 内容 `),v(`div`,le,[v(`div`,ue,[v(`span`,de,A(t.message.title),1),t.message.priority===`urgent`||t.message.priority===`high`?(E(),h(c,{key:0,type:o.value.type,size:`tiny`,bordered:!1,round:``},{default:N(()=>[y(A(o.value.label),1)]),_:1},8,[`type`])):g(`v-if`,!0)]),v(`div`,fe,A(t.message.summary),1),v(`div`,pe,[v(`span`,me,A(s.value),1),t.message.sender?.name?(E(),_(`span`,he,A(t.message.sender.name),1)):g(`v-if`,!0)])]),g(` 操作区 `),v(`div`,{class:`notification-item__actions`,onClick:n[2]||=P(()=>{},[`stop`])},[t.message.status===`unread`?(E(),h(l,{key:0,trigger:`hover`,placement:`top`},{trigger:N(()=>[v(`span`,{class:`notification-item__action`,onClick:n[0]||=e=>t.$emit(`read`,t.message.id)},[b(e,{name:`mdi:check`,size:16})])]),default:N(()=>[n[4]||=y(` 标记已读 `,-1)]),_:1,__:[4]})):g(`v-if`,!0),b(l,{trigger:`hover`,placement:`top`},{trigger:N(()=>[v(`span`,{class:`notification-item__action`,onClick:n[1]||=e=>t.$emit(`delete`,t.message.id)},[b(e,{name:`mdi:delete-outline`,size:16})])]),default:N(()=>[n[5]||=y(` 删除 `,-1)]),_:1,__:[5]})])],2)}}}),[[`__scopeId`,`data-v-30bf7ddc`]]);const _e={class:`notification-list`},ve={class:`notification-list__tabs`},ye=[`onClick`],be={key:0,class:`notification-list__tab-count`},xe={key:0,class:`notification-list__toolbar`},Se={class:`notification-list__skeleton-text`},Ce={class:`notification-list__items`},we={class:`notification-list__empty`};var Te=t(x({__name:`NotificationList`,props:{messages:{},activeCategory:{},unreadByCategory:{},unreadCount:{},loading:{type:Boolean},hasMore:{type:Boolean},scrollHeight:{default:420}},emits:[`switchCategory`,`itemClick`,`read`,`delete`,`markAllRead`,`clear`,`loadMore`],setup(t){let n=t,r=m(()=>n.activeCategory===`all`?n.unreadCount:n.unreadByCategory[n.activeCategory]??0);function i(e){return e===`all`?n.unreadCount:n.unreadByCategory[e]??0}return(t,n)=>{let o=a,u=c,d=l,p=s;return E(),_(`div`,_e,[g(` 分类 Tab `),v(`div`,ve,[(E(!0),_(f,null,k(j(H),e=>(E(),_(`div`,{key:e.key,class:S([`notification-list__tab`,{"notification-list__tab--active":t.activeCategory===e.key}]),onClick:n=>t.$emit(`switchCategory`,e.key)},[v(`span`,null,A(e.label),1),i(e.key)>0?(E(),_(`span`,be,A(i(e.key)),1)):g(`v-if`,!0)],10,ye))),128))]),g(` 操作栏 `),t.messages.length>0?(E(),_(`div`,xe,[b(o,{text:``,size:`tiny`,disabled:r.value===0,onClick:n[0]||=e=>t.$emit(`markAllRead`)},{icon:N(()=>[b(e,{name:`mdi:check-all`,size:14})]),default:N(()=>[n[6]||=y(` 全部已读 `,-1)]),_:1,__:[6]},8,[`disabled`]),b(o,{text:``,size:`tiny`,onClick:n[1]||=e=>t.$emit(`clear`)},{icon:N(()=>[b(e,{name:`mdi:delete-sweep-outline`,size:14})]),default:N(()=>[n[7]||=y(` 清空 `,-1)]),_:1,__:[7]})])):g(`v-if`,!0),g(` 消息列表 `),b(p,{class:`notification-list__scroll`,style:C({maxHeight:`${t.scrollHeight}px`})},{default:N(()=>[t.loading&&t.messages.length===0?(E(),_(f,{key:0},[g(` 骨架屏 `),(E(),_(f,null,k(4,e=>v(`div`,{key:e,class:`notification-list__skeleton`},[b(u,{circle:``,width:36,height:36}),v(`div`,Se,[b(u,{text:``,width:`60%`,height:14}),b(u,{text:``,width:`90%`,height:12}),b(u,{text:``,width:`40%`,height:10})])])),64))],64)):t.messages.length>0?(E(),_(f,{key:1},[v(`div`,Ce,[(E(!0),_(f,null,k(t.messages,e=>(E(),h(ge,{key:e.id,message:e,onClick:n[2]||=e=>t.$emit(`itemClick`,e),onRead:n[3]||=e=>t.$emit(`read`,e),onDelete:n[4]||=e=>t.$emit(`delete`,e)},null,8,[`message`]))),128))]),g(` 加载更多 `),t.hasMore?(E(),_(`div`,{key:0,class:`notification-list__load-more`,onClick:n[5]||=e=>t.$emit(`loadMore`)},[t.loading?(E(),h(d,{key:0,size:14})):g(`v-if`,!0),v(`span`,null,A(t.loading?`加载中...`:`加载更多`),1)])):g(`v-if`,!0)],64)):(E(),_(f,{key:2},[g(` 空状态 `),v(`div`,we,[b(e,{name:`mdi:bell-off-outline`,size:48,class:`notification-list__empty-icon`}),n[8]||=v(`span`,{class:`notification-list__empty-text`},`暂无消息`,-1)])],2112))]),_:1},8,[`style`])])}}}),[[`__scopeId`,`data-v-3db0c5bf`]]);const Ee={class:`notification-detail`},De={class:`notification-detail__back`},Oe={class:`notification-detail__header`},ke={class:`notification-detail__title`},Ae={class:`notification-detail__meta`},je={class:`notification-detail__time`},Me={key:0,class:`notification-detail__sender`},Ne=[`innerHTML`],Pe={key:1,class:`notification-detail__body`},Fe={key:0,class:`notification-detail__footer`};var Ie=t(x({__name:`NotificationDetail`,props:{message:{},scrollHeight:{default:320}},emits:[`back`,`action`,`navigate`],setup(t,{emit:n}){let r=t,o=n,{formatRelativeTime:c}=$(),l=m(()=>V[r.message.category]??V.system),d=m(()=>U[r.message.priority]??U.normal),f=m(()=>c(r.message.timestamp));function p(){let e=r.message.actionUrl;e&&(o(`action`,e),e.startsWith(`http`)?window.open(e,`_blank`):o(`navigate`,e))}return(t,n)=>{let r=a,o=u,c=i,m=s;return E(),_(`div`,Ee,[g(` 返回栏 `),v(`div`,De,[b(r,{text:``,size:`small`,onClick:n[0]||=e=>t.$emit(`back`)},{icon:N(()=>[b(e,{name:`mdi:arrow-left`,size:16})]),default:N(()=>[n[1]||=y(` 返回列表 `,-1)]),_:1,__:[1]})]),g(` 消息头部 `),v(`div`,Oe,[v(`h3`,ke,A(t.message.title),1),v(`div`,Ae,[b(o,{type:l.value.color,size:`tiny`,bordered:!1,round:``},{icon:N(()=>[b(e,{name:l.value.icon,size:12},null,8,[`name`])]),default:N(()=>[y(` `+A(l.value.label),1)]),_:1},8,[`type`]),t.message.priority===`urgent`||t.message.priority===`high`?(E(),h(o,{key:0,type:d.value.type,size:`tiny`,bordered:!1,round:``},{default:N(()=>[y(A(d.value.label),1)]),_:1},8,[`type`])):g(`v-if`,!0),v(`span`,je,A(f.value),1)]),t.message.sender?(E(),_(`div`,Me,[t.message.sender.avatar?(E(),h(c,{key:0,src:t.message.sender.avatar,size:20,round:``},null,8,[`src`])):g(`v-if`,!0),v(`span`,null,A(t.message.sender.name),1)])):g(`v-if`,!0)]),g(` 消息内容 `),b(m,{class:`notification-detail__content`,style:C({maxHeight:`${t.scrollHeight}px`})},{default:N(()=>[t.message.content?(E(),_(`div`,{key:0,class:`notification-detail__body`,innerHTML:t.message.content},null,8,Ne)):(E(),_(`div`,Pe,A(t.message.summary),1))]),_:1},8,[`style`]),g(` 操作区 `),t.message.actionUrl?(E(),_(`div`,Fe,[b(r,{type:`primary`,size:`small`,onClick:p},{icon:N(()=>[b(e,{name:`mdi:arrow-right`,size:16})]),default:N(()=>[y(A(t.message.actionText||`查看详情`)+` `,1)]),_:1})])):g(`v-if`,!0)])}}}),[[`__scopeId`,`data-v-b10b0b8e`]]);const Le={class:`c-notification-center`},Re={class:`c-notification-center__panel`},ze={class:`c-notification-center__header`},Be={class:`c-notification-center__header-extra`};var Ve=t(x({name:`C_NotificationCenter`,__name:`index`,props:{fetchNotifications:{},markAsRead:{},markAllRead:{},deleteNotification:{},clearNotifications:{},wsConfig:{},desktopNotification:{type:Boolean,default:!1},maxBadgeCount:{default:99},pollingInterval:{default:6e4},pageSize:{default:20},storageKey:{default:`notification_center`}},emits:[`itemClick`,`read`,`allRead`,`delete`,`unreadChange`,`wsStatusChange`,`newMessage`,`navigate`],setup(e,{expose:t,emit:n}){let r=e,i=n,a=K(r),s=m(()=>a.messages.value.some(e=>e.status===`unread`&&e.priority===`urgent`)),c=m(()=>({connected:`已连接`,connecting:`连接中...`,disconnected:`未连接`,reconnecting:`重连中...`})[a.wsStatus.value]??`未知`);M(()=>a.unreadCount.value,e=>{i(`unreadChange`,e)});function l(){a.popoverVisible.value=!a.popoverVisible.value}function u(e){a.selectMessage(e),i(`itemClick`,e)}function f(e){a.markAsRead([e]),i(`read`,[e])}function x(e){a.deleteMessages([e]),i(`delete`,[e])}function C(){let e=a.activeCategory.value===`all`?void 0:a.activeCategory.value;a.markAllAsRead(e),i(`allRead`,e)}function w(){let e=a.activeCategory.value===`all`?void 0:a.activeCategory.value;a.clearMessages(e)}function T(){a.popoverVisible.value=!1}function D(){a.clearSelection()}return t({refresh:()=>a.fetchMessages(!0),connectWS:()=>{r.wsConfig&&a.connectWS(r.wsConfig)},disconnectWS:a.disconnectWS,getUnreadCount:()=>a.unreadCount.value,getMessages:()=>a.messages.value,markRead:e=>a.markAsRead(e),markAllAsRead:e=>a.markAllAsRead(e)}),(e,t)=>{let n=d,m=o;return E(),_(`div`,Le,[b(m,{show:j(a).popoverVisible.value,"onUpdate:show":t[1]||=e=>j(a).popoverVisible.value=e,width:420,trigger:`click`,placement:`bottom-end`,"show-arrow":!1,"content-class":`c-notification-center__popover`,onAfterLeave:D},{trigger:N(()=>[b(ae,{count:j(a).unreadCount.value,"max-count":r.maxBadgeCount,"has-urgent":s.value,onClick:l},null,8,[`count`,`max-count`,`has-urgent`])]),default:N(()=>[v(`div`,Re,[g(` 头部标题 `),v(`div`,ze,[t[2]||=v(`span`,{class:`c-notification-center__title`},`消息中心`,-1),v(`div`,Be,[g(` WebSocket 连接状态 `),r.wsConfig?(E(),h(n,{key:0,trigger:`hover`,placement:`top`},{trigger:N(()=>[v(`span`,{class:S([`c-notification-center__ws-dot`,`c-notification-center__ws-dot--${j(a).wsStatus.value}`])},null,2)]),default:N(()=>[y(` `+A(c.value),1)]),_:1})):g(`v-if`,!0)])]),g(` 列表 / 详情切换 `),b(p,{name:`slide-fade`,mode:`out-in`},{default:N(()=>[j(a).selectedMessage.value?(E(),h(Ie,{key:j(a).selectedMessage.value.id,message:j(a).selectedMessage.value,onBack:j(a).clearSelection,onAction:T,onNavigate:t[0]||=e=>i(`navigate`,e)},null,8,[`message`,`onBack`])):(E(),h(Te,{key:1,messages:j(a).filteredMessages.value,"active-category":j(a).activeCategory.value,"unread-by-category":j(a).unreadByCategory.value,"unread-count":j(a).unreadCount.value,loading:j(a).loading.value,"has-more":j(a).hasMore.value,onSwitchCategory:j(a).switchCategory,onItemClick:u,onRead:f,onDelete:x,onMarkAllRead:C,onClear:w,onLoadMore:j(a).loadMore},null,8,[`messages`,`active-category`,`unread-by-category`,`unread-count`,`loading`,`has-more`,`onSwitchCategory`,`onLoadMore`]))]),_:1})])]),_:1},8,[`show`])])}}}),[[`__scopeId`,`data-v-a60d6896`]]);export{V as a,I as c,z as d,B as f,U as g,W as h,G as i,ee as l,L as m,$ as n,H as o,R as p,K as r,F as s,Ve as t,te as u};
|
|
1384
2
|
//# sourceMappingURL=C_NotificationCenter2.js.map
|