123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- <template>
- <div :class="classObj" class="wh-full">
- <!-- 遮罩层 -->
- <div
- v-if="classObj.mobile && classObj.openSidebar"
- class="wh-full fixed-lt z-999 bg-black bg-opacity-30"
- @click="handleOutsideClick"
- ></div>
- <!-- 公用侧边栏 -->
- <Sidebar class="sidebar-container" />
- <!-- 混合布局 -->
- <div v-if="layout === 'mix'" class="mix-container">
- <div class="mix-container__left">
- <el-scrollbar style="height: 100%; background-color: #000">
- <SidebarMenu
- :base-path="activeTopMenuPath"
- :menu-list="mixLeftMenus"
- />
- <div style="width: 100%; height: 50px; background-color: #000"></div>
- <!-- <div class="sidebar-toggle" style="background-color: #000">
- <hamburger
- :is-active="appStore.sidebar.opened"
- @toggle-click="toggleSidebar"
- />
- </div> -->
- </el-scrollbar>
- </div>
- <div :class="{ hasTagsView: showTagsView }" class="main-container">
- <div :class="{ 'fixed-header': fixedHeader }">
- <TagsView v-if="showTagsView" />
- </div>
- <AppMain />
- <Settings v-if="defaultSettings.showSettings" />
- </div>
- </div>
- <!-- 左侧和顶部布局 -->
- <div v-else :class="{ hasTagsView: showTagsView }" class="main-container">
- <div :class="{ 'fixed-header': fixedHeader }">
- <NavBar v-if="layout === 'left'" />
- <TagsView v-if="showTagsView" />
- </div>
- <AppMain />
- <Settings v-if="defaultSettings.showSettings" />
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { useAppStore, useSettingsStore, usePermissionStore } from "@/store";
- import defaultSettings from "@/settings";
- import { DeviceEnum } from "@/enums/DeviceEnum";
- const appStore = useAppStore();
- const settingsStore = useSettingsStore();
- const permissionStore = usePermissionStore();
- const fixedHeader = computed(() => settingsStore.fixedHeader); // 是否固定header
- const showTagsView = computed(() => settingsStore.tagsView); // 是否显示tagsView
- const layout = computed(() => settingsStore.layout); // 布局模式 left top mix
- const activeTopMenuPath = computed(() => appStore.activeTopMenuPath); // 顶部菜单激活path
- const mixLeftMenus = computed(() => permissionStore.mixLeftMenus); // 混合布局左侧菜单
- watch(
- () => activeTopMenuPath.value,
- (newVal) => {
- permissionStore.setMixLeftMenus(newVal);
- },
- {
- deep: true,
- immediate: true,
- }
- );
- const classObj = computed(() => ({
- hideSidebar: !appStore.sidebar.opened,
- openSidebar: appStore.sidebar.opened,
- mobile: appStore.device === DeviceEnum.MOBILE,
- "layout-left": layout.value === "left",
- "layout-top": layout.value === "top",
- "layout-mix": layout.value === "mix",
- }));
- const width = useWindowSize().width;
- const WIDTH = 992; // 响应式布局容器固定宽度 大屏(>=1200px) 中屏(>=992px) 小屏(>=768px)
- watchEffect(() => {
- if (width.value < WIDTH) {
- appStore.toggleDevice(DeviceEnum.MOBILE);
- appStore.closeSideBar();
- } else {
- appStore.toggleDevice(DeviceEnum.DESKTOP);
- if (width.value >= 1200) {
- appStore.openSideBar();
- } else {
- appStore.closeSideBar();
- }
- }
- });
- function handleOutsideClick() {
- appStore.closeSideBar();
- }
- function toggleSidebar() {
- appStore.toggleSidebar();
- }
- </script>
- <style lang="scss" scoped>
- .fixed-header {
- position: fixed;
- top: 0;
- right: 0;
- z-index: 9;
- width: calc(100% - $sidebar-width);
- transition: width 0.28s;
- }
- .sidebar-container {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- z-index: 999;
- width: $sidebar-width;
- height: 100%;
- overflow: hidden;
- background-color: $menu-background;
- transition: width 0.28s;
- :deep(.el-menu) {
- border: none;
- }
- }
- .main-container {
- position: relative;
- min-height: 100%;
- margin-left: $sidebar-width;
- transition: margin-left 0.28s;
- }
- .layout-top {
- .fixed-header {
- top: $navbar-height;
- width: 100%;
- }
- .sidebar-container {
- z-index: 999;
- display: flex;
- width: 100% !important;
- height: $navbar-height;
- :deep(.el-scrollbar) {
- flex: 1;
- height: $navbar-height;
- }
- :deep(.el-menu-item),
- :deep(.el-sub-menu__title),
- :deep(.el-menu--horizontal) {
- height: $navbar-height;
- line-height: $navbar-height;
- }
- :deep(.el-menu--collapse) {
- width: 100%;
- }
- }
- .main-container {
- min-height: calc(100vh - $navbar-height);
- padding-top: $navbar-height;
- margin-left: 0;
- }
- }
- .layout-mix {
- .sidebar-container {
- width: 100% !important;
- height: $navbar-height;
- :deep(.el-scrollbar) {
- flex: 1;
- height: $navbar-height;
- }
- :deep(.el-menu-item),
- :deep(.el-sub-menu__title),
- :deep(.el-menu--horizontal) {
- height: $navbar-height;
- line-height: $navbar-height;
- }
- :deep(.el-menu--horizontal.el-menu) {
- border: none;
- }
- }
- .mix-container {
- display: flex;
- height: 100%;
- padding-top: $navbar-height;
- .mix-container__left {
- position: relative;
- width: $sidebar-width;
- height: 100%;
- :deep(.el-menu) {
- height: 100%;
- border: none;
- }
- .sidebar-toggle {
- position: absolute;
- bottom: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: 50px;
- line-height: 50px;
- box-shadow: 0 0 6px -2px var(--el-color-primary);
- div:hover {
- background-color: var(--menu-background);
- }
- :deep(svg) {
- color: var(--el-color-primary) !important;
- }
- }
- }
- .main-container {
- flex: 1;
- min-width: 0;
- margin-left: 0;
- .fixed-header {
- top: $navbar-height;
- }
- }
- }
- }
- .hideSidebar {
- .fixed-header {
- left: $sidebar-width-collapsed;
- width: calc(100% - $sidebar-width-collapsed);
- }
- .main-container {
- margin-left: $sidebar-width-collapsed;
- }
- &.layout-top {
- .fixed-header {
- left: 0;
- width: 100%;
- }
- .main-container {
- margin-left: 0;
- }
- }
- &.layout-mix {
- .fixed-header {
- left: $sidebar-width-collapsed;
- width: calc(100% - $sidebar-width-collapsed);
- }
- .sidebar-container {
- width: 100% !important;
- }
- .mix-container {
- .mix-container__left {
- width: $sidebar-width-collapsed;
- }
- }
- }
- }
- .layout-left.hideSidebar {
- .sidebar-container {
- width: $sidebar-width-collapsed !important;
- }
- .main-container {
- margin-left: $sidebar-width-collapsed;
- }
- &.mobile {
- .sidebar-container {
- pointer-events: none;
- transition-duration: 0.3s;
- transform: translate3d(-210px, 0, 0);
- }
- .main-container {
- margin-left: 0;
- }
- }
- }
- .mobile {
- .fixed-header {
- left: 0;
- width: 100%;
- }
- .main-container {
- margin-left: 0;
- }
- &.layout-top {
- .sidebar-container {
- z-index: 999;
- display: flex;
- width: 100% !important;
- height: $navbar-height;
- :deep(.el-scrollbar) {
- flex: 1;
- min-width: 0;
- height: $navbar-height;
- }
- }
- .main-container {
- padding-top: $navbar-height;
- margin-left: 0;
- overflow: hidden;
- }
- // 顶部模式全局变量修改
- //--el-menu-item-height: $navbar-height;
- }
- }
- :deep(.el-input-number) {
- }
- // :deep(.el-collapse-item__content) {
- // padding: 18px 0 15px 10px;
- // margin-bottom: 10px;
- // background-color: var(--el-bg-color-overlay);
- // border: 1px solid var(--el-border-color-light);
- // border-radius: 4px;
- // box-shadow: var(--el-box-shadow-light);
- // }
- </style>
|