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:
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');
|
||||
|
||||
Reference in new issue
Block a user