MenuItem.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <template>
  2. <!-- 如果有子节点,渲染为子菜单 -->
  3. <ElSubMenu
  4. v-if="menuItemData.hasChildren && menuItemData.childs && menuItemData.childs.length"
  5. :index="menuItemData.id.toString()"
  6. :class="{ 'parent-active': isParentActive(menuItemData.id.toString()) }"
  7. >
  8. <template #title>
  9. <span :class="{ 'titleparent-active': isParentActive(menuItemData.id.toString()) }">
  10. {{ menuItemData.folderName }}
  11. </span>
  12. </template>
  13. <!-- 递归渲染子节点 -->
  14. <template v-for="child in menuItemData.childs" :key="child.id">
  15. <menu-item :menu-item-data="child" />
  16. </template>
  17. </ElSubMenu>
  18. <!-- 如果没有子节点,渲染为菜单项 -->
  19. <ElMenuItem
  20. v-else
  21. :index="menuItemData.id.toString()"
  22. >
  23. {{ menuItemData.folderName }}
  24. </ElMenuItem>
  25. </template>
  26. <script setup>
  27. import { ref, watch } from 'vue'
  28. // 定义组件属性
  29. const props = defineProps({
  30. menuItemData: {
  31. type: Object,
  32. required: true,
  33. default: () => ({
  34. id: '',
  35. parentId: '',
  36. projectId: '',
  37. contractId: '',
  38. folderName: '',
  39. hasChildren: false,
  40. childs: [],
  41. }),
  42. },
  43. selectedKeyPath: {
  44. type: Array,
  45. required: false,
  46. default: () => [],
  47. },
  48. })
  49. const selectedKeyPath = ref(props.selectedKeyPath || []) // 传入的选中路径
  50. watch(() => props.selectedKeyPath, (newVal) => {
  51. selectedKeyPath.value = newVal || []
  52. }, { immediate: true })
  53. // 菜单折叠状态
  54. // 判断父菜单是否应该激活
  55. const isParentActive = (parentIndex) => {
  56. return selectedKeyPath.value.includes(parentIndex)
  57. }
  58. </script>
  59. <style scoped>
  60. /* 基础菜单样式 */
  61. /* 菜单项基础样式 */
  62. .custom-menu .el-menu-item,
  63. .custom-menu .el-sub-menu__title {
  64. position: relative;
  65. transition: all 0.3s ease;
  66. }
  67. /* 选中菜单项样式 */
  68. .custom-menu .el-menu-item.is-active {
  69. color: #149BF4 !important;
  70. background-color: #E6F7FF !important;
  71. }
  72. /* 选中菜单项右侧边框 */
  73. .custom-menu .el-menu-item.is-active::after {
  74. content: '';
  75. position: absolute;
  76. right: 0;
  77. top: 0;
  78. height: 100%;
  79. width: 6px;
  80. background-color: #149BF4;
  81. }
  82. /* 父菜单标题激活样式 */
  83. .titleparent-active {
  84. color: #149BF4 !important;
  85. font-weight: bold !important;
  86. }
  87. /* 父菜单激活时箭头变色 - 通过父级激活类控制 */
  88. .parent-active .el-sub-menu__icon-arrow {
  89. color: #149BF4 !important;
  90. }
  91. /* 解决scoped样式穿透问题 */
  92. /* :deep(.parent-active) .el-sub-menu__icon-arrow {
  93. color: #149BF4 !important;
  94. } */
  95. :deep(.el-sub-menu.parent-active) .el-sub-menu__icon-arrow {
  96. color: #149BF4 !important;
  97. transition: color 0.3s ease;
  98. }
  99. /* 方
  100. /* 二级菜单背景色 - 保持f7f7f7 */
  101. .custom-menu .el-sub-menu .el-menu {
  102. background-color: #F7F7F7 !important;
  103. }
  104. /* 二级菜单项默认样式 */
  105. .custom-menu .el-sub-menu .el-menu .el-menu-item {
  106. background-color: #F7F7F7 !important;
  107. }
  108. /* 二级菜单项选中样式 */
  109. .custom-menu .el-sub-menu .el-menu .el-menu-item.is-active {
  110. background-color: #E6F7FF !important;
  111. }
  112. </style>