<template>
|
<template v-for="(item, index) in filteredMenuItems" :key="getUniqueKey(item, index)">
|
<ElSubMenu v-if="hasChildren(item)" :index="item.path || item.meta.title" :level="level">
|
<template #title>
|
<div class="menu-icon flex-cc">
|
<ArtSvgIcon
|
:icon="item.meta.icon"
|
:color="theme?.iconColor"
|
:style="{ color: theme.iconColor }"
|
/>
|
</div>
|
<span class="menu-name">
|
{{ formatMenuTitle(item.meta.title) }}
|
</span>
|
<div v-if="item.meta.showBadge" class="art-badge" style="right: 10px" />
|
</template>
|
|
<SidebarSubmenu
|
:list="item.children"
|
:is-mobile="isMobile"
|
:level="level + 1"
|
:theme="theme"
|
@close="closeMenu"
|
/>
|
</ElSubMenu>
|
|
<ElMenuItem
|
v-else
|
:index="isExternalLink(item) ? undefined : item.path || item.meta.title"
|
:level-item="level + 1"
|
@click="goPage(item)"
|
>
|
<div class="menu-icon flex-cc">
|
<ArtSvgIcon
|
:icon="item.meta.icon"
|
:color="theme?.iconColor"
|
:style="{ color: theme.iconColor }"
|
/>
|
</div>
|
<div
|
v-show="item.meta.showBadge && level === 0 && !menuOpen"
|
class="art-badge"
|
style="right: 5px"
|
/>
|
|
<template #title>
|
<span class="menu-name">
|
{{ formatMenuTitle(item.meta.title) }}
|
</span>
|
<div v-if="item.meta.showBadge" class="art-badge" />
|
<div v-if="item.meta.showTextBadge && (level > 0 || menuOpen)" class="art-text-badge">
|
{{ item.meta.showTextBadge }}
|
</div>
|
</template>
|
</ElMenuItem>
|
</template>
|
</template>
|
|
<script setup>
|
import { formatMenuTitle } from '@/utils/router'
|
|
import { computed } from 'vue'
|
import { handleMenuJump } from '@/utils/navigation'
|
import { useSettingStore } from '@/store/modules/setting'
|
const props = defineProps({
|
title: { required: false, default: '' },
|
list: { required: false, default: () => [] },
|
theme: { required: false, default: () => ({}) },
|
isMobile: { required: false, default: false },
|
level: { required: false, default: 0 }
|
})
|
const emit = defineEmits(['close'])
|
const settingStore = useSettingStore()
|
const { menuOpen } = storeToRefs(settingStore)
|
const filteredMenuItems = computed(() => filterRoutes(props.list))
|
const goPage = (item) => {
|
closeMenu()
|
handleMenuJump(item)
|
}
|
const closeMenu = () => {
|
emit('close')
|
}
|
const isNavigableRoute = (item) => {
|
return !!(
|
!item.meta.isHide &&
|
((item.path && item.path.trim()) || item.meta.link || item.meta.isIframe === true) &&
|
(item.component || item.meta.link || item.meta.isIframe === true)
|
)
|
}
|
const filterRoutes = (items) => {
|
return items
|
.filter((item) => {
|
if (item.meta.isHide) {
|
return false
|
}
|
if (item.children && item.children.length > 0) {
|
const filteredChildren = filterRoutes(item.children)
|
return filteredChildren.length > 0 || isNavigableRoute(item)
|
}
|
return isNavigableRoute(item)
|
})
|
.map((item) => ({
|
...item,
|
children: item.children ? filterRoutes(item.children) : void 0
|
}))
|
}
|
const hasChildren = (item) => {
|
if (!item.children || item.children.length === 0) {
|
return false
|
}
|
const filteredChildren = filterRoutes(item.children)
|
return filteredChildren.length > 0
|
}
|
const isExternalLink = (item) => {
|
return !!(item.meta.link && !item.meta.isIframe)
|
}
|
const getUniqueKey = (item, index) => {
|
return `${item.path || item.meta.title || 'menu'}-${props.level}-${index}`
|
}
|
</script>
|