// Author: fruit.com.cn import router, { resetRouter } from './router' import { useAppStoreWithOut } from '@/store/modules/app' import type { RouteRecordRaw } from 'vue-router' import { useTitle } from '@/hooks/web/useTitle' import { useNProgress } from '@/hooks/web/useNProgress' import { usePermissionStoreWithOut } from '@/store/modules/permission' import { usePageLoading } from '@/hooks/web/usePageLoading' import { NO_REDIRECT_WHITE_LIST } from '@/constants' import { useUserStoreWithOut } from '@/store/modules/user' import { getAdminRoleApi, getProfileApi } from '@/api/login' import { landingPath } from '@/utils/landing' const { start, done } = useNProgress() const { loadStart, loadDone } = usePageLoading() router.beforeEach(async (to, from, next) => { start() loadStart() const permissionStore = usePermissionStoreWithOut() const appStore = useAppStoreWithOut() const userStore = useUserStoreWithOut() if (userStore.getUserInfo) { if (to.path === '/login') { next({ path: '/' }) } else { if (permissionStore.getIsAddRouters) { // 已加过路由:只有还是同一个账号才能直接放行。 // 换账号时(例如超管退出后创作者登录)必须重建,否则侧边栏/路由会残留上一个账号的 const username = userStore.getUserInfo?.username || '' if (permissionStore.getRoutersOwner === username) { next() return } // 摘掉上一个账号动态加进去的路由,避免两套菜单并存 resetRouter() permissionStore.setIsAddRouters(false) } const username = userStore.getUserInfo?.username || '' const ownerChanged = permissionStore.getRoutersOwner !== username // 开发者可根据实际情况进行修改 const roleRouters = userStore.getRoleRouters || [] // 是否使用动态路由 if (appStore.getDynamicRouter) { if (appStore.serverDynamicRouter) { // 每次进入应用都重新拉菜单与权限:后台改了菜单或角色权限,刷新即可生效,不必重新登录 let routers = (userStore.getRoleRouters || []) as AppCustomRouteRecordRaw[] try { const [profileRes, menuRes] = await Promise.all([ getProfileApi(), getAdminRoleApi({ roleName: username }) ]) if (profileRes?.data) { userStore.setUserInfo({ ...userStore.getUserInfo, ...profileRes.data }) } if (menuRes?.data?.length) { routers = menuRes.data userStore.setRoleRouters(routers) } else if (ownerChanged) { // 换账号后菜单拉不到就别沿用上一个账号的缓存,宁可先给空菜单 routers = [] } } catch { // 拉取失败时退回上次缓存的菜单,不阻塞进入 } await permissionStore.generateRoutes('server', routers) } else { await permissionStore.generateRoutes('frontEnd', roleRouters as string[]) } } else { await permissionStore.generateRoutes('static') } permissionStore.getAddRouters.forEach((route) => { router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 }) permissionStore.setRoutersOwner(username) // 根路径按"这个账号能进的第一个菜单"落地:路由表里写死的 redirect 是 /dashboard/index, // 创作者没有运营后台权限,访问 '/' 会直接掉 404 if (to.path === '/') { permissionStore.setIsAddRouters(true) next({ path: landingPath(), replace: true }) return } const redirectPath = from.query.redirect || to.path const redirect = decodeURIComponent(redirectPath as string) const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } permissionStore.setIsAddRouters(true) next(nextData) } } else { if (NO_REDIRECT_WHITE_LIST.indexOf(to.path) !== -1) { next() } else { next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 } } }) router.afterEach((to) => { useTitle(to?.meta?.title as string) done() // 结束Progress loadDone() })