<template>
|
<div class="pc-chat_aside flex-0 relative" :style="`width:252px;transition: 0.7s ease-in;`">
|
<!-- Logo 部分 -->
|
<div class="h-[40px] w-full bg-[#0084ff] flex justify-between items-center text-white px-2">
|
<span>GIS系统</span>
|
<!-- <span>官网GIS</span> -->
|
</div>
|
<!-- 菜单项 -->
|
<div class="menu-container">
|
<el-menu :default-active="activeId" class="wi-menu !w-full" :unique-opened="true" @select="handleSelect">
|
<template v-for="item in menuData">
|
<el-sub-menu :key="`sub-${item.id}`" v-if="item.children?.length" :index="item.id">
|
<template #title>
|
<i v-if="item.icon" :class="item.icon"></i>
|
<span>{{ item.title }}</span>
|
</template>
|
|
<template v-for="subItem in item.children">
|
<el-sub-menu :key="`sub-${subItem.id}`" v-if="subItem.children?.length" :index="subItem.id">
|
<template #title>
|
<i v-if="subItem.icon" :class="subItem.icon"></i>
|
<span>{{ subItem.title }}</span>
|
</template>
|
<!-- 三级菜单项 -->
|
<el-menu-item v-for="child in subItem.children" :key="`item-${child.id}`" :index="child.id">
|
<i v-if="child.icon" :class="child.icon"></i>
|
<span>{{ child.title }}</span>
|
</el-menu-item>
|
</el-sub-menu>
|
<!-- 二级菜单项 -->
|
<el-menu-item v-else :key="`item-${subItem.id}`" :index="subItem.id">
|
<i v-if="subItem.icon" :class="subItem.icon"></i>
|
<span>{{ subItem.title }}</span>
|
</el-menu-item>
|
</template>
|
</el-sub-menu>
|
<el-menu-item v-else :key="`item-${item.id}`" :index="item.id">
|
<i v-if="item.icon" :class="item.icon"></i>
|
<span>{{ item.title }}</span>
|
</el-menu-item>
|
</template>
|
</el-menu>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { computed, ref, onMounted, watch } from 'vue';
|
import { useRouter } from 'vue-router';
|
import type { MenuItemData } from './types';
|
|
const router = useRouter();
|
const activeId = ref('');
|
|
// 示例菜单数据
|
const menuData = ref<MenuItemData[]>([
|
{
|
id: 'menu1',
|
title: '首页',
|
icon: 'icon-park-outline-chart-line',
|
path: '/gis/situation',
|
},
|
{
|
id: 'menu2',
|
title: '统计',
|
icon: 'icon-park-outline-folder',
|
children: [
|
{
|
id: '自定义统计',
|
title: '自定义统计',
|
path: '/gis/situation',
|
},
|
{
|
id: 'menu2-2',
|
title: '管线统计',
|
path: '/gis/situation',
|
},
|
],
|
},
|
]);
|
|
// 计算属性:有子菜单的项
|
const parentMenuItems = computed(() => menuData.value.filter((item) => item.children?.length));
|
|
// 计算属性:没有子菜单的项
|
const leafMenuItems = computed(() => menuData.value.filter((item) => !item.children?.length));
|
|
const handleSelect = (index: string) => {
|
activeId.value = index;
|
const findPath = (items: MenuItemData[]): string | undefined => {
|
for (const item of items) {
|
if (item.id === index) return item.path;
|
if (item.children) {
|
const path = findPath(item.children);
|
if (path) return path;
|
}
|
}
|
};
|
console.log('🚀 ~ index:', index);
|
const path = findPath(menuData.value);
|
if (path) {
|
router.push(path);
|
}
|
};
|
|
// 通过 path 找 index
|
const findIndex = (items: MenuItemData[]): string | undefined => {
|
for (const item of items) {
|
if (item.path === router.currentRoute.value.path) return item.id;
|
if (item.children) {
|
const index = findIndex(item.children);
|
if (index) return index;
|
}
|
}
|
};
|
watch(router.currentRoute, (newRoute) => {
|
activeId.value = findIndex(menuData.value) || '';
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.pc-chat_aside {
|
height: 100%;
|
box-sizing: border-box;
|
background-color: var(--color-bg-side);
|
overflow: visible;
|
transition: width 0.1s ease-in;
|
position: relative;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.aside_top {
|
box-sizing: border-box;
|
position: relative;
|
width: 100%;
|
padding: 18px;
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
}
|
|
.layout-logo-medium-img {
|
width: 28px;
|
margin-right: 7px;
|
}
|
|
.menu-container {
|
flex: 1;
|
overflow-y: auto;
|
|
:deep(.wi-menu) {
|
border-right: none;
|
background-color: transparent;
|
--hover-menu-bg: rgba(255, 255, 255, 0.1);
|
--menu-width: 100% !important;
|
|
--active-menu-bg: #333534 !important;
|
--active-menu-color: var(--color-btn-base) !important;
|
|
.el-menu {
|
background-color: transparent;
|
width: var(--menu-width) !important;
|
}
|
|
// 鼠标 hover 时颜色
|
|
.el-menu-item {
|
height: 40px;
|
line-height: 40px;
|
color: #ccc;
|
|
&:hover {
|
background: var(--hover-menu-bg) !important;
|
}
|
|
&.is-active {
|
background: var(--active-menu-bg) !important;
|
color: var(--active-menu-color);
|
}
|
|
i {
|
margin-right: 8px;
|
}
|
}
|
|
.el-sub-menu {
|
.el-menu {
|
width: var(--menu-width) !important;
|
}
|
--next-bg-menuBarActiveColor: unset !important;
|
|
.el-sub-menu__title {
|
height: 40px;
|
line-height: 40px;
|
color: #ccc;
|
|
&:hover {
|
background: var(--hover-menu-bg) !important;
|
}
|
|
i {
|
margin-right: 8px;
|
}
|
}
|
|
&.is-active {
|
.el-sub-menu__title {
|
color: var(--active-menu-color);
|
}
|
}
|
}
|
|
// 子菜单弹出层样式
|
.el-menu--popup {
|
background-color: var(--color-bg-side);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
padding: 0;
|
|
.el-menu-item {
|
background-color: transparent;
|
color: #ccc;
|
|
&:hover {
|
background-color: rgba(255, 255, 255, 0.1);
|
}
|
|
&.is-active {
|
background: var(--active-menu-bg);
|
color: var(--active-menu-color);
|
}
|
}
|
}
|
}
|
}
|
</style>
|