Files
ylst-pc/src/components/LeftMenuBar.vue
2022-10-15 11:57:43 +08:00

321 lines
7.9 KiB
Vue

<template>
<div class="menu-bar" v-click-outside="clickOutside">
<div class="menu-bar-item" v-for="(item, i) in menus" :key="i">
<div class="menu-bar-no-child">
<!-- <img
class="menu-bar-item-img"
:style="{
opacity: item.check && item.children.length === 0 ? 1 : 0,
}"
src="../assets/img/down_circle.png"
/> -->
<div
class="menu-bar-item-main"
:class="{ 'menu-bar-item-main-active': item.check || index == i }"
@click="parentCheck($event, item, i)"
>
<div class="menu-bar-item-main-icon">
<i class="iconfont" v-html="item.icon"></i>
</div>
<div class="menu-bar-item-main-text">
<div>{{ item[property] }}</div>
<i
v-if="item.children.length > 0"
class="iconfont"
:class="{ 'iconfont-active': item.unfold }"
>&#xe675;</i
>
</div>
</div>
<!-- <img
class="menu-bar-item-img"
:style="{
opacity: item.check && item.children.length === 0 ? 1 : 0,
}"
src="../assets/img/up_circle.png"
/> -->
</div>
<div class="menu-bar-has-child">
<div
class="menu-bar-item-child"
v-for="(child, childIndex) in item.children"
:key="childIndex"
>
<div class="menu-bar-item-parent">
<div
class="menu-bar-item-main"
:style="{
background: child.check ? 'rgba(112, 185, 54, 0.1)' : '#ffffff',
color: child.check ? '#70b936' : '#000000',
height: '32px',
margin: '10px 0',
borderRadius: '0',
}"
@click="childCheck(child, i)"
>
<div class="menu-bar-item-main-icon">
<i class="iconfont" v-html="child.icon"></i>
</div>
<div class="menu-bar-item-main-text">{{ child[property] }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, watch } from "@vue/runtime-core";
import { useRoute } from "vue-router";
export default {
name: "LeftMenuBar",
props: {
list: {
type: Array,
default: () => [],
},
property: {
type: String,
default: "name",
},
},
activated() {
const route = useRoute();
const path = route.path;
this.menus.forEach((x) => {
x.check = x.path === path;
});
},
setup(props, context) {
const index = ref(null);
const route = useRoute();
let menus = props.list.map((first) => {
const path = route.path;
first.check = path === first.path;
first.unfold = false;
first.children = first.children.map((second) => {
second.check = false;
return second;
});
return first;
});
const { parentCheck, childCheck, clickOutside } = domHandle(menus, context);
watch(
() => route.path,
() => {
console.log("menus", menus);
menus = menus.map((first) => {
const path = route.path;
first.check = path === first.path;
// first.unfold = false;
// first.children = first.children.map((second) => {
// second.check = false;
// return second;
// });
return first;
});
}
);
// 点击一级菜单名称
const menuName = ref("");
function domHandle(menus, context) {
// 点击一级菜单
const parentCheck = (e, item, i) => {
if (menuName.value !== item.name) {
menusStatusToFalsefather(menus);
}
menuName.value = item.name;
if (item.disable) return;
if (item.children.length > 0) {
item.unfold = !item.unfold;
const $checkDom = e.currentTarget.parentElement.nextElementSibling;
$checkDom.style.height = item.unfold
? `${$checkDom.scrollHeight}px`
: 0;
$checkDom.style.borderRadius = item.unfold || 0;
return;
}
if (item.check) return;
menusStatusToFalse(menus);
item.check = true;
index.value = i;
context.emit("menuCheck", item);
};
// 点击二级菜单
const childCheck = (child, i) => {
if (!!child.check) return;
menusStatusToFalse(menus);
context.emit("menuCheck", child);
child.check = true;
index.value = i;
menusStatusToFalsefather(menus);
};
const clickOutside = () => {
menus.forEach((x) => {
if (x.children && x.unfold) {
x.unfold = false;
const menuChild$ = document.querySelectorAll(".menu-bar-has-child");
for (let index = 0; index < menuChild$.length; index++) {
const element = menuChild$[index];
element.style.height = 0;
}
}
});
};
return {
parentCheck,
childCheck,
clickOutside,
};
}
return {
menus,
index,
parentCheck,
childCheck,
clickOutside,
};
},
};
function menusStatusToFalse(menus) {
menus.forEach((x) => {
x.check = false;
if (x.children) {
menusStatusToFalse(x.children);
}
});
}
function menusStatusToFalsefather(menus) {
menus.forEach((x) => {
x.unfold = false;
var menubar = document.getElementsByClassName("menu-bar-has-child");
for (var key = 0; key < menubar.length; key++) {
menubar[key].style.height = "0px";
}
});
}
</script>
<style lang="scss" scoped>
.menu-bar {
display: flex;
width: 100%;
height: 48px;
font-size: 13px;
z-index: 99999;
&-item {
position: relative;
width: 220px;
z-index: 99;
background: rgba(245, 245, 245, 0.6);
&-child {
background-color: #ffffff;
.menu-bar-item-main-text{
width: 68px;
}
}
&-img {
width: 10px;
height: 10px;
line-height: 50px;
display: block;
margin-left: 61px;
transition: all 0.3s;
}
&-main {
width: 220px;
height: 48px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px 8px 0px 0px;
padding-right: 5px;
transition: all 0.3s;
&-active {
color: $yili-default-color;
background: #ffffff;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
}
&-icon {
opacity: 0.9;
margin: 8px 10px 0 0;
}
&-text {
display: flex;
align-items: center;
margin-top: 8px;
opacity: 0.8;
div {
font-size: 12px;
}
}
.iconfont {
font-size: 20px;
height: 18px;
line-height: 20px;
transition: all 0.3s;
transform: rotate(0deg);
}
.iconfont-active {
transform: rotate(180deg);
}
&:hover &-icon {
opacity: 1;
}
&:hover &-text {
opacity: 1;
}
}
}
&-no-child {
}
&-has-child {
overflow: hidden;
transition: all 0.3s;
height: 0;
border-radius: 5px 5px 5px 5px;
box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 10%);
}
.menu-bar-item:last-child {
border-radius: 0px 8px 0px 0px;
}
.menu-bar-item:first-child {
border-radius: 8px 0px 0px 0px;
}
}
.menu-bar-item-main-text {
font-size: 0.75rem;
z-index: 99;
}
.menu-bar-item-main-icon {
z-index: 99;
}
::v-deep(.menu-bar-item-main) {
position: relative;
z-index: 99;
}
.menu-bar-item-child {
height: 50px;
display: block;
position: relative;
top: 0;
left: 0;
/* background: #ffffff; */
z-index: 999;
}
.menu-bar-item-parent {
height: 50px;
position: absolute;
z-index: 999;
left: 0;
top: 0;
background: #ffffff;
opacity: 1;
z-index: 100;
height: 50px;
}
</style>