批量转换 163 个文件,3204 处中文替换为 t() 调用: - Monitor: 日志中心/告警中心/数据源/大屏/站点拨测/SNMP/中间件 全部转换 - Kubernetes: ResourceVisualEditor/NamespaceResourcePage/拓扑/事件 全部转换 - Deploy: 流水线/发布/凭证/RBAC 全部转换 - Server/Cloud/Agent/Task/Layout/UI: 全部转换 - 翻译词典扩展至 6474 行 (22 namespaces, 5000+ keys) - tsc 编译零错误
119 lines
5.6 KiB
TypeScript
119 lines
5.6 KiB
TypeScript
// CreateHPADialog.tsx — 创建 HPA 弹窗 // Logan.Li
|
|
import { useState } from 'react';
|
|
import { Plus, Loader2 } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { kubernetesApi } from '@/api';
|
|
import { useToast } from '@/hooks/use-toast';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
export interface CreateHPADialogProps {
|
|
clusterCode: string;
|
|
namespace: string;
|
|
deploymentName: string;
|
|
onCreated: () => void;
|
|
}
|
|
|
|
export function CreateHPADialog({ clusterCode, namespace, deploymentName, onCreated }: CreateHPADialogProps) {
|
|
const { t } = useTranslation();
|
|
const { toast } = useToast();
|
|
const [open, setOpen] = useState(false);
|
|
const [loading, setLoading] = useState(false);
|
|
const [form, setForm] = useState({
|
|
name: '',
|
|
minReplicas: 1,
|
|
maxReplicas: 10,
|
|
cpuPercent: 80,
|
|
memPercent: 0,
|
|
});
|
|
|
|
const handleCreate = async () => {
|
|
if (!form.name.trim()) {
|
|
toast({ title: t('kubernetes.createhpadialog.sdf09ff'), variant: 'destructive' });
|
|
return;
|
|
}
|
|
setLoading(true);
|
|
try {
|
|
await kubernetesApi.createHPA(clusterCode, {
|
|
name: form.name,
|
|
namespace,
|
|
targetKind: 'Deployment',
|
|
targetName: deploymentName,
|
|
minReplicas: form.minReplicas,
|
|
maxReplicas: form.maxReplicas,
|
|
cpuPercent: form.cpuPercent,
|
|
memPercent: form.memPercent,
|
|
});
|
|
toast({ title: t('kubernetes.createhpadialog.s74b0b0') });
|
|
setOpen(false);
|
|
onCreated();
|
|
setForm({ name: '', minReplicas: 1, maxReplicas: 10, cpuPercent: 80, memPercent: 0 });
|
|
} catch (e: any) {
|
|
toast({ title: t('monitor.quickSetupFailed'), description: e?.message || String(e), variant: 'destructive' });
|
|
} finally { setLoading(false); }
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Button variant="outline" size="sm" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]" onClick={() => setOpen(true)}>
|
|
<Plus className="h-3.5 w-3.5 mr-1" />创建 HPA
|
|
</Button>
|
|
{open && (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4" onClick={() => setOpen(false)}>
|
|
<div className="bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-xl w-[480px] max-w-[92vw] max-h-[85vh] flex flex-col" onClick={(e) => e.stopPropagation()}>
|
|
<h2 className="text-lg font-bold text-[var(--dg-text-primary)] px-6 pt-6 pb-4 shrink-0">{t('k8s.hpaCronHpa.createHpa')}</h2>
|
|
<div className="flex-1 min-h-0 overflow-y-auto px-6 space-y-3">
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('common.name')}</Label>
|
|
<Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })}
|
|
placeholder={`hpa-${deploymentName}`}
|
|
className="dg-input mt-1" />
|
|
</div>
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('common.target')}</Label>
|
|
<p className="text-[var(--dg-text-secondary)] text-sm mt-1 bg-[var(--dg-bg-tertiary)] rounded px-3 py-2 truncate" title={t('kubernetes.createhpadialog.s7aa398', { deploymentName: deploymentName, namespace: namespace })}>
|
|
Deployment: {deploymentName} · 命名空间: {namespace}
|
|
</p>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('kubernetes.createhpadialog.s6a5bed')}</Label>
|
|
<Input type="number" value={form.minReplicas} min={1}
|
|
onChange={(e) => setForm({ ...form, minReplicas: Number(e.target.value) })}
|
|
className="dg-input mt-1" />
|
|
</div>
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('kubernetes.createhpadialog.sc3f2cf')}</Label>
|
|
<Input type="number" value={form.maxReplicas} min={1}
|
|
onChange={(e) => setForm({ ...form, maxReplicas: Number(e.target.value) })}
|
|
className="dg-input mt-1" />
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('kubernetes.createhpadialog.s94bfd4')}</Label>
|
|
<Input type="number" value={form.cpuPercent} min={0} max={100}
|
|
onChange={(e) => setForm({ ...form, cpuPercent: Number(e.target.value) })}
|
|
className="dg-input mt-1" />
|
|
</div>
|
|
<div>
|
|
<Label className="dg-text-secondary text-sm">{t('kubernetes.createhpadialog.s82f202')} <span className="dg-text-muted">{t('common.optional')}</span></Label>
|
|
<Input type="number" value={form.memPercent} min={0} max={100}
|
|
onChange={(e) => setForm({ ...form, memPercent: Number(e.target.value) })}
|
|
className="dg-input mt-1" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-end gap-2 px-6 py-4 border-t border-[var(--dg-border)] shrink-0">
|
|
<Button variant="outline" className="border-[var(--dg-border)] dg-text-secondary" onClick={() => setOpen(false)}>{t('common.cancel')}</Button>
|
|
<Button className="bg-blue-600 hover:bg-blue-700" disabled={loading} onClick={handleCreate}>
|
|
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : i18n.t('common.create')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
} |