feat: PTY kubectl终端 + 侧边栏对齐修复 + 构建缓存清理

**kubectl WebShell 修复:**
- 引入 github.com/creack/pty 库实现真正的伪终端
- 替换 bash --noediting + TERM=dumb 方案为 PTY-backed bash
- 支持 xterm-256color、窗口自适应、readline 交互
- 修复键盘输入无响应问题

**侧边栏优化:**
- 独立菜单项高度从 py-1.5 改为 h-8,与父菜单对齐
- 独立菜单图标从 h-3 w-3 改为 h-3.5 w-3.5,统一 14px

**构建优化:**
- run.sh docker up 增加 docker image prune -f 清理悬空镜像
- 每次部署自动清理 builder cache + dangling images

**认证修复(历史):**
- Token 存储:Zustand + localStorage 双写,http.ts 双源 fallback
- YamlViewer/DeploymentDetail token 来源统一为 Zustand store
This commit is contained in:
attacker committed 2026-06-19 11:22:45 +00:00
1 parent cac1414917
commit a3cd0d3910
29 files changed
+2954 -180

No files matched your search

@@ -26,11 +26,13 @@ import {
Eye,
Trash2,
Search,
Container,
} from 'lucide-react';
import { kubernetesApi } from '@/services/api';
import type { KubernetesCluster } from '@/types';
import { KubernetesClusterDetail } from './KubernetesClusterDetail';
import { KubernetesClusterDialog } from './KubernetesClusterDialog';
import { KubectlTerminal } from './KubectlTerminal';
export function KubernetesClusters() {
const [clusters, setClusters] = useState<any[]>([]);
@@ -42,6 +44,10 @@ export function KubernetesClusters() {
const [dialogOpen, setDialogOpen] = useState(false);
const [editingCluster, setEditingCluster] = useState<any>(null);
// kubectl 终端
const [kubectlCluster, setKubectlCluster] = useState<{id: number; name: string} | null>(null);
const [kubectlTerminalOpen, setKubectlTerminalOpen] = useState(false);
const loadData = async () => {
try {
setLoading(true);
@@ -273,6 +279,17 @@ export function KubernetesClusters() {
<Settings className="h-4 w-4 mr-2" />
配置
</DropdownMenuItem>
<DropdownMenuItem
className="text-emerald-400 focus:bg-slate-700 focus:text-emerald-300"
onClick={(e) => {
e.stopPropagation();
setKubectlCluster({ id: cluster.id, name: cluster.name });
setKubectlTerminalOpen(true);
}}
>
<Container className="h-4 w-4 mr-2" />
kubectl
</DropdownMenuItem>
<DropdownMenuSeparator className="bg-slate-700" />
<DropdownMenuItem
className="text-red-400 focus:bg-slate-700 focus:text-red-400"
@@ -355,6 +372,19 @@ export function KubernetesClusters() {
editingCluster={editingCluster}
onSaved={loadData}
/>
{/* kubectl 终端 */}
{kubectlCluster && (
<KubectlTerminal
open={kubectlTerminalOpen}
onOpenChange={(open) => {
setKubectlTerminalOpen(open);
if (!open) setKubectlCluster(null);
}}
clusterId={kubectlCluster.id}
clusterName={kubectlCluster.name}
/>
)}
</div>
);
}