125 lines
3.5 KiB
TypeScript
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>
|
|
);
|
|
}
|