feat: 流水线运行历史前后端联调 — 详情弹窗历史记录标签展示真实PipelineRun数据(构建号/状态/分支/Commit/触发者/时间)

This commit is contained in:
attacker committed 2026-06-14 11:05:09 +08:00
1 parent 1d98503f37
commit 6012418523
1 file changed
+71 -6
@@ -95,6 +95,8 @@ export function PipelineManager() {
const [isDetailDialogOpen, setIsDetailDialogOpen] = useState(false); const [isDetailDialogOpen, setIsDetailDialogOpen] = useState(false);
const [isRunDialogOpen, setIsRunDialogOpen] = useState(false); const [isRunDialogOpen, setIsRunDialogOpen] = useState(false);
const [activeStage, setActiveStage] = useState<string | null>(null); const [activeStage, setActiveStage] = useState<string | null>(null);
const [pipelineRuns, setPipelineRuns] = useState<any[]>([]);
const [loadingRuns, setLoadingRuns] = useState(false);
const [newPipeline, setNewPipeline] = useState({ const [newPipeline, setNewPipeline] = useState({
name: '', name: '',
description: '', description: '',
@@ -119,6 +121,25 @@ export function PipelineManager() {
loadData(); loadData();
}, []); }, []);
const loadPipelineRuns = async (pipelineId: number | string) => {
try {
setLoadingRuns(true);
const res = await pipelineApi.getRuns(pipelineId);
setPipelineRuns((res as any)?.list || []);
} catch (error) {
console.error('Failed to load pipeline runs:', error);
setPipelineRuns([]);
} finally {
setLoadingRuns(false);
}
};
const handleOpenDetail = (pipeline: any) => {
setSelectedPipeline(pipeline);
setIsDetailDialogOpen(true);
loadPipelineRuns(pipeline.id);
};
const filteredPipelines = pipelines.filter( const filteredPipelines = pipelines.filter(
(p) => (p) =>
(p.name || '').toLowerCase().includes(searchQuery.toLowerCase()) || (p.name || '').toLowerCase().includes(searchQuery.toLowerCase()) ||
@@ -203,6 +224,9 @@ export function PipelineManager() {
await pipelineApi.triggerPipeline(selectedPipeline.id); await pipelineApi.triggerPipeline(selectedPipeline.id);
setIsRunDialogOpen(false); setIsRunDialogOpen(false);
loadData(); loadData();
if (isDetailDialogOpen) {
loadPipelineRuns(selectedPipeline.id);
}
} catch (error) { } catch (error) {
console.error('Failed to trigger pipeline:', error); console.error('Failed to trigger pipeline:', error);
} }
@@ -382,10 +406,7 @@ export function PipelineManager() {
variant="ghost" variant="ghost"
size="icon" size="icon"
className="h-8 w-8 text-slate-400 hover:text-blue-400" className="h-8 w-8 text-slate-400 hover:text-blue-400"
onClick={() => { onClick={() => handleOpenDetail(pipeline)}
setSelectedPipeline(pipeline);
setIsDetailDialogOpen(true);
}}
> >
<Eye className="h-4 w-4" /> <Eye className="h-4 w-4" />
</Button> </Button>
@@ -509,7 +530,7 @@ export function PipelineManager() {
配置 配置
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="history" className="data-[state=active]:bg-slate-700"> <TabsTrigger value="history" className="data-[state=active]:bg-slate-700">
历史记录 历史记录{pipelineRuns.length > 0 && ` (${pipelineRuns.length})`}
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
<TabsContent value="stages" className="mt-4"> <TabsContent value="stages" className="mt-4">
@@ -569,7 +590,51 @@ export function PipelineManager() {
</div> </div>
</TabsContent> </TabsContent>
<TabsContent value="history" className="mt-4"> <TabsContent value="history" className="mt-4">
<div className="text-slate-500 text-center py-8">历史执行记录将在这里显示</div> {loadingRuns ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="h-5 w-5 text-slate-500 animate-spin" />
</div>
) : pipelineRuns.length === 0 ? (
<div className="text-slate-500 text-center py-8">暂无执行记录</div>
) : (
<div className="space-y-2">
{pipelineRuns.map((run: any) => (
<div
key={run.id}
className="flex items-center gap-3 p-3 rounded-lg border border-slate-700 bg-slate-800/50"
>
<div className="flex items-center gap-2 w-20 shrink-0">
<span className="text-slate-500 text-sm font-mono">#{run.build_number}</span>
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
{getStatusBadge(run.status)}
<Badge variant="outline" className="border-slate-700 text-slate-400 text-xs">
<GitBranch className="h-3 w-3 mr-1" />
{run.branch || 'main'}
</Badge>
</div>
<div className="flex items-center gap-3 mt-1 text-xs text-slate-500">
{run.commit_id && (
<span className="flex items-center gap-1">
<GitCommit className="h-3 w-3" />
{run.commit_id.substring(0, 7)}
</span>
)}
<span>{run.triggered_by || 'manual'}</span>
{run.duration > 0 && (
<span className="flex items-center gap-1">
<Clock className="h-3 w-3" />
{run.duration < 60 ? `${run.duration}s` : `${Math.floor(run.duration / 60)}m${run.duration % 60}s`}
</span>
)}
<span>{run.created_at ? new Date(run.created_at).toLocaleString('zh-CN') : '--'}</span>
</div>
</div>
</div>
))}
</div>
)}
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</div> </div>