// deployment-storage-fields — 存储卷类型字段 + 命名空间资源下拉关联 // Logan.Li import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { RefreshCw, Plus, Loader2 } from 'lucide-react'; import type { VolumeForm } from './deployment-volume-utils'; export interface NamespaceResourceLists { configMaps: string[]; secrets: string[]; pvcs: string[]; } /** 从列表 API 响应提取资源名称 // Logan.Li */ export function extractResourceNames(res: unknown): string[] { const arr = Array.isArray(res) ? res : ((res as Record)?.list || (res as Record)?.data || []); if (!Array.isArray(arr)) return []; return arr.map((x) => String((x as Record)?.name || '')).filter(Boolean).sort(); } interface ResourcePickerProps { label: string; value: string; options: string[]; loading?: boolean; onChange: (name: string) => void; onRefresh: () => void; onCreate: () => void; } /** 命名空间资源下拉:关联已有 / 刷新 / 新建 // Logan.Li */ export function NamespaceResourcePicker({ label, value, options, loading, onChange, onRefresh, onCreate, }: ResourcePickerProps) { const orphan = value && !options.includes(value); return (
{label} {options.length === 0 && !orphan && ( 命名空间内暂无{label},请先新建 )}
); } interface VolumeTypeFieldsProps { vol: VolumeForm; resources: NamespaceResourceLists; resourcesLoading: boolean; onChange: (p: Partial) => void; onRefreshResources: () => void; onCreateResource: (kind: 'configmaps' | 'secrets' | 'pvcs') => void; } export function VolumeTypeFields({ vol, resources, resourcesLoading, onChange, onRefreshResources, onCreateResource, }: VolumeTypeFieldsProps) { if (vol.type === 'persistentVolumeClaim') { return (
onChange({ pvcName: name })} onRefresh={onRefreshResources} onCreate={() => onCreateResource('pvcs')} />
); } if (vol.type === 'emptyDir') { return (
介质 onChange({ sizeLimit: e.target.value })} placeholder="sizeLimit 如 512Mi" className="h-7 flex-1 min-w-[120px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
); } if (vol.type === 'hostPath') { return (
主机路径 onChange({ path: e.target.value })} placeholder="/data/app" className="h-7 flex-1 min-w-[160px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
); } if (vol.type === 'nfs') { return (
NFS onChange({ nfsServer: e.target.value })} placeholder="Server IP" className="h-7 w-36 dg-input text-[var(--dg-text-secondary)] text-xs font-mono" /> onChange({ nfsPath: e.target.value })} placeholder="/export/path" className="h-7 flex-1 min-w-[120px] dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
); } if (vol.type === 'configMap') { return (
onChange({ configMapName: name })} onRefresh={onRefreshResources} onCreate={() => onCreateResource('configmaps')} />
键映射 onChange({ cmItems: e.target.value })} placeholder="key:path(可选,挂载子项)" className="h-7 flex-1 max-w-md dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
); } if (vol.type === 'secret') { return (
onChange({ secretName: name })} onRefresh={onRefreshResources} onCreate={() => onCreateResource('secrets')} />
键映射 onChange({ secItems: e.target.value })} placeholder="key:path(可选,挂载子项)" className="h-7 flex-1 max-w-md dg-input text-[var(--dg-text-secondary)] text-xs font-mono" />
); } if (vol.type === 'custom') { return

未识别卷类型,保存时将保留原始 YAML 结构

; } return null; }