| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- <template>
- <el-scrollbar v-if="showTabs">
- <el-menu
- :collapse="isCollapse"
- router
- unique-opened
- :default-active="activeMenuItem.index"
- :default-openeds="openKeys"
- @select="handleMenuClick"
- >
- <template v-if="menuList.length">
- <template v-for="item in menuList" :key="item.index">
- <el-sub-menu v-if="item.children && item.children.length" :index="item.index">
- <template #title>
- <el-icon v-if="item.icon"><component :is="item.icon" /></el-icon>
- <span>{{ item.label }}</span>
- </template>
- <el-menu-item
- v-for="child in item.children"
- :key="child.index"
- :index="child.index"
- >
- <el-icon v-if="child.icon"><component :is="child.icon" /></el-icon>
- <span>{{ child.label }}</span>
- </el-menu-item>
- </el-sub-menu>
- <el-menu-item v-else :index="item.index">
- <el-icon v-if="item.icon"><component :is="item.icon" /></el-icon>
- <span>{{ item.label }}</span>
- </el-menu-item>
- </template>
- </template>
- <template v-else>
- <el-menu-item disabled>未知的 Tab:{{ activeTab }}</el-menu-item>
- </template>
- </el-menu>
- </el-scrollbar>
- </template>
- <script setup lang="ts">
- import { inject, reactive, watch, toRefs, computed } from "vue";
- import { useRouter, useRoute, type RouteLocationAsPathGeneric, type RouteLocationAsRelativeGeneric } from "vue-router";
- import { ElMessage } from "element-plus";
- import { tabMenuMap } from "./menuItems2";
- console.log('当前使用的侧边栏组件:AppAsideForTab2.vue') // AppAsideForTab2.vue 中添加
- const props = defineProps({
- activeTab: {
- type: String,
- required: true,
- default: "introduction",
- },
- showTabs: {
- type: Boolean,
- required: true,
- default: true,
- },
- });
- const { activeTab } = toRefs(props);
- const isCollapse = inject("isCollapse", false);
- const router = useRouter();
- const route = useRoute();
- const activeMenuItem = reactive({ index: route.path });
- const openKeys = reactive<string[]>([]);
- const menuList = computed(() => {
- return tabMenuMap[activeTab.value] || [];
- });
- // 查找当前路由对应的父级菜单index,用于默认展开子菜单
- function findOpenKeys(menuItems: any[], currentPath: string, parents: string[] = []): string[] {
- for (const item of menuItems) {
- if (item.index === currentPath) {
- return parents;
- } else if (item.children) {
- const found = findOpenKeys(item.children, currentPath, [...parents, item.index]);
- if (found.length) return found;
- }
- }
- return [];
- }
- watch(
- () => route.path,
- (newPath) => {
- activeMenuItem.index = newPath;
- openKeys.splice(0, openKeys.length, ...findOpenKeys(menuList.value, newPath));
- },
- { immediate: true }
- );
- watch(
- activeTab,
- (newVal) => {
- const first = tabMenuMap[newVal]?.[0];
- if (first) activeMenuItem.index = first.index;
- else activeMenuItem.index = "";
- openKeys.splice(0, openKeys.length, ...findOpenKeys(menuList.value, activeMenuItem.index));
- },
- { immediate: true }
- );
- async function handleMenuClick(index: string | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric) {
- try {
- if (index === route.path) return;
- await router.push(index);
- activeMenuItem.index = index as string;
- } catch (error) {
- console.error(`[AppAsideForTab2] 路由跳转失败: ${index}`, error);
- ElMessage.error("导航失败,请检查网络连接或联系管理员。");
- }
- }
- </script>
- <style scoped>
- /* 给 el-menu 组件设置背景渐变 */
- :deep(.el-menu) {
- background: linear-gradient(to bottom, #B7F1FC , #FFF8F0) !important;
- height: 100%;
- border-right: none !important;
- padding-top: 12px;
- }
- /* 保持滚动条内容透明 */
- :deep(.el-scrollbar__wrap),
- :deep(.el-scrollbar__view) {
- background: transparent !important;
- height: 100%;
- display: flex;
- flex-direction: column;
- }
- /* 菜单项和子菜单标题 */
- :deep(.el-menu-item),
- :deep(.el-sub-menu__title) {
- margin-left: 0 !important;
- margin-right: 0 !important;
- width: 100%;
- box-sizing: border-box;
- padding-left: 40px !important;
- padding-right: 20px !important;
- }
- /* 子菜单中菜单项背景色 */
- :deep(.el-sub-menu .el-menu-item) {
- background-color: rgba(252, 234, 183, 0.3) !important;
- }
- /* Hover 效果 */
- :deep(.el-menu-item:hover),
- :deep(.el-sub-menu__title:hover) {
- background-color: rgba(16, 146, 216, 0.1) !important;
- color: #1092D8 !important;
- }
- /* 激活高亮 */
- :deep(.el-menu-item.is-active),
- :deep(.el-sub-menu__title.is-active) {
- background: linear-gradient(to right, #1092D8, #02C3AD) !important;
- color: #ffffff !important;
- border-radius: 8px !important;
- font-weight: 600 !important;
- box-shadow: 0 2px 8px rgba(16, 146, 216, 0.25) !important;
- }
- /* 子菜单标题样式 + 图标右移 */
- :deep(.el-sub-menu__title) {
- display: flex;
- align-items: center;
- padding-left: 20px !important;
- }
- /* 下拉图标右移 */
- :deep(.el-sub-menu__icon-arrow) {
- margin-left: auto;
- margin-right: -160px;
- transition: transform 0.3s ease;
- }
- </style>
|