初始化提交

This commit is contained in:
2025-12-14 15:25:31 +08:00
commit 4fa42f7115
48 changed files with 8718 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
import { useState, useEffect } from 'react';
import type { ServerConfig } from './types';
import { loadServers, saveServers, removeServer } from './utils/storage';
import { useServerMonitor } from './hooks/useServerMonitor';
import { ServerCard } from './components/ServerCard/ServerCard';
import { ServerDetail } from './components/ServerDetail/ServerDetail';
import './App.css';
function App() {
const [servers, setServers] = useState<ServerConfig[]>([]);
const [showAddForm, setShowAddForm] = useState(false);
const [selectedServerId, setSelectedServerId] = useState<string | null>(null);
const [newServerForm, setNewServerForm] = useState({ name: '', url: '' });
const statuses = useServerMonitor(servers, 2000);
useEffect(() => {
const loaded = loadServers();
setServers(loaded);
}, []);
const handleAddServer = () => {
if (!newServerForm.name || !newServerForm.url) {
alert('请填写服务器名称和地址');
return;
}
const newServer: ServerConfig = {
id: Date.now().toString(),
name: newServerForm.name,
url: newServerForm.url,
enabled: true,
};
const updated = [...servers, newServer];
setServers(updated);
saveServers(updated);
setNewServerForm({ name: '', url: '' });
setShowAddForm(false);
};
const handleRemoveServer = (serverId: string) => {
if (confirm('确定要移除这个服务器吗?')) {
const updated = servers.filter(s => s.id !== serverId);
setServers(updated);
removeServer(serverId);
}
};
const handleShowDetail = (serverId: string) => {
setSelectedServerId(serverId);
};
const selectedStatus = selectedServerId ? statuses[selectedServerId] : null;
const selectedServer = servers.find(s => s.id === selectedServerId);
return (
<div className="app">
<header className="app-header">
<h1>
<img className="app-logo" src="/logo.png" alt="萌芽监控面板" />
</h1>
<button className="btn-add" onClick={() => setShowAddForm(!showAddForm)} title={showAddForm ? '取消' : '添加服务器'}>
{showAddForm ? '×' : '+'}
</button>
</header>
{showAddForm && (
<div className="add-form">
<input
type="text"
placeholder="服务器名称"
value={newServerForm.name}
onChange={(e) => setNewServerForm({ ...newServerForm, name: e.target.value })}
/>
<input
type="text"
placeholder="服务器地址 (例如: http://192.168.1.100:9292)"
value={newServerForm.url}
onChange={(e) => setNewServerForm({ ...newServerForm, url: e.target.value })}
/>
<button className="btn-submit" onClick={handleAddServer}>
</button>
</div>
)}
<main className="server-grid">
{servers.length === 0 ? (
<div className="empty-state">
<p></p>
<p className="hint">"添加服务器"使</p>
</div>
) : (
servers.map((server) => {
const status = statuses[server.id];
// Calculate storage usage (max of all mounts)
const storageUsage = status?.metrics?.storage?.reduce((max, s) => Math.max(max, s.usedPercent), 0) || 0;
return (
<ServerCard
key={server.id}
server={server}
online={status?.online || false}
metrics={status?.metrics}
cpuUsage={status?.metrics?.cpu.usagePercent || 0}
memoryUsage={status?.metrics?.memory.usedPercent || 0}
storageUsage={storageUsage} // Pass max storage usage
uptime={status?.metrics?.uptimeSeconds}
onDetail={handleShowDetail}
onRemove={handleRemoveServer}
/>
);
})
)}
</main>
{selectedStatus?.metrics && selectedServer && (
<ServerDetail
metrics={selectedStatus.metrics}
serverName={selectedServer.name}
onClose={() => setSelectedServerId(null)}
/>
)}
</div>
);
}
export default App;