feat: 混合布局搭建

This commit is contained in:
wang_fan_w 2024-05-13 23:50:09 +08:00
parent 84835f4e26
commit 053b91edb6
2 changed files with 161 additions and 9 deletions

View File

@ -222,7 +222,7 @@ const handleCancel = () => {
top: 15px; top: 15px;
width: 20px; width: 20px;
height: calc(100% - 15px); height: calc(100% - 15px);
background: #fff; background: #232324;
} }
} }

View File

@ -1,30 +1,182 @@
<template> <template>
<a-layout class="layout"> <a-layout class="layout">
<Aside /> <div :class="asideDark ? 'aside dark' : 'aside'">
<Logo />
<a-layout-sider :collapsed="collapsed" breakpoint="xl" class="layout_side" :width="220">
<a-scrollbar style="height: 100%; overflow: auto" outer-class="scrollbar"><Menu /></a-scrollbar>
</a-layout-sider>
</div>
<a-layout> <a-layout>
<Header /> <div class="layout-head">
<Main /> <div class="layout-head-top">
<Footer v-if="isFooter" /> <a-layout-header class="header">
<div class="menu_fold">
<a-button size="mini" type="text" class="menu_fold_icon" @click="onCollapsed">
<template #icon>
<icon-menu-fold :size="18" v-if="!collapsed" />
<icon-menu-unfold :size="18" v-if="collapsed" />
</template>
</a-button>
</div>
<a-menu mode="horizontal" :selected-keys="[currentRoute.name]" @menu-item-click="onMenuItem">
<template v-for="item in routeTree" :key="item.name">
<a-sub-menu v-if="item.children && item.children.length > 0" :key="item.name">
<template #icon v-if="item.meta.svgIcon || item.meta.icon">
<MenuItemIcon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template>
<template #title>{{ $t(`language.${item.meta.title}`) }}</template>
<MenuItem :route-tree="item.children" />
</a-sub-menu>
<a-menu-item v-else :key="item?.name">
<template #icon v-if="item.meta.svgIcon || item.meta.icon">
<MenuItemIcon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template>
<span>{{ $t(`language.${item.meta.title}`) }}</span>
</a-menu-item>
</template>
</a-menu>
<HeaderRight />
</a-layout-header>
<Main />
<Footer v-if="isFooter" />
</div>
</div>
</a-layout> </a-layout>
</a-layout> </a-layout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Aside from "@/layout/components/Aside/index.vue"; import Logo from "@/layout/components/Logo/index.vue";
import Header from "@/layout/components/Header/index.vue";
import Main from "@/layout/components/Main/index.vue"; import Main from "@/layout/components/Main/index.vue";
import Footer from "@/layout/components/Footer/index.vue"; import Footer from "@/layout/components/Footer/index.vue";
import Menu from "@/layout/components/Menu/index.vue";
import HeaderRight from "@/layout/components/Header/components/header-right/index.vue";
import MenuItem from "@/layout/components/Menu/menu-item.vue";
import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
import { useRouter } from "vue-router";
import { useRoutesListStore } from "@/store/modules/route-list";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/modules/theme-config"; import { useThemeConfig } from "@/store/modules/theme-config";
defineOptions({ name: "LayoutMixing" }); defineOptions({ name: "LayoutMixing" });
const themeStore = useThemeConfig(); const themeStore = useThemeConfig();
let { isFooter } = storeToRefs(themeStore); const { isFooter, collapsed, asideDark } = storeToRefs(themeStore);
const router = useRouter();
const routerStore = useRoutesListStore();
const { routeTree, currentRoute } = storeToRefs(routerStore);
//
const onCollapsed = () => {
themeStore.setCollapsed(!collapsed.value);
};
/**
* @description 菜单点击事件
* @param {String} key
*/
const onMenuItem = (key: string) => {
const { findLinearArray } = useRoutingMethod();
const find = findLinearArray(key);
// 404
if (find) {
router.push(find.path);
} else {
router.push("/404");
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.layout { .layout {
height: 100vh; height: 100vh;
} }
.dark {
background: #232324;
}
.layout_side {
height: calc(100% - 60px);
.scrollbar {
height: 100%;
}
}
//
:deep(.arco-scrollbar-thumb-direction-vertical .arco-scrollbar-thumb-bar) {
width: 4px;
margin-left: 8px;
}
// 线
:deep(.arco-layout-sider-light) {
box-shadow: unset;
border-right: $border-1 solid $color-border-2;
}
// icon
:deep(.arco-menu-vertical.arco-menu-collapsed) {
// iconpadding
.arco-menu-has-icon {
padding: 0;
justify-content: center;
}
// iconmargin-righticonpaddingicon
.arco-menu-icon {
margin-right: 0;
padding: 10px 0;
}
// title
.arco-menu-title {
display: none;
}
}
// sider
.arco-layout-sider {
background: unset;
}
.layout-head {
height: 100%;
display: flex;
align-items: stretch; //
overflow: hidden;
border: 1px solid red;
.header-logo {
width: 150px;
}
&-top {
flex: 1; //
display: flex;
flex-direction: column; // flex
overflow: hidden;
}
}
.header {
padding: 0 $padding;
height: 60px;
box-sizing: border-box;
border-bottom: $border-1 solid $color-border-2;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
}
:deep(.arco-menu-pop) {
white-space: nowrap;
}
//
:deep(.arco-menu-horizontal) {
flex: 1;
overflow: hidden;
.arco-menu-inner {
padding-left: 0; // padding
.arco-menu-overflow-wrap {
white-space: nowrap; //
}
}
}
</style> </style>