配置Vite代理、API请求封装、JWT认证上下文、登录页面、路由鉴权
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { createContext, useContext, useState, useCallback, type ReactNode } from 'react'
|
||||
import { setToken } from '@/services/request'
|
||||
import { login as loginApi, type LoginResult } from '@/services/api'
|
||||
|
||||
interface AuthState {
|
||||
user: LoginResult | null
|
||||
loading: boolean
|
||||
login: (username: string, password: string) => Promise<void>
|
||||
logout: () => void
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthState>({
|
||||
user: null, loading: false,
|
||||
login: async () => {}, logout: () => {},
|
||||
})
|
||||
|
||||
export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
const [user, setUser] = useState<LoginResult | null>(() => {
|
||||
const saved = localStorage.getItem('auth_user')
|
||||
if (saved) {
|
||||
const u = JSON.parse(saved) as LoginResult
|
||||
setToken(u.token)
|
||||
return u
|
||||
}
|
||||
return null
|
||||
})
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const login = useCallback(async (username: string, password: string) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await loginApi({ username, password })
|
||||
const u = res.data
|
||||
setToken(u.token)
|
||||
setUser(u)
|
||||
localStorage.setItem('auth_user', JSON.stringify(u))
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const logout = useCallback(() => {
|
||||
setToken('')
|
||||
setUser(null)
|
||||
localStorage.removeItem('auth_user')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, loading, login, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAuth = () => useContext(AuthContext)
|
||||
Reference in New Issue
Block a user