From 3f033e9db8b0ba1809a199f5f5d0fae5e223d787 Mon Sep 17 00:00:00 2001 From: attacker Date: Mon, 15 Jun 2026 09:05:28 +0800 Subject: [PATCH] refactor: PipelineManager split into 4 files (776 to 438 lines) --- .../deploy/PipelineDetailDialog.tsx | 178 ++++++++ .../components/deploy/PipelineFormDialog.tsx | 135 ++++++ .../src/components/deploy/PipelineManager.tsx | 415 ++---------------- .../components/deploy/PipelineRunDialog.tsx | 63 +++ .../components/deploy/pipeline-helpers.tsx | 91 ++++ 5 files changed, 506 insertions(+), 376 deletions(-) create mode 100644 frontend/src/components/deploy/PipelineDetailDialog.tsx create mode 100644 frontend/src/components/deploy/PipelineFormDialog.tsx create mode 100644 frontend/src/components/deploy/PipelineRunDialog.tsx create mode 100644 frontend/src/components/deploy/pipeline-helpers.tsx diff --git a/frontend/src/components/deploy/PipelineDetailDialog.tsx b/frontend/src/components/deploy/PipelineDetailDialog.tsx new file mode 100644 index 0000000..a4a9e19 --- /dev/null +++ b/frontend/src/components/deploy/PipelineDetailDialog.tsx @@ -0,0 +1,178 @@ +import { Badge } from '@/components/ui/badge'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { + Table, + TableBody, + TableCell, + TableRow, +} from '@/components/ui/table'; +import { GitBranch, GitCommit, Clock, ChevronDown, Loader2 } from 'lucide-react'; +import type { PipelineStage } from './pipeline-helpers'; +import { parseStages, getStatusBadge, getStageStatusIcon } from './pipeline-helpers'; + +// 流水线详情弹窗(阶段/配置/历史三 Tab) // Logan.Li +export function PipelineDetailDialog({ + open, + onOpenChange, + selectedPipeline, + pipelineRuns, + loadingRuns, + activeStage, + setActiveStage, +}: { + open: boolean; + onOpenChange: (open: boolean) => void; + selectedPipeline: any; + pipelineRuns: any[]; + loadingRuns: boolean; + activeStage: string | null; + setActiveStage: (id: string | null) => void; +}) { + return ( + + + + {selectedPipeline?.name} + {selectedPipeline?.description} + + {selectedPipeline && ( +
+ + + + 执行阶段 + + + 配置 + + + 历史记录{pipelineRuns.length > 0 && ` (${pipelineRuns.length})`} + + + +
+ {parseStages(selectedPipeline.stages).length === 0 ? ( +
暂无阶段配置
+ ) : ( + parseStages(selectedPipeline.stages).map((stage: PipelineStage, index: number) => ( +
setActiveStage(activeStage === stage.id ? null : stage.id)} + > +
+
+ {index + 1} + {getStageStatusIcon(stage.status)} + {stage.name} +
+
+ {stage.duration} + +
+
+ {activeStage === stage.id && stage.logs.length > 0 && ( +
+ {stage.logs.map((log, i) => ( +
{log}
+ ))} +
+ )} +
+ )) + )} +
+
+ + + + + 代码仓库 + {selectedPipeline.source || '--'} + + + 默认分支 + {selectedPipeline.branch || '--'} + + + 流水线类型 + {selectedPipeline.type || 'deploy'} + + + 运行次数 + + {selectedPipeline.run_count || 0} 次(成功 {selectedPipeline.success_count || 0} / 失败 {selectedPipeline.fail_count || 0}) + + + +
+
+ + {loadingRuns ? ( +
+ +
+ ) : pipelineRuns.length === 0 ? ( +
暂无执行记录
+ ) : ( +
+ {pipelineRuns.map((run: any) => ( +
+
+ #{run.build_number} +
+
+
+ {getStatusBadge(run.status)} + + + {run.branch || 'main'} + +
+
+ {run.commit_id && ( + + + {run.commit_id.substring(0, 7)} + + )} + {run.triggered_by || 'manual'} + {run.duration > 0 && ( + + + {run.duration < 60 ? `${run.duration}s` : `${Math.floor(run.duration / 60)}m${run.duration % 60}s`} + + )} + {run.created_at ? new Date(run.created_at).toLocaleString('zh-CN') : '--'} +
+
+
+ ))} +
+ )} +
+
+
+ )} +
+
+ ); +} diff --git a/frontend/src/components/deploy/PipelineFormDialog.tsx b/frontend/src/components/deploy/PipelineFormDialog.tsx new file mode 100644 index 0000000..a175967 --- /dev/null +++ b/frontend/src/components/deploy/PipelineFormDialog.tsx @@ -0,0 +1,135 @@ +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Badge } from '@/components/ui/badge'; +import { Card, CardContent } from '@/components/ui/card'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Textarea } from '@/components/ui/textarea'; +import { Label } from '@/components/ui/label'; +import { pipelineTemplates } from './pipeline-helpers'; + +// 表单数据结构 // Logan.Li +export type PipelineFormData = { + name: string; + description: string; + source: string; + branch: string; + template: string; +} + +// 新建/编辑流水线弹窗 // Logan.Li +export function PipelineFormDialog({ + open, + onOpenChange, + editMode, + formData, + setFormData, + onSave, +}: { + open: boolean; + onOpenChange: (open: boolean) => void; + editMode: boolean; + formData: PipelineFormData; + setFormData: (data: PipelineFormData) => void; + onSave: () => void; +}) { + return ( + + + + {editMode ? '编辑流水线' : '新建流水线'} + + {editMode ? '修改流水线配置' : '配置新的 CI/CD 流水线'} + + +
+
+ + setFormData({ ...formData, name: e.target.value })} + placeholder="例如: frontend-build" + className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)] text-[var(--dg-text-primary)] mt-1" + /> +
+
+ +