This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<template v-for="item in list" :key="item.path">
|
||||
<template v-if="!item.children || !item.children.length || item.meta?.single">
|
||||
<t-menu-item :name="item.path" :value="getPath(item)" :to="item.path">
|
||||
<template #icon>
|
||||
<component :is="menuIcon(item)" class="t-icon"></component>
|
||||
</template>
|
||||
{{ renderMenuTitle(item.title) }}
|
||||
</t-menu-item>
|
||||
</template>
|
||||
<t-submenu v-else :name="item.path" :value="item.path" :title="renderMenuTitle(item.title)">
|
||||
<template #icon>
|
||||
<component :is="menuIcon(item)" class="t-icon"></component>
|
||||
</template>
|
||||
<menu-content v-if="item.children" :nav-data="item.children" />
|
||||
</t-submenu>
|
||||
</template>
|
||||
</template>
|
||||
<script setup lang="tsx">
|
||||
import type { PropType } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import type { LocalizedTitle } from '@/locales';
|
||||
import { useLocale } from '@/locales/useLocale';
|
||||
import { getActive } from '@/router';
|
||||
import type { MenuRoute } from '@/types/interface';
|
||||
|
||||
type ListItemType = MenuRoute;
|
||||
|
||||
const { navData } = defineProps({
|
||||
navData: {
|
||||
type: Array as PropType<MenuRoute[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const active = computed(() => getActive());
|
||||
|
||||
const { locale } = useLocale();
|
||||
|
||||
const list = computed(() => {
|
||||
return getMenuList(navData);
|
||||
});
|
||||
|
||||
const menuIcon = (item: ListItemType) => {
|
||||
if (typeof item.icon === 'string') return <t-icon name={item.icon} />;
|
||||
const RenderIcon = item.icon;
|
||||
return RenderIcon;
|
||||
};
|
||||
|
||||
const renderMenuTitle = (title?: LocalizedTitle) => {
|
||||
if (!title) return '';
|
||||
return title[locale.value as keyof LocalizedTitle] || '';
|
||||
};
|
||||
|
||||
function getMenuList(list: MenuRoute[], basePath?: string): MenuRoute[] {
|
||||
if (!list || list.length === 0) {
|
||||
return [];
|
||||
}
|
||||
// 如果meta中有orderNo则按照从小到大排序
|
||||
list.sort((a, b) => {
|
||||
return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0);
|
||||
});
|
||||
return list
|
||||
.map((item) => {
|
||||
const path = !basePath
|
||||
? item.path
|
||||
: item.path === ''
|
||||
? basePath
|
||||
: item.path.startsWith('/')
|
||||
? item.path
|
||||
: `${basePath}/${item.path}`;
|
||||
|
||||
return {
|
||||
path,
|
||||
title: item.meta?.title as LocalizedTitle | undefined,
|
||||
icon: item.meta?.icon,
|
||||
children: getMenuList(item.children, path),
|
||||
meta: item.meta,
|
||||
redirect: item.redirect,
|
||||
} as MenuRoute;
|
||||
})
|
||||
.filter((item) => item.meta && item.meta.hidden !== true);
|
||||
}
|
||||
|
||||
const getPath = (item: ListItemType) => {
|
||||
const activeLevel = active.value.split('/').length;
|
||||
const pathLevel = item.path.split('/').length;
|
||||
if (activeLevel > pathLevel && active.value.startsWith(item.path)) {
|
||||
return active.value;
|
||||
}
|
||||
|
||||
if (active.value === item.path) {
|
||||
return active.value;
|
||||
}
|
||||
|
||||
return item.meta?.single ? item.redirect : item.path;
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user