feat(k8s): 事件页简化、可视化编辑 P0、Deployment 五 Tab 修复
- 事件中心:去彩虹图表,改专业排名列表 + 主题变量 - 网络/配置/存储:ResourceVisualEditor 双向 YAML 同步、导入 YAML、新建 - vite manualChunks 减小 embed 主包体积 - run.sh:多副本强制 MODE=release + MySQL/Redis - Deployment 编辑:共享 manifest、统一 saveDeploymentManifest - 修复存储挂载 initContainers 混入 bug、补 Tolerations UI - 服务 Tab:applyYAML 创建 + ResourceVisualEditor 编辑 - 基本信息:Pod 模板标签 + Selector 同步
This commit is contained in:
1 parent
339b24a579
commit
d0cf71b05a
17 files changed
+814
-497
No files matched your search
@@ -7,10 +7,11 @@ import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import {
|
||||
Save, Loader2, Settings, RefreshCw, Shield, Clock, Network,
|
||||
Save, Loader2, Settings, RefreshCw, Shield, Clock, Network, Plus, Trash2,
|
||||
} from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { kubernetesApi } from '@/api';
|
||||
import { saveDeploymentManifest } from './deployment-manifest-save';
|
||||
import { SchedulingSection, type ScheduleMode } from './deployment-edit-advanced/SchedulingSection';
|
||||
import { DnsHostSection } from './deployment-edit-advanced/DnsHostSection';
|
||||
|
||||
@@ -19,7 +20,7 @@ interface Props {
|
||||
namespace: string;
|
||||
deploymentName: string;
|
||||
manifest: any | null;
|
||||
onSaved: () => void;
|
||||
onSaved: (updated?: any) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
@@ -308,10 +309,9 @@ export function DeploymentEditAdvanced({ clusterCode, namespace, deploymentName,
|
||||
if (Object.keys(dcObj).length > 0) podSpec.dnsConfig = dcObj;
|
||||
else delete podSpec.dnsConfig;
|
||||
|
||||
const json = JSON.stringify(base, null, 2);
|
||||
await kubernetesApi.updateResourceYaml(clusterCode, namespace, 'deployments', deploymentName, json);
|
||||
await saveDeploymentManifest(clusterCode, namespace, deploymentName, base);
|
||||
toast({ title: '高级设置已保存', description: `${deploymentName} 更新已提交` });
|
||||
onSaved();
|
||||
onSaved(base);
|
||||
} catch (e) {
|
||||
toast({ title: '保存失败', description: e?.message || String(e), variant: 'destructive' });
|
||||
} finally { setSaving(false); }
|
||||
@@ -398,6 +398,49 @@ export function DeploymentEditAdvanced({ clusterCode, namespace, deploymentName,
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 容忍 (Tolerations) — 此前仅有状态无 UI // Logan.Li */}
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm text-slate-200">容忍 (Tolerations)</CardTitle>
|
||||
<Button size="sm" variant="outline" className="h-7 border-slate-700 text-slate-300 text-xs"
|
||||
onClick={() => setTolerations(prev => [...prev, { key: '', operator: 'Equal', value: '', effect: 'NoSchedule', tolerationSeconds: '' }])}>
|
||||
<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 text-slate-600">未配置容忍</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 => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, key: e.target.value } : x))}
|
||||
className="h-7 bg-slate-800 border-slate-700 text-xs font-mono" />
|
||||
<select value={t.operator} onChange={e => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, operator: e.target.value } : x))}
|
||||
className="h-7 bg-slate-800 border border-slate-700 rounded text-xs text-slate-300 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 => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, value: e.target.value } : x))}
|
||||
className="h-7 bg-slate-800 border-slate-700 text-xs font-mono" />
|
||||
<select value={t.effect} onChange={e => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, effect: e.target.value } : x))}
|
||||
className="h-7 bg-slate-800 border border-slate-700 rounded text-xs text-slate-300 px-1">
|
||||
<option value="">任意</option>
|
||||
<option value="NoSchedule">NoSchedule</option>
|
||||
<option value="PreferNoSchedule">PreferNoSchedule</option>
|
||||
<option value="NoExecute">NoExecute</option>
|
||||
</select>
|
||||
<Input value={t.tolerationSeconds} placeholder="秒" disabled={t.effect !== 'NoExecute'}
|
||||
onChange={e => setTolerations(prev => prev.map((x, idx) => idx === i ? { ...x, tolerationSeconds: e.target.value } : x))}
|
||||
className="h-7 bg-slate-800 border-slate-700 text-xs font-mono" />
|
||||
<Button variant="ghost" size="icon" className="h-7 w-7 text-red-400" onClick={() => setTolerations(prev => prev.filter((_, idx) => idx !== i))}>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<SchedulingSection
|
||||
scheduleMode={scheduleMode}
|
||||
onScheduleModeChange={setScheduleMode}
|
||||
|
||||
Reference in new issue
Block a user