diff --git a/src/pages/Layout/index.vue b/src/pages/Layout/index.vue index 3d08a19..a9f7f13 100644 --- a/src/pages/Layout/index.vue +++ b/src/pages/Layout/index.vue @@ -35,7 +35,7 @@ @menu-select="handleTopMenuSelect" /> - + @@ -98,9 +98,14 @@ const topLevelMenuList = computed(() => { return menuList.value.map((item) => { const { children, ...rest } = item; return rest; - }); + }).filter(itv=>itv.name !== 'stage'); }); +// 后台管理点击获取列表 +const onStageManage = () =>{ + selectedTopMenu.value = '/stage'; +} + const topTitle = computed(() => { return ( topLevelMenuList.value.find((path) => path.path === selectedTopMenu.value) diff --git a/src/pages/Layout/rightMenuGroup.vue b/src/pages/Layout/rightMenuGroup.vue index 0052ebf..d6d7827 100644 --- a/src/pages/Layout/rightMenuGroup.vue +++ b/src/pages/Layout/rightMenuGroup.vue @@ -3,7 +3,7 @@
- +
@@ -53,6 +53,8 @@ defineOptions({ name: "RightMenuGroup" }); const userStore = useUserStore(); const tokenManager = TokenManager.getInstance(); const router = useRouter(); + +const emits = defineEmits(["on-stage-manage"]); const handleCommand = (command: string) => { if (command === "logout") { // 退出登录 @@ -61,6 +63,11 @@ const handleCommand = (command: string) => { } }; + +const onStageManage = () =>{ + emits('on-stage-manage') +} + // 获取当前的用户的数据信息 const userInfo = computed(() => { return userStore.userInfo; diff --git a/src/router/index.ts b/src/router/index.ts index 032af76..5bd627e 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,30 +1,34 @@ -import { createWebHistory, createRouter, type RouteRecordRaw } from 'vue-router' -import { useUserStore } from '@/store' -import { getRouteMenus } from '@/api' -import TokenManager from '@/utils/storage'; +import { + createWebHistory, + createRouter, + type RouteRecordRaw, +} from "vue-router"; +import { useUserStore } from "@/store"; +import { getRouteMenus } from "@/api"; +import TokenManager from "@/utils/storage"; -import Login from '@/pages/Login/index.vue'; -import HomeView from '@/pages/Layout/index.vue'; +import Login from "@/pages/Login/index.vue"; +import HomeView from "@/pages/Layout/index.vue"; const tokenManager = TokenManager.getInstance(); // 基础路由(不需要权限验证) const constantRoutes: RouteRecordRaw[] = [ - { - path: '/login', - name: 'Login', + { + path: "/login", + name: "Login", component: Login, - meta: { - title: '登录', - requiresAuth: false - } + meta: { + title: "登录", + requiresAuth: false, + }, }, -] +]; // 动态路由(需要权限验证) const asyncRoutes: RouteRecordRaw[] = [ { - path: '/', - name: 'Layout', + path: "/", + name: "Layout", component: HomeView, // redirect: '/home', meta: { @@ -32,61 +36,81 @@ const asyncRoutes: RouteRecordRaw[] = [ }, children: [] as RouteRecordRaw[], }, -] +]; const router = createRouter({ history: createWebHistory(), routes: [...constantRoutes, ...asyncRoutes], -}) +}); // 白名单路由(不需要登录即可访问) -const whiteList = ['/login'] +const whiteList = ["/login"]; // 1. 预先加载所有可能的页面组件 // 这里的路径模式要覆盖到你所有的业务组件 -const modules = import.meta.glob('@/pages/**/*.vue') +const modules = import.meta.glob("@/pages/**/*.vue"); const loadComponent = (componentPath: string) => { - if (!componentPath) return null + if (!componentPath) return null; // 统一路径格式处理 - let fullPath = '' + let fullPath = ""; - if (componentPath.startsWith('@/')) { - fullPath = componentPath - } else if (componentPath.includes('/')) { + if (componentPath.startsWith("@/")) { + fullPath = componentPath; + } else if (componentPath.includes("/")) { // 补全路径,确保以 @/pages 开头 - fullPath = componentPath.startsWith('pages/') ? `@/${componentPath}` : `@/pages/${componentPath}/index.vue` + fullPath = componentPath.startsWith("pages/") + ? `@/${componentPath}` + : `@/pages/${componentPath}/index.vue`; } else { // 补全 index.vue - fullPath = `@/pages/${componentPath}/index.vue` + fullPath = `@/pages/${componentPath}/index.vue`; } // 重点:将 @/ 转换为 /src/,因为 glob 默认生成的 key 是相对于项目根目录的 - const key = fullPath.replace('@/', '/src/') + const key = fullPath.replace("@/", "/src/"); // 从 modules 中查找对应的导入函数 if (modules[key]) { - return modules[key] + return modules[key]; } else { - console.error(`未找到组件文件: ${key}. 请检查路径或大小写。`) - return null + console.error(`未找到组件文件: ${key}. 请检查路径或大小写。`); + return null; } -} +}; // 将后端返回的路由数据转换为 Vue Router 路由 -const transformRoutes = (routes: any[], parentCode: string = ''): RouteRecordRaw[] => { +const transformRoutes = ( + routes: any[], + parentCode: string = "" +): RouteRecordRaw[] => { + console.log("transformRoutes", routes); return routes.flatMap((route) => { const fullCode = parentCode ? `${parentCode}/${route.code}` : route.code; - + // 如果当前路由有子路由,说明它是一个路由前缀,不需要组件 if (route.children && route.children.length > 0) { - // 将子路由的路径加上当前路由的前缀,然后递归处理 - return transformRoutes(route.children, fullCode); + const childRoutes = transformRoutes(route.children, fullCode); + if (route.code) { + // 创建一个父路由,将子路由作为其 children + const parentRoute: RouteRecordRaw = { + path: `/${fullCode}`, + name: route.code, + meta: { + title: route.name, + icon: route.icon, + ...route.meta, + }, + children: childRoutes, + }; + return parentRoute; + } else { + return childRoutes; + } } else { // 叶子节点才需要组件和路由配置 const component = fullCode ? loadComponent(fullCode) : undefined; - const routeRecord: any = { path: route.code, name: route.code, @@ -95,7 +119,7 @@ const transformRoutes = (routes: any[], parentCode: string = ''): RouteRecordRaw icon: route.icon, ...route.meta, }, - } + }; if (component) { routeRecord.component = component; @@ -104,135 +128,117 @@ const transformRoutes = (routes: any[], parentCode: string = ''): RouteRecordRaw return routeRecord as RouteRecordRaw; } }); -} +}; // 添加动态路由 const addDynamicRoutes = async () => { - const userStore = useUserStore() - + const userStore = useUserStore(); + // 如果路由已加载,直接返回 if (userStore.isRoutesLoaded) { - return + return; } try { - // TODO:从后端获取路由菜单数据 (这边需要区分 后台的菜单 和用户的菜单) - let response:any; + // 从后端获取路由菜单数据 (这边需要区分 后台的菜单 和用户的菜单) + let allRoutes:any[] = []; if (userStore.isBackendUser) { - const backendResponse = await getRouteMenus(); - response = [{ - code: 'stage', - name: '后台管理', - icon: '', - children: backendResponse, - }]; - }else{ + const backendResponse = await getRouteMenus(); + allRoutes = [ + { + code: "stage", + name: "后台管理", + icon: "", + children: backendResponse, + }, + ]; + } else { + // TODO:获取用户端的数据信息 // response = await getUserMenus(); - response = []; + allRoutes = []; } - if (response) { - const processRoutes = (routes: any[], prefix: string = ''): RouteRecordRaw[] => { - return routes.flatMap(route => { - const currentPath = prefix ? `${prefix}/${route.code}` : route.code; - - if (route.children && route.children.length > 0) { - // 如果有子路由,递归处理并添加当前路径作为前缀 - return processRoutes(route.children, currentPath); - } else { - // 叶子节点,创建路由记录 - const component = loadComponent(currentPath); - return { - path: route.code, - name: route.code, - component: component || HomeView, // 使用Layout的组件 - meta: { - title: route.name, - icon: route.icon, - ...route.meta, - } - } as RouteRecordRaw; - } - }); - }; + if (allRoutes) { // 转换路由数据 - // const dynamicRoutes = transformRoutes(Array.isArray(response) ? response : [response]) - const dynamicRoutes = processRoutes(Array.isArray(response) ? response : [response]) + const dynamicRoutes = transformRoutes( + Array.isArray(allRoutes) ? allRoutes : [allRoutes] + ); // 将动态路由添加到 Layout 的 children 中 - const layoutRoute = router.getRoutes().find(route => route.name === 'Layout') + const layoutRoute = router + .getRoutes() + .find((route) => route.name === "Layout"); if (layoutRoute) { - dynamicRoutes.forEach(route => { - router.addRoute('Layout', route) - }) + dynamicRoutes.forEach((route) => { + router.addRoute("Layout", route); + }); } else { // 如果找不到 Layout 路由,直接添加到根路由 - dynamicRoutes.forEach(route => { - router.addRoute(route) - }) + dynamicRoutes.forEach((route) => { + router.addRoute(route); + }); } - console.log('Layout route:', router.getRoutes()) // 保存路由数据到 store - userStore.setRoutes(response) - + userStore.setRoutes(dynamicRoutes); + // 标记路由已加载 - userStore.isRoutesLoaded = true + userStore.isRoutesLoaded = true; } } catch (error) { // 如果获取路由失败,清除用户数据并跳转到登录页 - userStore.clearUserData() - router.push('/login') + userStore.clearUserData(); + router.push("/login"); } -} +}; // 路由导航守卫 router.beforeEach(async (to, _from, next) => { - const userStore = useUserStore() - const accessToken = tokenManager.getToken('accessToken'); - + const userStore = useUserStore(); + const accessToken = tokenManager.getToken("accessToken"); + // 获取 token - const token = accessToken || userStore.token - + const token = accessToken || userStore.token; + // 如果已登录,更新 store 中的 token if (token) { - userStore.setToken(token) + userStore.setToken(token); } // 判断是否在白名单中 if (whiteList.includes(to.path)) { // 如果在白名单中且已登录,重定向到首页 if (token) { - next('/') + next("/"); } else { - next() + next(); } - return + return; } // 需要登录验证 if (!token) { // 未登录,重定向到登录页 next({ - path: '/login', + path: "/login", query: { redirect: to.fullPath }, // 保存当前路径,登录后可以跳转回来 - }) - return + }); + return; } // 已登录,检查路由是否已加载 if (!userStore.isRoutesLoaded) { try { // 加载动态路由 - await addDynamicRoutes() + await addDynamicRoutes(); // 路由加载完成后,重新导航到目标路由 - next({ ...to, replace: true }) + next({ ...to, replace: true }); } catch (error) { - console.error('Route loading error:', error) - next('/login') + console.error("Route loading error:", error); + next("/login"); } } else { // 路由已加载,直接放行 - next() + next(); } -}) +}); -export default router \ No newline at end of file +export default router;