- 抽取 deployment-volume-utils,修正 PVC/NFS/CM/Secret/HostPath/EmptyDir 读写 - 保存时保留系统卷与 serviceAccount 挂载,合并用户卷与挂载点 - 挂载支持 subPath;ConfigMap/Secret items 支持 key:path 简写
2 lines
31 KiB
JavaScript
2 lines
31 KiB
JavaScript
import{j as e,r as d}from"./vendor-codemirror-C7mXSpXt.js";import{C as oe,a as ne,b as Fe,c as He,d as Je}from"./card-BVNSlZ0C.js";import{g as Ge,f as Ke,B as v,D as Te,a as je,b as Ve,c as Ne,d as ve,e as Ze,t as j}from"./index-EF2TDvxx.js";import{I as Se}from"./input--Xdj49es.js";import{L as ae}from"./label-DZckFZd3.js";import{B as Ce}from"./badge-BodqHT_V.js";import{S as ce,a as re,b as le,c as ie,d as q}from"./select-DbRZUnPK.js";import{T as qe}from"./textarea-JgdELMPr.js";import{k as _}from"./index-CYw3SC6I.js";import{h as Ee,ad as es,a4 as ss,D as ts,N as os,B as ns,i as pe,G as as,d as _e,L as $e,R as cs,P as rs,ai as Me,$ as ls,n as is,S as ds,T as ps}from"./vendor-icons-Aso0-eeY.js";import"./index-CYARH0Cq.js";const de={cluster:"集群",loadbalancer:"Ingress",service:"Service",app:"Deployment",server:"Node",database:"数据库",external:"外部服务",custom:"自定义"},ms=[{value:"database",label:"数据库",desc:"MySQL / Redis / PostgreSQL 等"},{value:"external",label:"外部服务",desc:"外部 API / CDN / DNS 等"},{value:"custom",label:"自定义",desc:"其他自定义节点"}],X=u=>u.startsWith("custom-");function M(u,h="h-5 w-5"){switch(u){case"server":return e.jsx(Ee,{"code-path":"src/components/kubernetes/topology-helpers.tsx:31:27",className:h});case"loadbalancer":return e.jsx(as,{"code-path":"src/components/kubernetes/topology-helpers.tsx:32:33",className:h});case"cluster":return e.jsx(pe,{"code-path":"src/components/kubernetes/topology-helpers.tsx:33:28",className:h});case"app":return e.jsx(ns,{"code-path":"src/components/kubernetes/topology-helpers.tsx:34:24",className:h});case"service":return e.jsx(os,{"code-path":"src/components/kubernetes/topology-helpers.tsx:35:28",className:h});case"database":return e.jsx(ts,{"code-path":"src/components/kubernetes/topology-helpers.tsx:36:29",className:h});case"external":return e.jsx(ss,{"code-path":"src/components/kubernetes/topology-helpers.tsx:37:29",className:h});case"custom":return e.jsx(es,{"code-path":"src/components/kubernetes/topology-helpers.tsx:38:27",className:h});default:return e.jsx(Ee,{"code-path":"src/components/kubernetes/topology-helpers.tsx:39:21",className:h})}}function ee(u){switch(u){case"server":return"bg-blue-500/20 text-blue-400 border-blue-500/30";case"loadbalancer":return"bg-purple-500/20 text-purple-400 border-purple-500/30";case"cluster":return"bg-cyan-500/20 text-cyan-400 border-cyan-500/30";case"app":return"bg-rose-500/20 text-rose-400 border-rose-500/30";case"service":return"bg-emerald-500/20 text-emerald-400 border-emerald-500/30";case"database":return"bg-amber-500/20 text-amber-400 border-amber-500/30";case"external":return"bg-orange-500/20 text-orange-400 border-orange-500/30";case"custom":return"bg-slate-500/20 text-slate-400 border-slate-500/30";default:return"bg-slate-500/20 text-slate-400 border-slate-500/30"}}function us(u,h,D,Y,x){const V=[],l=[],z=Math.max(1,h.length,D.length,Y.length,x.length),L=Math.max(900,Math.min(z*130,2400)),r=[60,180,320,480,640],N=o=>{const i=Math.min(o,12);if(i===0)return[];if(i===1)return[L/2];const c=L/(i+1);return Array.from({length:i},(p,g)=>c*(g+1))},E=`cluster-${u.id}`;V.push({id:E,name:u.name||"集群",type:"cluster",x:L/2,y:r[0],data:{kind:"cluster",version:u.version,status:u.status,api_server:u.api_server,node_count:u.node_count,pod_count:u.pod_count}});const R=h.slice(0,12),B=N(R.length);R.forEach((o,i)=>{const c=`ingress-${o.id}`;V.push({id:c,name:o.name,type:"loadbalancer",x:B[i],y:r[1],data:{kind:"ingress",namespace:o.namespace,backend:o.backend,tls:o.tls,hosts:o.hosts}}),l.push({id:`e-${E}-${c}`,source:E,target:c,label:"route"})});const f=D.slice(0,12),A=N(f.length);f.forEach((o,i)=>{const c=`service-${o.id}`;V.push({id:c,name:o.name,type:"service",x:A[i],y:r[2],data:{kind:"service",namespace:o.namespace,type:o.type,cluster_ip:o.cluster_ip,external_ip:o.external_ip,selector:o.selector}})}),R.length>0&&f.length>0?R.forEach(o=>{const i=`ingress-${o.id}`,c=(o.backend||"").split(":")[0].trim();let p=f.filter(g=>g.name===c);p.length===0&&(p=f.filter(g=>g.namespace===o.namespace)),p.length===0&&(p=[f[0]]),p.forEach(g=>l.push({id:`e-${i}-service-${g.id}`,source:i,target:`service-${g.id}`,label:"→"}))}):f.length>0&&f.forEach(o=>l.push({id:`e-${E}-service-${o.id}`,source:E,target:`service-${o.id}`,label:"expose"}));const T=Y.slice(0,12),H=N(T.length);T.forEach((o,i)=>{const c=`deploy-${o.id}`;V.push({id:c,name:o.name,type:"app",x:H[i],y:r[3],data:{kind:"deployment",namespace:o.namespace,replicas:o.replicas,ready_replicas:o.ready_replicas,available_replicas:o.available_replicas,image:o.image}})}),f.length>0&&T.length>0&&f.forEach(o=>{const i=`service-${o.id}`;let c=[];try{const p=typeof o.selector=="string"?JSON.parse(o.selector||"{}"):o.selector||{},g=Object.entries(p);g.length>0&&(c=T.filter(P=>{let W={};try{W=typeof P.labels=="string"?JSON.parse(P.labels||"{}"):P.labels||{}}catch{}return g.every(([se,G])=>W[se]===G)}))}catch{}c.length===0&&(c=T.filter(p=>p.name===o.name)),c.length===0&&(c=T.filter(p=>p.namespace===o.namespace)),c.length===0&&(c=[T[0]]),c.slice(0,4).forEach(p=>l.push({id:`e-${i}-deploy-${p.id}`,source:i,target:`deploy-${p.id}`,label:"select"}))});const I=x.slice(0,12),J=N(I.length);I.forEach((o,i)=>{const c=`k8snode-${o.id}`;V.push({id:c,name:o.name,type:"server",x:J[i],y:r[4],data:{kind:"node",ip:o.ip,role:o.role,status:o.status,os:o.os,cpu:o.cpu,memory:o.memory,cpu_usage:o.cpu_usage,memory_usage:o.memory_usage,pod_count:o.pod_count}})});const y=I.filter(o=>(o.role||"").toLowerCase()==="worker"),O=y.length>0?y:I;return T.length>0&&O.length>0&&T.forEach(o=>{const i=`deploy-${o.id}`;O.slice(0,3).forEach(c=>l.push({id:`e-${i}-k8snode-${c.id}`,source:i,target:`k8snode-${c.id}`,label:"schedule"}))}),{nodes:V,edges:l}}function Ns(){const{clusterCode:u}=Ge(),h=Ke(),[D,Y]=d.useState([]),[x,V]=d.useState(""),[l,S]=d.useState({nodes:[],edges:[]}),[z,L]=d.useState(!1),[r,N]=d.useState(null),[E,R]=d.useState(""),[B,f]=d.useState("all"),[A,T]=d.useState(null),[H,I]=d.useState({x:0,y:0}),J=d.useRef(null),[y,O]=d.useState(!1),[o,i]=d.useState(!1),[c,p]=d.useState(null),[,g]=d.useState(null),[P,W]=d.useState(!1),[se,G]=d.useState(1),[De,Q]=d.useState(!1),[U,me]=d.useState(null),[w,F]=d.useState({name:"",type:"database",note:""}),ue=d.useCallback(async()=>{try{const n=(await _.getClusters())?.list||[];if(Y(n),!x)if(u){const t=n.find(a=>(a.code||String(a.id))===u);t&&V(String(t.id))}else n.length>0&&V(String(n[0].id))}catch{Y([])}},[u]);d.useEffect(()=>{ue()},[ue]);const xe=d.useCallback(async s=>{try{const t=await _.getTopology(s);if(t?.layout_data){const a=JSON.parse(t.layout_data);if(g(a),a.customNodes?.length>0){const m=Math.max(...a.customNodes.map(k=>{const b=k.id.match(/custom-(\d+)/);return b?parseInt(b[1]):0}));G(m+1)}return a}}catch{}return g(null),null},[]),K=d.useCallback(async()=>{if(x){L(!0);try{const s=C=>Array.isArray(C)?C:C?.list||[],[n,t,a,m]=await Promise.all([_.getNodes(x).catch(()=>[]),_.getServices(x).catch(()=>[]),_.getDeployments(x).catch(()=>[]),_.getIngresses(x).catch(()=>[])]),k=D.find(C=>String(C.id)===x)||{},b=us(k,s(m),s(t),s(a),s(n)),$=await xe(x);$&&($.positions&&(b.nodes=b.nodes.map(C=>{const te=$.positions[C.id];return te?{...C,x:te.x,y:te.y}:C})),$.customNodes&&(b.nodes=[...b.nodes,...$.customNodes]),$.customEdges&&(b.edges=[...b.edges,...$.customEdges])),S(b)}catch{S({nodes:[],edges:[]})}finally{L(!1)}}},[x,D,xe]);d.useEffect(()=>{K()},[K]);const Z=l.nodes.filter(s=>s.name.toLowerCase().includes(E.toLowerCase())&&(B==="all"||s.type===B)),he=new Set(Z.map(s=>s.id)),ge=s=>{const n=J.current;if(!n)return{x:0,y:0};const t=n.createSVGPoint();t.x=s.clientX,t.y=s.clientY;const a=n.getScreenCTM();return a?{x:t.matrixTransform(a.inverse()).x,y:t.matrixTransform(a.inverse()).y}:{x:0,y:0}},Le=(s,n)=>{if(o)return;s.stopPropagation();const t=ge(s);I({x:t.x-n.x,y:t.y-n.y}),T(n.id)},Re=s=>{if(!A)return;const n=ge(s);S(t=>({...t,nodes:t.nodes.map(a=>a.id===A?{...a,x:n.x-H.x,y:n.y-H.y}:a)}))},be=()=>T(null),Ae=s=>{if(!A){if(o){if(!c)p(s.id),j.info(`已选择源节点: ${s.name},请点击目标节点`);else if(c===s.id)j.info("不能连接自身");else{const n={id:`custom-edge-${Date.now()}`,source:c,target:s.id,label:"connect"};S(t=>({...t,edges:[...t.edges,n]})),j.success("连线已添加"),p(null),i(!1)}return}N(s)}},Ie=()=>{me(null),F({name:"",type:"database",note:""}),Q(!0)},ye=s=>{me(s),F({name:s.name,type:s.type,note:s.data?.note||""}),Q(!0)},Oe=()=>{if(!w.name.trim()){j.error("请输入节点名称");return}if(U)S(s=>({...s,nodes:s.nodes.map(n=>n.id===U.id?{...n,name:w.name,type:w.type,data:{...n.data,note:w.note}}:n)})),j.success("节点已更新");else{const n={id:`custom-${se}`,name:w.name,type:w.type,x:we/2+(Math.random()-.5)*100,y:ke/2+(Math.random()-.5)*100,data:{kind:"custom",note:w.note}};S(t=>({...t,nodes:[...t.nodes,n]})),G(t=>t+1),j.success("节点已添加")}Q(!1)},Pe=async s=>{await h({title:"删除节点",description:`确定删除「${s.name}」?相关连线也会一并删除`,variant:"destructive"})&&(S(t=>({nodes:t.nodes.filter(a=>a.id!==s.id),edges:t.edges.filter(a=>a.source!==s.id&&a.target!==s.id)})),N(null),j.success("节点已删除"))},Xe=async s=>{if(!s.id.startsWith("custom-edge")){j.info("Kubernetes 原生关系不可删除");return}await h({title:"删除连线",description:"确定删除此自定义连线?",variant:"destructive"})&&(S(t=>({...t,edges:t.edges.filter(a=>a.id!==s.id)})),j.success("连线已删除"))},Ye=async()=>{if(x){W(!0);try{const s={positions:Object.fromEntries(l.nodes.map(n=>[n.id,{x:n.x,y:n.y}])),customNodes:l.nodes.filter(n=>X(n.id)),customEdges:l.edges.filter(n=>n.id.startsWith("custom-edge"))};await _.saveTopology(x,JSON.stringify(s)),j.success("布局已保存")}catch{j.error("保存失败")}finally{W(!1)}}},ze=async()=>{if(await h({title:"重置布局",description:"将清除已保存的布局并重新自动排列",variant:"destructive"})){try{await _.saveTopology(x,"")}catch{}g(null),O(!1),i(!1),p(null),await K(),j.success("布局已重置")}},Be=l.nodes.length>0?Math.max(...l.nodes.map(s=>s.x))+80:900,We=l.nodes.length>0?Math.max(...l.nodes.map(s=>s.y))+80:700,we=Math.max(Be,900),ke=Math.max(We,700),fe=s=>l.nodes.filter(n=>n.type===s).length,Qe=()=>{if(l.nodes.length===0)return null;const s=[60,180,320,480,640],n=["集群","Ingress","Service","Deployment","Node"];return e.jsxs("svg",{"code-path":"src/components/kubernetes/TopologyView.tsx:291:7",ref:J,width:"100%",height:"100%",viewBox:`0 0 ${we} ${ke}`,className:"bg-slate-950 rounded-lg",preserveAspectRatio:"xMidYMin meet",onMouseMove:Re,onMouseUp:be,onMouseLeave:be,children:[e.jsxs("defs",{"code-path":"src/components/kubernetes/TopologyView.tsx:293:9",children:[e.jsx("pattern",{"code-path":"src/components/kubernetes/TopologyView.tsx:294:11",id:"grid",width:"20",height:"20",patternUnits:"userSpaceOnUse",children:e.jsx("path",{"code-path":"src/components/kubernetes/TopologyView.tsx:295:13",d:"M 20 0 L 0 0 0 20",fill:"none",stroke:"#1e293b",strokeWidth:"0.5"})}),e.jsx("marker",{"code-path":"src/components/kubernetes/TopologyView.tsx:297:11",id:"arrowhead",markerWidth:"10",markerHeight:"7",refX:"28",refY:"3.5",orient:"auto",children:e.jsx("polygon",{"code-path":"src/components/kubernetes/TopologyView.tsx:298:13",points:"0 0, 10 3.5, 0 7",fill:o?"#f59e0b":"#475569"})})]}),e.jsx("rect",{"code-path":"src/components/kubernetes/TopologyView.tsx:301:9",width:"100%",height:"100%",fill:"url(#grid)"}),n.map((t,a)=>e.jsx("text",{"code-path":"src/components/kubernetes/TopologyView.tsx:303:11",x:14,y:s[a]+4,fill:"#475569",fontSize:"11",className:"font-medium select-none",children:t},t)),l.edges.map(t=>{const a=l.nodes.find(b=>b.id===t.source),m=l.nodes.find(b=>b.id===t.target);if(!a||!m||!he.has(a.id)||!he.has(m.id))return null;const k=t.id.startsWith("custom-edge");return e.jsxs("g",{"code-path":"src/components/kubernetes/TopologyView.tsx:311:13",className:y&&k?"cursor-pointer":"",onClick:()=>{y&&k&&Xe(t)},children:[e.jsx("line",{"code-path":"src/components/kubernetes/TopologyView.tsx:312:15",x1:a.x,y1:a.y,x2:m.x,y2:m.y,stroke:k?"#f59e0b":"#475569",strokeWidth:k?2:1.5,strokeDasharray:k?"6 3":void 0,markerEnd:"url(#arrowhead)",opacity:k?.8:.6}),y&&k&&e.jsx("text",{"code-path":"src/components/kubernetes/TopologyView.tsx:317:17",x:(a.x+m.x)/2,y:(a.y+m.y)/2,fill:"#f59e0b",fontSize:"10",textAnchor:"middle",className:"select-none pointer-events-none",children:"✕ 删除"})]},t.id)}),Z.map(t=>{const a=X(t.id),m=c===t.id;return e.jsxs("g",{"code-path":"src/components/kubernetes/TopologyView.tsx:327:13",transform:`translate(${t.x}, ${t.y})`,className:o?"cursor-crosshair":A===t.id?"cursor-grabbing":"cursor-grab",onMouseDown:k=>Le(k,t),onClick:()=>Ae(t),onDoubleClick:()=>{y&&ye(t)},children:[e.jsx("circle",{"code-path":"src/components/kubernetes/TopologyView.tsx:332:15",r:"28",fill:"#0f172a",stroke:m?"#f59e0b":r?.id===t.id?"#3b82f6":a?"#f59e0b":"#334155",strokeWidth:m||r?.id===t.id?3:2,strokeDasharray:a?"4 2":void 0,className:"transition-all hover:stroke-blue-500"}),e.jsx("foreignObject",{"code-path":"src/components/kubernetes/TopologyView.tsx:337:15",x:"-12",y:"-12",width:"24",height:"24",children:e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:338:17",className:`flex items-center justify-center w-full h-full ${ee(t.type).split(" ")[1]}`,children:M(t.type)})}),e.jsx("text",{"code-path":"src/components/kubernetes/TopologyView.tsx:340:15",y:"45",fill:a?"#f59e0b":"#94a3b8",fontSize:"12",textAnchor:"middle",className:"font-medium select-none",children:t.name.length>20?t.name.slice(0,18)+"…":t.name})]},t.id)})]})},Ue=s=>{const n=s.data||{},t=Object.entries(n).filter(([a])=>a!=="kind");return t.length===0?null:e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:355:7",className:"grid grid-cols-2 gap-3",children:t.map(([a,m])=>e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:357:11",className:"p-2 rounded-lg bg-slate-800/50",children:[e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:358:13",className:"text-xs text-slate-500 mb-0.5",children:a}),e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:359:13",className:"text-sm text-slate-200 truncate",title:String(m),children:m==null?"—":String(m)})]},a))})};return e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:367:5",className:"space-y-6",children:[e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:369:7",className:"flex items-center justify-between",children:[e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:370:9",children:[e.jsx("h1",{"code-path":"src/components/kubernetes/TopologyView.tsx:371:11",className:"text-2xl font-bold text-slate-100",children:"架构拓扑"}),e.jsxs("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:372:11",className:"text-sm text-slate-500 mt-1",children:["Kubernetes 集群资源拓扑可视化 · 拖拽节点调整布局",y&&e.jsx("span",{"code-path":"src/components/kubernetes/TopologyView.tsx:374:26",className:"text-amber-400 ml-2",children:"· 编辑模式"}),o&&e.jsxs("span",{"code-path":"src/components/kubernetes/TopologyView.tsx:375:29",className:"text-amber-400 ml-1",children:["· 连线中",c?"(选择目标节点)":"(选择源节点)"]})]})]}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:378:9",className:"flex items-center gap-2",children:[e.jsxs(ce,{"code-path":"src/components/kubernetes/TopologyView.tsx:379:11",value:x,onValueChange:s=>{V(s),N(null),O(!1)},children:[e.jsx(re,{"code-path":"src/components/kubernetes/TopologyView.tsx:380:13",className:"w-44 h-9 bg-slate-800/50 border-slate-700 text-slate-200",children:e.jsx(le,{"code-path":"src/components/kubernetes/TopologyView.tsx:380:97",placeholder:"选择集群"})}),e.jsx(ie,{"code-path":"src/components/kubernetes/TopologyView.tsx:381:13",className:"bg-slate-800 border-slate-700",children:D.map(s=>e.jsx(q,{"code-path":"src/components/kubernetes/TopologyView.tsx:382:36",value:String(s.id),children:s.name},s.id))})]}),e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:385:11",variant:y?"default":"outline",size:"sm",className:"h-9",onClick:()=>{O(!y),i(!1),p(null)},children:[e.jsx(_e,{"code-path":"src/components/kubernetes/TopologyView.tsx:387:13",className:"h-4 w-4 mr-1"}),y?"退出编辑":"编辑"]}),e.jsx(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:389:11",variant:"outline",size:"icon",className:"h-9 w-9 border-slate-700 text-slate-400",onClick:K,disabled:z,children:z?e.jsx($e,{"code-path":"src/components/kubernetes/TopologyView.tsx:390:24",className:"h-4 w-4 animate-spin"}):e.jsx(cs,{"code-path":"src/components/kubernetes/TopologyView.tsx:390:71",className:"h-4 w-4"})})]})]}),y&&e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:397:9",className:"flex items-center gap-2 p-3 rounded-lg bg-slate-800/50 border border-slate-700",children:[e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:398:11",size:"sm",variant:"outline",className:"border-slate-600 text-slate-200",onClick:Ie,children:[e.jsx(rs,{"code-path":"src/components/kubernetes/TopologyView.tsx:399:13",className:"h-4 w-4 mr-1"}),"添加节点"]}),e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:401:11",size:"sm",variant:o?"default":"outline",className:o?"bg-amber-600 hover:bg-amber-700":"border-slate-600 text-slate-200",onClick:()=>{i(!o),p(null)},children:[e.jsx(Me,{"code-path":"src/components/kubernetes/TopologyView.tsx:403:13",className:"h-4 w-4 mr-1"}),o?"取消连线":"添加连线"]}),e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:405:11",className:"h-5 w-px bg-slate-600"}),e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:406:11",size:"sm",variant:"outline",className:"border-emerald-600/30 text-emerald-400 hover:bg-emerald-600/10",onClick:Ye,disabled:P,children:[e.jsx(ls,{"code-path":"src/components/kubernetes/TopologyView.tsx:407:13",className:"h-4 w-4 mr-1"}),P?"保存中...":"保存布局"]}),e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:409:11",size:"sm",variant:"outline",className:"border-red-500/30 text-red-400 hover:bg-red-500/10",onClick:ze,children:[e.jsx(is,{"code-path":"src/components/kubernetes/TopologyView.tsx:410:13",className:"h-4 w-4 mr-1"}),"重置布局"]}),e.jsx("span",{"code-path":"src/components/kubernetes/TopologyView.tsx:412:11",className:"text-xs text-slate-500 ml-auto",children:"双击节点编辑 · 点击虚线删除 · 拖拽调整位置"})]}),e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:417:7",className:"grid grid-cols-2 md:grid-cols-5 gap-4",children:[{label:"总节点数",value:l.nodes.length,icon:e.jsx(pe,{"code-path":"src/components/kubernetes/TopologyView.tsx:419:64",className:"h-5 w-5"}),color:"text-blue-400",bg:"bg-blue-500/10"},{label:"连接数",value:l.edges.length,icon:e.jsx(Me,{"code-path":"src/components/kubernetes/TopologyView.tsx:420:63",className:"h-5 w-5"}),color:"text-purple-400",bg:"bg-purple-500/10"},{label:"Service",value:fe("service"),icon:M("service"),color:"text-emerald-400",bg:"bg-emerald-500/10"},{label:"Deployment",value:fe("app"),icon:M("app"),color:"text-rose-400",bg:"bg-rose-500/10"},{label:"自定义",value:l.nodes.filter(s=>X(s.id)).length,icon:M("custom"),color:"text-amber-400",bg:"bg-amber-500/10"}].map(s=>e.jsx(oe,{"code-path":"src/components/kubernetes/TopologyView.tsx:425:11",className:"bg-slate-900 border-slate-800",children:e.jsx(ne,{"code-path":"src/components/kubernetes/TopologyView.tsx:426:13",className:"p-4",children:e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:427:15",className:"flex items-center justify-between",children:[e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:428:17",children:[e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:429:19",className:"text-sm text-slate-500",children:s.label}),e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:430:19",className:`text-2xl font-bold ${s.color}`,children:s.value})]}),e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:432:17",className:`p-3 rounded-lg ${s.bg} ${s.color}`,children:s.icon})]})})},s.label))}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:440:7",className:"flex items-center gap-3",children:[e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:441:9",className:"relative w-48",children:[e.jsx(ds,{"code-path":"src/components/kubernetes/TopologyView.tsx:442:11",className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-500"}),e.jsx(Se,{"code-path":"src/components/kubernetes/TopologyView.tsx:443:11",placeholder:"搜索节点...",value:E,onChange:s=>R(s.target.value),className:"pl-9 h-9 bg-slate-800/50 border-slate-700 text-slate-200"})]}),e.jsxs(ce,{"code-path":"src/components/kubernetes/TopologyView.tsx:445:9",value:B,onValueChange:f,children:[e.jsx(re,{"code-path":"src/components/kubernetes/TopologyView.tsx:446:11",className:"w-36 h-9 bg-slate-800/50 border-slate-700 text-slate-200",children:e.jsx(le,{"code-path":"src/components/kubernetes/TopologyView.tsx:446:95",placeholder:"节点类型"})}),e.jsxs(ie,{"code-path":"src/components/kubernetes/TopologyView.tsx:447:11",className:"bg-slate-800 border-slate-700",children:[e.jsx(q,{"code-path":"src/components/kubernetes/TopologyView.tsx:448:13",value:"all",children:"全部类型"}),Object.entries(de).map(([s,n])=>e.jsx(q,{"code-path":"src/components/kubernetes/TopologyView.tsx:449:63",value:s,children:n},s))]})]})]}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:455:7",className:"grid grid-cols-1 lg:grid-cols-4 gap-6",children:[e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:456:9",className:"lg:col-span-3",children:e.jsx(oe,{"code-path":"src/components/kubernetes/TopologyView.tsx:457:11",className:"bg-slate-900 border-slate-800",children:e.jsx(ne,{"code-path":"src/components/kubernetes/TopologyView.tsx:458:13",className:"p-4",children:e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:459:15",className:`h-[600px] overflow-auto ${o?"ring-2 ring-amber-500/30 rounded-lg":""}`,children:z?e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:461:19",className:"flex items-center justify-center h-full",children:e.jsx($e,{"code-path":"src/components/kubernetes/TopologyView.tsx:461:76",className:"h-8 w-8 animate-spin text-slate-600"})}):l.nodes.length===0?e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:463:19",className:"flex flex-col items-center justify-center h-full text-slate-600",children:[e.jsx(pe,{"code-path":"src/components/kubernetes/TopologyView.tsx:464:21",className:"h-12 w-12 mb-3 opacity-50"}),e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:465:21",className:"text-sm",children:x?"该集群暂无拓扑数据":"请选择集群查看拓扑"})]}):Qe()})})})}),e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:472:9",children:e.jsxs(oe,{"code-path":"src/components/kubernetes/TopologyView.tsx:473:11",className:"bg-slate-900 border-slate-800",children:[e.jsxs(Fe,{"code-path":"src/components/kubernetes/TopologyView.tsx:474:13",className:"pb-2",children:[e.jsx(He,{"code-path":"src/components/kubernetes/TopologyView.tsx:475:15",className:"text-base text-slate-100",children:"节点列表"}),e.jsx(Je,{"code-path":"src/components/kubernetes/TopologyView.tsx:476:15",className:"text-slate-500",children:"点击节点查看详情"})]}),e.jsx(ne,{"code-path":"src/components/kubernetes/TopologyView.tsx:478:13",children:e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:479:15",className:"space-y-2 max-h-[520px] overflow-auto",children:Z.length===0?e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:481:19",className:"text-sm text-slate-600 text-center py-8",children:"暂无节点"}):Z.map(s=>e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:484:21",className:`flex items-center gap-3 p-2 rounded-lg cursor-pointer transition-colors ${r?.id===s.id?"bg-blue-500/10 border border-blue-500/30":"hover:bg-slate-800/50"}`,onClick:()=>N(s),children:[e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:485:23",className:`p-2 rounded-lg ${ee(s.type)}`,children:M(s.type)}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:486:23",className:"flex-1 min-w-0",children:[e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:487:25",className:"text-sm font-medium text-slate-200 truncate",children:s.name}),e.jsxs("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:488:25",className:"text-xs text-slate-500",children:[de[s.type]||s.type,X(s.id)?" · 自定义":""]})]})]},s.id))})})]})})]}),e.jsx(Te,{"code-path":"src/components/kubernetes/TopologyView.tsx:500:7",open:!!r,onOpenChange:()=>N(null),children:e.jsxs(je,{"code-path":"src/components/kubernetes/TopologyView.tsx:501:9",className:"bg-slate-900 border-slate-800 max-w-lg",children:[e.jsxs(Ve,{"code-path":"src/components/kubernetes/TopologyView.tsx:502:11",children:[e.jsxs(Ne,{"code-path":"src/components/kubernetes/TopologyView.tsx:503:13",className:"text-slate-100 flex items-center gap-2",children:[e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:504:15",className:`p-2 rounded-lg ${ee(r?.type||"server")}`,children:r&&M(r.type)}),r?.name,r&&X(r.id)&&e.jsx(Ce,{"code-path":"src/components/kubernetes/TopologyView.tsx:506:65",variant:"outline",className:"border-amber-500/30 text-amber-400 text-xs",children:"自定义"})]}),e.jsxs(ve,{"code-path":"src/components/kubernetes/TopologyView.tsx:508:13",className:"text-slate-500",children:["类型: ",de[r?.type||""]||r?.type]})]}),r&&e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:511:13",className:"space-y-4",children:[Ue(r),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:513:15",children:[e.jsx("h4",{"code-path":"src/components/kubernetes/TopologyView.tsx:514:17",className:"text-sm font-medium text-slate-300 mb-2",children:"关联连接"}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:515:17",className:"space-y-2",children:[l.edges.filter(s=>s.source===r.id||s.target===r.id).map(s=>{const n=s.source===r.id,t=l.nodes.find(a=>a.id===(n?s.target:s.source));return t?e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:521:23",className:"flex items-center gap-2 p-2 rounded-lg bg-slate-800/50",children:[e.jsx("span",{"code-path":"src/components/kubernetes/TopologyView.tsx:522:25",className:"text-sm text-slate-400",children:n?"→":"←"}),e.jsx("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:523:25",className:`p-1 rounded ${ee(t.type)}`,children:M(t.type,"h-4 w-4")}),e.jsx("span",{"code-path":"src/components/kubernetes/TopologyView.tsx:524:25",className:"text-sm text-slate-300",children:t.name}),e.jsx(Ce,{"code-path":"src/components/kubernetes/TopologyView.tsx:525:25",variant:"outline",className:"ml-auto border-slate-700 text-slate-400 text-xs",children:s.label})]},s.id):null}),l.edges.filter(s=>s.source===r.id||s.target===r.id).length===0&&e.jsx("p",{"code-path":"src/components/kubernetes/TopologyView.tsx:529:127",className:"text-xs text-slate-600",children:"无关联连接"})]})]}),y&&r&&e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:534:17",className:"flex gap-2 pt-2 border-t border-slate-700",children:[e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:535:19",size:"sm",variant:"outline",className:"border-slate-600 text-slate-200",onClick:()=>ye(r),children:[e.jsx(_e,{"code-path":"src/components/kubernetes/TopologyView.tsx:536:21",className:"h-3.5 w-3.5 mr-1"}),"编辑"]}),X(r.id)&&e.jsxs(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:539:21",size:"sm",variant:"outline",className:"border-red-500/30 text-red-400 hover:bg-red-500/10",onClick:()=>Pe(r),children:[e.jsx(ps,{"code-path":"src/components/kubernetes/TopologyView.tsx:540:23",className:"h-3.5 w-3.5 mr-1"}),"删除"]})]})]})]})}),e.jsx(Te,{"code-path":"src/components/kubernetes/TopologyView.tsx:551:7",open:De,onOpenChange:Q,children:e.jsxs(je,{"code-path":"src/components/kubernetes/TopologyView.tsx:552:9",className:"bg-slate-900 border-slate-800 max-w-md",children:[e.jsxs(Ve,{"code-path":"src/components/kubernetes/TopologyView.tsx:553:11",children:[e.jsx(Ne,{"code-path":"src/components/kubernetes/TopologyView.tsx:554:13",className:"text-slate-100",children:U?"编辑节点":"添加自定义节点"}),e.jsx(ve,{"code-path":"src/components/kubernetes/TopologyView.tsx:555:13",className:"text-slate-500",children:U?"修改节点属性":"添加数据库、外部服务等非 Kubernetes 资源节点"})]}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:557:11",className:"space-y-4",children:[e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:558:13",className:"space-y-2",children:[e.jsx(ae,{"code-path":"src/components/kubernetes/TopologyView.tsx:559:15",className:"text-slate-300",children:"名称"}),e.jsx(Se,{"code-path":"src/components/kubernetes/TopologyView.tsx:560:15",value:w.name,onChange:s=>F({...w,name:s.target.value}),placeholder:"如 MySQL 主库、Redis 集群",className:"bg-slate-800/50 border-slate-700 text-slate-200"})]}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:563:13",className:"space-y-2",children:[e.jsx(ae,{"code-path":"src/components/kubernetes/TopologyView.tsx:564:15",className:"text-slate-300",children:"类型"}),e.jsxs(ce,{"code-path":"src/components/kubernetes/TopologyView.tsx:565:15",value:w.type,onValueChange:s=>F({...w,type:s}),children:[e.jsx(re,{"code-path":"src/components/kubernetes/TopologyView.tsx:566:17",className:"bg-slate-800/50 border-slate-700 text-slate-200",children:e.jsx(le,{"code-path":"src/components/kubernetes/TopologyView.tsx:566:92"})}),e.jsx(ie,{"code-path":"src/components/kubernetes/TopologyView.tsx:567:17",className:"bg-slate-800 border-slate-700",children:ms.map(s=>e.jsxs(q,{"code-path":"src/components/kubernetes/TopologyView.tsx:568:49",value:s.value,children:[s.label," — ",s.desc]},s.value))})]})]}),e.jsxs("div",{"code-path":"src/components/kubernetes/TopologyView.tsx:572:13",className:"space-y-2",children:[e.jsx(ae,{"code-path":"src/components/kubernetes/TopologyView.tsx:573:15",className:"text-slate-300",children:"备注"}),e.jsx(qe,{"code-path":"src/components/kubernetes/TopologyView.tsx:574:15",value:w.note,onChange:s=>F({...w,note:s.target.value}),placeholder:"连接信息、用途说明等",rows:2,className:"bg-slate-800/50 border-slate-700 text-slate-200 resize-none"})]})]}),e.jsxs(Ze,{"code-path":"src/components/kubernetes/TopologyView.tsx:578:11",children:[e.jsx(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:579:13",variant:"outline",className:"border-slate-700 text-slate-300",onClick:()=>Q(!1),children:"取消"}),e.jsx(v,{"code-path":"src/components/kubernetes/TopologyView.tsx:580:13",onClick:Oe,children:U?"保存":"添加"})]})]})})]})}export{Ns as TopologyView};
|