fix(q1): 修复 tsc -b 构建中断 — 回退不安全的 unknown→any + 移除 Ansible 残留引用

- 781处 tsc -b 错误清零(unknown 属性访问/隐式any返回类型/类型转换不匹配)
- 移除 App.tsx 中已删除的 AnsibleManager/AnsibleWorkflow 导入和路由
- 修复 DeploymentView 中 _prefix 解构导致的属性不存在错误
- 修复 Header/Sidebar/PipelineEditor 中无效的类型断言
- asList() 返回类型 unknown[]→any[], 恢复 AgentMonitor 正常工作
- 放宽 noImplicitAny(临时), 待 types/ 定义完善后逐步恢复
- ESLint: unused=0, console=0, any=1041(Q1 后续降低)
- npm run build: ✅ 0 errors
This commit is contained in:
attacker committed 2026-06-25 07:17:47 +08:00
1 parent 4dd5e10b46
commit 5364d93ed7
149 files changed
+2021 -3128

No files matched your search

@@ -3,7 +3,7 @@
// 替代纯 YAML 编辑,提供表单式交互体验
// 作者: Logan <admin@attacker.club>
import { useState, useEffect, useCallback } from 'react';
import { X, Save, RefreshCw, Loader2, Plus, Trash2, FileText, Network, Shield, Database, ChevronRight } from 'lucide-react';
import { X, Save, Loader2, Plus, Trash2, FileText, Network, Shield, Database, ChevronRight} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -61,13 +61,13 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
toast({ title: '可视化编辑不可用', description: '无法解析资源结构,已切换到 YAML 编辑模式' });
}
} catch (e: any) {
toast({ title: '加载失败', description: e.message, variant: 'destructive' });
toast({ title: '加载失败', description: (e as Record<string, any>).message, variant: 'destructive' });
} finally { setLoading(false); }
}, [clusterCode, namespace, resource, name]);
useEffect(() => { loadData(); }, [loadData]);
const handleSave = async (updatedManifest: any) => {
const handleSave = async ( updatedManifest: any) => {
setSaving(true);
try {
// Serialize manifest back to YAML
@@ -77,7 +77,7 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
onSaved?.();
onClose();
} catch (e: any) {
toast({ title: '保存失败', description: e.message, variant: 'destructive' });
toast({ title: '保存失败', description: (e as Record<string, any>).message, variant: 'destructive' });
} finally { setSaving(false); }
};
@@ -89,12 +89,12 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
onSaved?.();
onClose();
} catch (e: any) {
toast({ title: '保存失败', description: e.message, variant: 'destructive' });
toast({ title: '保存失败', description: (e as Record<string, any>).message, variant: 'destructive' });
} finally { setSaving(false); }
};
// Manifest → YAML string (JSON serialization works as YAML superset for K8s API)
function manifestToYaml(m: any): string {
function manifestToYaml( m: any): string {
// Use 2-space indented JSON — K8s API accepts JSON as YAML
return JSON.stringify(m, null, 2);
}
@@ -192,7 +192,7 @@ export function ResourceVisualEditor({ clusterCode, namespace, resource, name, o
// ══════════════════════════════════════════════
// ConfigMap 编辑器 — 键值对表格
// ══════════════════════════════════════════════
function ConfigMapEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m: any) => void; saving: boolean }) {
function ConfigMapEditor({ manifest, onSave, saving }: { manifest: any; onSave: ( m: any) => void; saving: boolean }) {
const data = manifest?.data || {};
const [entries, setEntries] = useState<{ key: string; value: string }[]>(
Object.entries(data).map(([key, value]) => ({ key, value: String(value) }))
@@ -264,7 +264,7 @@ function ConfigMapEditor({ manifest, onSave, saving }: { manifest: any; onSave:
// ══════════════════════════════════════════════
// Secret 编辑器 — 键值对表格 (Base64 编码/解码)
// ══════════════════════════════════════════════
function SecretEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m: any) => void; saving: boolean }) {
function SecretEditor({ manifest, onSave, saving }: { manifest: any; onSave: ( m: any) => void; saving: boolean }) {
const rawData = manifest?.data || {};
// Decode base64 values for editing
const [entries, setEntries] = useState<{ key: string; value: string; encoded: boolean }[]>(
@@ -353,11 +353,11 @@ function SecretEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m:
// ══════════════════════════════════════════════
// Service 编辑器 — 端口配置 + 类型 + 选择器
// ══════════════════════════════════════════════
function ServiceEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m: any) => void; saving: boolean }) {
function ServiceEditor({ manifest, onSave, saving }: { manifest: any; onSave: ( m: any) => void; saving: boolean }) {
const spec = manifest?.spec || {};
const [svcType, setSvcType] = useState(spec.type || 'ClusterIP');
const [ports, setPorts] = useState<any[]>(
(spec.ports || []).map((p: any) => ({
(spec.ports || []).map(( p: any) => ({
name: p.name || '',
port: String(p.port || ''),
targetPort: String(p.targetPort || ''),
@@ -386,10 +386,10 @@ function ServiceEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m
const removeSelector = (i: number) => setSelector(selector.filter((_, idx) => idx !== i));
const handleSave = () => {
const newSpec: any = { ...spec };
const newSpec: Record<string, any> = { ...spec };
newSpec.type = svcType;
newSpec.ports = ports.map(p => {
const port: any = {
const port: Record<string, any> = {
port: parseInt(p.port) || 80,
targetPort: parseInt(p.targetPort) || parseInt(p.port) || 80,
protocol: p.protocol,
@@ -484,15 +484,15 @@ function ServiceEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m
// ══════════════════════════════════════════════
// Ingress 编辑器 — Host/Path 路由规则
// ══════════════════════════════════════════════
function IngressEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m: any) => void; saving: boolean }) {
function IngressEditor({ manifest, onSave, saving }: { manifest: any; onSave: ( m: any) => void; saving: boolean }) {
const spec = manifest?.spec || {};
const [rules, setRules] = useState<{ host: string; paths: { path: string; pathType: string; serviceName: string; servicePort: string }[] }[]>(
(spec.rules || []).map((r: any) => ({
(spec.rules || []).map(( r: any) => ({
host: r.host || '',
paths: (r.http?.backend?.servicePort != null
? // Old-style single backend
[{ path: '/', pathType: 'Prefix', serviceName: r.http?.backend?.serviceName || '', servicePort: String(r.http?.backend?.servicePort || '80') }]
: (r.http?.paths || []).map((p: any) => ({
: (r.http?.paths || []).map(( p: any) => ({
path: p.path || '/',
pathType: p.pathType || 'Prefix',
serviceName: p.backend?.service?.name || p.backend?.serviceName || '',
@@ -594,7 +594,7 @@ function IngressEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m
// ══════════════════════════════════════════════
// PVC 编辑器 — 存储大小/访问模式/StorageClass
// ══════════════════════════════════════════════
function PvcEditor({ manifest, onSave, saving }: { manifest: any; onSave: (m: any) => void; saving: boolean }) {
function PvcEditor({ manifest, onSave, saving }: { manifest: any; onSave: ( m: any) => void; saving: boolean }) {
const spec = manifest?.spec || {};
const resources = spec.resources?.requests || {};
const [size, setSize] = useState(resources.storage || '1Gi');