批量转换 163 个文件,3204 处中文替换为 t() 调用: - Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换 - Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换 - Deploy: 流水线/发布/凭证/RBAC 全部转换 - Server/Cloud/Agent/Task/Layout/UI: 全部转换 - 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys) - tsc 编译零错误
167 lines
7.2 KiB
TypeScript
167 lines
7.2 KiB
TypeScript
// DeploymentOverview.tsx — Deployment 详情头部、状态与操作区 // Logan.Li
|
|
import {
|
|
ArrowLeft, Minus, Plus, RotateCw, Upload, RefreshCw, Loader2,
|
|
} from 'lucide-react';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { CreateHPADialog } from './CreateHPADialog';
|
|
import type { JsonData } from '@/types/common';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
export interface DeploymentOverviewProps {
|
|
deploymentName: string;
|
|
namespace: string;
|
|
deployment?: JsonData;
|
|
hpas: JsonData[];
|
|
clusterCode: string;
|
|
ready: number;
|
|
total: number;
|
|
available: number;
|
|
isHealthy: boolean;
|
|
actionLoading: string;
|
|
newImage: string;
|
|
showImageUpdate: boolean;
|
|
onBack: () => void;
|
|
onRefresh: () => void;
|
|
onScale: (delta: number) => void;
|
|
onRestart: () => void;
|
|
onNewImageChange: (value: string) => void;
|
|
onToggleImageUpdate: () => void;
|
|
onUpdateImage: () => void;
|
|
}
|
|
|
|
export function DeploymentOverview({
|
|
deploymentName, namespace, deployment, hpas, clusterCode,
|
|
ready, total, available, isHealthy, actionLoading,
|
|
newImage, showImageUpdate, onBack, onRefresh, onScale, onRestart,
|
|
onNewImageChange, onToggleImageUpdate, onUpdateImage,
|
|
}: DeploymentOverviewProps) {
|
|
const { t } = useTranslation();
|
|
return (
|
|
<>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<Button variant="ghost" size="sm" className="dg-text-secondary" onClick={onBack}>
|
|
<ArrowLeft className="h-4 w-4 mr-1" />返回
|
|
</Button>
|
|
<div>
|
|
<div className="flex items-center gap-2">
|
|
<h1 className="text-xl font-bold text-[var(--dg-text-primary)]">{deploymentName}</h1>
|
|
<Badge variant="outline" className="border-[var(--dg-border)] dg-text-secondary">{namespace}</Badge>
|
|
</div>
|
|
<p className="text-sm dg-text-muted mt-0.5">镜像: {deployment.image || '-'}</p>
|
|
</div>
|
|
</div>
|
|
<Button variant="outline" size="sm" className="border-[var(--dg-border)] dg-text-secondary" onClick={onRefresh}>
|
|
<RefreshCw className="h-4 w-4 mr-1" />刷新
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
|
<Card className="dg-card">
|
|
<CardContent className="p-3">
|
|
<p className="text-xs dg-text-muted">{t('kubernetes.deploymentoverview.sb4cac1')}</p>
|
|
<p className={`text-lg font-bold ${isHealthy ? 'dg-text-green' : 'dg-text-yellow'}`}>
|
|
{ready}/{total}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="dg-card">
|
|
<CardContent className="p-3">
|
|
<p className="text-xs dg-text-muted">{t('k8s.column.availableReplicas')}</p>
|
|
<p className="text-lg font-bold dg-text-blue">{available}</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="dg-card">
|
|
<CardContent className="p-3">
|
|
<p className="text-xs dg-text-muted">{t('k8s.column.image')}</p>
|
|
<p className="text-sm font-mono text-[var(--dg-text-secondary)] truncate max-w-[200px]" title={deployment.image}>
|
|
{deployment.image?.split('/').pop() || '-'}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="dg-card">
|
|
<CardContent className="p-3">
|
|
<p className="text-xs dg-text-muted">HPA</p>
|
|
{hpas.length > 0 ? (
|
|
<p className="text-lg font-bold dg-text-purple">{t('alert.enabled')}</p>
|
|
) : (
|
|
<div className="flex items-center justify-between">
|
|
<p className="text-lg font-bold dg-text-muted">{t('k8s.dnsHost.notConfigured')}</p>
|
|
<CreateHPADialog
|
|
clusterCode={clusterCode}
|
|
namespace={namespace}
|
|
deploymentName={deploymentName}
|
|
onCreated={onRefresh}
|
|
/>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<Card className="dg-card">
|
|
<CardHeader className="pb-3">
|
|
<CardTitle className="text-base text-[var(--dg-text-primary)]">{t('common.actions')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex flex-wrap items-center gap-3">
|
|
<div className="flex items-center gap-1 bg-[var(--dg-bg-tertiary)] rounded-lg p-1">
|
|
<Button
|
|
variant="ghost" size="icon" className="h-8 w-8 text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)]"
|
|
disabled={actionLoading === 'scale' || total <= 0}
|
|
onClick={() => onScale(-1)}
|
|
>
|
|
<Minus className="h-4 w-4" />
|
|
</Button>
|
|
<span className="text-sm font-mono text-[var(--dg-text-primary)] w-8 text-center">
|
|
{actionLoading === 'scale' ? <Loader2 className="h-4 w-4 animate-spin inline" /> : total}
|
|
</span>
|
|
<Button
|
|
variant="ghost" size="icon" className="h-8 w-8 text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)]"
|
|
disabled={actionLoading === 'scale'}
|
|
onClick={() => onScale(1)}
|
|
>
|
|
<Plus className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
<Button
|
|
variant="outline" size="sm" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)]"
|
|
disabled={actionLoading === 'restart'}
|
|
onClick={onRestart}
|
|
>
|
|
{actionLoading === 'restart' ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : <RotateCw className="h-4 w-4 mr-1" />}
|
|
滚动重启
|
|
</Button>
|
|
<Button
|
|
variant="outline" size="sm" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)]"
|
|
onClick={onToggleImageUpdate}
|
|
>
|
|
<Upload className="h-4 w-4 mr-1" />
|
|
更新镜像
|
|
</Button>
|
|
</div>
|
|
{showImageUpdate && (
|
|
<div className="mt-3 flex items-center gap-2 p-3 bg-[var(--dg-bg-tertiary)]/50 rounded-lg border border-[var(--dg-border)]">
|
|
<Input
|
|
value={newImage}
|
|
onChange={(e) => onNewImageChange(e.target.value)}
|
|
placeholder=t('kubernetes.deploymentoverview.s416d7e')
|
|
className="flex-1 h-9 dg-input text-[var(--dg-text-primary)] text-sm font-mono"
|
|
/>
|
|
<Button size="sm" className="bg-blue-600 hover:bg-blue-700"
|
|
disabled={actionLoading === 'image' || !newImage.trim()}
|
|
onClick={onUpdateImage}
|
|
>
|
|
{actionLoading === 'image' ? <Loader2 className="h-4 w-4 animate-spin" /> : t('common.update')}
|
|
</Button>
|
|
<Button variant="ghost" size="sm" className="dg-text-secondary" onClick={onToggleImageUpdate}>{t('common.cancel')}</Button>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</>
|
|
);
|
|
} |