feat: 🎸 重构layout-classic布局

This commit is contained in:
chenkl 2020-12-17 17:01:13 +08:00
parent 7ede02141e
commit 29d9c98860
11 changed files with 270 additions and 145 deletions

View File

@ -1,5 +1,5 @@
{ {
"name": "vue-antdv-admin-webpack", "name": "vue-element-admin-webpack",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {

View File

@ -24,10 +24,18 @@
<div class="setting__title">顶部菜单主题</div> <div class="setting__title">顶部菜单主题</div>
<div class="setting__title">界面功能</div> <div class="setting__title">界面功能</div>
<div class="setting__item"> <!-- <div class="setting__item">
<span>固定顶部操作栏</span> <span>固定顶部操作栏</span>
<el-switch v-model="fixedNavbar" @change="setFixedNavbar" /> <el-switch v-model="fixedNavbar" @change="setFixedNavbar" />
</div> </div>
<div class="setting__item">
<span>固定标签页</span>
<el-switch v-model="fixedTags" @change="setFixedTags" />
</div> -->
<div class="setting__item">
<span>固定Header</span>
<el-switch v-model="fixedHeader" @change="setFixedHeader" />
</div>
<div class="setting__title">界面显示</div> <div class="setting__title">界面显示</div>
<div class="setting__item"> <div class="setting__item">
@ -73,9 +81,19 @@ export default defineComponent({
appStore.SetLayout(mode) appStore.SetLayout(mode)
} }
const fixedNavbar = ref<boolean>(appStore.fixedNavbar) // const fixedNavbar = ref<boolean>(appStore.fixedNavbar)
function setFixedNavbar(fixedNavbar: boolean) { // function setFixedNavbar(fixedNavbar: boolean) {
appStore.SetFixedNavbar(fixedNavbar) // appStore.SetFixedNavbar(fixedNavbar)
// }
// const fixedTags = ref<boolean>(appStore.fixedTags)
// function setFixedTags(fixedTags: boolean) {
// appStore.SetFixedTags(fixedTags)
// }
const fixedHeader = ref<boolean>(appStore.fixedHeader)
function setFixedHeader(fixedHeader: boolean) {
appStore.SetFixedHeader(fixedHeader)
} }
const navbar = ref<boolean>(appStore.showNavbar) const navbar = ref<boolean>(appStore.showNavbar)
@ -115,7 +133,9 @@ export default defineComponent({
return { return {
layout, setLayout, layout, setLayout,
fixedNavbar, setFixedNavbar, // fixedNavbar, setFixedNavbar,
// fixedTags, setFixedTags,
fixedHeader, setFixedHeader,
navbar, setNavbar, navbar, setNavbar,
hamburger, setHamburger, hamburger, setHamburger,
breadcrumb, setBreadcrumb, breadcrumb, setBreadcrumb,

View File

@ -1,7 +1,7 @@
<template> <template>
<template v-if="!item.meta?.hidden"> <div v-if="!item.meta?.hidden">
<template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.meta?.alwaysShow"> <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.meta?.alwaysShow">
<el-menu-item :index="resolvePath(onlyOneChild.path)"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown': !isNest}">
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" /> <item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
<template #title> <template #title>
<span class="anticon-item">{{ onlyOneChild.meta.title }}</span> <span class="anticon-item">{{ onlyOneChild.meta.title }}</span>
@ -9,7 +9,7 @@
</el-menu-item> </el-menu-item>
</template> </template>
<el-submenu v-else :index="resolvePath(item.path)"> <el-submenu v-else popper-class="nest-popper-menu" :index="resolvePath(item.path)">
<template #title> <template #title>
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template> </template>
@ -19,9 +19,10 @@
:is-nest="true" :is-nest="true"
:item="child" :item="child"
:base-path="resolvePath(child.path)" :base-path="resolvePath(child.path)"
class="nest-menu"
/> />
</el-submenu> </el-submenu>
</template> </div>
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@ -5,9 +5,6 @@
:default-active="activeMenu" :default-active="activeMenu"
:collapse="collapsed" :collapse="collapsed"
:unique-opened="false" :unique-opened="false"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:active-text-color="variables.menuActiveText"
mode="vertical" mode="vertical"
@select="selectMenu" @select="selectMenu"
> >
@ -73,7 +70,6 @@ export default defineComponent({
<style lang="less" scoped> <style lang="less" scoped>
.sidebar-container { .sidebar-container {
height: 100%; height: 100%;
background: @menuBg;
@{deep}(.svg-icon) { @{deep}(.svg-icon) {
margin-right: 16px; margin-right: 16px;
} }
@ -88,7 +84,7 @@ export default defineComponent({
overflow: scroll; overflow: scroll;
overflow-x: hidden; overflow-x: hidden;
.el-menu { .el-menu {
width: 100% !important; width: 100%;
border: none; border: none;
} }
} }

View File

@ -5,18 +5,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Classic from './modules/Classic.vue' // import Classic from './modules/Classic.vue'
import Top from './modules/Top.vue' // import Top from './modules/Top.vue'
import LeftTop from './modules/LeftTop.vue' // import LeftTop from './modules/LeftTop.vue'
import Test from './modules/Test.vue' import Test from './modules/Test.vue'
import { defineComponent, ref } from 'vue' import { defineComponent, ref } from 'vue'
import config from '_p/index/config' import config from '_p/index/config'
export default defineComponent({ export default defineComponent({
name: 'Layout', name: 'Layout',
components: { components: {
Classic, // Classic,
Top, // Top,
LeftTop, // LeftTop,
Test Test
}, },
setup() { setup() {

View File

@ -16,31 +16,40 @@
<el-scrollbar <el-scrollbar
class="main__wrap--content" class="main__wrap--content"
:class="{ :class="{
'main__wrap--navFixed': fixedNavbar 'main__wrap--fixed--all': fixedHeader && showNavbar && showTags,
'main__wrap--fixed--nav': fixedHeader && showNavbar && !showTags,
'main__wrap--fixed--tags': fixedHeader && !showNavbar && showTags
}" }"
> >
<div <div
v-if="showNavbar" class="header__wrap"
class="navbar__wrap"
:class="{ :class="{
'navbar__wrap--fixed': fixedNavbar, 'header__wrap--fixed': fixedHeader,
'navbar__wrap--collapsed': fixedNavbar && collapsed 'header__wrap--collapsed': fixedHeader && collapsed
}" }"
> >
<hamburger <div
v-if="showHamburger" v-if="showNavbar"
:collapsed="collapsed" class="navbar__wrap"
class="hover-container" >
@toggleClick="setCollapsed" <hamburger
/> v-if="showHamburger"
<breadcrumb v-if="showBreadcrumb" /> :collapsed="collapsed"
<div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right"> class="hover-container"
<screenfull v-if="showScreenfull" class="hover-container screenfull-container" /> @toggleClick="setCollapsed"
<user-info v-if="showUserInfo" class="hover-container user-container" /> />
<breadcrumb v-if="showBreadcrumb" />
<div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right">
<screenfull v-if="showScreenfull" class="hover-container screenfull-container" />
<user-info v-if="showUserInfo" class="hover-container user-container" />
</div>
</div>
<div
v-if="showTags"
class="tags__wrap"
>
<tags-view />
</div> </div>
</div>
<div v-if="showTags" class="tags__wrap">
<tags-view />
</div> </div>
<app-main /> <app-main />
</el-scrollbar> </el-scrollbar>
@ -101,7 +110,9 @@ export default defineComponent({
const showScreenfull = computed(() => appStore.showScreenfull) const showScreenfull = computed(() => appStore.showScreenfull)
const showUserInfo = computed(() => appStore.showUserInfo) const showUserInfo = computed(() => appStore.showUserInfo)
const showNavbar = computed(() => appStore.showNavbar) const showNavbar = computed(() => appStore.showNavbar)
const fixedNavbar = computed(() => appStore.fixedNavbar) // const fixedNavbar = computed(() => appStore.fixedNavbar)
// const fixedTags = computed(() => appStore.fixedTags)
const fixedHeader = computed(() => appStore.fixedHeader)
const classObj = computed(() => { const classObj = computed(() => {
const obj = {} const obj = {}
@ -128,7 +139,9 @@ export default defineComponent({
showScreenfull, showScreenfull,
showUserInfo, showUserInfo,
showNavbar, showNavbar,
fixedNavbar, fixedHeader,
// fixedNavbar,
// fixedTags,
setCollapsed, setCollapsed,
toggleClick toggleClick
} }
@ -137,7 +150,7 @@ export default defineComponent({
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.app__wrap--Classic { .app__wrap {
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -163,58 +176,47 @@ export default defineComponent({
left: @menuWidth; left: @menuWidth;
transition: all 0.2s; transition: all 0.2s;
z-index: 1; z-index: 1;
.navbar__wrap { .header__wrap {
display: flex;
align-items: center;
height: @navbarHeight;
padding: 0 20px 0 15px;
position: relative;
background: @contentBg;
transition: all 0.2s; transition: all 0.2s;
&:after { .navbar__wrap {
content: "";
width: 100%;
height: 1px;
border-top: 1px solid #d8dce5;
position: absolute;
bottom: 0;
left: 0;
}
@{deep}(.hover-container) {
transition: background 0.2s;
height: 100%;
line-height: @navbarHeight + 5px;
padding: 0 5px;
&:hover {
background: #f6f6f6;
}
}
.navbar__wrap--right {
display: flex; display: flex;
align-items: center; align-items: center;
height: @navbarHeight; height: @navbarHeight;
position: absolute; padding: 0 20px 0 15px;
top: 0; position: relative;
right: 20px; background: @contentBg;
@{deep}(.screenfull-container), &:after {
@{deep}(.user-container) { content: "";
line-height: @navbarHeight !important; width: 100%;
height: 1px;
border-top: 1px solid #d8dce5;
position: absolute;
bottom: 0;
left: 0;
}
@{deep}(.hover-container) {
transition: background 0.2s;
height: 100%;
line-height: @navbarHeight + 5px;
padding: 0 5px;
&:hover {
background: #f6f6f6;
}
}
.navbar__wrap--right {
display: flex;
align-items: center;
height: @navbarHeight;
position: absolute;
top: 0;
right: 20px;
@{deep}(.screenfull-container),
@{deep}(.user-container) {
line-height: @navbarHeight !important;
}
} }
} }
} }
//
.navbar__wrap--fixed {
position: fixed;
width: calc(~"100% - @{menuWidth} - 35px");
top: 0;
left: @menuWidth;
z-index: 200;
}
.navbar__wrap--collapsed {
width: calc(~"100% - @{menuMinWidth} - 35px");
left: @menuMinWidth;
}
//
// content // content
.main__wrap--content { .main__wrap--content {
@ -223,10 +225,6 @@ export default defineComponent({
overflow-x: hidden; overflow-x: hidden;
} }
} }
.main__wrap--navFixed {
padding-top: @navbarHeight;
height: calc(~"100% - @{navbarHeight}");
}
// content // content
} }
.main__wrap--collapsed { .main__wrap--collapsed {
@ -235,6 +233,33 @@ export default defineComponent({
} }
} }
//
.app__wrap--Classic {
.main__wrap--fixed--all {
margin-top: @navbarHeight + @tagsViewHeight !important;
height: calc(~"100% - @{navbarHeight} - @{tagsViewHeight}") !important;
}
.main__wrap--fixed--nav {
margin-top: @navbarHeight !important;
height: calc(~"100% - @{navbarHeight}") !important;
}
.main__wrap--fixed--tags {
margin-top: @tagsViewHeight !important;
height: calc(~"100% - @{tagsViewHeight}") !important;
}
.header__wrap--fixed {
position: fixed !important;
width: calc(~"100% - @{menuWidth}") !important;
top: 0 !important;
left: @menuWidth !important;
z-index: 200;
}
.header__wrap--collapsed {
width: calc(~"100% - @{menuMinWidth}") !important;
left: @menuMinWidth !important;
}
}
// //
.setting__wrap { .setting__wrap {
position: fixed; position: fixed;

View File

@ -6,8 +6,9 @@ export interface AppState {
showTags: boolean showTags: boolean
showLogo: boolean showLogo: boolean
showNavbar: boolean showNavbar: boolean
fixedTags: boolean fixedHeader: boolean
fixedNavbar: boolean // fixedTags: boolean
// fixedNavbar: boolean
layout: string layout: string
showBreadcrumb: boolean showBreadcrumb: boolean
showHamburger: boolean showHamburger: boolean
@ -21,8 +22,9 @@ class App extends VuexModule implements AppState {
public showLogo = true // 是否显示logo public showLogo = true // 是否显示logo
public showTags = true // 是否显示标签栏 public showTags = true // 是否显示标签栏
public showNavbar = true // 是否显示navbar public showNavbar = true // 是否显示navbar
public fixedTags = true // 是否固定标签栏 // public fixedTags = true // 是否固定标签栏
public fixedNavbar = true // 是否固定navbar // public fixedNavbar = true // 是否固定navbar
public fixedHeader = true // 是否固定header
public layout = 'Classic' // layout布局 public layout = 'Classic' // layout布局
public showBreadcrumb = true // 是否显示面包屑 public showBreadcrumb = true // 是否显示面包屑
public showHamburger = true // 是否显示侧边栏缩收按钮 public showHamburger = true // 是否显示侧边栏缩收按钮
@ -45,13 +47,17 @@ class App extends VuexModule implements AppState {
private SET_NAVBAR(showNavbar: boolean): void { private SET_NAVBAR(showNavbar: boolean): void {
this.showNavbar = showNavbar this.showNavbar = showNavbar
} }
// @Mutation
// private SET_FIXEDTAGS(fixedTags: boolean): void {
// this.fixedTags = fixedTags
// }
// @Mutation
// private SET_FIXEDNAVBAR(fixedNavbar: boolean): void {
// this.fixedNavbar = fixedNavbar
// }
@Mutation @Mutation
private SET_FIXEDTAGS(fixedTags: boolean): void { private SET_FIXEDHEADER(fixedHeader: boolean): void {
this.fixedTags = fixedTags this.fixedHeader = fixedHeader
}
@Mutation
private SET_FIXEDNAVBAR(fixedNavbar: boolean): void {
this.fixedNavbar = fixedNavbar
} }
@Mutation @Mutation
private SET_LAYOUT(layout: 'Classic' | 'LeftTop' | 'Top' | 'Test'): void { private SET_LAYOUT(layout: 'Classic' | 'LeftTop' | 'Top' | 'Test'): void {
@ -91,13 +97,17 @@ class App extends VuexModule implements AppState {
this.SET_NAVBAR(showNavbar) this.SET_NAVBAR(showNavbar)
} }
@Action @Action
public SetFixedTags(fixedTags: boolean): void { public SetFixedHeader(fixedHeader: boolean): void {
this.SET_FIXEDTAGS(fixedTags) this.SET_FIXEDHEADER(fixedHeader)
}
@Action
public SetFixedNavbar(fixedNavbar: boolean): void {
this.SET_FIXEDNAVBAR(fixedNavbar)
} }
// @Action
// public SetFixedTags(fixedTags: boolean): void {
// this.SET_FIXEDTAGS(fixedTags)
// }
// @Action
// public SetFixedNavbar(fixedNavbar: boolean): void {
// this.SET_FIXEDNAVBAR(fixedNavbar)
// }
@Action @Action
public SetLayout(layout: 'Classic' | 'LeftTop' | 'Top' | 'Test'): void { public SetLayout(layout: 'Classic' | 'LeftTop' | 'Top' | 'Test'): void {
this.SET_LAYOUT(layout) this.SET_LAYOUT(layout)

View File

@ -1,7 +1,7 @@
@import '~element-plus/lib/theme-chalk/index.css'; @import '~element-plus/lib/theme-chalk/index.css';
// @import './sidebar.less'; // @import './sidebar.less';
@import './transition.less'; @import './transition.less';
@import './silder.less'; @import './sider.less';
@import './glob.less'; @import './glob.less';
// @import './button.less'; // @import './button.less';
// @import './antdv.less'; // @import './antdv.less';

108
src/styles/sider.less Normal file
View File

@ -0,0 +1,108 @@
.app__wrap--Classic {
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out !important;
}
.sidebar-container {
background: @menuBg;
.el-menu {
background-color: @menuBg !important;
.el-menu-item,
.el-submenu__title {
color: @menuText !important;
background-color: @menuBg !important;
i {
color: @menuText !important;
}
}
.is-active {
color: @menuActiveText !important;
background-color: @subMenuHover !important;
&>.el-submenu__title {
color: @menuActiveText !important;
}
}
.is-opened {
.el-menu-item {
background-color: @subMenuBg !important;
}
}
.nest-menu {
background-color: @subMenuBg !important;
.el-submenu>.el-submenu__title {
background-color: @subMenuBg !important;
}
.is-active {
background-color: @subMenuHover !important;
}
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: @menuBg !important;
color: @subMenuActiveText !important;
}
}
.el-menu-item:hover {
color: @subMenuActiveText !important;
background-color: @subMenuHover !important;
}
}
.el-menu--collapse {
&>div>.el-submenu {
i {
display: none;
}
}
.is-active {
&>.el-submenu__title {
background-color: @subMenuHover !important;
}
}
}
}
}
.nest-popper-menu {
background: @menuBg;
.el-menu {
background-color: @menuBg !important;
.el-menu-item,
.el-submenu__title {
color: @menuText !important;
background-color: @menuBg !important;
i {
color: @menuText !important;
}
}
.is-active {
color: @menuActiveText !important;
background-color: @subMenuHover !important;
&>.el-submenu__title {
color: @menuActiveText !important;
}
}
.nest-menu {
.is-active {
background-color: @subMenuHover !important;
}
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: @menuBg !important;
color: @subMenuActiveText !important;
}
}
.el-menu-item:hover {
color: @subMenuActiveText !important;
background-color: @subMenuHover !important;
}
}
}

View File

@ -1,27 +0,0 @@
.ant-layout-sider-collapsed,
.ant-menu-horizontal {
.dark-active-item {
background: @menuDarkActiveBg;
.ant-menu-submenu-title {
color: @menuDarkActiveText;
}
}
.light-active-item {
background: @menuLightActiveBg;
.ant-menu-submenu-title {
color: @menuLightActiveText;
}
}
}
.dark-popup-active-item {
.ant-menu-submenu-title {
color: @menuDarkActiveText;
}
}
.light-popup-active-item {
.ant-menu-submenu-title {
color: @menuLightActiveText;
}
}

View File

@ -1,25 +1,17 @@
// Silder // Silder
@menuText: #bfcbd9; @menuText: #bfcbd9;
@menuActiveText: #409EFF; @menuActiveText: #fff;
@menuActiveBg: #2d8cf0; @menuActiveBg: #2d8cf0;
@menuBg: #001529; @menuBg: #001529;
@subMenuBg: #1f2d3d; @subMenuBg: #1f2d3d;
@subMenuHover: #1f2d3d; @subMenuHover: #2d8cf0;
@subMenuActiveText: #fff; @subMenuActiveText: #fff;
@menuWidth: 200px; @menuWidth: 200px;
@menuMinWidth: 64px; @menuMinWidth: 64px;
@menuLightActiveText: #1890ff;
@menuLightActiveBg: #e6f7ff;
@menuDarkActiveText: #fff;
@menuDarkActiveBg: #1890ff;
@menuLightBg: #fff;
// topSilder // topSilder
@topSilderHeight: 50px; @topSilderHeight: 50px;