- lib/auth.ts: localStorage token 存储 + login/logout - app/login: 登录表单页 - components/AppShell: 视口驱动侧边栏 + 路由保护 - app/(app)/layout: 路由组布局套 AppShell - app/(app)/dashboard: 聚合统计卡片页 - app/(app)/classes: 迁移 CRUD 改用真实 JWT - app/page.tsx: 根路径重定向 - known-issues.md: 记录 P2 经验
78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
// 认证工具:token 存储 + 路由保护
|
||
|
||
const TOKEN_KEY = "edu_access_token";
|
||
const USER_KEY = "edu_user_info";
|
||
|
||
export interface UserInfo {
|
||
id: string;
|
||
email: string;
|
||
name: string;
|
||
roles: string[];
|
||
permissions: string[];
|
||
dataScope: string;
|
||
}
|
||
|
||
export function getToken(): string | null {
|
||
if (typeof window === "undefined") return null;
|
||
return localStorage.getItem(TOKEN_KEY);
|
||
}
|
||
|
||
export function setToken(token: string): void {
|
||
if (typeof window === "undefined") return;
|
||
localStorage.setItem(TOKEN_KEY, token);
|
||
}
|
||
|
||
export function clearToken(): void {
|
||
if (typeof window === "undefined") return;
|
||
localStorage.removeItem(TOKEN_KEY);
|
||
localStorage.removeItem(USER_KEY);
|
||
}
|
||
|
||
export function getUser(): UserInfo | null {
|
||
if (typeof window === "undefined") return null;
|
||
const raw = localStorage.getItem(USER_KEY);
|
||
if (!raw) return null;
|
||
try {
|
||
return JSON.parse(raw) as UserInfo;
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function setUser(user: UserInfo): void {
|
||
if (typeof window === "undefined") return;
|
||
localStorage.setItem(USER_KEY, JSON.stringify(user));
|
||
}
|
||
|
||
export function isAuthenticated(): boolean {
|
||
return getToken() !== null;
|
||
}
|
||
|
||
// 调用 Gateway 登录接口
|
||
export async function login(
|
||
email: string,
|
||
password: string,
|
||
): Promise<{ user: UserInfo; token: string }> {
|
||
const res = await fetch("/api/v1/iam/login", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ email, password }),
|
||
});
|
||
const json = await res.json();
|
||
if (!json.success) {
|
||
throw new Error(json.error?.message || "登录失败");
|
||
}
|
||
const user = json.data.user as UserInfo;
|
||
const token = json.data.tokens.accessToken as string;
|
||
setToken(token);
|
||
setUser(user);
|
||
return { user, token };
|
||
}
|
||
|
||
export function logout(): void {
|
||
clearToken();
|
||
if (typeof window !== "undefined") {
|
||
window.location.href = "/login";
|
||
}
|
||
}
|