@robot-admin/naive-ui-components 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/C_Menu.cjs +1 -1
- package/dist/C_Menu.js +1 -1
- package/dist/C_Menu.js.map +1 -1
- package/dist/C_Menu2.js.map +1 -1
- package/dist/_shared.cjs +1 -1
- package/dist/_shared.js +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants2.d.ts +2 -2
- package/dist/constants3.d.ts +5 -5
- package/dist/constants4.d.ts +3 -3
- package/dist/constants5.d.ts +2 -2
- package/dist/data.d.ts +2 -2
- package/dist/index.vue.d.ts +1 -1
- package/dist/index11.vue.d.ts +7 -7
- package/dist/index13.vue.d.ts +4 -4
- package/dist/index15.vue.d.ts +3 -3
- package/dist/index16.vue.d.ts +1 -1
- package/dist/index17.vue.d.ts +1 -1
- package/dist/index19.vue.d.ts +3 -3
- package/dist/index2.vue.d.ts +1 -1
- package/dist/index7.vue.d.ts +3 -3
- package/dist/index8.vue.d.ts +1 -1
- package/dist/index9.vue.d.ts +2 -2
- package/dist/menuAdapter.js +1 -1
- package/dist/menuAdapter.js.map +1 -1
- package/dist/useCalendarEvents.d.ts +1 -1
- package/dist/useCollapsePanel.d.ts +4 -4
- package/dist/useCropperCore.d.ts +4 -4
- package/dist/useDraggableLayout.d.ts +9 -9
- package/dist/useDynamicFormState.d.ts +116 -116
- package/dist/useEdgeInteraction.d.ts +2 -2
- package/dist/useInfiniteScroll.d.ts +2 -2
- package/dist/useModalEdit.d.ts +2 -2
- package/dist/useQRCode.d.ts +4 -4
- package/dist/useSignatureHistory.d.ts +2 -2
- package/dist/useSplitResize.d.ts +5 -5
- package/dist/useTimeSelection.d.ts +2 -2
- package/dist/useTreeOperations.d.ts +6 -6
- package/dist/useWorkflowValidation.d.ts +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @robot-admin/naive-ui-components
|
|
2
2
|
|
|
3
|
+
## 0.6.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 菜单图标渲染统一使用 C_Icon 组件
|
|
8
|
+
- menuAdapter.defaultRenderIcon 改用组件库自有的 C_Icon 替代直接使用 NIcon + @iconify/vue
|
|
9
|
+
- 与 C_Breadcrumb、C_TagsView 等组件保持一致的图标渲染方式
|
|
10
|
+
- 彻底解决生产环境图标对齐问题
|
|
11
|
+
|
|
3
12
|
## 0.6.2
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/C_Menu.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./C_Menu.js`);exports.C_Menu=e.t;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./C_Icon.js`);const e=require(`./C_Menu.js`);exports.C_Menu=e.t;
|
package/dist/C_Menu.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./C_Menu2.js";export{e as C_Menu};
|
|
1
|
+
import"./C_Icon2.js";import{t as e}from"./C_Menu2.js";export{e as C_Menu};
|
package/dist/C_Menu.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Menu.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n","<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n"],"mappings":"gnBE6DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,GAAA,EAAA,EAAA,KAA+B,KAAK,CACpC,GAAA,EAAA,EAAA,KAA6B,EAAE,CAAC,CAEhC,GAAA,EAAA,EAAA,cAA2B,EAAM,OAAS,GAAG,CAK7C,GAAA,EAAA,EAAA,cAA6C,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACrE,CACD,OAAO,EAAA,EAAkB,EAAM,OAAQ,EAAO,CAGhD,MAAO,EAAE,EACT,CAKI,GACJ,EACA,EACA,EAAuB,EAAE,GACZ,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAc,CACvD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAY,CAC/D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAE,EAIL,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAC1C,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAY,EACrB,CACF,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAC,CAChE,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAI,EAIjB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAK,SAKnC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAI,CACvC,UAAS,CAAC,EAIrC,EAAA,EAAA,WACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAO,CAC3C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAC,CAC7C,EACD,EAAA,EAAA,cAAe,EAAQ,OAAO,WAAW,EAAO,CAAC,EAEnD,CAAE,UAAW,GAAM,CACpB,EAED,EAAA,EAAA,eAAgB,EACd,EAAA,EAAA,cAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAC,CACrE,EAAQ,OAAO,WAAW,EAAU,MAAM,GAE5C,EACF,iEAtLA,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
|
|
1
|
+
{"version":3,"file":"C_Menu.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n"],"mappings":"gnBE6DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,GAAA,EAAA,EAAA,KAA+B,KAAI,CACnC,GAAA,EAAA,EAAA,KAA6B,EAAE,CAAA,CAE/B,GAAA,EAAA,EAAA,cAA2B,EAAM,OAAS,GAAE,CAK5C,GAAA,EAAA,EAAA,cAA6C,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACtE,CACA,OAAO,EAAA,EAAkB,EAAM,OAAQ,EAAM,CAG/C,MAAO,EAAC,EACT,CAKK,GACJ,EACA,EACA,EAAuB,EAAC,GACX,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAa,CACtD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAW,CAC9D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAC,EAIJ,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAO,CACzC,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAW,EACrB,CACD,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAA,CAC/D,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAG,EAIhB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAI,SAKlC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAG,CACtC,UAAS,CAAA,EAIpC,EAAA,EAAA,WACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAM,CAC1C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAA,CAC7C,EACA,EAAA,EAAA,cAAe,EAAQ,OAAO,WAAW,EAAO,CAAA,EAElD,CAAE,UAAW,GAAK,CACpB,EAEA,EAAA,EAAA,eAAgB,EACd,EAAA,EAAA,cAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAA,CACpE,EAAQ,OAAO,WAAW,EAAU,MAAK,GAE5C,EACF,iEAtLC,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
|
package/dist/C_Menu2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"C_Menu2.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n","/* unplugin-vue-components disabled */<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n","<!--\r\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\r\n *\r\n * 支持两种数据输入模式:\r\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\r\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\r\n *\r\n * @example 路由模式(推荐)\r\n * ```vue\r\n * <C_Menu\r\n * :routes=\"menuData\"\r\n * :label-formatter=\"$t\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * @example 原生模式\r\n * ```vue\r\n * <C_Menu\r\n * :options=\"nMenuOptions\"\r\n * @select=\"router.push\"\r\n * />\r\n * ```\r\n *\r\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\r\n-->\r\n<template>\r\n <NMenu\r\n ref=\"menuRef\"\r\n :options=\"mergedOptions\"\r\n :expanded-keys=\"expandedKeys\"\r\n :value=\"activeKey\"\r\n :mode=\"mode\"\r\n :collapsed=\"collapsed\"\r\n :collapsed-width=\"collapsedWidth\"\r\n :collapsed-icon-size=\"collapsedIconSize\"\r\n :inverted=\"inverted\"\r\n :theme-overrides=\"themeOverrides\"\r\n :dropdown-props=\"dropdownProps\"\r\n :indent=\"indent\"\r\n :root-indent=\"rootIndent\"\r\n @update:value=\"handleMenuClick\"\r\n @update:expanded-keys=\"onExpandedKeysChange\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\r\n import {\r\n type MenuOption,\r\n type MenuInst,\r\n type DropdownProps,\r\n } from 'naive-ui/es'\r\n import {\r\n createMenuOptions,\r\n type RouteItem,\r\n type MenuAdapterConfig,\r\n } from '../_shared'\r\n\r\n defineOptions({ name: 'C_Menu' })\r\n\r\n const props = withDefaults(\r\n defineProps<{\r\n /**\r\n * 模式一:直传 NMenu 原生 MenuOption[]\r\n * 与 `routes` 二选一,`options` 优先级更高\r\n */\r\n options?: MenuOption[]\r\n /**\r\n * 模式二:传入路由数据,自动转换为 MenuOption[]\r\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\r\n */\r\n routes?: RouteItem[]\r\n /**\r\n * 适配器配置(仅 routes 模式生效)\r\n * 可自定义 key/label/icon 取值、过滤逻辑等\r\n */\r\n adapterConfig?: MenuAdapterConfig\r\n /**\r\n * 标签文本格式化函数(routes 模式的快捷方式)\r\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\r\n */\r\n labelFormatter?: (label: string) => string\r\n /** 当前激活的菜单 key */\r\n value?: string\r\n /** 菜单模式 */\r\n mode?: 'vertical' | 'horizontal'\r\n /** 是否折叠 */\r\n collapsed?: boolean\r\n /** 折叠宽度 */\r\n collapsedWidth?: number\r\n /** 折叠图标大小 */\r\n collapsedIconSize?: number\r\n /** 是否反色 */\r\n inverted?: boolean\r\n /** 主题覆盖 */\r\n themeOverrides?: Record<string, any>\r\n /** 缩进像素 */\r\n indent?: number\r\n /** 根缩进像素 */\r\n rootIndent?: number\r\n /** 下拉菜单属性(折叠模式) */\r\n dropdownProps?: DropdownProps\r\n }>(),\r\n {\r\n mode: 'vertical',\r\n collapsed: false,\r\n collapsedWidth: 64,\r\n collapsedIconSize: 22,\r\n inverted: false,\r\n indent: 24,\r\n rootIndent: 16,\r\n dropdownProps: () => ({\r\n placement: 'right-start' as const,\r\n trigger: 'hover' as const,\r\n arrowStyle: { color: 'var(--n-color)' },\r\n }),\r\n }\r\n )\r\n\r\n const emit = defineEmits<{\r\n /** 菜单项被选中 */\r\n select: [key: string]\r\n /** 展开项变化 */\r\n 'update:expandedKeys': [keys: string[]]\r\n }>()\r\n\r\n const menuRef = ref<MenuInst | null>(null)\r\n const expandedKeys = ref<string[]>([])\r\n\r\n const activeKey = computed(() => props.value ?? '')\r\n\r\n // ====== 数据合成 ======\r\n\r\n /** 合并后的最终 MenuOption[] */\r\n const mergedOptions = computed<MenuOption[]>(() => {\r\n // 优先使用 options 直传模式\r\n if (props.options) return props.options\r\n\r\n // routes 模式 → 适配器转换\r\n if (props.routes) {\r\n const config: MenuAdapterConfig = {\r\n ...props.adapterConfig,\r\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\r\n }\r\n return createMenuOptions(props.routes, config)\r\n }\r\n\r\n return []\r\n })\r\n\r\n // ====== 展开逻辑 ======\r\n\r\n /** 从 MenuOption[] 中查找所有祖先 key */\r\n const findParentKeys = (\r\n items: MenuOption[],\r\n targetKey: string,\r\n parentKeys: string[] = []\r\n ): string[] => {\r\n for (const item of items) {\r\n const children = item.children as MenuOption[] | undefined\r\n if (children?.length) {\r\n const currentKeys = [...parentKeys, item.key as string]\r\n if (children.some(child => child.key === targetKey)) {\r\n return currentKeys\r\n }\r\n const result = findParentKeys(children, targetKey, currentKeys)\r\n if (result.length > 0) return result\r\n }\r\n }\r\n return []\r\n }\r\n\r\n /** 通过路径段推导展开 key + 查找祖先 key */\r\n const computeExpandedKeys = (path: string): Set<string> => {\r\n const segments = path.split('/').filter(Boolean)\r\n const keys = new Set<string>()\r\n let currentPath = ''\r\n segments.forEach(segment => {\r\n currentPath += `/${segment}`\r\n keys.add(currentPath)\r\n })\r\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\r\n return keys\r\n }\r\n\r\n // ====== 事件处理 ======\r\n\r\n const handleMenuClick = (key: string) => {\r\n if (key && key !== activeKey.value) {\r\n emit('select', key)\r\n }\r\n }\r\n\r\n const onExpandedKeysChange = (keys: string[]) => {\r\n expandedKeys.value = keys\r\n emit('update:expandedKeys', keys)\r\n }\r\n\r\n // ====== 暴露方法 ======\r\n const showOption = (key: string) => menuRef.value?.showOption(key)\r\n defineExpose({ showOption, menuRef })\r\n\r\n // ====== 路由跟踪 ======\r\n\r\n watch(\r\n () => activeKey.value,\r\n newKey => {\r\n if (!newKey) return\r\n const newKeys = computeExpandedKeys(newKey)\r\n expandedKeys.value = Array.from(\r\n new Set([...expandedKeys.value, ...newKeys])\r\n )\r\n nextTick(() => menuRef.value?.showOption(newKey))\r\n },\r\n { immediate: true }\r\n )\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n if (activeKey.value) {\r\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\r\n menuRef.value?.showOption(activeKey.value)\r\n }\r\n })\r\n })\r\n</script>\r\n"],"mappings":"ksBE6DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,EAAU,EAAqB,KAAK,CACpC,EAAe,EAAc,EAAE,CAAC,CAEhC,EAAY,MAAe,EAAM,OAAS,GAAG,CAK7C,EAAgB,MAA6B,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACrE,CACD,OAAO,EAAkB,EAAM,OAAQ,EAAO,CAGhD,MAAO,EAAE,EACT,CAKI,GACJ,EACA,EACA,EAAuB,EAAE,GACZ,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAc,CACvD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAY,CAC/D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAE,EAIL,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAC1C,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAY,EACrB,CACF,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAC,CAChE,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAI,EAIjB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAK,SAKnC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAI,CACvC,UAAS,CAAC,CAIrC,MACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAO,CAC3C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAC,CAC7C,CACD,MAAe,EAAQ,OAAO,WAAW,EAAO,CAAC,EAEnD,CAAE,UAAW,GAAM,CACpB,CAED,MAAgB,CACd,MAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAC,CACrE,EAAQ,OAAO,WAAW,EAAU,MAAM,GAE5C,EACF,4BAtMF,EAgBE,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
|
|
1
|
+
{"version":3,"file":"C_Menu2.js","names":["mode","collapsed","collapsedWidth","collapsedIconSize","inverted","themeOverrides","dropdownProps","indent","rootIndent"],"sources":["../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue","../src/components/C_Menu/index.vue"],"sourcesContent":["/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","/* unplugin-vue-components disabled */<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n","<!--\n * @Description: 通用菜单组件 — 基于 NMenu 的树形导航菜单\n *\n * 支持两种数据输入模式:\n * 1. `options` — 直传 NMenu 原生 MenuOption[](零转换,高级用户)\n * 2. `routes` — 传入路由数据,自动通过内置适配器转换为 MenuOption[]\n *\n * @example 路由模式(推荐)\n * ```vue\n * <C_Menu\n * :routes=\"menuData\"\n * :label-formatter=\"$t\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * @example 原生模式\n * ```vue\n * <C_Menu\n * :options=\"nMenuOptions\"\n * @select=\"router.push\"\n * />\n * ```\n *\n * Copyright (c) 2025 by CHENY, All Rights Reserved.\n-->\n<template>\n <NMenu\n ref=\"menuRef\"\n :options=\"mergedOptions\"\n :expanded-keys=\"expandedKeys\"\n :value=\"activeKey\"\n :mode=\"mode\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"collapsedWidth\"\n :collapsed-icon-size=\"collapsedIconSize\"\n :inverted=\"inverted\"\n :theme-overrides=\"themeOverrides\"\n :dropdown-props=\"dropdownProps\"\n :indent=\"indent\"\n :root-indent=\"rootIndent\"\n @update:value=\"handleMenuClick\"\n @update:expanded-keys=\"onExpandedKeysChange\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref, computed, watch, nextTick, onMounted } from 'vue'\n import {\n type MenuOption,\n type MenuInst,\n type DropdownProps,\n } from 'naive-ui/es'\n import {\n createMenuOptions,\n type RouteItem,\n type MenuAdapterConfig,\n } from '../_shared'\n\n defineOptions({ name: 'C_Menu' })\n\n const props = withDefaults(\n defineProps<{\n /**\n * 模式一:直传 NMenu 原生 MenuOption[]\n * 与 `routes` 二选一,`options` 优先级更高\n */\n options?: MenuOption[]\n /**\n * 模式二:传入路由数据,自动转换为 MenuOption[]\n * 兼容 Vue Router RouteRecordRaw / 后端 JSON 路由表\n */\n routes?: RouteItem[]\n /**\n * 适配器配置(仅 routes 模式生效)\n * 可自定义 key/label/icon 取值、过滤逻辑等\n */\n adapterConfig?: MenuAdapterConfig\n /**\n * 标签文本格式化函数(routes 模式的快捷方式)\n * 等同于 `adapterConfig.labelFormatter`,但优先级更高\n */\n labelFormatter?: (label: string) => string\n /** 当前激活的菜单 key */\n value?: string\n /** 菜单模式 */\n mode?: 'vertical' | 'horizontal'\n /** 是否折叠 */\n collapsed?: boolean\n /** 折叠宽度 */\n collapsedWidth?: number\n /** 折叠图标大小 */\n collapsedIconSize?: number\n /** 是否反色 */\n inverted?: boolean\n /** 主题覆盖 */\n themeOverrides?: Record<string, any>\n /** 缩进像素 */\n indent?: number\n /** 根缩进像素 */\n rootIndent?: number\n /** 下拉菜单属性(折叠模式) */\n dropdownProps?: DropdownProps\n }>(),\n {\n mode: 'vertical',\n collapsed: false,\n collapsedWidth: 64,\n collapsedIconSize: 22,\n inverted: false,\n indent: 24,\n rootIndent: 16,\n dropdownProps: () => ({\n placement: 'right-start' as const,\n trigger: 'hover' as const,\n arrowStyle: { color: 'var(--n-color)' },\n }),\n }\n )\n\n const emit = defineEmits<{\n /** 菜单项被选中 */\n select: [key: string]\n /** 展开项变化 */\n 'update:expandedKeys': [keys: string[]]\n }>()\n\n const menuRef = ref<MenuInst | null>(null)\n const expandedKeys = ref<string[]>([])\n\n const activeKey = computed(() => props.value ?? '')\n\n // ====== 数据合成 ======\n\n /** 合并后的最终 MenuOption[] */\n const mergedOptions = computed<MenuOption[]>(() => {\n // 优先使用 options 直传模式\n if (props.options) return props.options\n\n // routes 模式 → 适配器转换\n if (props.routes) {\n const config: MenuAdapterConfig = {\n ...props.adapterConfig,\n ...(props.labelFormatter && { labelFormatter: props.labelFormatter }),\n }\n return createMenuOptions(props.routes, config)\n }\n\n return []\n })\n\n // ====== 展开逻辑 ======\n\n /** 从 MenuOption[] 中查找所有祖先 key */\n const findParentKeys = (\n items: MenuOption[],\n targetKey: string,\n parentKeys: string[] = []\n ): string[] => {\n for (const item of items) {\n const children = item.children as MenuOption[] | undefined\n if (children?.length) {\n const currentKeys = [...parentKeys, item.key as string]\n if (children.some(child => child.key === targetKey)) {\n return currentKeys\n }\n const result = findParentKeys(children, targetKey, currentKeys)\n if (result.length > 0) return result\n }\n }\n return []\n }\n\n /** 通过路径段推导展开 key + 查找祖先 key */\n const computeExpandedKeys = (path: string): Set<string> => {\n const segments = path.split('/').filter(Boolean)\n const keys = new Set<string>()\n let currentPath = ''\n segments.forEach(segment => {\n currentPath += `/${segment}`\n keys.add(currentPath)\n })\n findParentKeys(mergedOptions.value, path).forEach(key => keys.add(key))\n return keys\n }\n\n // ====== 事件处理 ======\n\n const handleMenuClick = (key: string) => {\n if (key && key !== activeKey.value) {\n emit('select', key)\n }\n }\n\n const onExpandedKeysChange = (keys: string[]) => {\n expandedKeys.value = keys\n emit('update:expandedKeys', keys)\n }\n\n // ====== 暴露方法 ======\n const showOption = (key: string) => menuRef.value?.showOption(key)\n defineExpose({ showOption, menuRef })\n\n // ====== 路由跟踪 ======\n\n watch(\n () => activeKey.value,\n newKey => {\n if (!newKey) return\n const newKeys = computeExpandedKeys(newKey)\n expandedKeys.value = Array.from(\n new Set([...expandedKeys.value, ...newKeys])\n )\n nextTick(() => menuRef.value?.showOption(newKey))\n },\n { immediate: true }\n )\n\n onMounted(() => {\n nextTick(() => {\n if (activeKey.value) {\n expandedKeys.value = Array.from(computeExpandedKeys(activeKey.value))\n menuRef.value?.showOption(activeKey.value)\n }\n })\n })\n</script>\n"],"mappings":"ksBE6DE,IAAM,EAAQ,EA2DR,EAAO,EAOP,EAAU,EAAqB,KAAI,CACnC,EAAe,EAAc,EAAE,CAAA,CAE/B,EAAY,MAAe,EAAM,OAAS,GAAE,CAK5C,EAAgB,MAA6B,CAEjD,GAAI,EAAM,QAAS,OAAO,EAAM,QAGhC,GAAI,EAAM,OAAQ,CAChB,IAAM,EAA4B,CAChC,GAAG,EAAM,cACT,GAAI,EAAM,gBAAkB,CAAE,eAAgB,EAAM,eAAgB,CACtE,CACA,OAAO,EAAkB,EAAM,OAAQ,EAAM,CAG/C,MAAO,EAAC,EACT,CAKK,GACJ,EACA,EACA,EAAuB,EAAC,GACX,CACb,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAW,EAAK,SACtB,GAAI,GAAU,OAAQ,CACpB,IAAM,EAAc,CAAC,GAAG,EAAY,EAAK,IAAa,CACtD,GAAI,EAAS,KAAK,GAAS,EAAM,MAAQ,EAAU,CACjD,OAAO,EAET,IAAM,EAAS,EAAe,EAAU,EAAW,EAAW,CAC9D,GAAI,EAAO,OAAS,EAAG,OAAO,GAGlC,MAAO,EAAC,EAIJ,EAAuB,GAA8B,CACzD,IAAM,EAAW,EAAK,MAAM,IAAI,CAAC,OAAO,QAAO,CACzC,EAAO,IAAI,IACb,EAAc,GAMlB,OALA,EAAS,QAAQ,GAAW,CAC1B,GAAe,IAAI,IACnB,EAAK,IAAI,EAAW,EACrB,CACD,EAAe,EAAc,MAAO,EAAK,CAAC,QAAQ,GAAO,EAAK,IAAI,EAAI,CAAA,CAC/D,GAKH,EAAmB,GAAgB,CACnC,GAAO,IAAQ,EAAU,OAC3B,EAAK,SAAU,EAAG,EAIhB,EAAwB,GAAmB,CAC/C,EAAa,MAAQ,EACrB,EAAK,sBAAuB,EAAI,SAKlC,EAAa,CAAE,WADK,GAAgB,EAAQ,OAAO,WAAW,EAAG,CACtC,UAAS,CAAA,CAIpC,MACQ,EAAU,MAChB,GAAU,CACR,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,EAAoB,EAAM,CAC1C,EAAa,MAAQ,MAAM,KACzB,IAAI,IAAI,CAAC,GAAG,EAAa,MAAO,GAAG,EAAQ,CAAA,CAC7C,CACA,MAAe,EAAQ,OAAO,WAAW,EAAO,CAAA,EAElD,CAAE,UAAW,GAAK,CACpB,CAEA,MAAgB,CACd,MAAe,CACT,EAAU,QACZ,EAAa,MAAQ,MAAM,KAAK,EAAoB,EAAU,MAAM,CAAA,CACpE,EAAQ,OAAO,WAAW,EAAU,MAAK,GAE5C,EACF,4BAtMD,EAgBE,EAAA,SAfI,UAAJ,IAAI,EACH,QAAS,EAAA,MACT,gBAAe,EAAA,MACf,MAAO,EAAA,MACP,KAAMA,EAAAA,KACN,UAAWC,EAAAA,UACX,kBAAiBC,EAAAA,eACjB,sBAAqBC,EAAAA,kBACrB,SAAUC,EAAAA,SACV,kBAAiBC,EAAAA,eACjB,iBAAgBC,EAAAA,cAChB,OAAQC,EAAAA,OACR,cAAaC,EAAAA,WACb,iBAAc,EACd,wBAAsB"}
|
package/dist/_shared.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./menuAdapter.js`);exports.createMenuOptions=e.t,exports.flattenRoutes=e.n;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./C_Icon.js`);const e=require(`./menuAdapter.js`);exports.createMenuOptions=e.t,exports.flattenRoutes=e.n;
|
package/dist/_shared.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./menuAdapter.js";export{t as createMenuOptions,e as flattenRoutes};
|
|
1
|
+
import"./C_Icon2.js";import{n as e,t}from"./menuAdapter.js";export{t as createMenuOptions,e as flattenRoutes};
|
package/dist/constants.d.ts
CHANGED
|
@@ -118,9 +118,9 @@ declare const __VLS_export: vue.DefineComponent<CronProps, {
|
|
|
118
118
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
119
119
|
"onValidation-change"?: ((result: CronValidation) => any) | undefined;
|
|
120
120
|
}>, {
|
|
121
|
-
height: string | number;
|
|
122
121
|
disabled: boolean;
|
|
123
122
|
modelValue: string;
|
|
123
|
+
height: string | number;
|
|
124
124
|
showPreview: boolean;
|
|
125
125
|
previewCount: number;
|
|
126
126
|
showTemplates: boolean;
|
package/dist/constants2.d.ts
CHANGED
|
@@ -120,10 +120,10 @@ declare const __VLS_export: vue.DefineComponent<FormulaEditorProps, FormulaEdito
|
|
|
120
120
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
121
121
|
"onValidation-change"?: ((result: FormulaValidation) => any) | undefined;
|
|
122
122
|
}>, {
|
|
123
|
-
height: string | number;
|
|
124
123
|
disabled: boolean;
|
|
125
|
-
placeholder: string;
|
|
126
124
|
modelValue: string;
|
|
125
|
+
height: string | number;
|
|
126
|
+
placeholder: string;
|
|
127
127
|
variables: FormulaVariable[];
|
|
128
128
|
functions: FormulaFunction[];
|
|
129
129
|
sampleData: Record<string, number | string | boolean>;
|
package/dist/constants3.d.ts
CHANGED
|
@@ -151,8 +151,8 @@ interface NotificationCenterExpose {
|
|
|
151
151
|
//#region src/components/C_NotificationCenter/index.vue.d.ts
|
|
152
152
|
declare const __VLS_export: vue.DefineComponent<NotificationCenterProps, NotificationCenterExpose, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
153
153
|
delete: (ids: string[]) => any;
|
|
154
|
-
itemClick: (message: NotificationMessage) => any;
|
|
155
154
|
read: (ids: string[]) => any;
|
|
155
|
+
itemClick: (message: NotificationMessage) => any;
|
|
156
156
|
allRead: (category?: NotificationCategory | undefined) => any;
|
|
157
157
|
unreadChange: (count: number) => any;
|
|
158
158
|
wsStatusChange: (status: string) => any;
|
|
@@ -160,19 +160,19 @@ declare const __VLS_export: vue.DefineComponent<NotificationCenterProps, Notific
|
|
|
160
160
|
navigate: (url: string) => any;
|
|
161
161
|
}, string, vue.PublicProps, Readonly<NotificationCenterProps> & Readonly<{
|
|
162
162
|
onDelete?: ((ids: string[]) => any) | undefined;
|
|
163
|
-
onItemClick?: ((message: NotificationMessage) => any) | undefined;
|
|
164
163
|
onRead?: ((ids: string[]) => any) | undefined;
|
|
164
|
+
onItemClick?: ((message: NotificationMessage) => any) | undefined;
|
|
165
165
|
onAllRead?: ((category?: NotificationCategory | undefined) => any) | undefined;
|
|
166
166
|
onUnreadChange?: ((count: number) => any) | undefined;
|
|
167
167
|
onWsStatusChange?: ((status: string) => any) | undefined;
|
|
168
168
|
onNewMessage?: ((message: NotificationMessage) => any) | undefined;
|
|
169
169
|
onNavigate?: ((url: string) => any) | undefined;
|
|
170
170
|
}>, {
|
|
171
|
-
pageSize: number;
|
|
172
|
-
storageKey: string;
|
|
173
171
|
desktopNotification: boolean;
|
|
174
172
|
maxBadgeCount: number;
|
|
175
173
|
pollingInterval: number;
|
|
174
|
+
pageSize: number;
|
|
175
|
+
storageKey: string;
|
|
176
176
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
177
177
|
declare const _default: typeof __VLS_export;
|
|
178
178
|
//#endregion
|
|
@@ -217,7 +217,7 @@ declare function useNotificationCore(props: NotificationCenterProps): {
|
|
|
217
217
|
actionText?: string | undefined;
|
|
218
218
|
extra?: Record<string, unknown> | undefined;
|
|
219
219
|
}[]>;
|
|
220
|
-
activeCategory: vue.Ref<"all" |
|
|
220
|
+
activeCategory: vue.Ref<NotificationCategory | "all", NotificationCategory | "all">;
|
|
221
221
|
loading: vue.Ref<boolean, boolean>;
|
|
222
222
|
total: vue.Ref<number, number>;
|
|
223
223
|
page: vue.Ref<number, number>;
|
package/dist/constants4.d.ts
CHANGED
|
@@ -196,17 +196,17 @@ type __VLS_Slots = {} & {
|
|
|
196
196
|
area?: (props: typeof __VLS_11) => any;
|
|
197
197
|
};
|
|
198
198
|
declare const __VLS_base: vue.DefineComponent<UploadProps, UploadExpose, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
199
|
-
error: (file: UploadFileItem, error: Error) => any;
|
|
200
199
|
success: (file: UploadFileItem, response: any) => any;
|
|
201
200
|
change: (fileList: UploadFileItem[]) => any;
|
|
201
|
+
error: (file: UploadFileItem, error: Error) => any;
|
|
202
202
|
progress: (file: UploadFileItem, percent: number) => any;
|
|
203
203
|
remove: (file: UploadFileItem) => any;
|
|
204
204
|
finish: (fileList: UploadFileItem[]) => any;
|
|
205
205
|
exceed: (files: File[], fileList: UploadFileItem[]) => any;
|
|
206
206
|
}, string, vue.PublicProps, Readonly<UploadProps> & Readonly<{
|
|
207
|
-
onError?: ((file: UploadFileItem, error: Error) => any) | undefined;
|
|
208
207
|
onSuccess?: ((file: UploadFileItem, response: any) => any) | undefined;
|
|
209
208
|
onChange?: ((fileList: UploadFileItem[]) => any) | undefined;
|
|
209
|
+
onError?: ((file: UploadFileItem, error: Error) => any) | undefined;
|
|
210
210
|
onProgress?: ((file: UploadFileItem, percent: number) => any) | undefined;
|
|
211
211
|
onRemove?: ((file: UploadFileItem) => any) | undefined;
|
|
212
212
|
onFinish?: ((fileList: UploadFileItem[]) => any) | undefined;
|
|
@@ -216,11 +216,11 @@ declare const __VLS_base: vue.DefineComponent<UploadProps, UploadExpose, {}, {},
|
|
|
216
216
|
data: Record<string, any>;
|
|
217
217
|
multiple: boolean;
|
|
218
218
|
draggable: boolean;
|
|
219
|
-
maxSize: number;
|
|
220
219
|
action: string;
|
|
221
220
|
headers: Record<string, string>;
|
|
222
221
|
directory: boolean;
|
|
223
222
|
accept: string;
|
|
223
|
+
maxSize: number;
|
|
224
224
|
maxCount: number;
|
|
225
225
|
pasteable: boolean;
|
|
226
226
|
chunked: boolean;
|
package/dist/constants5.d.ts
CHANGED
|
@@ -260,8 +260,8 @@ type PlayerInstance = InstanceType<typeof xgplayer.default>;
|
|
|
260
260
|
//#region src/components/C_VideoPlayer/index.vue.d.ts
|
|
261
261
|
declare const __VLS_export: vue.DefineComponent<VideoPlayerProps, VideoPlayerExpose, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
262
262
|
error: (error: Error) => any;
|
|
263
|
-
ended: () => any;
|
|
264
263
|
ready: () => any;
|
|
264
|
+
ended: () => any;
|
|
265
265
|
stateChange: (state: PlayerState) => any;
|
|
266
266
|
timeUpdate: (currentTime: number, duration: number) => any;
|
|
267
267
|
qualityChange: (quality: QualityLevel) => any;
|
|
@@ -273,8 +273,8 @@ declare const __VLS_export: vue.DefineComponent<VideoPlayerProps, VideoPlayerExp
|
|
|
273
273
|
progressUpdate: (data: ProgressData) => any;
|
|
274
274
|
}, string, vue.PublicProps, Readonly<VideoPlayerProps> & Readonly<{
|
|
275
275
|
onError?: ((error: Error) => any) | undefined;
|
|
276
|
-
onEnded?: (() => any) | undefined;
|
|
277
276
|
onReady?: (() => any) | undefined;
|
|
277
|
+
onEnded?: (() => any) | undefined;
|
|
278
278
|
onStateChange?: ((state: PlayerState) => any) | undefined;
|
|
279
279
|
onTimeUpdate?: ((currentTime: number, duration: number) => any) | undefined;
|
|
280
280
|
onQualityChange?: ((quality: QualityLevel) => any) | undefined;
|
package/dist/data.d.ts
CHANGED
|
@@ -23,10 +23,10 @@ declare const __VLS_export: vue.DefineComponent<__VLS_Props, {}, {}, {}, {}, vue
|
|
|
23
23
|
onMarkerClick?: ((marker: MapMarker$1, event: any) => any) | undefined;
|
|
24
24
|
}>, {
|
|
25
25
|
height: string;
|
|
26
|
-
zoom: number;
|
|
27
|
-
center: [number, number];
|
|
28
26
|
markers: MapMarker$1[];
|
|
29
27
|
amapKey: string;
|
|
28
|
+
center: [number, number];
|
|
29
|
+
zoom: number;
|
|
30
30
|
mapType: "osm" | "amap";
|
|
31
31
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
32
32
|
declare const _default: typeof __VLS_export;
|
package/dist/index.vue.d.ts
CHANGED
|
@@ -63,10 +63,10 @@ declare const __VLS_base: vue.DefineComponent<TableActionsProps, {}, {}, {}, {},
|
|
|
63
63
|
"onDropdown-click"?: ((item: ActionDropdownItem, action: ActionItem) => any) | undefined;
|
|
64
64
|
"onAction-click"?: ((action: ActionItem) => any) | undefined;
|
|
65
65
|
}>, {
|
|
66
|
-
config: ActionBarConfig;
|
|
67
66
|
actions: ActionItem[];
|
|
68
67
|
leftActions: ActionItem[];
|
|
69
68
|
rightActions: ActionItem[];
|
|
69
|
+
config: ActionBarConfig;
|
|
70
70
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
71
71
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
72
72
|
declare const _default: typeof __VLS_export;
|
package/dist/index11.vue.d.ts
CHANGED
|
@@ -41,29 +41,29 @@ declare const __VLS_export: vue.DefineComponent<IconProps, {
|
|
|
41
41
|
errorMessage: Readonly<vue.Ref<string, string>>; /** DOM引用 */
|
|
42
42
|
el: vue.Ref<HTMLElement | undefined, HTMLElement | undefined>;
|
|
43
43
|
}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
44
|
-
error: (type: string, error?: any) => any;
|
|
45
44
|
click: (event: MouseEvent) => any;
|
|
45
|
+
error: (type: string, error?: any) => any;
|
|
46
46
|
load: () => any;
|
|
47
47
|
}, string, vue.PublicProps, Readonly<IconProps> & Readonly<{
|
|
48
|
-
onError?: ((type: string, error?: any) => any) | undefined;
|
|
49
48
|
onClick?: ((event: MouseEvent) => any) | undefined;
|
|
49
|
+
onError?: ((type: string, error?: any) => any) | undefined;
|
|
50
50
|
onLoad?: (() => any) | undefined;
|
|
51
51
|
}>, {
|
|
52
52
|
type: "iconify" | "unocss" | "component" | "svg" | "image";
|
|
53
53
|
name: string | any;
|
|
54
|
-
size: number | string;
|
|
55
|
-
title: string;
|
|
56
54
|
color: string;
|
|
57
|
-
|
|
58
|
-
flip: "horizontal" | "vertical" | "both";
|
|
59
|
-
loading: boolean;
|
|
55
|
+
size: number | string;
|
|
60
56
|
svgPath: string;
|
|
61
57
|
viewBox: string;
|
|
62
58
|
alt: string;
|
|
63
59
|
clickable: boolean;
|
|
60
|
+
loading: boolean;
|
|
64
61
|
fallbackIcon: string;
|
|
62
|
+
title: string;
|
|
65
63
|
ariaLabel: string;
|
|
66
64
|
customClass: string;
|
|
65
|
+
rotate: number;
|
|
66
|
+
flip: "horizontal" | "vertical" | "both";
|
|
67
67
|
componentProps: Record<string, any>;
|
|
68
68
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
69
69
|
declare const _default: typeof __VLS_export;
|
package/dist/index13.vue.d.ts
CHANGED
|
@@ -58,12 +58,11 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
58
58
|
"onAuto-save"?: ((text: string) => any) | undefined;
|
|
59
59
|
"onMax-length-exceeded"?: ((currentLength: number, maxLength: number) => any) | undefined;
|
|
60
60
|
}>, {
|
|
61
|
-
height: string | number;
|
|
62
61
|
disabled: boolean;
|
|
63
|
-
mode: "edit" | "editable" | "preview";
|
|
64
|
-
placeholder: string;
|
|
65
62
|
modelValue: string;
|
|
66
|
-
|
|
63
|
+
height: string | number;
|
|
64
|
+
placeholder: string;
|
|
65
|
+
mode: "edit" | "editable" | "preview";
|
|
67
66
|
tocNavPosition: "left" | "right";
|
|
68
67
|
defaultFullscreen: boolean;
|
|
69
68
|
autofocus: boolean;
|
|
@@ -72,6 +71,7 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
72
71
|
rightToolbar: string;
|
|
73
72
|
maxLength: number;
|
|
74
73
|
showWordCount: boolean;
|
|
74
|
+
autoSave: boolean;
|
|
75
75
|
autoSaveInterval: number;
|
|
76
76
|
isDark: boolean;
|
|
77
77
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
package/dist/index15.vue.d.ts
CHANGED
|
@@ -34,13 +34,13 @@ type __VLS_Slots = {} & {
|
|
|
34
34
|
indicator?: (props: typeof __VLS_9) => any;
|
|
35
35
|
};
|
|
36
36
|
declare const __VLS_base: vue.DefineComponent<Props, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
37
|
-
strokeWidth: number;
|
|
38
|
-
time: number;
|
|
39
|
-
status: "default" | "success" | "error" | "warning" | "info";
|
|
40
37
|
percentage: number | number[];
|
|
41
38
|
isAnimation: boolean;
|
|
39
|
+
time: number;
|
|
42
40
|
indicatorPlacement: "inside" | "outside";
|
|
43
41
|
showIndicator: boolean;
|
|
42
|
+
status: "default" | "success" | "error" | "warning" | "info";
|
|
43
|
+
strokeWidth: number;
|
|
44
44
|
unit: string;
|
|
45
45
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
46
46
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
package/dist/index16.vue.d.ts
CHANGED
|
@@ -23,8 +23,8 @@ declare const __VLS_export: vue.DefineComponent<__VLS_Props, {}, {}, {}, {}, vue
|
|
|
23
23
|
onChange?: ((args_0: number) => any) | undefined;
|
|
24
24
|
"onUpdate:current"?: ((args_0: number) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
|
-
direction: "horizontal" | "vertical";
|
|
27
26
|
clickable: boolean;
|
|
27
|
+
direction: "horizontal" | "vertical";
|
|
28
28
|
current: number;
|
|
29
29
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
30
30
|
declare const _default: typeof __VLS_export;
|
package/dist/index17.vue.d.ts
CHANGED
|
@@ -76,10 +76,10 @@ declare const __VLS_export: vue.DefineComponent<__VLS_Props, {
|
|
|
76
76
|
onClose?: ((fallbackPath: string) => any) | undefined;
|
|
77
77
|
onCloseAll?: (() => any) | undefined;
|
|
78
78
|
}>, {
|
|
79
|
+
persistKey: string;
|
|
79
80
|
homePath: string;
|
|
80
81
|
homeTitle: string;
|
|
81
82
|
homeIcon: string;
|
|
82
|
-
persistKey: string;
|
|
83
83
|
contextMenuLabels: ContextMenuLabels;
|
|
84
84
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
85
85
|
declare const _default: typeof __VLS_export;
|
package/dist/index19.vue.d.ts
CHANGED
|
@@ -647,12 +647,12 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
647
647
|
onTaskClick?: ((task: GanttTask, event: Event) => any) | undefined;
|
|
648
648
|
onTaskChange?: ((task: GanttTask, changes: any) => any) | undefined;
|
|
649
649
|
}>, {
|
|
650
|
-
height: string | number;
|
|
651
650
|
theme: "light" | "dark";
|
|
652
|
-
data: GanttTask[];
|
|
653
651
|
title: string;
|
|
654
|
-
|
|
652
|
+
height: string | number;
|
|
653
|
+
data: GanttTask[];
|
|
655
654
|
showToolbar: boolean;
|
|
655
|
+
options: GanttOptions;
|
|
656
656
|
preset: GanttPreset;
|
|
657
657
|
showFullscreenButton: boolean;
|
|
658
658
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
package/dist/index2.vue.d.ts
CHANGED
|
@@ -20,9 +20,9 @@ declare const __VLS_export: vue.DefineComponent<Props, {}, {}, {}, {}, vue.Compo
|
|
|
20
20
|
}, string, vue.PublicProps, Readonly<Props> & Readonly<{
|
|
21
21
|
onError?: ((error: Error) => any) | undefined;
|
|
22
22
|
}>, {
|
|
23
|
+
height: number;
|
|
23
24
|
format: "CODE128" | "CODE39" | "EAN13" | "EAN8" | "UPC" | "ITF14" | "MSI" | "pharmacode";
|
|
24
25
|
width: number;
|
|
25
|
-
height: number;
|
|
26
26
|
showText: boolean;
|
|
27
27
|
fontSize: number;
|
|
28
28
|
textPosition: "bottom" | "top";
|
package/dist/index7.vue.d.ts
CHANGED
|
@@ -25,20 +25,20 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
25
25
|
copyCode: typeof copyCode;
|
|
26
26
|
toggleFullscreen: typeof toggleFullscreen;
|
|
27
27
|
}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
28
|
-
copy: (code: string) => any;
|
|
29
28
|
click: (event: MouseEvent) => any;
|
|
29
|
+
copy: (code: string) => any;
|
|
30
30
|
fullscreen: (isFullscreen: boolean) => any;
|
|
31
31
|
}, string, vue.PublicProps, Readonly<Props> & Readonly<{
|
|
32
|
-
onCopy?: ((code: string) => any) | undefined;
|
|
33
32
|
onClick?: ((event: MouseEvent) => any) | undefined;
|
|
33
|
+
onCopy?: ((code: string) => any) | undefined;
|
|
34
34
|
onFullscreen?: ((isFullscreen: boolean) => any) | undefined;
|
|
35
35
|
}>, {
|
|
36
|
-
wordWrap: boolean;
|
|
37
36
|
trim: boolean;
|
|
38
37
|
code: string;
|
|
39
38
|
language: string;
|
|
40
39
|
showHeader: boolean;
|
|
41
40
|
showLineNumbers: boolean;
|
|
41
|
+
wordWrap: boolean;
|
|
42
42
|
showFullscreen: boolean;
|
|
43
43
|
autoLoadLanguage: boolean;
|
|
44
44
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
package/dist/index8.vue.d.ts
CHANGED
|
@@ -40,8 +40,8 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
40
40
|
"onUpdate:smartRange"?: ((value: DateRangeValue) => any) | undefined;
|
|
41
41
|
}>, {
|
|
42
42
|
disabled: boolean;
|
|
43
|
-
mode: DatePickerMode;
|
|
44
43
|
placeholder: string;
|
|
44
|
+
mode: DatePickerMode;
|
|
45
45
|
startPlaceholder: string;
|
|
46
46
|
endPlaceholder: string;
|
|
47
47
|
disabledBeforeToday: boolean;
|
package/dist/index9.vue.d.ts
CHANGED
|
@@ -28,11 +28,11 @@ declare const __VLS_export: vue.DefineComponent<Props, {
|
|
|
28
28
|
"onEditor-mounted"?: ((editor: any) => any) | undefined;
|
|
29
29
|
"onEditor-change"?: ((html: string) => any) | undefined;
|
|
30
30
|
}>, {
|
|
31
|
-
height: number;
|
|
32
31
|
disabled: boolean;
|
|
33
32
|
theme: "light" | "dark";
|
|
34
|
-
placeholder: string;
|
|
35
33
|
modelValue: string;
|
|
34
|
+
height: number;
|
|
35
|
+
placeholder: string;
|
|
36
36
|
readonly: boolean;
|
|
37
37
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
|
|
38
38
|
declare const _default: typeof __VLS_export;
|
package/dist/menuAdapter.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{t as e}from"./C_Icon2.js";import{h as t}from"vue";const n=e=>e.startsWith(`/`)?e:`/${e}`,r=e=>e.path?n(e.path):``,i=e=>e.meta?.title||e.name||``,a=e=>!e.meta?.hidden,o=n=>{if(n){if(typeof n==`string`)return()=>t(e,{name:n,size:18});if(typeof n==`function`)return n}};function s(e,t={}){let{labelFormatter:n=e=>e,getKey:s=r,getLabel:c=i,filter:l=a,renderIcon:u=o,recursive:d=!0}=t,f=e=>e.filter(l).map(e=>{let t=e.meta?.icon||e.icon,r=d&&e.children?.length?f(e.children):void 0;return{key:s(e),label:n(c(e)),disabled:e.disabled||!1,icon:u(t),...e.type&&{type:e.type},...r?.length&&{children:r}}});return f(e)}function c(e,t=a){let n=[],r=e=>{for(let i of e)t(i)&&n.push(i),i.children?.length&&r(i.children)};return r(e),n}export{c as n,s as t};
|
|
2
2
|
//# sourceMappingURL=menuAdapter.js.map
|