mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 22:07:16 +08:00
feat: 菜单支持右键打开,close #954
This commit is contained in:
@@ -5,9 +5,9 @@ import SideMenu from './components/SideMenu.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div h-screen flex flex-col>
|
||||
<side-logo flex-shrink-0 />
|
||||
<side-menu flex-shrink-0 flex-grow-1 />
|
||||
<side-setting flex-shrink-0 />
|
||||
<div class="h-screen flex flex-col">
|
||||
<side-logo class="flex-shrink-0" />
|
||||
<side-menu class="flex-shrink-0 flex-grow-1" />
|
||||
<side-setting class="flex-shrink-0" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { isUrl, renderIcon } from '@/utils'
|
||||
|
||||
import type { MenuInst, MenuOption } from 'naive-ui'
|
||||
import type { VNodeChild } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { Meta, RouteType } from '~/types/router'
|
||||
|
||||
const router = useRouter()
|
||||
@@ -32,7 +33,7 @@ function resolvePath(basePath: string, path: string) {
|
||||
}
|
||||
|
||||
type MenuItem = MenuOption & {
|
||||
label: string
|
||||
label: () => VNodeChild
|
||||
key: string
|
||||
path: string
|
||||
children?: Array<MenuItem>
|
||||
@@ -40,7 +41,16 @@ type MenuItem = MenuOption & {
|
||||
|
||||
function getMenuItem(route: RouteType, basePath = ''): MenuItem {
|
||||
let menuItem: MenuItem = {
|
||||
label: route.meta?.title ? translateTitle(route.meta.title) : route.name,
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: { name: route.name as string }
|
||||
},
|
||||
{
|
||||
default: () => (route.meta?.title ? translateTitle(route.meta.title) : route.name)
|
||||
}
|
||||
),
|
||||
key: route.name,
|
||||
path: resolvePath(basePath, route.path),
|
||||
icon: getIcon(route.meta)
|
||||
@@ -55,11 +65,21 @@ function getMenuItem(route: RouteType, basePath = ''): MenuItem {
|
||||
|
||||
if (!visibleChildren.length) return menuItem
|
||||
|
||||
if (visibleChildren.length === 1) {
|
||||
if (visibleChildren.length === 1 && visibleChildren[0]) {
|
||||
// 单个子路由处理
|
||||
const singleRoute = visibleChildren[0]
|
||||
menuItem = {
|
||||
label: singleRoute.meta?.title ? translateTitle(singleRoute.meta.title) : singleRoute.name,
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: { name: singleRoute.name as string }
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
singleRoute.meta?.title ? translateTitle(singleRoute.meta.title) : singleRoute?.name
|
||||
}
|
||||
),
|
||||
key: singleRoute.name,
|
||||
path: resolvePath(menuItem.path, singleRoute.path),
|
||||
icon: getIcon(singleRoute.meta)
|
||||
@@ -68,7 +88,7 @@ function getMenuItem(route: RouteType, basePath = ''): MenuItem {
|
||||
? singleRoute.children.filter((item: RouteType) => item.name && !item.isHidden)
|
||||
: []
|
||||
|
||||
if (visibleItems.length === 1) menuItem = getMenuItem(visibleItems[0], menuItem.path)
|
||||
if (visibleItems.length === 1) menuItem = getMenuItem(visibleItems[0]!, menuItem.path)
|
||||
else if (visibleItems.length > 1)
|
||||
menuItem.children = visibleItems.map((item) => getMenuItem(item, menuItem.path))
|
||||
} else {
|
||||
|
||||
@@ -65,44 +65,44 @@ const menus = computed<TreeSelectOption[]>(() => {
|
||||
</template>
|
||||
{{ $gettext('Menu Settings') }}
|
||||
</n-tooltip>
|
||||
<n-modal
|
||||
v-model:show="settingModal"
|
||||
preset="card"
|
||||
:title="$gettext('Menu Settings')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="settingModal = false"
|
||||
@mask-click="settingModal = false"
|
||||
>
|
||||
<n-form>
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'Settings are saved in the browser and will be reset after clearing the browser cache'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Custom Logo')">
|
||||
<n-input
|
||||
v-model:value="themeStore.logo"
|
||||
:placeholder="$gettext('Please enter the complete URL')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Hide Menu')">
|
||||
<n-tree-select
|
||||
cascade
|
||||
checkable
|
||||
clearable
|
||||
multiple
|
||||
:options="menus"
|
||||
v-model:value="permissionStore.hiddenRoutes"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
</n-modal>
|
||||
</div>
|
||||
<n-modal
|
||||
v-model:show="settingModal"
|
||||
preset="card"
|
||||
:title="$gettext('Menu Settings')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="settingModal = false"
|
||||
@mask-click="settingModal = false"
|
||||
>
|
||||
<n-form>
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'Settings are saved in the browser and will be reset after clearing the browser cache'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Custom Logo')">
|
||||
<n-input
|
||||
v-model:value="themeStore.logo"
|
||||
:placeholder="$gettext('Please enter the complete URL')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Hide Menu')">
|
||||
<n-tree-select
|
||||
cascade
|
||||
checkable
|
||||
clearable
|
||||
multiple
|
||||
:options="menus"
|
||||
v-model:value="permissionStore.hiddenRoutes"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user