Files
lan-manager/server/static/assets/MachineDetail-CV5DfGMb.js
openclaw dbeaeda083 fix(pve): 修复review反馈 — body二次读取、URL编码、前端并行检测、错误态、emoji风格
后端修复(缅因猫 review):
- server/services/pve.go: Login 使用 url.Values 编码 form data,修复密码含特殊字符导致认证失败
- server/services/pve.go: GetVMStatus 先 io.ReadAll 再 json.Unmarshal,修复 decode 错误时 body 为空的问题

前端修复(暹罗猫 UI review + 布偶猫实现):
- PVEHosts.vue: 节点状态检测改为 Promise.all 并行,避免 N 个节点串行 RTT
- PVEHosts.vue: VM 弹窗增加错误态提示(el-alert),失败时不再只 Toast 报错
- MachineDetail.vue: VM 状态标签去掉 emoji,改用纯文字 + el-tag 语义色
- MachineDetail.vue: VM 状态 API 失败时标记 _error 态,显示「VM检测失败」而非「检测中」

[宪宪/K2.6🐾]
2026-04-21 02:17:09 +08:00

2 lines
26 KiB
JavaScript

import{k as Ne,I as qe,J as Fe,K as Le,W as Ke,X as Oe,o as i,c as d,a as l,b as s,w as n,h as c,t as u,p as ce,e as _,n as m,m as C,Y as Ae,Z as Ge,_ as se,$ as ae,S as X,N as U,O as T,a0 as We,M as fe,a1 as je,r as h,d as S,G as Ye,u as Je,L as Qe,Q as Xe,a2 as Ze,a3 as et,a4 as tt,a5 as lt,a6 as st,a7 as ye,a8 as he,a9 as A,aa as at,E as P,ab as Ve,ac as ge,q as ot,ad as nt,T as it,ae as ut,af as dt,ag as rt,ah as vt,ai as mt,aj as _t,ak as pt}from"./index-D__NZX4I.js";import{_ as ct}from"./_plugin-vue_export-helper-DlAUqK2U.js";const ft={key:0,class:"page"},yt={class:"detail-header"},ht={class:"header-left"},Vt={class:"host-title"},gt={class:"host-subtitle"},kt={key:0},bt={key:1},wt={key:0,class:"header-actions"},Mt={class:"detail-grid"},xt={class:"card"},St={class:"info-list"},$t={class:"info-item"},Ct={class:"info-value"},Ut={key:0,class:"info-item"},Pt={class:"info-value"},Dt={class:"info-item"},Tt={class:"info-value"},Et={key:1,class:"info-item"},Ht={class:"info-value"},It={key:2,class:"info-item"},Rt={class:"info-value text-muted"},zt={key:0,class:"card"},Bt={class:"vm-status-grid"},Nt={class:"vm-stat-item"},qt={key:0,class:"vm-stat-item"},Ft={class:"vm-stat-value"},Lt={key:1,class:"vm-stat-item"},Kt={class:"vm-stat-value"},Ot={key:2,class:"vm-stat-item"},At={class:"vm-stat-value"},Gt={key:1,class:"card"},Wt={class:"status-pills"},jt={key:0,class:"status-pill"},Yt={class:"sp-info"},Jt={class:"sp-title"},Qt={class:"sp-bar"},Xt={class:"sp-num"},Zt={key:1,class:"status-pill"},el={class:"sp-info"},tl={class:"sp-title"},ll={class:"sp-bar"},sl={class:"sp-num"},al={key:2,class:"status-pill disk-multi"},ol={class:"sp-info"},nl={class:"sp-title"},il={class:"sp-bar"},ul={class:"sp-num"},dl={class:"sp-info multi-disk-info"},rl={class:"dd-mount"},vl={class:"dd-bar-wrap"},ml={class:"dd-bar"},_l={class:"dd-val"},pl={class:"dd-pct"},cl={key:0,class:"uptime-line"},fl={key:2,class:"card"},yl={key:0,class:"sync-actions"},hl={class:"ssh-actions"},Vl={key:1,class:"ssh-result"},gl={class:"result-grid"},kl={class:"result-item"},bl={class:"rv"},wl={class:"result-item"},Ml={class:"rv"},xl={class:"result-item"},Sl={class:"rv"},$l={class:"result-item"},Cl={class:"rv"},Ul={class:"result-item"},Pl={class:"rv"},Dl={class:"result-item"},Tl={class:"rv"},El={class:"result-item full"},Hl={class:"rv"},Il={class:"card"},Rl={class:"card-title"},zl={key:0,class:"service-list"},Bl={class:"service-main"},Nl={class:"service-name"},ql={class:"service-port"},Fl={key:0,class:"service-target"},Ll={key:0,class:"target-note"},Kl={key:1,class:"service-note"},Ol={key:2,class:"service-actions"},Al={key:3,class:"card"},Gl={class:"offline-stats"},Wl={class:"stat-box"},jl={class:"stat-num"},Yl={class:"stat-box"},Jl={class:"stat-num"},Ql={key:0,class:"stat-box"},Xl={class:"stat-reason"},Zl={key:0,class:"offline-logs"},es={class:"log-time"},ts={class:"log-reason"},ls={key:0,class:"log-dur"},ss={key:1,class:"log-dur pending"},as={key:4,class:"card"},os={class:"card-title"},ns={key:0,class:"rel-list"},is={class:"rel-arrow"},us={class:"rel-host"},ds={class:"rel-host"},rs={class:"rel-meta"},vs={key:0,class:"rel-port"},ms={key:1,class:"rel-note"},_s={class:"rel-actions"},ps={__name:"MachineDetail",setup(cs){const ke=je(),be=Je(),k=Ye().is_admin,V=ke.params.id,o=h(null),Z=h([]),ee=h([]),z=h(!1),f=h({}),B=h([]),te=h([]),oe=h([]),q=h(!1),p=h({}),F=h(!1),E=h({username:"",password:""}),M=h(null),N=h(!1),L=h(!1),b=h({}),K=h(!1),w=h({}),we=ot(()=>{const a={};return B.value.forEach(e=>a[e.id]=e.hostname),a});let le=null;Ne(async()=>{if(await H(),await G(),k){await W();const e=await Qe();B.value=e.data;try{const r=await Xe();oe.value=r.data}catch{}await j()}await qe();const a=Fe||1e4;a>0&&(le=setInterval(async()=>{await H(),await G(),k&&(await W(),await j())},a))}),Le(()=>{le&&clearInterval(le)});async function H(){const a=await Ke(V);if(o.value=a.data.machine,k){const e=await Ze(V);te.value=e.data}o.value&&(o.value.cpu_info||o.value.memory_info||o.value.disk_info||o.value.uptime)?M.value={hostname:o.value.hostname,os_version:o.value.os_version,cpu:o.value.cpu_info,memory:o.value.memory_info,disk:o.value.disk_info,uptime:o.value.uptime,listen_ports:o.value.listen_ports?o.value.listen_ports.split(",").map(e=>e.trim()).filter(Boolean):[]}:M.value=null}async function G(){const a=await Oe(V);Z.value=a.data}async function W(){const a=await et(),e={};B.value.forEach(r=>e[r.id]=r.hostname),ee.value=a.data.filter(r=>r.source_machine_id==V||r.target_machine_id==V).map(r=>({...r,source_hostname:e[r.source_machine_id]||r.source_machine_id,target_hostname:e[r.target_machine_id]||r.target_machine_id}))}function Me(a){p.value={...a,ssh_port:a.ssh_port||22,ssh_username:a.ssh_username||"",ssh_password:"",pve_host_id:a.pve_host_id||null,pve_vmid:a.pve_vmid||""},q.value=!0}async function xe(){if(o.value.ssh_username){N.value=!0;try{const a=await Ve(V,{username:o.value.ssh_username,password:""});M.value=a.data;const e={...M.value};delete e.hostname,await ge(V,e),P.success("获取并同步成功"),await H(),N.value=!1;return}catch{N.value=!1}}E.value={username:o.value.ssh_username||"",password:""},F.value=!0}async function Se(){await it(p.value.id,p.value),P.success("保存成功"),q.value=!1,H()}async function j(){if(!(!o.value||!o.value.pve_host_id||!o.value.pve_vmid))try{const a=await tt(V);f.value=a.data}catch{f.value={_error:!0}}}async function $e(){try{await A.confirm("确定要启动虚拟机吗?","确认启动",{type:"info"}),z.value=!0,await mt(V),P.success("虚拟机已启动"),await j(),H()}catch{}z.value=!1}async function Ce(){try{await A.confirm("确定要关闭虚拟机吗?","确认关闭",{type:"warning"}),z.value=!0,await _t(V),P.success("虚拟机已关闭"),await j(),H()}catch{}z.value=!1}async function Ue(){try{await A.confirm("确定删除该机器?","提示",{type:"warning"}),await at(V),P.success("删除成功"),be.back()}catch{}}async function Pe(){N.value=!0;try{const a=await Ve(V,E.value);M.value=a.data,F.value=!1;const e={...M.value};delete e.hostname,await ge(V,e),P.success("获取并同步成功"),await H()}catch{}N.value=!1}function ne(a){b.value=a?{...a,target_machine_id:a.target_machine_id||null,target_notes:a.target_notes||""}:{name:"",port:80,protocol:"TCP",notes:"",target_machine_id:null,target_notes:""},L.value=!0}async function De(){const a={...b.value};a.id?await ut(a.id,a):await dt(V,a),P.success("保存成功"),L.value=!1,G()}async function Te(a){try{await A.confirm("确定删除该服务?","提示",{type:"warning"}),await pt(a.id),P.success("删除成功"),G()}catch{}}function ie(a){w.value=a?{...a}:{source_machine_id:Number(V),target_machine_id:null,relation_type:"dependency",source_port:null,target_port:null,notes:""},K.value=!0}async function Ee(){const a={...w.value};a.id?await rt(a.id,a):await vt(a),P.success("保存成功"),K.value=!1,W()}async function He(a){try{await A.confirm("确定删除该关系?","提示",{type:"warning"}),await nt(a.id),P.success("删除成功"),W()}catch{}}function Ie(a){return{port_forward:"端口转发",dependency:"依赖",primary_secondary:"主从",custom:"自定义"}[a]||a}function D(a){if(!a)return 0;const e=a.match(/\((\d+)%\)/)||a.match(/(\d+(?:\.\d+)?)%/);if(e){const r=parseFloat(e[1]);return isNaN(r)?0:Math.min(100,Math.max(0,Math.round(r)))}return 0}function Re(a){return a>=90?"#f87171":a>=70?"#fbbf24":"#34d399"}function ue(a){return a>=90?"#f87171":a>=80?"#fbbf24":"#60a5fa"}function de(a){if(!a)return[];const e=[],r=/(\S+)\s+([\d\.]+[KMGT]?\/[\d\.]+[KMGT]?)\s+\((\d+)%\)/g;let v;for(;(v=r.exec(a))!==null;)e.push({mount:v[1],detail:v[2],percent:parseInt(v[3],10)});if(e.length>0)return e;const $=D(a),I=extractDetail(a);return I?[{mount:"",detail:I,percent:$}]:[]}function re(a){if(!a)return"-";const e=new Date(a);if(isNaN(e.getTime()))return a;const r=v=>String(v).padStart(2,"0");return`${e.getFullYear()}-${r(e.getMonth()+1)}-${r(e.getDate())} ${r(e.getHours())}:${r(e.getMinutes())}:${r(e.getSeconds())}`}function ve(a){if(!a&&a!==0)return"-";const e=Number(a);if(e<60)return`${e}`;if(e<3600)return`${Math.floor(e/60)}${e%60}`;const r=Math.floor(e/3600),v=Math.floor(e%3600/60);if(r<24)return`${r}${v}`;const $=Math.floor(r/24),I=r%24;return`${$}${I}${v}`}function me(a){if(!a&&a!==0)return"-";const e=Number(a);return 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(1)}GB`}function ze(a){if(!a&&a!==0)return"-";const e=Number(a),r=Math.floor(e/86400),v=Math.floor(e%86400/3600),$=Math.floor(e%3600/60);return r>0?`${r}${v}${$}`:v>0?`${v}${$}`:`${$}`}return(a,e)=>{var _e,pe;const r=S("el-icon"),v=S("el-button"),$=S("el-tag"),I=S("el-empty"),x=S("el-input"),y=S("el-form-item"),Y=S("el-form"),J=S("el-dialog"),Q=S("el-input-number"),g=S("el-option"),R=S("el-select"),Be=S("el-divider");return o.value?(i(),d("div",ft,[l("div",yt,[l("div",ht,[s(v,{text:"",circle:"",onClick:e[0]||(e[0]=t=>a.$router.back())},{default:n(()=>[s(r,null,{default:n(()=>[s(_(lt))]),_:1})]),_:1}),l("div",null,[l("div",Vt,[c(u(o.value.hostname)+" ",1),l("span",{class:ce(["status-badge",o.value.is_online?"online":"offline"])},u(o.value.is_online?"在线":"离线"),3)]),l("div",gt,[_(k)?(i(),d("span",kt,u(o.value.ip),1)):m("",!0),l("span",null,u(o.value.os_type),1),o.value.os_version?(i(),d("span",bt,u(o.value.os_version),1)):m("",!0)])])]),_(k)?(i(),d("div",wt,[o.value.pve_host_id&&o.value.pve_vmid?(i(),C($,{key:0,size:"small",type:f.value._error?"info":f.value.status==="running"?"success":f.value.status==="stopped"?"danger":"info",effect:"light",class:"vm-status-tag"},{default:n(()=>[c(u(f.value._error?"VM检测失败":f.value.status==="running"?"VM运行中":f.value.status==="stopped"?"VM已停止":"VM检测中"),1)]),_:1},8,["type"])):m("",!0),o.value.pve_host_id&&o.value.pve_vmid?(i(),C(v,{key:1,type:"success",icon:_(Ae),loading:z.value,onClick:$e,disabled:f.value.status==="running"||f.value._error},{default:n(()=>[...e[37]||(e[37]=[c("启动",-1)])]),_:1},8,["icon","loading","disabled"])):m("",!0),o.value.pve_host_id&&o.value.pve_vmid?(i(),C(v,{key:2,type:"warning",icon:_(Ge),loading:z.value,onClick:Ce,disabled:f.value.status==="stopped"||f.value._error},{default:n(()=>[...e[38]||(e[38]=[c("关闭",-1)])]),_:1},8,["icon","loading","disabled"])):m("",!0),s(v,{text:"",icon:_(se),onClick:e[1]||(e[1]=t=>Me(o.value))},{default:n(()=>[...e[39]||(e[39]=[c("编辑",-1)])]),_:1},8,["icon"]),s(v,{text:"",type:"danger",icon:_(ae),onClick:Ue},{default:n(()=>[...e[40]||(e[40]=[c("删除",-1)])]),_:1},8,["icon"])])):m("",!0)]),l("div",Mt,[l("div",xt,[e[46]||(e[46]=l("div",{class:"card-title"},"基本信息",-1)),l("div",St,[l("div",$t,[e[41]||(e[41]=l("span",{class:"info-label"},"IP",-1)),l("span",Ct,u(o.value.ip),1)]),_(k)?(i(),d("div",Ut,[e[42]||(e[42]=l("span",{class:"info-label"},"MAC",-1)),l("span",Pt,u(o.value.mac||"-"),1)])):m("",!0),l("div",Dt,[e[43]||(e[43]=l("span",{class:"info-label"},"系统",-1)),l("span",Tt,u(o.value.os_type)+" "+u(o.value.os_version||""),1)]),_(k)?(i(),d("div",Et,[e[44]||(e[44]=l("span",{class:"info-label"},"SSH 端口",-1)),l("span",Ht,u(o.value.ssh_port||22),1)])):m("",!0),_(k)?(i(),d("div",It,[e[45]||(e[45]=l("span",{class:"info-label"},"备注",-1)),l("span",Rt,u(o.value.notes||"-"),1)])):m("",!0)])]),o.value.pve_host_id&&o.value.pve_vmid&&f.value.status?(i(),d("div",zt,[e[51]||(e[51]=l("div",{class:"card-title"},"PVE 虚拟机状态",-1)),l("div",Bt,[l("div",Nt,[e[47]||(e[47]=l("span",{class:"vm-stat-label"},"运行状态",-1)),l("span",{class:ce(["vm-stat-value",f.value.status])},u(f.value.status==="running"?"运行中":"已停止"),3)]),f.value.cpu!==void 0?(i(),d("div",qt,[e[48]||(e[48]=l("span",{class:"vm-stat-label"},"CPU 使用率",-1)),l("span",Ft,u((_e=f.value.cpu)!=null&&_e.toFixed?f.value.cpu.toFixed(1):f.value.cpu)+"%",1)])):m("",!0),f.value.memory_used!==void 0&&f.value.memory_total?(i(),d("div",Lt,[e[49]||(e[49]=l("span",{class:"vm-stat-label"},"内存使用",-1)),l("span",Kt,u(me(f.value.memory_used))+" / "+u(me(f.value.memory_total)),1)])):m("",!0),f.value.uptime?(i(),d("div",Ot,[e[50]||(e[50]=l("span",{class:"vm-stat-label"},"运行时长",-1)),l("span",At,u(ze(f.value.uptime)),1)])):m("",!0)])])):m("",!0),o.value.cpu_info||o.value.memory_info||o.value.disk_info?(i(),d("div",Gt,[e[56]||(e[56]=l("div",{class:"card-title"},"系统状态",-1)),l("div",Wt,[o.value.cpu_info?(i(),d("div",jt,[e[52]||(e[52]=l("div",{class:"sp-icon cpu"},"CPU",-1)),l("div",Yt,[l("div",Jt,u(o.value.cpu_info),1),l("div",Qt,[l("div",{class:"sp-fill",style:X({width:D(o.value.cpu_info)+"%"})},null,4)])]),l("div",Xt,u(D(o.value.cpu_info))+"%",1)])):m("",!0),o.value.memory_info?(i(),d("div",Zt,[e[53]||(e[53]=l("div",{class:"sp-icon mem"},"MEM",-1)),l("div",el,[l("div",tl,u(o.value.memory_info),1),l("div",ll,[l("div",{class:"sp-fill",style:X({width:D(o.value.memory_info)+"%",background:Re(D(o.value.memory_info))})},null,4)])]),l("div",sl,u(D(o.value.memory_info))+"%",1)])):m("",!0),o.value.disk_info?(i(),d("div",al,[de(o.value.disk_info).length<=1?(i(),d(U,{key:0},[e[54]||(e[54]=l("div",{class:"sp-icon disk"},"DISK",-1)),l("div",ol,[l("div",nl,u(o.value.disk_info),1),l("div",il,[l("div",{class:"sp-fill",style:X({width:D(o.value.disk_info)+"%",background:ue(D(o.value.disk_info))})},null,4)])]),l("div",ul,u(D(o.value.disk_info))+"%",1)],64)):(i(),d(U,{key:1},[e[55]||(e[55]=l("div",{class:"sp-icon disk"},"DISK",-1)),l("div",dl,[(i(!0),d(U,null,T(de(o.value.disk_info),(t,O)=>(i(),d("div",{key:O,class:"detail-disk-item"},[l("span",rl,u(t.mount),1),l("div",vl,[l("div",ml,[l("div",{class:"dd-fill",style:X({width:t.percent+"%",background:ue(t.percent)})},null,4)])]),l("span",_l,u(t.detail),1),l("span",pl,u(t.percent)+"%",1)]))),128))])],64))])):m("",!0)]),o.value.uptime?(i(),d("div",cl,[s(r,null,{default:n(()=>[s(_(st))]),_:1}),l("span",null,"运行时间 "+u(o.value.uptime),1)])):m("",!0)])):m("",!0),_(k)?(i(),d("div",fl,[e[65]||(e[65]=l("div",{class:"card-title"},"SSH 系统信息",-1)),o.value.cpu_info||o.value.memory_info||o.value.disk_info||o.value.uptime?(i(),d("div",yl,[s($,{size:"small",effect:"plain",round:""},{default:n(()=>[c("上次同步 "+u(re(o.value.ssh_synced_at)),1)]),_:1})])):m("",!0),l("div",hl,[s(v,{type:"primary",icon:_(We),onClick:xe},{default:n(()=>[...e[57]||(e[57]=[c("获取系统信息",-1)])]),_:1},8,["icon"])]),M.value?(i(),d("div",Vl,[l("div",gl,[l("div",kl,[e[58]||(e[58]=l("span",{class:"rl"},"主机名",-1)),l("span",bl,u(M.value.hostname),1)]),l("div",wl,[e[59]||(e[59]=l("span",{class:"rl"},"系统版本",-1)),l("span",Ml,u(M.value.os_version),1)]),l("div",xl,[e[60]||(e[60]=l("span",{class:"rl"},"CPU",-1)),l("span",Sl,u(M.value.cpu),1)]),l("div",$l,[e[61]||(e[61]=l("span",{class:"rl"},"内存",-1)),l("span",Cl,u(M.value.memory),1)]),l("div",Ul,[e[62]||(e[62]=l("span",{class:"rl"},"磁盘",-1)),l("span",Pl,u(M.value.disk),1)]),l("div",Dl,[e[63]||(e[63]=l("span",{class:"rl"},"运行时间",-1)),l("span",Tl,u(M.value.uptime),1)]),l("div",El,[e[64]||(e[64]=l("span",{class:"rl"},"监听端口",-1)),l("span",Hl,u((pe=M.value.listen_ports)==null?void 0:pe.join(", ")),1)])])])):m("",!0)])):m("",!0),l("div",Il,[l("div",Rl,[e[67]||(e[67]=c(" 服务列表 ",-1)),_(k)?(i(),C(v,{key:0,size:"small",type:"primary",icon:_(fe),onClick:e[2]||(e[2]=t=>ne())},{default:n(()=>[...e[66]||(e[66]=[c("添加服务",-1)])]),_:1},8,["icon"])):m("",!0)]),Z.value.length?(i(),d("div",zl,[(i(!0),d(U,null,T(Z.value,t=>(i(),d("div",{key:t.id,class:"service-row"},[l("div",Bl,[l("div",Nl,u(t.name),1),l("div",ql,u(t.port)+" / "+u(t.protocol),1)]),_(k)&&t.target_machine_id?(i(),d("div",Fl,[s(r,null,{default:n(()=>[s(_(ye))]),_:1}),l("span",null,u(we.value[t.target_machine_id]||t.target_machine_id),1),t.target_notes?(i(),d("span",Ll,u(t.target_notes),1)):m("",!0)])):m("",!0),_(k)&&t.notes?(i(),d("div",Kl,u(t.notes),1)):m("",!0),_(k)?(i(),d("div",Ol,[s(v,{text:"",size:"small",icon:_(se),onClick:he(O=>ne(t),["stop"])},{default:n(()=>[...e[68]||(e[68]=[c("编辑",-1)])]),_:1},8,["icon","onClick"]),s(v,{text:"",size:"small",type:"danger",icon:_(ae),onClick:he(O=>Te(t),["stop"])},{default:n(()=>[...e[69]||(e[69]=[c("删除",-1)])]),_:1},8,["icon","onClick"])])):m("",!0)]))),128))])):(i(),C(I,{key:1,description:"暂无服务","image-size":80}))]),_(k)?(i(),d("div",Al,[e[74]||(e[74]=l("div",{class:"card-title"},"离线统计",-1)),l("div",Gl,[l("div",Wl,[l("div",jl,u(o.value.offline_count||0),1),e[70]||(e[70]=l("div",{class:"stat-label"},"离线次数",-1))]),l("div",Yl,[l("div",Jl,u(ve(o.value.total_offline_seconds)),1),e[71]||(e[71]=l("div",{class:"stat-label"},"累计离线时长",-1))]),o.value.last_offline_reason?(i(),d("div",Ql,[l("div",Xl,u(o.value.last_offline_reason),1),e[72]||(e[72]=l("div",{class:"stat-label"},"上次离线原因",-1))])):m("",!0)]),te.value.length?(i(),d("div",Zl,[e[73]||(e[73]=l("div",{class:"log-title"},"最近离线记录",-1)),(i(!0),d(U,null,T(te.value.slice(0,5),t=>(i(),d("div",{key:t.id,class:"log-row"},[l("span",es,u(re(t.started_at)),1),l("span",ts,u(t.reason||"未知原因"),1),t.duration_seconds!==null&&t.duration_seconds!==void 0?(i(),d("span",ls,"持续 "+u(ve(t.duration_seconds)),1)):(i(),d("span",ss,"未恢复"))]))),128))])):m("",!0)])):m("",!0),_(k)?(i(),d("div",as,[l("div",os,[e[76]||(e[76]=c(" 关联关系 ",-1)),s(v,{size:"small",type:"primary",icon:_(fe),onClick:e[3]||(e[3]=t=>ie())},{default:n(()=>[...e[75]||(e[75]=[c("添加关系",-1)])]),_:1},8,["icon"])]),ee.value.length?(i(),d("div",ns,[(i(!0),d(U,null,T(ee.value,t=>(i(),d("div",{key:t.id,class:"rel-row"},[l("div",is,[l("span",us,u(t.source_hostname),1),s(r,null,{default:n(()=>[s(_(ye))]),_:1}),l("span",ds,u(t.target_hostname),1)]),l("div",rs,[s($,{size:"small",effect:"plain",round:""},{default:n(()=>[c(u(Ie(t.relation_type)),1)]),_:2},1024),t.source_port?(i(),d("span",vs,u(t.source_port)+" → "+u(t.target_port||"-"),1)):m("",!0),t.notes?(i(),d("span",ms,u(t.notes),1)):m("",!0)]),l("div",_s,[s(v,{text:"",size:"small",icon:_(se),onClick:O=>ie(t)},{default:n(()=>[...e[77]||(e[77]=[c("编辑",-1)])]),_:1},8,["icon","onClick"]),s(v,{text:"",size:"small",type:"danger",icon:_(ae),onClick:O=>He(t)},{default:n(()=>[...e[78]||(e[78]=[c("删除",-1)])]),_:1},8,["icon","onClick"])])]))),128))])):(i(),C(I,{key:1,description:"暂无关系","image-size":80}))])):m("",!0)]),s(J,{modelValue:F.value,"onUpdate:modelValue":e[7]||(e[7]=t=>F.value=t),title:"SSH 获取系统信息",width:"360px",class:"modern-dialog"},{footer:n(()=>[s(v,{onClick:e[6]||(e[6]=t=>F.value=!1)},{default:n(()=>[...e[79]||(e[79]=[c("取消",-1)])]),_:1}),s(v,{type:"primary",loading:N.value,onClick:Pe},{default:n(()=>[...e[80]||(e[80]=[c("连接",-1)])]),_:1},8,["loading"])]),default:n(()=>[s(Y,{model:E.value,"label-width":"80px"},{default:n(()=>[s(y,{label:"用户名"},{default:n(()=>[s(x,{modelValue:E.value.username,"onUpdate:modelValue":e[4]||(e[4]=t=>E.value.username=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"密码"},{default:n(()=>[s(x,{modelValue:E.value.password,"onUpdate:modelValue":e[5]||(e[5]=t=>E.value.password=t),type:"password","show-password":""},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),s(J,{modelValue:q.value,"onUpdate:modelValue":e[20]||(e[20]=t=>q.value=t),title:"编辑机器",width:"480px",class:"modern-dialog"},{footer:n(()=>[s(v,{onClick:e[19]||(e[19]=t=>q.value=!1)},{default:n(()=>[...e[82]||(e[82]=[c("取消",-1)])]),_:1}),s(v,{type:"primary",onClick:Se},{default:n(()=>[...e[83]||(e[83]=[c("保存",-1)])]),_:1})]),default:n(()=>[s(Y,{model:p.value,"label-width":"90px"},{default:n(()=>[s(y,{label:"主机名",required:""},{default:n(()=>[s(x,{modelValue:p.value.hostname,"onUpdate:modelValue":e[8]||(e[8]=t=>p.value.hostname=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"IP",required:""},{default:n(()=>[s(x,{modelValue:p.value.ip,"onUpdate:modelValue":e[9]||(e[9]=t=>p.value.ip=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"MAC"},{default:n(()=>[s(x,{modelValue:p.value.mac,"onUpdate:modelValue":e[10]||(e[10]=t=>p.value.mac=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"SSH端口"},{default:n(()=>[s(Q,{modelValue:p.value.ssh_port,"onUpdate:modelValue":e[11]||(e[11]=t=>p.value.ssh_port=t),min:1,max:65535,style:{width:"100%"}},null,8,["modelValue"])]),_:1}),s(y,{label:"SSH用户"},{default:n(()=>[s(x,{modelValue:p.value.ssh_username,"onUpdate:modelValue":e[12]||(e[12]=t=>p.value.ssh_username=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"SSH密码"},{default:n(()=>[s(x,{modelValue:p.value.ssh_password,"onUpdate:modelValue":e[13]||(e[13]=t=>p.value.ssh_password=t),type:"password","show-password":"",placeholder:"输入则更新密码,留空保持不变"},null,8,["modelValue"])]),_:1}),s(y,{label:"系统",required:""},{default:n(()=>[s(R,{modelValue:p.value.os_type,"onUpdate:modelValue":e[14]||(e[14]=t=>p.value.os_type=t),style:{width:"100%"}},{default:n(()=>[s(g,{label:"Linux",value:"Linux"}),s(g,{label:"Windows",value:"Windows"}),s(g,{label:"macOS",value:"macOS"}),s(g,{label:"Other",value:"Other"})]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"系统版本"},{default:n(()=>[s(x,{modelValue:p.value.os_version,"onUpdate:modelValue":e[15]||(e[15]=t=>p.value.os_version=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"备注"},{default:n(()=>[s(x,{modelValue:p.value.notes,"onUpdate:modelValue":e[16]||(e[16]=t=>p.value.notes=t),type:"textarea",rows:2},null,8,["modelValue"])]),_:1}),s(Be,{"content-position":"left"},{default:n(()=>[...e[81]||(e[81]=[c("PVE 配置(可选)",-1)])]),_:1}),s(y,{label:"PVE 主机"},{default:n(()=>[s(R,{modelValue:p.value.pve_host_id,"onUpdate:modelValue":e[17]||(e[17]=t=>p.value.pve_host_id=t),placeholder:"选择 PVE 主机",clearable:"",style:{width:"100%"}},{default:n(()=>[(i(!0),d(U,null,T(oe.value,t=>(i(),C(g,{key:t.id,label:t.name,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"虚拟机 ID"},{default:n(()=>[s(x,{modelValue:p.value.pve_vmid,"onUpdate:modelValue":e[18]||(e[18]=t=>p.value.pve_vmid=t),placeholder:"如 101"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),s(J,{modelValue:L.value,"onUpdate:modelValue":e[28]||(e[28]=t=>L.value=t),title:"编辑服务",width:"440px",class:"modern-dialog"},{footer:n(()=>[s(v,{onClick:e[27]||(e[27]=t=>L.value=!1)},{default:n(()=>[...e[84]||(e[84]=[c("取消",-1)])]),_:1}),s(v,{type:"primary",onClick:De},{default:n(()=>[...e[85]||(e[85]=[c("保存",-1)])]),_:1})]),default:n(()=>[s(Y,{model:b.value,"label-width":"90px"},{default:n(()=>[s(y,{label:"名称",required:""},{default:n(()=>[s(x,{modelValue:b.value.name,"onUpdate:modelValue":e[21]||(e[21]=t=>b.value.name=t)},null,8,["modelValue"])]),_:1}),s(y,{label:"端口",required:""},{default:n(()=>[s(Q,{modelValue:b.value.port,"onUpdate:modelValue":e[22]||(e[22]=t=>b.value.port=t),min:1,max:65535,style:{width:"100%"}},null,8,["modelValue"])]),_:1}),s(y,{label:"协议"},{default:n(()=>[s(R,{modelValue:b.value.protocol,"onUpdate:modelValue":e[23]||(e[23]=t=>b.value.protocol=t),style:{width:"100%"}},{default:n(()=>[s(g,{label:"TCP",value:"TCP"}),s(g,{label:"UDP",value:"UDP"}),s(g,{label:"HTTP",value:"HTTP"}),s(g,{label:"HTTPS",value:"HTTPS"})]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"指向机器"},{default:n(()=>[s(R,{modelValue:b.value.target_machine_id,"onUpdate:modelValue":e[24]||(e[24]=t=>b.value.target_machine_id=t),clearable:"",style:{width:"100%"},placeholder:"选择目标机器(拓扑连线用)"},{default:n(()=>[(i(!0),d(U,null,T(B.value.filter(t=>t.id!=_(V)),t=>(i(),C(g,{key:t.id,label:t.hostname,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"指向备注"},{default:n(()=>[s(x,{modelValue:b.value.target_notes,"onUpdate:modelValue":e[25]||(e[25]=t=>b.value.target_notes=t),placeholder:"如:反向代理到目标"},null,8,["modelValue"])]),_:1}),s(y,{label:"备注"},{default:n(()=>[s(x,{modelValue:b.value.notes,"onUpdate:modelValue":e[26]||(e[26]=t=>b.value.notes=t),type:"textarea",rows:2},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),s(J,{modelValue:K.value,"onUpdate:modelValue":e[36]||(e[36]=t=>K.value=t),title:"编辑关系",width:"440px",class:"modern-dialog"},{footer:n(()=>[s(v,{onClick:e[35]||(e[35]=t=>K.value=!1)},{default:n(()=>[...e[86]||(e[86]=[c("取消",-1)])]),_:1}),s(v,{type:"primary",onClick:Ee},{default:n(()=>[...e[87]||(e[87]=[c("保存",-1)])]),_:1})]),default:n(()=>[s(Y,{model:w.value,"label-width":"100px"},{default:n(()=>[s(y,{label:"源机器",required:""},{default:n(()=>[s(R,{modelValue:w.value.source_machine_id,"onUpdate:modelValue":e[29]||(e[29]=t=>w.value.source_machine_id=t),style:{width:"100%"}},{default:n(()=>[(i(!0),d(U,null,T(B.value,t=>(i(),C(g,{key:t.id,label:t.hostname,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"目标机器",required:""},{default:n(()=>[s(R,{modelValue:w.value.target_machine_id,"onUpdate:modelValue":e[30]||(e[30]=t=>w.value.target_machine_id=t),style:{width:"100%"}},{default:n(()=>[(i(!0),d(U,null,T(B.value,t=>(i(),C(g,{key:t.id,label:t.hostname,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"关系类型",required:""},{default:n(()=>[s(R,{modelValue:w.value.relation_type,"onUpdate:modelValue":e[31]||(e[31]=t=>w.value.relation_type=t),style:{width:"100%"}},{default:n(()=>[s(g,{label:"端口转发",value:"port_forward"}),s(g,{label:"依赖",value:"dependency"}),s(g,{label:"主从",value:"primary_secondary"}),s(g,{label:"自定义",value:"custom"})]),_:1},8,["modelValue"])]),_:1}),s(y,{label:"源端口"},{default:n(()=>[s(Q,{modelValue:w.value.source_port,"onUpdate:modelValue":e[32]||(e[32]=t=>w.value.source_port=t),min:1,max:65535,style:{width:"100%"}},null,8,["modelValue"])]),_:1}),s(y,{label:"目标端口"},{default:n(()=>[s(Q,{modelValue:w.value.target_port,"onUpdate:modelValue":e[33]||(e[33]=t=>w.value.target_port=t),min:1,max:65535,style:{width:"100%"}},null,8,["modelValue"])]),_:1}),s(y,{label:"备注"},{default:n(()=>[s(x,{modelValue:w.value.notes,"onUpdate:modelValue":e[34]||(e[34]=t=>w.value.notes=t),type:"textarea",rows:2},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])):m("",!0)}}},hs=ct(ps,[["__scopeId","data-v-6f4bd63e"]]);export{hs as default};