feat: 菜单跳转,关联tags栏

This commit is contained in:
wang_fan_w 2024-04-18 00:24:07 +08:00
parent 7ff3b00d0e
commit 77ee7ba1af
7 changed files with 197 additions and 176 deletions

View File

@ -1,35 +1,31 @@
<template> <template>
<a-layout-content class="content"> <a-layout-content class="content">
<Tabs /> <Tabs />
<a-scrollbar style="height: 100%; overflow: auto" outer-class="scrollbar"> <a-scrollbar style="height: 100%; overflow: auto" outer-class="scrollbar">
<div class="main"> <div class="main">
<div class="main_box"></div> <router-view />
</div> </div>
</a-scrollbar> </a-scrollbar>
</a-layout-content> </a-layout-content>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Tabs from "@/layout/components/Tabs/index.vue"; import Tabs from "@/layout/components/Tabs/index.vue";
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.content { .content {
height: calc(100vh - 60px - 30px); // -footer height: calc(100vh - 60px - 30px); // -footer
} }
.scrollbar { .scrollbar {
height: calc(100% - 40px); height: calc(100% - 40px);
} }
.main { .main {
padding: $padding; padding: $padding;
.main_box { }
height: 1000px; //
background: #eee; :deep(.arco-scrollbar-thumb-direction-vertical .arco-scrollbar-thumb-bar) {
} width: 4px;
} margin-left: 8px;
// }
:deep(.arco-scrollbar-thumb-direction-vertical .arco-scrollbar-thumb-bar) { </style>
width: 4px;
margin-left: 8px;
}
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<a-menu breakpoint="xl" :collapsed="collapsed"> <a-menu breakpoint="xl" :collapsed="collapsed" @menu-item-click="onMenuItem">
<MenuItem :route-tree="routeTree" /> <MenuItem :route-tree="routeTree" />
</a-menu> </a-menu>
</template> </template>
@ -9,13 +9,25 @@ import MenuItem from "@/layout/components/Menu/menu-item.vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/theme-config"; import { useThemeConfig } from "@/store/theme-config";
import { useRoutesListStore } from "@/store/route-list"; import { useRoutesListStore } from "@/store/route-list";
import { useRouter } from "vue-router";
const router = useRouter();
const routerStore = useRoutesListStore(); const routerStore = useRoutesListStore();
const { routeTree } = storeToRefs(routerStore); const { routeTree, routeList } = storeToRefs(routerStore);
const themeStore = useThemeConfig(); const themeStore = useThemeConfig();
const { collapsed } = storeToRefs(themeStore); const { collapsed } = storeToRefs(themeStore);
console.log("路由树", routeTree.value); console.log("路由树", routeTree.value);
const onMenuItem = (key: string) => {
let find = routeList.value.find((item: Menu.MenuOptions) => item.name === key);
console.log("当前", find);
if (find) {
routerStore.setTagsList(find);
router.push(find.path);
} else {
router.push("/404");
}
};
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -7,7 +7,7 @@
<template #title>{{ item.meta.title }}</template> <template #title>{{ item.meta.title }}</template>
<MenuItem :route-tree="item.children" /> <MenuItem :route-tree="item.children" />
</a-sub-menu> </a-sub-menu>
<a-menu-item v-else :key="item.name"> <a-menu-item v-else :key="item?.name">
<template #icon v-if="item.meta.svgIcon || item.meta.icon"> <template #icon v-if="item.meta.svgIcon || item.meta.icon">
<IconCommon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" /> <IconCommon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template> </template>

View File

@ -1,122 +1,129 @@
<template> <template>
<div class="tabs"> <div class="tabs">
<a-tabs <a-tabs :editable="true" :hide-content="true" size="medium" type="line" @delete="handleDelete">
:editable="true" <a-tab-pane v-for="item of tagsList" :key="item.name" :title="item.meta.title" :closable="!item.meta.isAffix" />
:hide-content="true" </a-tabs>
size="medium" <div class="tabs_setting">
type="line" <a-dropdown trigger="hover">
show-add-button <div class="setting"><icon-loop :size="18" /></div>
@add="handleAdd" <template #content>
@delete="handleDelete" <a-doption>
> <template #icon><icon-refresh /></template>
<a-tab-pane v-for="(item, index) of data" :key="item.key" :title="item.title" :closable="index !== 2" /> <template #default>刷新</template>
</a-tabs> </a-doption>
<div class="tabs_setting"> <a-doption>
<a-dropdown trigger="hover"> <template #icon><icon-left /></template>
<div class="setting"><icon-loop :size="18" /></div> <template #default>关闭左侧</template>
<template #content> </a-doption>
<a-doption> <a-doption>
<template #icon><icon-refresh /></template> <template #icon><icon-right /></template>
<template #default>刷新</template> <template #default>关闭右侧</template>
</a-doption> </a-doption>
<a-doption> <a-doption>
<template #icon><icon-left /></template> <template #icon><icon-close /></template>
<template #default>关闭左侧</template> <template #default>关闭其它</template>
</a-doption> </a-doption>
<a-doption> <a-doption>
<template #icon><icon-right /></template> <template #icon><icon-close-circle /></template>
<template #default>关闭右侧</template> <template #default>全部关闭</template>
</a-doption> </a-doption>
<a-doption> </template>
<template #icon><icon-close /></template> </a-dropdown>
<template #default>关闭其它</template> </div>
</a-doption> </div>
<a-doption> </template>
<template #icon><icon-close-circle /></template>
<template #default>全部关闭</template> <script setup lang="ts">
</a-doption> import { storeToRefs } from "pinia";
</template> import { useRoutesListStore } from "@/store/route-list";
</a-dropdown> const routerStore = useRoutesListStore();
</div> const { tagsList } = storeToRefs(routerStore);
</div>
</template> watch(
tagsList.value,
<script setup lang="ts"> newV => {
let count = 5; console.log("tagsList", newV);
const data = ref([ },
{ { flush: "post" }
key: "1", );
title: "Tab 1",
content: "Content of Tab Panel 1" // let count = 5;
}, // const data = ref([
{ // {
key: "2", // key: "1",
title: "Tab 2", // title: "Tab 1",
content: "Content of Tab Panel 2" // content: "Content of Tab Panel 1"
}, // },
{ // {
key: "3", // key: "2",
title: "Tab 3", // title: "Tab 2",
content: "Content of Tab Panel 3" // content: "Content of Tab Panel 2"
}, // },
{ // {
key: "4", // key: "3",
title: "Tab 4", // title: "Tab 3",
content: "Content of Tab Panel 4" // content: "Content of Tab Panel 3"
} // },
]); // {
// key: "4",
const handleAdd = () => { // title: "Tab 4",
const number = count++; // content: "Content of Tab Panel 4"
data.value = data.value.concat({ // }
key: `${number}`, // ]);
title: `New Tab ${number}`,
content: `Content of New Tab Panel ${number}` // const handleAdd = () => {
}); // const number = count++;
}; // data.value = data.value.concat({
const handleDelete = (key: any) => { // key: `${number}`,
data.value = data.value.filter(item => item.key !== key); // title: `New Tab ${number}`,
}; // content: `Content of New Tab Panel ${number}`
</script> // });
// };
<style lang="scss" scoped> const handleDelete = (key: any) => {
.tabs { console.log("关闭tags", key);
height: 40px;
box-sizing: border-box; // data.value = data.value.filter(item => item.key !== key);
border-bottom: $border-1 solid $color-border-2; };
display: flex; </script>
justify-content: space-between;
align-items: center; <style lang="scss" scoped>
.tabs_setting { .tabs {
margin: 0 0 0 $margin; height: 40px;
.setting { box-sizing: border-box;
margin-right: $margin; border-bottom: $border-1 solid $color-border-2;
color: $color-text-2; display: flex;
} justify-content: space-between;
} align-items: center;
} .tabs_setting {
:deep(.arco-tabs-nav-tab) { margin: 0 0 0 $margin;
// icon .setting {
.arco-tabs-tab-closable { margin-right: $margin;
svg { color: $color-text-2;
width: 0px; }
transition: all 0.2s; }
} }
&:hover { :deep(.arco-tabs-nav-tab) {
svg { // icon
width: 1em; .arco-tabs-tab-closable {
} svg {
} width: 0px;
} transition: all 0.2s;
// tab }
&:hover .arco-tabs-tab-title::before { &:hover {
background: unset; svg {
} width: 1em;
} }
// tabs线 }
:deep(.arco-tabs-nav) { }
&::before { // tab
background: unset; &:hover .arco-tabs-tab-title::before {
} background: unset;
} }
</style> }
// tabs线
:deep(.arco-tabs-nav) {
&::before {
background: unset;
}
}
</style>

View File

@ -39,7 +39,7 @@ export async function initSetRouter() {
export function setCacheName(flattenedArray: any) { export function setCacheName(flattenedArray: any) {
const store = useRoutesListStore(pinia); const store = useRoutesListStore(pinia);
const cacheName = flattenedArray.map((item: any) => item.name); const cacheName = flattenedArray.map((item: any) => item.name);
store.setrouteNames(cacheName); // 缓存路由name store.setRouteNames(cacheName); // 缓存路由name
store.setRouteList(flattenedArray); // 缓存路由 store.setRouteList(flattenedArray); // 缓存路由
} }

View File

@ -191,16 +191,6 @@ export const staticRoutes = [
* @link https://router.vuejs.org/zh/guide/essentials/history-mode.html#netlify * @link https://router.vuejs.org/zh/guide/essentials/history-mode.html#netlify
*/ */
export const notFoundAndNoPower = [ export const notFoundAndNoPower = [
// 未找到页面的时候跳转该页面
{
path: "/:path(.*)*",
name: "notFound",
component: () => import("@/views/error/404.vue"),
meta: {
title: "notFound",
isHide: true
}
},
{ {
path: "/401", path: "/401",
name: "noPower", name: "noPower",
@ -209,5 +199,14 @@ export const notFoundAndNoPower = [
title: "notFound", title: "notFound",
isHide: true isHide: true
} }
},
{
path: "/:path(.*)*", // 匹配任意路由,兜底,未找到页面的时候跳转该页面
name: "notFound",
component: () => import("@/views/error/404.vue"),
meta: {
title: "notFound",
isHide: true
}
} }
]; ];

View File

@ -4,13 +4,14 @@ import { defineStore } from "pinia";
* *
* @methods setRouteTree * @methods setRouteTree
* @methods setRoutesList * @methods setRoutesList
* @methods setrouteNames * @methods setRouteNames
*/ */
export const useRoutesListStore = defineStore("routeList", { export const useRoutesListStore = defineStore("routeList", {
state: (): any => ({ state: (): any => ({
routeTree: [], // 路由树 routeTree: [], // 路由树
routeList: [], // 路由数据 routeList: [], // 路由数据-一维
routeNames: [] // 路由名称 routeNames: [], // 路由名称
tagsList: [] // 标签页数据
}), }),
actions: { actions: {
setRouteTree(data: any) { setRouteTree(data: any) {
@ -19,8 +20,14 @@ export const useRoutesListStore = defineStore("routeList", {
setRouteList(data: any) { setRouteList(data: any) {
this.routeList = data; this.routeList = data;
}, },
setrouteNames(data: Array<string>) { setRouteNames(data: Array<string>) {
this.routeNames = data; this.routeNames = data;
},
setTagsList(data: Menu.MenuOptions) {
let isExist = this.tagsList.some((item: Menu.MenuOptions) => item.name === data.name);
if (!isExist) {
this.tagsList.push(data);
}
} }
} }
}); });