diff --git a/src/hooks/usePathUrl.ts b/src/hooks/usePathUrl.ts index ff3c796..01b4a1e 100644 --- a/src/hooks/usePathUrl.ts +++ b/src/hooks/usePathUrl.ts @@ -1,6 +1,16 @@ -export const usePathUrl = () => { - const PATH_URL = `${import.meta.env.VITE_APP_SSO_LOGINURL}?client_id=${ - import.meta.env.VITE_APP_SSO_APPID - }&redirect_uri=${encodeURIComponent(import.meta.env.VITE_REDIRECT_URL)}&response_type=code`; - return PATH_URL; +export const usePathUrl = (redirect_path?: any) => { + let PATH_URL: any = ""; + if (redirect_path) { + PATH_URL = `${import.meta.env.VITE_APP_SSO_LOGINURL}?client_id=${ + import.meta.env.VITE_APP_SSO_APPID + }&redirect_uri=${encodeURIComponent( + import.meta.env.VITE_REDIRECT_URL + "?redirect_path=" + redirect_path + )}&response_type=code`; + return PATH_URL; + } else { + PATH_URL = `${import.meta.env.VITE_APP_SSO_LOGINURL}?client_id=${ + import.meta.env.VITE_APP_SSO_APPID + }&redirect_uri=${encodeURIComponent(import.meta.env.VITE_REDIRECT_URL)}&response_type=code`; + return PATH_URL; + } }; diff --git a/src/layouts/components/Tabs/index.vue b/src/layouts/components/Tabs/index.vue index ea53256..70f6363 100644 --- a/src/layouts/components/Tabs/index.vue +++ b/src/layouts/components/Tabs/index.vue @@ -107,13 +107,12 @@ const tabClick = (tabItem: TabsPaneContext) => { // Remove Tab const tabRemove = (fullPath: TabPaneName) => { - if (fullPath === "/index") { + const name = tabStore.tabsMenuList.filter(item => item.path == fullPath)[0].name || ""; + + if (fullPath === "/index" || name === "home") { return; } - // const name = tabStore.tabsMenuList.filter(item => item.path == fullPath)[0].name || ""; - // keepAliveStore.removeKeepAliveName(name); - // tabStore.removeTabs(fullPath as string, fullPath == route.fullPath); - const name = tabStore.tabsMenuList.filter(item => item.path == fullPath)[0].name || ""; + tabStore.removeTabs(fullPath as string, fullPath == route.fullPath); let isKeepAlive = tabStore.tabsMenuList.some((item: any) => { return item.name === name; diff --git a/src/routers/index.ts b/src/routers/index.ts index db7faf8..63dfb8a 100644 --- a/src/routers/index.ts +++ b/src/routers/index.ts @@ -29,6 +29,22 @@ const router = createRouter({ scrollBehavior: () => ({ left: 0, top: 0 }) }); +// 1. 定义获取URL参数的函数 +function getUrlParam(paramName: any) { + // 获取当前页面URL的查询参数部分(如 "?redirect_path=xxx&t=xxx") + const searchStr = window.location.search.slice(1); + // 将参数按 "&" 分割成数组(如 ["redirect_path=xxx", "t=xxx"]) + const paramArr = searchStr.split("&"); + // 遍历数组匹配目标参数 + for (let item of paramArr) { + const [key, value] = item.split("="); + if (key === paramName) { + return decodeURIComponent(value); // 解码特殊字符,确保内容准确 + } + } + return null; // 未找到参数时返回null +} + /** * @description 路由拦截 beforeEach * */ @@ -38,6 +54,7 @@ router.beforeEach(async (to, from, next) => { // 1.NProgress 开始 NProgress.start(); + let redirect_path = getUrlParam("redirect_path"); // 2.动态设置标题 const title = import.meta.env.VITE_GLOB_APP_TITLE; @@ -51,6 +68,17 @@ router.beforeEach(async (to, from, next) => { // 4.判断访问页面是否在路由白名单地址(静态路由)中,如果存在直接放行 if (ROUTER_WHITE_LIST.includes(to.path)) return next(); + // 4.判断访问页面是否在路由白名单地址(静态路由)中,如果存在直接放行 + if (ROUTER_WHITE_LIST.includes(to.path)) return next(); + + // 如果没有token但是有订阅路由就将订阅路由当参数携带 + if (!userStore.newUserToken && redirect_path) { + return next({ + path: LOGIN_URL, + replace: true, + query: { redirect_path: redirect_path } // 通过query传递参数 + }); + } // 5.判断是否有 Token,没有重定向到 login 页面 if (!userStore.newUserToken) return next({ path: LOGIN_URL, replace: true }); diff --git a/src/stores/modules/tabs.ts b/src/stores/modules/tabs.ts index 4df4b86..35aad75 100644 --- a/src/stores/modules/tabs.ts +++ b/src/stores/modules/tabs.ts @@ -6,16 +6,46 @@ import piniaPersistConfig from "@/config/piniaPersist"; export const useTabsStore = defineStore({ id: "wms-tabs", state: (): TabsState => ({ - tabsMenuList: [] + tabsMenuList: [ + { + icon: "", // 首页的icon,按实际路由meta.icon填写(如"Home") + title: "首页", // 固定首页标题 + path: "/index", // 首页的基础路径(无参数版本,避免初始参数冗余) + name: "home", // 必须与首页路由的name一致(如路由定义中name: "home") + close: true // 首页是否可关闭,按业务需求设置(通常true,若禁止关闭设为false) + } + ] }), actions: { - // Add Tabs + // Add Tabs:按 name 去重,首页始终在最前 async addTabs(tabItem: any) { - if (this.tabsMenuList.every(item => item.path !== tabItem.path)) { - this.tabsMenuList.push(tabItem); + // 1. 校验参数:确保 tabItem 有 name(避免异常数据) + if (!tabItem.name) return; + + // 2. 去重逻辑:按 name 判断是否已存在 + const isExist = this.tabsMenuList.some(item => item.name === tabItem.name); + + if (!isExist) { + // 3. 首页(name: "home")添加到数组开头,其他标签添加到末尾 + if (tabItem.name === "home") { + // 先移除旧的首页(防止极端情况残留),再添加新首页到最前 + this.tabsMenuList = this.tabsMenuList.filter(item => item.name !== "home"); + this.tabsMenuList.unshift(tabItem); // 首页放第一位 + } else { + this.tabsMenuList.push(tabItem); // 非首页放末尾 + } + } else { + // 4. 可选优化:若标签已存在,同步更新其 path(如首页参数变化时) + this.tabsMenuList = this.tabsMenuList.map(item => { + if (item.name === tabItem.name) { + return { ...item, path: tabItem.path }; // 仅更新 path,保留其他属性 + } + return item; + }); } }, - // Remove Tabs + + // Remove Tabs(原有逻辑不变,无需修改) async removeTabs(tabPath: string, isCurrent: boolean = true) { const tabsMenuList = this.tabsMenuList; if (isCurrent) { @@ -28,17 +58,36 @@ export const useTabsStore = defineStore({ } this.tabsMenuList = tabsMenuList.filter(item => item.path !== tabPath); }, - // Close MultipleTab + + // Close MultipleTab(原有逻辑不变) async closeMultipleTab(tabsMenuValue?: string) { this.tabsMenuList = this.tabsMenuList.filter(item => { return item.path === tabsMenuValue || !item.close; }); }, - // Set Tabs + + // Set Tabs(原有逻辑不变) async setTabs(tabsMenuList: any[]) { - this.tabsMenuList = tabsMenuList; + // 补充:设置 tabs 时也需去重,避免批量设置时带入重复首页 + const uniqueTabs = []; + const nameSet = new Set(); + // 先处理首页,确保在最前 + const homeTab = tabsMenuList.find(item => item.name === "home"); + if (homeTab) { + uniqueTabs.push(homeTab); + nameSet.add("home"); + } + // 再处理其他标签,去重 + tabsMenuList.forEach(tab => { + if (!nameSet.has(tab.name)) { + nameSet.add(tab.name); + uniqueTabs.push(tab); + } + }); + this.tabsMenuList = uniqueTabs; }, - // Set Tabs Title + + // Set Tabs Title(原有逻辑不变) async setTabsTitle(title: string) { const nowFullPath = location.hash.substring(1); this.tabsMenuList.forEach(item => { diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 7586d02..a809619 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -7,10 +7,13 @@