From 892cb85676201fe3ecec4db86e71fc91346b8332 Mon Sep 17 00:00:00 2001 From: attacker Date: Mon, 6 Jul 2026 20:20:59 +0800 Subject: [PATCH] =?UTF-8?q?refactor(quality):=20Q6=20=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E5=B7=A8=E5=9E=8B=E7=BB=84=E4=BB=B6=E6=8B=86=E5=88=86=20?= =?UTF-8?q?=E2=80=94=20ResourceVisualEditor=20882L=E2=86=92282L=20(-68%),?= =?UTF-8?q?=20=E6=8F=90=E5=8F=96=205=20=E4=B8=AA=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E7=BC=96=E8=BE=91=E5=99=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 ResourceVisualEditor.tsx (882L, 项目最大前端组件) 中的 5 个内联资源编辑器 提取为 resource-visual-editors/ 子目录下的独立文件: - ConfigMapEditor.tsx (95L) — ConfigMap 键值对表格 - SecretEditor.tsx (114L) — Secret Base64 编解码 - ServiceEditor.tsx (155L) — Service 端口/类型/选择器 - IngressEditor.tsx (215L) — Ingress Host/Path 路由规则 - PvcEditor.tsx (90L) — PVC 存储配置 主文件仅保留加载/保存逻辑 + YAML/可视化切换 + 资源类型分发。 清理 11 个 unused import。零逻辑变更,纯机械提取。 验证: tsc -b=0, npm build✓ (16.11s), ESLint errors=0, 17/17 测试通过 --- PROJECT_EVALUATION.md | 2 +- ROADMAP.md | 35 + .../kubernetes/ResourceVisualEditor.tsx | 612 +----------------- .../ConfigMapEditor.tsx | 95 +++ .../resource-visual-editors/IngressEditor.tsx | 215 ++++++ .../resource-visual-editors/PvcEditor.tsx | 90 +++ .../resource-visual-editors/SecretEditor.tsx | 114 ++++ .../resource-visual-editors/ServiceEditor.tsx | 155 +++++ 8 files changed, 711 insertions(+), 607 deletions(-) create mode 100644 frontend/src/components/kubernetes/resource-visual-editors/ConfigMapEditor.tsx create mode 100644 frontend/src/components/kubernetes/resource-visual-editors/IngressEditor.tsx create mode 100644 frontend/src/components/kubernetes/resource-visual-editors/PvcEditor.tsx create mode 100644 frontend/src/components/kubernetes/resource-visual-editors/SecretEditor.tsx create mode 100644 frontend/src/components/kubernetes/resource-visual-editors/ServiceEditor.tsx diff --git a/PROJECT_EVALUATION.md b/PROJECT_EVALUATION.md index b8c891f..2279a48 100644 --- a/PROJECT_EVALUATION.md +++ b/PROJECT_EVALUATION.md @@ -129,7 +129,7 @@ | ~~`api.ts` 1324 行/352 方法~~ → 已拆分为 12 个域文件 (api/kubernetes.ts, deploy.ts, monitor.ts 等) | ✅ 已解决 | 前端 | ~~P0~~ done | | 前端 **1026 处** `any` 类型 | 类型安全缺失,重构风险高 | 前端全局 | ~~P0~~ **done** (any 1076→40, unused 25→6, console 93→1, tsc --noEmit=0) | | ~~K8s 双路由体系(集群域+Kuboard 域)~~ → code 路由统一为主,ID 路由标记 deprecated 向后兼容 | ✅ 已解决 | 后端 | ~~P1~~ done | -| 25 个 ≥500 行巨型组件 | 拆分困难 | 前端 | P1 | +| 25 个 ≥500 行巨型组件 | 拆分困难 | 前端 | P1 → **Q6 done: 最大组件 ResourceVisualEditor 882L→282L (-68%),提取 5 个独立编辑器文件** | ### 3.2 🟡 中优先级 diff --git a/ROADMAP.md b/ROADMAP.md index 0538e5e..177d68b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -477,6 +477,7 @@ services/api.ts (1324L) | Q4+ | 后端错误处理治理扩展(Q5: RDP/API Token/AIOps 模块 `_ =` DB 写入) | P0 | **done** | | U13 | 主机监控大屏挂载(HostMonitorDashboard 死代码复活) | P3 | **done** | | U14 | ESLint 冗余 disable 指令清理(unused eslint-disable 6→0) | P3 | **done** | +| Q6 | 前端巨型组件拆分(ResourceVisualEditor 882L→282L,提取 5 个独立编辑器) | P0 | **done** | --- @@ -610,3 +611,37 @@ pending → in_progress → done / blocked - [x] `npm run build` 零错误(✓ built in 16.93s) - [x] 17/17 集成回归测试通过(零回归) - [x] Docker 部署 healthy(改动不影响运行时) + +--- + +## Q6: 前端巨型组件拆分 — ResourceVisualEditor [done] + +**问题**: `ResourceVisualEditor.tsx`(882 行)是项目最大的前端组件,包含 5 个内联资源编辑器(ConfigMap/Secret/Service/Ingress/PVC),是 PROJECT_EVALUATION.md 3.1 🔴 高优先级技术债"25 个 ≥500 行巨型组件"中最大的一个。单文件过大导致维护困难、代码导航低效。 + +**已完成 (2026-07-06)**: + +将 5 个内联资源编辑器提取为 `resource-visual-editors/` 子目录下的独立文件: + +| 新文件 | 行数 | 职责 | +|--------|------|------| +| `ConfigMapEditor.tsx` | 95 | ConfigMap 键值对表格编辑器 | +| `SecretEditor.tsx` | 114 | Secret 键值对表格 (Base64 编码/解码) | +| `ServiceEditor.tsx` | 155 | Service 端口/类型/选择器编辑器 | +| `IngressEditor.tsx` | 215 | Ingress Host/Path 路由规则编辑器 | +| `PvcEditor.tsx` | 90 | PVC 存储大小/访问模式/StorageClass 编辑器 | + +主文件 `ResourceVisualEditor.tsx` 从 **882 行降至 282 行**(-68%),仅保留:加载/保存逻辑、YAML/可视化模式切换、资源类型分发(dispatch)。 + +**提取原则**: 每个子编辑器是自包含的函数组件,接收 `{manifest, onSave, saving, isCreate}` props(IngressEditor 额外接收 `clusterCode`),无共享状态。提取为纯机械操作(移动函数 + 添加 import/export),零逻辑变更。 + +**验收标准**: +- [x] ResourceVisualEditor.tsx 从 882 行降至 **282 行**(-68%) +- [x] 5 个提取的编辑器文件全部 < 220 行 +- [x] `tsc -b` 零错误 +- [x] `npm run build` 零错误(✓ built in 16.11s) +- [x] ESLint errors 保持 **0**(清理 11 个 unused import) +- [x] ESLint warnings 保持 **59**(无新增) +- [x] `go build` 零错误 +- [x] 17/17 集成回归测试通过(零回归) +- [x] Docker 部署 healthy +- [x] K8s 资源 YAML API 链路验证通过(visual editor dispatch 正常) diff --git a/frontend/src/components/kubernetes/ResourceVisualEditor.tsx b/frontend/src/components/kubernetes/ResourceVisualEditor.tsx index f3bd060..dff1f79 100644 --- a/frontend/src/components/kubernetes/ResourceVisualEditor.tsx +++ b/frontend/src/components/kubernetes/ResourceVisualEditor.tsx @@ -2,13 +2,9 @@ // ResourceVisualEditor — ConfigMap/Secret/Service/Ingress/PVC 可视化编辑 // Logan.Li import { useState, useEffect, useCallback } from 'react'; import type { ComponentType } from 'react'; -import { X, Save, Loader2, Plus, Trash2, FileText, Network, Shield, Database, ChevronRight} from 'lucide-react'; +import { X, Loader2, FileText, Network, Shield, Database, ChevronRight} from 'lucide-react'; import { Button } from '@/components/ui/button'; import { ModalOverlay } from '@/components/ui/modal-overlay'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; -import { Textarea } from '@/components/ui/textarea'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { useToast } from '@/hooks/use-toast'; import { kubernetesApi } from '@/api'; import { createEmptyManifest } from './resource-create-templates'; @@ -18,6 +14,11 @@ import { YamlCodeMirror } from './YamlCodeMirror'; import { getYamlResourceConfig, yamlDownloadFilename } from './k8s-yaml-resource-config'; import { downloadYamlFile } from '@/utils/export'; import i18n from '@/i18n'; +import { ConfigMapEditor } from './resource-visual-editors/ConfigMapEditor'; +import { SecretEditor } from './resource-visual-editors/SecretEditor'; +import { ServiceEditor } from './resource-visual-editors/ServiceEditor'; +import { IngressEditor } from './resource-visual-editors/IngressEditor'; +import { PvcEditor } from './resource-visual-editors/PvcEditor'; interface ResourceVisualEditorProps { clusterCode: string; @@ -279,604 +280,3 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o ); } -// ══════════════════════════════════════════════ -// ConfigMap 编辑器 — 键值对表格 -// ══════════════════════════════════════════════ -function ConfigMapEditor({ manifest, onSave, saving, isCreate }: { manifest: any; onSave: (m: any) => void; saving: boolean; isCreate?: boolean }) { - const data = manifest?.data || {}; - const [resName, setResName] = useState(manifest?.metadata?.name || ''); - const [entries, setEntries] = useState<{ key: string; value: string }[]>( - Object.entries(data).map(([key, value]) => ({ key, value: String(value) })) - ); - const [expandAll, setExpandAll] = useState(false); - - const update = (i: number, field: 'key' | 'value', val: string) => { - const next = [...entries]; - next[i] = { ...next[i], [field]: val }; - setEntries(next); - }; - - const addRow = () => setEntries([...entries, { key: '', value: '' }]); - const removeRow = (i: number) => setEntries(entries.filter((_, idx) => idx !== i)); - - const handleSave = () => { - const newData: Record = {}; - entries.forEach(e => { - if (e.key.trim()) newData[e.key.trim()] = e.value; - }); - onSave({ ...manifest, metadata: { ...manifest.metadata, name: resName.trim() }, data: newData }); - }; - - return ( -
-
- - setResName(e.target.value)} readOnly={!isCreate} className="mt-1 font-mono text-xs bg-[var(--dg-bg-tertiary)]" /> -
- -
-
- -
- - -
-
-
- {entries.map((entry, i) => ( -
- update(i, 'key', e.target.value)} - placeholder={i18n.t('kubernetes.resourcevisuale.s65017dab')} - className="flex-1 font-mono text-xs h-8 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" - /> -