From 174382ff812cf9e94ac102813d9c42f8353b9be1 Mon Sep 17 00:00:00 2001 From: attacker Date: Tue, 23 Jun 2026 02:27:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(k8s):=20PodExecTerminal=20error=20msg=20?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=AF=B9=E9=BD=90=20+=20command=20=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PodExecTerminal 传 shell 作为 command 到 WS URL - 去掉发送 shell\r 的旧行为(K8s exec URL 已含 command) - error 消息检查 msg.data 字段(与后端 WSMessage.Data 对齐) - 已验证: WebSocket exec 端到端可用 (id 命令在 argocd pod 成功执行) --- .../src/components/kubernetes/PodExecTerminal.tsx | 3 ++- frontend/src/components/kubernetes/YamlViewer.tsx | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/kubernetes/PodExecTerminal.tsx b/frontend/src/components/kubernetes/PodExecTerminal.tsx index 921adfd..ee11441 100644 --- a/frontend/src/components/kubernetes/PodExecTerminal.tsx +++ b/frontend/src/components/kubernetes/PodExecTerminal.tsx @@ -130,7 +130,8 @@ export function PodExecTerminal({ } else if (msg.status === 1) { // 服务端 resize 确认,忽略 } else if (msg.status === 2 || msg.error) { - term.write(`\r\n\x1b[31m${msg.message || msg.error || '执行错误'}\x1b[0m\r\n`); + const errMsg = msg.data || msg.message || msg.error || '执行错误'; + term.write(errMsg.includes('\\x1b') ? errMsg : `\\r\\n\\x1b[31m${errMsg}\\x1b[0m\\r\\n`); } } catch { if (typeof event.data === 'string') term.write(event.data); diff --git a/frontend/src/components/kubernetes/YamlViewer.tsx b/frontend/src/components/kubernetes/YamlViewer.tsx index 698fbc4..b8cc405 100644 --- a/frontend/src/components/kubernetes/YamlViewer.tsx +++ b/frontend/src/components/kubernetes/YamlViewer.tsx @@ -14,23 +14,27 @@ interface YamlViewerProps { onSaved?: () => void; /** 进入编辑模式前是否清理只读/噪音字段(managedFields/uid/status 等) */ cleanBeforeEdit?: boolean; + /** 打开即自动进入编辑模式(编辑按钮专用入口) */ + autoEdit?: boolean; } -export function YamlViewer({ clusterCode, namespace, resource, name, onClose, onSaved, cleanBeforeEdit = false }: YamlViewerProps) { +export function YamlViewer({ clusterCode, namespace, resource, name, onClose, onSaved, cleanBeforeEdit = false, autoEdit = false }: YamlViewerProps) { const { toast } = useToast(); const [rawYaml, setRawYaml] = useState(''); // 原始(只读展示用) const [editYaml, setEditYaml] = useState(''); // 编辑态(可能被清理过) const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); - const [editing, setEditing] = useState(false); + const [editing, setEditing] = useState(autoEdit); // autoEdit → 初始即编辑态 const [copied, setCopied] = useState(false); + // autoEdit 时隐式启用清理(编辑入口必须有清理,否则 status/managedFields 会被 K8s 拒绝) + const effectiveClean = cleanBeforeEdit || autoEdit; const loadYaml = async () => { setLoading(true); try { const text = await kubernetesApi.getResourceYaml(clusterCode, namespace, resource, name); setRawYaml(text); - setEditYaml(text); + setEditYaml(effectiveClean ? cleanYAML(text) : text); } catch (e: any) { toast({ title: '获取YAML失败', description: e.message, variant: 'destructive' }); const err = `# Error: ${e.message}`; @@ -41,10 +45,10 @@ export function YamlViewer({ clusterCode, namespace, resource, name, onClose, on const enterEdit = () => { // 进入编辑前可选清理 - const cleaned = cleanBeforeEdit ? cleanYAML(rawYaml) : rawYaml; + const cleaned = effectiveClean ? cleanYAML(rawYaml) : rawYaml; setEditYaml(cleaned); setEditing(true); - if (cleanBeforeEdit) { + if (effectiveClean) { toast({ title: '已清理只读字段', description: '已剥离 status / managedFields / uid 等' }); } };