You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
2.6 KiB

  1. <script setup lang="ts">
  2. import Logo from "./logo.vue";
  3. import { useRoute } from "vue-router";
  4. import { emitter } from "@/utils/mitt";
  5. import SidebarItem from "./sidebarItem.vue";
  6. import leftCollapse from "./leftCollapse.vue";
  7. import { useNav } from "@/layout/hooks/useNav";
  8. import { storageLocal } from "@pureadmin/utils";
  9. import { ref, computed, watch, onBeforeMount } from "vue";
  10. import { findRouteByPath, getParentPaths } from "@/router/utils";
  11. import { usePermissionStoreHook } from "@/store/modules/permission";
  12. const route = useRoute();
  13. const showLogo = ref(
  14. storageLocal.getItem<StorageConfigs>("responsive-configure")?.showLogo ?? true
  15. );
  16. const { routers, device, pureApp, isCollapse, menuSelect, toggleSideBar } =
  17. useNav();
  18. const subMenuData = ref([]);
  19. const menuData = computed(() => {
  20. return pureApp.layout === "mix" && device.value !== "mobile"
  21. ? subMenuData.value
  22. : usePermissionStoreHook().wholeMenus;
  23. });
  24. function getSubMenuData(path: string) {
  25. // path的上级路由组成的数组
  26. const parentPathArr = getParentPaths(
  27. path,
  28. usePermissionStoreHook().wholeMenus
  29. );
  30. // 当前路由的父级路由信息
  31. const parenetRoute = findRouteByPath(
  32. parentPathArr[0] || path,
  33. usePermissionStoreHook().wholeMenus
  34. );
  35. if (!parenetRoute?.children) return;
  36. subMenuData.value = parenetRoute?.children;
  37. }
  38. getSubMenuData(route.path);
  39. onBeforeMount(() => {
  40. emitter.on("logoChange", key => {
  41. showLogo.value = key;
  42. });
  43. });
  44. watch(
  45. () => [route.path, usePermissionStoreHook().wholeMenus],
  46. () => {
  47. getSubMenuData(route.path);
  48. menuSelect(route.path, routers);
  49. }
  50. );
  51. </script>
  52. <template>
  53. <div
  54. v-loading="menuData.length === 0"
  55. :class="['sidebar-container', showLogo ? 'has-logo' : '']"
  56. >
  57. <Logo v-if="showLogo" :collapse="isCollapse" />
  58. <el-scrollbar
  59. wrap-class="scrollbar-wrapper"
  60. :class="[device === 'mobile' ? 'mobile' : 'pc']"
  61. >
  62. <el-menu
  63. router
  64. unique-opened
  65. mode="vertical"
  66. class="outer-most select-none"
  67. :collapse="isCollapse"
  68. :default-active="route.path"
  69. :collapse-transition="false"
  70. @select="indexPath => menuSelect(indexPath, routers)"
  71. >
  72. <sidebar-item
  73. v-for="routes in menuData"
  74. :key="routes.path"
  75. :item="routes"
  76. :base-path="routes.path"
  77. class="outer-most select-none"
  78. />
  79. </el-menu>
  80. </el-scrollbar>
  81. <leftCollapse
  82. v-if="device !== 'mobile'"
  83. :is-active="pureApp.sidebar.opened"
  84. @toggleClick="toggleSideBar"
  85. />
  86. </div>
  87. </template>
  88. <style scoped>
  89. :deep(.el-loading-mask) {
  90. opacity: 0.45;
  91. }
  92. </style>