123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- <template>
- <el-scrollbar v-if="showTabs && activeTab !== 'selectCityAndCounty'">
- <el-menu
- :collapse="isCollapse"
- router
- unique-opened
- :default-active="activeMenuItem.index"
- class="professional-menu"
- >
- <template v-for="item in filteredMenuItems" :key="item.index">
- <el-sub-menu v-if="item.children" :index="item.index">
- <template #title>
- <el-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"
- @click="handleMenuClick(child.index)"
- >
- <el-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"
- @click="handleMenuClick(item.index)"
- >
- <el-icon><component :is="item.icon" /></el-icon>
- <span>{{ item.label }}</span>
- </el-menu-item>
- </template>
- </el-menu>
- </el-scrollbar>
- </template>
- <script setup lang="ts">
- import { reactive, computed, inject, toRefs, watch } from 'vue';
- import { useRouter } from 'vue-router';
- import { ElMessage } from 'element-plus';
- import { menuItems } from './menuItems'; // 建议你将 menuItems 独立维护在该文件中
- const props = defineProps({
- activeTab: {
- type: String,
- required: true,
- default: 'introduction'
- },
- showTabs: {
- type: Boolean,
- required: false,
- default: true
- }
- });
- const { activeTab } = toRefs(props);
- const isCollapse = inject('isCollapse', false);
- const userPermissions = inject('userPermissions', [] as string[]);
- const router = useRouter();
- const activeMenuItem = reactive({ index: '' });
- const filteredMenuItems = computed(() =>
- menuItems
- .filter(item => item.tab === activeTab.value)
- .map(item => {
- if (!item.children) return item;
- return {
- ...item,
- children: item.children.filter(
- child => !child.permission || userPermissions.includes(child.permission)
- )
- };
- })
- );
- function handleMenuClick(index: string) {
- try {
- if (router.currentRoute.value.path !== index) {
- router.push(index);
- activeMenuItem.index = index;
- }
- } catch (error) {
- ElMessage.error('导航失败,请检查网络或联系管理员');
- }
- }
- watch(
- activeTab,
- newVal => {
- const current = filteredMenuItems.value?.[0];
- activeMenuItem.index = current?.children?.[0]?.index || current?.index || '';
- },
- { immediate: true }
- );
- </script>
- <style scoped>
- :deep(.el-scrollbar) {
- 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;
- height: 100%;
- display: flex;
- flex-direction: column;
- }
- .professional-menu {
- background: transparent;
- border-right: none;
- padding-top: 12px;
- flex: 1;
- display: flex;
- flex-direction: column;
- min-height: 100%;
- }
- :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;
- }
- :deep(.el-sub-menu .el-menu-item:not(:last-child)) {
- margin-bottom: 0;
- }
- :deep(.el-sub-menu__title) {
- font-size: 18px;
- font-weight: 500;
- color: #000000;
- border-radius: 6px;
- padding: 12px 16px !important;
- transition: all 0.2s ease;
- }
- /* Hover 效果 */
- :deep(.el-menu-item:hover),
- :deep(.el-sub-menu__title:hover) {
- background-color: rgba(16, 146, 216, 0.1);
- color: #1092D8;
- }
- /* 激活高亮 */
- :deep(.el-menu-item.is-active),
- :deep(.el-sub-menu__title.is-active) {
- background: linear-gradient(to right, #1092D8, #02C3AD);
- color: #ffffff !important;
- border-radius: 8px;
- font-weight: 600;
- box-shadow: 0 2px 8px rgba(16, 146, 216, 0.25);
- }
- /* 子菜单标题样式 + 图标右移 */
- :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>
|