1.AI 协作文档体系重构(objections/worklines/contracts+matrix.md) 2.coord 仲裁文档(final-decisions/cross-review/final-rulings/orchestration) 3.各服务 01/02 文档补全 4.共享包初始化(shared-ts/shared-go/hooks/ui-components/ui-tokens) 5.Proto 契约补全 6.004 架构影响地图更新 7.端口分配表 8.设计规格文档
94 lines
2.4 KiB
TypeScript
94 lines
2.4 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
||
import type { AuthState, UserSession } from "./types.js";
|
||
|
||
/**
|
||
* useAuth - 会话状态管理
|
||
*
|
||
* 用途:管理用户登录状态、token、用户信息。
|
||
* P2 阶段:token 存储在 localStorage(F12 裁决),P6 评估迁移 httpOnly Cookie。
|
||
*
|
||
* 注意:本 hook 提供"状态管理"骨架,具体的登录/登出 API 调用
|
||
* 由 apps/* 注入(通过 AuthProvider Context 或 props 传入 fetcher)。
|
||
*
|
||
* @example
|
||
* const { user, isAuthenticated, login, logout } = useAuth();
|
||
*/
|
||
|
||
const TOKEN_KEY = "edu_auth_token";
|
||
const USER_KEY = "edu_auth_user";
|
||
|
||
export interface UseAuthReturn extends AuthState {
|
||
/** 登录(由调用方注入 fetcher) */
|
||
login: (token: string, user: UserSession) => void;
|
||
/** 登出 */
|
||
logout: () => void;
|
||
/** 刷新用户信息 */
|
||
refreshUser: (user: UserSession) => void;
|
||
}
|
||
|
||
export function useAuth(): UseAuthReturn {
|
||
const [state, setState] = useState<AuthState>({
|
||
user: null,
|
||
token: null,
|
||
isAuthenticated: false,
|
||
isLoading: true,
|
||
});
|
||
|
||
// 初始化:从 localStorage 读取 token + user(F12 裁决 P2 用 localStorage)
|
||
useEffect(() => {
|
||
try {
|
||
const token = localStorage.getItem(TOKEN_KEY);
|
||
const userJson = localStorage.getItem(USER_KEY);
|
||
const user = userJson ? (JSON.parse(userJson) as UserSession) : null;
|
||
|
||
setState({
|
||
user,
|
||
token,
|
||
isAuthenticated: Boolean(token && user),
|
||
isLoading: false,
|
||
});
|
||
} catch {
|
||
setState({
|
||
user: null,
|
||
token: null,
|
||
isAuthenticated: false,
|
||
isLoading: false,
|
||
});
|
||
}
|
||
}, []);
|
||
|
||
const login = useCallback((token: string, user: UserSession): void => {
|
||
localStorage.setItem(TOKEN_KEY, token);
|
||
localStorage.setItem(USER_KEY, JSON.stringify(user));
|
||
setState({
|
||
user,
|
||
token,
|
||
isAuthenticated: true,
|
||
isLoading: false,
|
||
});
|
||
}, []);
|
||
|
||
const logout = useCallback((): void => {
|
||
localStorage.removeItem(TOKEN_KEY);
|
||
localStorage.removeItem(USER_KEY);
|
||
setState({
|
||
user: null,
|
||
token: null,
|
||
isAuthenticated: false,
|
||
isLoading: false,
|
||
});
|
||
}, []);
|
||
|
||
const refreshUser = useCallback((user: UserSession): void => {
|
||
localStorage.setItem(USER_KEY, JSON.stringify(user));
|
||
setState((prev) => ({ ...prev, user }));
|
||
}, []);
|
||
|
||
return {
|
||
...state,
|
||
login,
|
||
logout,
|
||
refreshUser,
|
||
};
|
||
}
|