All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 2m16s
- 新增 Project 模型(repo_url, local_path, name, description) - 项目 CRUD API(GET/PUT /api/v1/projects) - 日志上报自动 upsert Project 记录 - ErrorLog 增加 failure_reason 字段 - update_task_status / create_repair_report 写入失败原因 - Repair Agent 优先从 API 获取项目配置,回退 .env - 新增 Web 端「项目管理」页面(表格 + 行内编辑) - BugList/BugDetail/RepairList 展示失败原因 - 更新接入指南文档 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { BrowserRouter, Routes, Route, NavLink, useLocation } from 'react-router-dom';
|
|
import { LayoutDashboard, Bug, Wrench, FolderGit2, Shield, Menu, X } from 'lucide-react';
|
|
import Dashboard from './pages/Dashboard';
|
|
import BugList from './pages/BugList';
|
|
import BugDetail from './pages/BugDetail';
|
|
import RepairList from './pages/RepairList';
|
|
import RepairDetail from './pages/RepairDetail';
|
|
import ProjectList from './pages/ProjectList';
|
|
import './index.css';
|
|
|
|
function AppLayout() {
|
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
const location = useLocation();
|
|
|
|
// Close sidebar on route change (mobile)
|
|
useEffect(() => {
|
|
setSidebarOpen(false);
|
|
}, [location.pathname]);
|
|
|
|
return (
|
|
<div className="app">
|
|
{/* Mobile header */}
|
|
<header className="mobile-header">
|
|
<button className="mobile-menu-btn" onClick={() => setSidebarOpen(true)}>
|
|
<Menu size={20} />
|
|
</button>
|
|
<div className="mobile-logo">
|
|
<div className="logo-icon"><Shield size={14} /></div>
|
|
日志中台
|
|
</div>
|
|
<div style={{ width: 36 }} />
|
|
</header>
|
|
|
|
{/* Overlay */}
|
|
{sidebarOpen && (
|
|
<div className="sidebar-overlay" onClick={() => setSidebarOpen(false)} />
|
|
)}
|
|
|
|
<aside className={`sidebar ${sidebarOpen ? 'sidebar-open' : ''}`}>
|
|
<div className="sidebar-top">
|
|
<div className="logo">
|
|
<div className="logo-icon"><Shield size={16} /></div>
|
|
日志中台
|
|
</div>
|
|
<button className="sidebar-close-btn" onClick={() => setSidebarOpen(false)}>
|
|
<X size={18} />
|
|
</button>
|
|
</div>
|
|
<nav>
|
|
<ul className="nav-menu">
|
|
<li className="nav-item">
|
|
<NavLink
|
|
to="/"
|
|
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
|
|
end
|
|
>
|
|
<LayoutDashboard size={16} />
|
|
仪表盘
|
|
</NavLink>
|
|
</li>
|
|
<li className="nav-item">
|
|
<NavLink
|
|
to="/bugs"
|
|
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
|
|
>
|
|
<Bug size={16} />
|
|
缺陷列表
|
|
</NavLink>
|
|
</li>
|
|
<li className="nav-item">
|
|
<NavLink
|
|
to="/repairs"
|
|
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
|
|
>
|
|
<Wrench size={16} />
|
|
修复报告
|
|
</NavLink>
|
|
</li>
|
|
<li className="nav-item">
|
|
<NavLink
|
|
to="/projects"
|
|
className={({ isActive }) => `nav-link ${isActive ? 'active' : ''}`}
|
|
>
|
|
<FolderGit2 size={16} />
|
|
项目管理
|
|
</NavLink>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</aside>
|
|
|
|
<main className="main-content">
|
|
<Routes>
|
|
<Route path="/" element={<Dashboard />} />
|
|
<Route path="/bugs" element={<BugList />} />
|
|
<Route path="/bugs/:id" element={<BugDetail />} />
|
|
<Route path="/repairs" element={<RepairList />} />
|
|
<Route path="/repairs/:id" element={<RepairDetail />} />
|
|
<Route path="/projects" element={<ProjectList />} />
|
|
</Routes>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function App() {
|
|
return (
|
|
<BrowserRouter>
|
|
<AppLayout />
|
|
</BrowserRouter>
|
|
);
|
|
}
|
|
|
|
export default App;
|