2026-03-18 15:05:37 +08:00
|
|
|
import { useState, useEffect } from 'react';
|
2026-03-18 18:50:26 +08:00
|
|
|
import { FileText, Box } from 'lucide-react';
|
2026-03-18 14:22:07 +08:00
|
|
|
import { ApiDocViewer } from './components/ApiDocViewer';
|
|
|
|
|
import BlueprintPage from './components/blueprint/BlueprintPage';
|
|
|
|
|
import { config } from './config';
|
|
|
|
|
|
2026-03-18 18:50:26 +08:00
|
|
|
const _origLog = console.log;
|
|
|
|
|
const _origError = console.error;
|
|
|
|
|
const _origWarn = console.warn;
|
|
|
|
|
console.log = (...args) => { window.electronAPI?.log('log', ...args); _origLog.apply(console, args); };
|
|
|
|
|
console.error = (...args) => { window.electronAPI?.log('error', ...args); _origError.apply(console, args); };
|
|
|
|
|
console.warn = (...args) => { window.electronAPI?.log('warn', ...args); _origWarn.apply(console, args); };
|
|
|
|
|
|
2026-03-18 14:22:07 +08:00
|
|
|
type Page = 'docs' | 'blueprint';
|
2026-03-18 14:09:06 +08:00
|
|
|
|
2026-03-18 15:05:37 +08:00
|
|
|
declare global {
|
|
|
|
|
interface Window {
|
|
|
|
|
electronAPI?: {
|
2026-03-18 18:50:26 +08:00
|
|
|
listDocsFiles: (basePath: string) => Promise<{ name: string; path: string; relativePath: string }[]>;
|
|
|
|
|
readDocFile: (filePath: string) => Promise<string | null>;
|
|
|
|
|
log: (level: string, ...args: unknown[]) => void;
|
2026-03-18 15:05:37 +08:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 14:09:06 +08:00
|
|
|
function App() {
|
2026-03-18 14:22:07 +08:00
|
|
|
const [currentPage, setCurrentPage] = useState<Page>('docs');
|
2026-03-18 15:05:37 +08:00
|
|
|
const [docsPath, setDocsPath] = useState<string>('');
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
document.title = config.projectName;
|
|
|
|
|
}, []);
|
2026-03-18 14:22:07 +08:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="h-screen flex flex-col">
|
|
|
|
|
<header className="h-12 bg-zinc-900 border-b border-zinc-800 flex items-center px-4 justify-between">
|
2026-03-18 15:05:37 +08:00
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<h1 className="text-sm font-medium text-white">{config.projectName}</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<nav className="flex gap-1">
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setCurrentPage('docs')}
|
|
|
|
|
className={`flex items-center gap-2 px-3 py-1.5 rounded text-sm ${
|
|
|
|
|
currentPage === 'docs'
|
|
|
|
|
? 'bg-zinc-800 text-white'
|
|
|
|
|
: 'text-zinc-400 hover:text-white hover:bg-zinc-800/50'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<FileText size={16} />
|
|
|
|
|
API 文档
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setCurrentPage('blueprint')}
|
|
|
|
|
className={`flex items-center gap-2 px-3 py-1.5 rounded text-sm ${
|
|
|
|
|
currentPage === 'blueprint'
|
|
|
|
|
? 'bg-zinc-800 text-white'
|
|
|
|
|
: 'text-zinc-400 hover:text-white hover:bg-zinc-800/50'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<Box size={16} />
|
|
|
|
|
3D 蓝图
|
|
|
|
|
</button>
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
2026-03-18 14:22:07 +08:00
|
|
|
</header>
|
|
|
|
|
<main className="flex-1 overflow-hidden">
|
2026-03-18 18:50:26 +08:00
|
|
|
{currentPage === 'docs' ? (
|
|
|
|
|
<ApiDocViewer onDocsPathChange={setDocsPath} />
|
|
|
|
|
) : (
|
|
|
|
|
<BlueprintPage docsPath={docsPath} />
|
|
|
|
|
)}
|
2026-03-18 14:22:07 +08:00
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-03-18 14:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-18 14:22:07 +08:00
|
|
|
export default App;
|