import { useState, useEffect, useRef } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Progress } from "@/components/ui/progress"; import { Plus, Search, GitBranch, Calendar, Users, Settings, ExternalLink, Code, Shield, Activity, Upload, FileText, AlertCircle } from "lucide-react"; import { api } from "@/shared/config/database"; import { scanZipFile, validateZipFile } from "@/features/projects/services"; import type { Project, CreateProjectForm } from "@/shared/types"; import { Link } from "react-router-dom"; import { toast } from "sonner"; export default function Projects() { const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(""); const [showCreateDialog, setShowCreateDialog] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [uploading, setUploading] = useState(false); const fileInputRef = useRef(null); const [createForm, setCreateForm] = useState({ name: "", description: "", repository_url: "", repository_type: "github", default_branch: "main", programming_languages: [] }); const supportedLanguages = [ 'JavaScript', 'TypeScript', 'Python', 'Java', 'Go', 'Rust', 'C++', 'C#', 'PHP', 'Ruby' ]; useEffect(() => { loadProjects(); }, []); const loadProjects = async () => { try { setLoading(true); const data = await api.getProjects(); setProjects(data); } catch (error) { console.error('Failed to load projects:', error); toast.error("加载项目失败"); } finally { setLoading(false); } }; const handleCreateProject = async () => { if (!createForm.name.trim()) { toast.error("请输入项目名称"); return; } try { await api.createProject({ ...createForm, // 无登录场景下不传 owner_id,由后端置为 null } as any); toast.success("项目创建成功"); setShowCreateDialog(false); resetCreateForm(); loadProjects(); } catch (error) { console.error('Failed to create project:', error); toast.error("创建项目失败"); } }; const resetCreateForm = () => { setCreateForm({ name: "", description: "", repository_url: "", repository_type: "github", default_branch: "main", programming_languages: [] }); }; const handleFileUpload = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; // 验证文件 const validation = validateZipFile(file); if (!validation.valid) { toast.error(validation.error); return; } // 检查是否有项目名称 if (!createForm.name.trim()) { toast.error("请先输入项目名称"); return; } try { setUploading(true); setUploadProgress(0); // 创建项目 const project = await api.createProject({ ...createForm, repository_type: "other" } as any); // 模拟上传进度 const progressInterval = setInterval(() => { setUploadProgress(prev => { if (prev >= 90) { clearInterval(progressInterval); return 90; } return prev + 10; }); }, 200); // 扫描ZIP文件 const taskId = await scanZipFile({ projectId: project.id, zipFile: file, excludePatterns: ['node_modules/**', '.git/**', 'dist/**', 'build/**'], createdBy: undefined }); clearInterval(progressInterval); setUploadProgress(100); toast.success("项目创建并开始分析"); setShowCreateDialog(false); resetCreateForm(); loadProjects(); // 跳转到任务详情页 setTimeout(() => { window.open(`/tasks/${taskId}`, '_blank'); }, 1000); } catch (error: any) { console.error('Upload failed:', error); toast.error(error.message || "上传失败"); } finally { setUploading(false); setUploadProgress(0); if (fileInputRef.current) { fileInputRef.current.value = ''; } } }; const filteredProjects = projects.filter(project => project.name.toLowerCase().includes(searchTerm.toLowerCase()) || project.description?.toLowerCase().includes(searchTerm.toLowerCase()) ); const getRepositoryIcon = (type?: string) => { switch (type) { case 'github': return '🐙'; case 'gitlab': return '🦊'; default: return '📁'; } }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('zh-CN'); }; if (loading) { return (
); } return (
{/* 页面标题和操作 */}

项目管理

管理您的代码项目,配置审计规则和查看分析结果

创建新项目 Git 仓库 上传代码
setCreateForm({ ...createForm, name: e.target.value })} placeholder="输入项目名称" />