NavVertical.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <script setup lang="ts">
  2. import { useRoute } from "vue-router";
  3. import { emitter } from "@/utils/mitt";
  4. import { useNav } from "@/layout/hooks/useNav";
  5. import { responsiveStorageNameSpace } from "@/config";
  6. import { storageLocal, isAllEmpty } from "@pureadmin/utils";
  7. import { findRouteByPath, getParentPaths } from "@/router/utils";
  8. import { usePermissionStoreHook } from "@/store/modules/permission";
  9. import { ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
  10. import LaySidebarLogo from "../lay-sidebar/components/SidebarLogo.vue";
  11. import LaySidebarItem from "../lay-sidebar/components/SidebarItem.vue";
  12. const route = useRoute();
  13. const showLogo = ref(
  14. storageLocal().getItem<StorageConfigs>(
  15. `${responsiveStorageNameSpace()}configure`
  16. )?.showLogo ?? true
  17. );
  18. const {
  19. device,
  20. pureApp,
  21. tooltipEffect,
  22. menuSelect
  23. } = useNav();
  24. const subMenuData = ref([]);
  25. const menuData = computed(() => {
  26. return pureApp.layout === "mix" && device.value !== "mobile"
  27. ? subMenuData.value
  28. : usePermissionStoreHook().wholeMenus;
  29. });
  30. const loading = computed(() =>
  31. pureApp.layout === "mix" ? false : menuData.value.length === 0 ? true : false
  32. );
  33. const defaultActive = computed(() =>
  34. !isAllEmpty(route.meta?.activePath) ? route.meta.activePath : route.path
  35. );
  36. function getSubMenuData() {
  37. let path = "";
  38. path = defaultActive.value;
  39. subMenuData.value = [];
  40. // path的上级路由组成的数组
  41. const parentPathArr = getParentPaths(
  42. path,
  43. usePermissionStoreHook().wholeMenus
  44. );
  45. // 当前路由的父级路由信息
  46. const parenetRoute = findRouteByPath(
  47. parentPathArr[0] || path,
  48. usePermissionStoreHook().wholeMenus
  49. );
  50. if (!parenetRoute?.children) return;
  51. subMenuData.value = parenetRoute?.children;
  52. }
  53. watch(
  54. () => [route.path, usePermissionStoreHook().wholeMenus],
  55. () => {
  56. if (route.path.includes("/redirect")) return;
  57. getSubMenuData();
  58. menuSelect(route.path);
  59. }
  60. );
  61. onMounted(() => {
  62. getSubMenuData();
  63. emitter.on("logoChange", key => {
  64. showLogo.value = key;
  65. });
  66. });
  67. onBeforeUnmount(() => {
  68. // 解绑`logoChange`公共事件,防止多次触发
  69. emitter.off("logoChange");
  70. });
  71. </script>
  72. <template>
  73. <div
  74. v-loading="loading"
  75. :class="['sidebar-container', showLogo ? 'has-logo' : 'no-logo']"
  76. >
  77. <LaySidebarLogo v-if="showLogo" :collapse="false" />
  78. <el-scrollbar
  79. wrap-class="scrollbar-wrapper"
  80. :class="[device === 'mobile' ? 'mobile' : 'pc']"
  81. >
  82. <el-menu
  83. unique-opened
  84. mode="vertical"
  85. popper-class="pure-scrollbar"
  86. class="outer-most select-none"
  87. :collapse="false"
  88. :collapse-transition="false"
  89. :popper-effect="tooltipEffect"
  90. :default-active="defaultActive"
  91. >
  92. <LaySidebarItem
  93. v-for="routes in menuData"
  94. :key="routes.path"
  95. :item="routes"
  96. :base-path="routes.path"
  97. class="outer-most select-none"
  98. />
  99. </el-menu>
  100. </el-scrollbar>
  101. </div>
  102. </template>
  103. <style scoped>
  104. :deep(.el-loading-mask) {
  105. opacity: 0.45;
  106. }
  107. :deep(.el-scrollbar.pc .el-scrollbar__wrap) {
  108. padding-top: 20px !important;
  109. }
  110. :deep(.el-menu.outer-most) {
  111. padding-top: 0 !important;
  112. }
  113. </style>