162 lines
4.8 KiB
Vue

<template>
<div class="layout-navbars-breadcrumb-index" :class="setBreadcrumbStyle">
<div class="left-section">
<Logo v-if="setIsShowLogo" />
</div>
<Horizontal :menuList="state.menuList" />
<div class="right-section">
<User />
</div>
</div>
</template>
<script setup lang="ts" name="layoutBreadcrumbIndex">
import { defineAsyncComponent, computed, reactive, onMounted, onUnmounted, onBeforeMount } from 'vue'
import { useRoute, useRouter, RouteRecordRaw } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useRoutesList } from '/@/stores/routesList'
import { useThemeConfig } from '/@/stores/themeConfig'
import mittBus from '/@/utils/mitt'
import { treeToList, listToTree, filterList } from '/@/utils/tree'
import { cloneDeep } from 'lodash-es'
// 引入组件
const User = defineAsyncComponent(() => import('/@/layout/navBars/topBar/user.vue'))
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 { routesList } = storeToRefs(stores)
const { themeConfig } = storeToRefs(storesThemeConfig)
const state = reactive({
menuList: [] as RouteItems,
})
const setBreadcrumbStyle = computed(() => {
const { topBar } = themeConfig.value
const bgTheme = ['#FFFFFF', '#FFF', '#fff', '#ffffff']
return [bgTheme.includes(topBar) ? '' : 'layout-navbars-breadcrumb-index-no-bb']
})
// 设置 logo 显示/隐藏
const setIsShowLogo = computed(() => {
let { isShowLogo, layout } = themeConfig.value
return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse')
})
// 设置/过滤路由(非静态路由/是否显示在菜单中)
const setFilterRoutes = () => {
let { layout, isClassicSplitMenu } = themeConfig.value
if (layout === 'classic' && isClassicSplitMenu) {
// 为了支持下拉菜单,我们保留完整的菜单结构给 horizontal 组件
// 但仍然发送分割后的数据给侧边栏
state.menuList = filterRoutesFun(routesList.value) // 保留完整结构用于下拉菜单
const resData = setSendClassicChildren(route.path)
//console.log('设置/过滤路由', resData)
//mittBus.emit('setSendClassicChildren', resData)
} else {
state.menuList = filterRoutesFun(routesList.value)
}
}
// 路由过滤递归函数
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 res: MittMenu = { children: [] }
//解析菜单路径
const rootPath = getRootPath(path)
const module = state.menuList.find(item => item.path === rootPath)
if (module && module.children) {
const sub = module.children.find((child: RouteRecordRaw) => path.startsWith(child.path))
if (sub) {
res.item = { ...sub }
res.children = sub.children ? [...sub.children] : []
}
}
return res
}
// 页面加载时
onMounted(() => {
setFilterRoutes()
if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
mittBus.emit('setSendClassicChildren', setSendClassicChildren(route.path))
}
})
// 页面卸载时
onUnmounted(() => {
mittBus.off('getBreadcrumbIndexSetFilterRoutes', () => {})
})
onBeforeMount(() => {
if (themeConfig.value.layout === 'classic' && themeConfig.value.isClassicSplitMenu) {
//console.log('onBeforeMount11122', route.path)
//mittBus.emit('setSendClassicChildren', route.path)
}
})
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-index {
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;
}
</style>