mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-12-11 02:10:25 +08:00
refactor: 样式优化
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
<template>
|
||||
<div class="layout-navbars-breadcrumb" v-show="themeConfig.isBreadcrumb">
|
||||
<SvgIcon class="layout-navbars-breadcrumb-icon" :name="themeConfig.isCollapse ? 'expand' : 'fold'" @click="onThemeConfigChange" />
|
||||
<div class="flex flex-1 h-inherit items-center pl-4" v-show="themeConfig.isBreadcrumb">
|
||||
<SvgIcon
|
||||
class="cursor-pointer text-18px mr-4 text-[var(--bg-topBarColor)]"
|
||||
:name="themeConfig.isCollapse ? 'expand' : 'fold'"
|
||||
@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.title">
|
||||
<span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
<span v-if="k === state.breadcrumbList.length - 1 || (!v.redirect && !v.component)" class="opacity-70 text-[var(--bg-topBarColor)]">
|
||||
<SvgIcon :name="v.meta.icon" class="text-14px mr-1.25" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
{{ $t(v.meta.title) }}
|
||||
</span>
|
||||
<a v-else @click.prevent="onBreadcrumbClick(v)">
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
<a v-else @click.prevent="onBreadcrumbClick(v)" class="opacity-100 text-[var(--bg-topBarColor)] hover:opacity-100">
|
||||
<SvgIcon :name="v.meta.icon" class="text-14px mr-1.25" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
{{ $t(v.meta.title) }}
|
||||
</a>
|
||||
</el-breadcrumb-item>
|
||||
@@ -29,84 +33,99 @@ const { themeConfig } = storeToRefs(useThemeConfig());
|
||||
const { routesList } = storeToRefs(useRoutesList());
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state: any = reactive({
|
||||
breadcrumbList: [],
|
||||
routeSplit: [],
|
||||
routeSplitFirst: '',
|
||||
routeSplitIndex: 1,
|
||||
const state = reactive({
|
||||
breadcrumbList: [] as any[],
|
||||
});
|
||||
|
||||
// 面包屑点击时
|
||||
const onBreadcrumbClick = (v: any) => {
|
||||
const { redirect, path } = v;
|
||||
if (redirect) router.push(redirect);
|
||||
else router.push(path);
|
||||
if (redirect) {
|
||||
router.push(redirect);
|
||||
return;
|
||||
}
|
||||
if (v.component) {
|
||||
router.push(path);
|
||||
}
|
||||
};
|
||||
// 展开/收起左侧菜单点击
|
||||
const onThemeConfigChange = () => {
|
||||
themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
|
||||
};
|
||||
// 处理面包屑数据
|
||||
const getBreadcrumbList = (arr: Array<object>) => {
|
||||
arr.map((item: any) => {
|
||||
state.routeSplit.map((v: any, k: number, arrs: any) => {
|
||||
if (state.routeSplitFirst === item.path) {
|
||||
state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`;
|
||||
state.breadcrumbList.push(item);
|
||||
state.routeSplitIndex++;
|
||||
if (item.children) getBreadcrumbList(item.children);
|
||||
|
||||
// 根据当前路径生成面包屑列表
|
||||
const generateBreadcrumbList = (currentPath: string) => {
|
||||
if (!themeConfig.value.isBreadcrumb) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化面包屑列表,包含首页
|
||||
const homeRoute = routesList.value.length > 0 ? routesList.value[0] : null;
|
||||
const breadcrumbList = homeRoute ? [homeRoute] : [];
|
||||
|
||||
// 查找匹配的路由及其所有父级路由(除了首页)
|
||||
if (homeRoute && currentPath !== homeRoute.path) {
|
||||
const matchedRoutes = findMatchedRoutes(routesList.value, currentPath);
|
||||
// 如果找到匹配的路由,添加到面包屑列表中(排除首页,避免重复)
|
||||
if (matchedRoutes.length > 0) {
|
||||
// 过滤掉首页路由,避免重复添加
|
||||
const filteredRoutes = matchedRoutes.filter((r) => r !== homeRoute);
|
||||
breadcrumbList.push(...filteredRoutes);
|
||||
}
|
||||
}
|
||||
|
||||
state.breadcrumbList = breadcrumbList;
|
||||
};
|
||||
|
||||
// 在路由树中查找匹配当前路径的路由,并返回该路由及其所有父级路由
|
||||
const findMatchedRoutes = (routes: any[], currentPath: string): any[] => {
|
||||
for (const route of routes) {
|
||||
// 精确匹配
|
||||
if (route.path === currentPath) {
|
||||
return [route];
|
||||
}
|
||||
|
||||
// 前缀匹配且有子路由
|
||||
if (currentPath.startsWith(route.path + '/') && route.children) {
|
||||
const matchedChildren = findMatchedRoutes(route.children, currentPath);
|
||||
if (matchedChildren.length > 0) {
|
||||
return [route, ...matchedChildren];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
// 当前路由字符串切割成数组,并删除第一项空内容
|
||||
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.path === '/' && route.children) {
|
||||
const matchedChildren = findMatchedRoutes(route.children, currentPath);
|
||||
if (matchedChildren.length > 0) {
|
||||
return [route, ...matchedChildren];
|
||||
}
|
||||
}
|
||||
|
||||
// 递归查找子路由
|
||||
if (route.children) {
|
||||
const matchedChildren = findMatchedRoutes(route.children, currentPath);
|
||||
if (matchedChildren.length > 0) {
|
||||
return [route, ...matchedChildren];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initRouteSplit(route.path);
|
||||
generateBreadcrumbList(route.path);
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
initRouteSplit(to.path);
|
||||
generateBreadcrumbList(to.path);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout-navbars-breadcrumb {
|
||||
flex: 1;
|
||||
height: inherit;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 15px;
|
||||
|
||||
.layout-navbars-breadcrumb-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
margin-right: 15px;
|
||||
color: var(--bg-topBarColor);
|
||||
}
|
||||
|
||||
.layout-navbars-breadcrumb-span {
|
||||
opacity: 0.7;
|
||||
color: var(--bg-topBarColor);
|
||||
}
|
||||
|
||||
.layout-navbars-breadcrumb-iconfont {
|
||||
font-size: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
::v-deep(.el-breadcrumb__separator) {
|
||||
opacity: 0.7;
|
||||
color: var(--bg-topBarColor);
|
||||
}
|
||||
<style scoped>
|
||||
::v-deep(.el-breadcrumb__separator) {
|
||||
opacity: 0.7;
|
||||
color: var(--bg-topBarColor);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user