App.vue 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. <template>
  2. <div :class="['web-app', layoutClass]">
  3. <template v-if="isAppLayout">
  4. <div class="app-shell">
  5. <TopNavBar @logout="onLogout" />
  6. <div class="app-body">
  7. <SideNav />
  8. <main class="content">
  9. <router-view />
  10. </main>
  11. </div>
  12. </div>
  13. </template>
  14. <router-view v-else />
  15. <ToastHost />
  16. </div>
  17. </template>
  18. <script setup>
  19. import { computed, watch } from 'vue'
  20. import { useRoute, useRouter } from 'vue-router'
  21. import { useAuth } from '@/store/auth'
  22. import { useMenu } from '@/store/menu'
  23. import { useSyncDocumentTitle } from '@/composables/useSyncDocumentTitle'
  24. import TopNavBar from '@/components/TopNavBar.vue'
  25. import SideNav from '@/components/SideNav.vue'
  26. import ToastHost from '@/components/common/ToastHost.vue'
  27. const route = useRoute()
  28. const router = useRouter()
  29. const { logout } = useAuth()
  30. const { state: menuState, reset: resetMenu, load: loadMenu } = useMenu()
  31. useSyncDocumentTitle()
  32. const isAppLayout = computed(() => route.meta?.layout !== 'blank')
  33. const layoutClass = computed(() => (isAppLayout.value ? 'layout-app' : 'layout-blank'))
  34. watch(
  35. () => route.path,
  36. (path) => {
  37. if (menuState.loaded) loadMenu()
  38. void path
  39. },
  40. { immediate: true },
  41. )
  42. function onLogout() {
  43. resetMenu()
  44. logout()
  45. router.replace('/login')
  46. }
  47. </script>