auto-sync: 2026-05-17 06:16:51
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// App 主入口
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { TaskBoard } from './pages/TaskBoard';
|
||||
import { Monitor } from './pages/Monitor';
|
||||
import { Config } from './pages/Config';
|
||||
import { Briefing } from './pages/Briefing';
|
||||
import { TaskModal } from './components/TaskModal';
|
||||
import { useProjects } from './hooks/useApi';
|
||||
import type { Task } from './types';
|
||||
|
||||
type Page = 'tasks' | 'monitor' | 'config' | 'briefing';
|
||||
|
||||
export default function App() {
|
||||
const [page, setPage] = useState<Page>('tasks');
|
||||
const [selectedProject, setSelectedProject] = useState<string | null>(null);
|
||||
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
|
||||
const { projects } = useProjects();
|
||||
|
||||
const handleSelectTask = useCallback((task: Task) => {
|
||||
setSelectedTask(task);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
{/* Sidebar */}
|
||||
<nav className="sidebar">
|
||||
<div className="sidebar-title">墨子+ v2.0</div>
|
||||
<div className="sidebar-nav">
|
||||
<div
|
||||
className={`nav-item ${page === 'tasks' ? 'active' : ''}`}
|
||||
onClick={() => setPage('tasks')}
|
||||
>
|
||||
📋 任务看板
|
||||
</div>
|
||||
<div
|
||||
className={`nav-item ${page === 'monitor' ? 'active' : ''}`}
|
||||
onClick={() => setPage('monitor')}
|
||||
>
|
||||
📊 全局监控
|
||||
</div>
|
||||
<div
|
||||
className={`nav-item ${page === 'briefing' ? 'active' : ''}`}
|
||||
onClick={() => setPage('briefing')}
|
||||
>
|
||||
🤖 AI Briefing
|
||||
</div>
|
||||
<div
|
||||
className={`nav-item ${page === 'config' ? 'active' : ''}`}
|
||||
onClick={() => setPage('config')}
|
||||
>
|
||||
⚙️ 系统配置
|
||||
</div>
|
||||
|
||||
{/* Project selector */}
|
||||
{page === 'tasks' && (
|
||||
<div style={{ marginTop: 16, padding: '0 4px' }}>
|
||||
<div style={{ fontSize: 11, color: 'var(--muted)', marginBottom: 6, textTransform: 'uppercase' }}>
|
||||
项目
|
||||
</div>
|
||||
{projects.map(p => (
|
||||
<div
|
||||
key={p.id}
|
||||
className={`nav-item ${selectedProject === p.id ? 'active' : ''}`}
|
||||
onClick={() => setSelectedProject(p.id)}
|
||||
>
|
||||
{p.name}
|
||||
</div>
|
||||
))}
|
||||
{projects.length === 0 && (
|
||||
<div style={{ fontSize: 12, color: 'var(--muted)', padding: '4px 12px' }}>
|
||||
暂无项目
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Main content */}
|
||||
<main className="main">
|
||||
{page === 'tasks' && (
|
||||
<TaskBoard projectId={selectedProject} onSelectTask={handleSelectTask} />
|
||||
)}
|
||||
{page === 'monitor' && <Monitor />}
|
||||
{page === 'briefing' && <Briefing />}
|
||||
{page === 'config' && <Config />}
|
||||
</main>
|
||||
|
||||
{/* Task detail modal */}
|
||||
<TaskModal task={selectedTask} onClose={() => setSelectedTask(null)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './styles/global.css';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
Reference in New Issue
Block a user