@robot-admin/naive-ui-components 0.6.8 → 0.6.11

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 (177) hide show
  1. package/README.md +277 -261
  2. package/dist/C_AudioPlayer-DKRIGhi7.css.map +1 -0
  3. package/dist/C_AudioPlayer-DlB6eNsa.css.map +1 -0
  4. package/dist/C_AudioPlayer.cjs +1 -0
  5. package/dist/C_AudioPlayer.css +283 -0
  6. package/dist/C_AudioPlayer.d.cts +2 -0
  7. package/dist/C_AudioPlayer.d.ts +2 -0
  8. package/dist/C_AudioPlayer.js +1 -0
  9. package/dist/C_AudioPlayer.js.map +1 -0
  10. package/dist/C_AudioPlayer2.js +2 -0
  11. package/dist/C_AudioPlayer2.js.map +1 -0
  12. package/dist/C_AvatarGroup-D02zci-i.css.map +1 -0
  13. package/dist/C_AvatarGroup-DatHaUlY.css.map +1 -0
  14. package/dist/C_AvatarGroup.cjs +1 -0
  15. package/dist/C_AvatarGroup.css +107 -0
  16. package/dist/C_AvatarGroup.d.cts +2 -0
  17. package/dist/C_AvatarGroup.d.ts +2 -0
  18. package/dist/C_AvatarGroup.js +1 -0
  19. package/dist/C_AvatarGroup.js.map +1 -0
  20. package/dist/C_AvatarGroup2.js +2 -0
  21. package/dist/C_AvatarGroup2.js.map +1 -0
  22. package/dist/C_Barcode.d.cts +1 -1
  23. package/dist/C_Barcode.d.ts +1 -1
  24. package/dist/{C_Breadcrumb-B5PGpP5m.css.map → C_Breadcrumb-BiH0d9AI.css.map} +1 -1
  25. package/dist/{C_Breadcrumb-Cay7qluL.css.map → C_Breadcrumb-Bqqrl8nX.css.map} +1 -1
  26. package/dist/C_Breadcrumb.css +8 -2
  27. package/dist/C_Breadcrumb.d.cts +1 -1
  28. package/dist/C_Breadcrumb.d.ts +1 -1
  29. package/dist/C_Breadcrumb.js.map +1 -1
  30. package/dist/C_Breadcrumb2.js.map +1 -1
  31. package/dist/C_Captcha.d.cts +1 -1
  32. package/dist/C_Captcha.d.ts +1 -1
  33. package/dist/C_Cascade.d.cts +1 -1
  34. package/dist/C_Cascade.d.ts +1 -1
  35. package/dist/C_Chat-CcjZdAwu.css.map +1 -0
  36. package/dist/C_Chat-Diq7tyWU.css.map +1 -0
  37. package/dist/C_Chat.cjs +1 -0
  38. package/dist/C_Chat.css +395 -0
  39. package/dist/C_Chat.d.cts +2 -0
  40. package/dist/C_Chat.d.ts +2 -0
  41. package/dist/C_Chat.js +1 -0
  42. package/dist/C_Chat.js.map +1 -0
  43. package/dist/C_Chat2.js +2 -0
  44. package/dist/C_Chat2.js.map +1 -0
  45. package/dist/C_City.d.cts +1 -1
  46. package/dist/C_City.d.ts +1 -1
  47. package/dist/C_Code.d.cts +1 -1
  48. package/dist/C_Code.d.ts +1 -1
  49. package/dist/C_ContextMenu-B3Cgz_wJ.css.map +1 -0
  50. package/dist/C_ContextMenu-u1LixF3_.css.map +1 -0
  51. package/dist/C_ContextMenu.cjs +1 -0
  52. package/dist/C_ContextMenu.css +115 -0
  53. package/dist/C_ContextMenu.d.cts +2 -0
  54. package/dist/C_ContextMenu.d.ts +2 -0
  55. package/dist/C_ContextMenu.js +1 -0
  56. package/dist/C_ContextMenu.js.map +1 -0
  57. package/dist/C_ContextMenu2.js +2 -0
  58. package/dist/C_ContextMenu2.js.map +1 -0
  59. package/dist/C_Date.d.cts +1 -1
  60. package/dist/C_Date.d.ts +1 -1
  61. package/dist/C_Editor.d.cts +1 -1
  62. package/dist/C_Editor.d.ts +1 -1
  63. package/dist/C_Guide.d.cts +1 -1
  64. package/dist/C_Guide.d.ts +1 -1
  65. package/dist/C_Icon.d.cts +1 -1
  66. package/dist/C_Icon.d.ts +1 -1
  67. package/dist/C_Icon.js.map +1 -1
  68. package/dist/C_Icon2.js +1 -1
  69. package/dist/C_Icon2.js.map +1 -1
  70. package/dist/C_Language.d.cts +1 -1
  71. package/dist/C_Language.d.ts +1 -1
  72. package/dist/C_Language.js.map +1 -1
  73. package/dist/C_Language2.js +1 -1
  74. package/dist/C_Language2.js.map +1 -1
  75. package/dist/C_Login-BkdnkBKX.css.map +1 -0
  76. package/dist/C_Login-VkMM6OJ2.css.map +1 -0
  77. package/dist/C_Login.cjs +1 -0
  78. package/dist/C_Login.css +515 -0
  79. package/dist/C_Login.d.cts +2 -0
  80. package/dist/C_Login.d.ts +2 -0
  81. package/dist/C_Login.js +1 -0
  82. package/dist/C_Login.js.map +1 -0
  83. package/dist/C_Login2.js +2 -0
  84. package/dist/C_Login2.js.map +1 -0
  85. package/dist/C_Markdown.d.cts +1 -1
  86. package/dist/C_Markdown.d.ts +1 -1
  87. package/dist/C_Menu.d.cts +1 -1
  88. package/dist/C_Menu.d.ts +1 -1
  89. package/dist/C_Progress.d.cts +1 -1
  90. package/dist/C_Progress.d.ts +1 -1
  91. package/dist/C_Steps.d.cts +1 -1
  92. package/dist/C_Steps.d.ts +1 -1
  93. package/dist/C_TagsView.d.cts +1 -1
  94. package/dist/C_TagsView.d.ts +1 -1
  95. package/dist/C_Theme.d.cts +1 -1
  96. package/dist/C_Theme.d.ts +1 -1
  97. package/dist/C_Timeline-BIvw3f41.css.map +1 -0
  98. package/dist/C_Timeline-VsDfCv4Q.css.map +1 -0
  99. package/dist/C_Timeline.cjs +1 -0
  100. package/dist/C_Timeline.css +271 -0
  101. package/dist/C_Timeline.d.cts +2 -0
  102. package/dist/C_Timeline.d.ts +2 -0
  103. package/dist/C_Timeline.js +1 -0
  104. package/dist/C_Timeline.js.map +1 -0
  105. package/dist/C_Timeline2.js +2 -0
  106. package/dist/C_Timeline2.js.map +1 -0
  107. package/dist/C_Transfer-BOB6OBqS.css.map +1 -0
  108. package/dist/C_Transfer-Dpq7ezWC.css.map +1 -0
  109. package/dist/C_Transfer.cjs +1 -0
  110. package/dist/C_Transfer.css +193 -0
  111. package/dist/C_Transfer.d.cts +2 -0
  112. package/dist/C_Transfer.d.ts +2 -0
  113. package/dist/C_Transfer.js +1 -0
  114. package/dist/C_Transfer.js.map +1 -0
  115. package/dist/C_Transfer2.js +2 -0
  116. package/dist/C_Transfer2.js.map +1 -0
  117. package/dist/C_VtableGantt.d.cts +1 -1
  118. package/dist/C_VtableGantt.d.ts +1 -1
  119. package/dist/constants.d.ts +2 -2
  120. package/dist/constants2.d.ts +2 -2
  121. package/dist/constants4.d.ts +3 -3
  122. package/dist/constants5.d.ts +2 -2
  123. package/dist/data.d.ts +1 -1
  124. package/dist/index.cjs +1 -1
  125. package/dist/index.cjs.map +1 -1
  126. package/dist/index.d.cts +48 -41
  127. package/dist/index.d.ts +48 -41
  128. package/dist/index.js +1 -1
  129. package/dist/index.js.map +1 -1
  130. package/dist/index.vue.d.ts +1 -1
  131. package/dist/index10.vue.d.ts +41 -23
  132. package/dist/index11.vue.d.ts +80 -63
  133. package/dist/index12.vue.d.ts +48 -20
  134. package/dist/index13.vue.d.ts +23 -63
  135. package/dist/index14.vue.d.ts +21 -58
  136. package/dist/index15.vue.d.ts +65 -48
  137. package/dist/index16.vue.d.ts +16 -21
  138. package/dist/index17.vue.d.ts +106 -77
  139. package/dist/index18.vue.d.ts +74 -11
  140. package/dist/index19.vue.d.ts +58 -653
  141. package/dist/index2.vue.d.ts +75 -30
  142. package/dist/index20.vue.d.ts +55 -0
  143. package/dist/index21.vue.d.ts +33 -0
  144. package/dist/index22.vue.d.ts +88 -0
  145. package/dist/index23.vue.d.ts +18 -0
  146. package/dist/index24.vue.d.ts +112 -0
  147. package/dist/index25.vue.d.ts +81 -0
  148. package/dist/index26.vue.d.ts +662 -0
  149. package/dist/index3.vue.d.ts +77 -19
  150. package/dist/index4.vue.d.ts +29 -36
  151. package/dist/index5.vue.d.ts +19 -20
  152. package/dist/index6.vue.d.ts +36 -26
  153. package/dist/index7.vue.d.ts +23 -40
  154. package/dist/index8.vue.d.ts +117 -45
  155. package/dist/index9.vue.d.ts +19 -25
  156. package/dist/resolver.cjs +1 -1
  157. package/dist/resolver.cjs.map +1 -1
  158. package/dist/resolver.d.cts +1 -1
  159. package/dist/resolver.d.ts +1 -1
  160. package/dist/resolver.js +1 -1
  161. package/dist/resolver.js.map +1 -1
  162. package/dist/style.css +1920 -21
  163. package/dist/useCollapsePanel.d.ts +1 -1
  164. package/dist/useCropperCore.d.ts +4 -4
  165. package/dist/useDraggableLayout.d.ts +8 -8
  166. package/dist/useDynamicFormState.d.ts +10 -10
  167. package/dist/useEdgeInteraction.d.ts +1 -1
  168. package/dist/useInfiniteScroll.d.ts +2 -2
  169. package/dist/useModalEdit.d.ts +2 -2
  170. package/dist/useQRCode.d.ts +4 -4
  171. package/dist/useSearchState.d.ts +2 -2
  172. package/dist/useSignatureHistory.d.ts +1 -1
  173. package/dist/useSplitResize.d.ts +5 -5
  174. package/dist/useTimeSelection.d.ts +2 -2
  175. package/dist/useTreeOperations.d.ts +6 -6
  176. package/dist/useWorkflowValidation.d.ts +1 -1
  177. package/package.json +1 -1
@@ -0,0 +1,107 @@
1
+ /* unplugin-vue-components disabled *//**
2
+ * C_AvatarGroup — 头像组组件样式
3
+ */
4
+ .c-avatar-group[data-v-8be58d5b] {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ /* ======================== 单个头像 ======================== */
8
+ /* ---- 头像图片 ---- */
9
+ /* ---- 首字母 fallback ---- */
10
+ /* ---- 状态指示点 ---- */
11
+ /* ======================== 溢出 +N ======================== */
12
+ }
13
+ .c-avatar-group.is-rtl[data-v-8be58d5b] {
14
+ flex-direction: row-reverse;
15
+ }
16
+ .c-avatar-group__item[data-v-8be58d5b] {
17
+ position: relative;
18
+ flex-shrink: 0;
19
+ border: 2px solid var(--card-color);
20
+ background: var(--card-color);
21
+ transition: transform 0.2s, z-index 0.2s, box-shadow 0.2s;
22
+ cursor: default;
23
+ z-index: 1;
24
+ }
25
+ .c-avatar-group__item.is-circle[data-v-8be58d5b] {
26
+ border-radius: 50%;
27
+ }
28
+ .c-avatar-group__item.is-square[data-v-8be58d5b] {
29
+ border-radius: 6px;
30
+ }
31
+ .c-avatar-group__item.is-clickable[data-v-8be58d5b] {
32
+ cursor: pointer;
33
+ }
34
+ .c-avatar-group__item.is-clickable[data-v-8be58d5b]:hover {
35
+ transform: translateY(-3px) scale(1.08);
36
+ z-index: 10;
37
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
38
+ }
39
+ .c-avatar-group__item[data-v-8be58d5b]:hover {
40
+ z-index: 10;
41
+ }
42
+ .c-avatar-group__img[data-v-8be58d5b] {
43
+ display: block;
44
+ width: 100%;
45
+ height: 100%;
46
+ object-fit: cover;
47
+ }
48
+ .is-circle .c-avatar-group__img[data-v-8be58d5b] {
49
+ border-radius: 50%;
50
+ }
51
+ .is-square .c-avatar-group__img[data-v-8be58d5b] {
52
+ border-radius: 4px;
53
+ }
54
+ .c-avatar-group__initials[data-v-8be58d5b] {
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ width: 100%;
59
+ height: 100%;
60
+ color: #fff;
61
+ font-weight: 600;
62
+ user-select: none;
63
+ }
64
+ .is-circle .c-avatar-group__initials[data-v-8be58d5b] {
65
+ border-radius: 50%;
66
+ }
67
+ .is-square .c-avatar-group__initials[data-v-8be58d5b] {
68
+ border-radius: 4px;
69
+ }
70
+ .c-avatar-group__status[data-v-8be58d5b] {
71
+ position: absolute;
72
+ bottom: 0;
73
+ right: 0;
74
+ border-radius: 50%;
75
+ border: 2px solid var(--card-color);
76
+ z-index: 2;
77
+ }
78
+ .c-avatar-group__overflow[data-v-8be58d5b] {
79
+ position: relative;
80
+ flex-shrink: 0;
81
+ display: flex;
82
+ align-items: center;
83
+ justify-content: center;
84
+ border: 2px solid var(--card-color);
85
+ background: color-mix(in srgb, var(--primary-color) 12%, var(--card-color));
86
+ color: var(--primary-color);
87
+ font-weight: 700;
88
+ z-index: 0;
89
+ transition: transform 0.2s, box-shadow 0.2s;
90
+ }
91
+ .c-avatar-group__overflow.is-circle[data-v-8be58d5b] {
92
+ border-radius: 50%;
93
+ }
94
+ .c-avatar-group__overflow.is-square[data-v-8be58d5b] {
95
+ border-radius: 6px;
96
+ }
97
+ .c-avatar-group__overflow.is-clickable[data-v-8be58d5b] {
98
+ cursor: pointer;
99
+ }
100
+ .c-avatar-group__overflow.is-clickable[data-v-8be58d5b]:hover {
101
+ transform: translateY(-3px) scale(1.08);
102
+ z-index: 10;
103
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
104
+ background: color-mix(in srgb, var(--primary-color) 20%, var(--card-color));
105
+ }
106
+
107
+ /*# sourceMappingURL=C_AvatarGroup-D02zci-i.css.map*/
@@ -0,0 +1,2 @@
1
+ import { a as STATUS_COLOR_MAP, i as DEFAULT_AVATAR_GROUP_PROPS, n as AvatarGroupProps, o as getInitials, r as AvatarItem, s as nameToColor, t as _default } from "./index3.vue.js";
2
+ export { type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS, STATUS_COLOR_MAP, getInitials, nameToColor };
@@ -0,0 +1,2 @@
1
+ import { a as STATUS_COLOR_MAP, i as DEFAULT_AVATAR_GROUP_PROPS, n as AvatarGroupProps, o as getInitials, r as AvatarItem, s as nameToColor, t as _default } from "./index3.vue.js";
2
+ export { type AvatarGroupProps, type AvatarItem, _default as C_AvatarGroup, DEFAULT_AVATAR_GROUP_PROPS, STATUS_COLOR_MAP, getInitials, nameToColor };
@@ -0,0 +1 @@
1
+ import{a as e,i as t,n,r,t as i}from"./C_AvatarGroup2.js";export{i as C_AvatarGroup,n as DEFAULT_AVATAR_GROUP_PROPS,r as STATUS_COLOR_MAP,t as getInitials,e as nameToColor};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_AvatarGroup.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","/* unplugin-vue-components disabled */<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./export-helper.js";import{NTooltip as t}from"naive-ui";import{Fragment as n,computed as r,createBlock as i,createCommentVNode as a,createElementBlock as o,createElementVNode as s,createTextVNode as c,defineComponent as l,normalizeClass as u,normalizeStyle as d,openBlock as f,renderList as p,toDisplayString as m,unref as h,withCtx as g}from"vue";const _={max:5,size:40,overlap:-10,shape:`circle`,showStatus:!0,showTooltip:!0,clickable:!1,overflowClickable:!0,direction:`ltr`},v={online:`#18a058`,offline:`#909399`,busy:`#e53e3e`,away:`#f0a020`};function y(e){if(!e)return`?`;let t=e.trim().split(/\s+/);return t.length>=2?(t[0][0]+t[1][0]).toUpperCase():/[\u4E00-\u9FFF]/.test(e)?e.slice(-1):e.slice(0,2).toUpperCase()}function b(e){let t=[`#6366f1`,`#8b5cf6`,`#a855f7`,`#d946ef`,`#ec4899`,`#f43f5e`,`#ef4444`,`#f97316`,`#eab308`,`#84cc16`,`#22c55e`,`#14b8a6`,`#06b6d4`,`#0ea5e9`,`#3b82f6`,`#6d28d9`],n=0;for(let t=0;t<e.length;t++)n=e.charCodeAt(t)+(n*31|0);return t[Math.abs(n)%t.length]}const x=[`onClick`],S=[`src`,`alt`],C={style:{"max-width":`200px`}};var w=e(l({__name:`index`,props:{items:{},max:{default:_.max},size:{default:_.size},overlap:{default:_.overlap},shape:{default:_.shape},showStatus:{type:Boolean,default:_.showStatus},showTooltip:{type:Boolean,default:_.showTooltip},clickable:{type:Boolean,default:_.clickable},overflowClickable:{type:Boolean,default:_.overflowClickable},direction:{default:_.direction}},emits:[`itemClick`,`overflowClick`],setup(e,{emit:l}){let w=e,T=l,E=r(()=>({..._,...w})),D=r(()=>{let e=E.value.max;return w.items.length>e?w.items.slice(0,e):w.items}),O=r(()=>{let e=E.value.max;return w.items.length>e?w.items.slice(e):[]}),k=r(()=>O.value.length),A=r(()=>`${Math.round(E.value.size*.38)}px`);function j(e){let t=E.value.size,n=E.value.overlap;return{width:`${t}px`,height:`${t}px`,marginLeft:e===0?`0`:`${n}px`}}let M=r(()=>{let e=E.value.size,t=E.value.overlap;return{width:`${e}px`,height:`${e}px`,marginLeft:`${t}px`,fontSize:`${Math.round(e*.32)}px`}});function N(e){let t=Math.max(8,Math.round(E.value.size*.24));return{width:`${t}px`,height:`${t}px`,backgroundColor:v[e]??v.offline}}return(e,r)=>{let l=t;return f(),o(`div`,{class:u([`c-avatar-group`,{"is-rtl":E.value.direction===`rtl`}])},[(f(!0),o(n,null,p(D.value,(e,t)=>(f(),i(l,{key:e.id,disabled:!E.value.showTooltip,placement:`top`},{trigger:g(()=>[s(`div`,{class:u([`c-avatar-group__item`,[`is-${E.value.shape}`,{"is-clickable":E.value.clickable}]]),style:d(j(t)),onClick:t=>E.value.clickable&&T(`itemClick`,e)},[e.src?(f(),o(`img`,{key:0,src:e.src,alt:e.name,class:`c-avatar-group__img`},null,8,S)):(f(),o(`div`,{key:1,class:`c-avatar-group__initials`,style:d({background:h(b)(e.name),fontSize:A.value})},m(h(y)(e.name)),5)),E.value.showStatus&&e.status?(f(),o(`span`,{key:2,class:`c-avatar-group__status`,style:d(N(e.status))},null,4)):a(`v-if`,!0)],14,x)]),default:g(()=>[c(` `+m(e.tooltip??e.name),1)]),_:2},1032,[`disabled`]))),128)),a(` 溢出 +N `),k.value>0?(f(),i(l,{key:0,placement:`top`},{trigger:g(()=>[s(`div`,{class:u([`c-avatar-group__overflow`,[`is-${E.value.shape}`,{"is-clickable":E.value.overflowClickable}]]),style:d(M.value),onClick:r[0]||=e=>E.value.overflowClickable&&T(`overflowClick`,O.value)},` +`+m(k.value),7)]),default:g(()=>[s(`div`,C,[(f(!0),o(n,null,p(O.value,e=>(f(),o(`div`,{key:e.id,style:{"line-height":`1.6`}},m(e.name),1))),128))])]),_:1})):a(`v-if`,!0)],2)}}}),[[`__scopeId`,`data-v-8be58d5b`]]);export{b as a,y as i,_ as n,v as r,w as t};
2
+ //# sourceMappingURL=C_AvatarGroup2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_AvatarGroup2.js","names":[],"sources":["../src/components/C_AvatarGroup/types.ts","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue","../src/components/C_AvatarGroup/index.vue"],"sourcesContent":["/**\n * @Description: 头像组组件类型定义\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n */\n\n/** 单个头像数据 */\nexport interface AvatarItem {\n /** 唯一标识 */\n id: string | number\n /** 头像图片 URL */\n src?: string\n /** 姓名(用于首字母 fallback 和 tooltip) */\n name: string\n /** 悬浮提示(默认取 name) */\n tooltip?: string\n /** 在线状态 */\n status?: 'online' | 'offline' | 'busy' | 'away'\n /** 额外数据 */\n extra?: Record<string, unknown>\n}\n\n/** 组件 Props */\nexport interface AvatarGroupProps {\n /** 头像数据列表 */\n items: AvatarItem[]\n /** 最多显示数量(超出 +N) */\n max?: number\n /** 头像尺寸 (px) */\n size?: number\n /** 头像间重叠偏移量 (px),负值表示堆叠 */\n overlap?: number\n /** 形状 */\n shape?: 'circle' | 'square'\n /** 是否显示状态指示点 */\n showStatus?: boolean\n /** 是否显示悬浮提示 */\n showTooltip?: boolean\n /** 是否可点击 */\n clickable?: boolean\n /** +N 溢出按钮是否可点击 */\n overflowClickable?: boolean\n /** 堆叠方向 */\n direction?: 'ltr' | 'rtl'\n}\n\n/** 默认 Props */\nexport const DEFAULT_AVATAR_GROUP_PROPS: Partial<AvatarGroupProps> = {\n max: 5,\n size: 40,\n overlap: -10,\n shape: 'circle',\n showStatus: true,\n showTooltip: true,\n clickable: false,\n overflowClickable: true,\n direction: 'ltr',\n}\n\n/** 状态颜色映射 */\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n online: '#18a058',\n offline: '#909399',\n busy: '#e53e3e',\n away: '#f0a020',\n}\n\n/** 从名字中提取首字母 */\nexport function getInitials(name: string): string {\n if (!name) return '?'\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n // 中文直接取最后一个字\n if (/[\\u4E00-\\u9FFF]/.test(name)) return name.slice(-1)\n return name.slice(0, 2).toUpperCase()\n}\n\n/** 根据名字生成稳定的背景色 */\nexport function nameToColor(name: string): string {\n const palette = [\n '#6366f1',\n '#8b5cf6',\n '#a855f7',\n '#d946ef',\n '#ec4899',\n '#f43f5e',\n '#ef4444',\n '#f97316',\n '#eab308',\n '#84cc16',\n '#22c55e',\n '#14b8a6',\n '#06b6d4',\n '#0ea5e9',\n '#3b82f6',\n '#6d28d9',\n ]\n let hash = 0\n for (let i = 0; i < name.length; i++) {\n hash = name.charCodeAt(i) + ((hash * 31) | 0)\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","/* unplugin-vue-components disabled */<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n","<!--\n * @Description: 头像组组件\n * Copyright (c) 2026 by CHENY, All Rights Reserved 😎.\n-->\n<template>\n <div\n class=\"c-avatar-group\"\n :class=\"{ 'is-rtl': mergedProps.direction === 'rtl' }\"\n >\n <NTooltip\n v-for=\"(item, idx) in visibleItems\"\n :key=\"item.id\"\n :disabled=\"!mergedProps.showTooltip\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__item\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.clickable },\n ]\"\n :style=\"itemStyle(idx)\"\n @click=\"mergedProps.clickable && emit('itemClick', item)\"\n >\n <img\n v-if=\"item.src\"\n :src=\"item.src\"\n :alt=\"item.name\"\n class=\"c-avatar-group__img\"\n />\n <div\n v-else\n class=\"c-avatar-group__initials\"\n :style=\"{\n background: nameToColor(item.name),\n fontSize: initialsFontSize,\n }\"\n >\n {{ getInitials(item.name) }}\n </div>\n\n <span\n v-if=\"mergedProps.showStatus && item.status\"\n class=\"c-avatar-group__status\"\n :style=\"statusStyle(item.status)\"\n />\n </div>\n </template>\n {{ item.tooltip ?? item.name }}\n </NTooltip>\n\n <!-- 溢出 +N -->\n <NTooltip\n v-if=\"overflowCount > 0\"\n placement=\"top\"\n >\n <template #trigger>\n <div\n class=\"c-avatar-group__overflow\"\n :class=\"[\n `is-${mergedProps.shape}`,\n { 'is-clickable': mergedProps.overflowClickable },\n ]\"\n :style=\"overflowStyle\"\n @click=\"\n mergedProps.overflowClickable && emit('overflowClick', hiddenItems)\n \"\n >\n +{{ overflowCount }}\n </div>\n </template>\n <div style=\"max-width: 200px\">\n <div\n v-for=\"h in hiddenItems\"\n :key=\"h.id\"\n style=\"line-height: 1.6\"\n >\n {{ h.name }}\n </div>\n </div>\n </NTooltip>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import {\n DEFAULT_AVATAR_GROUP_PROPS,\n getInitials,\n nameToColor,\n STATUS_COLOR_MAP,\n type AvatarGroupProps,\n type AvatarItem,\n } from './types'\n\n const props = withDefaults(\n defineProps<{\n items: AvatarGroupProps['items']\n max?: number\n size?: number\n overlap?: number\n shape?: AvatarGroupProps['shape']\n showStatus?: boolean\n showTooltip?: boolean\n clickable?: boolean\n overflowClickable?: boolean\n direction?: AvatarGroupProps['direction']\n }>(),\n {\n max: DEFAULT_AVATAR_GROUP_PROPS.max,\n size: DEFAULT_AVATAR_GROUP_PROPS.size,\n overlap: DEFAULT_AVATAR_GROUP_PROPS.overlap,\n shape: DEFAULT_AVATAR_GROUP_PROPS.shape,\n showStatus: DEFAULT_AVATAR_GROUP_PROPS.showStatus,\n showTooltip: DEFAULT_AVATAR_GROUP_PROPS.showTooltip,\n clickable: DEFAULT_AVATAR_GROUP_PROPS.clickable,\n overflowClickable: DEFAULT_AVATAR_GROUP_PROPS.overflowClickable,\n direction: DEFAULT_AVATAR_GROUP_PROPS.direction,\n }\n )\n\n const emit = defineEmits<{\n itemClick: [item: AvatarItem]\n overflowClick: [hiddenItems: AvatarItem[]]\n }>()\n\n const mergedProps = computed(() => ({\n ...DEFAULT_AVATAR_GROUP_PROPS,\n ...props,\n }))\n\n const visibleItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(0, max) : props.items\n })\n\n const hiddenItems = computed(() => {\n const max = mergedProps.value.max!\n return props.items.length > max ? props.items.slice(max) : []\n })\n\n const overflowCount = computed(() => hiddenItems.value.length)\n\n const initialsFontSize = computed(\n () => `${Math.round(mergedProps.value.size! * 0.38)}px`\n )\n\n /** 计算头像项定位样式 */\n function itemStyle(idx: number) {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: idx === 0 ? '0' : `${overlap}px`,\n }\n }\n\n const overflowStyle = computed(() => {\n const s = mergedProps.value.size!\n const overlap = mergedProps.value.overlap!\n return {\n width: `${s}px`,\n height: `${s}px`,\n marginLeft: `${overlap}px`,\n fontSize: `${Math.round(s * 0.32)}px`,\n }\n })\n\n /** 计算状态指示点样式 */\n function statusStyle(status: string) {\n const dotSize = Math.max(8, Math.round(mergedProps.value.size! * 0.24))\n return {\n width: `${dotSize}px`,\n height: `${dotSize}px`,\n backgroundColor: STATUS_COLOR_MAP[status] ?? STATUS_COLOR_MAP.offline,\n }\n }\n</script>\n\n<style scoped lang=\"scss\">\n @use './index.scss';\n</style>\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index2.vue.js";
1
+ import { t as _default } from "./index4.vue.js";
2
2
  export { _default as C_Barcode };
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index2.vue.js";
1
+ import { t as _default } from "./index4.vue.js";
2
2
  export { _default as C_Barcode };
@@ -1 +1 @@
1
- {"version":3,"file":"C_Breadcrumb-B5PGpP5m.css","names":[],"sources":["../src/components/C_Breadcrumb/index.vue?vue&type=style&index=0&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-breadcrumb {\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n display: flex;\n align-items: center;\n height: 100%;\n}\n.c-breadcrumb__trigger, .c-breadcrumb__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n}\n.c-breadcrumb .c-icon {\n flex-shrink: 0;\n}\n.c-breadcrumb .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\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"}
1
+ {"version":3,"file":"C_Breadcrumb-BiH0d9AI.css","names":[],"sources":["../src/components/C_Breadcrumb/index.vue?vue&type=style&index=0&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-breadcrumb {\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n display: flex;\n align-items: center;\n height: 100%;\n}\n.c-breadcrumb__trigger, .c-breadcrumb__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n}\n.c-breadcrumb .c-icon {\n flex-shrink: 0;\n}\n.c-breadcrumb .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n}\n.c-breadcrumb .n-breadcrumb-item .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\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"}
@@ -1 +1 @@
1
- {"version":3,"file":"C_Breadcrumb-Cay7qluL.css","names":[],"sources":["../src/components/C_Breadcrumb/index.vue?vue&type=style&index=0&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-breadcrumb {\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n display: flex;\n align-items: center;\n height: 100%;\n}\n.c-breadcrumb__trigger, .c-breadcrumb__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n}\n.c-breadcrumb .c-icon {\n flex-shrink: 0;\n}\n.c-breadcrumb .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\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"}
1
+ {"version":3,"file":"C_Breadcrumb-Bqqrl8nX.css","names":[],"sources":["../src/components/C_Breadcrumb/index.vue?vue&type=style&index=0&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled */.c-breadcrumb {\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n display: flex;\n align-items: center;\n height: 100%;\n}\n.c-breadcrumb__trigger, .c-breadcrumb__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n}\n.c-breadcrumb .c-icon {\n flex-shrink: 0;\n}\n.c-breadcrumb .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n}\n.c-breadcrumb .n-breadcrumb-item .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\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"}
@@ -17,9 +17,15 @@
17
17
  .c-breadcrumb .c-icon {
18
18
  flex-shrink: 0;
19
19
  }
20
- .c-breadcrumb .n-breadcrumb-item__separator {
20
+ .c-breadcrumb .n-breadcrumb-item {
21
+ display: inline-flex !important;
22
+ align-items: center;
23
+ }
24
+ .c-breadcrumb .n-breadcrumb-item .n-breadcrumb-item__separator {
21
25
  display: inline-flex;
22
26
  align-items: center;
27
+ line-height: 1;
28
+ margin-top: -4px;
23
29
  }
24
30
 
25
- /*# sourceMappingURL=C_Breadcrumb-B5PGpP5m.css.map*/
31
+ /*# sourceMappingURL=C_Breadcrumb-BiH0d9AI.css.map*/
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index3.vue.js";
1
+ import { t as _default } from "./index5.vue.js";
2
2
  export { _default as C_Breadcrumb };
@@ -1,3 +1,3 @@
1
1
  import "./menuAdapter.js";
2
- import { t as _default } from "./index3.vue.js";
2
+ import { t as _default } from "./index5.vue.js";
3
3
  export { _default as C_Breadcrumb };
@@ -1 +1 @@
1
- {"version":3,"file":"C_Breadcrumb.js","names":["iconSize","showIcon"],"sources":["../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n","<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n"],"mappings":"6WE6EE,IAAM,EAAQ,EAuBR,EAAO,EAKP,GAAA,EAAA,EAAA,WAAiB,CAEjB,EAAe,GACnB,EAAM,eAAiB,EAAM,eAAe,EAAM,CAAG,EAGjD,GAAA,EAAA,EAAA,cACG,EAAM,QACV,OAAQ,GAAgB,EAAO,MAAM,MAAK,CAC1C,IAAK,IAAiB,CACrB,IAAK,EAAO,KACZ,MAAO,EAAa,EAAO,KAAK,OAAS,GAAc,CACvD,KAAM,EAAO,KAAK,KAClB,SAAU,EAAO,UAAU,OACvB,EAAO,SAAS,IAAK,IAAgB,CACnC,IAAK,EAAM,KACX,MAAO,EAAa,EAAM,MAAM,OAAS,GAAc,CACvD,GAAI,EAAM,UAAU,QAAU,CAC5B,SAAU,EAAM,SAAS,IAAK,IAAqB,CACjD,IAAK,EAAW,KAChB,MAAO,EAAa,EAAW,MAAM,OAAS,GAAc,CAC7D,EAAE,CACJ,CACF,EAAC,CACF,EAAE,CACP,EAAC,CACL,CAEK,GAAA,EAAA,EAAA,cACE,EAAM,OAAS,EAAe,MACtC,CAEM,EAAgB,GAAgB,CACpC,EAAK,SAAU,EAAG,uHAxEd,MAAA,CAvCJ,MAAM,8BACL,OAAA,EAAA,EAAA,gBAAK,+BAAyCA,EAAAA,SAAQ,4BAAqC,KAAK,IAAI,KAAK,MAAMA,EAAAA,SAAQ,EAAA,CAAA,EAAA,CAAA,0BAqC1G,EAAA,KAAA,2BA9B8B,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBA6BxB,EAAA,SAAA,MAAA,EAAA,EAAA,YA7BQ,EAAA,OAAhB,EAAM,yCA6BE,EAAA,CA5Bf,IAAK,EAAK,CAAA,2BAkBb,CAfU,EAAK,UAAU,SAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAYX,EAAA,OAXT,QAAS,EAAK,SACd,SAAQ,8BASH,EAAA,EAAA,EAAA,oBAAA,MAPN,EAOM,CALIC,EAAAA,WAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,cAAAA,EAAAA,EAAAA,OAGN,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,6FACP,KAAA,EAAA,EAAA,iBACC,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,qEAcV,OAAA,OATL,MAAM,qBACL,QAAK,GAAE,EAAa,EAAK,IAAG,GAGrBC,EAAAA,WAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,cAAAA,EAAAA,EAAAA,OAGN,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,6FACP,KAAA,EAAA,EAAA,iBACC,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,EAAA,EAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"C_Breadcrumb.js","names":["iconSize","showIcon"],"sources":["../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n","<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n"],"mappings":"6WE6EE,IAAM,EAAQ,EAuBR,EAAO,EAKP,GAAA,EAAA,EAAA,WAAiB,CAEjB,EAAe,GACnB,EAAM,eAAiB,EAAM,eAAe,EAAM,CAAG,EAGjD,GAAA,EAAA,EAAA,cACG,EAAM,QACV,OAAQ,GAAgB,EAAO,MAAM,MAAK,CAC1C,IAAK,IAAiB,CACrB,IAAK,EAAO,KACZ,MAAO,EAAa,EAAO,KAAK,OAAS,GAAc,CACvD,KAAM,EAAO,KAAK,KAClB,SAAU,EAAO,UAAU,OACvB,EAAO,SAAS,IAAK,IAAgB,CACnC,IAAK,EAAM,KACX,MAAO,EAAa,EAAM,MAAM,OAAS,GAAc,CACvD,GAAI,EAAM,UAAU,QAAU,CAC5B,SAAU,EAAM,SAAS,IAAK,IAAqB,CACjD,IAAK,EAAW,KAChB,MAAO,EAAa,EAAW,MAAM,OAAS,GAAc,CAC7D,EAAE,CACJ,CACF,EAAC,CACF,EAAE,CACP,EAAC,CACL,CAEK,GAAA,EAAA,EAAA,cACE,EAAM,OAAS,EAAe,MACtC,CAEM,EAAgB,GAAgB,CACpC,EAAK,SAAU,EAAG,uHAxEd,MAAA,CAvCJ,MAAM,8BACL,OAAA,EAAA,EAAA,gBAAK,+BAAyCA,EAAAA,SAAQ,4BAAqC,KAAK,IAAI,KAAK,MAAMA,EAAAA,SAAQ,EAAA,CAAA,EAAA,CAAA,0BAqC1G,EAAA,KAAA,2BA9B8B,GAAA,EAAA,EAAA,WAAA,GAAA,EAAA,EAAA,EAAA,oBA6BxB,EAAA,SAAA,MAAA,EAAA,EAAA,YA7BQ,EAAA,OAAhB,EAAM,yCA6BE,EAAA,CA5Bf,IAAK,EAAK,CAAA,2BAkBb,CAfU,EAAK,UAAU,SAAA,EAAA,EAAA,YAAA,EAAA,EAAA,EAAA,aAYX,EAAA,OAXT,QAAS,EAAK,SACd,SAAQ,8BASH,EAAA,EAAA,EAAA,oBAAA,MAPN,EAOM,CALIC,EAAAA,WAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,cAAAA,EAAAA,EAAAA,OAGN,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,6FACP,KAAA,EAAA,EAAA,iBACC,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,qEAcV,OAAA,OATL,MAAM,qBACL,QAAK,GAAE,EAAa,EAAK,IAAG,GAGrBC,EAAAA,WAAAA,EAAAA,EAAAA,YAAAA,EAAAA,EAAAA,EAAAA,cAAAA,EAAAA,EAAAA,OAGN,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,6FACP,KAAA,EAAA,EAAA,iBACC,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,EAAA,EAAA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"C_Breadcrumb2.js","names":["iconSize","showIcon"],"sources":["../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n","<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符垂直对齐偏移\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n }\n }\n</style>\n"],"mappings":"opBE6EE,IAAM,EAAQ,EAuBR,EAAO,EAKP,EAAQ,GAAS,CAEjB,EAAe,GACnB,EAAM,eAAiB,EAAM,eAAe,EAAM,CAAG,EAGjD,EAAiB,MACd,EAAM,QACV,OAAQ,GAAgB,EAAO,MAAM,MAAK,CAC1C,IAAK,IAAiB,CACrB,IAAK,EAAO,KACZ,MAAO,EAAa,EAAO,KAAK,OAAS,GAAc,CACvD,KAAM,EAAO,KAAK,KAClB,SAAU,EAAO,UAAU,OACvB,EAAO,SAAS,IAAK,IAAgB,CACnC,IAAK,EAAM,KACX,MAAO,EAAa,EAAM,MAAM,OAAS,GAAc,CACvD,GAAI,EAAM,UAAU,QAAU,CAC5B,SAAU,EAAM,SAAS,IAAK,IAAqB,CACjD,IAAK,EAAW,KAChB,MAAO,EAAa,EAAW,MAAM,OAAS,GAAc,CAC7D,EAAE,CACJ,CACF,EAAC,CACF,EAAE,CACP,EAAC,CACL,CAEK,EAAkB,MAChB,EAAM,OAAS,EAAe,MACtC,CAEM,EAAgB,GAAgB,CACpC,EAAK,SAAU,EAAG,2CAhHpB,EAwCM,MAAA,CAvCJ,MAAM,8BACL,MAAK,EAAA,+BAAyCA,EAAAA,SAAQ,4BAAqC,KAAK,IAAI,KAAK,MAAMA,EAAAA,SAAQ,EAAA,CAAA,EAAA,CAAA,QAKxH,EAgCc,EAAA,KAAA,eA9B8B,EAAA,EAAA,GAAA,CAD1C,EA8BkB,EAAA,KAAA,EA7BQ,EAAA,OAAhB,EAAM,SADhB,EA8BkB,EAAA,CA5Bf,IAAK,EAAK,CAAA,eAkBb,CAfU,EAAK,UAAU,QAAA,GAAA,CADvB,EAaY,EAAA,OAXT,QAAS,EAAK,SACd,SAAQ,kBASH,CAPN,EAOM,MAPN,EAOM,CALIC,EAAAA,UAAAA,GAAAA,CADR,EAIE,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,kDACP,IACF,EAAG,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,8BAGjB,EAWO,OAAA,OATL,MAAM,qBACL,QAAK,GAAE,EAAa,EAAK,IAAG,GAGrBC,EAAAA,UAAAA,GAAAA,CADR,EAIE,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,kDACP,IACF,EAAG,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,EAAA,EAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"C_Breadcrumb2.js","names":["iconSize","showIcon"],"sources":["../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue","../src/components/C_Breadcrumb/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n","<!--\n * @Description: 通用面包屑组件 — 基于 NBreadcrumb 的路由面包屑导航\n *\n * 支持两种模式:\n * 1. 自动模式(默认)— 从 `route.matched` 自动生成面包屑\n * 2. 手动模式 — 传入 `items` 完全自定义\n *\n * @example 自动模式(零配置)\n * ```vue\n * <C_Breadcrumb\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 手动模式\n * ```vue\n * <C_Breadcrumb\n * :items=\"customBreadcrumbs\"\n * @select=\"handleSelect\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <div\n class=\"c-breadcrumb flex-1 min-w-0\"\n :style=\"{\n '--c-breadcrumb-icon-size': `${iconSize}px`,\n '--c-breadcrumb-gap': `${Math.max(Math.round(iconSize / 4), 2)}px`,\n }\"\n >\n <NBreadcrumb>\n <NBreadcrumbItem\n v-for=\"(item, index) in breadcrumbItems\"\n :key=\"index\"\n >\n <NDropdown\n v-if=\"item.children?.length\"\n :options=\"item.children\"\n @select=\"handleSelect\"\n >\n <div class=\"c-breadcrumb__trigger\">\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </div>\n </NDropdown>\n <span\n v-else\n class=\"c-breadcrumb__link\"\n @click=\"handleSelect(item.key)\"\n >\n <C_Icon\n v-if=\"showIcon\"\n :name=\"item.icon\"\n :size=\"iconSize\"\n />\n {{ item.label }}\n </span>\n </NBreadcrumbItem>\n </NBreadcrumb>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useRoute } from 'vue-router'\n import { C_Icon } from '../C_Icon'\n import type { BreadcrumbItem } from '../_shared'\n\n defineOptions({ name: 'C_Breadcrumb' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 手动传入面包屑数据\n * 不传时自动从 `route.matched` 生成(零配置)\n */\n items?: BreadcrumbItem[]\n /** 是否显示图标 */\n showIcon?: boolean\n /** 图标大小 (px),默认 16 */\n iconSize?: number\n /**\n * 标签文本格式化函数(用于 i18n)\n * 仅在自动模式下生效\n */\n labelFormatter?: (label: string) => string\n }>(),\n {\n showIcon: true,\n iconSize: 16,\n }\n )\n\n const emit = defineEmits<{\n /** 面包屑项被选中(返回路径 key) */\n select: [path: string]\n }>()\n\n const route = useRoute()\n\n const formatLabel = (title: string): string =>\n props.labelFormatter ? props.labelFormatter(title) : title\n\n /** 从 route.matched 自动生成面包屑 */\n const autoBreadcrumb = computed<BreadcrumbItem[]>(() => {\n return route.matched\n .filter((record: any) => record.meta?.title)\n .map((record: any) => ({\n key: record.path,\n label: formatLabel((record.meta.title || '') as string),\n icon: record.meta.icon as string | undefined,\n children: record.children?.length\n ? record.children.map((child: any) => ({\n key: child.path,\n label: formatLabel((child.meta?.title || '') as string),\n ...(child.children?.length && {\n children: child.children.map((grandChild: any) => ({\n key: grandChild.path,\n label: formatLabel((grandChild.meta?.title || '') as string),\n })),\n }),\n }))\n : [],\n }))\n })\n\n const breadcrumbItems = computed<BreadcrumbItem[]>(\n () => props.items ?? autoBreadcrumb.value\n )\n\n const handleSelect = (key: string) => {\n emit('select', key)\n }\n</script>\n\n<style lang=\"scss\">\n .c-breadcrumb {\n // 暴露 CSS 变量,方便主项目覆盖\n --c-breadcrumb-icon-size: 16px;\n --c-breadcrumb-gap: 4px;\n --c-breadcrumb-font-size: inherit;\n\n display: flex;\n align-items: center;\n height: 100%;\n\n &__trigger,\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--c-breadcrumb-gap);\n font-size: var(--c-breadcrumb-font-size);\n line-height: 1;\n cursor: pointer;\n }\n\n // 确保 C_Icon 在面包屑中尺寸一致\n .c-icon {\n flex-shrink: 0;\n }\n\n // 修复分隔符 \"/\" 与文本/图标垂直居中对齐\n // 原因:Naive UI 分隔符默认 line-height (~1.4) 导致 \"/\" 基线偏低\n .n-breadcrumb-item {\n display: inline-flex !important;\n align-items: center;\n\n .n-breadcrumb-item__separator {\n display: inline-flex;\n align-items: center;\n line-height: 1;\n margin-top: -4px;\n }\n }\n }\n</style>\n"],"mappings":"opBE6EE,IAAM,EAAQ,EAuBR,EAAO,EAKP,EAAQ,GAAS,CAEjB,EAAe,GACnB,EAAM,eAAiB,EAAM,eAAe,EAAM,CAAG,EAGjD,EAAiB,MACd,EAAM,QACV,OAAQ,GAAgB,EAAO,MAAM,MAAK,CAC1C,IAAK,IAAiB,CACrB,IAAK,EAAO,KACZ,MAAO,EAAa,EAAO,KAAK,OAAS,GAAc,CACvD,KAAM,EAAO,KAAK,KAClB,SAAU,EAAO,UAAU,OACvB,EAAO,SAAS,IAAK,IAAgB,CACnC,IAAK,EAAM,KACX,MAAO,EAAa,EAAM,MAAM,OAAS,GAAc,CACvD,GAAI,EAAM,UAAU,QAAU,CAC5B,SAAU,EAAM,SAAS,IAAK,IAAqB,CACjD,IAAK,EAAW,KAChB,MAAO,EAAa,EAAW,MAAM,OAAS,GAAc,CAC7D,EAAE,CACJ,CACF,EAAC,CACF,EAAE,CACP,EAAC,CACL,CAEK,EAAkB,MAChB,EAAM,OAAS,EAAe,MACtC,CAEM,EAAgB,GAAgB,CACpC,EAAK,SAAU,EAAG,2CAhHpB,EAwCM,MAAA,CAvCJ,MAAM,8BACL,MAAK,EAAA,+BAAyCA,EAAAA,SAAQ,4BAAqC,KAAK,IAAI,KAAK,MAAMA,EAAAA,SAAQ,EAAA,CAAA,EAAA,CAAA,QAKxH,EAgCc,EAAA,KAAA,eA9B8B,EAAA,EAAA,GAAA,CAD1C,EA8BkB,EAAA,KAAA,EA7BQ,EAAA,OAAhB,EAAM,SADhB,EA8BkB,EAAA,CA5Bf,IAAK,EAAK,CAAA,eAkBb,CAfU,EAAK,UAAU,QAAA,GAAA,CADvB,EAaY,EAAA,OAXT,QAAS,EAAK,SACd,SAAQ,kBASH,CAPN,EAOM,MAPN,EAOM,CALIC,EAAAA,UAAAA,GAAAA,CADR,EAIE,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,kDACP,IACF,EAAG,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,8BAGjB,EAWO,OAAA,OATL,MAAM,qBACL,QAAK,GAAE,EAAa,EAAK,IAAG,GAGrBC,EAAAA,UAAAA,GAAAA,CADR,EAIE,EAAA,EAAA,CAAA,OAFC,KAAM,EAAK,KACX,KAAMD,EAAAA,kDACP,IACF,EAAG,EAAK,MAAK,CAAA,EAAA,CAAA,CAAA,EAAA,EAAA,EAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index4.vue.js";
1
+ import { t as _default } from "./index6.vue.js";
2
2
  export { _default as C_Captcha };
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./index4.vue.js";
1
+ import { t as _default } from "./index6.vue.js";
2
2
  export { _default as C_Captcha };
@@ -1,2 +1,2 @@
1
- import { n as _default, t as CascadeItem } from "./index5.vue.js";
1
+ import { n as _default, t as CascadeItem } from "./index7.vue.js";
2
2
  export { _default as C_Cascade, type CascadeItem };
@@ -1,2 +1,2 @@
1
- import { n as _default, t as CascadeItem } from "./index5.vue.js";
1
+ import { n as _default, t as CascadeItem } from "./index7.vue.js";
2
2
  export { _default as C_Cascade, type CascadeItem };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Chat-CcjZdAwu.css","names":[],"sources":["../src/components/C_Chat/index.vue?vue&type=style&index=0&scoped=2bbae884&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* ─── CSS 变量(基于项目主题变量,自动适配明暗) ───────────────────────── */\n.c-chat[data-v-2bbae884] {\n --chat-bg: var(--card-color);\n --chat-sidebar-bg: var(--body-color);\n --chat-sidebar-width: 280px;\n --chat-header-bg: var(--card-color);\n --chat-header-height: 56px;\n --chat-input-bg: var(--body-color);\n --chat-input-height: 56px;\n --chat-bubble-self: var(--primary-color);\n --chat-bubble-other: var(--body-color);\n --chat-bubble-system: transparent;\n --chat-text-primary: var(--app-text-primary);\n --chat-text-secondary: var(--text-color-3);\n --chat-text-self: #fff;\n --chat-border: var(--border-color);\n --chat-radius: 12px;\n --chat-avatar-size: 36px;\n --chat-scrollbar-thumb: var(--border-color);\n display: flex;\n width: 100%;\n height: 100%;\n min-height: 0;\n border-radius: var(--chat-radius);\n overflow: hidden;\n background: var(--chat-bg);\n color: var(--chat-text-primary);\n font-size: 14px;\n border: 1px solid var(--chat-border);\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);\n}\n\n/* ─── 联系人侧栏 ──────────────────────────────────────── */\n.c-chat__sidebar[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n width: var(--chat-sidebar-width);\n min-width: var(--chat-sidebar-width);\n background: var(--chat-sidebar-bg);\n border-right: 1px solid var(--chat-border);\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.03);\n}\n.c-chat__sidebar-header[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: var(--chat-header-height);\n padding: 0 16px;\n border-bottom: 1px solid var(--chat-border);\n font-weight: 600;\n font-size: 15px;\n}\n.c-chat__search[data-v-2bbae884] {\n padding: 8px 12px;\n}\n.c-chat__contact-list[data-v-2bbae884] {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.c-chat__contact-list[data-v-2bbae884]::-webkit-scrollbar {\n width: 4px;\n}\n.c-chat__contact-list[data-v-2bbae884]::-webkit-scrollbar-thumb {\n background: var(--chat-scrollbar-thumb);\n border-radius: 2px;\n}\n.c-chat__contact[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.15s;\n}\n.c-chat__contact[data-v-2bbae884]:hover {\n background: color-mix(in srgb, var(--primary-color) 6%, transparent);\n}\n.c-chat__contact.is-active[data-v-2bbae884] {\n background: color-mix(in srgb, var(--primary-color) 12%, transparent);\n}\n.c-chat__contact-avatar[data-v-2bbae884] {\n position: relative;\n flex-shrink: 0;\n}\n.c-chat__avatar[data-v-2bbae884] {\n width: var(--chat-avatar-size);\n height: var(--chat-avatar-size);\n border-radius: 50%;\n object-fit: cover;\n background: color-mix(in srgb, var(--border-color) 50%, transparent);\n}\n.c-chat__avatar-fallback[data-v-2bbae884] {\n width: var(--chat-avatar-size);\n height: var(--chat-avatar-size);\n border-radius: 50%;\n background: color-mix(in srgb, var(--primary-color) 25%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n font-weight: 600;\n color: var(--app-text-primary);\n}\n.c-chat__online-dot[data-v-2bbae884] {\n position: absolute;\n bottom: 0;\n right: 0;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #22c55e;\n border: 2px solid var(--chat-sidebar-bg);\n}\n.c-chat__contact-info[data-v-2bbae884] {\n flex: 1;\n min-width: 0;\n}\n.c-chat__contact-name[data-v-2bbae884] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 13px;\n font-weight: 500;\n}\n.c-chat__contact-time[data-v-2bbae884] {\n font-size: 11px;\n color: var(--chat-text-secondary);\n margin-left: 8px;\n flex-shrink: 0;\n}\n.c-chat__contact-last[data-v-2bbae884] {\n font-size: 12px;\n color: var(--chat-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n.c-chat__unread[data-v-2bbae884] {\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 9px;\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n/* ─── 主聊天区域 ──────────────────────────────────────── */\n.c-chat__main[data-v-2bbae884] {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.c-chat__header[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 10px;\n height: var(--chat-header-height);\n padding: 0 20px;\n background: var(--chat-header-bg);\n border-bottom: 1px solid var(--chat-border);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.03);\n font-weight: 600;\n font-size: 15px;\n}\n.c-chat__header-status[data-v-2bbae884] {\n font-size: 12px;\n font-weight: 400;\n color: var(--chat-text-secondary);\n}\n\n/* ─── 消息区域 ────────────────────────────────────────── */\n.c-chat__messages[data-v-2bbae884] {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: color-mix(in srgb, var(--body-color) 50%, var(--card-color));\n}\n.c-chat__messages[data-v-2bbae884]::-webkit-scrollbar {\n width: 4px;\n}\n.c-chat__messages[data-v-2bbae884]::-webkit-scrollbar-thumb {\n background: var(--chat-scrollbar-thumb);\n border-radius: 2px;\n}\n.c-chat__load-more[data-v-2bbae884] {\n text-align: center;\n padding: 8px;\n}\n.c-chat__empty[data-v-2bbae884] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--chat-text-secondary);\n font-size: 13px;\n}\n\n/* ─── 消息气泡 ────────────────────────────────────────── */\n.c-chat__msg[data-v-2bbae884] {\n display: flex;\n gap: 8px;\n max-width: 75%;\n}\n.c-chat__msg.is-self[data-v-2bbae884] {\n margin-left: auto;\n flex-direction: row-reverse;\n}\n.c-chat__msg.is-system[data-v-2bbae884] {\n max-width: 100%;\n justify-content: center;\n align-self: center;\n}\n.c-chat__msg-avatar[data-v-2bbae884] {\n flex-shrink: 0;\n margin-top: 2px;\n}\n.c-chat__msg-body[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n}\n.c-chat__msg-username[data-v-2bbae884] {\n font-size: 12px;\n color: var(--chat-text-secondary);\n margin-bottom: 2px;\n}\n.is-self .c-chat__msg-username[data-v-2bbae884] {\n text-align: right;\n}\n.c-chat__bubble[data-v-2bbae884] {\n padding: 10px 14px;\n border-radius: 16px;\n line-height: 1.5;\n word-break: break-word;\n white-space: pre-wrap;\n}\n.is-other .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-other);\n border: 1px solid var(--chat-border);\n border-top-left-radius: 4px;\n}\n.is-self .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-self);\n color: var(--chat-text-self);\n border-top-right-radius: 4px;\n}\n.is-system .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-system);\n color: var(--chat-text-secondary);\n font-size: 12px;\n padding: 4px 12px;\n}\n.c-chat__msg-image[data-v-2bbae884] {\n max-width: 240px;\n max-height: 180px;\n border-radius: 12px;\n cursor: pointer;\n object-fit: cover;\n}\n.is-self .c-chat__msg-image[data-v-2bbae884] {\n border-top-right-radius: 4px;\n}\n.is-other .c-chat__msg-image[data-v-2bbae884] {\n border-top-left-radius: 4px;\n}\n.c-chat__msg-file[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-radius: 12px;\n cursor: pointer;\n}\n.is-other .c-chat__msg-file[data-v-2bbae884] {\n background: var(--chat-bubble-other);\n border: 1px solid var(--chat-border);\n border-top-left-radius: 4px;\n}\n.is-self .c-chat__msg-file[data-v-2bbae884] {\n background: var(--chat-bubble-self);\n color: var(--chat-text-self);\n border-top-right-radius: 4px;\n}\n.c-chat__file-info[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.c-chat__file-name[data-v-2bbae884] {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.c-chat__file-size[data-v-2bbae884] {\n font-size: 11px;\n opacity: 0.6;\n}\n.c-chat__msg-time[data-v-2bbae884] {\n font-size: 11px;\n color: var(--chat-text-secondary);\n margin-top: 4px;\n}\n.is-self .c-chat__msg-time[data-v-2bbae884] {\n text-align: right;\n}\n.c-chat__msg-status[data-v-2bbae884] {\n font-size: 11px;\n margin-top: 2px;\n text-align: right;\n}\n.c-chat__msg-status.is-sending[data-v-2bbae884] {\n color: var(--chat-text-secondary);\n}\n.c-chat__msg-status.is-failed[data-v-2bbae884] {\n color: #ef4444;\n cursor: pointer;\n}\n\n/* ─── 时间分割线 ──────────────────────────────────────── */\n.c-chat__time-divider[data-v-2bbae884] {\n text-align: center;\n font-size: 11px;\n color: var(--chat-text-secondary);\n padding: 4px 0;\n}\n\n/* ─── 输入区域 ────────────────────────────────────────── */\n.c-chat__input-area[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: var(--chat-input-height);\n padding: 10px 16px;\n background: var(--chat-input-bg);\n border-top: 1px solid var(--chat-border);\n}\n.c-chat__input-actions[data-v-2bbae884] {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n.c-chat__input-wrap[data-v-2bbae884] {\n flex: 1;\n min-width: 0;\n}\n.c-chat__send-btn[data-v-2bbae884] {\n flex-shrink: 0;\n}\n\n/* ─── 空态 ────────────────────────────────────────────── */\n.c-chat__no-chat[data-v-2bbae884] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n color: var(--chat-text-secondary);\n}\n.c-chat__no-chat-icon[data-v-2bbae884] {\n font-size: 48px;\n opacity: 0.3;\n}\n\n/* ─── 响应式 ──────────────────────────────────────────── */\n@media (max-width: 640px) {\n.c-chat[data-v-2bbae884] {\n --chat-sidebar-width: 72px;\n}\n.c-chat__contact-info[data-v-2bbae884],\n .c-chat__search[data-v-2bbae884],\n .c-chat__unread[data-v-2bbae884] {\n display: none;\n}\n.c-chat__contact[data-v-2bbae884] {\n justify-content: center;\n padding: 10px 8px;\n}\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;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"C_Chat-Diq7tyWU.css","names":[],"sources":["../src/components/C_Chat/index.vue?vue&type=style&index=0&scoped=2bbae884&lang.scss"],"sourcesContent":["/* unplugin-vue-components disabled *//* ─── CSS 变量(基于项目主题变量,自动适配明暗) ───────────────────────── */\n.c-chat[data-v-2bbae884] {\n --chat-bg: var(--card-color);\n --chat-sidebar-bg: var(--body-color);\n --chat-sidebar-width: 280px;\n --chat-header-bg: var(--card-color);\n --chat-header-height: 56px;\n --chat-input-bg: var(--body-color);\n --chat-input-height: 56px;\n --chat-bubble-self: var(--primary-color);\n --chat-bubble-other: var(--body-color);\n --chat-bubble-system: transparent;\n --chat-text-primary: var(--app-text-primary);\n --chat-text-secondary: var(--text-color-3);\n --chat-text-self: #fff;\n --chat-border: var(--border-color);\n --chat-radius: 12px;\n --chat-avatar-size: 36px;\n --chat-scrollbar-thumb: var(--border-color);\n display: flex;\n width: 100%;\n height: 100%;\n min-height: 0;\n border-radius: var(--chat-radius);\n overflow: hidden;\n background: var(--chat-bg);\n color: var(--chat-text-primary);\n font-size: 14px;\n border: 1px solid var(--chat-border);\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);\n}\n\n/* ─── 联系人侧栏 ──────────────────────────────────────── */\n.c-chat__sidebar[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n width: var(--chat-sidebar-width);\n min-width: var(--chat-sidebar-width);\n background: var(--chat-sidebar-bg);\n border-right: 1px solid var(--chat-border);\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.03);\n}\n.c-chat__sidebar-header[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: var(--chat-header-height);\n padding: 0 16px;\n border-bottom: 1px solid var(--chat-border);\n font-weight: 600;\n font-size: 15px;\n}\n.c-chat__search[data-v-2bbae884] {\n padding: 8px 12px;\n}\n.c-chat__contact-list[data-v-2bbae884] {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.c-chat__contact-list[data-v-2bbae884]::-webkit-scrollbar {\n width: 4px;\n}\n.c-chat__contact-list[data-v-2bbae884]::-webkit-scrollbar-thumb {\n background: var(--chat-scrollbar-thumb);\n border-radius: 2px;\n}\n.c-chat__contact[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.15s;\n}\n.c-chat__contact[data-v-2bbae884]:hover {\n background: color-mix(in srgb, var(--primary-color) 6%, transparent);\n}\n.c-chat__contact.is-active[data-v-2bbae884] {\n background: color-mix(in srgb, var(--primary-color) 12%, transparent);\n}\n.c-chat__contact-avatar[data-v-2bbae884] {\n position: relative;\n flex-shrink: 0;\n}\n.c-chat__avatar[data-v-2bbae884] {\n width: var(--chat-avatar-size);\n height: var(--chat-avatar-size);\n border-radius: 50%;\n object-fit: cover;\n background: color-mix(in srgb, var(--border-color) 50%, transparent);\n}\n.c-chat__avatar-fallback[data-v-2bbae884] {\n width: var(--chat-avatar-size);\n height: var(--chat-avatar-size);\n border-radius: 50%;\n background: color-mix(in srgb, var(--primary-color) 25%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n font-weight: 600;\n color: var(--app-text-primary);\n}\n.c-chat__online-dot[data-v-2bbae884] {\n position: absolute;\n bottom: 0;\n right: 0;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #22c55e;\n border: 2px solid var(--chat-sidebar-bg);\n}\n.c-chat__contact-info[data-v-2bbae884] {\n flex: 1;\n min-width: 0;\n}\n.c-chat__contact-name[data-v-2bbae884] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 13px;\n font-weight: 500;\n}\n.c-chat__contact-time[data-v-2bbae884] {\n font-size: 11px;\n color: var(--chat-text-secondary);\n margin-left: 8px;\n flex-shrink: 0;\n}\n.c-chat__contact-last[data-v-2bbae884] {\n font-size: 12px;\n color: var(--chat-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n}\n.c-chat__unread[data-v-2bbae884] {\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 9px;\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n/* ─── 主聊天区域 ──────────────────────────────────────── */\n.c-chat__main[data-v-2bbae884] {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.c-chat__header[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 10px;\n height: var(--chat-header-height);\n padding: 0 20px;\n background: var(--chat-header-bg);\n border-bottom: 1px solid var(--chat-border);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.03);\n font-weight: 600;\n font-size: 15px;\n}\n.c-chat__header-status[data-v-2bbae884] {\n font-size: 12px;\n font-weight: 400;\n color: var(--chat-text-secondary);\n}\n\n/* ─── 消息区域 ────────────────────────────────────────── */\n.c-chat__messages[data-v-2bbae884] {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 16px 20px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: color-mix(in srgb, var(--body-color) 50%, var(--card-color));\n}\n.c-chat__messages[data-v-2bbae884]::-webkit-scrollbar {\n width: 4px;\n}\n.c-chat__messages[data-v-2bbae884]::-webkit-scrollbar-thumb {\n background: var(--chat-scrollbar-thumb);\n border-radius: 2px;\n}\n.c-chat__load-more[data-v-2bbae884] {\n text-align: center;\n padding: 8px;\n}\n.c-chat__empty[data-v-2bbae884] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--chat-text-secondary);\n font-size: 13px;\n}\n\n/* ─── 消息气泡 ────────────────────────────────────────── */\n.c-chat__msg[data-v-2bbae884] {\n display: flex;\n gap: 8px;\n max-width: 75%;\n}\n.c-chat__msg.is-self[data-v-2bbae884] {\n margin-left: auto;\n flex-direction: row-reverse;\n}\n.c-chat__msg.is-system[data-v-2bbae884] {\n max-width: 100%;\n justify-content: center;\n align-self: center;\n}\n.c-chat__msg-avatar[data-v-2bbae884] {\n flex-shrink: 0;\n margin-top: 2px;\n}\n.c-chat__msg-body[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n}\n.c-chat__msg-username[data-v-2bbae884] {\n font-size: 12px;\n color: var(--chat-text-secondary);\n margin-bottom: 2px;\n}\n.is-self .c-chat__msg-username[data-v-2bbae884] {\n text-align: right;\n}\n.c-chat__bubble[data-v-2bbae884] {\n padding: 10px 14px;\n border-radius: 16px;\n line-height: 1.5;\n word-break: break-word;\n white-space: pre-wrap;\n}\n.is-other .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-other);\n border: 1px solid var(--chat-border);\n border-top-left-radius: 4px;\n}\n.is-self .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-self);\n color: var(--chat-text-self);\n border-top-right-radius: 4px;\n}\n.is-system .c-chat__bubble[data-v-2bbae884] {\n background: var(--chat-bubble-system);\n color: var(--chat-text-secondary);\n font-size: 12px;\n padding: 4px 12px;\n}\n.c-chat__msg-image[data-v-2bbae884] {\n max-width: 240px;\n max-height: 180px;\n border-radius: 12px;\n cursor: pointer;\n object-fit: cover;\n}\n.is-self .c-chat__msg-image[data-v-2bbae884] {\n border-top-right-radius: 4px;\n}\n.is-other .c-chat__msg-image[data-v-2bbae884] {\n border-top-left-radius: 4px;\n}\n.c-chat__msg-file[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 14px;\n border-radius: 12px;\n cursor: pointer;\n}\n.is-other .c-chat__msg-file[data-v-2bbae884] {\n background: var(--chat-bubble-other);\n border: 1px solid var(--chat-border);\n border-top-left-radius: 4px;\n}\n.is-self .c-chat__msg-file[data-v-2bbae884] {\n background: var(--chat-bubble-self);\n color: var(--chat-text-self);\n border-top-right-radius: 4px;\n}\n.c-chat__file-info[data-v-2bbae884] {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.c-chat__file-name[data-v-2bbae884] {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.c-chat__file-size[data-v-2bbae884] {\n font-size: 11px;\n opacity: 0.6;\n}\n.c-chat__msg-time[data-v-2bbae884] {\n font-size: 11px;\n color: var(--chat-text-secondary);\n margin-top: 4px;\n}\n.is-self .c-chat__msg-time[data-v-2bbae884] {\n text-align: right;\n}\n.c-chat__msg-status[data-v-2bbae884] {\n font-size: 11px;\n margin-top: 2px;\n text-align: right;\n}\n.c-chat__msg-status.is-sending[data-v-2bbae884] {\n color: var(--chat-text-secondary);\n}\n.c-chat__msg-status.is-failed[data-v-2bbae884] {\n color: #ef4444;\n cursor: pointer;\n}\n\n/* ─── 时间分割线 ──────────────────────────────────────── */\n.c-chat__time-divider[data-v-2bbae884] {\n text-align: center;\n font-size: 11px;\n color: var(--chat-text-secondary);\n padding: 4px 0;\n}\n\n/* ─── 输入区域 ────────────────────────────────────────── */\n.c-chat__input-area[data-v-2bbae884] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: var(--chat-input-height);\n padding: 10px 16px;\n background: var(--chat-input-bg);\n border-top: 1px solid var(--chat-border);\n}\n.c-chat__input-actions[data-v-2bbae884] {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n.c-chat__input-wrap[data-v-2bbae884] {\n flex: 1;\n min-width: 0;\n}\n.c-chat__send-btn[data-v-2bbae884] {\n flex-shrink: 0;\n}\n\n/* ─── 空态 ────────────────────────────────────────────── */\n.c-chat__no-chat[data-v-2bbae884] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n color: var(--chat-text-secondary);\n}\n.c-chat__no-chat-icon[data-v-2bbae884] {\n font-size: 48px;\n opacity: 0.3;\n}\n\n/* ─── 响应式 ──────────────────────────────────────────── */\n@media (max-width: 640px) {\n.c-chat[data-v-2bbae884] {\n --chat-sidebar-width: 72px;\n}\n.c-chat__contact-info[data-v-2bbae884],\n .c-chat__search[data-v-2bbae884],\n .c-chat__unread[data-v-2bbae884] {\n display: none;\n}\n.c-chat__contact[data-v-2bbae884] {\n justify-content: center;\n padding: 10px 8px;\n}\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;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./C_Icon.js`);const e=require(`./C_Chat.js`);exports.C_Chat=e.t,exports.DEFAULT_CHAT_PROPS=e.n;