131 lines
3.3 KiB
Vue
131 lines
3.3 KiB
Vue
<template>
|
||
<v-app>
|
||
<LoginForm />
|
||
<Notifications />
|
||
|
||
<template v-if="!authStore.showLoginForm && !appStore.isLoading">
|
||
<div class="app-layout">
|
||
<!-- Часть А: Меню (слева для ПК, шторка для мобильных) -->
|
||
<NavigationMenu
|
||
ref="navigationMenu"
|
||
@update-collapsed="isCollapsed = $event"
|
||
@toggle-menu="toggleMobileMenu"
|
||
/>
|
||
|
||
<!-- Часть Б: Футер + Контент -->
|
||
<div
|
||
class="content-section"
|
||
:class="{ 'with-menu': !isMobile, 'menu-collapsed': !isMobile && isCollapsed }"
|
||
:style="{ marginLeft: !isMobile ? (isCollapsed ? '80px' : '250px') : '0' }"
|
||
>
|
||
<!-- Футер (HeaderBar) - скрыт для ПК, показан для мобильных -->
|
||
<HeaderBar v-if="isMobile || showFooter" @toggle-menu="toggleMobileMenu" />
|
||
|
||
<!-- Основной контент -->
|
||
<v-main
|
||
:class="{
|
||
'mobile-main': isMobile,
|
||
'with-menu': !isMobile
|
||
}"
|
||
>
|
||
<RouterView />
|
||
</v-main>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</v-app>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||
import { RouterView } from 'vue-router'
|
||
import NavigationMenu from './components/NavigationMenu.vue'
|
||
import HeaderBar from './components/HeaderBar.vue'
|
||
import LoginForm from './components/LoginForm.vue'
|
||
import Notifications from './components/Notifications.vue'
|
||
import { useAppStore } from '@/stores/app'
|
||
import { useAuthStore } from '@/stores/auth'
|
||
import { useNotificationStore } from '@/stores/notification'
|
||
|
||
const appStore = useAppStore()
|
||
const authStore = useAuthStore()
|
||
|
||
const navigationMenu = ref()
|
||
const windowWidth = ref(window.innerWidth)
|
||
const isCollapsed = ref(false)
|
||
const showFooter = ref(false)
|
||
|
||
const isMobile = computed(() => windowWidth.value < 768)
|
||
|
||
const toggleMobileMenu = () => {
|
||
if (navigationMenu.value) {
|
||
navigationMenu.value.toggle()
|
||
}
|
||
}
|
||
|
||
const updateWidth = () => {
|
||
windowWidth.value = window.innerWidth
|
||
}
|
||
|
||
onMounted(async () => {
|
||
window.addEventListener('resize', updateWidth)
|
||
|
||
appStore.initializeApi('http://localhost:8080/api')
|
||
await authStore.initializeAuth()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
window.removeEventListener('resize', updateWidth)
|
||
})
|
||
</script>
|
||
|
||
<style>
|
||
#app {
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.v-application {
|
||
min-height: 100vh;
|
||
width: 100%;
|
||
}
|
||
|
||
/* Основной layout контейнер */
|
||
.app-layout {
|
||
display: flex;
|
||
min-height: 100vh;
|
||
width: 100%;
|
||
}
|
||
|
||
/* Часть Б: Контентная секция */
|
||
.content-section {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 100%;
|
||
min-height: 100vh;
|
||
background: rgb(var(--v-theme-background));
|
||
transition: margin-left 0.3s ease;
|
||
}
|
||
|
||
/* Для ПК - основной контент без отступов */
|
||
.v-main.with-menu {
|
||
padding: 16px;
|
||
flex: 1;
|
||
background: transparent !important;
|
||
}
|
||
|
||
/* Для мобильных - контент с отступом под футером */
|
||
.mobile-main {
|
||
padding-top: 45px !important;
|
||
flex: 1 !important;
|
||
}
|
||
|
||
.mobile-main :deep(.v-main__content) {
|
||
padding: 0 !important;
|
||
}
|
||
|
||
.mobile-main :deep(.v-container) {
|
||
padding: 0 !important;
|
||
}
|
||
</style>
|