| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| <template> | |
| <a-layout class="layout" :class="[device]"> | |
| <template v-if="isSideMenu()"> | |
| <a-drawer | |
| v-if="isMobile()" | |
| :wrapClassName="'drawer-sider ' + navTheme" | |
| :closable="false" | |
| :visible="collapsed" | |
| placement="left" | |
| @close="() => this.collapsed = false" | |
| > | |
| <side-menu | |
| :menus="menus" | |
| :theme="navTheme" | |
| :collapsed="false" | |
| :collapsible="true" | |
| mode="inline" | |
| @menuSelect="menuSelect"></side-menu> | |
| </a-drawer> | |
| <side-menu | |
| v-else | |
| mode="inline" | |
| :menus="menus" | |
| :theme="navTheme" | |
| :collapsed="collapsed" | |
| :collapsible="true"></side-menu> | |
| </template> | |
| <template v-else> | |
| <a-drawer | |
| v-if="isMobile()" | |
| :wrapClassName="'drawer-sider ' + navTheme" | |
| placement="left" | |
| @close="() => this.collapsed = false" | |
| :closable="false" | |
| :visible="collapsed" | |
| > | |
| <side-menu | |
| :menus="menus" | |
| :theme="navTheme" | |
| :collapsed="false" | |
| :collapsible="true" | |
| mode="inline" | |
| @menuSelect="menuSelect"></side-menu> | |
| </a-drawer> | |
| </template> | |
| <a-layout :class="[layoutMode, `content-width-${contentWidth}`]" :style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }"> | |
| <!-- layout header --> | |
| <global-header | |
| :mode="layoutMode" | |
| :menus="menus" | |
| :theme="navTheme" | |
| :collapsed="collapsed" | |
| :device="device" | |
| @toggle="toggle" | |
| /> | |
| <!-- layout content --> | |
| <a-layout-content class="layout-content" :class="{'is-header-fixed': fixedHeader}"> | |
| <slot></slot> | |
| </a-layout-content> | |
| <!-- layout footer --> | |
| <a-layout-footer style="padding: 0"> | |
| <global-footer /> | |
| </a-layout-footer> | |
| </a-layout> | |
| </a-layout> | |
| </template> | |
| <script> | |
| import SideMenu from '@/components/menu/SideMenu' | |
| import GlobalHeader from '@/components/page/GlobalHeader' | |
| import GlobalFooter from '@/components/page/GlobalFooter' | |
| import { triggerWindowResizeEvent } from '@/utils/util' | |
| import { mapState, mapActions } from 'vuex' | |
| import { mixin, mixinDevice } from '@/utils/mixin.js' | |
| export default { | |
| name: 'GlobalLayout', | |
| components: { | |
| SideMenu, | |
| GlobalHeader, | |
| GlobalFooter | |
| }, | |
| mixins: [mixin, mixinDevice], | |
| data () { | |
| return { | |
| collapsed: false, | |
| menus: [] | |
| } | |
| }, | |
| computed: { | |
| ...mapState({ | |
| mainMenu: state => state.permission.addRouters | |
| }), | |
| contentPaddingLeft () { | |
| if (!this.fixSidebar || this.isMobile()) { | |
| return '0' | |
| } | |
| if (this.sidebarOpened) { | |
| return '256px' | |
| } | |
| return '80px' | |
| } | |
| }, | |
| watch: { | |
| sidebarOpened (val) { | |
| this.collapsed = !val | |
| }, | |
| mainMenu (newMenu) { | |
| this.menus = newMenu.find((item) => item.path === '/').children | |
| } | |
| }, | |
| created () { | |
| this.menus = this.mainMenu.find((item) => item.path === '/').children | |
| this.collapsed = !this.sidebarOpened | |
| }, | |
| mounted () { | |
| const userAgent = navigator.userAgent | |
| if (userAgent.indexOf('Edge') > -1) { | |
| this.$nextTick(() => { | |
| this.collapsed = !this.collapsed | |
| setTimeout(() => { | |
| this.collapsed = !this.collapsed | |
| }, 16) | |
| }) | |
| } | |
| }, | |
| methods: { | |
| ...mapActions(['setSidebar']), | |
| toggle () { | |
| this.collapsed = !this.collapsed | |
| this.setSidebar(!this.collapsed) | |
| triggerWindowResizeEvent() | |
| }, | |
| paddingCalc () { | |
| let left = '' | |
| if (this.sidebarOpened) { | |
| left = this.isDesktop() ? '256px' : '80px' | |
| } else { | |
| left = this.isMobile() && '0' || (this.fixSidebar && '80px' || '0') | |
| } | |
| return left | |
| }, | |
| menuSelect () { | |
| if (!this.isDesktop()) { | |
| this.collapsed = false | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style lang="less"> | |
| .layout-content { | |
| &.is-header-fixed { | |
| margin: 78px 12px 0; | |
| } | |
| } | |
| // Todo try to get this rules scoped | |
| .ant-drawer.drawer-sider { | |
| .sider { | |
| box-shadow: none; | |
| } | |
| &.dark { | |
| .ant-drawer-content { | |
| background-color: rgb(0, 21, 41); | |
| } | |
| } | |
| &.light { | |
| box-shadow: none; | |
| .ant-drawer-content { | |
| background-color: #fff; | |
| } | |
| } | |
| .ant-drawer-body { | |
| padding: 0 | |
| } | |
| } | |
| </style> |