2
0
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:
2025-08-23 02:00:15 +08:00
parent 1331c10b65
commit 74bf295acd
3 changed files with 68 additions and 48 deletions

View File

@@ -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>

View File

@@ -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 {

View File

@@ -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>