import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { GitBranch, Settings, FileText, AlertCircle, Info, Zap, Shield, Search } from "lucide-react"; import { api } from "@/shared/config/database"; import type { Project, CreateAuditTaskForm } from "@/shared/types"; import { toast } from "sonner"; interface CreateTaskDialogProps { open: boolean; onOpenChange: (open: boolean) => void; onTaskCreated: () => void; } export default function CreateTaskDialog({ open, onOpenChange, onTaskCreated }: CreateTaskDialogProps) { const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(false); const [creating, setCreating] = useState(false); const [searchTerm, setSearchTerm] = useState(""); const [taskForm, setTaskForm] = useState({ project_id: "", task_type: "repository", branch_name: "main", exclude_patterns: ["node_modules/**", ".git/**", "dist/**", "build/**", "*.log"], scan_config: { include_tests: true, include_docs: false, max_file_size: 1024, // KB analysis_depth: "standard" } }); const commonExcludePatterns = [ { label: "node_modules", value: "node_modules/**", description: "Node.js 依赖包" }, { label: ".git", value: ".git/**", description: "Git 版本控制文件" }, { label: "dist/build", value: "dist/**", description: "构建输出目录" }, { label: "logs", value: "*.log", description: "日志文件" }, { label: "cache", value: ".cache/**", description: "缓存文件" }, { label: "temp", value: "temp/**", description: "临时文件" }, { label: "vendor", value: "vendor/**", description: "第三方库" }, { label: "coverage", value: "coverage/**", description: "测试覆盖率报告" } ]; useEffect(() => { if (open) { loadProjects(); } }, [open]); const loadProjects = async () => { try { setLoading(true); const data = await api.getProjects(); setProjects(data.filter(p => p.is_active)); } catch (error) { console.error('Failed to load projects:', error); toast.error("加载项目失败"); } finally { setLoading(false); } }; const handleCreateTask = async () => { if (!taskForm.project_id) { toast.error("请选择项目"); return; } if (taskForm.task_type === "repository" && !taskForm.branch_name?.trim()) { toast.error("请输入分支名称"); return; } try { setCreating(true); await api.createAuditTask({ ...taskForm, created_by: "system" // 无登录场景下使用系统用户 } as any); toast.success("审计任务创建成功"); onOpenChange(false); resetForm(); onTaskCreated(); } catch (error) { console.error('Failed to create task:', error); toast.error("创建任务失败"); } finally { setCreating(false); } }; const resetForm = () => { setTaskForm({ project_id: "", task_type: "repository", branch_name: "main", exclude_patterns: ["node_modules/**", ".git/**", "dist/**", "build/**", "*.log"], scan_config: { include_tests: true, include_docs: false, max_file_size: 1024, analysis_depth: "standard" } }); setSearchTerm(""); }; const toggleExcludePattern = (pattern: string) => { const patterns = taskForm.exclude_patterns || []; if (patterns.includes(pattern)) { setTaskForm({ ...taskForm, exclude_patterns: patterns.filter(p => p !== pattern) }); } else { setTaskForm({ ...taskForm, exclude_patterns: [...patterns, pattern] }); } }; const addCustomPattern = (pattern: string) => { if (pattern.trim() && !taskForm.exclude_patterns.includes(pattern.trim())) { setTaskForm({ ...taskForm, exclude_patterns: [...taskForm.exclude_patterns, pattern.trim()] }); } }; const removeExcludePattern = (pattern: string) => { setTaskForm({ ...taskForm, exclude_patterns: taskForm.exclude_patterns.filter(p => p !== pattern) }); }; const selectedProject = projects.find(p => p.id === taskForm.project_id); const filteredProjects = projects.filter(project => project.name.toLowerCase().includes(searchTerm.toLowerCase()) || project.description?.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( 新建审计任务
{/* 项目选择 */}
{filteredProjects.length} 个可用项目
{/* 项目搜索 */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* 项目列表 */}
{loading ? (
) : filteredProjects.length > 0 ? ( filteredProjects.map((project) => ( setTaskForm({ ...taskForm, project_id: project.id })} >

{project.name}

{project.description && (

{project.description}

)}
{project.repository_type?.toUpperCase() || 'OTHER'} {project.default_branch}
{taskForm.project_id === project.id && (
)}
)) ) : (

{searchTerm ? '未找到匹配的项目' : '暂无可用项目'}

)}
{/* 任务配置 */} {selectedProject && ( 基础配置 排除规则 高级选项
{taskForm.task_type === "repository" && (
setTaskForm({ ...taskForm, branch_name: e.target.value })} placeholder={selectedProject.default_branch || "main"} />
)}
{/* 项目信息展示 */}

选中项目:{selectedProject.name}

{selectedProject.description && (

描述:{selectedProject.description}

)}

默认分支:{selectedProject.default_branch}

{selectedProject.programming_languages && (

编程语言:{JSON.parse(selectedProject.programming_languages).join(', ')}

)}

选择要从审计中排除的文件和目录模式

{/* 常用排除模式 */}
{commonExcludePatterns.map((pattern) => (
toggleExcludePattern(pattern.value)} />

{pattern.label}

{pattern.description}

))}
{/* 自定义排除模式 */}
{ if (e.key === 'Enter') { addCustomPattern(e.currentTarget.value); e.currentTarget.value = ''; } }} />
{/* 已选择的排除模式 */} {taskForm.exclude_patterns.length > 0 && (
{taskForm.exclude_patterns.map((pattern) => ( removeExcludePattern(pattern)} > {pattern} × ))}
)}

配置代码扫描的详细参数

setTaskForm({ ...taskForm, scan_config: { ...taskForm.scan_config, include_tests: !!checked } }) } />

包含测试文件

扫描 *test*, *spec* 等测试文件

setTaskForm({ ...taskForm, scan_config: { ...taskForm.scan_config, include_docs: !!checked } }) } />

包含文档文件

扫描 README, docs 等文档文件

setTaskForm({ ...taskForm, scan_config: { ...taskForm.scan_config, max_file_size: parseInt(e.target.value) || 1024 } }) } min="1" max="10240" />
{/* 分析深度说明 */}

分析深度说明:

  • 基础扫描:快速检查语法错误和基本问题
  • 标准扫描:包含代码质量、安全性和性能分析
  • 深度扫描:全面分析,包含复杂度、可维护性等高级指标
)} {/* 操作按钮 */}
); }