Files
linux-mirror-browser/src/app/page.tsx

125 lines
3.5 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { FileBrowser } from '@/components/FileBrowser';
import { Header } from '@/components/Header';
import { Footer } from '@/components/Footer';
import { CommandModal } from '@/components/CommandModal';
import { LoginModal } from '@/components/LoginModal';
import { Config } from '@/types';
interface User {
id: number;
username: string;
email: string;
role: string;
}
export default function Home() {
const [config, setConfig] = useState<Config | null>(null);
const [loading, setLoading] = useState(true);
const [darkMode, setDarkMode] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
const [user, setUser] = useState<User | null>(null);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
useEffect(() => {
if (!mounted) return;
// 加载配置
fetch('/api/config')
.then(res => res.json())
.then(data => {
if (data.success) {
setConfig(data.data);
}
})
.catch(console.error)
.finally(() => setLoading(false));
// 检查本地存储的主题设置
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark' || (!savedTheme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
setDarkMode(true);
}
// 检查本地存储的登录状态
const savedUser = localStorage.getItem('user');
if (savedUser) {
try {
setUser(JSON.parse(savedUser));
} catch (error) {
console.error('解析用户数据失败:', error);
localStorage.removeItem('user');
}
}
}, [mounted]);
useEffect(() => {
if (!mounted) return;
if (darkMode) {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
}
}, [darkMode, mounted]);
// 防止hydration不匹配的loading状态
if (!mounted || loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="text-center">
<div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
<p className="mt-2 text-gray-600">...</p>
</div>
</div>
);
}
if (!config) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900">
<div className="text-center">
<p className="text-red-600"></p>
</div>
</div>
);
}
return (
<div className={`min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors duration-300`}>
<Header
config={config}
darkMode={darkMode}
onToggleTheme={() => setDarkMode(!darkMode)}
onOpenModal={() => setIsModalOpen(true)}
onLogin={() => setIsLoginModalOpen(true)}
user={user}
onUserChange={setUser}
/>
<main className="flex-1">
<FileBrowser config={config} user={user} />
</main>
<Footer />
<CommandModal
config={config}
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
/>
<LoginModal
isOpen={isLoginModalOpen}
onClose={() => setIsLoginModalOpen(false)}
onLogin={setUser}
/>
</div>
);
}