2
0
Files
fe.wfc.user/src/router/guard/route.ts
2025-01-22 18:40:00 +08:00

270 lines
7.7 KiB
TypeScript

import type {
LocationQueryRaw,
NavigationGuardNext,
RouteLocationNormalized,
RouteLocationRaw,
Router
} from 'vue-router';
import type { RouteKey } from '@elegant-router/types';
import { useAuthStore } from '@/store/modules/auth';
import { useRouteStore } from '@/store/modules/route';
import { localStg } from '@/utils/storage';
import { getQueryParams } from "@/utils/common";
/**
* create route guard
*
* @param router router instance
*/
export function createRouteGuard(router: Router) {
router.beforeEach(async (to, from, next) => {
const routeLocation = await checkRoute(to);
if (routeLocation) {
next(routeLocation);
return;
}
const authStore = useAuthStore();
const rootRoute: RouteKey = 'root';
const loginRoute: RouteKey = 'login';
const noAuthorizationRoute: RouteKey = '403';
const isLogin = Boolean(localStg.get('tokenU'));
const needLogin = !to.meta.constant;
const routeRoles = to.meta.roles || [];
const hasRole = authStore.userInfo.roles?.some(role => routeRoles.includes(role));
const hasAuth = !routeRoles.length || hasRole;
const routeSwitches: CommonType.StrategicPattern[] = [
// if it is login route when logged in, then switch to the root page
{
condition: isLogin && to.name === loginRoute,
callback: () => {
next({ name: rootRoute });
}
},
// if is is constant route, then it is allowed to access directly
{
condition: !needLogin,
callback: () => {
handleRouteSwitch(to, from, next);
}
},
// if the route need login but the user is not logged in, then switch to the login page
{
condition: !isLogin && needLogin,
callback: () => {
next({ name: loginRoute, query: { redirect: to.fullPath } });
}
},
// if the user is logged in and has authorization, then it is allowed to access
{
condition: isLogin && needLogin && (hasAuth ?? false),
callback: () => {
handleRouteSwitch(to, from, next);
}
},
// if the user is logged in but does not have authorization, then switch to the 403 page
{
condition: isLogin && needLogin && !hasAuth,
callback: () => {
next({ name: noAuthorizationRoute });
}
}
];
routeSwitches.some(({ condition, callback }) => {
if (condition) {
callback();
}
return condition;
});
});
}
/**
* initialize route
*
* @param to to route
*/
async function checkRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
const routeStore = useRouteStore();
const notFoundRoute: RouteKey = 'not-found';
const isNotFoundRoute = to.name === notFoundRoute;
// 门户检查
checkRedirectParams();
// if the constant route is not initialized, then initialize the constant route
if (!routeStore.isInitConstantRoute) {
await routeStore.initConstantRoute();
// the route is captured by the "not-found" route because the constant route is not initialized
// after the constant route is initialized, redirect to the original route
if (isNotFoundRoute) {
const path = to.fullPath;
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};
return location;
}
}
// if the route is the constant route but is not the "not-found" route, then it is allowed to access.
if (to.meta.constant && !isNotFoundRoute) {
return null;
}
// the auth route is initialized
// it is not the "not-found" route, then it is allowed to access
if (routeStore.isInitAuthRoute && !isNotFoundRoute) {
return null;
}
// it is captured by the "not-found" route, then check whether the route exists
if (routeStore.isInitAuthRoute && isNotFoundRoute) {
// const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
const noPermissionRoute: RouteKey = '403';
return {
name: noPermissionRoute
} as RouteLocationRaw;
// if (exist) {
// const location: RouteLocationRaw = {
// name: noPermissionRoute
// };
// return location;
// }
// return null;
}
// if the auth route is not initialized, then initialize the auth route
const isLogin = Boolean(localStg.get('tokenU'));
// initialize the auth route requires the user to be logged in, if not, redirect to the login page
if (!isLogin) {
const loginRoute: RouteKey = 'login';
const redirect = to.fullPath;
const query: LocationQueryRaw = to.name !== loginRoute ? { redirect } : {};
const location: RouteLocationRaw = {
name: loginRoute,
query
};
return location;
}
// initialize the auth route
await routeStore.initAuthRoute();
// the route is captured by the "not-found" route because the auth route is not initialized
// after the auth route is initialized, redirect to the original route
if (isNotFoundRoute) {
const rootRoute: RouteKey = 'root';
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};
return location;
}
return null;
}
/**
* 检查门户重定向参数
*/
function checkRedirectParams(){
// console.log('checkRoute to', to)
// console.log('checkRoute location', location)
if (import.meta.env.VITE_ROUTER_HISTORY_MODE === 'hash') {
const queryParams = getQueryParams(window.location.search);
if (['site', 'clientMac'].every(s => Object.keys(queryParams).includes(s))) {
sessionStg.set<any>('wanfiRedirectParams', queryParams);
}
} else if (import.meta.env.VITE_ROUTER_HISTORY_MODE === 'history') {
let search = window.location.search;
const index = search.indexOf("?", 2);
if (index !== -1) {
search = search.slice(index);
}
const queryParams = getQueryParams(decodeURIComponent(search));
if (['site', 'clientMac'].every(s => Object.keys(queryParams).includes(s))) {
sessionStg.set<any>('wanfiRedirectParams', queryParams);
}
}
// 没有重定向参数强制从新获取
const wanfiRedirectParams = sessionStg.get('wanfiRedirectParams');
if (wanfiRedirectParams) {
if (!['site', 'clientMac'].every(s => Object.keys(wanfiRedirectParams).includes(s))) {
localStg.remove('tokenU');
sessionStg.remove('wanfiRedirectParams');
reLoadLocationHref();
}
} else {
reLoadLocationHref();
}
}
/**
* 重定向地址
*/
function reLoadLocationHref(){
if(import.meta.env.DEV){
const paramsObject = {
clientMac: "C2-83-E5-D2-17-C3",
clientIp: "192.168.2.51",
t: "1733370350",
site: "67333c27f6161a69b3e42efe",
redirectUrl: "http%3A%2F%2F192.168.9.59%2Flocal-u%2F%23%2Fhome",
apMac: "B0-19-21-7E-27-40",
ssidName: "TP-Link_OMC_Local",
radioId: "0"
};
// 获取当前页面的 URL
const currentUrl = window.location.origin;
// 使用 URLSearchParams 将对象转换为查询字符串
const searchParams = new URLSearchParams(paramsObject);
// 检查当前 URL 是否已经包含查询参数
const newUrl = currentUrl.includes('?')
? `${currentUrl}&${searchParams.toString()}`
: `${currentUrl}?${searchParams.toString()}`;
// 跳转到新的 URL
window.location.href = newUrl;
return
}
// window.location.href = `//8.8.8.8`;
}
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
// route with href
if (to.meta.href) {
window.open(to.meta.href, '_blank');
next({ path: from.fullPath, replace: true, query: from.query, hash: to.hash });
return;
}
next();
}