fix: perfect menu manage

This commit is contained in:
chansee97 2024-04-13 12:26:39 +08:00
parent cd67da6b00
commit de368c7e9e
12 changed files with 71 additions and 55 deletions

2
.env
View File

@ -5,7 +5,7 @@ VITE_APP_NAME=Nova - Admin
# 路由模式
VITE_ROUTE_MODE = web
# 权限路由模式: static dynamic
VITE_AUTH_ROUTE_MODE=dynamic
VITE_AUTH_ROUTE_MODE=static
# 设置登陆后跳转地址
VITE_HOME_PATH = /dashboard/workbench

View File

@ -0,0 +1,16 @@
<script setup lang="ts">
interface Props {
message: string
}
const props = defineProps<Props>()
</script>
<template>
<n-tooltip :show-arrow="false" trigger="hover">
<template #trigger>
<icon-park-outline-help />
</template>
{{ props.message }}
</n-tooltip>
</template>

View File

@ -1,6 +1,13 @@
<script setup lang="ts">
import { icons } from './icons'
interface Props {
disabled?: boolean
}
const props = withDefaults(defineProps<Props>(), {
disabled: false,
})
const value = defineModel('value', { type: String })
const searchValue = ref('')
const showPopover = ref(false)
@ -16,11 +23,11 @@ function handleSelectIcon(icon: string) {
</script>
<template>
<n-popover v-model:show="showPopover" placement="bottom" trigger="click">
<n-popover v-model:show="showPopover" placement="bottom" trigger="click" :disabled="props.disabled">
<template #trigger>
<n-input :value="value" readonly :placeholder="t('components.iconSelector.inputPlaceholder')">
<template #suffix>
<nova-icon :icon="value || 'icon-park-outline:all-application'" />
<nova-icon :icon="value" />
</template>
</n-input>
</template>
@ -30,9 +37,7 @@ function handleSelectIcon(icon: string) {
<div class="w-400px">
<div v-if="iconList.length > 0" class="grid grid-cols-9 h-auto overflow-auto gap-1">
<div
v-for="(item, index) in iconList"
:key="index"
class="border border-gray-200 m-2px p-5px flex-center"
v-for="(item, index) in iconList" :key="index" class="border border-gray-200 m-2px p-5px flex-center"
@click="handleSelectIcon(item)"
>
<nova-icon :icon="item" :size="24" />

View File

@ -1,31 +0,0 @@
<script lang="ts" setup>
const props = defineProps({
prefix: {
type: String,
default: 'icon',
},
name: {
type: String,
required: true,
},
size: {
type: Number,
default: 18,
},
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
<template>
<svg
aria-hidden="true"
:width="`${props.size}px`"
:height="`${props.size}px`"
class="inline"
>
<use
:xlink:href="symbolId"
fill="currentColor"
/>
</svg>
</template>

View File

@ -1,6 +1,6 @@
import type { App } from 'vue'
import AppVue from './App.vue'
import AppLoading from './components/common/appLoading.vue'
import AppLoading from './components/common/AppLoading.vue'
import { installRouter } from '@/router'
import { installPinia } from '@/store'

View File

@ -261,7 +261,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.requiresAuth': true,
'meta.icon': 'logos:vueuse',
'meta.herf': 'https://vueuse.org/guide/',
'componentPath': '/docments/vueuse/index.vue',
'componentPath': 'null',
'id': 27,
'pid': 24,
},

View File

@ -19,7 +19,7 @@ declare namespace AppRoute {
order?: number
/* 嵌套外链 */
herf?: string
/** 当前路由不在左侧菜单显示,但需要需要高亮某个菜单的情况 */
/** 当前路由不在左侧菜单显示,但需要高亮某个菜单的情况 */
activeMenu?: string
/** 当前路由是否会被添加到Tab中 */
withoutTab?: boolean

View File

@ -1,4 +1,5 @@
<script setup lang="ts">
import HelpInfo from '@/components/common/HelpInfo.vue'
import { useLoading } from '@/hooks'
interface Props {
@ -177,10 +178,14 @@ const options = [
:disabled="modalType === 'view'"
>
<n-grid :cols="2" :x-gap="18">
<n-form-item-grid-item :span="2" label="父级目录" path="pid">
<n-form-item-grid-item :span="2" path="pid">
<template #label>
父级目录
<HelpInfo message="不填写则为顶层菜单" />
</template>
<n-tree-select
v-model:value="formModel.pid" filterable clearable :options="dirTreeOptions" key-field="id" label-field="meta.title"
children-field="children" placeholder="请选择父级目录"
v-model:value="formModel.pid" filterable clearable :options="dirTreeOptions" key-field="id"
label-field="meta.title" children-field="children" placeholder="请选择父级目录"
/>
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="菜单名称" path="name">
@ -189,7 +194,7 @@ const options = [
<n-form-item-grid-item :span="1" label="标题" path="meta.title">
<n-input v-model:value="formModel['meta.title']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="2" label="路径" path="path">
<n-form-item-grid-item :span="2" label="路由路径" path="path">
<n-input v-model:value="formModel.path" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="菜单类型" path="meta.menuType">
@ -205,7 +210,7 @@ const options = [
</n-radio-group>
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="图标" path="meta.icon">
<icon-select v-model:value="formModel['meta.icon']" />
<icon-select v-model:value="formModel['meta.icon']" :disabled="modalType === 'view'" />
</n-form-item-grid-item>
<n-form-item-grid-item v-if="formModel['meta.menuType'] === 'page'" :span="2" label="组件路径" path="componentPath">
<n-input v-model:value="formModel.componentPath" />
@ -213,28 +218,49 @@ const options = [
<n-form-item-grid-item :span="1" label="菜单排序" path="meta.order">
<n-input-number v-model:value="formModel['meta.order']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="外链页面" path="meta.herf">
<n-form-item-grid-item v-if="formModel['meta.menuType'] === 'page'" :span="1" path="meta.herf">
<template #label>
外链页面
<HelpInfo message="填写后,点击菜单将跳转到该地址,组件路径任意填写" />
</template>
<n-input v-model:value="formModel['meta.herf']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="登录访问" path="meta.requiresAuth">
<n-switch v-model:value="formModel['meta.requiresAuth']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="页面缓存" path="meta.keepAlive">
<n-form-item-grid-item
v-if="formModel['meta.menuType'] === 'page'" :span="1" label="页面缓存"
path="meta.keepAlive"
>
<n-switch v-model:value="formModel['meta.keepAlive']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="标签栏可见" path="meta.withoutTab">
<n-form-item-grid-item
v-if="formModel['meta.menuType'] === 'page'" :span="1" label="标签栏可见"
path="meta.withoutTab"
>
<n-switch v-model:value="formModel['meta.withoutTab']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="常驻标签栏" path="meta.pinTab">
<n-form-item-grid-item v-if="formModel['meta.menuType'] === 'page'" :span="1" label="常驻标签栏" path="meta.pinTab">
<n-switch v-model:value="formModel['meta.pinTab']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="1" label="侧边菜单隐藏" path="meta.hide">
<n-switch v-model:value="formModel['meta.hide']" />
</n-form-item-grid-item>
<n-form-item-grid-item v-if="formModel['meta.hide']" :span="2" label="高亮菜单" path="meta.activeMenu">
<n-form-item-grid-item
v-if="formModel['meta.menuType'] === 'page' && formModel['meta.hide']" :span="2"
path="meta.activeMenu"
>
<template #label>
高亮菜单
<HelpInfo message="当前路由不在左侧菜单显示,但需要高亮某个菜单" />
</template>
<n-input v-model:value="formModel['meta.activeMenu']" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="2" label="访问角色" path="meta.roles">
<n-form-item-grid-item :span="2" path="meta.roles">
<template #label>
访问角色
<HelpInfo message="不填写则表示所有角色都可以访问" />
</template>
<n-select v-model:value="formModel['meta.roles']" multiple filterable :options="options" />
</n-form-item-grid-item>
</n-grid>

View File

@ -24,6 +24,7 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
title: '图标',
align: 'center',
key: 'meta.icon',
width: '6em',
render: (row) => {
return row['meta.icon'] && renderIcon(row['meta.icon'], { size: 20 })()
},
@ -31,7 +32,6 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
{
title: '标题',
align: 'center',
width: 200,
key: 'meta.title',
ellipsis: {
tooltip: true,
@ -40,7 +40,6 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
{
title: '路径',
key: 'path',
width: 300,
ellipsis: {
tooltip: true,
},
@ -49,7 +48,6 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
{
title: '组件路径',
key: 'componentPath',
width: 300,
ellipsis: {
tooltip: true,
},
@ -61,11 +59,13 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
title: '排序值',
key: 'meta.order',
align: 'center',
width: '6em',
},
{
title: '菜单类型',
align: 'center',
key: 'meta.menuType',
width: '6em',
render: (row) => {
const menuType = row['meta.menuType'] || 'page'
const menuTagType: Record<AppRoute.MenuType, NaiveUI.ThemeColor> = {
@ -98,7 +98,7 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
<NPopconfirm onPositiveClick={() => deleteData(rowData.id)}>
{{
default: () => '确认删除',
trigger: () => <NButton size="small">删除</NButton>,
trigger: () => <NButton size="small" type="error">删除</NButton>,
}}
</NPopconfirm>
</NSpace>