import React, { useState } from 'react'; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { Package, GitBranch, Rocket, Server, CheckCircle2, XCircle, TrendingUp, Clock, History, Loader2, User, FileText, Hash, } from "lucide-react"; import { formatDuration, formatTime, getStatusIcon, getStatusText } from '../utils/dashboardUtils'; import type { ApplicationConfig, DeployEnvironment, DeployRecord } from '../types'; import { DeployFlowGraphModal } from './DeployFlowGraphModal'; import DeploymentFormModal from './DeploymentFormModal'; interface ApplicationCardProps { app: ApplicationConfig; environment: DeployEnvironment; teamId: number; onDeploy: (app: ApplicationConfig, remark: string) => void; isDeploying: boolean; } export const ApplicationCard: React.FC = ({ app, environment, teamId, onDeploy, isDeploying, }) => { const [selectedDeployRecordId, setSelectedDeployRecordId] = useState(null); const [flowModalOpen, setFlowModalOpen] = useState(false); const [deployDialogOpen, setDeployDialogOpen] = useState(false); const handleDeployRecordClick = (record: DeployRecord) => { setSelectedDeployRecordId(record.id); setFlowModalOpen(true); }; return (
{/* 应用基本信息 */}
{app.applicationName ? (

{app.applicationName}

) : ( )} {app.applicationCode ? ( {app.applicationCode} ) : ( )} {app.applicationDesc && (

{app.applicationDesc}

)}
{/* Git/工作流/系统信息 */}
{/* 分支 */}
{app.branch ? ( {app.branch} ) : ( )}
{/* 工作流 */}
{app.workflowDefinitionName ? ( {app.workflowDefinitionName} ) : ( )}
{/* Jenkins */} {app.deploySystemName ? (
{app.deploySystemName}
{app.deployJob && (

{app.deploySystemName} ({app.deployJob})

)}
) : (
)}
{/* 部署统计信息 */}
{/* 总次数 */}
{app.deployStatistics ? ( <>
{app.deployStatistics.totalCount ?? 0}
总数
) : ( <> )}
{/* 成功次数 */}
{app.deployStatistics ? ( <>
{app.deployStatistics.successCount ?? 0}
成功
) : ( <> )}
{/* 失败次数 */}
{app.deployStatistics ? ( <>
{app.deployStatistics.failedCount ?? 0}
失败
) : ( <> )}
{/* 运行中次数 */}
{app.deployStatistics ? ( <>
{app.deployStatistics.runningCount ?? 0}
运行中
) : ( <> )}
{/* 最近部署信息 */} {app.deployStatistics ? (
{app.deployStatistics.lastDeployTime ? ( <> 最近: {formatTime(app.deployStatistics.lastDeployTime)} {app.deployStatistics.lastDeployBy ? ( by {app.deployStatistics.lastDeployBy} ) : ( )} {app.deployStatistics.latestStatus ? (() => { const { icon: StatusIcon, color } = getStatusIcon(app.deployStatistics.latestStatus); return ( {getStatusText(app.deployStatistics.latestStatus)} ); })() : ( )} ) : ( )}
) : (
)} {/* 最近部署记录 */}
最近记录
{app.recentDeployRecords && app.recentDeployRecords.length > 0 ? ( <> {/* 显示实际记录(最多2条) */} {app.recentDeployRecords.slice(0, 2).map((record) => { const { icon: StatusIcon, color } = getStatusIcon(record.status); return (
{/* 第一行:状态、编号、部署人 */}
{getStatusText(record.status)}
{record.deployBy && (
{record.deployBy}
)}
{/* 第二行:时间信息(一行显示) */} {(record.startTime || record.endTime || record.duration) && (
{record.startTime && ( {formatTime(record.startTime)} )} {record.endTime && ( <> {formatTime(record.endTime)} )} {record.duration && ( <> {formatDuration(record.duration)} )}
)} {/* 第三行:备注 */} {record.deployRemark && (
{record.deployRemark}
)}
); })} {/* 如果记录少于2条,用骨架屏补充 */} {app.recentDeployRecords.length < 2 && ( Array.from({ length: 2 - app.recentDeployRecords.length }).map((_, index) => (
)) )} ) : ( /* 如果没有记录,显示2条骨架记录 */ Array.from({ length: 2 }).map((_, index) => (
)) )}
{/* 部署按钮 */}
{!environment.canDeploy && (

您没有部署权限

)}
{/* 部署表单对话框 */} setDeployDialogOpen(false)} app={app} environment={environment} teamId={teamId} onSuccess={() => { // 部署成功后,触发父组件的 onDeploy 回调(用于刷新数据) onDeploy(app, ''); }} /> {/* 部署流程图模态框 */}
); };