From 2080e8fe55d8babf0b40a5a4ac0e2079965adb95 Mon Sep 17 00:00:00 2001 From: WANGFan <15871339963@163.com> Date: Sun, 18 May 2025 17:40:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B7=AF=E7=94=B1=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E9=A1=B5=EF=BC=8C=E5=AE=8C=E5=96=84=E4=BA=86=E6=99=AE=E9=80=9A?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=92=8C=E5=8A=A8=E6=80=81=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=EF=BC=8C=E5=B9=B6=E4=B8=94=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E4=BA=86=E6=A0=87=E7=AD=BE=E9=A1=B5=E5=88=87=E6=8D=A2=E6=97=B6?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=8F=82=E6=95=B0=E4=B8=A2=E5=A4=B1=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useRoutingMethod.ts | 25 +++++++++++++++++- .../components/system-settings/index.vue | 2 +- src/layout/components/Tabs/index.vue | 22 +++++++++++----- src/mock/_data/system_menu.ts | 2 +- src/router/index.ts | 13 +++++++--- src/router/route-output.ts | 26 ++++++++++--------- src/store/modules/route-config.ts | 10 ++++--- .../functions/routing-operation/index.vue | 2 +- .../test-router/test-common-route/index.vue | 1 + .../test-router/test-dynamic-route/index.vue | 1 + 10 files changed, 73 insertions(+), 31 deletions(-) diff --git a/src/hooks/useRoutingMethod.ts b/src/hooks/useRoutingMethod.ts index 7804455..22481df 100644 --- a/src/hooks/useRoutingMethod.ts +++ b/src/hooks/useRoutingMethod.ts @@ -1,6 +1,7 @@ import pinia from "@/store/index"; import { storeToRefs } from "pinia"; import { useRoutesConfigStore } from "@/store/modules/route-config"; + /** * 路由处理hooks,内置多种路由处理场景 * @returns 路由方法 @@ -17,6 +18,17 @@ export const useRoutingMethod = () => { return routeList.value.find((item: Menu.MenuOptions) => item.name == key); }; + /** + * 从一维路由中判断路由是否存在 + * @param {string} key 路由的name + * @returns 路由是否存在,true存在 false不存在 + */ + const hasRoute = (key: string) => { + const routerStore = useRoutesConfigStore(pinia); + const { routeList } = storeToRefs(routerStore); + return routeList.value.some((item: Menu.MenuOptions) => item.name == key); + }; + /** * 从tabs路由中查找路由 * @param {string} key 路由的name @@ -39,9 +51,20 @@ export const useRoutingMethod = () => { } }; + /** + * 检测是否是动态匹配路由,如果是动态匹配路由,则path必然带有"/:"字样,例如:/user/:id + * @param {string} path 路由path + * @returns 是否是动态匹配路由 + */ + const isDynamicRoute = (path: string) => { + return path.includes("/:"); + }; + return { findLinearArray, findTagsList, - openExternalLinks + openExternalLinks, + isDynamicRoute, + hasRoute }; }; diff --git a/src/layout/components/Header/components/system-settings/index.vue b/src/layout/components/Header/components/system-settings/index.vue index 5c814f8..d625882 100644 --- a/src/layout/components/Header/components/system-settings/index.vue +++ b/src/layout/components/Header/components/system-settings/index.vue @@ -112,7 +112,7 @@ const tabsChange = (e: Boolean) => { tabsList.value = []; cacheRoutes.value = []; } else { - currentlyRoute(route.name as string); + currentlyRoute(route); } }; diff --git a/src/layout/components/Tabs/index.vue b/src/layout/components/Tabs/index.vue index 29bcebf..5ef1b52 100644 --- a/src/layout/components/Tabs/index.vue +++ b/src/layout/components/Tabs/index.vue @@ -58,15 +58,23 @@ const router = useRouter(); const routerStore = useRoutesConfigStore(); const { tabsList, currentRoute } = storeToRefs(routerStore); +// 统一处理跳转 +const routerPush = (route: any) => { + const { isDynamicRoute } = useRoutingMethod(); + // 区分动态路由和普通路由 + if (isDynamicRoute(route.path)) { + router.push({ name: route.name, params: route.params }); + } else { + router.push({ path: route.path, query: route.query }); + } +}; + // 点击标签页,如果标签页存在,则跳转 const onTabs = (key: string) => { const { findTagsList } = useRoutingMethod(); const find = findTagsList(key); - console.log("点击", key, find); - - if (find != undefined) { - router.push(find.path); - } + if (find == undefined) return; + routerPush(find); }; // 删除当前标签页并跳转到最后一个标签页 @@ -75,7 +83,7 @@ const onDelete = (key: string) => { routerStore.removeRouteName(key); if (tabsList.value.length == 0) return; if (currentRoute.value.name != key) return; - router.push(tabsList.value.at(-1).path); + routerPush(tabsList.value.at(-1)); }; // 刷新当前页 @@ -141,7 +149,7 @@ const closeOther = (type: string) => { routerStore.removeRouteNames(rightNames); // 关闭全部,若当前被关闭则跳转最后一个 if (tabsList.value.length != 0 && !currentRoute.value.meta.affix && type == "all") { - router.push(tabsList.value.at(-1).path); + routerPush(tabsList.value.at(-1)); } }; diff --git a/src/mock/_data/system_menu.ts b/src/mock/_data/system_menu.ts index ee3c26b..3e2a617 100644 --- a/src/mock/_data/system_menu.ts +++ b/src/mock/_data/system_menu.ts @@ -763,7 +763,7 @@ export const systemMenu = [ parentId: "0", path: "/functions", name: "functions", - redirect: "/functions", + redirect: "/functions/routing-operation", meta: { title: "functions", hide: false, diff --git a/src/router/index.ts b/src/router/index.ts index 454f990..37ad3e5 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -37,7 +37,6 @@ const router = createRouter({ * 页面刷新会导致addRoute动态添加的路由失效,需要重新初始化路由 */ router.beforeEach(async (to: any, _: any, next: any) => { - console.log("去", to); NProgress.start(); // 开启进度条 const store = useUserInfoStore(pinia); const { token, account } = storeToRefs(store); @@ -53,7 +52,7 @@ router.beforeEach(async (to: any, _: any, next: any) => { // 3、去登录页,有token,直接重定向到home页 next("/home"); // 项目内的跳转,处理跳转路由高亮 - currentlyRoute(to.name as string); + currentlyRoute(to); } else { // 4、去非登录页,有token,用户信息是否存在,有则放行,否则重新获取路由信息、初始化路由 const routeStore = useRoutesConfigStore(pinia); @@ -65,7 +64,13 @@ router.beforeEach(async (to: any, _: any, next: any) => { await store.setAccount(); // 获取路由信息 await routeStore.initSetRouter(); - next({ path: to.path, query: to.query, params: to.params }); + // 判断是否是动态路由 + const { isDynamicRoute } = useRoutingMethod(); + if (isDynamicRoute(to.path)) { + next({ name: to.name, params: to.params }); + } else { + next({ path: to.path, query: to.query }); + } } else { // 获取外链路由的处理函数 // 所有的路由正常放行,只不过额外判断是否是外链,如果是,则打开新窗口跳转外链 @@ -76,7 +81,7 @@ router.beforeEach(async (to: any, _: any, next: any) => { // 动态路由添加过走这里,直接放行 next(); // 项目内的跳转,处理跳转路由高亮 - currentlyRoute(to.name as string); + currentlyRoute(to); } } }); diff --git a/src/router/route-output.ts b/src/router/route-output.ts index 60aecc3..91249eb 100644 --- a/src/router/route-output.ts +++ b/src/router/route-output.ts @@ -19,9 +19,10 @@ export function linearArray(tree: any) { * 统一处理所有的路由跳转:当前路由高亮、tabs栏数据 * 处理项目内跳转,存入当前跳转路由和tabs标签栏数据 * menu和tabs以及手动刷新浏览器等功能只需要跳转即可,缓存和高亮的逻辑这边负责 - * @param {object} name 需要跳转的路由 + * @param {any} current 需要跳转的路由和路由参数 */ -export const currentlyRoute = (name: string) => { +export const currentlyRoute = (current: any) => { + const route = deepClone(current); const themeStore = useThemeConfig(); const { isTabs } = storeToRefs(themeStore); const store = useRoutesConfigStore(pinia); @@ -30,22 +31,23 @@ export const currentlyRoute = (name: string) => { if (tabsList.value.length == 0 && routeList.value.length != 0) { store.setTabs(routeList.value[0]); } - // 跳转路由是有权限的,缓存跳转路由 - const { findLinearArray } = useRoutingMethod(); - const find = findLinearArray(name); - if (find === undefined) return; + + // 跳转路由是有权限的,从有权限路由中匹配 + const { hasRoute } = useRoutingMethod(); + // 未找到,说明当前跳转路由无权限 + if (!hasRoute(route.name)) return; + // 存入当前路由-高亮 - store.setCurrentRoute(find); + store.setCurrentRoute(route); // 如果是外链路由则不做后续任何缓存操作,条件: 有外链 && 非内嵌 - if (find.meta.link && !find.meta.iframe) return; - console.log("跳转存入tabs", tabsList.value, find); + if (route.meta.link && !route.meta.iframe) return; // 存入tabs栏数据,条件:开启tabs - if (isTabs.value) store.setTabs(find); + if (isTabs.value) store.setTabs(route); // 不缓存路由 || 不渲染tabs ,符合任意条件则不缓存路由 - if (!find.meta.keepAlive || !isTabs.value) return; - store.setRouteNames(find.name); // 缓存路由name + if (!route.meta.keepAlive || !isTabs.value) return; + store.setRouteNames(route.name); // 缓存路由name }; /** diff --git a/src/store/modules/route-config.ts b/src/store/modules/route-config.ts index cd5ba1c..df16a4d 100644 --- a/src/store/modules/route-config.ts +++ b/src/store/modules/route-config.ts @@ -36,9 +36,11 @@ export const routesConfigStore = () => { * @param {object} data 当前tabs路由 */ function setTabs(data: Menu.MenuOptions) { - // 当前路由在tags中是否存在,不存在则缓存 - let isExist = tabsList.value.some((item: Menu.MenuOptions) => item.name === data.name); - if (isExist) return; + // 当前路由在tags中是否存在 + let index = tabsList.value.findIndex((item: Menu.MenuOptions) => item.name === data.name); + // 如果存在,新路由替换旧路由,因为路由存在并不代表本次跳转的参数一致 + if (index != -1) return tabsList.value.splice(index, 1, data); + // 不存在,直接缓存 tabsList.value.push(data); } /** @@ -46,7 +48,7 @@ export const routesConfigStore = () => { * @param {object} data 当前路由 */ function setCurrentRoute(data: Menu.MenuOptions) { - if (currentRoute.value.name && data.name === currentRoute.value.name) return; + // 名称一样不代表参数相同,这不用做已存在匹配,直接存储当前路由 currentRoute.value = data; } /** diff --git a/src/views/functions/routing-operation/index.vue b/src/views/functions/routing-operation/index.vue index 445b948..ca1586d 100644 --- a/src/views/functions/routing-operation/index.vue +++ b/src/views/functions/routing-operation/index.vue @@ -62,8 +62,8 @@ diff --git a/src/views/test-router/test-dynamic-route/index.vue b/src/views/test-router/test-dynamic-route/index.vue index 6ce0610..f135845 100644 --- a/src/views/test-router/test-dynamic-route/index.vue +++ b/src/views/test-router/test-dynamic-route/index.vue @@ -12,6 +12,7 @@