refactor: 样式优化

This commit is contained in:
meilin.huang
2025-08-04 21:02:27 +08:00
parent 7d344c71e1
commit 614a144f60
38 changed files with 274 additions and 313 deletions

View File

@@ -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>