import { useState, useEffect } from 'react' import { useNavigate } from '@tanstack/react-router' import { Key, Lock, AlertCircle, Moon, Sun, HelpCircle, FileText, Terminal, Zap } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' import { WavesBackground } from '@/components/waves-background' import { useAnimation } from '@/hooks/use-animation' import { useTheme } from '@/components/use-theme' import { checkAuthStatus } from '@/lib/fetch-with-auth' import { cn } from '@/lib/utils' import { APP_FULL_NAME } from '@/lib/version' export function AuthPage() { const [token, setToken] = useState('') const [isValidating, setIsValidating] = useState(false) const [error, setError] = useState('') const [checkingAuth, setCheckingAuth] = useState(true) const navigate = useNavigate() const { enableWavesBackground, setEnableWavesBackground } = useAnimation() const { theme, setTheme } = useTheme() // 如果已经认证,直接跳转到首页 useEffect(() => { const verifyAuth = async () => { try { const isAuth = await checkAuthStatus() if (isAuth) { navigate({ to: '/' }) } } catch { // 忽略错误,保持在登录页 } finally { setCheckingAuth(false) } } verifyAuth() }, [navigate]) // 获取实际应用的主题(处理 system 情况) const getActualTheme = () => { if (theme === 'system') { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } return theme } const actualTheme = getActualTheme() // 主题切换(无动画) const toggleTheme = () => { const newTheme = actualTheme === 'dark' ? 'light' : 'dark' setTheme(newTheme) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setError('') if (!token.trim()) { setError('请输入 Access Token') return } setIsValidating(true) console.log('开始验证 token...') try { // 向后端发送请求验证 token(后端会设置 HttpOnly Cookie) const response = await fetch('/api/webui/auth/verify', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', // 确保接收并存储 Cookie body: JSON.stringify({ token: token.trim() }), }) console.log('Token 验证响应状态:', response.status) const data = await response.json() console.log('Token 验证响应数据:', data) if (response.ok && data.valid) { console.log('Token 验证成功,准备跳转...') console.log('is_first_setup:', data.is_first_setup) // Token 验证成功,Cookie 已由后端设置 // 等待一小段时间确保 Cookie 已设置 await new Promise(resolve => setTimeout(resolve, 100)) // 再次检查认证状态 const authCheck = await checkAuthStatus() console.log('跳转前认证状态检查:', authCheck) // 直接使用验证响应中的 is_first_setup 字段,避免额外请求 if (data.is_first_setup) { console.log('跳转到首次配置页面') // 需要首次配置,跳转到配置向导 navigate({ to: '/setup' }) } else { console.log('跳转到首页') // 不需要配置或配置已完成,跳转到首页 navigate({ to: '/' }) } } else { console.error('Token 验证失败:', data.message) setError(data.message || 'Token 验证失败,请检查后重试') } } catch (err) { console.error('Token 验证错误:', err) setError('连接服务器失败,请检查网络连接') } finally { setIsValidating(false) } } // 正在检查认证状态时显示加载 if (checkingAuth) { return (
{APP_FULL_NAME}