default-layout.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <a-layout class="layout" :class="{ mobile: appStore.hideMenu }">
  3. <div v-if="navbar" class="layout-navbar">
  4. <NavBar />
  5. </div>
  6. <a-layout>
  7. <a-layout>
  8. <a-layout-sider
  9. v-if="renderMenu"
  10. v-show="!hideMenu"
  11. class="layout-sider"
  12. breakpoint="xl"
  13. :collapsed="collapsed"
  14. :collapsible="true"
  15. :width="menuWidth"
  16. :style="{ paddingTop: navbar ? '60px' : '' }"
  17. :hide-trigger="true"
  18. @collapse="setCollapsed"
  19. >
  20. <div class="menu-wrapper">
  21. <Menu />
  22. </div>
  23. </a-layout-sider>
  24. <a-drawer
  25. v-if="hideMenu"
  26. :visible="drawerVisible"
  27. placement="left"
  28. :footer="false"
  29. mask-closable
  30. :closable="false"
  31. @cancel="drawerCancel"
  32. >
  33. <Menu />
  34. </a-drawer>
  35. <a-layout class="layout-content" :style="paddingStyle">
  36. <TabBar v-if="appStore.tabBar" />
  37. <a-layout-content>
  38. <PageLayout />
  39. </a-layout-content>
  40. <Footer v-if="footer" />
  41. </a-layout>
  42. </a-layout>
  43. </a-layout>
  44. </a-layout>
  45. </template>
  46. <script lang="ts" setup>
  47. import { ref, computed, watch, provide, onMounted } from 'vue';
  48. import { useRouter, useRoute } from 'vue-router';
  49. import { useAppStore, useUserStore } from '@/store';
  50. import NavBar from '@/components/navbar/index.vue';
  51. import Menu from '@/components/menu/index.vue';
  52. import Footer from '@/components/footer/index.vue';
  53. import TabBar from '@/components/tab-bar/index.vue';
  54. import usePermission from '@/hooks/permission';
  55. import useResponsive from '@/hooks/responsive';
  56. import PageLayout from './page-layout.vue';
  57. const isInit = ref(false);
  58. const appStore = useAppStore();
  59. const userStore = useUserStore();
  60. const router = useRouter();
  61. const route = useRoute();
  62. const permission = usePermission();
  63. useResponsive(true);
  64. const navbarHeight = `60px`;
  65. const navbar = computed(() => appStore.navbar);
  66. const renderMenu = computed(() => appStore.menu && !appStore.topMenu);
  67. const hideMenu = computed(() => appStore.hideMenu);
  68. const footer = computed(() => appStore.footer);
  69. const menuWidth = computed(() => {
  70. return appStore.menuCollapse ? 48 : appStore.menuWidth;
  71. });
  72. const collapsed = computed(() => {
  73. return appStore.menuCollapse;
  74. });
  75. const paddingStyle = computed(() => {
  76. const paddingLeft =
  77. renderMenu.value && !hideMenu.value
  78. ? { paddingLeft: `${menuWidth.value}px` }
  79. : {};
  80. const paddingTop = navbar.value ? { paddingTop: navbarHeight } : {};
  81. return { ...paddingLeft, ...paddingTop };
  82. });
  83. const setCollapsed = (val: boolean) => {
  84. if (!isInit.value) return; // for page initialization menu state problem
  85. appStore.updateSettings({ menuCollapse: val });
  86. };
  87. watch(
  88. () => userStore.role,
  89. (roleValue) => {
  90. if (roleValue && !permission.accessRouter(route))
  91. router.push({ name: 'notFound' });
  92. }
  93. );
  94. const drawerVisible = ref(false);
  95. const drawerCancel = () => {
  96. drawerVisible.value = false;
  97. };
  98. provide('toggleDrawerMenu', () => {
  99. drawerVisible.value = !drawerVisible.value;
  100. });
  101. onMounted(() => {
  102. isInit.value = true;
  103. });
  104. </script>
  105. <style scoped lang="less">
  106. @nav-size-height: 60px;
  107. @layout-max-width: 1100px;
  108. .layout {
  109. width: 100%;
  110. height: 100%;
  111. }
  112. .layout-navbar {
  113. position: fixed;
  114. top: 0;
  115. left: 0;
  116. z-index: 100;
  117. width: 100%;
  118. height: @nav-size-height;
  119. }
  120. .layout-sider {
  121. position: fixed;
  122. top: 0;
  123. left: 0;
  124. z-index: 99;
  125. height: 100%;
  126. transition: all 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
  127. &::after {
  128. position: absolute;
  129. top: 0;
  130. right: -1px;
  131. display: block;
  132. width: 1px;
  133. height: 100%;
  134. background-color: var(--color-border);
  135. content: '';
  136. }
  137. > :deep(.arco-layout-sider-children) {
  138. overflow-y: hidden;
  139. }
  140. }
  141. .menu-wrapper {
  142. height: 100%;
  143. overflow: auto;
  144. overflow-x: hidden;
  145. :deep(.arco-menu) {
  146. ::-webkit-scrollbar {
  147. width: 12px;
  148. height: 4px;
  149. }
  150. ::-webkit-scrollbar-thumb {
  151. border: 4px solid transparent;
  152. background-clip: padding-box;
  153. border-radius: 7px;
  154. background-color: var(--color-text-4);
  155. }
  156. ::-webkit-scrollbar-thumb:hover {
  157. background-color: var(--color-text-3);
  158. }
  159. }
  160. }
  161. .layout-content {
  162. min-height: 100vh;
  163. overflow-y: hidden;
  164. background-color: var(--color-fill-2);
  165. transition: padding 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
  166. }
  167. </style>