fix:登录增加记住密码 优化路由逻辑

This commit is contained in:
liangdong
2026-01-11 22:23:34 +08:00
parent 23a7285e29
commit 79e16909f0
3 changed files with 94 additions and 21 deletions

View File

@@ -110,12 +110,13 @@ const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
const tokenManager = TokenManager.getInstance();
const KEEP_KEY = "keep_login_remember";
const loginFormRef = ref<FormInstance>();
const loading = ref(false);
const loginForm = reactive({
username: "18280362106",
password: "123456789",
username: "",
password: "",
remember:false
});
@@ -159,22 +160,46 @@ const handleLogin = async () => {
userStore.setToken(refresh_token);
// 获取用户信息
userStore.setUserInfo(userInfo);
// TODO:记住密码功能
// 记住密码功能
if (loginForm.remember) {
const saveInfo = {
username: loginForm.username,
password: loginForm.password // TODO:密码要加密才行
};
tokenManager.setToken(KEEP_KEY, JSON.stringify(saveInfo));
} else {
// 如果用户取消勾选,则移除
tokenManager.removeToken(KEEP_KEY);
}
ElMessage.success("登录成功");
// 跳转到首页或之前访问的页面
const redirect = (route.query.redirect as string) || "/";
router.push(redirect);
const redirect = (route.query.redirect as string);
router.push({path:'/',query:redirect});
}
} catch (error: any) {
console.error("Login error:", error);
ElMessage.error(error.error || "登录失败,请稍后重试");
} finally {
loading.value = false;
}
});
};
onMounted(() => {
const savedInfo = tokenManager.getToken(KEEP_KEY);
if (savedInfo) {
try {
const { username, password } = JSON.parse(savedInfo);
loginForm.username = username;
loginForm.password = password;
loginForm.remember = true;
} catch (e) {
console.error("解析记住的密码失败", e);
}
}
});
</script>
<style lang="scss" scoped>

View File

@@ -128,6 +128,29 @@ const transformRoutes = (
}
});
};
/**
* 递归查找路由配置中的第一个有效路径(叶子节点)
*/
const getFirstValidPath = (routes: RouteRecordRaw[], parentPath: string = "") => {
for (const route of routes) {
// 拼接当前层级的完整路径
let currentPath = route.path.startsWith("/")
? route.path
: `${parentPath}/${route.path}`.replace(/\/+/g, "/");
// 如果有子路由,继续递归,并将当前路径传下去
if (route.children && route.children.length > 0) {
const childPath = getFirstValidPath(route.children, currentPath);
if (childPath) return childPath;
}
// 如果是叶子节点(有组件),返回拼接好的完整路径
if (route.component) {
return currentPath;
}
}
return "/";
};
// 添加动态路由
const addDynamicRoutes = async () => {
@@ -150,9 +173,11 @@ const addDynamicRoutes = async () => {
name: "管理中心",
icon: "",
meta: {
title:'管理中心'
title: "管理中心",
},
children: Object.keys(backendResponse).length ? backendResponse : mockBackendMenuData,
children: Object.keys(backendResponse).length
? backendResponse
: mockBackendMenuData,
},
];
} else {
@@ -222,7 +247,7 @@ router.beforeEach(async (to, _from, next) => {
// 未登录,重定向到登录页
next({
path: "/login",
query: { redirect: to.fullPath }, // 保存当前路径,登录后可以跳转回来
query: { redirect: to.fullPath },
});
return;
}
@@ -232,16 +257,30 @@ router.beforeEach(async (to, _from, next) => {
try {
// 加载动态路由
await addDynamicRoutes();
console.log("当前完整路由表:", router.getRoutes());
const redirect = to.query.redirect as string;
if (to.path === "/" || to.path === "/login") {
const redirect = to.query.redirect as string;
const firstPath = getFirstValidPath(userStore.routes);
const targetPath = (redirect && redirect !== '/') ? redirect : firstPath;
next({ path: targetPath, replace: true });
} else {
// 路由加载完成后,重新导航到目标路由
next({ ...to, replace: true });
}
} catch (error) {
console.error("Route loading error:", error);
next("/login");
}
} else {
// 路由已加载,直接放行
if (to.path === "/") {
const firstPath = getFirstValidPath(userStore.routes);
next({ path: firstPath, replace: true });
} else {
next();
}
}
});
export default router;

View File

@@ -2,11 +2,16 @@ class TokenManager {
private static instance: TokenManager | null = null;
private storage: Storage;
private constructor(storageType: 'localStorage' | 'sessionStorage' = 'localStorage') {
this.storage = storageType === 'localStorage' ? localStorage : sessionStorage;
private constructor(
storageType: "localStorage" | "sessionStorage" = "localStorage"
) {
this.storage =
storageType === "localStorage" ? localStorage : sessionStorage;
}
public static getInstance(storageType: 'localStorage' | 'sessionStorage' = 'localStorage'): TokenManager {
public static getInstance(
storageType: "localStorage" | "sessionStorage" = "localStorage"
): TokenManager {
if (!TokenManager.instance) {
TokenManager.instance = new TokenManager(storageType);
}
@@ -25,9 +30,13 @@ class TokenManager {
this.storage.removeItem(key);
}
clearStorage(): void {
this.storage.clear();
const PROTECT_PREFIX = "keep_";
Object.keys(this.storage).forEach((key) => {
if (!key.startsWith(PROTECT_PREFIX)) {
this.storage.removeItem(key);
}
});
}
}
export default TokenManager;