'use client' import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react' import { api, clearTokens, getAccessToken, User, UserRole, LoginRequest, RegisterRequest } from '@/lib/api' interface AuthState { user: User | null isAuthenticated: boolean isLoading: boolean } interface AuthContextType extends AuthState { login: (credentials: LoginRequest) => Promise<{ success: boolean; error?: string }> register: (data: RegisterRequest) => Promise<{ success: boolean; error?: string }> logout: () => void switchRole: (role: UserRole) => void } const AuthContext = createContext(undefined) const USER_STORAGE_KEY = 'miaosi_user' // 开发模式:使用 mock 数据 export const USE_MOCK = process.env.NEXT_PUBLIC_USE_MOCK === 'true' || process.env.NODE_ENV === 'development' // Mock 用户数据 const MOCK_USERS: Record = { 'creator@demo.com': { id: 'user-001', name: '达人小美', email: 'creator@demo.com', role: 'creator', is_verified: true, creator_id: 'CR123456', tenant_id: 'BR001', tenant_name: '美妆品牌A', password: 'demo123', }, 'agency@demo.com': { id: 'user-002', name: '张经理', email: 'agency@demo.com', role: 'agency', is_verified: true, agency_id: 'AG123456', tenant_id: 'BR001', tenant_name: '美妆品牌A', password: 'demo123', }, 'brand@demo.com': { id: 'user-003', name: '李总监', email: 'brand@demo.com', role: 'brand', is_verified: true, brand_id: 'BR001', tenant_id: 'BR001', tenant_name: '美妆品牌A', password: 'demo123', }, } export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null) const [isLoading, setIsLoading] = useState(true) // 初始化时从 localStorage 恢复登录状态 useEffect(() => { if (typeof window !== 'undefined') { // 检查是否有 token const token = getAccessToken() const storedUser = localStorage.getItem(USER_STORAGE_KEY) if (token && storedUser) { try { const parsed = JSON.parse(storedUser) setUser(parsed) } catch { clearTokens() localStorage.removeItem(USER_STORAGE_KEY) } } } setIsLoading(false) }, []) const login = useCallback(async (credentials: LoginRequest): Promise<{ success: boolean; error?: string }> => { try { if (USE_MOCK) { // Mock 登录 await new Promise((resolve) => setTimeout(resolve, 500)) const email = credentials.email || '' const mockUser = MOCK_USERS[email] if (!mockUser) { return { success: false, error: '用户不存在' } } // 验证码登录或密码登录 if (credentials.email_code) { // 验证码登录 mock: 任何验证码都通过 } else if (mockUser.password !== credentials.password) { return { success: false, error: '密码错误' } } const { password: _, ...userWithoutPassword } = mockUser setUser(userWithoutPassword) localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(userWithoutPassword)) return { success: true } } // 真实 API 登录 const response = await api.login(credentials) setUser(response.user) localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(response.user)) return { success: true } } catch (err) { const error = err instanceof Error ? err.message : '登录失败' return { success: false, error } } }, []) const register = useCallback(async (data: RegisterRequest): Promise<{ success: boolean; error?: string }> => { try { if (USE_MOCK) { // Mock 注册(直接登录) await new Promise((resolve) => setTimeout(resolve, 500)) const mockUser: User = { id: `user-${Date.now()}`, email: data.email, phone: data.phone, name: data.name, role: data.role, is_verified: false, } setUser(mockUser) localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(mockUser)) return { success: true } } // 真实 API 注册 const response = await api.register(data) setUser(response.user) localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(response.user)) return { success: true } } catch (err) { const error = err instanceof Error ? err.message : '注册失败' return { success: false, error } } }, []) const logout = useCallback(() => { setUser(null) clearTokens() localStorage.removeItem(USER_STORAGE_KEY) }, []) const switchRole = useCallback((role: UserRole) => { if (user) { const updated = { ...user, role } setUser(updated) localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(updated)) } }, [user]) return ( {children} ) } export function useAuth() { const context = useContext(AuthContext) if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider') } return context }