Files
YG_FT/frontend/dist/assets/ComputeNodesView-CF2EhAu2.js
2026-07-24 21:11:06 +08:00

2 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{E as xe,a as Ee}from"./el-form-item-rY4vNiXx.js";import{E as $e}from"./index-DYpWD2QI.js";import{E as Ue}from"./index-Cp3It01C.js";import{E as je}from"./el-tag-BhOuL4lf.js";import{E as Be,a as Ge}from"./el-select-C8XVvVg6.js";import{E as Pe}from"./el-dialog-CGSDUoRt.js";import{E as De}from"./el-input-number-12Fb-t8x.js";import{E as Le}from"./el-progress-qjLucY-4.js";import{E as ze}from"./el-space-Crx-QUvu.js";import{E as Re}from"./el-switch-CRgLvWkS.js";import{a as Se,E as Te}from"./el-table-Cp5xAgqT.js";import{a as Fe,E as qe}from"./el-tab-pane-CPYE4n_6.js";import{v as Ie}from"./directive-BVaYA311.js";import{aF as U,aG as j,aH as Ae,d as Me,y as p,D as Je,G as Oe,ah as Ke,K as He,c as C,q as i,aa as u,g as F,s as l,w as a,ac as Qe,j as q,o as f,x as r,f as b,M as ee,ad as te,e as I,z as We,A as h,v as Xe}from"./index-DMfSG-9l.js";import"./el-scrollbar-B3-sB_hq.js";import"./el-popper-DAm2mVaB.js";import"./el-tooltip-l0sNRNKZ.js";import"./el-checkbox-U4Gmy-zV.js";import{s as E,a as $}from"./status-Dl1fykxa.js";import{_ as Ye}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./castArray-qEIBurnE.js";import"./_baseClone-DE0sfIfI.js";import"./raf-Cz9mkNBb.js";import"./index-D3hDDBfW.js";import"./index-BqlQpMip.js";import"./index-CJA4tZk1.js";import"./vnode-DQ45xHFU.js";import"./index-YDvJ5KV2.js";import"./scroll-D2ojO4wB.js";import"./clamp-B9tkuT1F.js";import"./toNumber-COrtsVXo.js";import"./_baseIteratee-bMWfS5oT.js";import"./index-h-ZEyEHT.js";import"./use-dialog-CRHE-RMe.js";import"./index-DHvxCawT.js";import"./index-y5Ln8gqh.js";import"./validator-WVQr2HNG.js";import"./debounce-CVrTo2Ot.js";import"./omit-teeY8va1.js";const Ze=()=>U("/compute/nodes"),et=m=>j("/compute/nodes",m),tt=(m,w)=>Ae(`/compute/nodes/${m}`,w),lt=m=>j(`/compute/nodes/${m}/test-connection`),at=m=>j(`/compute/nodes/${m}/enable`),ot=m=>j(`/compute/nodes/${m}/disable`),st=m=>j(`/compute/nodes/${m}/drain`),nt=()=>U("/compute/gpus"),ut=()=>U("/compute/queue"),it=m=>U(`/compute/nodes/${m}/replicas`),dt=m=>U(`/compute/nodes/${m}/replicas/drift`),rt=(m,w)=>j(`/compute/nodes/${m}/replicas/repair`,w!=null&&w.length?{replica_ids:w}:{}),mt=m=>U(`/compute/sync-jobs/${m}`),pt={class:"compute-page"},_t={class:"compute-header"},ct={class:"header-actions"},ft={key:0,class:"last-updated"},gt={class:"summary-grid"},bt={class:"summary-tile"},vt={class:"summary-tile"},yt={class:"summary-tile"},ht={class:"summary-tile"},wt={class:"mono"},Vt={class:"muted mono"},Ct={class:"muted"},kt={class:"muted"},Nt={key:0,class:"muted"},xt={class:"muted"},Et={class:"replica-toolbar"},$t={key:0,class:"muted"},Ut={key:0,class:"sync-progress"},jt={class:"node-form-grid"},Bt=Me({__name:"ComputeNodesView",setup(m){const w=Qe(),ne=Xe(),A=p(String(w.query.tab||"nodes")),M=p(!0),J=p(!1),O=p(!1),K=p(!1),k=p([]),D=p([]),H=p([]),N=p([]),v=p(null),g=p(""),Q=p(""),x=p(!1),B=p("create"),W=p(!1),s=We({id:"",code:"",name:"",api_base_url:"",file_gateway_url:"",enabled:!0,scheduler_status:"offline",scheduler_weight:100,tags_text:"",max_parallel_jobs:1,data_root:"/data/yg-ft",model_root:"/data/yg-ft/models",log_root:"/opt/yg-ft/logs/training",description:""});let X=null,Y=!1;const le=q(()=>k.value.find(o=>o.id===g.value)),ue=q(()=>k.value.filter(o=>o.enabled).length),ie=q(()=>D.value.filter(o=>o.status==="busy"||o.status==="reserved").length),de=q(()=>k.value.reduce((o,e)=>o+e.current_running_jobs,0));function Gt(o){return o}Je(()=>w.query.tab,o=>{A.value=String(o||"nodes")});async function G(o={}){if(!Y){Y=!0,o.showLoading&&(M.value=!0),o.showButtonLoading&&(J.value=!0);try{const[e,d,n]=await Promise.all([Ze(),nt(),ut()]);k.value=e,D.value=d,H.value=n,(!g.value||!e.some(y=>y.id===g.value))&&e.length&&(g.value=e[0].id),await re(),await L(),Q.value=new Date().toLocaleTimeString("zh-CN",{hour12:!1})}finally{o.showLoading&&(M.value=!1),o.showButtonLoading&&(J.value=!1),Y=!1}}}async function re(){var o;if((o=v.value)!=null&&o.id)try{const e=await mt(v.value.id);v.value=e,["completed","failed","stopped","cancelled"].includes(e.status)&&await L()}catch{v.value=null}}async function L(){if(!g.value){N.value=[];return}N.value=await it(g.value)}async function me(o){await ne.replace({path:"/compute",query:{tab:String(o)}})}async function z(o,e){const d=String(e.id);if(o==="enable"&&await at(d),o==="disable"&&await ot(d),o==="drain"&&await st(d),o==="test"){const n=await lt(d);n.success?h.success(`连接成功,发现 ${n.gpu_count} 张 GPU延迟 ${n.latency_ms}ms`):h.error(n.error||"连接失败")}await G()}async function pe(){if(g.value){O.value=!0;try{const o=await dt(g.value);N.value=o.items||[],h.success(o.drifted?`检测完成,发现 ${o.drifted} 个异常副本`:"检测完成,副本状态正常")}finally{O.value=!1}}}async function _e(){var e;if(!g.value)return;const o=N.value.filter(d=>["drifted","failed","repair_pending"].includes(d.sync_status));if(!o.length){h.info("暂无需要修复的副本");return}K.value=!0;try{const d=await rt(g.value,o.map(n=>n.id));v.value=d.sync,N.value=d.replicas||[],d.async?h.success("副本修复任务已提交,页面将自动刷新进度"):(e=d.failed)!=null&&e.length?h.warning(`修复完成,失败 ${d.failed.length}`):h.success("副本修复完成"),await L()}finally{K.value=!1}}function ce(){Object.assign(s,{id:"",code:"",name:"",api_base_url:"",file_gateway_url:"",enabled:!0,scheduler_status:"offline",scheduler_weight:100,tags_text:"",max_parallel_jobs:1,data_root:"/data/yg-ft",model_root:"/data/yg-ft/models",log_root:"/opt/yg-ft/logs/training",description:""})}function fe(){ce(),B.value="create",x.value=!0}function ge(o){var e;Object.assign(s,{id:o.id,code:o.code,name:o.name,api_base_url:o.api_base_url,file_gateway_url:o.file_gateway_url,enabled:o.enabled,scheduler_status:o.scheduler_status,scheduler_weight:o.scheduler_weight,tags_text:((e=o.tags)==null?void 0:e.join(", "))||"",max_parallel_jobs:o.max_parallel_jobs,data_root:o.data_root,model_root:o.model_root,log_root:o.log_root,description:o.description||""}),B.value="edit",x.value=!0}function be(){const o=s.tags_text.replace(//g,",").split(",").map(e=>e.trim()).filter(Boolean);return{code:s.code.trim(),name:s.name.trim()||s.code.trim(),api_base_url:s.api_base_url.trim().replace(/\/$/,""),file_gateway_url:(s.file_gateway_url||s.api_base_url).trim().replace(/\/$/,""),enabled:s.enabled,scheduler_status:s.scheduler_status,scheduler_weight:Number(s.scheduler_weight)||0,tags:o,max_parallel_jobs:Number(s.max_parallel_jobs)||1,data_root:s.data_root.trim()||"/data/yg-ft",model_root:s.model_root.trim()||"/data/yg-ft/models",log_root:s.log_root.trim()||"/opt/yg-ft/logs/training",description:s.description.trim()}}async function ve(){const o=be();if(!o.code||!o.api_base_url){h.warning("请填写节点编码和 Compute API 地址");return}W.value=!0;try{B.value==="create"?(await et(o),h.success("节点已创建")):(await tt(s.id,o),h.success("节点配置已更新")),x.value=!1,await G()}finally{W.value=!1}}function ye(o){const e=Number(o||0);return e?e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/1024/1024).toFixed(1)} MB`:`${(e/1024/1024/1024).toFixed(2)} GB`:"-"}function ae(o){return o?new Date(o).toLocaleString("zh-CN"):"-"}return Oe(()=>{G({showLoading:!0}),X=setInterval(()=>G(),5e3)}),Ke(()=>{X&&clearInterval(X)}),(o,e)=>{const d=Ue,n=Te,y=je,he=ze,R=Se,S=qe,T=Le,P=Ge,oe=Be,we=Fe,V=$e,_=Ee,se=De,Ve=Re,Ce=xe,ke=Pe,Ne=Ie;return He((f(),C("section",pt,[i("header",_t,[e[20]||(e[20]=i("div",null,[i("h1",null,"算力节点"),i("p",null,"维护训练算力节点、GPU 状态、任务队列和模型/数据集本地副本。")],-1)),i("div",ct,[Q.value?(f(),C("span",ft,"更新 "+u(Q.value),1)):F("",!0),l(d,{type:"primary",onClick:fe},{default:a(()=>[...e[18]||(e[18]=[r("新增节点",-1)])]),_:1}),l(d,{loading:J.value,onClick:e[0]||(e[0]=t=>G({showButtonLoading:!0}))},{default:a(()=>[...e[19]||(e[19]=[r("刷新",-1)])]),_:1},8,["loading"])])]),i("div",gt,[i("div",bt,[e[21]||(e[21]=i("span",null,"启用节点",-1)),i("strong",null,u(ue.value)+" / "+u(k.value.length),1)]),i("div",vt,[e[22]||(e[22]=i("span",null,"GPU 占用",-1)),i("strong",null,u(ie.value)+" / "+u(D.value.length),1)]),i("div",yt,[e[23]||(e[23]=i("span",null,"运行任务",-1)),i("strong",null,u(de.value),1)]),i("div",ht,[e[24]||(e[24]=i("span",null,"队列任务",-1)),i("strong",null,u(H.value.length),1)])]),l(we,{modelValue:A.value,"onUpdate:modelValue":e[2]||(e[2]=t=>A.value=t),class:"compute-tabs",onTabChange:me},{default:a(()=>[l(S,{label:"节点",name:"nodes"},{default:a(()=>[l(R,{data:k.value,height:"100%"},{default:a(()=>[l(n,{prop:"code",label:"节点编码","min-width":"150"}),l(n,{prop:"name",label:"节点名称","min-width":"150"}),l(n,{label:"状态",width:"120"},{default:a(({row:t})=>[l(y,{type:b(E)(t.scheduler_status)},{default:a(()=>[r(u(b($)(t.scheduler_status)),1)]),_:2},1032,["type"])]),_:1}),l(n,{label:"启用",width:"90"},{default:a(({row:t})=>[l(y,{type:t.enabled?"success":"info"},{default:a(()=>[r(u(t.enabled?"启用":"停用"),1)]),_:2},1032,["type"])]),_:1}),l(n,{prop:"scheduler_weight",label:"权重",width:"90"}),l(n,{label:"标签","min-width":"220"},{default:a(({row:t})=>[l(he,{wrap:""},{default:a(()=>[(f(!0),C(ee,null,te(t.tags,c=>(f(),I(y,{key:c,effect:"plain"},{default:a(()=>[r(u(c),1)]),_:2},1024))),128))]),_:2},1024)]),_:1}),l(n,{label:"任务/GPU",width:"120"},{default:a(({row:t})=>[r(u(t.current_running_jobs)+" / "+u(t.gpu_count),1)]),_:1}),l(n,{label:"服务地址","min-width":"260"},{default:a(({row:t})=>[i("div",wt,u(t.api_base_url),1),i("div",Vt,u(t.file_gateway_url),1)]),_:1}),l(n,{label:"操作",width:"330",fixed:"right"},{default:a(({row:t})=>[l(d,{size:"small",onClick:c=>ge(t)},{default:a(()=>[...e[25]||(e[25]=[r("编辑",-1)])]),_:1},8,["onClick"]),l(d,{size:"small",onClick:c=>z("test",t)},{default:a(()=>[...e[26]||(e[26]=[r("测试",-1)])]),_:1},8,["onClick"]),t.enabled?(f(),I(d,{key:0,size:"small",onClick:c=>z("disable",t)},{default:a(()=>[...e[27]||(e[27]=[r("停用",-1)])]),_:1},8,["onClick"])):(f(),I(d,{key:1,size:"small",type:"primary",onClick:c=>z("enable",t)},{default:a(()=>[...e[28]||(e[28]=[r("启用",-1)])]),_:1},8,["onClick"])),l(d,{size:"small",type:"warning",plain:"",onClick:c=>z("drain",t)},{default:a(()=>[...e[29]||(e[29]=[r("维护",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])]),_:1}),l(S,{label:"GPU",name:"gpus"},{default:a(()=>[l(R,{data:D.value,height:"100%"},{default:a(()=>[l(n,{label:"GPU","min-width":"220"},{default:a(({row:t})=>[i("strong",null,u(t.node_code)+" / GPU "+u(t.id),1),i("div",Ct,u(t.name),1)]),_:1}),l(n,{label:"状态",width:"100"},{default:a(({row:t})=>[l(y,{type:b(E)(t.status)},{default:a(()=>[r(u(b($)(t.status)),1)]),_:2},1032,["type"])]),_:1}),l(n,{label:"利用率","min-width":"180"},{default:a(({row:t})=>[l(T,{percentage:t.gpu_percent,"stroke-width":8},null,8,["percentage"])]),_:1}),l(n,{label:"显存","min-width":"190"},{default:a(({row:t})=>[l(T,{percentage:Math.round(t.memory_percent),"stroke-width":8},null,8,["percentage"]),i("span",kt,u(t.memory_used_gb)+" / "+u(t.memory_total_gb)+" GB",1)]),_:1}),l(n,{label:"温度/功耗",width:"150"},{default:a(({row:t})=>[r(u(t.temperature)+" C / "+u(t.power_w)+" W",1)]),_:1}),l(n,{label:"进程","min-width":"220"},{default:a(({row:t})=>{var c;return[(c=t.processes)!=null&&c.length?F("",!0):(f(),C("span",Nt,"空闲")),(f(!0),C(ee,null,te(t.processes,Z=>(f(),C("div",{key:Z.pid},[r(u(Z.task_name)+" ",1),i("span",xt,"PID "+u(Z.pid),1)]))),128))]}),_:1})]),_:1},8,["data"])]),_:1}),l(S,{label:"队列",name:"queue"},{default:a(()=>[l(R,{data:H.value,height:"100%"},{default:a(()=>[l(n,{prop:"name",label:"任务名称","min-width":"200"}),l(n,{label:"状态",width:"110"},{default:a(({row:t})=>[l(y,{type:b(E)(t.status)},{default:a(()=>[r(u(b($)(t.status)),1)]),_:2},1032,["type"])]),_:1}),l(n,{label:"进度","min-width":"220"},{default:a(({row:t})=>[l(T,{percentage:t.progress,"stroke-width":8},null,8,["percentage"])]),_:1}),l(n,{prop:"compute_node_id",label:"节点",width:"140"}),l(n,{label:"GPU",width:"120"},{default:a(({row:t})=>{var c;return[r(u(((c=t.gpus)==null?void 0:c.join(", "))||"-"),1)]}),_:1}),l(n,{label:"创建时间",width:"190"},{default:a(({row:t})=>[r(u(ae(t.create_time)),1)]),_:1})]),_:1},8,["data"])]),_:1}),l(S,{label:"资源副本",name:"replicas"},{default:a(()=>[i("div",Et,[l(oe,{modelValue:g.value,"onUpdate:modelValue":e[1]||(e[1]=t=>g.value=t),filterable:"",onChange:L},{default:a(()=>[(f(!0),C(ee,null,te(k.value,t=>(f(),I(P,{key:t.id,label:`${t.code} - ${t.name}`,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"]),le.value?(f(),C("span",$t,"当前节点 "+u(le.value.api_base_url),1)):F("",!0),l(d,{loading:O.value,onClick:pe},{default:a(()=>[...e[30]||(e[30]=[r("漂移检测",-1)])]),_:1},8,["loading"]),l(d,{type:"primary",loading:K.value,onClick:_e},{default:a(()=>[...e[31]||(e[31]=[r("修复副本",-1)])]),_:1},8,["loading"])]),v.value?(f(),C("div",Ut,[i("div",null,[i("strong",null,"同步任务 "+u(v.value.id),1),l(y,{type:b(E)(v.value.status),size:"small"},{default:a(()=>[r(u(b($)(v.value.status)),1)]),_:1},8,["type"])]),l(T,{percentage:Number(v.value.progress||0),"stroke-width":8},null,8,["percentage"])])):F("",!0),l(R,{data:N.value,height:"100%"},{default:a(()=>[l(n,{prop:"resource_type",label:"资源类型",width:"110"}),l(n,{prop:"resource_id",label:"资源 ID","min-width":"180"}),l(n,{prop:"local_path",label:"本地路径","min-width":"300","show-overflow-tooltip":""}),l(n,{label:"状态",width:"110"},{default:a(({row:t})=>[l(y,{type:b(E)(t.status),size:"small"},{default:a(()=>[r(u(b($)(t.status)),1)]),_:2},1032,["type"])]),_:1}),l(n,{label:"同步状态",width:"120"},{default:a(({row:t})=>[l(y,{type:b(E)(t.sync_status),size:"small"},{default:a(()=>[r(u(b($)(t.sync_status)),1)]),_:2},1032,["type"])]),_:1}),l(n,{label:"大小",width:"110"},{default:a(({row:t})=>[r(u(ye(t.byte_size)),1)]),_:1}),l(n,{label:"最后检测",width:"190"},{default:a(({row:t})=>[r(u(ae(t.last_checked_at)),1)]),_:1})]),_:1},8,["data"])]),_:1})]),_:1},8,["modelValue"]),l(ke,{modelValue:x.value,"onUpdate:modelValue":e[17]||(e[17]=t=>x.value=t),title:B.value==="create"?"新增算力节点":"编辑算力节点",width:"720px"},{footer:a(()=>[l(d,{onClick:e[16]||(e[16]=t=>x.value=!1)},{default:a(()=>[...e[32]||(e[32]=[r("取消",-1)])]),_:1}),l(d,{type:"primary",loading:W.value,onClick:ve},{default:a(()=>[...e[33]||(e[33]=[r("保存",-1)])]),_:1},8,["loading"])]),default:a(()=>[l(Ce,{"label-width":"130px"},{default:a(()=>[i("div",jt,[l(_,{label:"节点编码",required:""},{default:a(()=>[l(V,{modelValue:s.code,"onUpdate:modelValue":e[3]||(e[3]=t=>s.code=t),disabled:B.value==="edit",placeholder:"gpu-node-01"},null,8,["modelValue","disabled"])]),_:1}),l(_,{label:"节点名称"},{default:a(()=>[l(V,{modelValue:s.name,"onUpdate:modelValue":e[4]||(e[4]=t=>s.name=t),placeholder:"A800 训练节点 01"},null,8,["modelValue"])]),_:1}),l(_,{label:"Compute API",required:""},{default:a(()=>[l(V,{modelValue:s.api_base_url,"onUpdate:modelValue":e[5]||(e[5]=t=>s.api_base_url=t),placeholder:"http://10.0.0.11:19100"},null,8,["modelValue"])]),_:1}),l(_,{label:"File Gateway"},{default:a(()=>[l(V,{modelValue:s.file_gateway_url,"onUpdate:modelValue":e[6]||(e[6]=t=>s.file_gateway_url=t),placeholder:"http://10.0.0.11:19101"},null,8,["modelValue"])]),_:1}),l(_,{label:"调度权重"},{default:a(()=>[l(se,{modelValue:s.scheduler_weight,"onUpdate:modelValue":e[7]||(e[7]=t=>s.scheduler_weight=t),min:0,max:1e3,"controls-position":"right"},null,8,["modelValue"])]),_:1}),l(_,{label:"最大并行任务"},{default:a(()=>[l(se,{modelValue:s.max_parallel_jobs,"onUpdate:modelValue":e[8]||(e[8]=t=>s.max_parallel_jobs=t),min:1,max:32,"controls-position":"right"},null,8,["modelValue"])]),_:1}),l(_,{label:"启用状态"},{default:a(()=>[l(Ve,{modelValue:s.enabled,"onUpdate:modelValue":e[9]||(e[9]=t=>s.enabled=t),"active-text":"启用","inactive-text":"停用"},null,8,["modelValue"])]),_:1}),l(_,{label:"调度状态"},{default:a(()=>[l(oe,{modelValue:s.scheduler_status,"onUpdate:modelValue":e[10]||(e[10]=t=>s.scheduler_status=t)},{default:a(()=>[l(P,{label:"离线",value:"offline"}),l(P,{label:"在线",value:"online"}),l(P,{label:"维护中",value:"draining"}),l(P,{label:"维护模式",value:"maintenance"})]),_:1},8,["modelValue"])]),_:1})]),l(_,{label:"标签"},{default:a(()=>[l(V,{modelValue:s.tags_text,"onUpdate:modelValue":e[11]||(e[11]=t=>s.tags_text=t),placeholder:"a800, lora, beijing"},null,8,["modelValue"])]),_:1}),l(_,{label:"数据根目录"},{default:a(()=>[l(V,{modelValue:s.data_root,"onUpdate:modelValue":e[12]||(e[12]=t=>s.data_root=t)},null,8,["modelValue"])]),_:1}),l(_,{label:"模型根目录"},{default:a(()=>[l(V,{modelValue:s.model_root,"onUpdate:modelValue":e[13]||(e[13]=t=>s.model_root=t)},null,8,["modelValue"])]),_:1}),l(_,{label:"训练日志目录"},{default:a(()=>[l(V,{modelValue:s.log_root,"onUpdate:modelValue":e[14]||(e[14]=t=>s.log_root=t)},null,8,["modelValue"])]),_:1}),l(_,{label:"备注"},{default:a(()=>[l(V,{modelValue:s.description,"onUpdate:modelValue":e[15]||(e[15]=t=>s.description=t),type:"textarea",rows:3},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue","title"])])),[[Ne,M.value]])}}}),vl=Ye(Bt,[["__scopeId","data-v-569994b3"]]);export{vl as default};