wms-elevue/src/layout/components/Sider/Sider.vue
2024-07-12 08:47:19 +08:00

174 lines
4.9 KiB
Vue

<template>
<el-menu
:default-openeds="openKeys"
:default-active="getSelectedKeys"
:theme="getTheme"
:collapse="getCollapsed"
:collapse-transition="false"
:unique-opened="getUniqueOpened"
:mode="props.mode"
style="width: 100%"
@select="menuItemClick"
@open="subMenuItemClick"
>
<template v-for="item in menus" :key="item.key">
<el-menu-item v-if="!item.children" :key="getMenuKey(item.key)" :index="item.key">
<template #title>
<icon :name="item.icon" :size="20" v-if="item.icon"/>
<span>{{ item.title }}</span>
</template>
</el-menu-item>
<template v-else><ReSubMenu :parent="item" /></template>
</template>
</el-menu>
</template>
<script lang="ts" setup>
import { ref, computed, watch, onMounted, unref, inject } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { generatorMenu, generatorMenuMix } from '@/utils';
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
import { useAsyncRouteStore } from '@/store/modules/asyncRoute';
import { useProjectSettingStore } from '@/store/modules/projectSetting';
import ReSubMenu from './ReSubMenu.vue';
const collapsed = inject('collapsed');
const { getMenuSetting, getNavMode, getNavTheme } = useProjectSetting();
const navMode = getNavMode;
defineEmits(['update:collapsed']);
const props = defineProps({
mode: {
type: String,
default: 'vertical',
},
theme: {
type: String,
default: 'dark',
},
//位置
location: {
type: String,
default: 'left',
},
});
// 当前路由
const currentRoute = useRoute();
const router = useRouter();
const settingStore = useProjectSettingStore();
const menus = ref<any>([]);
const headerMenuSelectKey = ref<string>('');
// 获取当前打开的子菜单
const matched = currentRoute.matched;
const activeMenu = currentRoute.meta?.activeMenu ?? null;
const selectedKeys = ref<string>((activeMenu ?? currentRoute.name) as string);
const openKeys = ref(matched && matched.length ? matched.map((item) => item.name) : []);
const asyncRouteStore = useAsyncRouteStore();
const getCollapsed = computed(() => {
let location = props.location;
return location === 'left' ? unref(collapsed) : false;
});
const getUniqueOpened = computed(() => {
return getMenuSetting.value.uniqueOpened;
});
const getSelectedKeys = computed(() => {
let location = props.location;
return location === 'left' || (location === 'header' && unref(navMode) === 'horizontal')
? unref(selectedKeys)
: unref(headerMenuSelectKey);
});
// 监听分割菜单
watch(
() => settingStore.menuSetting.mixMenu,
() => {
updateMenu();
},
);
// 跟随页面路由变化,切换菜单选中状态
watch(
() => currentRoute.fullPath,
() => {
updateMenu();
const matched = currentRoute.matched;
openKeys.value = matched.map((item) => item.name);
const activeMenu: string = (currentRoute.meta?.activeMenu as string) || '';
selectedKeys.value = activeMenu ? activeMenu : (currentRoute.name as string);
},
);
function getMenuKey(key) {
return `${props.location}_${key}`;
}
function updateMenu() {
if (!settingStore.menuSetting.mixMenu) {
menus.value = generatorMenu(asyncRouteStore.getMenus);
} else {
//混合菜单
const firstRouteName: string = (currentRoute.matched[0].name as string) || '';
menus.value = generatorMenuMix(asyncRouteStore.getMenus, firstRouteName, props.location);
const activeMenu: string = currentRoute?.matched[0].meta?.activeMenu as string;
headerMenuSelectKey.value = (activeMenu ? activeMenu : firstRouteName) || '';
}
}
// const getMenuMode = computed(() => {
// if (props.mode === 'vertical') {
// return getMenuIsPop.value ? 'pop' : 'vertical';
// } else {
// return props.mode;
// }
// });
const getTheme = computed(() => {
return getNavTheme.value === 'light' ? 'light' : props.theme;
});
//点击菜单项时触发
function menuItemClick(key) {
if (/http(s)?:/.test(key)) {
window.open(key);
} else {
router.push({ name: key });
}
}
function subMenuItemClick(_, keys) {
if (!keys) return;
const latestOpenKey = keys.find((key) => openKeys.value.indexOf(key) === -1);
const isExistChildren = findChildrenLen(latestOpenKey as string);
openKeys.value = isExistChildren ? (latestOpenKey ? [latestOpenKey] : []) : keys;
}
//查找是否存在子路由
function findChildrenLen(key: string) {
if (!key) return false;
const subRouteChildren: string[] = [];
for (const { children, key } of unref(menus)) {
if (children && children.length) {
subRouteChildren.push(key as string);
}
}
return subRouteChildren.includes(key);
}
onMounted(() => {
updateMenu();
});
</script>