feat: 流水线运行历史前后端联调 — 详情弹窗历史记录标签展示真实PipelineRun数据(构建号/状态/分支/Commit/触发者/时间)
This commit is contained in:
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>
|
||||||
|
|||||||
Reference in new issue
Block a user