Commit 903c29de by ningjihai

顶部菜单

parent b6f46f4e
<template> <template>
<div v-if="!item.hidden"> <div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow"> <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link :to="resolvePath(onlyOneChild.path, onlyOneChild.query)"> <app-link :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
<el-menu-item style="height: 80px;" :index="resolvePath(onlyOneChild.path)" @click="pageLuyou(onlyOneChild)"> <el-menu-item
style="height: 80px;"
:index="resolvePath(onlyOneChild.path)"
@click="handleNoChildrenClick(item)"
>
<svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/> <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>
<span class="menu-title" style="color: #fff;">{{ onlyOneChild.meta.title }}</span> <span class="menu-title" style="color: #fff;">{{ onlyOneChild.meta.title }}</span>
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
<el-sub-menu style="height: 80px;line-height: 80px;" v-else :index="resolvePath(item.path)" teleported> <el-menu-item
<template v-if="item.meta" #title> v-else
style="height: 80px;"
:index="resolvePath(item.path)"
@click="handleItemClick(item)"
>
<svg-icon :icon-class="item.meta && item.meta.icon" /> <svg-icon :icon-class="item.meta && item.meta.icon" />
<span class="menu-title" style="color: #fff;">{{ item.meta.title }}</span> <span class="menu-title" style="color: #fff;">{{ item.meta.title }}</span>
</template> </el-menu-item>
<sidebar-item
v-for="(child, index) in item.children"
:key="child.path + index"
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-sub-menu>
</div> </div>
</template> </template>
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
import { isExternal } from '@/utils/validate' import { isExternal } from '@/utils/validate'
import AppLink from './Link' import AppLink from './Link'
import { getNormalPath } from '@/utils/ruoyi' import { getNormalPath } from '@/utils/ruoyi'
import { ref } from 'vue'
const props = defineProps({ const props = defineProps({
// route object // route object
...@@ -45,11 +47,36 @@ const props = defineProps({ ...@@ -45,11 +47,36 @@ const props = defineProps({
} }
}) })
const emit = defineEmits(['parent-click','no-children-click'])
const onlyOneChild = ref({}) const onlyOneChild = ref({})
function handleItemClick(item) {
if (item.children && item.children.length > 0) {
const visibleChildren = item.children.map(child => ({
...child,
fullPath: getNormalPath(props.basePath + '/' + child.path) // 添加完整路径
})).filter(child => !child.hidden)
if (visibleChildren.length > 0) {
emit('parent-click', visibleChildren)
} else {
emit('no-children-click')
}
} else {
emit('no-children-click')
}
pageLuyou(item)
}
function handleNoChildrenClick(item) {
emit('no-children-click')
pageLuyou(item)
}
function pageLuyou(route) { function pageLuyou(route) {
console.log(route) console.log('导航到:', route)
} }
...@@ -65,12 +92,10 @@ function hasOneShowingChild(children = [], parent) { ...@@ -65,12 +92,10 @@ function hasOneShowingChild(children = [], parent) {
return true return true
}) })
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) { if (showingChildren.length === 1) {
return true return true
} }
// Show parent if there are no child router to display
if (showingChildren.length === 0) { if (showingChildren.length === 0) {
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
return true return true
...@@ -88,16 +113,11 @@ function resolvePath(routePath, routeQuery) { ...@@ -88,16 +113,11 @@ function resolvePath(routePath, routeQuery) {
} }
if (routeQuery) { if (routeQuery) {
let query = JSON.parse(routeQuery) let query = JSON.parse(routeQuery)
return { path: getNormalPath(props.basePath + '/' + routePath), query: query } return {
path: getNormalPath(props.basePath + '/' + routePath),
query: query
} }
return getNormalPath(props.basePath + '/' + routePath)
}
function hasTitle(title){
if (title.length > 5) {
return title
} else {
return ""
} }
return getNormalPath(props.basePath + '/' + routePath)
} }
</script> </script>
\ No newline at end of file
...@@ -9,16 +9,35 @@ ...@@ -9,16 +9,35 @@
:text-color="getMenuTextColor" :text-color="getMenuTextColor"
:active-text-color="'#fff'" :active-text-color="'#fff'"
:unique-opened="false" :unique-opened="false"
:ellipsis="false"
> >
<sidebar-item <sidebar-item
v-for="(route, index) in menuShowData" v-for="(route, index) in menuShowData"
:key="route.id || route.path + index" :key="route.id || route.path + index"
:item="route" :item="route"
:base-path="route.path" :base-path="route.path"
@parent-click="handleParentClick"
@no-children-click="handleNoChildrenClick"
/> />
</el-menu> </el-menu>
</el-scrollbar> </el-scrollbar>
<!-- 子菜单容器 -->
<div v-if="submenuItems.length > 0" class="submenu-container">
<div class="submenu-wrapper">
<template v-for="(child, index) in submenuItems" :key="child.path + index">
<div v-if="!child.hidden" class="submenu-item" :class="[child.fullPath === route.fullPath ? 'active-submenu-item' : '']" >
<app-link :to="child.fullPath"> <!-- 使用完整路径 -->
<div class="submenu-link" >
<svg-icon :icon-class="child.meta.icon" />
<span>{{ child.meta.title }}</span>
</div>
</app-link>
</div>
</template>
</div>
</div>
<div class="right-menu"> <div class="right-menu">
<!-- 这里可以放用户信息、设置按钮等 --> <!-- 这里可以放用户信息、设置按钮等 -->
<header-search id="header-search" class="right-menu-item" /> <header-search id="header-search" class="right-menu-item" />
...@@ -45,18 +64,22 @@ ...@@ -45,18 +64,22 @@
</template> </template>
<script setup> <script setup>
import { isExternal } from '@/utils/validate'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import HeaderSearch from '@/components/HeaderSearch' import HeaderSearch from '@/components/HeaderSearch'
import Logo from './Logo' import Logo from './Logo'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
import AppLink from './Link'
import variables from '@/assets/styles/variables.module.scss' import variables from '@/assets/styles/variables.module.scss'
import useAppStore from '@/store/modules/app' import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings' import useSettingsStore from '@/store/modules/settings'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import usePermissionStore from '@/store/modules/permission' import usePermissionStore from '@/store/modules/permission'
import { computed } from 'vue' import { ref, computed } from 'vue'
import { getNormalPath } from '@/utils/ruoyi'
import { useRoute } from 'vue-router'
const route = useRoute() const route = useRoute()
const submenuItems = ref([])
const appStore = useAppStore() const appStore = useAppStore()
const userStore = useUserStore() const userStore = useUserStore()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
...@@ -73,6 +96,31 @@ const navType = computed(() => { ...@@ -73,6 +96,31 @@ const navType = computed(() => {
return type return type
}) })
function handleParentClick(children) {
submenuItems.value = children
}
function handleNoChildrenClick() {
submenuItems.value = []
}
const activeMenuItem = ref(null)
function handleChild(child) {
}
function resolvePath(routePath, routeQuery) {
// 您的路径解析逻辑
if (isExternal(routePath)) {
return routePath
}
if (routeQuery) {
let query = JSON.parse(routeQuery)
return { path: getNormalPath(routePath), query: query }
}
return getNormalPath(routePath)
}
// 菜单显示数据 // 菜单显示数据
const menuShowData = computed(() => { const menuShowData = computed(() => {
const list = processedRouters.value.filter(item => { const list = processedRouters.value.filter(item => {
...@@ -168,20 +216,26 @@ function logout() { ...@@ -168,20 +216,26 @@ function logout() {
display: flex; display: flex;
align-items: center; align-items: center;
height: var(--navbar-height); height: var(--navbar-height);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
.navbar-logo { .navbar-logo {
flex-shrink: 0; flex-shrink: 0;
// width: vars.$base-sidebar-width; height: 80px;
height: 100%; width: 300px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: absolute;
top: 0;
left: 0;
} }
.scrollbar-wrapper { .scrollbar-wrapper {
margin: 0 300px;
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
// padding-right: 83px;
display: flex;
justify-content: center;
:deep(.el-scrollbar__view) { :deep(.el-scrollbar__view) {
height: 100%; height: 100%;
...@@ -198,11 +252,43 @@ function logout() { ...@@ -198,11 +252,43 @@ function logout() {
} }
.right-menu { .right-menu {
position: absolute;
top: 0;
right: 0;
height: 80px;
display: flex; display: flex;
flex-shrink: 0; align-items: center;
padding-right: 15px;
}
} }
}
.submenu-container {
position: absolute;
left: 0;
top: 80px;
width: 100%;
height: 50px;
.submenu-wrapper {
height: 100%;
background: rgba(255, 255, 255, 1);
display: flex;
justify-content: center;
align-items: center;
.submenu-item {
margin-left: 66px;
&:first-child {
margin-left: 0;
}
&:hover {
color: rgba(33, 103, 217, 1);
cursor: pointer;
}
}
.active-submenu-item {
color: rgba(33, 103, 217, 1);
cursor: pointer;
}
}
}
.avatar-container { .avatar-container {
margin-right: 0px; margin-right: 0px;
...@@ -237,4 +323,7 @@ function logout() { ...@@ -237,4 +323,7 @@ function logout() {
} }
} }
} }
</style> </style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论