commit
1f2df3e944
|
|
@ -12,11 +12,13 @@
|
||||||
"axios",
|
"axios",
|
||||||
"brotli",
|
"brotli",
|
||||||
"cascader",
|
"cascader",
|
||||||
|
"chatcmpl",
|
||||||
"clsx",
|
"clsx",
|
||||||
"dedup",
|
"dedup",
|
||||||
"defu",
|
"defu",
|
||||||
"demi",
|
"demi",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"echart",
|
||||||
"echarts",
|
"echarts",
|
||||||
"ependencies",
|
"ependencies",
|
||||||
"esbuild",
|
"esbuild",
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
"changeset": "pnpm exec changeset",
|
"changeset": "pnpm exec changeset",
|
||||||
"check": "pnpm run check:circular && pnpm run check:dep && pnpm run check:type && pnpm check:cspell",
|
"check": "pnpm run check:circular && pnpm run check:dep && pnpm run check:type && pnpm check:cspell",
|
||||||
"check:circular": "vsh check-circular",
|
"check:circular": "vsh check-circular",
|
||||||
"check:cspell": "cspell lint **/*.ts **/README.md .changeset/*.md --no-progress",
|
"check:cspell": "cspell lint \"**/*.ts\" \"**/README.md\" \".changeset/*.md\" --no-progress",
|
||||||
"check:dep": "vsh check-dep",
|
"check:dep": "vsh check-dep",
|
||||||
"check:type": "turbo run typecheck",
|
"check:type": "turbo run typecheck",
|
||||||
"clean": "node ./scripts/clean.mjs",
|
"clean": "node ./scripts/clean.mjs",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import type { RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
|
import type { Recordable } from './helper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扩展路由原始对象
|
* 扩展路由原始对象
|
||||||
*/
|
*/
|
||||||
|
|
@ -66,6 +68,10 @@ interface MenuRecordRaw extends MenuRecordBadgeRaw {
|
||||||
* 菜单路径,唯一,可当作key
|
* 菜单路径,唯一,可当作key
|
||||||
*/
|
*/
|
||||||
path: string;
|
path: string;
|
||||||
|
/**
|
||||||
|
* 菜单参数
|
||||||
|
*/
|
||||||
|
query?: Recordable<any>;
|
||||||
/**
|
/**
|
||||||
* 是否显示菜单
|
* 是否显示菜单
|
||||||
* @default true
|
* @default true
|
||||||
|
|
|
||||||
|
|
@ -307,14 +307,14 @@ onUnmounted(() => {
|
||||||
<aside
|
<aside
|
||||||
ref="asideRef"
|
ref="asideRef"
|
||||||
:style="style"
|
:style="style"
|
||||||
class="fixed top-0 left-0 h-full transition-all duration-150"
|
class="fixed left-0 top-0 h-full transition-all duration-150"
|
||||||
|
:class="theme"
|
||||||
@mouseenter="handleMouseenter"
|
@mouseenter="handleMouseenter"
|
||||||
@mouseleave="handleMouseleave"
|
@mouseleave="handleMouseleave"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="h-full"
|
class="h-full"
|
||||||
:class="[
|
:class="[
|
||||||
theme,
|
|
||||||
{
|
{
|
||||||
'bg-sidebar-deep': isSidebarMixed,
|
'bg-sidebar-deep': isSidebarMixed,
|
||||||
'border-r border-border bg-sidebar': !isSidebarMixed,
|
'border-r border-border bg-sidebar': !isSidebarMixed,
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@
|
||||||
"@vben-core/shared": "workspace:*",
|
"@vben-core/shared": "workspace:*",
|
||||||
"@vben-core/typings": "workspace:*",
|
"@vben-core/typings": "workspace:*",
|
||||||
"@vueuse/core": "catalog:",
|
"@vueuse/core": "catalog:",
|
||||||
|
"qs": "catalog:",
|
||||||
"vue": "catalog:"
|
"vue": "catalog:"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/qs": "catalog:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
|
||||||
import { useNamespace } from '@vben-core/composables';
|
import { useNamespace } from '@vben-core/composables';
|
||||||
import { VbenIcon, VbenTooltip } from '@vben-core/shadcn-ui';
|
import { VbenIcon, VbenTooltip } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
import { MenuBadge } from '../components';
|
import { MenuBadge } from '../components';
|
||||||
import { useMenu, useMenuContext, useSubMenuContext } from '../hooks';
|
import { useMenu, useMenuContext, useSubMenuContext } from '../hooks';
|
||||||
|
|
||||||
|
|
@ -54,6 +56,7 @@ const item: MenuItemRegistered = reactive({
|
||||||
active,
|
active,
|
||||||
parentPaths: parentPaths.value,
|
parentPaths: parentPaths.value,
|
||||||
path: props.path || '',
|
path: props.path || '',
|
||||||
|
query: props.query,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -81,42 +84,50 @@ onBeforeUnmount(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<li
|
<a
|
||||||
:class="[
|
:href="
|
||||||
rootMenu.theme,
|
(item.parentPaths.at(-1) ?? '') +
|
||||||
b(),
|
(item?.query ? `?${qs.stringify(item?.query)}` : '')
|
||||||
is('active', active),
|
"
|
||||||
is('disabled', disabled),
|
@click.prevent.stop="handleClick"
|
||||||
is('collapse-show-title', collapseShowTitle),
|
|
||||||
]"
|
|
||||||
role="menuitem"
|
|
||||||
@click.stop="handleClick"
|
|
||||||
>
|
>
|
||||||
<VbenTooltip
|
<li
|
||||||
v-if="showTooltip"
|
:class="[
|
||||||
:content-class="[rootMenu.theme]"
|
rootMenu.theme,
|
||||||
side="right"
|
b(),
|
||||||
|
is('active', active),
|
||||||
|
is('disabled', disabled),
|
||||||
|
is('collapse-show-title', collapseShowTitle),
|
||||||
|
]"
|
||||||
|
role="menuitem"
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<!-- -->
|
||||||
<div :class="[nsMenu.be('tooltip', 'trigger')]">
|
<VbenTooltip
|
||||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" fallback />
|
v-if="showTooltip"
|
||||||
<slot></slot>
|
:content-class="[rootMenu.theme]"
|
||||||
<span v-if="collapseShowTitle" :class="nsMenu.e('name')">
|
side="right"
|
||||||
<slot name="title"></slot>
|
>
|
||||||
</span>
|
<template #trigger>
|
||||||
</div>
|
<div :class="[nsMenu.be('tooltip', 'trigger')]">
|
||||||
</template>
|
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" fallback />
|
||||||
<slot name="title"></slot>
|
<slot></slot>
|
||||||
</VbenTooltip>
|
<span v-if="collapseShowTitle" :class="nsMenu.e('name')">
|
||||||
<div v-show="!showTooltip" :class="[e('content')]">
|
<slot name="title"></slot>
|
||||||
<MenuBadge
|
</span>
|
||||||
v-if="rootMenu.props.mode !== 'horizontal'"
|
</div>
|
||||||
class="right-2"
|
</template>
|
||||||
v-bind="props"
|
<slot name="title"></slot>
|
||||||
/>
|
</VbenTooltip>
|
||||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" />
|
<div v-show="!showTooltip" :class="[e('content')]">
|
||||||
<slot></slot>
|
<MenuBadge
|
||||||
<slot name="title"></slot>
|
v-if="rootMenu.props.mode !== 'horizontal'"
|
||||||
</div>
|
class="right-2"
|
||||||
</li>
|
v-bind="props"
|
||||||
|
/>
|
||||||
|
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" />
|
||||||
|
<slot></slot>
|
||||||
|
<slot name="title"></slot>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -212,15 +212,15 @@ const enableScroll = computed(
|
||||||
() => props.scrollToActive && props.mode === 'vertical' && !props.collapse,
|
() => props.scrollToActive && props.mode === 'vertical' && !props.collapse,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { scrollToActiveItem } = useMenuScroll(activePath, {
|
useMenuScroll(activePath, {
|
||||||
enable: enableScroll,
|
enable: enableScroll,
|
||||||
delay: 320,
|
delay: 320,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听 activePath 变化,自动滚动到激活项
|
// 监听 activePath 变化,自动滚动到激活项
|
||||||
watch(activePath, () => {
|
// watch(activePath, () => {
|
||||||
scrollToActiveItem();
|
// scrollToActiveItem();
|
||||||
});
|
// });
|
||||||
|
|
||||||
// 默认展开菜单
|
// 默认展开菜单
|
||||||
function initMenu() {
|
function initMenu() {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ const hasChildren = computed(() => {
|
||||||
:badge-variants="menu.badgeVariants"
|
:badge-variants="menu.badgeVariants"
|
||||||
:icon="menu.icon"
|
:icon="menu.icon"
|
||||||
:path="menu.path"
|
:path="menu.path"
|
||||||
|
:query="menu.query"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>{{ menu.name }}</span>
|
<span>{{ menu.name }}</span>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import type { Component, Ref } from 'vue';
|
import type { Component, Ref } from 'vue';
|
||||||
|
|
||||||
import type { MenuRecordBadgeRaw, ThemeModeType } from '@vben-core/typings';
|
import type {
|
||||||
|
MenuRecordBadgeRaw,
|
||||||
|
Recordable,
|
||||||
|
ThemeModeType,
|
||||||
|
} from '@vben-core/typings';
|
||||||
|
|
||||||
interface MenuProps {
|
interface MenuProps {
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,12 +95,17 @@ interface MenuItemProps extends MenuRecordBadgeRaw {
|
||||||
* @zh_CN menuitem 名称
|
* @zh_CN menuitem 名称
|
||||||
*/
|
*/
|
||||||
path: string;
|
path: string;
|
||||||
|
/**
|
||||||
|
* @zh_CN 菜单所携带的参数
|
||||||
|
*/
|
||||||
|
query?: Recordable<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenuItemRegistered {
|
interface MenuItemRegistered {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
parentPaths: string[];
|
parentPaths: string[];
|
||||||
path: string;
|
path: string;
|
||||||
|
query?: Recordable<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenuItemClicked {
|
interface MenuItemClicked {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ function generateMenus(
|
||||||
link,
|
link,
|
||||||
order,
|
order,
|
||||||
title = '',
|
title = '',
|
||||||
|
query,
|
||||||
} = meta;
|
} = meta;
|
||||||
|
|
||||||
// 确保菜单名称不为空
|
// 确保菜单名称不为空
|
||||||
|
|
@ -71,6 +72,7 @@ function generateMenus(
|
||||||
badgeVariants,
|
badgeVariants,
|
||||||
icon,
|
icon,
|
||||||
name,
|
name,
|
||||||
|
query,
|
||||||
order,
|
order,
|
||||||
parent: route.parent,
|
parent: route.parent,
|
||||||
parents: route.parents,
|
parents: route.parents,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue