123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <script setup lang="ts">
- import { useMediaQuery } from '@vueuse/core'
- import { isEmpty } from 'lodash-es'
- import { NScrollbar } from 'naive-ui'
- import { computed, provide, watch, ref } from 'vue'
- import texturePng from '@/assets/texture.png'
- import { EmptyPlaceholder } from '@/components'
- import { useComponentThemeOverrides } from '@/composable/useComponentThemeOverrides'
- import { mediaQueryInjectionKey, layoutInjectionKey } from '@/injection'
- import { usePreferencesStore } from '@/stores'
- import { useTabsStore } from '@/stores'
- import AsideLayout from './aside/index.vue'
- import MobileLeftAside from './aside/mobile/MobileLeftAside.vue'
- import MobileRightAside from './aside/mobile/MobileRightAside.vue'
- import Tabs from './component/Tabs.vue'
- import FooterLayout from './footer/index.vue'
- import HeaderLayout from './header/index.vue'
- import MainLayout from './main/index.vue'
- import type { LayoutSlideDirection } from '@/injection'
- defineOptions({
- name: 'Layouts',
- })
- const tabsStore = useTabsStore()
- const preferencesStore = usePreferencesStore()
- const { scrollbarInMainLayout } = useComponentThemeOverrides()
- const mediaQuery = {
- sm: useMediaQuery('(max-width: 640px)'),
- md: useMediaQuery('(max-width: 768px)'),
- lg: useMediaQuery('(max-width: 1024px)'),
- xl: useMediaQuery('(max-width: 1280px)'),
- xxl: useMediaQuery('(max-width: 1536px)'),
- }
- const layoutSlideDirection = ref<LayoutSlideDirection>(null)
- const shouldRefreshRoute = ref(false)
- const layoutTranslateOffset = computed(() => {
- return layoutSlideDirection.value === 'right'
- ? preferencesStore.preferences.menu.maxWidth || 0
- : layoutSlideDirection.value === 'left'
- ? -62
- : 0
- })
- function setLayoutSlideDirection(direction: LayoutSlideDirection) {
- layoutSlideDirection.value = direction === layoutSlideDirection.value ? null : direction
- }
- watch(
- () => mediaQuery.sm.value,
- (isSm) => {
- if (isSm) {
- preferencesStore.modify({
- menu: {
- collapsed: false,
- },
- })
- setLayoutSlideDirection(null)
- }
- },
- )
- provide(mediaQueryInjectionKey, mediaQuery)
- provide(layoutInjectionKey, {
- shouldRefreshRoute,
- layoutSlideDirection,
- setLayoutSlideDirection,
- })
- </script>
- <template>
- <div
- class="relative flex h-svh overflow-hidden"
- :style="{ backgroundImage: `url(${texturePng})` }"
- >
- <MobileLeftAside v-if="mediaQuery.sm.value" />
- <div
- class="relative flex h-full w-full flex-col border-naive-border transition-[border-color,rounded,transform] max-sm:rounded-xl sm:transform-none!"
- :class="{
- 'overflow-hidden rounded-xl border': mediaQuery.sm.value && layoutTranslateOffset,
- }"
- :style="
- mediaQuery.sm.value && layoutSlideDirection
- ? {
- transform: `translate(${layoutTranslateOffset}px) scale(0.88)`,
- }
- : null
- "
- >
- <HeaderLayout />
- <div class="flex flex-1 overflow-hidden">
- <AsideLayout v-if="!mediaQuery.sm.value" />
- <div class="relative flex flex-1 flex-col overflow-x-hidden">
- <Transition
- type="transition"
- enter-active-class="transition-[grid-template-rows]"
- leave-active-class="transition-[grid-template-rows]"
- enter-from-class="grid-rows-[0fr]"
- leave-to-class="grid-rows-[0fr]"
- enter-to-class="grid-rows-[1fr]"
- leave-from-class="grid-rows-[1fr]"
- >
- <div
- v-if="
- !mediaQuery.sm.value &&
- !isEmpty(tabsStore.tabs) &&
- preferencesStore.preferences.showTabs
- "
- class="grid shrink-0 items-baseline overflow-hidden"
- >
- <Tabs />
- </div>
- </Transition>
- <NScrollbar
- class="transition-[padding]"
- :class="{
- 'pb-4': mediaQuery.sm.value && layoutSlideDirection,
- }"
- container-class="main-container"
- :theme-overrides="scrollbarInMainLayout"
- >
- <MainLayout />
- </NScrollbar>
- <EmptyPlaceholder
- :show="isEmpty(tabsStore.tabs)"
- description="空标签页"
- size="huge"
- >
- <template #icon>
- <div class="flex items-center justify-center">
- <span class="iconify ph--rectangle" />
- </div>
- </template>
- </EmptyPlaceholder>
- <Transition
- type="transition"
- enter-active-class="transition-[grid-template-rows]"
- leave-active-class="transition-[grid-template-rows]"
- enter-from-class="grid-rows-[0fr]"
- leave-to-class="grid-rows-[0fr]"
- enter-to-class="grid-rows-[1fr]"
- leave-from-class="grid-rows-[1fr]"
- >
- <div
- v-if="!mediaQuery.sm.value && preferencesStore.preferences.showFooter"
- class="grid shrink-0 items-baseline overflow-hidden"
- >
- <FooterLayout />
- </div>
- </Transition>
- </div>
- </div>
- </div>
- <MobileRightAside v-if="mediaQuery.sm.value" />
- </div>
- </template>
|