Files
kaidi/frontend/src/layouts/components/MenuContent.vue
T
Qiufeng 12d78b4c86
Release / release (push) Canceled after 0s
feat: add system operations dashboard
2026-08-19 13:51:48 +08:00

100 lines
2.8 KiB
Vue

<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 : item.path;
};
</script>