Compare commits

...

2 Commits

Author SHA1 Message Date
Soybean
91de4a8ef7 chore(deps): update deps 2024-11-15 12:41:33 +08:00
Soybean
09144dfe93 refactor(projects): refactor router guard. fix #655 (#667) 2024-11-15 12:39:57 +08:00
8 changed files with 1109 additions and 1074 deletions

View File

@@ -54,51 +54,51 @@
"@sa/hooks": "workspace:*",
"@sa/materials": "workspace:*",
"@sa/utils": "workspace:*",
"@vueuse/core": "11.1.0",
"@vueuse/core": "11.2.0",
"clipboard": "2.0.11",
"dayjs": "1.11.13",
"echarts": "5.5.1",
"json5": "2.2.3",
"naive-ui": "2.40.1",
"nprogress": "0.2.0",
"pinia": "2.2.4",
"pinia": "2.2.6",
"tailwind-merge": "2.5.4",
"vue": "3.5.12",
"vue-draggable-plus": "0.5.4",
"vue-draggable-plus": "0.6.0",
"vue-i18n": "10.0.4",
"vue-router": "4.4.5"
},
"devDependencies": {
"@elegant-router/vue": "0.3.8",
"@iconify/json": "2.2.263",
"@iconify/json": "2.2.272",
"@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.4.2",
"@types/node": "22.7.9",
"@types/node": "22.9.0",
"@types/nprogress": "0.2.3",
"@unocss/eslint-config": "0.63.6",
"@unocss/preset-icons": "0.63.6",
"@unocss/preset-uno": "0.63.6",
"@unocss/transformer-directives": "0.63.6",
"@unocss/transformer-variant-group": "0.63.6",
"@unocss/vite": "0.63.6",
"@vitejs/plugin-vue": "5.1.4",
"@vitejs/plugin-vue-jsx": "4.0.1",
"eslint": "9.13.0",
"eslint-plugin-vue": "9.29.1",
"@unocss/eslint-config": "0.64.0",
"@unocss/preset-icons": "0.64.0",
"@unocss/preset-uno": "0.64.0",
"@unocss/transformer-directives": "0.64.0",
"@unocss/transformer-variant-group": "0.64.0",
"@unocss/vite": "0.64.0",
"@vitejs/plugin-vue": "5.2.0",
"@vitejs/plugin-vue-jsx": "4.1.0",
"eslint": "9.14.0",
"eslint-plugin-vue": "9.31.0",
"lint-staged": "15.2.10",
"sass": "1.80.4",
"sass": "1.81.0",
"simple-git-hooks": "2.11.1",
"tsx": "4.19.1",
"tsx": "4.19.2",
"typescript": "5.6.3",
"unplugin-icons": "0.19.3",
"unplugin-icons": "0.20.1",
"unplugin-vue-components": "0.27.4",
"vite": "5.4.10",
"vite": "5.4.11",
"vite-plugin-progress": "0.0.7",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-devtools": "7.5.4",
"vite-plugin-vue-devtools": "7.6.4",
"vue-eslint-parser": "9.4.3",
"vue-tsc": "2.1.6"
"vue-tsc": "2.1.10"
},
"simple-git-hooks": {
"commit-msg": "pnpm sa git-commit-verify",

View File

@@ -13,8 +13,8 @@
}
},
"dependencies": {
"@alova/mock": "2.0.8",
"@alova/mock": "2.0.9",
"@sa/utils": "workspace:*",
"alova": "3.1.1"
"alova": "3.2.3"
}
}

View File

@@ -16,6 +16,6 @@
"qs": "6.13.0"
},
"devDependencies": {
"@types/qs": "6.9.16"
"@types/qs": "6.9.17"
}
}

View File

@@ -14,14 +14,14 @@
},
"devDependencies": {
"@soybeanjs/changelog": "0.3.24",
"bumpp": "9.7.1",
"bumpp": "9.8.1",
"c12": "2.0.1",
"cac": "6.7.14",
"consola": "3.2.3",
"enquirer": "2.4.1",
"execa": "9.4.1",
"execa": "9.5.1",
"kolorist": "1.8.0",
"npm-check-updates": "17.1.4",
"npm-check-updates": "17.1.11",
"rimraf": "6.0.1"
}
}

View File

@@ -14,7 +14,7 @@
"crypto-js": "4.2.0",
"klona": "2.0.6",
"localforage": "1.10.0",
"nanoid": "5.0.7"
"nanoid": "5.0.8"
},
"devDependencies": {
"@types/crypto-js": "4.2.2"

1946
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -36,54 +36,34 @@ export function createRouteGuard(router: Router) {
const routeRoles = to.meta.roles || [];
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role));
const hasAuth = authStore.isStaticSuper || !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 it 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,
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 });
}
}
];
// if it is login route when logged in, then switch to the root page
if (to.name === loginRoute && isLogin) {
next({ name: rootRoute });
return;
}
routeSwitches.some(({ condition, callback }) => {
if (condition) {
callback();
}
// if the route does not need login, then it is allowed to access directly
if (!needLogin) {
handleRouteSwitch(to, from, next);
return;
}
return condition;
});
// the route need login but the user is not logged in, then switch to the login page
if (!isLogin) {
next({ name: loginRoute, query: { redirect: to.fullPath } });
return;
}
// if the user is logged in but does not have authorization, then switch to the 403 page
if (!hasAuth) {
next({ name: noAuthorizationRoute });
return;
}
// switch route normally
handleRouteSwitch(to, from, next);
});
}
@@ -93,7 +73,6 @@ export function createRouteGuard(router: Router) {
* @param to to route
*/
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
const authStore = useAuthStore();
const routeStore = useRouteStore();
const notFoundRoute: RouteKey = 'not-found';
@@ -105,8 +84,48 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
// 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
const path = to.fullPath;
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};
return location;
}
const isLogin = Boolean(localStg.get('token'));
if (!isLogin) {
// if the user is not logged in and the route is a constant route but not the "not-found" route, then it is allowed to access.
if (to.meta.constant && !isNotFoundRoute) {
routeStore.onRouteSwitchWhenNotLoggedIn();
return null;
}
// if the user is not logged in, then switch to the login page
const loginRoute: RouteKey = 'login';
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome);
const location: RouteLocationRaw = {
name: loginRoute,
query
};
return location;
}
if (!routeStore.isInitAuthRoute) {
// 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 path = to.fullPath;
const rootRoute: RouteKey = 'root';
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;
const location: RouteLocationRaw = {
path,
@@ -119,63 +138,21 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
}
}
// 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) {
if (!isNotFoundRoute) {
routeStore.onRouteSwitchWhenLoggedIn();
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';
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('token'));
// 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 query = getRouteQueryOfLoginRoute(to, routeStore.routeHome);
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
const noPermissionRoute: RouteKey = '403';
if (exist) {
const location: RouteLocationRaw = {
name: loginRoute,
query
};
return location;
}
await authStore.initUserInfo();
// 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
name: noPermissionRoute
};
return location;

View File

@@ -310,6 +310,14 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
return getSelectedMenuKeyPathByKey(selectedKey, menus.value);
}
async function onRouteSwitchWhenLoggedIn() {
authStore.initUserInfo();
}
async function onRouteSwitchWhenNotLoggedIn() {
// some global init logic if it does not need to be logged in
}
return {
resetStore,
routeHome,
@@ -326,6 +334,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
isInitAuthRoute,
setIsInitAuthRoute,
getIsAuthRouteExist,
getSelectedMenuKeyPath
getSelectedMenuKeyPath,
onRouteSwitchWhenLoggedIn,
onRouteSwitchWhenNotLoggedIn
};
});