zhou zhou
昨天 46d872c1a5b77aa8799de4a64888a0a24a1422d6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<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>