【功能优化】修改面包屑组件至顶部,统一面包屑组件至layout,增加tags页签简单功能

This commit is contained in:
97
2025-04-25 23:22:35 +08:00
parent 76c1918685
commit c0599a0fd0
20 changed files with 166 additions and 65 deletions
@@ -0,0 +1,46 @@
<template>
<a-breadcrumb :routes="routes">
<template #itemRender="{ route, routes }">
<span v-if="isLastRoute(route, routes)">{{ route.breadcrumbName }}</span>
<router-link v-else :to="route.path">{{ route.breadcrumbName }}</router-link>
</template>
</a-breadcrumb>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { useRoute } from "vue-router";
interface BreadcrumbRoute {
path: string;
breadcrumbName?: string;
}
const route = useRoute();
const routes = ref<BreadcrumbRoute[]>([]);
const isLastRoute = (currentRoute: BreadcrumbRoute, allRoutes: BreadcrumbRoute[]) => {
return allRoutes.indexOf(currentRoute) === allRoutes.length - 1;
};
const getBreadcrumb = () => {
const matchedRoutes = route.matched
.filter((_, index) => index > 0) // 跳过第一个匹配项
.map(item => ({
path: item.path,
breadcrumbName: item.meta.title?.toString()
}));
routes.value = matchedRoutes.length > 1 ? matchedRoutes : [];
};
// 初始化并监听路由变化
watch(() => route.path, getBreadcrumb, { immediate: true });
</script>
<style scoped>
/* 可以添加一些样式优化 */
.a-breadcrumb {
margin: 12px 0;
}
</style>
+96
View File
@@ -0,0 +1,96 @@
<template>
<a-tabs
v-model:activeKey="activeKey"
hide-add
:animated="false"
type="editable-card"
@edit="onEdit"
@change="onChange"
>
<a-tab-pane
v-for="pane in panes"
:key="pane.key"
:tab="pane.title"
:closable="pane.closable"
/>
</a-tabs>
</template>
<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from "vue-router";
interface Pane {
title: string;
path: string;
key: string;
closable?: boolean;
}
const router = useRouter();
const route = useRoute();
const panes = ref<Pane[]>([
{
title: '工作台',
path: '/dashboard/workplace',
key: '/dashboard/workplace',
closable: false
}
]);
const activeKey = ref(panes.value[0].key);
const getRoute = () => {
const existingPane = panes.value.some(pane => pane.key === route.path);
if (!existingPane) {
panes.value.push({
title: route.meta.title?.toString() || '未命名',
path: route.path,
key: route.path,
closable: true
});
}
activeKey.value = route.path;
}
const removePane = (targetKey: string) => {
const paneIndex = panes.value.findIndex(pane => pane.key === targetKey);
panes.value = panes.value.filter(pane => pane.key !== targetKey);
if (activeKey.value === targetKey && panes.value.length) {
const newIndex = Math.max(0, paneIndex - 1);
activeKey.value = panes.value[newIndex].key;
router.push(activeKey.value);
}
};
const onEdit = (targetKey: string | MouseEvent, action: string) => {
if (action === 'remove') {
removePane(targetKey as string);
}
};
const onChange = (targetKey: string) => {
router.push(targetKey);
};
onMounted(getRoute);
watch(() => route.path, getRoute);
</script>
<style scoped>
/* 添加以下样式 */
:deep(.ant-tabs-nav) {
will-change: transform;
backface-visibility: hidden;
}
:deep(.ant-tabs-tab) {
transition: none !important;
}
:deep(.ant-tabs-ink-bar) {
transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
</style>