feat: 标签页基本功能

This commit is contained in:
wang_fan_w 2024-04-20 16:54:12 +08:00
parent 96f2bbc687
commit a0a0aca533
7 changed files with 137 additions and 39 deletions

View File

@ -0,0 +1,34 @@
import pinia from "@/store/index";
import { storeToRefs } from "pinia";
import { useRoutesListStore } from "@/store/route-list";
/**
* hooks
* @returns
*/
export const useRoutingMethod = () => {
/**
*
* @param {string} key name
* @returns undefined则表示未找到
*/
const findLinearArray = (key: string) => {
const routerStore = useRoutesListStore(pinia);
const { routeList } = storeToRefs(routerStore);
return routeList.value.find((item: Menu.MenuOptions) => item.name == key);
};
/**
* tabs路由中查找路由
* @param {string} key name
* @returns undefined则表示未找到
*/
const findTagsList = (key: string) => {
const routerStore = useRoutesListStore(pinia);
const { tabsList } = storeToRefs(routerStore);
return tabsList.value.find((item: Menu.MenuOptions) => item.name == key);
};
return {
findLinearArray,
findTagsList
};
};

View File

@ -1,5 +1,12 @@
<template>
<a-menu breakpoint="xl" :collapsed="collapsed" @menu-item-click="onMenuItem">
<a-menu
breakpoint="xl"
:collapsed="collapsed"
:auto-open-selected="true"
:accordion="true"
:selected-keys="[currentRoute.name]"
@menu-item-click="onMenuItem"
>
<MenuItem :route-tree="routeTree" />
</a-menu>
</template>
@ -10,19 +17,18 @@ import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/theme-config";
import { useRoutesListStore } from "@/store/route-list";
import { useRouter } from "vue-router";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
const router = useRouter();
const routerStore = useRoutesListStore();
const { routeTree, routeList } = storeToRefs(routerStore);
const { routeTree, currentRoute } = storeToRefs(routerStore);
const themeStore = useThemeConfig();
const { collapsed } = storeToRefs(themeStore);
console.log("路由树", routeTree.value);
const onMenuItem = (key: string) => {
let find = routeList.value.find((item: Menu.MenuOptions) => item.name === key);
console.log("当前", find);
const { findLinearArray } = useRoutingMethod();
const find = findLinearArray(key);
if (find) {
routerStore.setTagsList(find);
routerStore.setTabs(find);
router.push(find.path);
} else {
router.push("/404");

View File

@ -1,7 +1,15 @@
<template>
<div class="tabs">
<a-tabs :editable="true" :hide-content="true" size="medium" type="line" @delete="handleDelete">
<a-tab-pane v-for="item of tagsList" :key="item.name" :title="item.meta.title" :closable="!item.meta.isAffix" />
<a-tabs
:editable="true"
:hide-content="true"
:active-key="currentRoute.name"
size="medium"
type="line"
@tab-click="onTabs"
@delete="handleDelete"
>
<a-tab-pane v-for="item of tabsList" :key="item.name" :title="item.meta.title" :closable="!item.meta.isAffix" />
</a-tabs>
<div class="tabs_setting">
<a-dropdown trigger="hover">
@ -34,22 +42,27 @@
</template>
<script setup lang="ts">
import { useRouter } from "vue-router";
import { storeToRefs } from "pinia";
import { useRoutesListStore } from "@/store/route-list";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
const router = useRouter();
const routerStore = useRoutesListStore();
const { tagsList } = storeToRefs(routerStore);
const { tabsList, currentRoute } = storeToRefs(routerStore);
watch(
tagsList.value,
newV => {
console.log("tagsList", newV);
},
{ flush: "post" }
);
const onTabs = (key: string) => {
const { findTagsList } = useRoutingMethod();
const find = findTagsList(key);
if (find != undefined) {
routerStore.setCurrentRoute(find);
router.push(find.path);
}
};
const handleDelete = (key: any) => {
console.log("关闭tags", key);
// data.value = data.value.filter(item => item.key !== key);
const handleDelete = (key: string) => {
routerStore.removeTabsList(key);
if (tabsList.value.length == 0) return;
router.push(tabsList.value.at(-1).path);
};
</script>

View File

@ -41,23 +41,30 @@ router.beforeEach(async (to, from, next) => {
const { token } = storeToRefs(store);
console.log(to, from);
if (to.path === "/login" && !token.value) {
// 1、去登录页无token放行
next();
} else if (!token.value) {
// 2、没有token直接重定向到登录页
next("/login");
} else if (to.path === "/login" && token.value) {
// 3、去登录页有token直接重定向到home页
next("/home");
// 项目内的跳转,处理跳转路由高亮
currentlyRoute(to);
} else {
// 4、去非登录页有token校验是否动态添加过路由添加过则放行未添加则执行路由初始化
const routeStore = useRoutesListStore(pinia);
const { routeTree } = storeToRefs(routeStore);
// 如果缓存的路由是0则说明未动态添加路由先添加再跳转
// 解决刷新页面404的问题
if (routeTree.value.length == 0) {
await initSetRouter();
// 处理完重新跳转
next({ path: to.path, query: to.query });
} else {
// 动态路由添加过走这里,直接放行
next();
// 项目内的跳转,处理跳转路由高亮
currentlyRoute(to);
}
}

View File

@ -5,6 +5,7 @@ import { storeToRefs } from "pinia";
import { useUserInfoStore } from "@/store/user-info";
import { useRoutesListStore } from "@/store/route-list";
import { deepClone, arrayFlattened } from "@/utils/index";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
/**
*
@ -55,11 +56,11 @@ export function linearArray(tree: any) {
/**
*
* @param {array} nodes
* @param {array} tree
* @returns
*/
export const filterByRole = (nodes: any) => {
return nodes.filter((item: any) => {
export const filterByRole = (tree: any) => {
return tree.filter((item: any) => {
if (item.meta && item.meta.roles) {
if (!roleBase(item.meta.roles)) return false;
}
@ -80,12 +81,23 @@ export const roleBase = (roles: Array<string>) => {
};
/**
* store
* tabsstore
* @param {object} to
* @returns true是 false否
*/
export const currentlyRoute = (to: any) => {
// const store = useRoutesListStore(pinia);
// const { routeList, currentRoute, tagsList } = storeToRefs(store);
console.log("当前路由", to);
const store = useRoutesListStore(pinia);
const { tabsList, routeList } = storeToRefs(store);
console.log("刷新", tabsList.value, routeList.value);
// tabs无数据则默认添加首页
if (tabsList.value.length == 0 && routeList.value.length != 0) {
store.setTabs(routeList.value[0]);
}
const { findLinearArray } = useRoutingMethod();
const find = findLinearArray(to.name);
if (find != undefined) {
// 存入当前路由
store.setCurrentRoute(find);
store.setTabs(find);
}
console.log("刷新", tabsList.value);
};

View File

@ -154,7 +154,7 @@ export const dynamicRoutes: RouteRecordRaw[] = [
title: "about-project",
isHide: false,
isKeepAlive: true,
isAffix: true,
isAffix: false,
isLink: "",
isIframe: false,
roles: ["admin", "common"],

View File

@ -8,30 +8,56 @@ import { defineStore } from "pinia";
*/
export const useRoutesListStore = defineStore("routeList", {
state: (): any => ({
routeTree: [], // 路由树
routeList: [], // 路由数据-一维
routeNames: [], // 路由名称
tagsList: [], // 标签页数据
routeTree: [], // 有访问权限的路由树
routeList: [], // 有访问权限的一维路由数组
routeNames: [], // 有访问权限的路由名称
tabsList: [], // 标签页数据
currentRoute: {} // 当前路由
}),
actions: {
setRouteTree(data: Menu.MenuOptions) {
this.routeTree = data;
},
/**
* 访
* @param {Array} data
*/
setRouteList(data: any) {
this.routeList = data;
},
/**
*
* @param {Array} data
*/
setRouteNames(data: Array<string>) {
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);
}
/**
* tabs标签页
* @param {object} data tabs路由
*/
setTabs(data: Menu.MenuOptions) {
// 当前路由在tags中是否存在不存在则缓存
let isExist = this.tabsList.some((item: Menu.MenuOptions) => item.name === data.name);
if (isExist) return;
this.tabsList.push(data);
},
setCurrentRoute(data: any) {
/**
*
* @param {object} data
*/
setCurrentRoute(data: Menu.MenuOptions) {
if (this.currentRoute.name && data.name === this.currentRoute.name) return;
this.currentRoute = data;
},
/**
* tabs页的指定路由
* @param {string} key name
*/
removeTabsList(key: string) {
const index = this.tabsList.findIndex((item: Menu.MenuOptions) => item.name === key);
if (index === -1) return;
this.tabsList.splice(index, 1);
}
}
});