feat: 菜单风格3;

This commit is contained in:
From-wh 2023-05-05 18:21:51 +08:00
parent fb32942c35
commit d3bf3d2b40
5 changed files with 304 additions and 5 deletions

View File

@ -0,0 +1,287 @@
<template>
<div class="layout-columns-tra-aside">
<el-scrollbar>
<ul>
<li
v-for="(v, k) in columnsAsideList"
:key="k"
@click="onColumnsAsideMenuClick(v)"
ref="columnsAsideOffsetLeftRefs"
class="layout-columns"
:class="{ 'layout-columns-active': v.k === liIndex }"
:title="$t(v.title)"
>
<div :class="setColumnsAsidelayout" v-if="!v.isLink || (v.isLink && v.isIframe)">
<Icon :type="v.icon" />
<div class="font12">
{{
$t(v.title) && $t(v.title).length >= 4
? $t(v.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.title)
}}
</div>
</div>
<div :class="setColumnsAsidelayout" v-else>
<a :href="v.isLink" target="_blank">
<Icon :type="v.icon" />
<div class="font12">
{{
$t(v.title) && $t(v.title).length >= 4
? $t(v.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.title)
}}1
</div>
</a>
</div>
</li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
</ul>
</el-scrollbar>
</div>
</template>
<script>
import { getMenuSider, getHeaderName } from '@/libs/system';
import Logo from '@/layout/logo/index.vue';
export default {
name: 'layoutColumnsAside',
components: { Logo },
data() {
return {
columnsAsideList: [],
liIndex: 0,
difference: 0,
routeSplit: [],
activePath: '',
};
},
computed: {
// 设置分栏高亮风格
setColumnsAsideStyle() {
return this.$store.state.themeConfig.themeConfig.columnsAsideStyle;
},
// 设置分栏布局风格
setColumnsAsidelayout() {
return this.$store.state.themeConfig.themeConfig.columnsAsideLayout;
},
Layout() {
return this.$store.state.themeConfig.themeConfig.Layout;
},
routesList() {
this.$store.state.routesList.routesList;
},
},
beforeDestroy() {
this.bus.$off('routesListChange');
},
mounted() {
this.bus.$on('routesListChange', () => {
this.setFilterRoutes();
});
this.setFilterRoutes();
},
methods: {
// 设置菜单高亮位置移动
setColumnsAsideMove(k) {
if (k === undefined) return false;
const els = this.$refs.columnsAsideOffsetLeftRefs;
this.liIndex = k;
this.$refs.columnsAsideActiveRef.style.left = `${els[k].offsetLeft + this.difference}px`;
},
// 菜单高亮点击事件
onColumnsAsideMenuClick(v) {
let { path, redirect } = v;
if (path) this.$router.push(path);
else this.$router.push(path);
// 一个路由设置自动收起菜单
if (!v.children || v.children.length <= 1) this.$store.state.themeConfig.themeConfig.isCollapse = true;
else if (v.children.length > 1) this.$store.state.themeConfig.themeConfig.isCollapse = false;
// this.bus.$emit('setSendColumnsChildren', getMenuSider(this.columnsAsideList, path));
},
// 设置高亮动态位置
onColumnsAsideDown(k) {
this.$nextTick(() => {
this.setColumnsAsideMove(k);
});
},
// 设置/过滤路由(非静态路由/是否显示在菜单中)
setFilterRoutes() {
if (this.$store.state.routesList.routesList.length <= 0) return false;
this.columnsAsideList = this.filterRoutesFun(this.$store.state.routesList.routesList);
// const resData = getHeaderName(this.$route.path, this.columnsAsideList);
const resData = this.setSendChildren(getHeaderName(this.$route, this.columnsAsideList));
if (!resData.children) {
this.bus.$emit('setSendColumnsChildren', []);
this.$store.commit('menus/childMenuList', []);
this.$store.state.themeConfig.themeConfig.isCollapse = true;
return false;
}
this.bus.$emit('oneCatName', resData.item[0].title);
this.onColumnsAsideDown(resData.item[0].k);
// 刷新时,初始化一个路由设置自动收起菜单
resData.children.length > 0
? (this.$store.state.themeConfig.themeConfig.isCollapse = false)
: (this.$store.state.themeConfig.themeConfig.isCollapse = true);
this.bus.$emit('setSendColumnsChildren', resData?.children || []);
this.$store.commit('menus/childMenuList', resData?.children || []);
},
// 传送当前子级数据到菜单中
setSendChildren(path) {
const currentPathSplit = path.split('/');
let currentData = {};
this.columnsAsideList.map((v, k) => {
if (v.path === path) {
v['k'] = k;
currentData['item'] = [{ ...v }];
// currentData['children'] = [{ ...v }];
if (v.children) currentData['children'] = v.children;
}
});
return currentData;
},
// 路由过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => item.path)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮
setColumnsMenuHighlight(path) {
// this.routeSplit = path.split('/');
// this.routeSplit.shift();
// const routeFirst = `/${this.routeSplit[0]}`;
const currentSplitRoute = this.columnsAsideList.find((v) => v.path === path);
if (!currentSplitRoute) {
// this.onColumnsAsideDown(0);
return false;
}
// 延迟拿值,防止取不到
setTimeout(() => {
this.onColumnsAsideDown(currentSplitRoute.k);
}, 0);
},
},
watch: {
// 监听 vuex 数据变化
'$store.state': {
handler(val) {
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound'
? (this.difference = 3)
: (this.difference = 0);
if (val.routesList.routesList.length === this.columnsAsideList.length) return false;
},
deep: true,
},
// 监听路由的变化
$route: {
handler(to) {
this.setColumnsMenuHighlight(to.path);
// this.setColumnsAsideMove();
let HeadName = getHeaderName(to, this.columnsAsideList);
let asideList = getMenuSider(this.columnsAsideList, HeadName)[0]?.children;
const resData = this.setSendChildren(HeadName);
if (resData.length <= 0) return false;
this.onColumnsAsideDown(resData.item[0].k);
this.bus.$emit('oneCatName', resData.item[0].title);
this.bus.$emit('setSendColumnsChildren', asideList || []);
this.$store.commit('menus/childMenuList', asideList || []);
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-columns-tra-aside {
// width: 70px;
height: 100%;
background: var(--prev-bg-columnsMenuBar);
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
overflow-y: hidden;
ul {
position: relative;
display: flex;
li {
color: var(--prev-bg-columnsMenuBarColor);
width: 80px;
height: 50px;
text-align: center;
display: flex;
cursor: pointer;
position: relative;
z-index: 1;
.columns-vertical {
margin: auto;
.columns-vertical-title {
// padding-top: 1px;
}
}
.columns-horizontal {
display: flex;
height: 50px;
width: 100%;
align-items: center;
justify-content: center;
padding: 0 5px;
i {
margin-right: 5px;
}
a {
display: flex;
.columns-horizontal-title {
padding-top: 1px;
}
}
}
a {
text-decoration: none;
color: var(--prev-bg-columnsMenuBarColor);
}
}
.layout-columns {
transition: 0.3s ease-in-out;
}
.layout-columns-active,
.layout-columns-active a {
color: var(--prev-bg-columnsMenuActiveColor);
transition: 0.3s ease-in-out;
}
.columns-round {
background: var(--prev-color-primary);
// color: var(--prev-color-text-white);
position: absolute;
left: 0;
// top: 2px;
height: 50px;
width: 80px;
transform: translatey(0%);
z-index: 0;
transition: 0.3s ease-in-out;
border-radius: 5px;
}
.columns-card {
@extend .columns-round;
top: 0;
height: 50px;
width: 80px;
border-radius: 0;
}
}
}
/deep/ .el-scrollbar {
height: 50px;
}
/deep/ .el-scrollbar__bar.is-horizontal {
display: none;
}
/deep/ .el-scrollbar__thumb {
display: none;
}
</style>

View File

@ -82,7 +82,7 @@ export default {
// 动态设置经典、横向布局不显示
isShowBreadcrumb() {
const { layout, isBreadcrumb } = this.$store.state.themeConfig.themeConfig;
if (layout === 'transverse') {
if (layout === 'transverse' || layout === 'classic') {
return 'none';
} else {
return isBreadcrumb ? '' : 'none';

View File

@ -3,6 +3,7 @@
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
<transverseAside v-if="isLayoutClassic" />
<User />
</div>
</template>
@ -12,9 +13,10 @@ import Breadcrumb from '@/layout/navBars/breadcrumb/breadcrumb.vue';
import User from '@/layout/navBars/breadcrumb/user.vue';
import Logo from '@/layout/logo/index.vue';
import Horizontal from '@/layout/navMenu/horizontal.vue';
import transverseAside from '@/layout/component/transverseAside.vue';
export default {
name: 'layoutNavBars',
components: { Breadcrumb, User, Logo, Horizontal },
components: { Breadcrumb, User, Logo, Horizontal, transverseAside },
data() {
return {
menuList: [],
@ -31,6 +33,10 @@ export default {
let { layout, isClassicSplitMenu } = this.$store.state.themeConfig.themeConfig;
return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic');
},
isLayoutClassic() {
let { layout } = this.$store.state.themeConfig.themeConfig;
return layout === 'classic';
},
},
mounted() {
this.setFilterRoutes();

View File

@ -275,7 +275,10 @@
</el-radio-group>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15" :class="{ mb28: getThemeConfig.layout !== 'columns' }">
<div
class="layout-breadcrumb-seting-bar-flex mt15"
:class="{ mb28: getThemeConfig.layout !== 'columns' && getThemeConfig.layout !== 'classic' }"
>
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-radio-group v-model="getThemeConfig.columnsAsideStyle" size="mini" @change="setLocalThemeConfig">
@ -284,7 +287,10 @@
</el-radio-group>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15 mb28" v-if="getThemeConfig.layout === 'columns'">
<div
class="layout-breadcrumb-seting-bar-flex mt15 mb28"
v-if="getThemeConfig.layout === 'columns' || getThemeConfig.layout === 'classic'"
>
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-radio-group v-model="getThemeConfig.columnsAsideLayout" size="mini" @change="setLocalThemeConfig">

View File

@ -418,7 +418,7 @@ export default {
line-height: 26px;
display: flex;
align-items: center;
border: 1px solid var(--prev-border-color-lighter);
border: 1px solid #ebeef5;
padding: 0 12px 0 15px;
margin-right: 5px;
border-radius: 2px;