63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
|
|
import { useCallback, useState } from 'react'
|
|||
|
|
import { login as loginRequest } from '../api/auth'
|
|||
|
|
|
|||
|
|
// localStorage 键:记住登录态时把会话写在这里,刷新后仍处于登录态。
|
|||
|
|
const STORAGE_KEY = 'ip.auth'
|
|||
|
|
|
|||
|
|
interface Session {
|
|||
|
|
username: string
|
|||
|
|
token: string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function loadSession(): Session | null {
|
|||
|
|
try {
|
|||
|
|
const raw = localStorage.getItem(STORAGE_KEY)
|
|||
|
|
if (!raw) return null
|
|||
|
|
const parsed = JSON.parse(raw) as Partial<Session>
|
|||
|
|
if (typeof parsed.username === 'string' && typeof parsed.token === 'string') {
|
|||
|
|
return { username: parsed.username, token: parsed.token }
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
// 解析失败(被手动改坏等)当作未登录
|
|||
|
|
}
|
|||
|
|
return null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface Auth {
|
|||
|
|
/** 已登录则为当前用户名,否则为 null */
|
|||
|
|
username: string | null
|
|||
|
|
/** 校验凭据;remember 为 true 时持久化到 localStorage */
|
|||
|
|
signIn: (username: string, password: string, remember: boolean) => Promise<void>
|
|||
|
|
/** 退出登录并清除持久化会话 */
|
|||
|
|
signOut: () => void
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 登录态管理。初始值从 localStorage 恢复(记住登录态),
|
|||
|
|
* 因此刷新页面后仍停留在登录后界面。
|
|||
|
|
*/
|
|||
|
|
export function useAuth(): Auth {
|
|||
|
|
const [session, setSession] = useState<Session | null>(loadSession)
|
|||
|
|
|
|||
|
|
const signIn = useCallback(
|
|||
|
|
async (username: string, password: string, remember: boolean) => {
|
|||
|
|
const result = await loginRequest(username, password)
|
|||
|
|
const next: Session = { username: result.username, token: result.token }
|
|||
|
|
setSession(next)
|
|||
|
|
if (remember) {
|
|||
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(next))
|
|||
|
|
} else {
|
|||
|
|
localStorage.removeItem(STORAGE_KEY)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
[],
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
const signOut = useCallback(() => {
|
|||
|
|
setSession(null)
|
|||
|
|
localStorage.removeItem(STORAGE_KEY)
|
|||
|
|
}, [])
|
|||
|
|
|
|||
|
|
return { username: session?.username ?? null, signIn, signOut }
|
|||
|
|
}
|