update:登录路由验证

This commit is contained in:
ltx 2026-06-16 10:57:20 +08:00
parent 47ce6786aa
commit 1db0535a07
3 changed files with 153 additions and 19 deletions

2
.env
View File

@ -8,4 +8,4 @@ VITE_OPEN = true
VITE_OPEN_CDN = false
# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202606040917/'
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202606161054/'

View File

@ -81,6 +81,7 @@ import type { FormInstance, FormRules } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import { useRoutesList } from '/@/stores/routesList';
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
import { initBackEndControlRoutes } from '/@/router/backEnd';
import { Session } from '/@/utils/storage';
@ -93,6 +94,8 @@ const emit = defineEmits(['switchTab']);
const { t } = useI18n();
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const storesRoutesList = useRoutesList();
const { routesList } = storeToRefs(storesRoutesList);
const route = useRoute();
const router = useRouter();
const formRef = ref<FormInstance>();
@ -147,6 +150,77 @@ const onCaptchaChange = () => {
state.random = new Date().getTime();
};
const normalizeRoutePath = (path: string) => {
if (!path) return '/';
const normalizedPath = path.split('?')[0].replace(/\/+$/, '');
return normalizedPath || '/';
};
const flattenRoutePaths = (list: any[] = []) => {
const pathSet = new Set<string>();
const walk = (items: any[]) => {
items.forEach((item) => {
if (item?.path) pathSet.add(normalizeRoutePath(item.path));
if (item?.children?.length) walk(item.children);
});
};
walk(list);
return pathSet;
};
const getFirstAccessiblePath = (list: any[] = []): string => {
for (const item of list) {
if (!item || item.meta?.isHide) continue;
if (item.children?.length) {
const childPath = getFirstAccessiblePath(item.children);
if (childPath) return childPath;
}
if (item.redirect && item.redirect !== '/login') {
return item.redirect;
}
if (item.path && item.path !== '/' && item.path !== '/login') {
return item.path;
}
}
return '/';
};
const canAccessRedirectRoute = (path: string) => {
if (!path || path === '/login') return false;
const resolved = router.resolve(path);
const lastMatchedRoute = resolved.matched[resolved.matched.length - 1];
if (!lastMatchedRoute || lastMatchedRoute.name === 'notFound') return false;
const routePathSet = flattenRoutePaths(routesList.value as any[]);
return routePathSet.has(normalizeRoutePath(lastMatchedRoute.path));
};
const getRedirectQuery = () => {
const queryParams = route.query?.params;
if (typeof queryParams !== 'string' || !queryParams) return undefined;
try {
const parsedQuery = JSON.parse(queryParams);
return parsedQuery && typeof parsedQuery === 'object' ? parsedQuery : undefined;
} catch {
return undefined;
}
};
const getRedirectTarget = () => {
const redirectPath = typeof route.query?.redirect === 'string' ? route.query.redirect : '';
if (canAccessRedirectRoute(redirectPath)) {
return {
path: redirectPath,
query: getRedirectQuery(),
};
}
if (redirectPath) {
// ElMessage.warning('无权访问目标页面,已为您跳转首页');
}
return {
path: getFirstAccessiblePath(routesList.value as any[]),
};
};
const onSignIn = async () => {
formRef.value!.validate(async (valid) => {
if (valid) {
@ -169,20 +243,13 @@ const onSignIn = async () => {
});
};
const signInSuccess = (isNoPower) => {
const signInSuccess = (isNoPower: boolean | undefined) => {
if (isNoPower) {
ElMessage.warning('抱歉,该账号对应的角色未配置任何权限');
Session.clear();
} else {
let currentTimeInfo = currentTime.value;
if (route.query?.redirect) {
router.push({
path: route.query?.redirect,
query: Object.keys(route.query?.params).length > 0 ? JSON.parse(route.query?.params) : '',
});
} else {
router.push('/');
}
router.push(getRedirectTarget());
const signInText = t('message.signInText');
ElMessage.success(`${currentTimeInfo},${signInText}`);
NextLoading.start();
@ -197,7 +264,7 @@ const goToRegister = () => {
emit('switchTab', 'register');
};
const enterHandler = async (event) => {
const enterHandler = async (event: KeyboardEvent) => {
if (event.key === 'Enter') {
await onSignIn();
}

View File

@ -62,6 +62,7 @@ import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import { useRoutesList } from '/@/stores/routesList';
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
import { initBackEndControlRoutes } from '/@/router/backEnd';
import { Session } from '/@/utils/storage';
@ -74,6 +75,8 @@ const emit = defineEmits(['switchTab']);
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const storesRoutesList = useRoutesList();
const { routesList } = storeToRefs(storesRoutesList);
const route = useRoute();
const router = useRouter();
const formRef = ref<FormInstance>();
@ -158,20 +161,84 @@ const onSmsLogin = async () => {
});
};
const normalizeRoutePath = (path: string) => {
if (!path) return '/';
const normalizedPath = path.split('?')[0].replace(/\/+$/, '');
return normalizedPath || '/';
};
const flattenRoutePaths = (list: any[] = []) => {
const pathSet = new Set<string>();
const walk = (items: any[]) => {
items.forEach((item) => {
if (item?.path) pathSet.add(normalizeRoutePath(item.path));
if (item?.children?.length) walk(item.children);
});
};
walk(list);
return pathSet;
};
const getFirstAccessiblePath = (list: any[] = []): string => {
for (const item of list) {
if (!item || item.meta?.isHide) continue;
if (item.children?.length) {
const childPath = getFirstAccessiblePath(item.children);
if (childPath) return childPath;
}
if (item.redirect && item.redirect !== '/login') {
return item.redirect;
}
if (item.path && item.path !== '/' && item.path !== '/login') {
return item.path;
}
}
return '/';
};
const canAccessRedirectRoute = (path: string) => {
if (!path || path === '/login') return false;
const resolved = router.resolve(path);
const lastMatchedRoute = resolved.matched[resolved.matched.length - 1];
if (!lastMatchedRoute || lastMatchedRoute.name === 'notFound') return false;
const routePathSet = flattenRoutePaths(routesList.value as any[]);
return routePathSet.has(normalizeRoutePath(lastMatchedRoute.path));
};
const getRedirectQuery = () => {
const queryParams = route.query?.params;
if (typeof queryParams !== 'string' || !queryParams) return undefined;
try {
const parsedQuery = JSON.parse(queryParams);
return parsedQuery && typeof parsedQuery === 'object' ? parsedQuery : undefined;
} catch {
return undefined;
}
};
const getRedirectTarget = () => {
const redirectPath = typeof route.query?.redirect === 'string' ? route.query.redirect : '';
if (canAccessRedirectRoute(redirectPath)) {
return {
path: redirectPath,
query: getRedirectQuery(),
};
}
if (redirectPath) {
ElMessage.warning('无权访问目标页面,已为您跳转首页');
}
return {
path: getFirstAccessiblePath(routesList.value as any[]),
};
};
const signInSuccess = (isNoPower: boolean | undefined) => {
if (isNoPower) {
ElMessage.warning('抱歉,该账号对应的角色未配置任何权限');
Session.clear();
} else {
let currentTimeInfo = currentTime.value;
if (route.query?.redirect) {
router.push({
path: <string>route.query?.redirect,
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
});
} else {
router.push('/');
}
router.push(getRedirectTarget());
const signInText = '登录成功';
ElMessage.success(`${currentTimeInfo},${signInText}`);
NextLoading.start();