diff --git a/src/layout/navBars/topBar/index.vue b/src/layout/navBars/topBar/index.vue
index 4fb0ff1..bc19d7a 100644
--- a/src/layout/navBars/topBar/index.vue
+++ b/src/layout/navBars/topBar/index.vue
@@ -3,9 +3,8 @@
-
-
+
@@ -81,11 +80,8 @@ const filterRoutesFun = (arr: T[]): T[] => {
.filter((item: T) => !item.meta?.isHide)
.map((item: T) => {
item = Object.assign({}, item)
- // 移除 children 以避免下拉菜单效果
- // if (item.children) item.children = filterRoutesFun(item.children)
- if (item.children) {
- delete (item as any).children // 删除子菜单数据以避免下拉效果
- }
+ // 恢复子菜单数据处理,支持下拉菜单功能
+ if (item.children) item.children = filterRoutesFun(item.children)
return item
})
}
diff --git a/src/layout/navMenu/horizontal.vue b/src/layout/navMenu/horizontal.vue
index b834fe2..4973b07 100644
--- a/src/layout/navMenu/horizontal.vue
+++ b/src/layout/navMenu/horizontal.vue
@@ -1,25 +1,34 @@
@@ -27,6 +36,7 @@
import { defineAsyncComponent, reactive, computed, onBeforeMount } from 'vue'
import { useRoute, onBeforeRouteUpdate, RouteRecordRaw, useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
+import { useI18n } from 'vue-i18n'
import { useRoutesList } from '/@/stores/routesList'
import { useThemeConfig } from '/@/stores/themeConfig'
import other from '/@/utils/other'
@@ -35,9 +45,10 @@ import { treeToList, listToTree, filterList } from '/@/utils/tree'
import { cloneDeep } from 'lodash-es'
const router = useRouter()
+const { t } = useI18n()
// 引入组件
-// const SubItem = defineAsyncComponent(() => import('/@/layout/navMenu/subItem.vue')) // 已移除下拉菜单,不再需要
+// const SubItem = defineAsyncComponent(() => import('/@/layout/navMenu/subItem.vue')) // 使用el-dropdown替代
// 定义父组件传过来的值
const props = defineProps({
@@ -56,12 +67,35 @@ const { themeConfig } = storeToRefs(storesThemeConfig)
const route = useRoute()
const state = reactive({
defaultActive: '' as string | undefined,
+ currentModulePath: '' as string,
})
// 获取父级菜单数据
const menuLists = computed(() => {
return props.menuList
})
+
+// 模块列表 - 将顶级菜单转换为模块选项
+const moduleList = computed(() => {
+ return menuLists.value.map(item => ({
+ path: item.path,
+ title: item.meta?.title ? t(item.meta.title) : '未命名模块',
+ icon: item.meta?.icon || 'ele-Menu'
+ }))
+})
+
+// 当前选中的模块
+const currentModule = computed(() => {
+ const current = moduleList.value.find(module =>
+ state.currentModulePath === module.path ||
+ route.path.startsWith(module.path)
+ )
+ return current || moduleList.value[0] || {
+ path: '',
+ title: '选择模块',
+ icon: 'ele-Menu'
+ }
+})
// 路由过滤递归函数
const filterRoutesFun = (arr: T[]): T[] => {
return arr
@@ -124,14 +158,80 @@ const setCurrentRouterHighlight = (currentRoute: RouteToFrom) => {
const onALinkClick = (val: RouteItem) => {
other.handleOpenLink(val)
}
+
+// 处理模块切换命令
+const onModuleCommand = (path: string) => {
+ // 更新当前模块路径
+ state.currentModulePath = path
+
+ // 查找选中的模块
+ const selectedModule = menuLists.value.find(item => item.path === path)
+ if (!selectedModule) return
+
+ // 如果是外部链接,使用原有的处理方式
+ if (selectedModule.meta?.isLink && !selectedModule.meta?.isIframe) {
+ onALinkClick(selectedModule)
+ return
+ }
+
+ // 如果模块有子菜单,跳转到第一个可用的子菜单
+ if (selectedModule.children && selectedModule.children.length > 0) {
+ const firstChild = selectedModule.children.find((child: RouteItem) => !child.meta?.isHide)
+ if (firstChild) {
+ router.push(firstChild.path)
+ } else {
+ router.push(selectedModule.path)
+ }
+ } else {
+ // 没有子菜单,直接跳转到模块根路径
+ router.push(selectedModule.path)
+ }
+
+ // 触发相关事件,保持原有的菜单切换效果
+ mittBus.emit('getBreadcrumbIndexSetFilterRoutes')
+ if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
+ mittBus.emit('setSendClassicChildren', setSendClassicChildren(path))
+ }
+}
+
+// 判断是否为当前模块
+const isCurrentModule = (path: string): boolean => {
+ return state.currentModulePath === path || route.path.startsWith(path)
+}
// 页面加载前
onBeforeMount(() => {
setCurrentRouterHighlight(route)
+ // 初始化当前模块
+ initCurrentModule()
})
+
+// 初始化当前模块
+const initCurrentModule = () => {
+ // 根据当前路由确定所属模块
+ const currentPath = route.path
+ const matchedModule = menuLists.value.find(module =>
+ currentPath.startsWith(module.path) && module.path !== '/'
+ )
+ if (matchedModule) {
+ state.currentModulePath = matchedModule.path
+ } else if (menuLists.value.length > 0) {
+ // 如果没有匹配的模块,默认选择第一个
+ state.currentModulePath = menuLists.value[0].path
+ }
+}
// 路由更新时
onBeforeRouteUpdate((to) => {
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
setCurrentRouterHighlight(to)
+
+ // 更新当前模块
+ const matchedModule = menuLists.value.find(module =>
+ to.path.startsWith(module.path) && module.path !== '/'
+ )
+ if (matchedModule) {
+ state.currentModulePath = matchedModule.path
+ }
+
// 修复经典布局开启切割菜单时,点击tagsView后左侧导航菜单数据不变的问题
let { layout, isClassicSplitMenu } = themeConfig.value
if (layout === 'classic' && isClassicSplitMenu) {
@@ -145,17 +245,100 @@ onBeforeRouteUpdate((to) => {
flex: 1;
overflow: hidden;
margin-right: 30px;
+ display: flex;
+ align-items: center;
+ height: 100%;
+
+ .module-dropdown {
+ .module-selector {
+ height: 50px;
+ line-height: 50px;
+ padding: 0 10px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ color: var(--next-bg-topBarColor);
+ background: transparent;
+ border: none;
+ border-radius: 6px;
+ font-size: 14px;
+ transition: all 0.3s;
+ white-space: nowrap;
+
+ .module-title {
+ font-weight: 500;
+ }
+
+ &:hover {
+ background: var(--next-color-user-hover);
+ color: var(--next-bg-topBarColor);
+ }
+ }
+ }
+
+ // 下拉菜单样式
+ :deep(.el-dropdown-menu) {
+ border-radius: 8px;
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
+ border: 1px solid var(--el-border-color-light);
+ min-width: 180px;
+
+ .el-dropdown-menu__item {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ transition: all 0.3s;
+ border-radius: 6px;
+ margin: 4px 6px;
+
+ .dropdown-icon {
+ margin-right: 10px;
+ font-size: 16px;
+ width: 16px;
+ height: 16px;
+ }
+
+ &:hover {
+ background: var(--next-color-user-hover);
+ color: var(--next-bg-topBarColor);
+ }
+
+ &.is-active {
+ background: var(--next-color-user-hover);
+ color: var(--next-bg-topBarColor);
+ font-weight: 600;
+
+ .dropdown-icon {
+ color: var(--next-bg-topBarColor);
+ }
+ }
+ }
+ }
+
+ // 兼容原有样式
:deep(.el-scrollbar__bar.is-vertical) {
display: none;
}
:deep(a) {
width: 100%;
}
- .el-menu.el-menu--horizontal {
- display: flex;
- height: 100%;
- width: 100%;
- box-sizing: border-box;
+
+ // 响应式设计
+ @media (max-width: 768px) {
+ .module-dropdown {
+ .module-selector {
+ padding: 0 12px;
+ height: 40px;
+ line-height: 40px;
+ font-size: 14px;
+
+ .module-title {
+ margin-left: 6px;
+ margin-right: 6px;
+ }
+ }
+ }
}
}
diff --git a/src/theme/element.scss b/src/theme/element.scss
index 1238425..9539059 100644
--- a/src/theme/element.scss
+++ b/src/theme/element.scss
@@ -385,17 +385,13 @@
padding: 0px;
}
-/* 隐藏水平菜单的下拉效果 */
+/* 水平菜单下拉样式优化 */
.el-menu--horizontal {
.el-sub-menu .el-sub-menu__icon-arrow {
- display: none !important; /* 隐藏下拉箭头 */
+ transition: transform 0.3s;
}
- .el-sub-menu__title:hover + .el-menu {
- display: none !important; /* 隐藏下拉菜单 */
- }
-
- .el-popper.is-pure.is-light {
- display: none !important; /* 完全隐藏下拉弹出层 */
+ .el-sub-menu.is-opened .el-sub-menu__icon-arrow {
+ transform: rotate(180deg);
}
}