MainLayout.vue 6.26 KB
Newer Older
hucy's avatar
hucy committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<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>

hucy's avatar
hucy committed
17
        <q-toolbar-title style="min-width: 140px"> Quasar App </q-toolbar-title>
hucy's avatar
hucy committed
18 19 20 21 22 23 24 25
        <q-tabs
          v-model="defaultRouter"
          inline-label
          outside-arrows
          no-caps
          shrink
          class="my-tabs"
        >
hucy's avatar
hucy committed
26 27 28 29 30 31 32 33 34
          <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
hucy's avatar
hucy committed
35
              v-show="isShowCloseBtn"
hucy's avatar
hucy committed
36 37 38 39 40
              dense
              flat
              round
              size="sm"
              icon="close"
hucy's avatar
hucy committed
41
              title="关闭"
hucy's avatar
hucy committed
42 43 44 45
              @mousedown.stop="doNothing"
              @click.stop="closeTab(page)"
            >
            </q-btn>
hucy's avatar
hucy committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

            <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>
hucy's avatar
hucy committed
64 65 66 67
          </q-tab>
        </q-tabs>

        <q-space />
hucy's avatar
hucy committed
68
        <language-select />
hucy's avatar
hucy committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        <div>Quasar v{{ $q.version }}</div>
      </q-toolbar>
    </q-header>

    <q-drawer v-model="leftDrawerOpen" show-if-above bordered>
      <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-drawer>

    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script lang="ts">
hucy's avatar
hucy committed
94 95 96 97 98 99 100 101
import {
  defineComponent,
  ref,
  onMounted,
  reactive,
  toRefs,
  computed,
} from 'vue';
hucy's avatar
hucy committed
102
import { onBeforeRouteUpdate, useRouter } from 'vue-router';
hucy's avatar
hucy committed
103
import { usePageStore } from 'src/common/hooks';
hucy's avatar
hucy committed
104
import EssentialLink from 'components/EssentialLink.vue';
hucy's avatar
hucy committed
105
// import TopLeftLoading from './TopLeftLoading.vue';
hucy's avatar
hucy committed
106
import { MenuList } from './config';
hucy's avatar
hucy committed
107
import TopLeftLoading from './TopLeftText.vue';
hucy's avatar
hucy committed
108
import LanguageSelect from './element/LanguageSelect.vue';
hucy's avatar
hucy committed
109 110 111 112 113 114 115

export default defineComponent({
  name: 'MainLayout',

  components: {
    EssentialLink,
    TopLeftLoading,
hucy's avatar
hucy committed
116
    LanguageSelect,
hucy's avatar
hucy committed
117 118 119 120 121
  },

  setup() {
    const pageStore = usePageStore();
    const router = useRouter();
hucy's avatar
hucy committed
122

hucy's avatar
hucy committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    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();
    });
hucy's avatar
hucy committed
138 139 140 141 142 143 144 145 146 147 148 149 150

    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;
    });

hucy's avatar
hucy committed
151 152 153 154 155 156 157 158 159
    onMounted(() => {
      getLinksList();
      const path = router.currentRoute.value.path;
      defaultRouter.value = path;
      pageStore.addRoute(router.currentRoute.value as any);
      getTabsList();
    });

    const getLinksList = () => {
hucy's avatar
hucy committed
160
      let lists = MenuList;
hucy's avatar
hucy committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
      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,
hucy's avatar
hucy committed
178
          name: item.name,
hucy's avatar
hucy committed
179 180 181 182 183 184 185 186 187
        };
      });
    };

    const clickTab = (page: any) => {
      router.push(page.link);
    };

    const closeTab = (page: any) => {
hucy's avatar
hucy committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201
      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);
hucy's avatar
hucy committed
202
      getTabsList();
hucy's avatar
hucy committed
203
      router.push(pageStore.activeRouter.path);
hucy's avatar
hucy committed
204 205 206
    };

    const closeAll = () => {
hucy's avatar
hucy committed
207 208 209
      pageStore.removeAllPage();
      router.push('/home');
      getTabsList();
hucy's avatar
hucy committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    };

    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,
hucy's avatar
hucy committed
228 229
      closeNotCurrentPage,
      closeAll,
hucy's avatar
hucy committed
230
      doNothing,
hucy's avatar
hucy committed
231
      isShowCloseBtn,
hucy's avatar
hucy committed
232 233 234 235 236 237
    };
  },
});
</script>
<style lang="scss" scoped>
.my-tab {
hucy's avatar
hucy committed
238 239 240
  box-sizing: border-box;
  background-color: $primary-4;
  margin: 0 2px;
hucy's avatar
hucy committed
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  :deep(.q-tab__content) {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    > button {
      color: transparent;
    }
    &:hover > button {
      color: white;
    }
    .q-tab__label {
      flex: 1;
    }
  }
}
hucy's avatar
hucy committed
256 257 258 259 260 261

.my-tabs {
  :deep(.q-tab--active) {
    background-color: $primary-2;
  }
}
hucy's avatar
hucy committed
262
</style>