import React, { useState, useEffect, createContext, useContext } from 'react'; import { useQuery, useQueryClient, } from '@tanstack/react-query'; import axios from 'axios'; import 'dayjs/locale/zh-cn'; import type { AuthContextType } from '@/share/types'; import { authClient } from '@/client/api'; import type { InferResponseType, InferRequestType } from 'hono/client'; export type User = InferResponseType; // 创建认证上下文 const AuthContext = createContext | null>(null); // 认证提供器组件 export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [user, setUser] = useState(null); const [token, setToken] = useState(localStorage.getItem('token')); const [isAuthenticated, setIsAuthenticated] = useState(false); const queryClient = useQueryClient(); // 声明handleLogout函数 const handleLogout = async () => { try { // 如果已登录,调用登出API if (token) { await authClient.logout.$post(); } } catch (error) { console.error('登出请求失败:', error); } finally { // 清除本地状态 setToken(null); setUser(null); setIsAuthenticated(false); localStorage.removeItem('token'); // 清除Authorization头 delete axios.defaults.headers.common['Authorization']; console.log('登出时已删除全局Authorization头'); // 清除所有查询缓存 queryClient.clear(); } }; // 使用useQuery检查登录状态 const { isLoading } = useQuery({ queryKey: ['auth', 'status', token], queryFn: async () => { if (!token) { setIsAuthenticated(false); setUser(null); return null; } try { // 设置全局默认请求头 axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; // 使用API验证当前用户 const res = await authClient.me.$get(); if (res.status !== 200) { const result = await res.json(); throw new Error(result.message) } const currentUser = await res.json(); setUser(currentUser); setIsAuthenticated(true); return { isValid: true, user: currentUser }; } catch (error) { return { isValid: false }; } }, enabled: !!token, refetchOnWindowFocus: false, retry: false }); const handleLogin = async (username: string, password: string, latitude?: number, longitude?: number): Promise => { try { // 使用AuthAPI登录 const response = await authClient.login.$post({ json: { username, password } }) if (response.status !== 200) { const result = await response.json() throw new Error(result.message); } const result = await response.json() // 保存token和用户信息 const { token: newToken, user: newUser } = result; // 设置全局默认请求头 axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; // 保存状态 setToken(newToken); setUser(newUser); setIsAuthenticated(true); localStorage.setItem('token', newToken); } catch (error) { console.error('登录失败:', error); throw error; } }; return ( {children} ); }; // 使用上下文的钩子 export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth必须在AuthProvider内部使用'); } return context; };