MenuItem.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <template>
  2. <el-menu-item
  3. v-if="!hasChildren"
  4. :index="menuInfo.index"
  5. popper-class="main-layout-submenu-popper"
  6. class="main-layout-sub-menu"
  7. :class="{ 'is-collapse': mainLayoutStore.collapse, 'active-index': currentIndex === menuInfo.index }"
  8. @click="$emit('handle')"
  9. >
  10. <div class="flex items-center flex-1 menu-padding-left main-layout-sub-menu-title">
  11. <component
  12. :is="menuInfo.path ? 'router-link' : 'div'"
  13. :to="menuInfo.path"
  14. class="flex items-center flex-1 menu-item"
  15. >
  16. <span class="icon">
  17. <svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" />
  18. </span>
  19. <span v-if="!mainLayoutStore.collapse" class="menu-label">{{ menuInfo.label }}</span>
  20. </component>
  21. </div>
  22. </el-menu-item>
  23. <el-sub-menu
  24. v-else
  25. :index="menuInfo.index"
  26. popper-class="main-layout-submenu-popper"
  27. class="main-layout-sub-menu"
  28. :class="{ 'is-collapse': mainLayoutStore.collapse, 'active-index': currentIndex?.startsWith(menu.index) }"
  29. >
  30. <template #title>
  31. <div class="flex items-center flex-1 main-layout-sub-menu-title" :class="{ 'menu-padding-left': hasChildren }">
  32. <component
  33. :is="menuInfo.path ? 'router-link' : 'div'"
  34. :to="menuInfo.path"
  35. class="flex items-center flex-1 menu-item"
  36. >
  37. <span class="icon"><svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" /></span>
  38. <span v-if="!mainLayoutStore.collapse" class="menu-label">{{ menuInfo.label }}</span>
  39. </component>
  40. </div>
  41. </template>
  42. <template v-for="child in menuInfo.children" :key="child.key">
  43. <el-menu-item
  44. v-if="!child.children?.length"
  45. :index="child.index"
  46. class="main-layout-menu-item"
  47. :class="{ 'active-index': currentIndex === child.index }"
  48. >
  49. <component :is="child.path ? 'router-link' : 'div'" :to="child.path" class="flex items-center flex-1 menu-item">
  50. <span class="menu-label">{{ child.label }}</span>
  51. </component>
  52. </el-menu-item>
  53. <main-layout-menu-item v-else :menu="child"></main-layout-menu-item>
  54. </template>
  55. </el-sub-menu>
  56. </template>
  57. <script setup lang="ts" name="MainLayoutMenuItem">
  58. import SvgIcon from '@/components/common/SvgIcon.vue'
  59. import useMainLayoutStore from '@/store/layout'
  60. import { computed } from 'vue'
  61. import { ElSubMenu, ElMenuItem } from 'element-plus'
  62. const mainLayoutStore = useMainLayoutStore()
  63. const props = defineProps<{
  64. currentIndex?: string
  65. menu: ExtractArrayValue<typeof mainLayoutStore.menuList>
  66. }>()
  67. const menuInfo = computed(() => {
  68. return { ...props.menu, children: props.menu.children || [] }
  69. })
  70. const hasChildren = computed(() => !!menuInfo.value.children.length)
  71. </script>
  72. <style scoped lang="scss">
  73. .main-layout-sub-menu,
  74. .main-layout-submenu-popper {
  75. ::v-deep(.el-sub-menu__icon-arrow) {
  76. display: none;
  77. }
  78. ::v-deep(.el-sub-menu__title) {
  79. margin-bottom: $SmallGapSpace;
  80. }
  81. &.main-layout-sub-menu {
  82. margin-bottom: $ExtraSmallGapSpace;
  83. }
  84. .menu-padding-left {
  85. padding-left: $ExtraBaseGapSpace;
  86. }
  87. .main-layout-sub-menu-title {
  88. // color: $LayoutLeftSubMenuColor;
  89. color: #fff;
  90. .menu-label {
  91. margin-left: $ExtraSmallGapSpace;
  92. }
  93. * {
  94. vertical-align: middle;
  95. }
  96. }
  97. .main-layout-menu-item {
  98. color: $LayoutLeftMenuItemColor;
  99. margin-bottom: $ExtraMiniGapSpace;
  100. &:hover {
  101. color: $LayoutLeftMenuItemHoverColor;
  102. }
  103. &.active-index {
  104. color: $LayoutLeftMenuItemActiveColor;
  105. }
  106. }
  107. .menu-item {
  108. color: inherit;
  109. }
  110. &.is-collapse {
  111. > .main-layout-sub-menu-title,
  112. > .el-sub-menu__title > .main-layout-sub-menu-title {
  113. padding: 0;
  114. text-align: center;
  115. }
  116. }
  117. &.active-index {
  118. > .main-layout-sub-menu-title,
  119. > .el-sub-menu__title > .main-layout-sub-menu-title {
  120. color: $color--primary;
  121. }
  122. }
  123. &:not(.is-collapse) {
  124. // &.is-opened,
  125. &.active-index {
  126. > .main-layout-sub-menu-title,
  127. > .el-sub-menu__title > .main-layout-sub-menu-title {
  128. background: $color--primary;
  129. border-radius: $LayoutLeftMenuRadius;
  130. color: $color--white;
  131. }
  132. }
  133. }
  134. }
  135. </style>