mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	fix: 修复取消固定头部问题 (#75)
* fix: 修复取消固定头部问题 * perf: simplify the layout code
This commit is contained in:
		
							parent
							
								
									5a78685ac9
								
							
						
					
					
						commit
						1fa5793ec4
					
				
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@ -45,5 +45,6 @@
 | 
				
			|||||||
    "source.fixAll.eslint": true
 | 
					    "source.fixAll.eslint": true
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "volar.tsPlugin": true,
 | 
					  "volar.tsPlugin": true,
 | 
				
			||||||
  "typescript.tsdk": "node_modules/typescript/lib"
 | 
					  "typescript.tsdk": "node_modules/typescript/lib",
 | 
				
			||||||
 | 
					  "i18n-ally.localesPaths": ["src/plugins/i18n"]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,42 +1,72 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref, computed, getCurrentInstance } from "vue";
 | 
					import {
 | 
				
			||||||
 | 
					  h,
 | 
				
			||||||
 | 
					  ref,
 | 
				
			||||||
 | 
					  computed,
 | 
				
			||||||
 | 
					  Transition,
 | 
				
			||||||
 | 
					  defineComponent,
 | 
				
			||||||
 | 
					  getCurrentInstance
 | 
				
			||||||
 | 
					} from "vue";
 | 
				
			||||||
 | 
					import { RouterView } from "vue-router";
 | 
				
			||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
					import { usePermissionStoreHook } from "/@/store/modules/permission";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
					  fixedHeader: Boolean
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
const keepAlive: Boolean = ref(
 | 
					const keepAlive: Boolean = ref(
 | 
				
			||||||
  getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
 | 
					  getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const transition = computed(() => {
 | 
					const transitions = computed(() => {
 | 
				
			||||||
  return route => {
 | 
					  return route => {
 | 
				
			||||||
    return route.meta.transition;
 | 
					    return route.meta.transition;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const transitionMain = defineComponent({
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    return h(
 | 
				
			||||||
 | 
					      Transition,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        name:
 | 
				
			||||||
 | 
					          transitions.value(this.route) &&
 | 
				
			||||||
 | 
					          this.route.meta.transition.enterTransition
 | 
				
			||||||
 | 
					            ? "pure-classes-transition"
 | 
				
			||||||
 | 
					            : (transitions.value(this.route) &&
 | 
				
			||||||
 | 
					                this.route.meta.transition.name) ||
 | 
				
			||||||
 | 
					              "fade-transform",
 | 
				
			||||||
 | 
					        enterActiveClass:
 | 
				
			||||||
 | 
					          transitions.value(this.route) &&
 | 
				
			||||||
 | 
					          `animate__animated ${this.route.meta.transition.enterTransition}`,
 | 
				
			||||||
 | 
					        leaveActiveClass:
 | 
				
			||||||
 | 
					          transitions.value(this.route) &&
 | 
				
			||||||
 | 
					          `animate__animated ${this.route.meta.transition.leaveTransition}`,
 | 
				
			||||||
 | 
					        mode: "out-in",
 | 
				
			||||||
 | 
					        appear: true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        default: () => [this.$slots.default()]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  props: {
 | 
				
			||||||
 | 
					    route: {
 | 
				
			||||||
 | 
					      type: undefined,
 | 
				
			||||||
 | 
					      required: true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <section class="app-main">
 | 
					  <section
 | 
				
			||||||
    <el-scrollbar>
 | 
					    :class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
 | 
				
			||||||
      <el-backtop target=".app-main .el-scrollbar__wrap"></el-backtop>
 | 
					  >
 | 
				
			||||||
      <router-view>
 | 
					    <router-view>
 | 
				
			||||||
        <template #default="{ Component, route }">
 | 
					      <template #default="{ Component, route }">
 | 
				
			||||||
          <transition
 | 
					        <el-scrollbar v-if="props.fixedHeader">
 | 
				
			||||||
            :name="
 | 
					          <el-backtop target=".app-main .el-scrollbar__wrap"></el-backtop>
 | 
				
			||||||
              transition(route) && route.meta.transition.enterTransition
 | 
					          <transitionMain :route="route">
 | 
				
			||||||
                ? 'pure-classes-transition'
 | 
					 | 
				
			||||||
                : (transition(route) && route.meta.transition.name) ||
 | 
					 | 
				
			||||||
                  'fade-transform'
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
            :enter-active-class="
 | 
					 | 
				
			||||||
              transition(route) &&
 | 
					 | 
				
			||||||
              `animate__animated ${route.meta.transition.enterTransition}`
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
            :leave-active-class="
 | 
					 | 
				
			||||||
              transition(route) &&
 | 
					 | 
				
			||||||
              `animate__animated ${route.meta.transition.leaveTransition}`
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
            mode="out-in"
 | 
					 | 
				
			||||||
            appear
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            <keep-alive
 | 
					            <keep-alive
 | 
				
			||||||
              v-if="keepAlive"
 | 
					              v-if="keepAlive"
 | 
				
			||||||
              :include="usePermissionStoreHook().cachePageList"
 | 
					              :include="usePermissionStoreHook().cachePageList"
 | 
				
			||||||
@ -44,10 +74,21 @@ const transition = computed(() => {
 | 
				
			|||||||
              <component :is="Component" :key="route.fullPath" />
 | 
					              <component :is="Component" :key="route.fullPath" />
 | 
				
			||||||
            </keep-alive>
 | 
					            </keep-alive>
 | 
				
			||||||
            <component v-else :is="Component" :key="route.fullPath" />
 | 
					            <component v-else :is="Component" :key="route.fullPath" />
 | 
				
			||||||
          </transition>
 | 
					          </transitionMain>
 | 
				
			||||||
        </template>
 | 
					        </el-scrollbar>
 | 
				
			||||||
      </router-view>
 | 
					        <div v-else>
 | 
				
			||||||
    </el-scrollbar>
 | 
					          <transitionMain :route="route">
 | 
				
			||||||
 | 
					            <keep-alive
 | 
				
			||||||
 | 
					              v-if="keepAlive"
 | 
				
			||||||
 | 
					              :include="usePermissionStoreHook().cachePageList"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <component :is="Component" :key="route.fullPath" />
 | 
				
			||||||
 | 
					            </keep-alive>
 | 
				
			||||||
 | 
					            <component v-else :is="Component" :key="route.fullPath" />
 | 
				
			||||||
 | 
					          </transitionMain>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					    </router-view>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -58,4 +99,10 @@ const transition = computed(() => {
 | 
				
			|||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  overflow-x: hidden;
 | 
					  overflow-x: hidden;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.app-main-nofixed-header {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  min-height: 100vh;
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,32 +1,6 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
import { routerArrays } from "./types";
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
  computed: {
 | 
					 | 
				
			||||||
    layout() {
 | 
					 | 
				
			||||||
      if (!this.$storage.layout) {
 | 
					 | 
				
			||||||
        // eslint-disable-next-line vue/no-side-effects-in-computed-properties
 | 
					 | 
				
			||||||
        this.$storage.layout = { layout: "vertical-dark" };
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (
 | 
					 | 
				
			||||||
        !this.$storage.routesInStorage ||
 | 
					 | 
				
			||||||
        this.$storage.routesInStorage.length === 0
 | 
					 | 
				
			||||||
      ) {
 | 
					 | 
				
			||||||
        // eslint-disable-next-line vue/no-side-effects-in-computed-properties
 | 
					 | 
				
			||||||
        this.$storage.routesInStorage = routerArrays;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (!this.$storage.locale) {
 | 
					 | 
				
			||||||
        // eslint-disable-next-line
 | 
					 | 
				
			||||||
        this.$storage.locale = { locale: "zh" };
 | 
					 | 
				
			||||||
        useI18n().locale.value = "zh";
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return this.$storage?.layout.layout;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					  h,
 | 
				
			||||||
  ref,
 | 
					  ref,
 | 
				
			||||||
  unref,
 | 
					  unref,
 | 
				
			||||||
  reactive,
 | 
					  reactive,
 | 
				
			||||||
@ -34,10 +8,12 @@ import {
 | 
				
			|||||||
  onMounted,
 | 
					  onMounted,
 | 
				
			||||||
  watchEffect,
 | 
					  watchEffect,
 | 
				
			||||||
  onBeforeMount,
 | 
					  onBeforeMount,
 | 
				
			||||||
 | 
					  defineComponent,
 | 
				
			||||||
  getCurrentInstance
 | 
					  getCurrentInstance
 | 
				
			||||||
} from "vue";
 | 
					} from "vue";
 | 
				
			||||||
import { setType } from "./types";
 | 
					import { setType } from "./types";
 | 
				
			||||||
import { useI18n } from "vue-i18n";
 | 
					import { useI18n } from "vue-i18n";
 | 
				
			||||||
 | 
					import { routerArrays } from "./types";
 | 
				
			||||||
import { emitter } from "/@/utils/mitt";
 | 
					import { emitter } from "/@/utils/mitt";
 | 
				
			||||||
import { useEventListener } from "@vueuse/core";
 | 
					import { useEventListener } from "@vueuse/core";
 | 
				
			||||||
import { storageLocal } from "/@/utils/storage";
 | 
					import { storageLocal } from "/@/utils/storage";
 | 
				
			||||||
@ -62,6 +38,23 @@ const hiddenSideBar = ref(
 | 
				
			|||||||
  getCurrentInstance().appContext.config.globalProperties.$config?.HiddenSideBar
 | 
					  getCurrentInstance().appContext.config.globalProperties.$config?.HiddenSideBar
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const layout = computed(() => {
 | 
				
			||||||
 | 
					  if (!instance.layout) {
 | 
				
			||||||
 | 
					    // eslint-disable-next-line vue/no-side-effects-in-computed-properties
 | 
				
			||||||
 | 
					    instance.layout = { layout: "vertical-dark" };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!instance.routesInStorage || instance.routesInStorage.length === 0) {
 | 
				
			||||||
 | 
					    // eslint-disable-next-line vue/no-side-effects-in-computed-properties
 | 
				
			||||||
 | 
					    instance.routesInStorage = routerArrays;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!instance.locale) {
 | 
				
			||||||
 | 
					    // eslint-disable-next-line
 | 
				
			||||||
 | 
					    instance.locale = { locale: "zh" };
 | 
				
			||||||
 | 
					    useI18n().locale.value = "zh";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return instance?.layout.layout;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const set: setType = reactive({
 | 
					const set: setType = reactive({
 | 
				
			||||||
  sidebar: computed(() => {
 | 
					  sidebar: computed(() => {
 | 
				
			||||||
    return useAppStoreHook().sidebar;
 | 
					    return useAppStoreHook().sidebar;
 | 
				
			||||||
@ -141,6 +134,42 @@ onMounted(() => {
 | 
				
			|||||||
onBeforeMount(() => {
 | 
					onBeforeMount(() => {
 | 
				
			||||||
  useEventListener("resize", $_resizeHandler);
 | 
					  useEventListener("resize", $_resizeHandler);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const layoutHeader = defineComponent({
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    return h(
 | 
				
			||||||
 | 
					      "div",
 | 
				
			||||||
 | 
					      { class: { "fixed-header": set.fixedHeader } },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        default: () => [
 | 
				
			||||||
 | 
					          !hiddenSideBar.value && layout.value.includes("vertical")
 | 
				
			||||||
 | 
					            ? h(navbar)
 | 
				
			||||||
 | 
					            : h("div"),
 | 
				
			||||||
 | 
					          !hiddenSideBar.value && layout.value.includes("horizontal")
 | 
				
			||||||
 | 
					            ? h(Horizontal)
 | 
				
			||||||
 | 
					            : h("div"),
 | 
				
			||||||
 | 
					          h(
 | 
				
			||||||
 | 
					            tag,
 | 
				
			||||||
 | 
					            {},
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              default: () => [
 | 
				
			||||||
 | 
					                h(
 | 
				
			||||||
 | 
					                  "span",
 | 
				
			||||||
 | 
					                  { onClick: onFullScreen },
 | 
				
			||||||
 | 
					                  {
 | 
				
			||||||
 | 
					                    default: () => [
 | 
				
			||||||
 | 
					                      !hiddenSideBar.value ? h(fullScreen) : h(exitScreen)
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					              ]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -156,20 +185,17 @@ onBeforeMount(() => {
 | 
				
			|||||||
    />
 | 
					    />
 | 
				
			||||||
    <Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
 | 
					    <Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
 | 
				
			||||||
    <div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
 | 
					    <div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
 | 
				
			||||||
      <div :class="{ 'fixed-header': set.fixedHeader }">
 | 
					      <div v-if="set.fixedHeader">
 | 
				
			||||||
        <!-- 顶部导航栏 -->
 | 
					        <layout-header />
 | 
				
			||||||
        <navbar v-show="!hiddenSideBar && layout.includes('vertical')" />
 | 
					        <!-- 主体内容 -->
 | 
				
			||||||
        <!-- tabs标签页 -->
 | 
					        <app-main :fixed-header="set.fixedHeader" />
 | 
				
			||||||
        <Horizontal v-show="!hiddenSideBar && layout.includes('horizontal')" />
 | 
					 | 
				
			||||||
        <tag>
 | 
					 | 
				
			||||||
          <span @click="onFullScreen">
 | 
					 | 
				
			||||||
            <fullScreen v-if="!hiddenSideBar" />
 | 
					 | 
				
			||||||
            <exitScreen v-else />
 | 
					 | 
				
			||||||
          </span>
 | 
					 | 
				
			||||||
        </tag>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <!-- 主体内容 -->
 | 
					      <el-scrollbar v-else>
 | 
				
			||||||
      <app-main />
 | 
					        <el-backtop target=".main-container .el-scrollbar__wrap"></el-backtop>
 | 
				
			||||||
 | 
					        <layout-header />
 | 
				
			||||||
 | 
					        <!-- 主体内容 -->
 | 
				
			||||||
 | 
					        <app-main :fixed-header="set.fixedHeader" />
 | 
				
			||||||
 | 
					      </el-scrollbar>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <!-- 系统设置 -->
 | 
					    <!-- 系统设置 -->
 | 
				
			||||||
    <setting />
 | 
					    <setting />
 | 
				
			||||||
 | 
				
			|||||||
@ -16,11 +16,33 @@
 | 
				
			|||||||
  $menuText: #7a80b4;
 | 
					  $menuText: #7a80b4;
 | 
				
			||||||
  $menuActiveText: #7a80b4;
 | 
					  $menuActiveText: #7a80b4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @media screen and (min-width: 150px) and (max-width: 420px) {
 | 
				
			||||||
 | 
					    .app-main-nofixed-header {
 | 
				
			||||||
 | 
					      overflow-y: hidden;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @media screen and (min-width: 420px) {
 | 
				
			||||||
 | 
					    .app-main-nofixed-header {
 | 
				
			||||||
 | 
					      overflow: hidden;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .main-container {
 | 
					  .main-container {
 | 
				
			||||||
 | 
					    height: 100vh;
 | 
				
			||||||
    min-height: 100%;
 | 
					    min-height: 100%;
 | 
				
			||||||
    transition: margin-left 0.28s;
 | 
					    transition: margin-left 0.28s;
 | 
				
			||||||
    margin-left: $sideBarWidth;
 | 
					    margin-left: $sideBarWidth;
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    @media screen and (min-width: 150px) and (max-width: 420px) {
 | 
				
			||||||
 | 
					      .el-scrollbar__view {
 | 
				
			||||||
 | 
					        overflow-y: hidden;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    @media screen and (min-width: 420px) {
 | 
				
			||||||
 | 
					      .el-scrollbar__view {
 | 
				
			||||||
 | 
					        overflow: hidden;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .fixed-header {
 | 
					  .fixed-header {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user