feat: 标签页基本功能
This commit is contained in:
parent
96f2bbc687
commit
a0a0aca533
34
src/hooks/useRoutingMethod.ts
Normal file
34
src/hooks/useRoutingMethod.ts
Normal 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
|
||||
};
|
||||
};
|
||||
@ -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");
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
* 处理tabs,跳转路由如果存在,则存入store
|
||||
* @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);
|
||||
};
|
||||
|
||||
@ -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"],
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user