'use client'; import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; interface User { id: number; username: string; email: string; avatar?: string; points: number; role: string; status: number; last_login_at?: string; created_at: string; updated_at: string; totalSkins?: number; totalDownloads?: number; } interface AuthContextType { user: User | null; isLoading: boolean; isAuthenticated: boolean; login: (username: string, password: string) => Promise; register: (username: string, email: string, password: string, verificationCode: string) => Promise; logout: () => void; updateUser: (userData: Partial) => void; refreshUser: () => Promise; } const API_BASE_URL = 'http://localhost:8080/api/v1'; const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); // Check if user is logged in on mount useEffect(() => { const checkAuthStatus = async () => { const token = localStorage.getItem('authToken'); if (token) { await refreshUser(); } else { setIsLoading(false); } }; checkAuthStatus(); }, []); const setAuthToken = (token: string) => { localStorage.setItem('authToken', token); }; const getAuthHeaders = () => { const token = localStorage.getItem('authToken'); return { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '', }; }; const login = async (username: string, password: string) => { setIsLoading(true); try { const response = await fetch(`${API_BASE_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password, }), }); const result = await response.json(); if (result.code === 200) { const { token, user_info } = result.data; setAuthToken(token); const userData: User = { id: user_info.id, username: user_info.username, email: user_info.email, avatar: user_info.avatar, points: user_info.points, role: user_info.role, status: user_info.status, last_login_at: user_info.last_login_at, created_at: user_info.created_at, updated_at: user_info.updated_at, }; setUser(userData); } else { throw new Error(result.message || '登录失败,请检查用户名和密码'); } } catch (error) { throw error instanceof Error ? error : new Error('登录失败,请检查用户名和密码'); } finally { setIsLoading(false); } }; const register = async (username: string, email: string, password: string, verificationCode: string) => { setIsLoading(true); try { const response = await fetch(`${API_BASE_URL}/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, email, password, verification_code: verificationCode, }), }); const result = await response.json(); if (result.code === 200) { const { token, user_info } = result.data; setAuthToken(token); const userData: User = { id: user_info.id, username: user_info.username, email: user_info.email, avatar: user_info.avatar, points: user_info.points, role: user_info.role, status: user_info.status, created_at: user_info.created_at, updated_at: user_info.updated_at, }; setUser(userData); } else { throw new Error(result.message || '注册失败,请稍后重试'); } } catch (error) { throw error instanceof Error ? error : new Error('注册失败,请稍后重试'); } finally { setIsLoading(false); } }; const refreshUser = async () => { try { const response = await fetch(`${API_BASE_URL}/user/profile`, { method: 'GET', headers: getAuthHeaders(), }); const result = await response.json(); if (result.code === 200) { const user_info = result.data; const userData: User = { id: user_info.id, username: user_info.username, email: user_info.email, avatar: user_info.avatar, points: user_info.points, role: user_info.role, status: user_info.status, last_login_at: user_info.last_login_at, created_at: user_info.created_at, updated_at: user_info.updated_at, }; setUser(userData); } else { // Token invalid or expired logout(); } } catch (error) { console.error('Failed to refresh user:', error); logout(); } finally { setIsLoading(false); } }; const logout = () => { setUser(null); localStorage.removeItem('authToken'); }; const updateUser = (userData: Partial) => { if (user) { setUser({ ...user, ...userData }); } }; const value: AuthContextType = { user, isLoading, isAuthenticated: !!user, login, register, logout, updateUser, refreshUser, }; return {children}; } export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }