mirror of
https://github.com/chansee97/nova-admin.git
synced 2025-04-05 19:41:59 +08:00
fix: perfect menu manage
This commit is contained in:
parent
cd67da6b00
commit
de368c7e9e
2
.env
2
.env
@ -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
|
||||
|
16
src/components/common/HelpInfo.vue
Normal file
16
src/components/common/HelpInfo.vue
Normal 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>
|
@ -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" />
|
@ -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>
|
@ -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'
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
|
2
src/typings/route.d.ts
vendored
2
src/typings/route.d.ts
vendored
@ -19,7 +19,7 @@ declare namespace AppRoute {
|
||||
order?: number
|
||||
/* 嵌套外链 */
|
||||
herf?: string
|
||||
/** 当前路由不在左侧菜单显示,但需要需要高亮某个菜单的情况 */
|
||||
/** 当前路由不在左侧菜单显示,但需要高亮某个菜单的情况 */
|
||||
activeMenu?: string
|
||||
/** 当前路由是否会被添加到Tab中 */
|
||||
withoutTab?: boolean
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user