Files
xiaohh-tdesign-ui/src/permission.ts
T

90 lines
2.9 KiB
TypeScript

import 'nprogress/nprogress.css'; // progress bar style
import NProgress from 'nprogress'; // progress bar
import { MessagePlugin } from 'tdesign-vue-next';
import type { RouteRecordRaw } from 'vue-router';
import router from '@/router';
import { getPermissionStore, useUserStore } from '@/store';
import { normalizePath } from '@/utils/route';
import { PAGE_NOT_FOUND_ROUTE } from '@/utils/route/constant';
NProgress.configure({ showSpinner: false });
/** 在每次导航前检查登录状态、初始化权限路由并维护进度条。 */
router.beforeEach(async (to, from, next) => {
NProgress.start();
const permissionStore = getPermissionStore();
const { whiteListRouters } = permissionStore;
const userStore = useUserStore();
if (userStore.token) {
if (normalizePath(to.path) === '/login') {
next();
return;
}
try {
await userStore.getUserInfo();
const { asyncRoutes } = permissionStore;
// 用户资料加载成功后,首次进入受保护页面时再构建动态菜单路由。
if (asyncRoutes && asyncRoutes.length === 0) {
const routeList = await permissionStore.buildAsyncRoutes();
routeList.forEach((item: RouteRecordRaw) => {
router.addRoute(item);
});
// 路由刚添加时需要重新匹配当前 URL,避免首次导航落到 404。
if (to.name === PAGE_NOT_FOUND_ROUTE.name) {
// 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容
next({ path: to.fullPath, replace: true, query: to.query });
} else {
// 直接基于 to 重新导航以加载动态路由;
// 若用 from.query.redirect 手动拼接 path+query,当 redirect 带参(如 /dashboard/base?tab=1)时
// to.path !== redirect 恒成立,且显式 query 会覆盖 path 内嵌参数,导致参数丢失,故统一用 to。
next({ ...to, replace: true });
return;
}
}
if (router.hasRoute(to.name!)) {
next();
} else {
next(`/`);
}
} catch (error) {
MessagePlugin.error((error as Error).message);
next({
path: '/login',
query: { redirect: to.fullPath },
});
NProgress.done();
}
} else {
// 未登录用户仅可进入白名单;其他地址记录目标路径后转向登录页。
if (whiteListRouters.includes(normalizePath(to.path))) {
next();
} else {
next({
path: '/login',
query: { redirect: to.fullPath },
});
}
NProgress.done();
}
});
/** 路由完成后收尾进度条;进入登录页时同步清理用户和动态路由状态。 */
router.afterEach((to) => {
if (normalizePath(to.path) === '/login') {
const userStore = useUserStore();
const permissionStore = getPermissionStore();
userStore.logout();
permissionStore.restoreRoutes();
}
NProgress.done();
});