refactor(quality): Q21 前端巨型组件拆分 — DeploymentEditAdvanced 590L→289L (-51%), 提取 types(parseAdvancedManifest+buildAdvancedManifest 纯函数) + UpdateStrategyCard/TolerationsCard/PodMiscCard/PodSecurityCard/HostSettingsCard 5 个受控 Card 组件, manifest 解析(106L)和序列化(121L)提取为纯函数, 零逻辑变更, ESLint errors=0/warnings=65/any=0, tsc -b=0, npm build✓, 17/17 测试通过
This commit is contained in:
1 parent
a530d3898c
commit
b4591de97c
10 files changed
+833
-430
No files matched your search
@@ -0,0 +1,61 @@
|
||||
// TolerationsCard.tsx — 容忍 (Tolerations) CRUD 卡片 (Q21 提取)
|
||||
// 受控展示组件,接收 tolerations 数组 + 增删改回调。
|
||||
import { Plus, Trash2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import i18n from '@/i18n';
|
||||
import type { Toleration } from './types';
|
||||
|
||||
interface TolerationsCardProps {
|
||||
tolerations: Toleration[];
|
||||
onAdd: () => void;
|
||||
onRemove: (index: number) => void;
|
||||
onUpdate: (index: number, patch: Partial<Toleration>) => void;
|
||||
}
|
||||
|
||||
export function TolerationsCard({ tolerations, onAdd, onRemove, onUpdate }: TolerationsCardProps) {
|
||||
return (
|
||||
<Card className="dg-card">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm text-[var(--dg-text-primary)]"> {i18n.t('kubernetes.deploymentedita.s13a8310b')} </CardTitle>
|
||||
<Button size="sm" variant="outline" className="h-7 border-[var(--dg-border)] text-[var(--dg-text-secondary)] text-xs"
|
||||
onClick={onAdd}>
|
||||
<Plus className="h-3 w-3 mr-1" />添加
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0 space-y-2">
|
||||
{tolerations.length === 0 && <p className="text-xs dg-text-muted"> {i18n.t('kubernetes.deploymentedita.s8bc06bde')} </p>}
|
||||
{tolerations.map((t, i) => (
|
||||
<div key={i} className="grid grid-cols-[1fr_80px_1fr_100px_80px_auto] gap-2 items-center">
|
||||
<Input value={t.key} placeholder="key" onChange={e => onUpdate(i, { key: e.target.value })}
|
||||
className="h-7 dg-input text-xs font-mono" />
|
||||
<select value={t.operator} onChange={e => onUpdate(i, { operator: e.target.value })}
|
||||
className="h-7 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded text-xs text-[var(--dg-text-secondary)] px-1">
|
||||
<option value="Equal">Equal</option>
|
||||
<option value="Exists">Exists</option>
|
||||
</select>
|
||||
<Input value={t.value} placeholder="value" disabled={t.operator === 'Exists'}
|
||||
onChange={e => onUpdate(i, { value: e.target.value })}
|
||||
className="h-7 dg-input text-xs font-mono" />
|
||||
<select value={t.effect} onChange={e => onUpdate(i, { effect: e.target.value })}
|
||||
className="h-7 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded text-xs text-[var(--dg-text-secondary)] px-1">
|
||||
<option value=""> {i18n.t('kubernetes.deploymentedita.s2a6eb2dd')} </option>
|
||||
<option value="NoSchedule">NoSchedule</option>
|
||||
<option value="PreferNoSchedule">PreferNoSchedule</option>
|
||||
<option value="NoExecute">NoExecute</option>
|
||||
</select>
|
||||
<Input value={t.tolerationSeconds} placeholder={i18n.t('k8s.editAdvanced.s0c1fec65')} disabled={t.effect !== 'NoExecute'}
|
||||
onChange={e => onUpdate(i, { tolerationSeconds: e.target.value })}
|
||||
className="h-7 dg-input text-xs font-mono" />
|
||||
<Button variant="ghost" size="icon" className="h-7 w-7 dg-text-red" onClick={() => onRemove(i)}>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user