refactor(app): extract page logic into composable drivers

This commit is contained in:
skytek_xinliang
2026-05-19 16:38:08 +08:00
parent 2b780a12c2
commit 51fbbd7101
13 changed files with 576 additions and 692 deletions
+69 -9
View File
@@ -1,17 +1,19 @@
<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'
import { mdiHome } from '@mdi/js'
import MainLayout from '@/components/layouts/MainLayout.vue'
import PlainLayout from '@/components/layouts/PlainLayout.vue'
import { useAppShell } from '@/composables/layout/useAppShell'
import AppTabs from './AppTabs.vue'
import GlobalOverlays from './GlobalOverlays.vue'
import type { LayoutMenuItem } from '@/stores/menu'
defineProps<{
menuItems?: LayoutMenuItem[]
}>()
type AppTabsInstance = InstanceType<typeof AppTabs>
type GlobalOverlaysInstance = InstanceType<typeof GlobalOverlays>
const route = useRoute()
const appTabs = ref<AppTabsInstance | null>(null)
const globalOverlays = ref<GlobalOverlaysInstance | null>(null)
const layoutMap = {
default: MainLayout,
@@ -22,14 +24,72 @@ const activeLayout = computed(
() => layoutMap[route.meta.layout as 'default' | 'none'] || MainLayout
)
const showTabs = computed(() => route.meta.layout === 'default')
function clearTabs() {
appTabs.value?.clearTabs()
}
const {
favoriteActionIcon,
favoriteActionLabel,
favoritesStore,
goHome,
handleLayoutAction,
handleLogout,
handleRemoveFavorite,
handleSelect,
isFavoriteActionDisabled,
layoutProps,
menuStore,
mergedMenuItems,
toggleFavorite,
} = useAppShell({ onLogout: clearTabs })
function handleSearch(value: string) {
globalOverlays.value?.handleSearch(value)
}
</script>
<template>
<component :is="activeLayout">
<AppTabs :menu-items="menuItems" :show-tabs="showTabs">
<slot />
<component
:is="activeLayout"
v-bind="layoutProps"
v-model:breadcrumb-bar-visible="favoritesStore.breadcrumbBarVisible"
v-model:favorites-bar-visible="favoritesStore.favoritesBarVisible"
v-model:is-rail="menuStore.isRail"
@action="handleLayoutAction"
@logout="handleLogout"
@remove-favorite="handleRemoveFavorite"
@search="handleSearch"
@select="handleSelect"
>
<template #breadcrumb-actions>
<v-btn
color="secondary"
:disabled="isFavoriteActionDisabled"
size="small"
variant="outlined"
@click="toggleFavorite"
>
<v-icon class="mr-1" size="14" :icon="favoriteActionIcon" />
{{ favoriteActionLabel }}
</v-btn>
<v-btn class="ml-2" color="primary" size="small" variant="text" @click="goHome">
<v-icon class="mr-1" size="14" :icon="mdiHome" />
返回首頁
</v-btn>
</template>
<AppTabs ref="appTabs" :menu-items="mergedMenuItems" :show-tabs="showTabs">
<router-view v-if="showTabs" v-slot="{ Component }">
<keep-alive>
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</router-view>
<router-view v-else />
</AppTabs>
</component>
<GlobalOverlays :menu-items="menuItems" @search-select="$emit('searchSelect', $event)" />
<GlobalOverlays ref="globalOverlays" :menu-items="mergedMenuItems" @search-select="handleSelect" />
</template>