123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <template>
- <div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb">
- <SvgIcon
- :name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
- :size="16"
- class="layout-navbars-breadcrumb-icon"
- @click="onThemeConfigChange"
- />
- <el-breadcrumb class="layout-navbars-breadcrumb-hide">
- <transition-group name="breadcrumb">
- <el-breadcrumb-item v-for="(v, k) in state.breadcrumbList"
- :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
- <span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
- <SvgIcon v-if="themeConfig.isBreadcrumbIcon" :name="v.meta.icon"
- class="layout-navbars-breadcrumb-iconfont"/>
- <div v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div>
- <div v-else>{{ v.meta.tagsViewName }}</div>
- </span>
- <a v-else @click.prevent="onBreadcrumbClick(v)" class="flex">
- <SvgIcon v-if="themeConfig.isBreadcrumbIcon" :name="v.meta.icon"
- class="layout-navbars-breadcrumb-iconfont"/>
- <span >
- {{ $t(v.meta.title) }}
- </span>
- </a>
- </el-breadcrumb-item>
- </transition-group>
- </el-breadcrumb>
- </div>
- </template>
- <script lang="ts" name="layoutBreadcrumb" setup>
- import { reactive, computed, onMounted } from 'vue';
- import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
- import { Local } from '/@/utils/storage';
- import other from '/@/utils/other';
- import { storeToRefs } from 'pinia';
- import { useThemeConfig } from '/@/stores/themeConfig';
- import { useRoutesList } from '/@/stores/routesList';
- // 定义变量内容
- const stores = useRoutesList();
- const storesThemeConfig = useThemeConfig();
- const { themeConfig } = storeToRefs(storesThemeConfig);
- const { routesList } = storeToRefs(stores);
- const route = useRoute();
- const router = useRouter();
- const state = reactive<BreadcrumbState>({
- breadcrumbList: [],
- routeSplit: [],
- routeSplitFirst: '',
- routeSplitIndex: 1
- });
- // 动态设置经典、横向布局不显示
- const isShowBreadcrumb = computed(() => {
- initRouteSplit(route.path);
- const { layout, isBreadcrumb } = themeConfig.value;
- if (layout === 'classic' || layout === 'transverse') return false;
- else return isBreadcrumb ? true : false;
- });
- // 面包屑点击时
- const onBreadcrumbClick = (v: RouteItem) => {
- const { redirect, path } = v;
- if (redirect) router.push(redirect);
- else router.push(path);
- };
- // 展开/收起左侧菜单点击
- const onThemeConfigChange = () => {
- themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
- setLocalThemeConfig();
- };
- // 存储布局配置
- const setLocalThemeConfig = () => {
- Local.remove('themeConfig');
- Local.set('themeConfig', themeConfig.value);
- };
- // 处理面包屑数据
- const getBreadcrumbList = (arr: RouteItems) => {
- arr.forEach((item: RouteItem) => {
- state.routeSplit.forEach((v: string, k: number, arrs: string[]) => {
- if (state.routeSplitFirst === item.path) {
- state.routeSplitFirst += `/${ arrs[state.routeSplitIndex] }`;
- state.breadcrumbList.push(item);
- state.routeSplitIndex++;
- if (item.children) getBreadcrumbList(item.children);
- }
- });
- });
- };
- // 当前路由字符串切割成数组,并删除第一项空内容
- const initRouteSplit = (path: string) => {
- if (!themeConfig.value.isBreadcrumb) return false;
- state.breadcrumbList = [ routesList.value[0] ];
- state.routeSplit = path.split('/');
- state.routeSplit.shift();
- state.routeSplitFirst = `/${ state.routeSplit[0] }`;
- state.routeSplitIndex = 1;
- getBreadcrumbList(routesList.value);
- if (route.name === 'home' || (route.name === 'notFound' && state.breadcrumbList.length > 1)) state.breadcrumbList.shift();
- if (state.breadcrumbList.length > 0)
- state.breadcrumbList[state.breadcrumbList.length - 1].meta.tagsViewName = other.setTagsViewNameI18n(<RouteToFrom>route);
- };
- // 页面加载时
- onMounted(() => {
- initRouteSplit(route.path);
- });
- // 路由更新时
- onBeforeRouteUpdate((to) => {
- initRouteSplit(to.path);
- });
- </script>
- <style lang="scss" scoped>
- .layout-navbars-breadcrumb {
- flex: 1;
- height: inherit;
- display: flex;
- align-items: center;
- .layout-navbars-breadcrumb-icon {
- cursor: pointer;
- font-size: 18px;
- color: var(--next-bg-topBarColor);
- height: 100%;
- width: 40px;
- opacity: 0.8;
- &:hover {
- opacity: 1;
- }
- }
- .layout-navbars-breadcrumb-span {
- display: flex;
- opacity: 0.7;
- color: var(--next-bg-topBarColor);
- }
- .layout-navbars-breadcrumb-iconfont {
- font-size: 14px;
- margin-right: 5px;
- }
- :deep(.el-breadcrumb__separator) {
- opacity: 0.7;
- color: var(--next-bg-topBarColor);
- }
- :deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
- font-weight: unset !important;
- color: var(--next-bg-topBarColor);
- &:hover {
- color: var(--el-color-primary) !important;
- }
- }
- }
- </style>
|