import { useState, useEffect } from 'react'; import { getProjects, updateProject, type Project } from '../api'; import { Save, X, Pencil } from 'lucide-react'; export default function ProjectList() { const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(true); const [editingId, setEditingId] = useState(null); const [editForm, setEditForm] = useState({ name: '', repo_url: '', local_path: '', description: '' }); const [saving, setSaving] = useState(false); const fetchProjects = async () => { setLoading(true); try { const res = await getProjects(); setProjects(res.data.projects); } catch (err) { console.error(err); } finally { setLoading(false); } }; useEffect(() => { fetchProjects(); }, []); const startEdit = (p: Project) => { setEditingId(p.id); setEditForm({ name: p.name || '', repo_url: p.repo_url || '', local_path: p.local_path || '', description: p.description || '', }); }; const cancelEdit = () => { setEditingId(null); }; const saveEdit = async (projectId: string) => { setSaving(true); try { await updateProject(projectId, editForm); setEditingId(null); await fetchProjects(); } catch (err) { console.error('保存失败:', err); } finally { setSaving(false); } }; const ConfigBadge = ({ value }: { value: string | null }) => ( value ? ( {value} ) : ( 未配置 ) ); if (loading) { return
; } return (

项目管理

管理项目的仓库地址和本地路径,供 Repair Agent 使用

{projects.length === 0 ? (
暂无项目,首次上报日志后会自动创建
) : ( <> {/* Desktop table */}
{projects.map((p) => ( {editingId === p.id ? ( <> ) : ( <> )} ))}
项目 ID 名称 仓库地址 本地路径 描述 更新时间 操作
{p.project_id} setEditForm({ ...editForm, name: e.target.value })} placeholder="项目名称" className="edit-input" /> setEditForm({ ...editForm, repo_url: e.target.value })} placeholder="https://gitea.example.com/..." className="edit-input" /> setEditForm({ ...editForm, local_path: e.target.value })} placeholder="/home/user/projects/..." className="edit-input" /> setEditForm({ ...editForm, description: e.target.value })} placeholder="项目描述" className="edit-input" /> {new Date(p.updated_at).toLocaleString()}
{p.project_id} {p.name || -} {p.description || '-'} {new Date(p.updated_at).toLocaleString()}
{/* Mobile card list */}
{projects.map((p) => (
{editingId === p.id ? (
{p.project_id} setEditForm({ ...editForm, name: e.target.value })} placeholder="项目名称" className="edit-input" /> setEditForm({ ...editForm, repo_url: e.target.value })} placeholder="仓库地址" className="edit-input" /> setEditForm({ ...editForm, local_path: e.target.value })} placeholder="本地路径" className="edit-input" /> setEditForm({ ...editForm, description: e.target.value })} placeholder="描述" className="edit-input" />
) : ( <>
{p.project_id}
{p.name &&
{p.name}
}
仓库:
路径:
{p.description && (
{p.description}
)} )}
))}
)}
); }