AppLayout.vue 1.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <script setup>
  2. import { ref, computed } from 'vue'
  3. import AppTopBar from '@/components/AppTopBar.vue'
  4. import AppSidebar from '@/components/AppSidebar.vue'
  5. import AppFooter from '@/components/AppFooter.vue'
  6. import AppMessage from '@/components/AppMessage.vue'
  7. import menu from '@/utils/menu'
  8. const containerClass = computed(() => {
  9. return [
  10. 'layout-wrapper',
  11. 'layout-static',
  12. {
  13. 'layout-static-sidebar-inactive': staticMenuInactive.value,
  14. 'layout-mobile-sidebar-active': mobileMenuActive.value,
  15. },
  16. ]
  17. })
  18. const mobileMenuActive = ref(false)
  19. const staticMenuInactive = ref(false)
  20. const menuClick = ref(false)
  21. const isDesktop = () => window.innerWidth >= 992
  22. const onMenuToggle = () => {
  23. menuClick.value = true
  24. if (isDesktop()) {
  25. staticMenuInactive.value = !staticMenuInactive.value
  26. } else {
  27. mobileMenuActive.value = !mobileMenuActive.value
  28. }
  29. }
  30. const onWrapperClick = () => {
  31. if (!menuClick.value) {
  32. mobileMenuActive.value = false
  33. }
  34. menuClick.value = false
  35. }
  36. </script>
  37. <template>
  38. <div :class="containerClass" @click="onWrapperClick">
  39. <AppTopBar @menu-toggle="onMenuToggle" />
  40. <div class="layout-sidebar">
  41. <AppSidebar :model="menu[$page.props.auth.user.role_id]" />
  42. </div>
  43. <div class="layout-main-container">
  44. <div class="layout-main">
  45. <AppMessage />
  46. <slot />
  47. </div>
  48. <AppFooter />
  49. </div>
  50. <Transition name="layout-mask">
  51. <div class="layout-mask p-component-overlay" v-if="mobileMenuActive"></div>
  52. </Transition>
  53. </div>
  54. </template>