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>
|
<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" />
|
<MenuItem :route-tree="routeTree" />
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</template>
|
</template>
|
||||||
@ -10,19 +17,18 @@ 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";
|
import { useRouter } from "vue-router";
|
||||||
|
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const routerStore = useRoutesListStore();
|
const routerStore = useRoutesListStore();
|
||||||
const { routeTree, routeList } = storeToRefs(routerStore);
|
const { routeTree, currentRoute } = storeToRefs(routerStore);
|
||||||
const themeStore = useThemeConfig();
|
const themeStore = useThemeConfig();
|
||||||
const { collapsed } = storeToRefs(themeStore);
|
const { collapsed } = storeToRefs(themeStore);
|
||||||
|
|
||||||
console.log("路由树", routeTree.value);
|
|
||||||
|
|
||||||
const onMenuItem = (key: string) => {
|
const onMenuItem = (key: string) => {
|
||||||
let find = routeList.value.find((item: Menu.MenuOptions) => item.name === key);
|
const { findLinearArray } = useRoutingMethod();
|
||||||
console.log("当前", find);
|
const find = findLinearArray(key);
|
||||||
if (find) {
|
if (find) {
|
||||||
routerStore.setTagsList(find);
|
routerStore.setTabs(find);
|
||||||
router.push(find.path);
|
router.push(find.path);
|
||||||
} else {
|
} else {
|
||||||
router.push("/404");
|
router.push("/404");
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<a-tabs :editable="true" :hide-content="true" size="medium" type="line" @delete="handleDelete">
|
<a-tabs
|
||||||
<a-tab-pane v-for="item of tagsList" :key="item.name" :title="item.meta.title" :closable="!item.meta.isAffix" />
|
: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>
|
</a-tabs>
|
||||||
<div class="tabs_setting">
|
<div class="tabs_setting">
|
||||||
<a-dropdown trigger="hover">
|
<a-dropdown trigger="hover">
|
||||||
@ -34,22 +42,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useRoutesListStore } from "@/store/route-list";
|
import { useRoutesListStore } from "@/store/route-list";
|
||||||
|
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||||
|
const router = useRouter();
|
||||||
const routerStore = useRoutesListStore();
|
const routerStore = useRoutesListStore();
|
||||||
const { tagsList } = storeToRefs(routerStore);
|
const { tabsList, currentRoute } = storeToRefs(routerStore);
|
||||||
|
|
||||||
watch(
|
const onTabs = (key: string) => {
|
||||||
tagsList.value,
|
const { findTagsList } = useRoutingMethod();
|
||||||
newV => {
|
const find = findTagsList(key);
|
||||||
console.log("tagsList", newV);
|
if (find != undefined) {
|
||||||
},
|
routerStore.setCurrentRoute(find);
|
||||||
{ flush: "post" }
|
router.push(find.path);
|
||||||
);
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleDelete = (key: any) => {
|
const handleDelete = (key: string) => {
|
||||||
console.log("关闭tags", key);
|
routerStore.removeTabsList(key);
|
||||||
// data.value = data.value.filter(item => item.key !== key);
|
if (tabsList.value.length == 0) return;
|
||||||
|
router.push(tabsList.value.at(-1).path);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -41,23 +41,30 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
const { token } = storeToRefs(store);
|
const { token } = storeToRefs(store);
|
||||||
console.log(to, from);
|
console.log(to, from);
|
||||||
if (to.path === "/login" && !token.value) {
|
if (to.path === "/login" && !token.value) {
|
||||||
|
// 1、去登录页,无token,放行
|
||||||
next();
|
next();
|
||||||
} else if (!token.value) {
|
} else if (!token.value) {
|
||||||
|
// 2、没有token,直接重定向到登录页
|
||||||
next("/login");
|
next("/login");
|
||||||
} else if (to.path === "/login" && token.value) {
|
} else if (to.path === "/login" && token.value) {
|
||||||
|
// 3、去登录页,有token,直接重定向到home页
|
||||||
next("/home");
|
next("/home");
|
||||||
|
// 项目内的跳转,处理跳转路由高亮
|
||||||
currentlyRoute(to);
|
currentlyRoute(to);
|
||||||
} else {
|
} else {
|
||||||
|
// 4、去非登录页,有token,校验是否动态添加过路由,添加过则放行,未添加则执行路由初始化
|
||||||
const routeStore = useRoutesListStore(pinia);
|
const routeStore = useRoutesListStore(pinia);
|
||||||
const { routeTree } = storeToRefs(routeStore);
|
const { routeTree } = storeToRefs(routeStore);
|
||||||
// 如果缓存的路由是0,则说明未动态添加路由,先添加再跳转
|
// 如果缓存的路由是0,则说明未动态添加路由,先添加再跳转
|
||||||
// 解决刷新页面404的问题
|
// 解决刷新页面404的问题
|
||||||
if (routeTree.value.length == 0) {
|
if (routeTree.value.length == 0) {
|
||||||
await initSetRouter();
|
await initSetRouter();
|
||||||
|
// 处理完重新跳转
|
||||||
next({ path: to.path, query: to.query });
|
next({ path: to.path, query: to.query });
|
||||||
} else {
|
} else {
|
||||||
// 动态路由添加过走这里,直接放行
|
// 动态路由添加过走这里,直接放行
|
||||||
next();
|
next();
|
||||||
|
// 项目内的跳转,处理跳转路由高亮
|
||||||
currentlyRoute(to);
|
currentlyRoute(to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { storeToRefs } from "pinia";
|
|||||||
import { useUserInfoStore } from "@/store/user-info";
|
import { useUserInfoStore } from "@/store/user-info";
|
||||||
import { useRoutesListStore } from "@/store/route-list";
|
import { useRoutesListStore } from "@/store/route-list";
|
||||||
import { deepClone, arrayFlattened } from "@/utils/index";
|
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 返回有权限的树
|
* @returns 返回有权限的树
|
||||||
*/
|
*/
|
||||||
export const filterByRole = (nodes: any) => {
|
export const filterByRole = (tree: any) => {
|
||||||
return nodes.filter((item: any) => {
|
return tree.filter((item: any) => {
|
||||||
if (item.meta && item.meta.roles) {
|
if (item.meta && item.meta.roles) {
|
||||||
if (!roleBase(item.meta.roles)) return false;
|
if (!roleBase(item.meta.roles)) return false;
|
||||||
}
|
}
|
||||||
@ -80,12 +81,23 @@ export const roleBase = (roles: Array<string>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路由跳转,将路由存入store
|
* 处理tabs,跳转路由如果存在,则存入store
|
||||||
* @param {object} to 需要跳转的路由
|
* @param {object} to 需要跳转的路由
|
||||||
* @returns 是否有权限 true是 false否
|
|
||||||
*/
|
*/
|
||||||
export const currentlyRoute = (to: any) => {
|
export const currentlyRoute = (to: any) => {
|
||||||
// const store = useRoutesListStore(pinia);
|
const store = useRoutesListStore(pinia);
|
||||||
// const { routeList, currentRoute, tagsList } = storeToRefs(store);
|
const { tabsList, routeList } = storeToRefs(store);
|
||||||
console.log("当前路由", to);
|
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",
|
title: "about-project",
|
||||||
isHide: false,
|
isHide: false,
|
||||||
isKeepAlive: true,
|
isKeepAlive: true,
|
||||||
isAffix: true,
|
isAffix: false,
|
||||||
isLink: "",
|
isLink: "",
|
||||||
isIframe: false,
|
isIframe: false,
|
||||||
roles: ["admin", "common"],
|
roles: ["admin", "common"],
|
||||||
|
|||||||
@ -8,30 +8,56 @@ import { defineStore } from "pinia";
|
|||||||
*/
|
*/
|
||||||
export const useRoutesListStore = defineStore("routeList", {
|
export const useRoutesListStore = defineStore("routeList", {
|
||||||
state: (): any => ({
|
state: (): any => ({
|
||||||
routeTree: [], // 路由树
|
routeTree: [], // 有访问权限的路由树
|
||||||
routeList: [], // 路由数据-一维
|
routeList: [], // 有访问权限的一维路由数组
|
||||||
routeNames: [], // 路由名称
|
routeNames: [], // 有访问权限的路由名称
|
||||||
tagsList: [], // 标签页数据
|
tabsList: [], // 标签页数据
|
||||||
currentRoute: {} // 当前路由
|
currentRoute: {} // 当前路由
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setRouteTree(data: Menu.MenuOptions) {
|
setRouteTree(data: Menu.MenuOptions) {
|
||||||
this.routeTree = data;
|
this.routeTree = data;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 设置有访问权限的一维路由数组
|
||||||
|
* @param {Array} data 一维路由数组
|
||||||
|
*/
|
||||||
setRouteList(data: any) {
|
setRouteList(data: any) {
|
||||||
this.routeList = data;
|
this.routeList = data;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 设置所有可缓存路由的路由名
|
||||||
|
* @param {Array} 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);
|
* 添加tabs标签页
|
||||||
if (!isExist) {
|
* @param {object} data 当前tabs路由
|
||||||
this.tagsList.push(data);
|
*/
|
||||||
}
|
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;
|
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