MenuItem.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. <component
  11. :is="menuInfo.path ? 'router-link' : 'div'"
  12. v-if="mainLayoutStore.collapse"
  13. :to="menuInfo.path"
  14. class="flex items-center collapse-icon"
  15. >
  16. <svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" />
  17. </component>
  18. <template #title>
  19. <div
  20. v-if="!mainLayoutStore.collapse"
  21. class="flex items-center flex-1 menu-padding-left main-layout-sub-menu-title"
  22. >
  23. <component
  24. :is="menuInfo.path ? 'router-link' : 'div'"
  25. :to="menuInfo.path"
  26. class="flex items-center flex-1 menu-item"
  27. >
  28. <span class="icon">
  29. <svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" />
  30. </span>
  31. <span class="menu-label">{{ menuInfo.label }}</span>
  32. </component>
  33. </div>
  34. <div v-else>{{ menuInfo.label }}</div>
  35. </template>
  36. <!-- <div class="flex items-center flex-1 menu-padding-left main-layout-sub-menu-title">
  37. <component
  38. :is="menuInfo.path ? 'router-link' : 'div'"
  39. :to="menuInfo.path"
  40. class="flex items-center flex-1 menu-item"
  41. >
  42. <span class="icon">
  43. <svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" />
  44. </span>
  45. <span v-if="!mainLayoutStore.collapse" class="menu-label">{{ menuInfo.label }}</span>
  46. </component>
  47. </div> -->
  48. </el-menu-item>
  49. <el-sub-menu
  50. v-else
  51. :index="menuInfo.index"
  52. popper-class="main-layout-submenu-popper"
  53. class="main-layout-sub-menu"
  54. :class="{ 'is-collapse': mainLayoutStore.collapse, 'active-index': checkActive() }"
  55. >
  56. <template #title>
  57. <div
  58. class="flex items-center flex-1 main-layout-sub-menu-title"
  59. :class="{ 'menu-padding-left': hasChildren }"
  60. @click="mClick(menuInfo)"
  61. >
  62. <component
  63. :is="menuInfo.path ? 'router-link' : 'div'"
  64. :to="menuInfo.path"
  65. class="flex items-center flex-1 menu-item"
  66. >
  67. <span class="icon"><svg-icon v-if="menuInfo.icon" :name="menuInfo.icon" /></span>
  68. <span v-if="!mainLayoutStore.collapse" class="menu-label">{{ menuInfo.label }}</span>
  69. </component>
  70. </div>
  71. </template>
  72. <template v-for="child in menuInfo.children" :key="child.key">
  73. <el-menu-item
  74. v-if="!child.children?.length"
  75. :index="child.index"
  76. class="main-layout-menu-item"
  77. :class="{ 'active-index': currentIndex === child.index }"
  78. >
  79. <component :is="child.path ? 'router-link' : 'div'" :to="child.path" class="flex items-center flex-1 menu-item">
  80. <span class="menu-label">{{ child.label }}</span>
  81. </component>
  82. </el-menu-item>
  83. <main-layout-menu-item v-else :menu="child"></main-layout-menu-item>
  84. </template>
  85. </el-sub-menu>
  86. </template>
  87. <script setup lang="ts" name="MainLayoutMenuItem">
  88. import SvgIcon from '@/components/common/SvgIcon.vue'
  89. import useMainLayoutStore from '@/store/layout'
  90. import { computed } from 'vue'
  91. import { ElSubMenu, ElMenuItem } from 'element-plus'
  92. const mainLayoutStore = useMainLayoutStore()
  93. const props = defineProps<{
  94. currentIndex?: string
  95. menu: ExtractArrayValue<typeof mainLayoutStore.menuList>
  96. }>()
  97. const mClick = (info: any) => {
  98. if (
  99. info.label === '评阅试卷' &&
  100. info.path === '/marking' &&
  101. !info.children.find((item: any) => item.path === '/marking/training-record')
  102. ) {
  103. mainLayoutStore.getRenderMenuList()
  104. }
  105. }
  106. const menuInfo = computed(() => {
  107. // console.log('menuInfo:', { ...props.menu, children: props.menu.children || [] })
  108. return { ...props.menu, children: props.menu.children || [] }
  109. })
  110. const hasChildren = computed(() => !!menuInfo.value.children.length)
  111. const checkActive = () => {
  112. if (props.currentIndex?.startsWith('marking_standard') && props.menu.index === 'marking') {
  113. return false
  114. }
  115. return props.currentIndex?.startsWith(props.menu.index)
  116. }
  117. </script>
  118. <style scoped lang="scss">
  119. .main-layout-sub-menu,
  120. .main-layout-submenu-popper {
  121. ::v-deep(.el-sub-menu__icon-arrow) {
  122. display: none;
  123. }
  124. ::v-deep(.el-sub-menu__title) {
  125. margin-bottom: $SmallGapSpace;
  126. .router-link-active.router-link-exact-active {
  127. background: $color--primary;
  128. }
  129. }
  130. &.is-collapse {
  131. ::v-deep(.el-sub-menu__title) {
  132. .router-link-active.router-link-exact-active {
  133. background: transparent;
  134. }
  135. }
  136. .menu-item {
  137. padding-left: 0;
  138. }
  139. }
  140. &.main-layout-sub-menu {
  141. margin-bottom: $ExtraSmallGapSpace;
  142. }
  143. .menu-padding-left {
  144. padding-left: $ExtraBaseGapSpace;
  145. }
  146. .main-layout-sub-menu-title {
  147. // color: $LayoutLeftSubMenuColor;
  148. // color: #fff;
  149. color: #666;
  150. .menu-label {
  151. margin-left: $ExtraSmallGapSpace;
  152. }
  153. * {
  154. vertical-align: middle;
  155. }
  156. }
  157. .main-layout-menu-item {
  158. color: $LayoutLeftMenuItemColor;
  159. margin-bottom: $ExtraMiniGapSpace;
  160. &:hover {
  161. color: $LayoutLeftMenuItemHoverColor;
  162. }
  163. &.active-index {
  164. color: $LayoutLeftMenuItemActiveColor;
  165. }
  166. }
  167. .menu-item {
  168. color: inherit;
  169. padding-left: 10px;
  170. border-radius: $LayoutLeftMenuRadius;
  171. }
  172. &.is-collapse {
  173. > .main-layout-sub-menu-title,
  174. > .el-sub-menu__title > .main-layout-sub-menu-title {
  175. padding: 0;
  176. text-align: center;
  177. }
  178. }
  179. .collapse-icon {
  180. // color: #fff;
  181. color: #666;
  182. &.router-link-active {
  183. color: $color--primary;
  184. }
  185. }
  186. &.active-index {
  187. .collapse-icon {
  188. // color: $color--primary;
  189. }
  190. > .main-layout-sub-menu-title,
  191. > .el-sub-menu__title > .main-layout-sub-menu-title {
  192. color: $color--primary;
  193. }
  194. }
  195. &:not(.is-collapse) {
  196. // &.is-opened,
  197. &.active-index {
  198. > .main-layout-sub-menu-title,
  199. > .el-sub-menu__title > .main-layout-sub-menu-title {
  200. // background: $color--primary;
  201. border-radius: $LayoutLeftMenuRadius;
  202. color: $color--white;
  203. }
  204. }
  205. }
  206. }
  207. </style>