@robot-admin/naive-ui-components 0.4.5 → 0.6.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.
Files changed (181) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/C_ActionBar-jZPsiXtT.css.map +1 -0
  3. package/dist/C_ActionBar.css +205 -0
  4. package/dist/C_AntV-D2Zp2qQF.css.map +1 -0
  5. package/dist/C_AntV.css +398 -0
  6. package/dist/C_Barcode-Do1Ozsmh.css.map +1 -0
  7. package/dist/C_Barcode.css +39 -0
  8. package/dist/C_Breadcrumb.cjs +1 -0
  9. package/dist/C_Breadcrumb.d.cts +2 -0
  10. package/dist/C_Breadcrumb.d.ts +3 -0
  11. package/dist/C_Breadcrumb.js +1 -0
  12. package/dist/C_Breadcrumb.js.map +1 -0
  13. package/dist/C_Breadcrumb2.js +2 -0
  14. package/dist/C_Breadcrumb2.js.map +1 -0
  15. package/dist/C_Captcha-CZmAETly.css.map +1 -0
  16. package/dist/C_Captcha.css +109 -0
  17. package/dist/C_Captcha.d.cts +1 -1
  18. package/dist/C_Captcha.d.ts +1 -1
  19. package/dist/C_Cascade-Dq0S5Jkm.css.map +1 -0
  20. package/dist/C_Cascade.css +10 -0
  21. package/dist/C_Cascade.d.cts +1 -1
  22. package/dist/C_Cascade.d.ts +1 -1
  23. package/dist/C_City-DNKv4MpH.css.map +1 -0
  24. package/dist/C_City.css +132 -0
  25. package/dist/C_City.d.cts +1 -1
  26. package/dist/C_City.d.ts +1 -1
  27. package/dist/C_Code-avZjAnHD.css.map +1 -0
  28. package/dist/C_Code.css +8 -0
  29. package/dist/C_Code.d.cts +1 -1
  30. package/dist/C_Code.d.ts +1 -1
  31. package/dist/C_CollapsePanel-BpofCDyl.css.map +1 -0
  32. package/dist/C_CollapsePanel.css +171 -0
  33. package/dist/C_Cron-DqHQ92LN.css.map +1 -0
  34. package/dist/C_Cron.css +307 -0
  35. package/dist/C_Date.d.cts +1 -1
  36. package/dist/C_Date.d.ts +1 -1
  37. package/dist/C_Draggable-r6nhx3yM.css.map +1 -0
  38. package/dist/C_Draggable.css +238 -0
  39. package/dist/C_Editor-D0_6UhIa.css.map +1 -0
  40. package/dist/C_Editor.css +52 -0
  41. package/dist/C_Editor.d.cts +1 -1
  42. package/dist/C_Editor.d.ts +1 -1
  43. package/dist/C_FilePreview-BVarVvnD.css.map +1 -0
  44. package/dist/C_FilePreview.css +507 -0
  45. package/dist/C_Form-BciQUPpS.css.map +1 -0
  46. package/dist/C_Form.css +976 -0
  47. package/dist/C_FormSearch-Bmd2CmG6.css.map +1 -0
  48. package/dist/C_FormSearch.css +177 -0
  49. package/dist/C_FormulaEditor-3WG2vtQl.css.map +1 -0
  50. package/dist/C_FormulaEditor.css +502 -0
  51. package/dist/C_FullCalendar-1U4VlG7X.css.map +1 -0
  52. package/dist/C_FullCalendar.css +7 -0
  53. package/dist/C_GlobalSearch-B6wK3m3k.css.map +1 -0
  54. package/dist/C_GlobalSearch.css +616 -0
  55. package/dist/C_Guide.d.cts +1 -1
  56. package/dist/C_Guide.d.ts +1 -1
  57. package/dist/C_Icon.d.cts +1 -1
  58. package/dist/C_Icon.d.ts +1 -1
  59. package/dist/C_ImageCropper-D3L2-J_J.css.map +1 -0
  60. package/dist/C_ImageCropper.css +129 -0
  61. package/dist/C_Language.d.cts +1 -1
  62. package/dist/C_Language.d.ts +1 -1
  63. package/dist/C_Map-BCJmDnJT.css.map +1 -0
  64. package/dist/C_Map.css +29 -0
  65. package/dist/C_Markdown-7iBnLDtL.css.map +1 -0
  66. package/dist/C_Markdown.css +112 -0
  67. package/dist/C_Markdown.d.cts +1 -1
  68. package/dist/C_Markdown.d.ts +1 -1
  69. package/dist/C_Menu.cjs +1 -0
  70. package/dist/C_Menu.d.cts +2 -0
  71. package/dist/C_Menu.d.ts +3 -0
  72. package/dist/C_Menu.js +1 -0
  73. package/dist/C_Menu.js.map +1 -0
  74. package/dist/C_Menu2.js +2 -0
  75. package/dist/C_Menu2.js.map +1 -0
  76. package/dist/C_NotificationCenter-DT6fQ79O.css.map +1 -0
  77. package/dist/C_NotificationCenter.css +466 -0
  78. package/dist/C_Progress.d.cts +1 -1
  79. package/dist/C_Progress.d.ts +1 -1
  80. package/dist/C_QRCode-DMxSyogU.css.map +1 -0
  81. package/dist/C_QRCode.css +51 -0
  82. package/dist/C_Signature-B5fFz6RD.css.map +1 -0
  83. package/dist/C_Signature.css +79 -0
  84. package/dist/C_SplitPane-DuyzUhKB.css.map +1 -0
  85. package/dist/C_SplitPane.css +152 -0
  86. package/dist/C_Steps-DGwXxS2Y.css.map +1 -0
  87. package/dist/C_Steps.css +171 -0
  88. package/dist/C_Steps.d.cts +1 -1
  89. package/dist/C_Steps.d.ts +1 -1
  90. package/dist/C_Table-Dcam_tRs.css.map +1 -0
  91. package/dist/C_Table.css +527 -0
  92. package/dist/C_TagsView-DX3LecK1.css.map +1 -0
  93. package/dist/C_TagsView-DqOTa8bL.css.map +1 -0
  94. package/dist/C_TagsView.cjs +1 -0
  95. package/dist/C_TagsView.css +194 -0
  96. package/dist/C_TagsView.d.cts +2 -0
  97. package/dist/C_TagsView.d.ts +3 -0
  98. package/dist/C_TagsView.js +1 -0
  99. package/dist/C_TagsView.js.map +1 -0
  100. package/dist/C_TagsView2.js +2 -0
  101. package/dist/C_TagsView2.js.map +1 -0
  102. package/dist/C_Theme.d.cts +1 -1
  103. package/dist/C_Theme.d.ts +1 -1
  104. package/dist/C_Time-CKb_fwdm.css.map +1 -0
  105. package/dist/C_Time.css +23 -0
  106. package/dist/C_Tree-B-Le4hjQ.css.map +1 -0
  107. package/dist/C_Tree.css +142 -0
  108. package/dist/C_Upload-S30RmC9t.css.map +1 -0
  109. package/dist/C_Upload.css +251 -0
  110. package/dist/C_VideoPlayer-Cdgv4Zq0.css.map +1 -0
  111. package/dist/C_VideoPlayer.css +355 -0
  112. package/dist/C_VideoPlayer.d.ts +1 -1
  113. package/dist/C_VtableGantt-DB87-jdS.css.map +1 -0
  114. package/dist/C_VtableGantt.css +89 -0
  115. package/dist/C_VtableGantt.d.cts +1 -1
  116. package/dist/C_VtableGantt.d.ts +1 -1
  117. package/dist/C_WaterFall-C4HDqf-a.css.map +1 -0
  118. package/dist/C_WaterFall.css +73 -0
  119. package/dist/C_WorkFlow-Cy3HWA6A.css.map +1 -0
  120. package/dist/C_WorkFlow.css +1166 -0
  121. package/dist/_shared.cjs +1 -0
  122. package/dist/_shared.d.cts +2 -0
  123. package/dist/_shared.d.ts +2 -0
  124. package/dist/_shared.js +1 -0
  125. package/dist/chunk.js +1 -1
  126. package/dist/constants.d.ts +3 -3
  127. package/dist/constants2.d.ts +4 -4
  128. package/dist/constants3.d.ts +4 -4
  129. package/dist/constants4.d.ts +3 -3
  130. package/dist/constants5.d.ts +6 -3814
  131. package/dist/data.d.ts +3 -3
  132. package/dist/index.cjs +1 -1
  133. package/dist/index.cjs.map +1 -1
  134. package/dist/index.d.cts +40 -36
  135. package/dist/index.d.ts +45 -36
  136. package/dist/index.js +1 -1
  137. package/dist/index.js.map +1 -1
  138. package/dist/index10.vue.d.ts +23 -65
  139. package/dist/index11.vue.d.ts +64 -18
  140. package/dist/index12.vue.d.ts +17 -72
  141. package/dist/index13.vue.d.ts +72 -46
  142. package/dist/index14.vue.d.ts +57 -23
  143. package/dist/index15.vue.d.ts +48 -11
  144. package/dist/index16.vue.d.ts +23 -652
  145. package/dist/index17.vue.d.ts +88 -0
  146. package/dist/index18.vue.d.ts +18 -0
  147. package/dist/index19.vue.d.ts +662 -0
  148. package/dist/index2.vue.d.ts +1 -1
  149. package/dist/index3.vue.d.ts +20 -37
  150. package/dist/index4.vue.d.ts +37 -23
  151. package/dist/index5.vue.d.ts +22 -26
  152. package/dist/index6.vue.d.ts +24 -37
  153. package/dist/index7.vue.d.ts +36 -44
  154. package/dist/index8.vue.d.ts +40 -25
  155. package/dist/index9.vue.d.ts +34 -23
  156. package/dist/menuAdapter.d.ts +167 -0
  157. package/dist/menuAdapter.js +2 -0
  158. package/dist/menuAdapter.js.map +1 -0
  159. package/dist/resolver.cjs +1 -1
  160. package/dist/resolver.cjs.map +1 -1
  161. package/dist/resolver.d.cts +8 -1
  162. package/dist/resolver.d.ts +8 -1
  163. package/dist/resolver.js +1 -1
  164. package/dist/resolver.js.map +1 -1
  165. package/dist/style.css +243 -47
  166. package/dist/useCalendarEvents.d.ts +1 -1
  167. package/dist/useCollapsePanel.d.ts +5 -5
  168. package/dist/useCropperCore.d.ts +4 -4
  169. package/dist/useDraggableLayout.d.ts +4 -4
  170. package/dist/useDynamicFormState.d.ts +6 -6
  171. package/dist/useEdgeInteraction.d.ts +2 -7283
  172. package/dist/useInfiniteScroll.d.ts +2 -2
  173. package/dist/useModalEdit.d.ts +8 -8
  174. package/dist/useQRCode.d.ts +1 -1
  175. package/dist/useSearchState.d.ts +1 -1
  176. package/dist/useSignatureHistory.d.ts +1 -1
  177. package/dist/useSplitResize.d.ts +6 -6
  178. package/dist/useTimeSelection.d.ts +2 -2
  179. package/dist/useTreeOperations.d.ts +3 -3
  180. package/dist/useWorkflowValidation.d.ts +4 -4
  181. package/package.json +34 -33
@@ -0,0 +1,129 @@
1
+ /* unplugin-vue-components disabled */.cropper-toolbar[data-v-ac310c55] {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ gap: 4px;
5
+ align-items: center;
6
+ padding: 8px 0;
7
+ }
8
+ /* unplugin-vue-components disabled */.cropper-preview[data-v-11f355b4] {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 16px;
12
+ }
13
+ .cropper-preview .preview-label[data-v-11f355b4] {
14
+ display: flex;
15
+ gap: 6px;
16
+ align-items: center;
17
+ font-size: 13px;
18
+ font-weight: 500;
19
+ color: var(--text-color-2);
20
+ }
21
+ .cropper-preview .preview-main[data-v-11f355b4] {
22
+ width: 100%;
23
+ overflow: hidden;
24
+ border: 1px solid var(--border-color);
25
+ border-radius: 6px;
26
+ background: linear-gradient(45deg, #f0f0f0 25%, transparent 25%), linear-gradient(-45deg, #f0f0f0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f0f0f0 75%), linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);
27
+ background-position: 0 0, 0 8px, 8px -8px, -8px 0;
28
+ background-size: 16px 16px;
29
+ }
30
+ .cropper-preview .preview-main--circular[data-v-11f355b4] {
31
+ border-radius: 50%;
32
+ }
33
+ .cropper-preview .preview-main__viewport img[data-v-11f355b4] {
34
+ display: block;
35
+ max-width: none !important;
36
+ }
37
+ .cropper-preview .preview-empty[data-v-11f355b4] {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ width: 100%;
42
+ height: 100%;
43
+ min-height: 120px;
44
+ }
45
+ .cropper-preview .preview-thumbs[data-v-11f355b4] {
46
+ display: flex;
47
+ gap: 12px;
48
+ align-items: flex-end;
49
+ justify-content: center;
50
+ }
51
+ .cropper-preview .preview-thumb[data-v-11f355b4] {
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: 4px;
55
+ align-items: center;
56
+ }
57
+ .cropper-preview .preview-thumb__box[data-v-11f355b4] {
58
+ overflow: hidden;
59
+ border: 1px solid var(--border-color);
60
+ border-radius: 4px;
61
+ background: var(--body-color);
62
+ }
63
+ .cropper-preview .preview-thumb__box--circular[data-v-11f355b4] {
64
+ border-radius: 50%;
65
+ }
66
+ .cropper-preview .preview-thumb__viewport img[data-v-11f355b4] {
67
+ display: block;
68
+ max-width: none !important;
69
+ }
70
+ .cropper-preview .preview-thumb__label[data-v-11f355b4] {
71
+ font-size: 11px;
72
+ color: var(--text-color-3);
73
+ }
74
+ /* unplugin-vue-components disabled *//* C_ImageCropper styles */
75
+ .c-image-cropper[data-v-b25a5839] {
76
+ width: 100%;
77
+ }
78
+ .c-image-cropper__body[data-v-b25a5839] {
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: 8px;
82
+ }
83
+ .c-image-cropper__workspace[data-v-b25a5839] {
84
+ display: flex;
85
+ gap: 16px;
86
+ align-items: stretch;
87
+ }
88
+ .c-image-cropper__canvas[data-v-b25a5839] {
89
+ position: relative;
90
+ flex: 1;
91
+ min-width: 0;
92
+ overflow: hidden;
93
+ border: 1px solid var(--border-color);
94
+ border-radius: 6px;
95
+ background: var(--body-color);
96
+ }
97
+ .c-image-cropper__canvas[data-v-b25a5839] .vue-cropper {
98
+ width: 100% !important;
99
+ height: 100% !important;
100
+ }
101
+ .c-image-cropper__preview-panel[data-v-b25a5839] {
102
+ flex: 0 1 280px;
103
+ min-width: 200px;
104
+ padding: 16px;
105
+ overflow: hidden;
106
+ border: 1px solid var(--border-color);
107
+ border-radius: 6px;
108
+ background: var(--card-color);
109
+ }
110
+ .c-image-cropper__placeholder[data-v-b25a5839] {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: 8px;
114
+ align-items: center;
115
+ justify-content: center;
116
+ height: 100%;
117
+ color: var(--text-color-3);
118
+ font-size: 14px;
119
+ }
120
+ @media (width <= 768px) {
121
+ .c-image-cropper__workspace[data-v-b25a5839] {
122
+ flex-direction: column;
123
+ }
124
+ .c-image-cropper__preview-panel[data-v-b25a5839] {
125
+ max-width: none;
126
+ }
127
+ }
128
+
129
+ /*# sourceMappingURL=C_ImageCropper-D3L2-J_J.css.map*/
@@ -1,2 +1,2 @@
1
- import { n as _default, t as LanguageOption } from "./index11.vue.js";
1
+ import { n as _default, t as LanguageOption } from "./index12.vue.js";
2
2
  export { _default as C_Language, type LanguageOption };
@@ -1,2 +1,2 @@
1
- import { n as _default, t as LanguageOption } from "./index11.vue.js";
1
+ import { n as _default, t as LanguageOption } from "./index12.vue.js";
2
2
  export { _default as C_Language, type LanguageOption };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Map-BCJmDnJT.css","names":[],"sources":["../src/components/C_Map/index.vue?vue&type=style&index=0&scoped=a3602506&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-map[data-v-a3602506] {\n position: relative;\n width: 100%;\n min-height: 300px;\n background: #f5f5f5;\n border-radius: 4px;\n overflow: hidden;\n}\n.c-map .map-container[data-v-a3602506] {\n width: 100%;\n height: 100%;\n border-radius: 4px;\n overflow: hidden;\n}\n.c-map .map-loading[data-v-a3602506] {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.9);\n border-radius: 4px;\n z-index: 1000;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
package/dist/C_Map.css ADDED
@@ -0,0 +1,29 @@
1
+ /* unplugin-vue-components disabled */.c-map[data-v-a3602506] {
2
+ position: relative;
3
+ width: 100%;
4
+ min-height: 300px;
5
+ background: #f5f5f5;
6
+ border-radius: 4px;
7
+ overflow: hidden;
8
+ }
9
+ .c-map .map-container[data-v-a3602506] {
10
+ width: 100%;
11
+ height: 100%;
12
+ border-radius: 4px;
13
+ overflow: hidden;
14
+ }
15
+ .c-map .map-loading[data-v-a3602506] {
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ background: rgba(255, 255, 255, 0.9);
25
+ border-radius: 4px;
26
+ z-index: 1000;
27
+ }
28
+
29
+ /*# sourceMappingURL=C_Map-BCJmDnJT.css.map*/
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Markdown-7iBnLDtL.css","names":[],"sources":["../src/components/C_Markdown/index.vue?vue&type=style&index=0&scoped=67f4346d&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* C_Markdown 组件样式文件 */\n.c-markdown-wrapper[data-v-67f4346d] {\n position: relative;\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor {\n border-radius: 6px;\n border: 1px solid var(--c-border);\n background-color: var(--c-bg-card);\n /* 禁用状态样式 */\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor:hover {\n border-color: var(--c-primary);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor:focus-within {\n border-color: var(--c-primary);\n box-shadow: 0 0 0 2px var(--c-primary-opacity, rgba(24, 160, 88, 0.2));\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor.disabled {\n background-color: var(--c-bg-disabled, #fafafc);\n cursor: not-allowed;\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor.disabled .v-md-editor__editor {\n cursor: not-allowed;\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar {\n background-color: var(--c-bg-card);\n border-bottom: 1px solid var(--c-border);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor-wrapper {\n background-color: var(--c-bg-card);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor {\n background-color: var(--c-bg-card);\n color: var(--c-text-1);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor textarea {\n color: var(--c-text-1);\n caret-color: var(--c-text-1);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__preview-wrapper {\n background-color: var(--c-bg-card);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__preview {\n background-color: var(--c-bg-card);\n color: var(--c-text-1);\n}\n.c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__toc-nav-wrapper {\n background-color: var(--c-bg-card);\n border-left: 1px solid var(--c-border);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item {\n color: #ffffff;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item:hover {\n background-color: rgba(255, 255, 255, 0.08);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item.is-active {\n background-color: rgba(255, 255, 255, 0.12);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item svg {\n fill: #ffffff;\n opacity: 0.9;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item:hover svg {\n opacity: 1;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item {\n background-color: transparent;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item svg {\n fill: #ffffff;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item:hover {\n background-color: rgba(255, 255, 255, 0.08);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-divider {\n background-color: var(--c-border);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar,\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-track,\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-track {\n background-color: rgba(255, 255, 255, 0.05);\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-thumb,\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-thumb {\n background-color: rgba(255, 255, 255, 0.2);\n border-radius: 4px;\n}\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-thumb:hover,\n.c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-thumb:hover {\n background-color: rgba(255, 255, 255, 0.3);\n}\n.c-markdown-wrapper .word-count[data-v-67f4346d] {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 12px;\n color: var(--c-text-4);\n background: var(--c-bg-card);\n padding: 2px 6px;\n border-radius: 4px;\n z-index: 10;\n}\n.c-markdown-wrapper .word-count.exceed[data-v-67f4346d] {\n color: var(--c-error);\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
@@ -0,0 +1,112 @@
1
+ /* unplugin-vue-components disabled *//* C_Markdown 组件样式文件 */
2
+ .c-markdown-wrapper[data-v-67f4346d] {
3
+ position: relative;
4
+ }
5
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor {
6
+ border-radius: 6px;
7
+ border: 1px solid var(--c-border);
8
+ background-color: var(--c-bg-card);
9
+ /* 禁用状态样式 */
10
+ }
11
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor:hover {
12
+ border-color: var(--c-primary);
13
+ }
14
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor:focus-within {
15
+ border-color: var(--c-primary);
16
+ box-shadow: 0 0 0 2px var(--c-primary-opacity, rgba(24, 160, 88, 0.2));
17
+ }
18
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor.disabled {
19
+ background-color: var(--c-bg-disabled, #fafafc);
20
+ cursor: not-allowed;
21
+ }
22
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor.disabled .v-md-editor__editor {
23
+ cursor: not-allowed;
24
+ }
25
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar {
26
+ background-color: var(--c-bg-card);
27
+ border-bottom: 1px solid var(--c-border);
28
+ }
29
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor-wrapper {
30
+ background-color: var(--c-bg-card);
31
+ }
32
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor {
33
+ background-color: var(--c-bg-card);
34
+ color: var(--c-text-1);
35
+ }
36
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__editor textarea {
37
+ color: var(--c-text-1);
38
+ caret-color: var(--c-text-1);
39
+ }
40
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__preview-wrapper {
41
+ background-color: var(--c-bg-card);
42
+ }
43
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__preview {
44
+ background-color: var(--c-bg-card);
45
+ color: var(--c-text-1);
46
+ }
47
+ .c-markdown-wrapper[data-v-67f4346d] .v-md-editor .v-md-editor__toc-nav-wrapper {
48
+ background-color: var(--c-bg-card);
49
+ border-left: 1px solid var(--c-border);
50
+ }
51
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item {
52
+ color: #ffffff;
53
+ }
54
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item:hover {
55
+ background-color: rgba(255, 255, 255, 0.08);
56
+ }
57
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item.is-active {
58
+ background-color: rgba(255, 255, 255, 0.12);
59
+ }
60
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item svg {
61
+ fill: #ffffff;
62
+ opacity: 0.9;
63
+ }
64
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-item:hover svg {
65
+ opacity: 1;
66
+ }
67
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item {
68
+ background-color: transparent;
69
+ }
70
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item svg {
71
+ fill: #ffffff;
72
+ }
73
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-right .v-md-editor__toolbar-item:hover {
74
+ background-color: rgba(255, 255, 255, 0.08);
75
+ }
76
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__toolbar-divider {
77
+ background-color: var(--c-border);
78
+ }
79
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar,
80
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar {
81
+ width: 8px;
82
+ height: 8px;
83
+ }
84
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-track,
85
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-track {
86
+ background-color: rgba(255, 255, 255, 0.05);
87
+ }
88
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-thumb,
89
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-thumb {
90
+ background-color: rgba(255, 255, 255, 0.2);
91
+ border-radius: 4px;
92
+ }
93
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__editor::-webkit-scrollbar-thumb:hover,
94
+ .c-markdown-wrapper.is-dark[data-v-67f4346d] .v-md-editor .v-md-editor__preview::-webkit-scrollbar-thumb:hover {
95
+ background-color: rgba(255, 255, 255, 0.3);
96
+ }
97
+ .c-markdown-wrapper .word-count[data-v-67f4346d] {
98
+ position: absolute;
99
+ bottom: 8px;
100
+ right: 12px;
101
+ font-size: 12px;
102
+ color: var(--c-text-4);
103
+ background: var(--c-bg-card);
104
+ padding: 2px 6px;
105
+ border-radius: 4px;
106
+ z-index: 10;
107
+ }
108
+ .c-markdown-wrapper .word-count.exceed[data-v-67f4346d] {
109
+ color: var(--c-error);
110
+ }
111
+
112
+ /*# sourceMappingURL=C_Markdown-7iBnLDtL.css.map*/
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index12.vue.js";
1
+ import { t as _default } from "./index13.vue.js";
2
2
  export { _default as C_Markdown };
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index12.vue.js";
1
+ import { t as _default } from "./index13.vue.js";
2
2
  export { _default as C_Markdown };
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./C_Menu.js`);exports.C_Menu=e.t;
@@ -0,0 +1,2 @@
1
+ import { t as _default } from "./index14.vue.js";
2
+ export { _default as C_Menu };
@@ -0,0 +1,3 @@
1
+ import "./menuAdapter.js";
2
+ import { t as _default } from "./index14.vue.js";
3
+ export { _default as C_Menu };
package/dist/C_Menu.js ADDED
@@ -0,0 +1 @@
1
+ import{t as e}from"./C_Menu2.js";export{e as C_Menu};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Menu.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n"],"mappings":"gnBE0DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,GAAA,EAAA,EAAA,KAA+B,KAAI,CACnC,GAAA,EAAA,EAAA,KAA6B,EAAE,CAAA,CAE/B,GAAA,EAAA,EAAA,cAA2B,EAAM,OAAS,GAAE,CAK5C,GAAA,EAAA,EAAA,cAA6C,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACtE,CACA,OAAO,EAAA,EAAkB,EAAM,OAAQ,EAAM,CAG/C,MAAO,EAAC,EACT,CAKK,GACJ,EACA,EACA,EAAuB,EAAC,GACX,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAa,CACtD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAW,CAC9D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAC,EAIJ,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAO,CACzC,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAW,EACrB,CACD,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAA,CAC/D,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAG,EAIhB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAI,SAKlC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAG,CACtC,UAAS,CAAA,EAIpC,EAAA,EAAA,WACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAM,CAC1C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAA,CAC7C,EACA,EAAA,EAAA,cAAe,EAAQ,OAAO,WAAW,EAAO,CAAA,EAElD,CAAE,UAAW,GAAK,CACpB,EAEA,EAAA,EAAA,eAAgB,EACd,EAAA,EAAA,cAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAA,CACpE,EAAQ,OAAO,WAAW,EAAU,MAAK,GAE5C,EACF,iEAnLC,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./menuAdapter.js";import{NMenu as t}from"naive-ui";import{computed as n,createBlock as r,defineComponent as i,nextTick as a,onMounted as o,openBlock as s,ref as c,watch as l}from"vue";var u=i({name:`C_Menu`,__name:`index`,props:{options:{},routes:{},adapterConfig:{},labelFormatter:{},value:{},mode:{default:`vertical`},collapsed:{type:Boolean,default:!1},collapsedWidth:{default:64},collapsedIconSize:{default:22},inverted:{type:Boolean,default:!1},themeOverrides:{},indent:{default:24},rootIndent:{default:16},dropdownProps:{default:()=>({placement:`right-start`,trigger:`hover`,arrowStyle:{color:`var(--n-color)`}})}},emits:[`select`,`update:expandedKeys`],setup(i,{expose:u,emit:d}){let f=i,p=d,m=c(null),h=c([]),g=n(()=>f.value??``),_=n(()=>{if(f.options)return f.options;if(f.routes){let t={...f.adapterConfig,...f.labelFormatter&&{labelFormatter:f.labelFormatter}};return e(f.routes,t)}return[]}),v=(e,t,n=[])=>{for(let r of e){let e=r.children;if(e?.length){let i=[...n,r.key];if(e.some(e=>e.key===t))return i;let a=v(e,t,i);if(a.length>0)return a}}return[]},y=e=>{let t=e.split(`/`).filter(Boolean),n=new Set,r=``;return t.forEach(e=>{r+=`/${e}`,n.add(r)}),v(_.value,e).forEach(e=>n.add(e)),n},b=e=>{e&&e!==g.value&&p(`select`,e)},x=e=>{h.value=e,p(`update:expandedKeys`,e)};return u({showOption:e=>m.value?.showOption(e),menuRef:m}),l(()=>g.value,e=>{if(!e)return;let t=y(e);h.value=Array.from(new Set([...h.value,...t])),a(()=>m.value?.showOption(e))},{immediate:!0}),o(()=>{a(()=>{g.value&&(h.value=Array.from(y(g.value)),m.value?.showOption(g.value))})}),(e,n)=>{let i=t;return s(),r(i,{ref_key:`menuRef`,ref:m,options:_.value,"expanded-keys":h.value,value:g.value,mode:e.mode,collapsed:e.collapsed,"collapsed-width":e.collapsedWidth,"collapsed-icon-size":e.collapsedIconSize,inverted:e.inverted,"theme-overrides":e.themeOverrides,"dropdown-props":e.dropdownProps,indent:e.indent,"root-indent":e.rootIndent,"onUpdate:value":b,"onUpdate:expandedKeys":x},null,8,[`options`,`expanded-keys`,`value`,`mode`,`collapsed`,`collapsed-width`,`collapsed-icon-size`,`inverted`,`theme-overrides`,`dropdown-props`,`indent`,`root-indent`])}}});export{u as t};
2
+ //# sourceMappingURL=C_Menu2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Menu2.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import type { RouteItem, MenuAdapterConfig } from '../_shared'\n import { createMenuOptions } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n"],"mappings":"ksBE0DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,EAAU,EAAqB,KAAI,CACnC,EAAe,EAAc,EAAE,CAAA,CAE/B,EAAY,MAAe,EAAM,OAAS,GAAE,CAK5C,EAAgB,MAA6B,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACtE,CACA,OAAO,EAAkB,EAAM,OAAQ,EAAM,CAG/C,MAAO,EAAC,EACT,CAKK,GACJ,EACA,EACA,EAAuB,EAAC,GACX,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAa,CACtD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAW,CAC9D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAC,EAIJ,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAO,CACzC,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAW,EACrB,CACD,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAA,CAC/D,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAG,EAIhB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAI,SAKlC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAG,CACtC,UAAS,CAAA,CAIpC,MACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAM,CAC1C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAA,CAC7C,CACA,MAAe,EAAQ,OAAO,WAAW,EAAO,CAAA,EAElD,CAAE,UAAW,GAAK,CACpB,CAEA,MAAgB,CACd,MAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAA,CACpE,EAAQ,OAAO,WAAW,EAAU,MAAK,GAE5C,EACF,4BAnMD,EAgBE,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_NotificationCenter-DT6fQ79O.css","names":[],"sources":["../src/components/C_NotificationCenter/components/NotificationBadge.vue?vue&type=style&index=0&scoped=03c9c8c7&lang.scss","../src/components/C_NotificationCenter/components/NotificationItem.vue?vue&type=style&index=0&scoped=30bf7ddc&lang.scss","../src/components/C_NotificationCenter/components/NotificationList.vue?vue&type=style&index=0&scoped=3db0c5bf&lang.scss","../src/components/C_NotificationCenter/components/NotificationDetail.vue?vue&type=style&index=0&scoped=b10b0b8e&lang.scss","../src/components/C_NotificationCenter/index.vue?vue&type=style&index=0&scoped=a60d6896&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.notification-badge[data-v-03c9c8c7] {\n position: relative;\n display: inline-flex;\n align-items: center;\n}\n.notification-badge__trigger[data-v-03c9c8c7] {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: 4px;\n border-radius: 6px;\n transition: all var(--c-transition, 0.2s ease);\n}\n.notification-badge__trigger[data-v-03c9c8c7]:hover {\n background-color: var(--c-border);\n}\n.notification-badge__trigger:hover .notification-badge__icon[data-v-03c9c8c7] {\n color: var(--c-primary);\n}\n.notification-badge__icon[data-v-03c9c8c7] {\n color: var(--c-text-2);\n transition: color var(--c-transition, 0.2s ease);\n}\n.notification-badge__count[data-v-03c9c8c7] {\n position: absolute;\n top: -2px;\n right: -4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: #f5222d;\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n white-space: nowrap;\n pointer-events: none;\n box-shadow: 0 0 0 2px var(--c-bg);\n}\n.notification-badge__pulse[data-v-03c9c8c7] {\n position: absolute;\n top: -2px;\n right: -4px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: rgba(245, 34, 45, 0.4);\n animation: pulse-ring-03c9c8c7 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;\n pointer-events: none;\n}\n@keyframes pulse-ring-03c9c8c7 {\n0% {\n transform: scale(0.8);\n opacity: 1;\n}\n100% {\n transform: scale(2.2);\n opacity: 0;\n}\n}\n.badge-bounce-enter-active[data-v-03c9c8c7] {\n animation: badge-in-03c9c8c7 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n}\n.badge-bounce-leave-active[data-v-03c9c8c7] {\n animation: badge-in-03c9c8c7 0.2s ease reverse;\n}\n@keyframes badge-in-03c9c8c7 {\n0% {\n transform: scale(0);\n opacity: 0;\n}\n100% {\n transform: scale(1);\n opacity: 1;\n}\n}","/* unplugin-vue-components disabled */.notification-item[data-v-30bf7ddc] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 16px;\n cursor: pointer;\n transition: background-color var(--c-transition, 0.2s ease);\n border-bottom: 1px solid var(--c-border);\n /* ─── 子元素 ──────────────────────────── */\n}\n.notification-item[data-v-30bf7ddc]:last-child {\n border-bottom: none;\n}\n.notification-item[data-v-30bf7ddc]:hover {\n background-color: var(--c-bg-card);\n}\n.notification-item:hover .notification-item__actions[data-v-30bf7ddc] {\n opacity: 1;\n}\n.notification-item--unread[data-v-30bf7ddc] {\n background-color: color-mix(in srgb, var(--c-primary) 4%, transparent);\n}\n.notification-item--unread[data-v-30bf7ddc]:hover {\n background-color: color-mix(in srgb, var(--c-primary) 8%, transparent);\n}\n.notification-item--urgent[data-v-30bf7ddc] {\n border-left: 3px solid #f5222d;\n padding-left: 13px;\n}\n.notification-item__indicator[data-v-30bf7ddc] {\n flex-shrink: 0;\n width: 8px;\n display: flex;\n align-items: center;\n padding-top: 14px;\n}\n.notification-item__dot[data-v-30bf7ddc] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--c-primary);\n}\n.notification-item__dot--urgent[data-v-30bf7ddc] {\n background: #f5222d;\n box-shadow: 0 0 4px rgba(245, 34, 45, 0.5);\n}\n.notification-item__dot--high[data-v-30bf7ddc] {\n background: #fa8c16;\n}\n.notification-item__dot--normal[data-v-30bf7ddc] {\n background: var(--c-primary);\n}\n.notification-item__dot--low[data-v-30bf7ddc] {\n background: var(--c-text-4);\n}\n.notification-item__avatar[data-v-30bf7ddc] {\n flex-shrink: 0;\n}\n.notification-item__avatar-placeholder[data-v-30bf7ddc] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: #fff;\n}\n.notification-item__avatar-placeholder--system[data-v-30bf7ddc] {\n background: linear-gradient(135deg, #667eea, #764ba2);\n}\n.notification-item__avatar-placeholder--business[data-v-30bf7ddc] {\n background: linear-gradient(135deg, #43e97b, #38f9d7);\n color: #0d1425;\n}\n.notification-item__avatar-placeholder--alarm[data-v-30bf7ddc] {\n background: linear-gradient(135deg, #f093fb, #f5576c);\n}\n.notification-item__body[data-v-30bf7ddc] {\n flex: 1;\n min-width: 0;\n}\n.notification-item__header[data-v-30bf7ddc] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n}\n.notification-item__title[data-v-30bf7ddc] {\n font-size: 13px;\n font-weight: 500;\n color: var(--c-text-1);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.notification-item__summary[data-v-30bf7ddc] {\n font-size: 12px;\n color: var(--c-text-2);\n line-height: 1.5;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.notification-item__meta[data-v-30bf7ddc] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 6px;\n}\n.notification-item__time[data-v-30bf7ddc], .notification-item__sender[data-v-30bf7ddc] {\n font-size: 11px;\n color: var(--c-text-4);\n}\n.notification-item__sender[data-v-30bf7ddc]::before {\n content: \"·\";\n margin-right: 8px;\n}\n.notification-item__actions[data-v-30bf7ddc] {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n opacity: 0;\n transition: opacity var(--c-transition, 0.2s ease);\n}\n.notification-item__action[data-v-30bf7ddc] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 2px;\n border-radius: 4px;\n cursor: pointer;\n color: var(--c-text-4);\n transition: all var(--c-transition, 0.2s ease);\n}\n.notification-item__action[data-v-30bf7ddc]:hover {\n color: var(--c-primary);\n background-color: var(--c-border);\n}","/* unplugin-vue-components disabled */.notification-list__tabs[data-v-3db0c5bf] {\n display: flex;\n border-bottom: 1px solid var(--c-border);\n padding: 0 4px;\n}\n.notification-list__tab[data-v-3db0c5bf] {\n position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 10px 12px;\n font-size: 13px;\n color: var(--c-text-2);\n cursor: pointer;\n transition: all var(--c-transition, 0.2s ease);\n user-select: none;\n}\n.notification-list__tab[data-v-3db0c5bf]::after {\n content: \"\";\n position: absolute;\n bottom: 0;\n left: 12px;\n right: 12px;\n height: 2px;\n background: transparent;\n border-radius: 1px;\n transition: background var(--c-transition, 0.2s ease);\n}\n.notification-list__tab[data-v-3db0c5bf]:hover {\n color: var(--c-text-1);\n}\n.notification-list__tab--active[data-v-3db0c5bf] {\n color: var(--c-primary);\n font-weight: 500;\n}\n.notification-list__tab--active[data-v-3db0c5bf]::after {\n background: var(--c-primary);\n}\n.notification-list__tab-count[data-v-3db0c5bf] {\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: #f5222d;\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n.notification-list__toolbar[data-v-3db0c5bf] {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 12px;\n padding: 6px 16px;\n border-bottom: 1px solid var(--c-border);\n}\n.notification-list__scroll[data-v-3db0c5bf] {\n flex: 1;\n}\n.notification-list__skeleton[data-v-3db0c5bf] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 16px;\n}\n.notification-list__skeleton-text[data-v-3db0c5bf] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.notification-list__load-more[data-v-3db0c5bf] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 12px;\n font-size: 12px;\n color: var(--c-text-2);\n cursor: pointer;\n transition: color var(--c-transition, 0.2s ease);\n}\n.notification-list__load-more[data-v-3db0c5bf]:hover {\n color: var(--c-primary);\n}\n.notification-list__empty[data-v-3db0c5bf] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 0;\n gap: 12px;\n}\n.notification-list__empty-icon[data-v-3db0c5bf] {\n color: var(--c-text-4);\n opacity: 0.5;\n}\n.notification-list__empty-text[data-v-3db0c5bf] {\n font-size: 13px;\n color: var(--c-text-4);\n}","/* unplugin-vue-components disabled */.notification-detail[data-v-b10b0b8e] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.notification-detail__back[data-v-b10b0b8e] {\n padding: 8px 16px;\n border-bottom: 1px solid var(--c-border);\n}\n.notification-detail__header[data-v-b10b0b8e] {\n padding: 16px;\n border-bottom: 1px solid var(--c-border);\n}\n.notification-detail__title[data-v-b10b0b8e] {\n font-size: 15px;\n font-weight: 600;\n color: var(--c-text-1);\n line-height: 1.5;\n margin: 0 0 8px;\n}\n.notification-detail__meta[data-v-b10b0b8e] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n.notification-detail__time[data-v-b10b0b8e] {\n font-size: 11px;\n color: var(--c-text-4);\n}\n.notification-detail__sender[data-v-b10b0b8e] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n font-size: 12px;\n color: var(--c-text-2);\n}\n.notification-detail__content[data-v-b10b0b8e] {\n flex: 1;\n min-height: 0;\n}\n.notification-detail__body[data-v-b10b0b8e] {\n padding: 16px;\n font-size: 13px;\n line-height: 1.7;\n color: var(--c-text-1);\n word-break: break-word;\n}\n.notification-detail__body[data-v-b10b0b8e] p {\n margin: 0 0 8px;\n}\n.notification-detail__body[data-v-b10b0b8e] ul,\n.notification-detail__body[data-v-b10b0b8e] ol {\n padding-left: 20px;\n margin: 8px 0;\n}\n.notification-detail__body[data-v-b10b0b8e] li {\n margin: 4px 0;\n}\n.notification-detail__body[data-v-b10b0b8e] strong {\n font-weight: 600;\n color: var(--c-primary);\n}\n.notification-detail__footer[data-v-b10b0b8e] {\n padding: 12px 16px;\n border-top: 1px solid var(--c-border);\n display: flex;\n justify-content: flex-end;\n}","/* unplugin-vue-components disabled */.c-notification-center[data-v-a60d6896] {\n display: inline-flex;\n align-items: center;\n}\n.c-notification-center__panel[data-v-a60d6896] {\n display: flex;\n flex-direction: column;\n max-height: 560px;\n}\n.c-notification-center__header[data-v-a60d6896] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px 10px;\n border-bottom: 1px solid var(--c-border);\n}\n.c-notification-center__title[data-v-a60d6896] {\n font-size: 15px;\n font-weight: 600;\n color: var(--c-text-1);\n}\n.c-notification-center__header-extra[data-v-a60d6896] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.c-notification-center__ws-dot[data-v-a60d6896] {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n transition: background-color var(--c-transition, 0.2s ease);\n}\n.c-notification-center__ws-dot--connected[data-v-a60d6896] {\n background: #52c41a;\n box-shadow: 0 0 4px rgba(82, 196, 26, 0.5);\n}\n.c-notification-center__ws-dot--connecting[data-v-a60d6896], .c-notification-center__ws-dot--reconnecting[data-v-a60d6896] {\n background: #faad14;\n animation: status-blink-a60d6896 1s ease-in-out infinite;\n}\n.c-notification-center__ws-dot--disconnected[data-v-a60d6896] {\n background: var(--c-text-4);\n}\n@keyframes status-blink-a60d6896 {\n0%, 100% {\n opacity: 1;\n}\n50% {\n opacity: 0.3;\n}\n}\n/* ─── 切换过渡 ───────────────────────────────── */\n.slide-fade-enter-active[data-v-a60d6896] {\n transition: all 0.25s ease-out;\n}\n.slide-fade-leave-active[data-v-a60d6896] {\n transition: all 0.2s ease-in;\n}\n.slide-fade-enter-from[data-v-a60d6896] {\n opacity: 0;\n transform: translateY(8px);\n}\n.slide-fade-leave-to[data-v-a60d6896] {\n opacity: 0;\n transform: translateY(-8px);\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AChJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}