/* eslint-disable @typescript-eslint/no-explicit-any */
import { TableCell, TableRow } from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import {
Boxes, Container, Network, FileText, Shield, Activity, Clock,
FileCode, Pencil, Terminal, HardDrive, Trash2, Eye,
} from 'lucide-react';
import i18n from '@/i18n';
export type ResourceType =
| 'deployments' | 'pods' | 'services' | 'ingresses'
| 'configmaps' | 'secrets' | 'hpas' | 'cronjobs'
| 'pvcs' | 'statefulsets' | 'daemonsets'
| 'serviceaccounts' | 'roles' | 'rolebindings';
// 支持可视化编辑/新建的资源类型 // Logan.Li
export const VISUAL_RESOURCE_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets', 'pvcs'];
/** Deployment 列表:新建 + YAML 导入,不做批量导出 // Logan.Li */
export const DEPLOYMENT_LIST_TYPES: ResourceType[] = ['deployments'];
/** 支持命名空间 YAML 批量导出(对齐集群导出)// Logan.Li */
export const EXPORT_YAML_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets'];
/** 列表页保留 CSV/JSON 导出的配置类资源 // Logan.Li */
export const BULK_EXPORT_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets', 'pvcs'];
export interface ResourceRowOpts {
clusterCode: string;
namespace: string;
onDetail?: (item: any) => void;
onYaml?: (name: string) => void;
onEdit?: (name: string) => void;
onTerminal?: (item: any) => void;
onFileBrowser?: (item: any) => void;
onDeletePod?: (item: any) => void;
onPodDetail?: (item: any) => void;
}
export const VisualActions = ({ name, opts }: { name: string; opts: { onYaml?: (n: string) => void; onEdit?: (n: string) => void } }) => (
);
export const RESOURCE_CONFIG: Record;
columns: string[];
renderRow: (item: any, opts: ResourceRowOpts) => React.ReactNode;
}> = {
deployments: {
title: 'Deployments', subtitle: i18n.t('k8s.nsResource.deployDesc'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('kubernetes.container.image')],
renderRow: (d, opts) => (
opts.onDetail?.(d)}>
{d.name}
{d.namespace}
{(() => {
const ready = d.ready_replicas || 0; const total = d.replicas || 0;
const pct = total > 0 ? (ready / total) * 100 : 0; const done = ready === total;
return (
);
})()}
{d.image || '-'}
),
},
pods: {
title: 'Pods', subtitle: i18n.t('k8s.nsResource.podDesc'), icon: Container,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.terminalStatus'), i18n.t('kubernetes.node.title'), 'CPU', i18n.t('kubernetes.pod.memory'), i18n.t('agent.agentServiceRestart'), i18n.t('kubernetes.container.image'), i18n.t('system.auditAction')],
renderRow: (p, opts) => {
const statusMap: Record = { Running: 'bg-[var(--dg-green)]/20 text-[var(--dg-green)] border-[var(--dg-green)]/30', Pending: 'bg-[var(--dg-orange)]/20 text-[var(--dg-orange)] border-[var(--dg-orange)]/30', Failed: 'bg-[var(--dg-red)]/20 text-[var(--dg-red)] border-[var(--dg-red)]/30' };
return (
opts.onPodDetail?.(p)}>
{p.name}
{p.namespace}
{p.status || 'Unknown'}
{p.node_name || '-'}
{p.cpu_usage_m || '-'}
{p.mem_usage_mi || '-'}
0 ? 'text-[var(--dg-orange)]' : 'text-[var(--dg-text-muted)]')}>{p.restart_count || 0}
{p.image || '-'}
);
},
},
services: {
title: 'Services', subtitle: i18n.t('k8s.nsResource.serviceDesc'), icon: Network,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.credentialType'), 'Cluster IP', i18n.t('system.ldapPort'), i18n.t('system.auditAction')],
renderRow: (s, opts) => (
{s.name}
{s.namespace}
{s.type || '-'}
{s.cluster_ip || '-'}
{s.ports || '-'}
e.stopPropagation()}>
),
},
ingresses: {
title: 'Ingresses', subtitle: i18n.t('k8s.nsResource.ingressDesc'), icon: Network,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), 'Hosts', 'TLS', i18n.t('system.auditAction')],
renderRow: (i, opts) => {
const hosts = i.hosts || [];
return (
{i.name}
{i.namespace}
{hosts.length > 0 ? hosts.join(', ') : '-'}
{i.tls ? 'HTTPS' : 'HTTP'}
e.stopPropagation()}>
);
},
},
configmaps: {
title: 'ConfigMaps', subtitle: i18n.t('k8s.nsResource.configMapDesc'), icon: FileText,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('system.auditAction')],
renderRow: (c, opts) => (
{c.name}
{c.namespace}
{c.key_count || '-'}
e.stopPropagation()}>
),
},
secrets: {
title: 'Secrets', subtitle: i18n.t('k8s.nsResource.secretDesc'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.credentialType'), i18n.t('system.auditAction')],
renderRow: (s, opts) => (
{s.name}
{s.namespace}
{s.type || '-'}
e.stopPropagation()}>
),
},
hpas: {
title: 'HPAs', subtitle: i18n.t('k8s.nsResource.hpaDesc'), icon: Activity,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('monitor.alertEvents.col.target'), i18n.t('k8s.hpaCronHpa.col.minMax'), 'CPU%', 'Mem%'],
renderRow: (h, _opts) => (
{h.name}
{h.namespace}
{h.target_kind}/{h.target_name}
{h.min_replicas}/{h.max_replicas}
{h.cpu_percent ?? '-'}%
{h.mem_percent ?? '-'}%
),
},
cronjobs: {
title: 'CronJobs', subtitle: i18n.t('automation.cronJobs'), icon: Clock,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('kubernetes.workload.scheduling'), i18n.t('system.terminalStatus'), i18n.t('automation.scriptLastExec')],
renderRow: (cj) => (
{cj.name}
{cj.namespace}
{cj.schedule || '-'}
{cj.suspend ? i18n.t('kubernetes.deployment.paused') : i18n.t('agent.agentServiceRunning')}
{cj.last_schedule || '-'}
),
},
pvcs: {
title: i18n.t('k8s.nsResource.pvcDesc'), subtitle: 'PersistentVolumeClaim', icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('system.terminalStatus'), i18n.t('kubernetes.storage.pvcSize'), 'StorageClass', i18n.t('system.auditAction')],
renderRow: (p, opts) => (
{p.name}
{p.namespace}
{p.phase || '-'}
{p.size || '-'}
{p.storage_class || '-'}
e.stopPropagation()}>
),
},
statefulsets: {
title: 'StatefulSets', subtitle: i18n.t('k8s.nsResource.stsDesc'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('kubernetes.pod.ready'), i18n.t('kubernetes.container.image')],
renderRow: (s, opts) => (
opts.onDetail?.(s)}>
{s.name}
{s.namespace}
{s.replicas || 0}
{s.ready || 0}
{s.image || '-'}
),
},
daemonsets: {
title: 'DaemonSets', subtitle: i18n.t('k8s.nsResource.dsDesc'), icon: Boxes,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('monitor.siteProtocol.http.expectedPrefix'), i18n.t('cloud.current'), i18n.t('kubernetes.pod.ready'), i18n.t('kubernetes.container.image')],
renderRow: (d, opts) => (
opts.onDetail?.(d)}>
{d.name}
{d.namespace}
{d.desired || 0}
{d.current || 0}
{d.ready || 0}
{d.image || '-'}
),
},
serviceaccounts: {
title: 'ServiceAccounts', subtitle: i18n.t('k8s.nsResource.saDesc'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('common.namespace'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (sa, opts) => (
{sa.name}
{sa.namespace}
{sa.secret_count ?? 0}
{sa.image_pull_secrets && sa.image_pull_secrets.length > 0 ? sa.image_pull_secrets.join(', ') : '-'}
{sa.age || '-'}
e.stopPropagation()}>
),
},
roles: {
title: 'Roles', subtitle: i18n.t('k8s.nsResource.roleDesc'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('system.apiKeyScope'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (r, opts) => {
const verbs = r.verbs || [];
const resources = r.resources || [];
const verbsStr = verbs.length > 4 ? verbs.slice(0, 4).join(', ') + ` +${verbs.length - 4}` : verbs.join(', ');
const resStr = resources.length > 4 ? resources.slice(0, 4).join(', ') + ` +${resources.length - 4}` : resources.join(', ');
return (
{r.name}
{r.namespace}
{r.rule_count ?? 0}
verbs: {verbsStr || '-'}
resources: {resStr || '-'}
{r.age || '-'}
e.stopPropagation()}>
);
},
},
rolebindings: {
title: 'RoleBindings', subtitle: i18n.t('k88s.nsResource.rbDesc'), icon: Shield,
columns: [i18n.t('kubernetes.secret.secretName'), i18n.t('kubernetes.namespace.title'), i18n.t('common.name'), i18n.t('common.namespace'), i18n.t('system.userCreatedAt'), i18n.t('system.auditAction')],
renderRow: (rb, opts) => {
const subjects = rb.subjects || [];
const subjStr = subjects.length > 3 ? subjects.slice(0, 3).join(', ') + ` +${subjects.length - 3}` : subjects.join(', ');
return (
{rb.name}
{rb.namespace}
{rb.role_ref_kind || '-'}/{rb.role_ref_name || '-'}
{subjStr || '-'}
{rb.age || '-'}
e.stopPropagation()}>
);
},
},
};