<template> <q-layout view="lHh Lpr lFf"> <q-header elevated> <q-toolbar> <q-btn flat dense round @click="toggleLeftDrawer"> <q-avatar> <img :src=" leftDrawerOpen ? require('./menuListIcons/toggle-left-drawer-show.svg') : require('./menuListIcons/toggle-left-drawer-hide.svg') " /> </q-avatar> </q-btn> <q-toolbar-title style="min-width: 140px"> Quasar App </q-toolbar-title> <q-tabs v-model="defaultRouter" inline-label outside-arrows no-caps shrink class="my-tabs" > <q-tab class="my-tab" v-for="page in tabsList" :key="page.link" :name="page.link" :label="page.title" @click.stop="clickTab(page)" > <q-btn v-show="isShowCloseBtn" dense flat round size="sm" icon="close" title="关闭" @mousedown.stop="doNothing" @click.stop="closeTab(page)" > </q-btn> <q-menu touch-position context-menu v-if="isShowCloseBtn"> <q-list dense style="min-width: 100px"> <q-item clickable v-close-popup> <q-item-section @click="closeTab(page)" >关闭当前页面</q-item-section > </q-item> <q-item clickable v-close-popup> <q-item-section @click="closeNotCurrentPage(page)" >关闭非当前页面</q-item-section > </q-item> <q-item clickable v-close-popup> <q-item-section @click="closeAll">关闭所有</q-item-section> </q-item> </q-list> </q-menu> </q-tab> </q-tabs> <q-space /> <language-select /> <div>Quasar v{{ $q.version }}</div> </q-toolbar> </q-header> <q-drawer v-model="leftDrawerOpen" show-if-above bordered> <q-scroll-area style="height: 100%"> <q-list> <q-item-label header style="padding: 0"> <TopLeftLoading /> </q-item-label> <EssentialLink v-for="link in essentialLinks" :key="link.title" v-bind="link" /> </q-list> </q-scroll-area> </q-drawer> <q-page-container> <router-view /> </q-page-container> </q-layout> </template> <script lang="ts"> import { defineComponent, ref, onMounted, reactive, toRefs, computed, } from 'vue'; import { onBeforeRouteUpdate, useRouter } from 'vue-router'; import { usePageStore } from 'src/common/hooks'; import EssentialLink from 'components/EssentialLink.vue'; // import TopLeftLoading from './TopLeftLoading.vue'; import { MenuList } from './config'; import TopLeftLoading from './TopLeftText.vue'; import LanguageSelect from './element/LanguageSelect.vue'; export default defineComponent({ name: 'MainLayout', components: { EssentialLink, TopLeftLoading, LanguageSelect, }, setup() { const pageStore = usePageStore(); const router = useRouter(); const leftDrawerOpen = ref(false); const defaultRouter = ref('/page1'); const linksList = ref<any>([]); const state = reactive({ tabsList: [] as any, }); onBeforeRouteUpdate((to, from, next) => { defaultRouter.value = to.path; if (to.matched.length == 3) { pageStore.addRoute(to as any); getTabsList(); } next(); }); const isShowCloseBtn = computed(() => { let flag = true; const { tabsList } = state; if (tabsList.length === 1) { const target = tabsList[0]; if (target.link === '/home') { flag = false; } } return flag; }); onMounted(() => { getLinksList(); const path = router.currentRoute.value.path; defaultRouter.value = path; pageStore.addRoute(router.currentRoute.value as any); getTabsList(); }); const getLinksList = () => { let lists = MenuList; for (const item of lists) { if (item.link === defaultRouter.value) { item.active = true; } else { item.active = false; } } linksList.value = lists; }; const getTabsList = () => { state.tabsList = pageStore.tabRouterList.map((item: any) => { return { title: item.meta?.title, link: item.path, keepalive: item.meta?.keepalive, permission: item.meta?.permission, name: item.name, }; }); }; const clickTab = (page: any) => { router.push(page.link); }; const closeTab = (page: any) => { const { tabsList } = state; if (tabsList.length === 1) { router.push('/home'); pageStore.removePage(page); getTabsList(); } else { pageStore.removePage(page); getTabsList(); router.push(pageStore.activeRouter.path); } }; const closeNotCurrentPage = (page: any) => { pageStore.removeNotCurrentPage(page); getTabsList(); router.push(pageStore.activeRouter.path); }; const closeAll = () => { pageStore.removeAllPage(); router.push('/home'); getTabsList(); }; const doNothing = () => { // to prevent tab close button ripple effect }; return { ...toRefs(state), essentialLinks: linksList, leftDrawerOpen, toggleLeftDrawer() { leftDrawerOpen.value = !leftDrawerOpen.value; }, linksList, pageStore, defaultRouter, clickTab, closeTab, closeNotCurrentPage, closeAll, doNothing, isShowCloseBtn, }; }, }); </script> <style lang="scss" scoped> .my-tab { box-sizing: border-box; background-color: $primary-4; margin: 0 2px; :deep(.q-tab__content) { display: flex; flex-direction: row; flex-wrap: nowrap; > button { color: transparent; } &:hover > button { color: white; } .q-tab__label { flex: 1; } } } .my-tabs { :deep(.q-tab--active) { background-color: $primary-2; } } </style>