92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
|
|
/**
|
|||
|
|
* Cosmo - Deep Space Explorer
|
|||
|
|
* Main application component
|
|||
|
|
*/
|
|||
|
|
import { useState } from 'react';
|
|||
|
|
import { useSpaceData } from './hooks/useSpaceData';
|
|||
|
|
import { useTrajectory } from './hooks/useTrajectory';
|
|||
|
|
import { Scene } from './components/Scene';
|
|||
|
|
import { ProbeList } from './components/ProbeList';
|
|||
|
|
import { Loading } from './components/Loading';
|
|||
|
|
import type { CelestialBody } from './types';
|
|||
|
|
|
|||
|
|
function App() {
|
|||
|
|
const { bodies, loading, error } = useSpaceData();
|
|||
|
|
const [selectedBody, setSelectedBody] = useState<CelestialBody | null>(null);
|
|||
|
|
const { trajectoryPositions } = useTrajectory(selectedBody);
|
|||
|
|
|
|||
|
|
// Filter probes and planets from all bodies
|
|||
|
|
const probes = bodies.filter((b) => b.type === 'probe');
|
|||
|
|
const planets = bodies.filter((b) => b.type === 'planet');
|
|||
|
|
|
|||
|
|
const handleBodySelect = (body: CelestialBody | null) => {
|
|||
|
|
setSelectedBody(body);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (loading) {
|
|||
|
|
return <Loading />;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (error) {
|
|||
|
|
return (
|
|||
|
|
<div className="w-full h-full flex items-center justify-center bg-black text-white">
|
|||
|
|
<div className="text-center">
|
|||
|
|
<h1 className="text-2xl font-bold mb-4">数据加载失败</h1>
|
|||
|
|
<p className="text-red-400">{error}</p>
|
|||
|
|
<p className="mt-4 text-sm text-gray-400">
|
|||
|
|
请确保后端 API 运行在 http://localhost:8000
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="w-full h-full relative">
|
|||
|
|
{/* Title overlay */}
|
|||
|
|
<div className="absolute top-4 left-4 z-50 text-white">
|
|||
|
|
<h1 className="text-3xl font-bold mb-1">Cosmo</h1>
|
|||
|
|
<p className="text-sm text-gray-300">深空探测器可视化</p>
|
|||
|
|
<p className="text-xs text-gray-400 mt-1">
|
|||
|
|
{selectedBody ? `聚焦: ${selectedBody.name}` : `${bodies.length} 个天体`}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Probe List Sidebar */}
|
|||
|
|
<ProbeList
|
|||
|
|
probes={probes}
|
|||
|
|
planets={planets}
|
|||
|
|
onBodySelect={handleBodySelect}
|
|||
|
|
selectedBody={selectedBody}
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{/* 3D Scene */}
|
|||
|
|
<Scene
|
|||
|
|
bodies={bodies}
|
|||
|
|
selectedBody={selectedBody}
|
|||
|
|
trajectoryPositions={trajectoryPositions}
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
{/* Instructions overlay */}
|
|||
|
|
<div className="absolute bottom-4 right-4 z-50 text-white text-xs bg-black bg-opacity-70 p-3 rounded">
|
|||
|
|
{selectedBody ? (
|
|||
|
|
<>
|
|||
|
|
<p className="text-cyan-400 font-bold mb-2">聚焦模式</p>
|
|||
|
|
<p>点击侧边栏的"返回太阳系视图"按钮</p>
|
|||
|
|
</>
|
|||
|
|
) : (
|
|||
|
|
<>
|
|||
|
|
<p className="font-bold mb-2">太阳系俯视图</p>
|
|||
|
|
<p>🖱️ 左键拖动: 旋转</p>
|
|||
|
|
<p>🖱️ 右键拖动: 平移</p>
|
|||
|
|
<p>🖱️ 滚轮: 缩放</p>
|
|||
|
|
<p className="mt-2 text-gray-400">点击左侧天体列表查看详情</p>
|
|||
|
|
</>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default App;
|