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