code 提交

This commit is contained in:
Asoka 2025-06-04 19:49:15 +08:00
parent d7e3a153dc
commit 87b8bd47dc
3 changed files with 246 additions and 15 deletions

View File

@ -1,19 +1,24 @@
<template>
<div class="layout-navbars-breadcrumb-index" :class="setBreadcrumbStyle">
<div class="left-section">
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="state.menuList" v-if="isLayoutTransverse" />
</div>
<div class="right-section">
<ModuleSwitch :menuList="state.menuList" />
<User />
</div>
</div>
</template>
<script setup lang="ts" name="layoutBreadcrumbIndex">
import { defineAsyncComponent, computed, reactive, onMounted, onUnmounted } from 'vue'
import { useRoute } from 'vue-router'
import { defineAsyncComponent, computed, reactive, onMounted, onUnmounted, onBeforeMount } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useRoutesList } from '/@/stores/routesList'
import { useThemeConfig } from '/@/stores/themeConfig'
import mittBus from '/@/utils/mitt'
import ModuleSwitch from './module-switch.vue'
//
const Breadcrumb = defineAsyncComponent(() => import('/@/layout/navBars/topBar/breadcrumb.vue'))
@ -21,12 +26,17 @@ const User = defineAsyncComponent(() => import('/@/layout/navBars/topBar/user.vu
const Logo = defineAsyncComponent(() => import('/@/layout/logo/index.vue'))
const Horizontal = defineAsyncComponent(() => import('/@/layout/navMenu/horizontal.vue'))
//
// props menuList
const props = defineProps<{
menuList?: RouteItems
}>()
const router = useRouter()
const route = useRoute()
const stores = useRoutesList()
const storesThemeConfig = useThemeConfig()
const { themeConfig } = storeToRefs(storesThemeConfig)
const { routesList } = storeToRefs(stores)
const route = useRoute()
const { themeConfig } = storeToRefs(storesThemeConfig)
const state = reactive({
menuList: [] as RouteItems,
})
@ -89,17 +99,45 @@ const setSendClassicChildren = (path: string) => {
})
return currentData
}
// props.menuList fallback layout.children
const topModules = computed<RouteItem[]>(() => {
if (props.menuList && props.menuList.length) {
return filterRoutesFun(props.menuList)
}
const layout = routesList.value.find((item: RouteItem) => item.path === '/')
if (!layout || !layout.children) return []
return filterRoutesFun(layout.children)
})
const onModuleChange = (path: string) => {
router.push(path)
mittBus.emit('getBreadcrumbIndexSetFilterRoutes')
if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
mittBus.emit('setSendClassicChildren', path)
}
}
//
onMounted(() => {
setFilterRoutes()
mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => {
setFilterRoutes()
})
if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
mittBus.emit('setSendClassicChildren', route.path)
}
})
//
onUnmounted(() => {
mittBus.off('getBreadcrumbIndexSetFilterRoutes', () => {})
})
onBeforeMount(() => {
if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
mittBus.emit('setSendClassicChildren', route.path)
}
})
</script>
<style scoped lang="scss">
@ -107,9 +145,23 @@ onUnmounted(() => {
height: 50px;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--next-bg-topBar);
border-bottom: 1px solid var(--next-border-color-light);
.left-section {
display: flex;
align-items: center;
}
.right-section {
display: flex;
align-items: center;
gap: 16px;
margin-right: 16px;
}
}
.layout-navbars-breadcrumb-index-no-bb {
border-bottom-width: 0px;
}

View File

@ -0,0 +1,180 @@
<template>
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onMenuChange">
<div class="layout-navbars-breadcrumb-user-icon">
<i class="iconfont icon-diqiu" :title="$t('message.user.title1')"></i>
<span class="current-lang">{{ currentModuleName }}</span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="item in menuLists as RouteItem[]" :key="item.path || ''" :command="item.path || ''">
<SvgIcon :name="item.meta?.icon" />
{{ $t(item.meta?.title || '未命名模块') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts" name="navMenuHorizontal">
import { defineAsyncComponent, reactive, computed, onBeforeMount, watch } from 'vue'
import { useRoute, onBeforeRouteUpdate, RouteRecordRaw, useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useRoutesList } from '/@/stores/routesList'
import { useThemeConfig } from '/@/stores/themeConfig'
import other from '/@/utils/other'
import mittBus from '/@/utils/mitt'
import { treeToList, listToTree, filterList } from '/@/utils/tree'
import { cloneDeep } from 'lodash-es'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const router = useRouter()
//
const SubItem = defineAsyncComponent(() => import('/@/layout/navMenu/subItem.vue'))
//
const props = defineProps({
//
menuList: {
type: Array<RouteRecordRaw>,
default: () => [],
},
})
//
const stores = useRoutesList()
const storesThemeConfig = useThemeConfig()
const { routesList } = storeToRefs(stores)
const { themeConfig } = storeToRefs(storesThemeConfig)
const route = useRoute()
const state = reactive({
defaultActive: '' as string | undefined,
currentModuleName: '' as string,
})
//
const menuLists = computed(() => {
return <RouteItems>props.menuList
})
const onMenuChange = (path: string) => {
console.log('path', path)
}
//
const filterRoutesFun = <T extends RouteItem>(arr: T[]): T[] => {
return arr
.filter((item: T) => !item.meta?.isHide)
.map((item: T) => {
item = Object.assign({}, item)
if (item.children) item.children = filterRoutesFun(item.children)
return item
})
}
//
const getRootPath = (path: string) => {
let rootPath = ''
let routeTree = listToTree(
filterList(treeToList(cloneDeep(routesList.value)), path, {
filterWhere: (item: any, filterword: string) => {
return item.path?.toLocaleLowerCase() === filterword
},
})
)
if (routeTree.length > 0 && routeTree[0]?.path) {
rootPath = routeTree[0].path
}
return rootPath
}
//
const setSendClassicChildren = (path: string) => {
let rootPath = getRootPath(path)
rootPath = rootPath || path
const currentPathSplit = rootPath.split('/')
let currentData: MittMenu = { children: [] }
filterRoutesFun(routesList.value).map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v['k'] = k
currentData['item'] = { ...v }
currentData['children'] = [{ ...v }]
if (v.children) currentData['children'] = v.children
}
})
return currentData
}
//
const setCurrentRouterHighlight = (currentRoute: RouteToFrom) => {
console.log('currentRoute', currentRoute)
const { path, meta } = currentRoute
if (themeConfig.value.layout === 'classic') {
let rootPath = getRootPath(path || '')
rootPath = rootPath || path || ''
setCurrentModuleName(`/${rootPath?.split('/')[1]}` || '')
state.defaultActive = `/${rootPath?.split('/')[1]}`
if (!state.defaultActive || state.defaultActive === '/') router.push(routesList.value[0].path)
} else {
const pathSplit = meta?.isDynamic ? meta.isDynamicPath!.split('/') : path!.split('/')
if (pathSplit.length >= 4 && meta?.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/')
else state.defaultActive = path
}
}
//
onBeforeMount(() => {
setCurrentRouterHighlight(route)
})
//
onBeforeRouteUpdate((to) => {
// https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
setCurrentRouterHighlight(to)
// tagsView
let { layout, isClassicSplitMenu } = themeConfig.value
if (layout === 'classic' && isClassicSplitMenu) {
mittBus.emit('setSendClassicChildren', setSendClassicChildren(to.path))
}
})
</script>
<style scoped lang="scss">
.el-menu-horizontal-warp {
flex: 1;
overflow: hidden;
margin-right: 30px;
: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;
}
}
.layout-navbars-breadcrumb-user-icon {
display: flex;
align-items: center;
gap: 8px;
.module-name {
font-size: 14px;
color: var(--el-text-color-primary);
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>

View File

@ -15,12 +15,6 @@
<SvgIcon :name="val.meta.icon" />
{{ $t(val.meta.title) }}
</template>
<template #title v-else>
<a class="w100" @click.prevent="onALinkClick(val)">
<SvgIcon :name="val.meta.icon" />
{{ $t(val.meta.title) }}
</a>
</template>
</el-menu-item>
</template>
</template>
@ -113,8 +107,12 @@ const setSendClassicChildren = (path: string) => {
}
//
const setCurrentRouterHighlight = (currentRoute: RouteToFrom) => {
console.log('currentRoute', currentRoute)
const { path, meta } = currentRoute
if (themeConfig.value.layout === 'classic') {
console.log('themeConfig.value.layout', themeConfig.value.layout)
let rootPath = getRootPath(path || '')
rootPath = rootPath || path || ''
state.defaultActive = `/${rootPath?.split('/')[1]}`
@ -135,6 +133,7 @@ onBeforeMount(() => {
})
//
onBeforeRouteUpdate((to) => {
console.log('to', to)
// https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
setCurrentRouterHighlight(to)
// tagsView