Explorar el Código

fix: 修复取消固定头部问题 (#75)

* fix: 修复取消固定头部问题

* perf: simplify the layout code
啝裳 hace 3 años
padre
commit
1fa5793ec4
Se han modificado 4 ficheros con 166 adiciones y 70 borrados
  1. 2 1
      .vscode/settings.json
  2. 76 29
      src/layout/components/appMain.vue
  3. 66 40
      src/layout/index.vue
  4. 22 0
      src/style/sidebar.scss

+ 2 - 1
.vscode/settings.json

@@ -45,5 +45,6 @@
     "source.fixAll.eslint": true
   },
   "volar.tsPlugin": true,
-  "typescript.tsdk": "node_modules/typescript/lib"
+  "typescript.tsdk": "node_modules/typescript/lib",
+  "i18n-ally.localesPaths": ["src/plugins/i18n"]
 }

+ 76 - 29
src/layout/components/appMain.vue

@@ -1,42 +1,83 @@
 <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";
 
+const props = defineProps({
+  fixedHeader: Boolean
+});
 const keepAlive: Boolean = ref(
   getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
 );
 
-const transition = computed(() => {
+const transitions = computed(() => {
   return route => {
     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>
 
 <template>
-  <section class="app-main">
-    <el-scrollbar>
-      <el-backtop target=".app-main .el-scrollbar__wrap"></el-backtop>
-      <router-view>
-        <template #default="{ Component, route }">
-          <transition
-            :name="
-              transition(route) && route.meta.transition.enterTransition
-                ? '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
-          >
+  <section
+    :class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
+  >
+    <router-view>
+      <template #default="{ Component, route }">
+        <el-scrollbar v-if="props.fixedHeader">
+          <el-backtop target=".app-main .el-scrollbar__wrap"></el-backtop>
+          <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>
+        </el-scrollbar>
+        <div v-else>
+          <transitionMain :route="route">
             <keep-alive
               v-if="keepAlive"
               :include="usePermissionStoreHook().cachePageList"
@@ -44,10 +85,10 @@ const transition = computed(() => {
               <component :is="Component" :key="route.fullPath" />
             </keep-alive>
             <component v-else :is="Component" :key="route.fullPath" />
-          </transition>
-        </template>
-      </router-view>
-    </el-scrollbar>
+          </transitionMain>
+        </div>
+      </template>
+    </router-view>
   </section>
 </template>
 
@@ -58,4 +99,10 @@ const transition = computed(() => {
   position: relative;
   overflow-x: hidden;
 }
+
+.app-main-nofixed-header {
+  width: 100%;
+  min-height: 100vh;
+  position: relative;
+}
 </style>

+ 66 - 40
src/layout/index.vue

@@ -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">
 import {
+  h,
   ref,
   unref,
   reactive,
@@ -34,10 +8,12 @@ import {
   onMounted,
   watchEffect,
   onBeforeMount,
+  defineComponent,
   getCurrentInstance
 } from "vue";
 import { setType } from "./types";
 import { useI18n } from "vue-i18n";
+import { routerArrays } from "./types";
 import { emitter } from "/@/utils/mitt";
 import { useEventListener } from "@vueuse/core";
 import { storageLocal } from "/@/utils/storage";
@@ -62,6 +38,23 @@ const hiddenSideBar = ref(
   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({
   sidebar: computed(() => {
     return useAppStoreHook().sidebar;
@@ -141,6 +134,42 @@ onMounted(() => {
 onBeforeMount(() => {
   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>
 
 <template>
@@ -156,20 +185,17 @@ onBeforeMount(() => {
     />
     <Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
     <div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
-      <div :class="{ 'fixed-header': set.fixedHeader }">
-        <!-- 顶部导航栏 -->
-        <navbar v-show="!hiddenSideBar && layout.includes('vertical')" />
-        <!-- tabs标签页 -->
-        <Horizontal v-show="!hiddenSideBar && layout.includes('horizontal')" />
-        <tag>
-          <span @click="onFullScreen">
-            <fullScreen v-if="!hiddenSideBar" />
-            <exitScreen v-else />
-          </span>
-        </tag>
+      <div v-if="set.fixedHeader">
+        <layout-header />
+        <!-- 主体内容 -->
+        <app-main :fixed-header="set.fixedHeader" />
       </div>
-      <!-- 主体内容 -->
-      <app-main />
+      <el-scrollbar v-else>
+        <el-backtop target=".main-container .el-scrollbar__wrap"></el-backtop>
+        <layout-header />
+        <!-- 主体内容 -->
+        <app-main :fixed-header="set.fixedHeader" />
+      </el-scrollbar>
     </div>
     <!-- 系统设置 -->
     <setting />

+ 22 - 0
src/style/sidebar.scss

@@ -16,11 +16,33 @@
   $menuText: #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 {
+    height: 100vh;
     min-height: 100%;
     transition: margin-left 0.28s;
     margin-left: $sideBarWidth;
     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 {