安虹睿
1 year ago
5 changed files with 275 additions and 219 deletions
@ -0,0 +1,222 @@ |
|||
<template> |
|||
<!-- 瀑布流版本布局 + 高度随宽度调整变化 --> |
|||
<el-card class="homeMenuPage" v-resize="setMaxHeight" v-loading="loading"> |
|||
<div class="firstMenuContain homeMenuPage-List"> |
|||
<div |
|||
class="firstMenuItem menuItem" |
|||
v-for="(item,index) in navList" |
|||
:key="index" |
|||
> |
|||
<div class="firstTitle" v-if="item.meta"> |
|||
<div class="icon"><svg-icon :icon-class="item.meta.icon" style="fill:currentColor; color:#fff;"/></div> |
|||
<div>{{item.meta.title}}</div> |
|||
</div> |
|||
<ul class="menuInfo" v-if="item.children && item.children.length > 0"> |
|||
<li |
|||
v-for="(item2,index2) in item.children" |
|||
:key="index2" |
|||
> |
|||
<div class="title"> |
|||
{{item2.meta.title}} |
|||
<i class="el-icon-arrow-right"></i> |
|||
</div> |
|||
<!-- 有下级菜单 --> |
|||
<div class="lastList" v-if="item2.children && item2.children.length > 0"> |
|||
<div |
|||
v-for="(item3,index3) in item2.children" |
|||
:key="index3" |
|||
class="item" |
|||
> |
|||
<span @click="goPage(item3)">{{item3.meta.title}}</span> |
|||
</div> |
|||
</div> |
|||
<!-- 如果二级为最后一级,统一格式,补充到children中 --> |
|||
<div class="lastList" v-else> |
|||
<div class="item"> |
|||
<span @click="goPage(item2)">{{item2.meta.title}}</span> |
|||
</div> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<span class="firstMenuItem break"></span> |
|||
<span class="firstMenuItem break"></span> |
|||
<span class="firstMenuItem break"></span> |
|||
</div> |
|||
</el-card> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapGetters } from 'vuex' |
|||
export default { |
|||
directives: { |
|||
// 页面宽度变化,重新计算总高度 |
|||
resize: { // 指令的名称 |
|||
bind(el, binding) { // el为绑定的元素,binding为绑定给指令的对象 |
|||
let width = '', height = ''; |
|||
function isReize() { |
|||
const style = document.defaultView.getComputedStyle(el); |
|||
if (width !== style.width || height !== style.height) { |
|||
binding.value(); // 关键 |
|||
} |
|||
width = style.width; |
|||
height = style.height; |
|||
} |
|||
el.__vueSetInterval__ = setInterval(isReize, 300); |
|||
}, |
|||
unbind(el) { |
|||
clearInterval(el.__vueSetInterval__); |
|||
} |
|||
} |
|||
}, |
|||
name: 'Dashboard', |
|||
data() { |
|||
return { |
|||
loading:true, |
|||
navList:[], |
|||
} |
|||
}, |
|||
watch: { |
|||
permission_routes(val, oldVal) { |
|||
this.initData(val) |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'permission_routes' |
|||
]) |
|||
}, |
|||
mounted(){ |
|||
console.log(90,this.permission_routes) |
|||
this.initData(this.permission_routes) |
|||
}, |
|||
methods:{ |
|||
initData(data){ |
|||
data.forEach(item => { |
|||
if(!item.hidden && item.path !== '/') { |
|||
this.navList.push(item) |
|||
} |
|||
}) |
|||
this.$nextTick(()=>{ |
|||
this.setMaxHeight() |
|||
}) |
|||
}, |
|||
goPage(item){ |
|||
this.$router.push({name: item.name}) |
|||
}, |
|||
setMaxHeight(){ |
|||
// todo:用this.$route.path != /dashboard 判断 |
|||
console.log("setMaxHeight",this.$route.path) |
|||
if(document.getElementsByClassName("homeMenuPage-List").length <= 0){ |
|||
return |
|||
} |
|||
let _items = document.getElementsByClassName("menuItem") |
|||
let _left = []; |
|||
let _right = []; |
|||
let _left_num = 0; |
|||
let _right_num = 0; |
|||
_items.forEach((item,key)=>{ |
|||
// 左侧 |
|||
if(key % 2 == 0){ |
|||
_left.push(item.offsetHeight) |
|||
_left_num += Number(item.offsetHeight) |
|||
} |
|||
// 右侧 |
|||
else{ |
|||
_right.push(item.offsetHeight) |
|||
_right_num += Number(item.offsetHeight) |
|||
} |
|||
}) |
|||
let _max = _left_num > _right_num ? _left_num : _right_num |
|||
_max += 20 * _items.length |
|||
document.getElementsByClassName("homeMenuPage-List")[0].style.height = _max + 'px' |
|||
this.loading = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
$iconSize:26px; |
|||
.homeMenuPage{ |
|||
height: 100%; |
|||
overflow: auto; |
|||
// padding: 20px 0; |
|||
} |
|||
.firstMenuContain { |
|||
display: flex; |
|||
flex-flow: column wrap; |
|||
align-content: space-between; |
|||
/* 容器必须有固定高度 |
|||
* 且高度大于最高的列高 */ |
|||
// height: 2500px; |
|||
.firstMenuItem { |
|||
width: calc(50% - 20px); |
|||
margin-bottom: 20px; |
|||
|
|||
.firstTitle{ |
|||
display: flex; |
|||
font-weight: bold; |
|||
font-size: 18px; |
|||
.icon{ |
|||
background: #409eff; |
|||
color: #fff; |
|||
border-radius: 4px; |
|||
width: $iconSize; |
|||
height: $iconSize; |
|||
line-height: $iconSize; |
|||
overflow: hidden; |
|||
text-align: center; |
|||
margin-right: 10px; |
|||
} |
|||
} |
|||
|
|||
.menuInfo{ |
|||
background: #f9fafb; |
|||
margin: 20px 0; |
|||
padding: 5px 0; |
|||
li{ |
|||
list-style: none; |
|||
display: flex; |
|||
padding-top: 10px; |
|||
.title{ |
|||
width: 240px; |
|||
text-align: right; |
|||
font-weight: bold; |
|||
flex-shrink: 0; |
|||
.el-icon-arrow-right{ |
|||
font-weight: bold; |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
.lastList{ |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
margin-left: 15px; |
|||
.item{ |
|||
margin-right: 25px; |
|||
margin-bottom: 10px; |
|||
cursor: pointer; |
|||
|
|||
&:hover{ |
|||
color: #409eff; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 将内容块重排为4列 */ |
|||
&:nth-of-type(2n+1) { order: 1; } |
|||
&:nth-of-type(2n) { order: 2; } |
|||
|
|||
/* 强制换列 */ |
|||
&.break { |
|||
flex-basis: 100%; |
|||
width: 0; |
|||
margin: 0; |
|||
content: ""; |
|||
padding: 0; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -1,221 +1,60 @@ |
|||
<template> |
|||
<!-- 瀑布流版本布局 + 高度随宽度调整变化 --> |
|||
<el-card class="homeMenuPage" v-resize="setMaxHeight" v-loading="loading"> |
|||
<div class="firstMenuContain homeMenuPage-List"> |
|||
<div |
|||
class="firstMenuItem menuItem" |
|||
v-for="(item,index) in navList" |
|||
:key="index" |
|||
> |
|||
<div class="firstTitle" v-if="item.meta"> |
|||
<div class="icon"><svg-icon :icon-class="item.meta.icon" style="fill:currentColor; color:#fff;"/></div> |
|||
<div>{{item.meta.title}}</div> |
|||
</div> |
|||
<ul class="menuInfo" v-if="item.children && item.children.length > 0"> |
|||
<li |
|||
v-for="(item2,index2) in item.children" |
|||
:key="index2" |
|||
> |
|||
<div class="title"> |
|||
{{item2.meta.title}} |
|||
<i class="el-icon-arrow-right"></i> |
|||
</div> |
|||
<!-- 有下级菜单 --> |
|||
<div class="lastList" v-if="item2.children && item2.children.length > 0"> |
|||
<div |
|||
v-for="(item3,index3) in item2.children" |
|||
:key="index3" |
|||
class="item" |
|||
> |
|||
<span @click="goPage(item3)">{{item3.meta.title}}</span> |
|||
</div> |
|||
</div> |
|||
<!-- 如果二级为最后一级,统一格式,补充到children中 --> |
|||
<div class="lastList" v-else> |
|||
<div class="item"> |
|||
<span @click="goPage(item2)">{{item2.meta.title}}</span> |
|||
</div> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<span class="firstMenuItem break"></span> |
|||
<span class="firstMenuItem break"></span> |
|||
<span class="firstMenuItem break"></span> |
|||
</div> |
|||
</el-card> |
|||
</template> |
|||
<div class="dashboardPage"> |
|||
<el-tree |
|||
:data="navList" |
|||
:props="defaultProps" |
|||
@node-click="goPage" |
|||
></el-tree> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapGetters } from 'vuex' |
|||
export default { |
|||
directives: { |
|||
// 页面宽度变化,重新计算总高度 |
|||
resize: { // 指令的名称 |
|||
bind(el, binding) { // el为绑定的元素,binding为绑定给指令的对象 |
|||
let width = '', height = ''; |
|||
function isReize() { |
|||
const style = document.defaultView.getComputedStyle(el); |
|||
if (width !== style.width || height !== style.height) { |
|||
binding.value(); // 关键 |
|||
} |
|||
width = style.width; |
|||
height = style.height; |
|||
} |
|||
el.__vueSetInterval__ = setInterval(isReize, 300); |
|||
}, |
|||
unbind(el) { |
|||
clearInterval(el.__vueSetInterval__); |
|||
} |
|||
} |
|||
}, |
|||
name: 'Dashboard', |
|||
data() { |
|||
return { |
|||
loading:true, |
|||
navList:[], |
|||
} |
|||
}, |
|||
watch: { |
|||
permission_routes(val, oldVal) { |
|||
this.initData(val) |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'permission_routes' |
|||
]) |
|||
}, |
|||
mounted(){ |
|||
this.initData(this.permission_routes) |
|||
}, |
|||
methods:{ |
|||
initData(data){ |
|||
data.forEach(item => { |
|||
if(!item.hidden && item.path !== '/') { |
|||
this.navList.push(item) |
|||
} |
|||
}) |
|||
this.$nextTick(()=>{ |
|||
this.setMaxHeight() |
|||
}) |
|||
}, |
|||
goPage(item){ |
|||
this.$router.push({name: item.name}) |
|||
}, |
|||
setMaxHeight(){ |
|||
// todo:用this.$route.path != /dashboard 判断 |
|||
console.log("setMaxHeight",this.$route.path) |
|||
if(document.getElementsByClassName("homeMenuPage-List").length <= 0){ |
|||
return |
|||
} |
|||
let _items = document.getElementsByClassName("menuItem") |
|||
let _left = []; |
|||
let _right = []; |
|||
let _left_num = 0; |
|||
let _right_num = 0; |
|||
_items.forEach((item,key)=>{ |
|||
// 左侧 |
|||
if(key % 2 == 0){ |
|||
_left.push(item.offsetHeight) |
|||
_left_num += Number(item.offsetHeight) |
|||
} |
|||
// 右侧 |
|||
else{ |
|||
_right.push(item.offsetHeight) |
|||
_right_num += Number(item.offsetHeight) |
|||
} |
|||
}) |
|||
let _max = _left_num > _right_num ? _left_num : _right_num |
|||
_max += 20 * _items.length |
|||
document.getElementsByClassName("homeMenuPage-List")[0].style.height = _max + 'px' |
|||
this.loading = false |
|||
<script> |
|||
import { mapGetters } from 'vuex' |
|||
export default { |
|||
name: 'Dashboard', |
|||
data() { |
|||
return { |
|||
navList:[], |
|||
defaultProps: { |
|||
children: 'children', |
|||
label: 'title' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
$iconSize:26px; |
|||
.homeMenuPage{ |
|||
height: 100%; |
|||
overflow: auto; |
|||
// padding: 20px 0; |
|||
} |
|||
.firstMenuContain { |
|||
display: flex; |
|||
flex-flow: column wrap; |
|||
align-content: space-between; |
|||
/* 容器必须有固定高度 |
|||
* 且高度大于最高的列高 */ |
|||
// height: 2500px; |
|||
.firstMenuItem { |
|||
width: calc(50% - 20px); |
|||
margin-bottom: 20px; |
|||
|
|||
.firstTitle{ |
|||
display: flex; |
|||
font-weight: bold; |
|||
font-size: 18px; |
|||
.icon{ |
|||
background: #409eff; |
|||
color: #fff; |
|||
border-radius: 4px; |
|||
width: $iconSize; |
|||
height: $iconSize; |
|||
line-height: $iconSize; |
|||
overflow: hidden; |
|||
text-align: center; |
|||
margin-right: 10px; |
|||
} |
|||
} |
|||
|
|||
.menuInfo{ |
|||
background: #f9fafb; |
|||
margin: 20px 0; |
|||
padding: 5px 0; |
|||
li{ |
|||
list-style: none; |
|||
display: flex; |
|||
padding-top: 10px; |
|||
.title{ |
|||
width: 240px; |
|||
text-align: right; |
|||
font-weight: bold; |
|||
flex-shrink: 0; |
|||
.el-icon-arrow-right{ |
|||
font-weight: bold; |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
.lastList{ |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
margin-left: 15px; |
|||
.item{ |
|||
margin-right: 25px; |
|||
margin-bottom: 10px; |
|||
cursor: pointer; |
|||
|
|||
&:hover{ |
|||
color: #409eff; |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'permission_routes' |
|||
]) |
|||
}, |
|||
mounted(){ |
|||
this.initData(this.permission_routes) |
|||
}, |
|||
methods:{ |
|||
initData(data){ |
|||
data.forEach(item => { |
|||
if(!item.hidden && item.path !== '/' && item.meta) { |
|||
let _item = { |
|||
title:item.meta.title, |
|||
name:item.name, |
|||
path:item.path, |
|||
children:item.children |
|||
} |
|||
this.navList.push(_item) |
|||
} |
|||
} |
|||
|
|||
/* 将内容块重排为4列 */ |
|||
&:nth-of-type(2n+1) { order: 1; } |
|||
&:nth-of-type(2n) { order: 2; } |
|||
|
|||
/* 强制换列 */ |
|||
&.break { |
|||
flex-basis: 100%; |
|||
width: 0; |
|||
margin: 0; |
|||
content: ""; |
|||
padding: 0; |
|||
} |
|||
} |
|||
if(!item.hidden && item.children){ |
|||
this.initData(item.children) |
|||
} |
|||
}) |
|||
}, |
|||
goPage(item){ |
|||
this.$router.push({name: item.name}) |
|||
}, |
|||
} |
|||
</style> |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.dashboardPage{ |
|||
padding:30px 10px; |
|||
background: #fff; |
|||
} |
|||
</style> |
Loading…
Reference in new issue