86 lines
2.0 KiB
TypeScript
86 lines
2.0 KiB
TypeScript
"use client"
|
|
|
|
import { createContext, useContext, useState, useEffect, type ReactNode } from "react"
|
|
import { saveToken, clearToken, isTokenExpired } from "@/lib/api"
|
|
|
|
interface User {
|
|
readerId: number
|
|
username: string
|
|
email: string
|
|
phone: string
|
|
isAdmin: boolean
|
|
isBanned: boolean
|
|
}
|
|
|
|
interface AuthContextType {
|
|
user: User | null
|
|
token: string | null
|
|
login: (user: User, token: string) => void
|
|
logout: () => void
|
|
checkAuth: () => boolean
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined)
|
|
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null)
|
|
const [token, setToken] = useState<string | null>(null)
|
|
|
|
useEffect(() => {
|
|
// 从本地存储中恢复用户状态和token
|
|
const storedUser = localStorage.getItem("user")
|
|
const storedToken = localStorage.getItem("token")
|
|
|
|
// 检查 token 是否过期
|
|
if (isTokenExpired()) {
|
|
clearToken()
|
|
return
|
|
}
|
|
|
|
if (storedUser) {
|
|
try {
|
|
setUser(JSON.parse(storedUser))
|
|
} catch (error) {
|
|
console.error("Failed to parse stored user", error)
|
|
localStorage.removeItem("user")
|
|
}
|
|
}
|
|
|
|
if (storedToken) {
|
|
setToken(storedToken)
|
|
}
|
|
}, [])
|
|
|
|
const login = (userData: User, authToken: string) => {
|
|
setUser(userData)
|
|
setToken(authToken)
|
|
localStorage.setItem("user", JSON.stringify(userData))
|
|
saveToken(authToken)
|
|
}
|
|
|
|
const logout = () => {
|
|
setUser(null)
|
|
setToken(null)
|
|
clearToken()
|
|
}
|
|
|
|
// 检查用户是否已认证
|
|
const checkAuth = (): boolean => {
|
|
if (!token || isTokenExpired()) {
|
|
logout()
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
return <AuthContext.Provider value={{ user, token, login, logout, checkAuth }}>{children}</AuthContext.Provider>
|
|
}
|
|
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext)
|
|
if (context === undefined) {
|
|
throw new Error("useAuth must be used within an AuthProvider")
|
|
}
|
|
return context
|
|
}
|