123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- <script setup lang="ts">
- import {
- h,
- ref,
- unref,
- reactive,
- computed,
- 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";
- 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 from "./components/navbar.vue";
- import tag from "./components/tag/index.vue";
- import appMain from "./components/appMain.vue";
- import setting from "./components/setting/index.vue";
- import Vertical from "./components/sidebar/vertical.vue";
- import Horizontal from "./components/sidebar/horizontal.vue";
- const pureSetting = useSettingStoreHook();
- const instance =
- getCurrentInstance().appContext.app.config.globalProperties.$storage;
- 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;
- }),
- device: computed(() => {
- return useAppStoreHook().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) => {
- useAppStoreHook().closeSideBar({ withoutAnimation: params });
- };
- function setTheme(layoutModel: string) {
- let { layout } = storageLocal.getItem("responsive-layout");
- let theme = layout.match(/-(.*)/)[1];
- window.document.body.setAttribute("data-layout", layoutModel);
- window.document.body.setAttribute("data-theme", theme);
- instance.layout = { layout: `${layoutModel}-${theme}` };
- }
- // 监听容器
- emitter.on("resize", ({ detail }) => {
- let { width } = detail;
- width <= 670 ? setTheme("vertical") : setTheme(useAppStoreHook().layout);
- });
- watchEffect(() => {
- if (set.device === "mobile" && !set.sidebar.opened) {
- handleClickOutside(false);
- }
- });
- const $_isMobile = () => {
- const rect = document.body.getBoundingClientRect();
- return rect.width - 1 < 992;
- };
- const $_resizeHandler = () => {
- if (!document.hidden) {
- const isMobile = $_isMobile();
- useAppStoreHook().toggleDevice(isMobile ? "mobile" : "desktop");
- if (isMobile) {
- handleClickOutside(true);
- }
- }
- };
- function onFullScreen() {
- unref(hiddenSideBar)
- ? (hiddenSideBar.value = false)
- : (hiddenSideBar.value = true);
- }
- onMounted(() => {
- const isMobile = $_isMobile();
- if (isMobile) {
- useAppStoreHook().toggleDevice("mobile");
- handleClickOutside(true);
- }
- });
- 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>
- <div :class="['app-wrapper', set.classes]" v-resize>
- <div
- v-show="
- set.device === 'mobile' &&
- set.sidebar.opened &&
- layout.includes('vertical')
- "
- class="drawer-bg"
- @click="handleClickOutside(false)"
- />
- <Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
- <div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
- <div v-if="set.fixedHeader">
- <layout-header />
- <!-- 主体内容 -->
- <app-main :fixed-header="set.fixedHeader" />
- </div>
- <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 />
- </div>
- </template>
- <style lang="scss" scoped>
- @mixin clearfix {
- &::after {
- content: "";
- display: table;
- clear: both;
- }
- }
- .app-wrapper {
- @include clearfix;
- position: relative;
- height: 100%;
- width: 100%;
- &.mobile.openSidebar {
- position: fixed;
- top: 0;
- }
- }
- .main-hidden {
- margin-left: 0 !important;
- }
- .drawer-bg {
- background: #000;
- opacity: 0.3;
- width: 100%;
- top: 0;
- height: 100%;
- position: absolute;
- z-index: 999;
- }
- .re-screen {
- margin-top: 12px;
- }
- </style>
|