mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	perf: perf layout
This commit is contained in:
		
							parent
							
								
									15e751dee8
								
							
						
					
					
						commit
						fe6dfb9e3d
					
				@ -21,6 +21,7 @@ const getBreadcrumb = (): void => {
 | 
			
		||||
    matched = [
 | 
			
		||||
      {
 | 
			
		||||
        path: "/welcome",
 | 
			
		||||
        parentPath: "/",
 | 
			
		||||
        meta: { title: "message.hshome" }
 | 
			
		||||
      } as unknown as RouteLocationMatched
 | 
			
		||||
    ].concat(matched);
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,19 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref, unref, computed, getCurrentInstance } from "vue";
 | 
			
		||||
import { useSettingStoreHook } from "/@/store/modules/settings";
 | 
			
		||||
 | 
			
		||||
const keepAlive: Boolean = ref(
 | 
			
		||||
  getCurrentInstance().appContext.config.globalProperties.$config?.keepAlive
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const getCachedPageList = computed((): string[] => {
 | 
			
		||||
  if (!unref(keepAlive)) {
 | 
			
		||||
    return [];
 | 
			
		||||
  }
 | 
			
		||||
  return useSettingStoreHook().cachedPageList;
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <section class="app-main">
 | 
			
		||||
    <router-view>
 | 
			
		||||
@ -13,32 +29,6 @@
 | 
			
		||||
  </section>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { ref, unref, computed, defineComponent, getCurrentInstance } from "vue";
 | 
			
		||||
import { useRoute } from "vue-router";
 | 
			
		||||
import { useSettingStoreHook } from "/@/store/modules/settings";
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: "appMain",
 | 
			
		||||
  setup() {
 | 
			
		||||
    const keepAlive: Boolean = ref(
 | 
			
		||||
      getCurrentInstance().appContext.config.globalProperties.$config?.keepAlive
 | 
			
		||||
    );
 | 
			
		||||
    const route = useRoute();
 | 
			
		||||
    const key = computed(() => route.path);
 | 
			
		||||
 | 
			
		||||
    const getCachedPageList = computed((): string[] => {
 | 
			
		||||
      if (!unref(keepAlive)) {
 | 
			
		||||
        return [];
 | 
			
		||||
      }
 | 
			
		||||
      return useSettingStoreHook().cachedPageList;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return { key, keepAlive, getCachedPageList };
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.app-main {
 | 
			
		||||
  min-height: calc(100vh - 70px);
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,7 @@ import { useI18n } from "vue-i18n";
 | 
			
		||||
let routerArrays: Array<object> = [
 | 
			
		||||
  {
 | 
			
		||||
    path: "/welcome",
 | 
			
		||||
    parentPath: "/",
 | 
			
		||||
    meta: {
 | 
			
		||||
      title: "message.hshome",
 | 
			
		||||
      icon: "el-icon-s-home",
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,35 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { useEventListener, onClickOutside } from "@vueuse/core";
 | 
			
		||||
import { emitter } from "/@/utils/mitt";
 | 
			
		||||
 | 
			
		||||
let show = ref(false);
 | 
			
		||||
const target = ref(null);
 | 
			
		||||
onClickOutside(target, () => {
 | 
			
		||||
  show.value = false;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const addEventClick = (): void => {
 | 
			
		||||
  useEventListener("click", closeSidebar);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const closeSidebar = (evt: any): void => {
 | 
			
		||||
  const parent = evt.target.closest(".right-panel");
 | 
			
		||||
  if (!parent) {
 | 
			
		||||
    show.value = false;
 | 
			
		||||
    window.removeEventListener("click", closeSidebar);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
emitter.on("openPanel", () => {
 | 
			
		||||
  show.value = true;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineExpose({
 | 
			
		||||
  addEventClick
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :class="{ show: show }" class="right-panel-container">
 | 
			
		||||
    <div class="right-panel-background" />
 | 
			
		||||
@ -14,47 +46,6 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { useEventListener, onClickOutside } from "@vueuse/core";
 | 
			
		||||
import { emitter } from "/@/utils/mitt";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "panel",
 | 
			
		||||
  setup() {
 | 
			
		||||
    let show = ref(false);
 | 
			
		||||
 | 
			
		||||
    const target = ref(null);
 | 
			
		||||
 | 
			
		||||
    onClickOutside(target, () => {
 | 
			
		||||
      show.value = false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
 | 
			
		||||
    const addEventClick = (): void => {
 | 
			
		||||
      useEventListener("click", closeSidebar);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const closeSidebar = (evt: any): void => {
 | 
			
		||||
      const parent = evt.target.closest(".right-panel");
 | 
			
		||||
      if (!parent) {
 | 
			
		||||
        show.value = false;
 | 
			
		||||
        window.removeEventListener("click", closeSidebar);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    emitter.on("openPanel", () => {
 | 
			
		||||
      show.value = true;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      show,
 | 
			
		||||
      target
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.showright-panel {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,118 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import panel from "../panel/index.vue";
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
import { emitter } from "/@/utils/mitt";
 | 
			
		||||
import { templateRef } from "@vueuse/core";
 | 
			
		||||
import { reactive, ref, unref, useCssModule } from "vue";
 | 
			
		||||
import { storageLocal, storageSession } from "/@/utils/storage";
 | 
			
		||||
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
const { isSelect } = useCssModule();
 | 
			
		||||
 | 
			
		||||
// 默认灵动模式
 | 
			
		||||
const markValue = ref(storageLocal.getItem("showModel") || "smart");
 | 
			
		||||
 | 
			
		||||
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
 | 
			
		||||
 | 
			
		||||
const localOperate = (key: string, value?: any, model?: string): any => {
 | 
			
		||||
  model && model === "set"
 | 
			
		||||
    ? storageLocal.setItem(key, value)
 | 
			
		||||
    : storageLocal.getItem(key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const settings = reactive({
 | 
			
		||||
  greyVal: storageLocal.getItem("greyVal"),
 | 
			
		||||
  weekVal: storageLocal.getItem("weekVal"),
 | 
			
		||||
  tagsVal: storageLocal.getItem("tagsVal")
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
settings.greyVal === null
 | 
			
		||||
  ? localOperate("greyVal", false, "set")
 | 
			
		||||
  : document.querySelector("html")?.setAttribute("class", "html-grey");
 | 
			
		||||
 | 
			
		||||
settings.weekVal === null
 | 
			
		||||
  ? localOperate("weekVal", false, "set")
 | 
			
		||||
  : document.querySelector("html")?.setAttribute("class", "html-weakness");
 | 
			
		||||
 | 
			
		||||
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
 | 
			
		||||
  const targetEl = target || document.body;
 | 
			
		||||
  let { className } = targetEl;
 | 
			
		||||
  className = className.replace(clsName, "");
 | 
			
		||||
  targetEl.className = flag ? `${className} ${clsName} ` : className;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 灰色模式设置
 | 
			
		||||
const greyChange = ({ value }): void => {
 | 
			
		||||
  toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
 | 
			
		||||
  value
 | 
			
		||||
    ? localOperate("greyVal", true, "set")
 | 
			
		||||
    : localOperate("greyVal", false, "set");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 色弱模式设置
 | 
			
		||||
const weekChange = ({ value }): void => {
 | 
			
		||||
  toggleClass(
 | 
			
		||||
    settings.weekVal,
 | 
			
		||||
    "html-weakness",
 | 
			
		||||
    document.querySelector("html")
 | 
			
		||||
  );
 | 
			
		||||
  value
 | 
			
		||||
    ? localOperate("weekVal", true, "set")
 | 
			
		||||
    : localOperate("weekVal", false, "set");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const tagsChange = () => {
 | 
			
		||||
  let showVal = settings.tagsVal;
 | 
			
		||||
  showVal
 | 
			
		||||
    ? storageLocal.setItem("tagsVal", true)
 | 
			
		||||
    : storageLocal.setItem("tagsVal", false);
 | 
			
		||||
  emitter.emit("tagViewsChange", showVal);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function onReset() {
 | 
			
		||||
  storageLocal.clear();
 | 
			
		||||
  storageSession.clear();
 | 
			
		||||
  router.push("/login");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onChange({ label }) {
 | 
			
		||||
  storageLocal.setItem("showModel", label);
 | 
			
		||||
  emitter.emit("tagViewsShowModel", label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const firstTheme = templateRef<HTMLElement | null>("firstTheme", null);
 | 
			
		||||
const secondTheme = templateRef<HTMLElement | null>("secondTheme", null);
 | 
			
		||||
 | 
			
		||||
const dataTheme = ref(storageLocal.getItem("data-theme") || "dark");
 | 
			
		||||
if (dataTheme.value) {
 | 
			
		||||
  storageLocal.setItem("data-theme", unref(dataTheme));
 | 
			
		||||
  window.document.body.setAttribute("data-theme", unref(dataTheme));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dark主题
 | 
			
		||||
function onDark() {
 | 
			
		||||
  storageLocal.setItem("data-theme", "dark");
 | 
			
		||||
  window.document.body.setAttribute("data-theme", "dark");
 | 
			
		||||
  toggleClass(true, isSelect, unref(firstTheme));
 | 
			
		||||
  toggleClass(false, isSelect, unref(secondTheme));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// light主题
 | 
			
		||||
function onLight() {
 | 
			
		||||
  storageLocal.setItem("data-theme", "light");
 | 
			
		||||
  window.document.body.setAttribute("data-theme", "light");
 | 
			
		||||
  toggleClass(false, isSelect, unref(firstTheme));
 | 
			
		||||
  toggleClass(true, isSelect, unref(secondTheme));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function logoChange() {
 | 
			
		||||
  unref(logoVal) === "1"
 | 
			
		||||
    ? storageLocal.setItem("logoVal", "1")
 | 
			
		||||
    : storageLocal.setItem("logoVal", "-1");
 | 
			
		||||
  emitter.emit("logoChange", unref(logoVal));
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <panel>
 | 
			
		||||
    <el-divider>主题风格</el-divider>
 | 
			
		||||
@ -40,7 +155,7 @@
 | 
			
		||||
      <li>
 | 
			
		||||
        <span>灰色模式</span>
 | 
			
		||||
        <vxe-switch
 | 
			
		||||
          v-model="greyVal"
 | 
			
		||||
          v-model="settings.greyVal"
 | 
			
		||||
          open-label="开"
 | 
			
		||||
          close-label="关"
 | 
			
		||||
          @change="greyChange"
 | 
			
		||||
@ -49,7 +164,7 @@
 | 
			
		||||
      <li>
 | 
			
		||||
        <span>色弱模式</span>
 | 
			
		||||
        <vxe-switch
 | 
			
		||||
          v-model="weekVal"
 | 
			
		||||
          v-model="settings.weekVal"
 | 
			
		||||
          open-label="开"
 | 
			
		||||
          close-label="关"
 | 
			
		||||
          @change="weekChange"
 | 
			
		||||
@ -58,7 +173,7 @@
 | 
			
		||||
      <li>
 | 
			
		||||
        <span>隐藏标签页</span>
 | 
			
		||||
        <vxe-switch
 | 
			
		||||
          v-model="tagsVal"
 | 
			
		||||
          v-model="settings.tagsVal"
 | 
			
		||||
          open-label="开"
 | 
			
		||||
          close-label="关"
 | 
			
		||||
          @change="tagsChange"
 | 
			
		||||
@ -96,147 +211,6 @@
 | 
			
		||||
  </panel>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import panel from "../panel/index.vue";
 | 
			
		||||
import { reactive, toRefs, ref, unref, useCssModule } from "vue";
 | 
			
		||||
import { storageLocal, storageSession } from "/@/utils/storage";
 | 
			
		||||
import { emitter } from "/@/utils/mitt";
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
import { templateRef } from "@vueuse/core";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "setting",
 | 
			
		||||
  components: { panel },
 | 
			
		||||
  setup() {
 | 
			
		||||
    const router = useRouter();
 | 
			
		||||
    const { isSelect } = useCssModule();
 | 
			
		||||
 | 
			
		||||
    // 默认灵动模式
 | 
			
		||||
    const markValue = ref(storageLocal.getItem("showModel") || "smart");
 | 
			
		||||
 | 
			
		||||
    const logoVal = ref(storageLocal.getItem("logoVal") || "1");
 | 
			
		||||
 | 
			
		||||
    const localOperate = (key: string, value?: any, model?: string): any => {
 | 
			
		||||
      model && model === "set"
 | 
			
		||||
        ? storageLocal.setItem(key, value)
 | 
			
		||||
        : storageLocal.getItem(key);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const settings = reactive({
 | 
			
		||||
      greyVal: storageLocal.getItem("greyVal"),
 | 
			
		||||
      weekVal: storageLocal.getItem("weekVal"),
 | 
			
		||||
      tagsVal: storageLocal.getItem("tagsVal")
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    settings.greyVal === null
 | 
			
		||||
      ? localOperate("greyVal", false, "set")
 | 
			
		||||
      : document.querySelector("html")?.setAttribute("class", "html-grey");
 | 
			
		||||
 | 
			
		||||
    settings.weekVal === null
 | 
			
		||||
      ? localOperate("weekVal", false, "set")
 | 
			
		||||
      : document.querySelector("html")?.setAttribute("class", "html-weakness");
 | 
			
		||||
 | 
			
		||||
    function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
 | 
			
		||||
      const targetEl = target || document.body;
 | 
			
		||||
      let { className } = targetEl;
 | 
			
		||||
      className = className.replace(clsName, "");
 | 
			
		||||
      targetEl.className = flag ? `${className} ${clsName} ` : className;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 灰色模式设置
 | 
			
		||||
    const greyChange = ({ value }): void => {
 | 
			
		||||
      toggleClass(
 | 
			
		||||
        settings.greyVal,
 | 
			
		||||
        "html-grey",
 | 
			
		||||
        document.querySelector("html")
 | 
			
		||||
      );
 | 
			
		||||
      value
 | 
			
		||||
        ? localOperate("greyVal", true, "set")
 | 
			
		||||
        : localOperate("greyVal", false, "set");
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // 色弱模式设置
 | 
			
		||||
    const weekChange = ({ value }): void => {
 | 
			
		||||
      toggleClass(
 | 
			
		||||
        settings.weekVal,
 | 
			
		||||
        "html-weakness",
 | 
			
		||||
        document.querySelector("html")
 | 
			
		||||
      );
 | 
			
		||||
      value
 | 
			
		||||
        ? localOperate("weekVal", true, "set")
 | 
			
		||||
        : localOperate("weekVal", false, "set");
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const tagsChange = () => {
 | 
			
		||||
      let showVal = settings.tagsVal;
 | 
			
		||||
      showVal
 | 
			
		||||
        ? storageLocal.setItem("tagsVal", true)
 | 
			
		||||
        : storageLocal.setItem("tagsVal", false);
 | 
			
		||||
      emitter.emit("tagViewsChange", showVal);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function onReset() {
 | 
			
		||||
      storageLocal.clear();
 | 
			
		||||
      storageSession.clear();
 | 
			
		||||
      router.push("/login");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onChange({ label }) {
 | 
			
		||||
      storageLocal.setItem("showModel", label);
 | 
			
		||||
      emitter.emit("tagViewsShowModel", label);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const firstTheme = templateRef<HTMLElement | null>("firstTheme", null);
 | 
			
		||||
    const secondTheme = templateRef<HTMLElement | null>("secondTheme", null);
 | 
			
		||||
 | 
			
		||||
    const dataTheme = ref(storageLocal.getItem("data-theme") || "dark");
 | 
			
		||||
    if (dataTheme.value) {
 | 
			
		||||
      storageLocal.setItem("data-theme", unref(dataTheme));
 | 
			
		||||
      window.document.body.setAttribute("data-theme", unref(dataTheme));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // dark主题
 | 
			
		||||
    function onDark() {
 | 
			
		||||
      storageLocal.setItem("data-theme", "dark");
 | 
			
		||||
      window.document.body.setAttribute("data-theme", "dark");
 | 
			
		||||
      toggleClass(true, isSelect, unref(firstTheme));
 | 
			
		||||
      toggleClass(false, isSelect, unref(secondTheme));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // light主题
 | 
			
		||||
    function onLight() {
 | 
			
		||||
      storageLocal.setItem("data-theme", "light");
 | 
			
		||||
      window.document.body.setAttribute("data-theme", "light");
 | 
			
		||||
      toggleClass(false, isSelect, unref(firstTheme));
 | 
			
		||||
      toggleClass(true, isSelect, unref(secondTheme));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function logoChange() {
 | 
			
		||||
      unref(logoVal) === "1"
 | 
			
		||||
        ? storageLocal.setItem("logoVal", "1")
 | 
			
		||||
        : storageLocal.setItem("logoVal", "-1");
 | 
			
		||||
      emitter.emit("logoChange", unref(logoVal));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      ...toRefs(settings),
 | 
			
		||||
      localOperate,
 | 
			
		||||
      greyChange,
 | 
			
		||||
      weekChange,
 | 
			
		||||
      tagsChange,
 | 
			
		||||
      onReset,
 | 
			
		||||
      markValue,
 | 
			
		||||
      onChange,
 | 
			
		||||
      onDark,
 | 
			
		||||
      onLight,
 | 
			
		||||
      dataTheme,
 | 
			
		||||
      logoVal,
 | 
			
		||||
      logoChange
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped module>
 | 
			
		||||
.isSelect {
 | 
			
		||||
  border: 2px solid #0960bd;
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,9 @@
 | 
			
		||||
  </component>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent, unref } from "vue";
 | 
			
		||||
import { isUrl } from "/@/utils/is.ts";
 | 
			
		||||
import { isUrl } from "/@/utils/is";
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: "Link",
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,133 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import {
 | 
			
		||||
  ref,
 | 
			
		||||
  unref,
 | 
			
		||||
  reactive,
 | 
			
		||||
  computed,
 | 
			
		||||
  watchEffect,
 | 
			
		||||
  onMounted,
 | 
			
		||||
  onBeforeMount,
 | 
			
		||||
  useCssModule
 | 
			
		||||
} from "vue";
 | 
			
		||||
import options from "/@/settings";
 | 
			
		||||
import { toggleClass } from "/@/utils/operate";
 | 
			
		||||
import { useEventListener } from "@vueuse/core";
 | 
			
		||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
			
		||||
import fullScreen from "/@/assets/svg/full_screen.svg";
 | 
			
		||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
 | 
			
		||||
import { useSettingStoreHook } from "/@/store/modules/settings";
 | 
			
		||||
import { Navbar, Sidebar, AppMain, setting, tag } from "./components";
 | 
			
		||||
 | 
			
		||||
interface setInter {
 | 
			
		||||
  sidebar: any;
 | 
			
		||||
  device: string;
 | 
			
		||||
  fixedHeader: boolean;
 | 
			
		||||
  classes: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const pureApp = useAppStoreHook();
 | 
			
		||||
const pureSetting = useSettingStoreHook();
 | 
			
		||||
const { hiddenMainContainer } = useCssModule();
 | 
			
		||||
 | 
			
		||||
const WIDTH = ref(992);
 | 
			
		||||
 | 
			
		||||
let containerHiddenSideBar = ref(options.hiddenSideBar);
 | 
			
		||||
 | 
			
		||||
const set: setInter = reactive({
 | 
			
		||||
  sidebar: computed(() => {
 | 
			
		||||
    return pureApp.sidebar;
 | 
			
		||||
  }),
 | 
			
		||||
 | 
			
		||||
  device: computed(() => {
 | 
			
		||||
    return pureApp.device;
 | 
			
		||||
  }),
 | 
			
		||||
 | 
			
		||||
  fixedHeader: computed(() => {
 | 
			
		||||
    return pureSetting.fixedHeader;
 | 
			
		||||
  }),
 | 
			
		||||
 | 
			
		||||
  classes: computed(() => {
 | 
			
		||||
    return {
 | 
			
		||||
      hideSidebar: !set.sidebar.opened,
 | 
			
		||||
      openSidebar: set.sidebar.opened,
 | 
			
		||||
      withoutAnimation: set.sidebar.withoutAnimation,
 | 
			
		||||
      mobile: set.device === "mobile"
 | 
			
		||||
    };
 | 
			
		||||
  })
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleClickOutside = (params: boolean) => {
 | 
			
		||||
  pureApp.closeSideBar({ withoutAnimation: params });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
  if (set.device === "mobile" && !set.sidebar.opened) {
 | 
			
		||||
    handleClickOutside(false);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const $_isMobile = () => {
 | 
			
		||||
  const rect = document.body.getBoundingClientRect();
 | 
			
		||||
  return rect.width - 1 < WIDTH.value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const $_resizeHandler = () => {
 | 
			
		||||
  if (!document.hidden) {
 | 
			
		||||
    const isMobile = $_isMobile();
 | 
			
		||||
    pureApp.toggleDevice(isMobile ? "mobile" : "desktop");
 | 
			
		||||
    if (isMobile) {
 | 
			
		||||
      handleClickOutside(true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function onFullScreen() {
 | 
			
		||||
  if (unref(containerHiddenSideBar)) {
 | 
			
		||||
    containerHiddenSideBar.value = false;
 | 
			
		||||
    toggleClass(
 | 
			
		||||
      false,
 | 
			
		||||
      hiddenMainContainer,
 | 
			
		||||
      document.querySelector(".main-container")
 | 
			
		||||
    );
 | 
			
		||||
  } else {
 | 
			
		||||
    containerHiddenSideBar.value = true;
 | 
			
		||||
    toggleClass(
 | 
			
		||||
      true,
 | 
			
		||||
      hiddenMainContainer,
 | 
			
		||||
      document.querySelector(".main-container")
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  const isMobile = $_isMobile();
 | 
			
		||||
  if (isMobile) {
 | 
			
		||||
    pureApp.toggleDevice("mobile");
 | 
			
		||||
    handleClickOutside(true);
 | 
			
		||||
  }
 | 
			
		||||
  toggleClass(
 | 
			
		||||
    unref(containerHiddenSideBar),
 | 
			
		||||
    hiddenMainContainer,
 | 
			
		||||
    document.querySelector(".main-container")
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onBeforeMount(() => {
 | 
			
		||||
  useEventListener("resize", $_resizeHandler);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :class="classes" class="app-wrapper">
 | 
			
		||||
  <div :class="set.classes" class="app-wrapper">
 | 
			
		||||
    <div
 | 
			
		||||
      v-if="device === 'mobile' && sidebar.opened"
 | 
			
		||||
      v-if="set.device === 'mobile' && set.sidebar.opened"
 | 
			
		||||
      class="drawer-bg"
 | 
			
		||||
      @click="handleClickOutside(false)"
 | 
			
		||||
    />
 | 
			
		||||
    <!-- 侧边栏 -->
 | 
			
		||||
    <sidebar class="sidebar-container" v-if="!containerHiddenSideBar" />
 | 
			
		||||
    <div class="main-container">
 | 
			
		||||
      <div :class="{ 'fixed-header': fixedHeader }">
 | 
			
		||||
      <div :class="{ 'fixed-header': set.fixedHeader }">
 | 
			
		||||
        <!-- 顶部导航栏 -->
 | 
			
		||||
        <navbar v-show="!containerHiddenSideBar" />
 | 
			
		||||
        <!-- tabs标签页 -->
 | 
			
		||||
@ -27,147 +146,6 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { Navbar, Sidebar, AppMain, setting, tag } from "./components";
 | 
			
		||||
import {
 | 
			
		||||
  ref,
 | 
			
		||||
  unref,
 | 
			
		||||
  reactive,
 | 
			
		||||
  computed,
 | 
			
		||||
  toRefs,
 | 
			
		||||
  watchEffect,
 | 
			
		||||
  onMounted,
 | 
			
		||||
  onBeforeMount,
 | 
			
		||||
  useCssModule
 | 
			
		||||
} from "vue";
 | 
			
		||||
import { useAppStoreHook } from "/@/store/modules/app";
 | 
			
		||||
import { useSettingStoreHook } from "/@/store/modules/settings";
 | 
			
		||||
import { useEventListener } from "@vueuse/core";
 | 
			
		||||
import { toggleClass } from "/@/utils/operate";
 | 
			
		||||
import options from "/@/settings";
 | 
			
		||||
import fullScreen from "/@/assets/svg/full_screen.svg";
 | 
			
		||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
 | 
			
		||||
 | 
			
		||||
interface setInter {
 | 
			
		||||
  sidebar: any;
 | 
			
		||||
  device: string;
 | 
			
		||||
  fixedHeader: boolean;
 | 
			
		||||
  classes: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "layout",
 | 
			
		||||
  components: {
 | 
			
		||||
    Navbar,
 | 
			
		||||
    Sidebar,
 | 
			
		||||
    AppMain,
 | 
			
		||||
    setting,
 | 
			
		||||
    tag,
 | 
			
		||||
    fullScreen,
 | 
			
		||||
    exitScreen
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
    const pureApp = useAppStoreHook();
 | 
			
		||||
    const pureSetting = useSettingStoreHook();
 | 
			
		||||
    const { hiddenMainContainer } = useCssModule();
 | 
			
		||||
 | 
			
		||||
    const WIDTH = ref(992);
 | 
			
		||||
 | 
			
		||||
    let containerHiddenSideBar = ref(options.hiddenSideBar);
 | 
			
		||||
 | 
			
		||||
    const set: setInter = reactive({
 | 
			
		||||
      sidebar: computed(() => {
 | 
			
		||||
        return pureApp.sidebar;
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      device: computed(() => {
 | 
			
		||||
        return pureApp.device;
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      fixedHeader: computed(() => {
 | 
			
		||||
        return pureSetting.fixedHeader;
 | 
			
		||||
      }),
 | 
			
		||||
 | 
			
		||||
      classes: computed(() => {
 | 
			
		||||
        return {
 | 
			
		||||
          hideSidebar: !set.sidebar.opened,
 | 
			
		||||
          openSidebar: set.sidebar.opened,
 | 
			
		||||
          withoutAnimation: set.sidebar.withoutAnimation,
 | 
			
		||||
          mobile: set.device === "mobile"
 | 
			
		||||
        };
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const handleClickOutside = (params: boolean) => {
 | 
			
		||||
      pureApp.closeSideBar({ withoutAnimation: params });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    watchEffect(() => {
 | 
			
		||||
      if (set.device === "mobile" && !set.sidebar.opened) {
 | 
			
		||||
        handleClickOutside(false);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const $_isMobile = () => {
 | 
			
		||||
      const rect = document.body.getBoundingClientRect();
 | 
			
		||||
      return rect.width - 1 < WIDTH.value;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const $_resizeHandler = () => {
 | 
			
		||||
      if (!document.hidden) {
 | 
			
		||||
        const isMobile = $_isMobile();
 | 
			
		||||
        pureApp.toggleDevice(isMobile ? "mobile" : "desktop");
 | 
			
		||||
        if (isMobile) {
 | 
			
		||||
          handleClickOutside(true);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function onFullScreen() {
 | 
			
		||||
      if (unref(containerHiddenSideBar)) {
 | 
			
		||||
        containerHiddenSideBar.value = false;
 | 
			
		||||
        toggleClass(
 | 
			
		||||
          false,
 | 
			
		||||
          hiddenMainContainer,
 | 
			
		||||
          document.querySelector(".main-container")
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        containerHiddenSideBar.value = true;
 | 
			
		||||
        toggleClass(
 | 
			
		||||
          true,
 | 
			
		||||
          hiddenMainContainer,
 | 
			
		||||
          document.querySelector(".main-container")
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onMounted(() => {
 | 
			
		||||
      const isMobile = $_isMobile();
 | 
			
		||||
      if (isMobile) {
 | 
			
		||||
        pureApp.toggleDevice("mobile");
 | 
			
		||||
        handleClickOutside(true);
 | 
			
		||||
      }
 | 
			
		||||
      toggleClass(
 | 
			
		||||
        unref(containerHiddenSideBar),
 | 
			
		||||
        hiddenMainContainer,
 | 
			
		||||
        document.querySelector(".main-container")
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    onBeforeMount(() => {
 | 
			
		||||
      useEventListener("resize", $_resizeHandler);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      ...toRefs(set),
 | 
			
		||||
      handleClickOutside,
 | 
			
		||||
      containerHiddenSideBar,
 | 
			
		||||
      onFullScreen
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped module>
 | 
			
		||||
.hiddenMainContainer {
 | 
			
		||||
  margin-left: 0 !important;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user