Files
Migu2.0/MiGu.Server/wwwroot/assets/MapMonitorView-C7AnAWKd.js
T
zhaowei.huangandCursor 42978930ca feat: 迁入 MiGu.Server、平台前端与车辆列表 reflection 回退
从 Simple-FR 拆出 Platform.Server 并重命名为 MiGu.Server;frontends 源码与构建脚本迁入本仓库。地图监控在 projection/cars 失败或为空时回退 reflection 车辆列表;Simple 仓库已移除旧 Platform.Server。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 18:16:34 +08:00

2 lines
31 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{aG as ve,b3 as o,aC as i,az as e,bj as u,aF as _,S as Se,a4 as Ae,bB as C,ai as D,bd as Z,_ as Le,aZ as ie,ad as Ce,aE as J,aB as H,$ as Ve,bb as g,av as S,al as fe,bA as Ie,aA as Ne,a3 as ze,s as ke,H as Fe,Z as Pe,Y as Q,R as xe,bm as de,aU as Oe,b0 as Be,bE as he,a_ as Re,au as De,p as Ue,bo as Ke,b1 as We,b2 as je,a2 as qe,x as Xe,a6 as He,u as Ge}from"./index-DrvLDslf.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{W as Ye}from"./Workspace3D-D7MYl2zT.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{r as oe}from"./reflection-Dr3WM5Rz.js";import{m as Ze}from"./mapEdit-DghrYjHu.js";import{W as Je}from"./WorkspaceCanvasToolbar-1mCqpdq_.js";import{l as Qe,a as et}from"./projection-CizY2UtH.js";import{u as tt}from"./useProjectionStream-DMf_8m8X.js";import"./el-tooltip-l0sNRNKZ.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */const nt={class:"vehicle-monitor"},st={class:"overview-row"},at={class:"overview-item"},lt={class:"overview-num"},ot={class:"overview-item"},it={class:"overview-num online"},rt={class:"overview-item"},ct={class:"overview-num running"},ut={class:"overview-item"},dt={class:"overview-num charging"},vt={class:"overview-item"},ft={class:"overview-num fault"},mt={class:"toolbar"},pt={class:"vehicle-list"},_t=["onClick"],ht={class:"vehicle-head"},kt={class:"vehicle-id-name"},yt={class:"vid"},gt={class:"vname"},bt={class:"vehicle-meta muted"},wt={key:0,class:"meta-item"},$t={key:1,class:"meta-item"},St={key:2,class:"meta-item"},Ct={class:"battery-row"},It={class:"mission-row"},Nt=["title"],xt={key:0,class:"empty muted"},Mt=ve({__name:"VehicleMonitorPanel",props:{cars:{},missions:{},selectedId:{}},emits:["select"],setup(h,{emit:N}){const l=h,b=N,I=g(""),d=g(""),p=[{value:"idle",label:"空闲"},{value:"running",label:"运行中"},{value:"charging",label:"充电中"},{value:"paused",label:"已暂停"},{value:"fault",label:"故障"},{value:"offline",label:"离线"}],V=p.reduce((a,m)=>(a[m.value]=m.label,a),{});function F(a){return V[a]??a}function O(a){switch(a){case"running":return"success";case"charging":return"primary";case"paused":return"warning";case"fault":return"danger";case"offline":return"info";case"idle":default:return"info"}}const G={queued:"排队",assigned:"已分配",running:"执行中",paused:"暂停",completed:"已完成",cancelled:"已取消",failed:"失败"};function B(a){return G[a]??a}function P(a){switch(a){case"running":return"success";case"assigned":return"primary";case"queued":return"info";case"paused":return"warning";case"completed":return"success";case"cancelled":return"info";case"failed":return"danger";default:return"info"}}const x=S(()=>l.cars.filter(a=>a.state!=="offline").length),v=S(()=>l.cars.filter(a=>a.state==="running").length),j=S(()=>l.cars.filter(a=>a.state==="charging").length),U=S(()=>l.cars.filter(a=>a.state==="fault").length),R=S(()=>{const a=w=>w==="running"?0:w==="paused"?1:w==="assigned"?2:3,m=new Map;for(const w of l.missions){if(!w.carId||w.status!=="running"&&w.status!=="paused"&&w.status!=="assigned")continue;const K=m.get(w.carId);(!K||a(w.status)<a(K.status))&&m.set(w.carId,w)}return m});function M(a){if(a.missionId){const m=l.missions.find(w=>w.id===a.missionId);if(m)return m}return R.value.get(a.id)}function T(a){const m=a.batterySoc??0,w=m>1?m:m*100;return Math.max(0,Math.min(100,Math.round(w)))}function Y(a){return a<20?"#f56c6c":a<50?"#e6a23c":"#67c23a"}function se(a){return a<20?"low":a<50?"mid":"high"}function E(a){const m=a.lastIndexOf(".");return m>=0?a.slice(m+1):a}const A=S(()=>{const a=I.value.trim().toLowerCase(),m=a?a.split(/\s+/).filter(Boolean):[];return l.cars.filter(w=>{if(d.value&&w.state!==d.value)return!1;if(!m.length)return!0;const K=M(w),ae=[w.id,w.name,w.typeName??"",w.group??"",w.ip??"",F(w.state),K?.name??"",K?B(K.status):""].join(" ").toLowerCase();return m.every(ne=>ae.includes(ne))})});function q(a){b("select",{kind:"vehicle",id:ee(a),name:a.name})}function ee(a){return a.rawId!=null?String(a.rawId):a.id.replace(/^C/i,"").replace(/^0+/,"")||a.id}return(a,m)=>{const w=Se,K=Le,ae=Ae,ne=Ce,te=Ve;return o(),i("div",nt,[e("div",st,[e("div",at,[e("div",lt,u(h.cars.length),1),m[2]||(m[2]=e("div",{class:"overview-label"},"总数",-1))]),e("div",ot,[e("div",it,u(x.value),1),m[3]||(m[3]=e("div",{class:"overview-label"},"在线",-1))]),e("div",rt,[e("div",ct,u(v.value),1),m[4]||(m[4]=e("div",{class:"overview-label"},"运行",-1))]),e("div",ut,[e("div",dt,u(j.value),1),m[5]||(m[5]=e("div",{class:"overview-label"},"充电",-1))]),e("div",vt,[e("div",ft,u(U.value),1),m[6]||(m[6]=e("div",{class:"overview-label"},"故障",-1))])]),e("div",mt,[_(w,{modelValue:I.value,"onUpdate:modelValue":m[0]||(m[0]=k=>I.value=k),size:"small",clearable:"",placeholder:"搜索 ID / 名称 / 任务",class:"search"},null,8,["modelValue"]),_(ae,{modelValue:d.value,"onUpdate:modelValue":m[1]||(m[1]=k=>d.value=k),size:"small",placeholder:"状态",clearable:"",class:"filter"},{default:C(()=>[(o(),i(D,null,Z(p,k=>_(K,{key:k.value,label:k.label,value:k.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"])]),e("div",pt,[(o(!0),i(D,null,Z(A.value,k=>(o(),i("div",{key:k.id,class:ie(["vehicle-row",{"is-selected":k.id===h.selectedId}]),onClick:re=>q(k)},[e("div",ht,[e("div",kt,[e("span",yt,u(k.id),1),e("span",gt,u(k.name),1)]),_(ne,{size:"small",type:O(k.state),class:"state-tag",effect:"dark"},{default:C(()=>[e("span",{class:ie(["dot",`dot-${k.state}`])},null,2),J(" "+u(F(k.state)),1)]),_:2},1032,["type"])]),e("div",bt,[k.typeName?(o(),i("span",wt,u(E(k.typeName)),1)):H("",!0),k.group?(o(),i("span",$t,u(k.group),1)):H("",!0),k.ip?(o(),i("span",St,u(k.ip),1)):H("",!0)]),e("div",Ct,[m[7]||(m[7]=e("span",{class:"battery-label"},"电量",-1)),_(te,{percentage:T(k),"stroke-width":8,"show-text":!1,color:Y(T(k)),class:"battery-bar"},null,8,["percentage","color"]),e("span",{class:ie(["battery-text",se(T(k))])},u(T(k))+"% ",3)]),e("div",It,[m[10]||(m[10]=e("span",{class:"mission-label"},"任务",-1)),M(k)?(o(),i(D,{key:0},[e("span",{class:"mission-name",title:M(k).name},u(M(k).name),9,Nt),_(ne,{size:"small",type:P(M(k).status),effect:"plain",class:"mission-tag"},{default:C(()=>[J(u(B(M(k).status)),1)]),_:2},1032,["type"])],64)):(o(),i(D,{key:1},[m[9]||(m[9]=e("span",{class:"mission-name muted"},"无任务",-1)),_(ne,{size:"small",type:"info",effect:"plain",class:"mission-tag"},{default:C(()=>[...m[8]||(m[8]=[J("空闲",-1)])]),_:1})],64))])],10,_t))),128)),A.value.length?H("",!0):(o(),i("div",xt," 无匹配车辆 "))])])}}}),Et=fe(Mt,[["__scopeId","data-v-058df7b7"]]),Tt=["onClick"],At={class:"sid"},Lt={class:"sname"},Vt={key:0,class:"empty"},zt=ve({__name:"SitePickDialog",props:{modelValue:{type:Boolean},title:{},sites:{}},emits:["update:modelValue","confirm","pickOnMap"],setup(h,{expose:N,emit:l}){const b=h,I=l,d=S({get:()=>b.modelValue,set:x=>I("update:modelValue",x)}),p=g(""),V=g(null),F=g(!1),O=S(()=>{const x=p.value.trim().toLowerCase();return x?b.sites.filter(v=>String(v.id).includes(x)||v.name.toLowerCase().includes(x)||v.label.toLowerCase().includes(x)):b.sites});Ie(()=>b.modelValue,x=>{x&&(p.value="",V.value=b.sites[0]?.id??null)});function G(){V.value!=null&&(I("confirm",V.value),d.value=!1)}function B(){F.value=!0,I("pickOnMap")}function P(){F.value=!1}return N({close:()=>{d.value=!1},endMapPick:()=>{F.value=!1}}),(x,v)=>{const j=Se,U=ze,R=ke,M=Fe;return o(),Ne(M,{modelValue:d.value,"onUpdate:modelValue":v[2]||(v[2]=T=>d.value=T),title:h.title,width:"420px","destroy-on-close":"","append-to-body":"",class:"site-pick-dialog",onClosed:P},{footer:C(()=>[_(R,{onClick:v[1]||(v[1]=T=>d.value=!1)},{default:C(()=>[...v[3]||(v[3]=[J("取消",-1)])]),_:1}),_(R,{loading:F.value,onClick:B},{default:C(()=>[...v[4]||(v[4]=[J("在地图上拾取",-1)])]),_:1},8,["loading"]),_(R,{type:"primary",disabled:V.value==null,onClick:G},{default:C(()=>[...v[5]||(v[5]=[J("确认前往",-1)])]),_:1},8,["disabled"])]),default:C(()=>[v[6]||(v[6]=e("p",{class:"hint"},"请选择车辆要前往的目标站点。",-1)),_(j,{modelValue:p.value,"onUpdate:modelValue":v[0]||(v[0]=T=>p.value=T),clearable:"",placeholder:"搜索站点 ID / 名称",class:"filter-input"},null,8,["modelValue"]),_(U,{"max-height":"280px",class:"site-scroll"},{default:C(()=>[(o(!0),i(D,null,Z(O.value,T=>(o(),i("button",{key:T.id,type:"button",class:ie(["site-row",{active:V.value===T.id}]),onClick:Y=>V.value=T.id},[e("span",At,"#"+u(T.id),1),e("span",Lt,u(T.name||"未命名"),1)],10,Tt))),128)),O.value.length?H("",!0):(o(),i("div",Vt,"无匹配站点"))]),_:1})]),_:1},8,["modelValue","title"])}}}),Ft=fe(zt,[["__scopeId","data-v-fe1b16d7"]]),Pt=new Set(["Goto","GotoSite"]),Ot=["去某地","前往站点"];function $e(h){if(h.params?.length)return!1;if(Pt.has(h.methodName))return!0;const N=h.label??"";return Ot.some(l=>N.includes(l))}async function Bt(){return(await oe.listObjects("site")).map(N=>({id:N.id,name:N.name,label:`#${N.id} ${N.name||"站点"}`})).sort((N,l)=>N.id-l.id)}async function Rt(){try{Q.info({message:"请在 3D 地图上点击目标站点附近",duration:4e3});const h=await Ze.pick();return h.siteId==null||h.siteId<0?(Q.warning("未识别到附近站点,请靠近站点再点击"),null):h.siteId}catch(h){return h instanceof Error&&/取消|cancel|499/i.test(h.message)||Q.error(`地图拾取失败:${h instanceof Error?h.message:String(h)}`),null}}async function Dt(h,N){try{const l=await oe.gotoCarSite(h,N);return Q.success(l.message||`已下发前往站点 #${N}`),!0}catch(l){return Q.error(`前往站点失败:${l instanceof Error?l.message:String(l)}`),!1}}async function Ut(h,N,l){const b=l.label||l.methodName,I={};for(const d of l.params)try{const{value:p}=await Pe.prompt(`参数 ${d.name}${d.typeName}`,b,{inputValue:d.defaultValue??"",confirmButtonText:"确定",cancelButtonText:"取消"});I[d.name]=p??""}catch{return!1}try{const d=await oe.execute(h,N,l.methodName,I);return Q.success(d.returnValue?`已执行:${d.returnValue}`:`已执行 ${b}`),!0}catch(d){return Q.error(`执行失败:${d instanceof Error?d.message:String(d)}`),!1}}const Kt={class:"monitor-selection"},Wt={key:0,class:"empty-hint"},jt={key:1,class:"pane"},qt={key:0,class:"pane-loading"},Xt={class:"card card--header"},Ht={class:"title-row"},Gt={class:"id-tag"},Yt={class:"name-line"},Zt={class:"card"},Jt={class:"kv-grid"},Qt={class:"kv"},en={class:"v mono"},tn={class:"kv"},nn={class:"v mono"},sn={class:"kv"},an={class:"v mono"},ln={key:0,class:"card"},on={class:"card-hd"},rn={class:"meta"},cn={class:"kv-list"},un={class:"k"},dn=["title"],vn={key:1,class:"card card--actions"},fn={class:"action-grid"},mn=["disabled","onClick"],pn={class:"card card--header"},_n={class:"title-row"},hn={class:"id-tag"},kn={class:"name-line"},yn={key:0,class:"sub-line"},gn={key:0,class:"card"},bn={class:"card-hd"},wn={class:"meta"},$n={class:"kv-list"},Sn={class:"k"},Cn=["title"],In={key:1,class:"card"},Nn={class:"card-hd"},xn={class:"meta"},Mn={class:"kv-list"},En={class:"k"},Tn=["title"],An={class:"card card--actions"},Ln={class:"card-hd"},Vn={key:0,class:"meta"},zn={key:0,class:"muted-line"},Fn={key:1,class:"muted-line"},Pn={key:2,class:"action-grid action-grid--vehicle"},On=["disabled","onClick"],Bn={class:"card card--header"},Rn={class:"title-row"},Dn={class:"id-tag"},Un={class:"name-line"},Kn={key:0,class:"card"},Wn={class:"kv-list"},jn={class:"k"},qn={class:"v"},Xn={class:"k"},Hn={class:"v"},Gn={key:1,class:"card card--actions"},Yn={class:"action-grid"},Zn=["disabled","onClick"],Jn={key:4,class:"muted-line"},Qn=ve({__name:"MonitorSelectionPanel",props:{selection:{},refreshKey:{},cars:{},missions:{}},setup(h){const N=new Set(["AllowLock","PreventLock"]),l=h,b=g(!1),I=g(!1),d=g(!1),p=g(null),V=g(null),F=g(""),O=g(""),G=g(""),B=g({}),P=g([]),x=g([]),v=g({}),j=g([]),U=g([]),R=g(!1),M=g(!1),T=g([]),Y=g("选择目标站点"),se={car:"car",vehicle:"car",site:"site",track:"track"},E=S(()=>{const s=l.selection?.kind?.toLowerCase();return s?se[s]??null:null}),A=S(()=>{const s=l.selection?.kind?.toLowerCase();return s==="site"?"site":s==="vehicle"||s==="car"?"vehicle":s==="track"?"track":"other"}),q=S(()=>{const s=Number(l.selection?.id);return Number.isFinite(s)?s:l.selection?.id??"-"});function ee(s,t=1){if(s==null||s==="")return"—";const f=Number(s);return Number.isFinite(f)?f.toFixed(t):s}function a(...s){for(const t of s){const f=B.value[t];if(f!=null&&f!=="")return f}return""}function m(...s){for(const t of s){const f=P.value.find($=>$.key===t);if(f?.value)return f.value}for(const t of s){const f=P.value.find($=>$.key.includes(t));if(f?.value)return f.value}return""}function w(){const s=m("标记","tags");return s?/unavailable/i.test(s):!1}const K=S(()=>({name:a("name")||F.value||l.selection?.name||`站点 ${q.value}`,x:ee(a("x"),1),y:ee(a("y"),1),z:ee(a("z"),1),disabled:w()})),ae=S(()=>{const s=j.value;if(s.length){const t=new Set(s);return x.value.filter(f=>t.has(f.methodName))}return x.value.filter(t=>N.has(t.methodName))}),ne=S(()=>{const s=U.value;if(!s.length)return x.value;const t=new Set(s);return x.value.filter(f=>t.has(f.methodName))});function te(){if(!l.selection||A.value!=="vehicle")return;const s=String(l.selection.id);return l.cars?.find(t=>t.id===s||String(t.rawId??"")===s||k(t)===s)}function k(s){return s.rawId!=null?String(s.rawId):s.id.replace(/^C/i,"").replace(/^0+/,"")||s.id}function re(s){if(!s?.missionId)return"无";const t=l.missions?.find($=>$.id===s.missionId);if(!t)return s.missionId;const f={running:"运行中",queued:"排队",completed:"已完成",failed:"失败",cancelled:"已取消"};return`${t.name||t.id}${f[t.status]??t.status}`}const le=S(()=>{const s=te(),t={idle:"空闲",running:"运行",charging:"充电",paused:"暂停",fault:"故障",offline:"离线"},f=s?.state??"offline";return{displayId:s?.id??l.selection?.id??"-",name:F.value||s?.name||l.selection?.name||"车辆",typeShort:ue(O.value||s?.typeName),stateLabel:t[f]??f,state:f}}),n=S(()=>{switch(le.value.state){case"running":return"success";case"charging":return"warning";case"fault":return"danger";default:return"info"}}),r=S(()=>{const s=P.value.map(t=>({key:t.key,value:t.value||"—",warn:/alarm|error|fault|block|stop/i.test(`${t.key} ${t.value}`)&&t.value!=="0"&&t.value!=="无"}));if(A.value==="vehicle"&&!s.length){const t=te(),f=re(t),$=a("batterySoc","battery","电量"),c=$?`${Math.round(Number($)<=1?Number($)*100:Number($))}%`:t!=null?`${Math.round(t.batterySoc<=1?t.batterySoc*100:t.batterySoc)}%`:"—";return[{key:"位姿",value:m("位姿","站点")||"—",warn:!1},{key:"任务",value:f,warn:!1},{key:"电量",value:c,warn:Number.parseFloat(c)<20}]}return s}),y=new Set(["name","x","y","z","th","theta","layerName","layer"]),L=S(()=>A.value!=="vehicle"?[]:Object.entries(B.value).filter(([t,f])=>f!=null&&f!==""&&!y.has(t)).map(([t,f])=>({key:t,value:f})).sort((t,f)=>t.key.localeCompare(f.key)));function X(){const s=v.value,t=G.value,f=O.value;if(t&&s[t]?.length)return s[t];if(f&&s[f]?.length)return s[f];for(const[$,c]of Object.entries(s))if(c.length&&(t&&($===t||$.endsWith("."+f)||t.endsWith("."+$))||f&&($===f||$.endsWith("."+f))))return c;return[]}const W=S(()=>X()),z=S(()=>{const s=W.value;if(!s.length)return[];const t=new Set(s);return x.value.filter(f=>t.has(f.methodName))}),ce=S(()=>R.value?Object.keys(v.value).length?W.value.length?"当前车型无可执行动作。":"当前车型未配置动作,或方法名与运营维护中勾选的不一致。":"未配置动作。请在「配置中心 → 运营维护」按车型勾选动作并保存。":"加载配置中…"),me=S(()=>({name:a("name")||F.value||l.selection?.name||`路径 ${q.value}`})),pe=S(()=>[{key:"layer",label:"图层",value:a("layerName","layer")||"—"},{key:"type",label:"类型",value:O.value||"—"}]);function ue(s){if(!s)return"";const t=s.split(".");return t[t.length-1]??s}function Me(s){return s?`${s.kind}:${s.id}`:""}async function Ee(s=!1){if(!(R.value&&!s))try{const t=await oe.getMonitorConfig();v.value={...t.config.carActionByType??{}},j.value=[...t.config.site?.methods??[]],U.value=[...t.config.track?.methods??[]]}catch{v.value={},j.value=[],U.value=[]}finally{R.value=!0}}async function ye(){if(!l.selection){F.value="",B.value={},P.value=[],x.value=[],I.value=!1;return}const s=E.value,t=Number(l.selection.id);if(!s||!Number.isFinite(t))return;const f=I.value;f?d.value=!0:b.value=!0;try{await Ee(!f);const[$,c]=await Promise.all([oe.getBundle(s,t),oe.listMethods(s,t)]);F.value=$.summary?.name??l.selection.name??"",O.value=$.typeName??"",G.value="fullTypeName"in $&&$.fullTypeName?$.fullTypeName:$.typeName??"",B.value={...$.fields};for(const _e of $.fieldList??[])B.value[_e.key]=_e.value;P.value=$.status??[],x.value=c,I.value=!0}catch($){Q.error(`加载选中信息失败:${$.message}`)}finally{b.value=!1,d.value=!1}}async function ge(s){const t=E.value;if(!t||!l.selection||!s.methodName)return;const f=Number(l.selection.id);if(Number.isFinite(f)){if(t==="car"&&$e(s)){V.value=s,Y.value=`选择目标站点 — ${s.label||s.methodName}`;try{T.value=await Bt()}catch($){Q.error(`加载站点列表失败:${$.message}`);return}M.value=!0;return}p.value=s.methodName;try{await Ut(t,f,s)&&await ye()}finally{p.value=null}}}async function be(s){const t=Number(l.selection?.id);if(Number.isFinite(t)){p.value=V.value?.methodName??"goto";try{await Dt(t,s)&&await ye()}finally{p.value=null,V.value=null}}}async function Te(){const s=await Rt();M.value=!1,s!=null&&await be(s)}let we=0;return Ie(()=>[Me(l.selection),l.refreshKey],()=>{const s=++we;(async()=>await ye())()},{immediate:!0}),(s,t)=>{const f=xe,$=Ce;return o(),i("div",Kt,[h.selection?(o(),i("div",jt,[b.value?(o(),i("div",qt,[_(f,{class:"is-loading"},{default:C(()=>[_(de(Oe))]),_:1}),t[2]||(t[2]=e("span",null,"加载中…",-1))])):A.value==="site"?(o(),i(D,{key:1},[e("section",Xt,[e("div",Ht,[e("span",Gt,"#"+u(q.value),1),t[3]||(t[3]=e("span",{class:"type-tag"},"站点",-1))]),e("div",Yt,u(K.value.name),1)]),e("section",Zt,[t[7]||(t[7]=e("header",{class:"card-hd"},[e("span",null,"位置")],-1)),e("div",Jt,[e("div",Qt,[t[4]||(t[4]=e("span",{class:"k"},"X",-1)),e("span",en,u(K.value.x),1)]),e("div",tn,[t[5]||(t[5]=e("span",{class:"k"},"Y",-1)),e("span",nn,u(K.value.y),1)]),e("div",sn,[t[6]||(t[6]=e("span",{class:"k"},"Z",-1)),e("span",an,u(K.value.z),1)])])]),r.value.length?(o(),i("section",ln,[e("header",on,[t[8]||(t[8]=e("span",null,"状态",-1)),e("span",rn,u(r.value.length),1)]),e("div",cn,[(o(!0),i(D,null,Z(r.value,c=>(o(),i("div",{key:c.key,class:"kv-row"},[e("span",un,u(c.key),1),e("span",{class:"v",title:c.value},u(c.value),9,dn)]))),128))])])):H("",!0),ae.value.length?(o(),i("section",vn,[t[9]||(t[9]=e("header",{class:"card-hd"},[e("span",null,"操作")],-1)),e("div",fn,[(o(!0),i(D,null,Z(ae.value,c=>(o(),i("button",{key:c.methodName,type:"button",class:"action-btn",disabled:p.value===c.methodName,onClick:_e=>ge(c)},u(c.label||c.methodName),9,mn))),128))])])):H("",!0)],64)):A.value==="vehicle"?(o(),i(D,{key:2},[e("section",pn,[e("div",_n,[e("span",hn,u(le.value.displayId),1),_($,{size:"small",type:n.value,effect:"dark"},{default:C(()=>[J(u(le.value.stateLabel),1)]),_:1},8,["type"])]),e("div",kn,u(le.value.name),1),le.value.typeShort?(o(),i("div",yn,u(le.value.typeShort),1)):H("",!0)]),r.value.length?(o(),i("section",gn,[e("header",bn,[t[10]||(t[10]=e("span",null,"状态",-1)),e("span",wn,u(r.value.length),1)]),e("div",$n,[(o(!0),i(D,null,Z(r.value,c=>(o(),i("div",{key:c.key,class:ie(["kv-row",{"is-warn":c.warn}])},[e("span",Sn,u(c.key),1),e("span",{class:"v",title:c.value},u(c.value),9,Cn)],2))),128))])])):H("",!0),L.value.length?(o(),i("section",In,[e("header",Nn,[t[11]||(t[11]=e("span",null,"属性",-1)),e("span",xn,u(L.value.length),1)]),e("div",Mn,[(o(!0),i(D,null,Z(L.value,c=>(o(),i("div",{key:c.key,class:"kv-row"},[e("span",En,u(c.key),1),e("span",{class:"v",title:c.value},u(c.value),9,Tn)]))),128))])])):H("",!0),e("section",An,[e("header",Ln,[t[12]||(t[12]=e("span",null,"动作",-1)),z.value.length?(o(),i("span",Vn,u(z.value.length),1)):H("",!0)]),d.value?(o(),i("div",zn,"加载动作…")):z.value.length?(o(),i("div",Pn,[(o(!0),i(D,null,Z(z.value,c=>(o(),i("button",{key:c.methodName,type:"button",class:ie(["action-btn",{"action-btn--goto":de($e)(c)}]),disabled:p.value===c.methodName,onClick:_e=>ge(c)},u(c.label||c.methodName),11,On))),128))])):(o(),i("div",Fn,u(ce.value),1))])],64)):A.value==="track"?(o(),i(D,{key:3},[e("section",Bn,[e("div",Rn,[e("span",Dn,"#"+u(q.value),1),t[13]||(t[13]=e("span",{class:"type-tag"},"路径",-1))]),e("div",Un,u(me.value.name),1)]),r.value.length||pe.value.length?(o(),i("section",Kn,[t[14]||(t[14]=e("header",{class:"card-hd"},[e("span",null,"信息")],-1)),e("div",Wn,[(o(!0),i(D,null,Z(pe.value,c=>(o(),i("div",{key:c.key,class:"kv-row"},[e("span",jn,u(c.label),1),e("span",qn,u(c.value),1)]))),128)),(o(!0),i(D,null,Z(r.value,c=>(o(),i("div",{key:"s-"+c.key,class:"kv-row"},[e("span",Xn,u(c.key),1),e("span",Hn,u(c.value),1)]))),128))])])):H("",!0),ne.value.length?(o(),i("section",Gn,[t[15]||(t[15]=e("header",{class:"card-hd"},[e("span",null,"动作")],-1)),e("div",Yn,[(o(!0),i(D,null,Z(ne.value,c=>(o(),i("button",{key:c.methodName,type:"button",class:"action-btn",disabled:p.value===c.methodName,onClick:_e=>ge(c)},u(c.label||c.methodName),9,Zn))),128))])])):H("",!0)],64)):(o(),i("div",Jn,"该类型暂不支持监控详情展示。"))])):(o(),i("div",Wt,[...t[1]||(t[1]=[e("span",{class:"empty-title"},"未选中对象",-1),e("span",{class:"empty-desc"},"在 3D 画布或车辆列表中点击以查看信息。",-1)])])),_(Ft,{modelValue:M.value,"onUpdate:modelValue":t[0]||(t[0]=c=>M.value=c),title:Y.value,sites:T.value,onConfirm:be,onPickOnMap:Te},null,8,["modelValue","title","sites"])])}}}),es=fe(Qn,[["__scopeId","data-v-3316dec5"]]),ts={class:"fac-header"},ns={class:"fac-title"},ss={class:"fac-time"},as={class:"fac-body"},ls={class:"fac-info"},os={class:"fac-coord"},is={key:0},rs={key:1,class:"muted"},cs={class:"fac-actions"},us=ve({__name:"FloatingAlarmCard",props:{alarm:{},initialOffset:{}},emits:["close","ack","snooze","locate"],setup(h,{emit:N}){const l=h,b=N,I=g(null),d=g(!1),p=g({right:l.initialOffset?.right??24,bottom:l.initialOffset?.bottom??24}),V=S(()=>typeof l.alarm.x=="number"&&Number.isFinite(l.alarm.x)),F=S(()=>{const E=(l.alarm.info||"").toLowerCase();return E.includes("critical")||E.includes("严重")||E.includes("紧急")?"critical":E.includes("error")||E.includes("故障")?"error":E.includes("warn")||E.includes("告警")?"warn":"info"}),O=S(()=>{try{return new Date(l.alarm.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return""}}),G=S(()=>({left:p.value.left!==void 0?`${p.value.left}px`:void 0,top:p.value.top!==void 0?`${p.value.top}px`:void 0,right:p.value.right!==void 0?`${p.value.right}px`:void 0,bottom:p.value.bottom!==void 0?`${p.value.bottom}px`:void 0}));let B=0,P=0,x=0,v=0;function j(E){if(!I.value)return;const A=I.value.getBoundingClientRect();x=A.left,v=A.top,B=E.clientX,P=E.clientY,d.value=!0,window.addEventListener("mousemove",U),window.addEventListener("mouseup",R)}function U(E){p.value={left:x+(E.clientX-B),top:v+(E.clientY-P)}}function R(){d.value=!1,window.removeEventListener("mousemove",U),window.removeEventListener("mouseup",R)}Be(()=>{window.removeEventListener("mousemove",U),window.removeEventListener("mouseup",R)});function M(){b("close")}function T(){b("ack")}function Y(){b("snooze")}function se(){b("locate",l.alarm)}return(E,A)=>{const q=xe,ee=ke;return o(),i("div",{ref_key:"cardRef",ref:I,class:ie(["floating-alarm-card",[`lvl-${F.value}`,{dragging:d.value}]]),style:Re(G.value),onMousedown:he(j,["stop"])},[e("div",ts,[A[0]||(A[0]=e("span",{class:"fac-dot"},null,-1)),e("span",ns,u(h.alarm.carName)+" #"+u(h.alarm.carId),1),e("span",ss,u(O.value),1),_(q,{class:"fac-close",onClick:he(M,["stop"])},{default:C(()=>[_(de(De))]),_:1})]),e("div",as,[e("div",ls,u(h.alarm.info),1),e("div",os,[V.value?(o(),i("span",is,"坐标 ("+u(h.alarm.x?.toFixed(0))+", "+u(h.alarm.y?.toFixed(0))+") mm",1)):(o(),i("span",rs,"无坐标"))])]),e("div",cs,[_(ee,{size:"small",plain:"",disabled:!V.value,onClick:he(se,["stop"])},{default:C(()=>[...A[1]||(A[1]=[J("定位",-1)])]),_:1},8,["disabled"]),_(ee,{size:"small",plain:"",onClick:he(T,["stop"])},{default:C(()=>[...A[2]||(A[2]=[J("确认",-1)])]),_:1}),_(ee,{size:"small",plain:"",onClick:he(Y,["stop"])},{default:C(()=>[...A[3]||(A[3]=[J("稍后",-1)])]),_:1})])],38)}}}),ds=fe(us,[["__scopeId","data-v-0b6ee97c"]]),vs={class:"floating-alarm-stack"},fs=ve({__name:"FloatingAlarmStack",props:{alarms:{}},emits:["locate","ack"],setup(h,{emit:N}){const l=h,b=N,I=g(new Set),d=g(new Set);function p(v){return`${v.carId}`}const V=S(()=>l.alarms.filter(v=>v.action!=="clear").filter(v=>!I.value.has(p(v))).filter(v=>!d.value.has(p(v)))),F=S(()=>l.alarms.filter(v=>d.value.has(p(v))));function O(v){I.value=new Set([...I.value,p(v)])}function G(v){I.value=new Set([...I.value,p(v)]),b("ack",v)}function B(v){d.value=new Set([...d.value,p(v)])}function P(v){b("locate",v)}function x(){d.value=new Set}return(v,j)=>{const U=ke,R=Ue;return o(),i("div",vs,[(o(!0),i(D,null,Z(V.value,(M,T)=>(o(),Ne(ds,{key:`${M.carId}-${M.timestamp}`,alarm:M,"initial-offset":{right:24,bottom:24+T*132},onClose:Y=>O(M),onAck:Y=>G(M),onSnooze:Y=>B(M),onLocate:P},null,8,["alarm","initial-offset","onClose","onAck","onSnooze"]))),128)),F.value.length?(o(),i("div",{key:0,class:"snooze-tray",onClick:x},[_(R,{value:F.value.length,type:"warning"},{default:C(()=>[_(U,{size:"small",circle:""},{default:C(()=>[...j[0]||(j[0]=[J("≡",-1)])]),_:1})]),_:1},8,["value"])])):H("",!0)])}}}),ms=fe(fs,[["__scopeId","data-v-c37fdeb1"]]),ps={class:"map-monitor-page"},_s={class:"muted"},hs={class:"canvas-with-alarms"},ks=ve({__name:"MapMonitorView",setup(h){const N=Ke(),l="localhost:8223",b=g([]),I=g([]),d=g(null),p=g(0),V=g(!1),F=g(null),O=g([]);async function G(n){const r=Number(n.carId);if(!Number.isFinite(r)){Q.warning(`报警车辆 id 无法解析:${n.carId}`);return}try{await oe.setSelection("car",r),d.value={kind:"vehicle",id:String(r),name:n.carName??String(n.carId)}}catch(y){Q.error(`定位失败:${y.message}`)}}function B(n){}let P=null;const x=S(()=>b.value.filter(n=>n.state!=="offline").length),v=S(()=>I.value.filter(n=>n.status==="running").length),j=S(()=>I.value.filter(n=>n.status==="queued").length),U=S(()=>{if(!d.value||d.value.kind!=="vehicle")return null;const n=d.value;return b.value.find(y=>y.id===n.id||te(y)===n.id)?.id??null});function R(n){}const M=/^(?:UI)?(?:Car|Vehicle)-(\d+)$/i,T=/^UISite-(\d+)$/i,Y=/^(?:UITrack|UICircularArcTrack|UIBezierTrack|UINurbsTrack)-(\d+)$/i;function se(n){const r=M.exec(n);if(r)return{kind:"vehicle",id:r[1]};const y=T.exec(n);if(y)return{kind:"site",id:y[1]};const L=Y.exec(n);if(L)return{kind:"track",id:L[1]};const X=/^UI([A-Za-z]+)-(\d+)$/.exec(n)??/^([A-Za-z]+)-(\d+)$/.exec(n);if(!X)return null;const W=X[1].toLowerCase(),z=X[2];return W==="site"?{kind:"site",id:z}:W==="car"||W==="vehicle"?{kind:"vehicle",id:z}:W.includes("track")?{kind:"track",id:z}:null}function E(n,r){return!n&&!r?!0:!n||!r?!1:n.kind===r.kind&&n.id===r.id}function A(n,r){let y;if(n.kind==="vehicle"){const L=(r?ae(r):void 0)??b.value.find(X=>te(X)===n.id);y=L?{kind:"vehicle",id:te(L),name:L.name}:{kind:"vehicle",id:n.id,name:`Vehicle ${n.id}`}}else y={kind:n.kind,id:n.id,name:r||`${n.kind==="site"?"Site":"Track"} ${n.id}`};E(d.value,y)||(d.value=y,p.value++)}function q(n,r,y){if(n==="car"){const z=String(r),ce=y?.find(ue=>M.test(ue))??`Car-${r}`,me=ae(ce)??b.value.find(ue=>te(ue)===z||ue.id===z),pe=me?{kind:"vehicle",id:te(me),name:me.name}:{kind:"vehicle",id:z,name:`Vehicle ${z}`};E(d.value,pe)||(d.value=pe,p.value++);return}const L=String(r),X=y?.find(z=>{const ce=se(z);return ce?.kind===n&&ce.id===L}),W={kind:n,id:L,name:X||`${n==="site"?"Site":"Track"} ${L}`};E(d.value,W)||(d.value=W,p.value++)}function ee(n){const r=n.siteIds?.length??0,y=n.trackIds?.length??0,L=n.carIds?.length??0,X=Array.isArray(n.names)?n.names.length:0;if(r+y+L+X===0){d.value=null,p.value++;return}if(Array.isArray(n.names))for(const W of n.names){const z=se(W);if(z){A(z,W);return}}if(n.kind&&n.id){q(n.kind,n.id,n.names);return}if(r>0){q("site",n.siteIds[0],n.names);return}if(y>0){q("track",n.trackIds[0],n.names);return}L>0&&q("car",n.carIds[0],n.names)}function a(n){if(!n.length){w();return}for(const r of n){const y=se(r);if(y){A(y,r);return}}w()}function m(){w()}async function w(){try{const n=await oe.getSelection();if(!n?.kind||n.id==null||n.kind!=="car"&&n.kind!=="site"&&n.kind!=="track")return;q(n.kind,Number(n.id),n.name?[n.name]:void 0)}catch{}}async function K(n){E(d.value,n)||(d.value=n,p.value++);const r=Number(n.id);if(Number.isFinite(r))try{await oe.setSelection("car",r)}catch(y){Q.error(`同步 3D 选中失败:${y.message}`)}}function ae(n){const r=ne(n);return b.value.find(y=>y.name===n||y.id===n||r!=null&&te(y)===r)}function ne(n){return/^(?:UI)?(?:Car|Vehicle)-(\d+)$/i.exec(n)?.[1]??null}function te(n){return n.rawId!=null?String(n.rawId):n.id.replace(/^C/i,"").replace(/^0+/,"")||n.id}async function k(){V.value=!0;try{b.value=await Qe(),I.value=await et()}catch(n){console.warn("[MapMonitor] refreshAll failed",n)}finally{p.value++,V.value=!1}}const re=tt({autoConnect:!0});function le(n){if(n?.kind)switch(n.kind){case"alarm":{const r=n.payload;if(!r)return;O.value=[r,...O.value.filter(y=>y.carId!==r.carId)].slice(0,30);break}case"car-state":case"mission-status":k();break;case"selection-detail":n.payload&&typeof n.payload=="object"&&ee(n.payload);break;case"monitor-config-updated":p.value++;break}}return re.on(le),We(async()=>{await k(),P=setInterval(()=>{(!re.connected.value||b.value.length===0)&&k()},3e3)}),je(()=>{P&&clearInterval(P),re.off(le)}),(n,r)=>{const y=He,L=Xe,X=qe,W=ke,z=Ge;return o(),i("div",ps,[_(X,{gutter:12,class:"kpi-row"},{default:C(()=>[_(L,{span:8},{default:C(()=>[_(y,{title:"在线车辆",value:x.value},{suffix:C(()=>[e("span",_s,"/ "+u(b.value.length),1)]),_:1},8,["value"])]),_:1}),_(L,{span:8},{default:C(()=>[_(y,{title:"运行中任务",value:v.value},null,8,["value"])]),_:1}),_(L,{span:8},{default:C(()=>[_(y,{title:"排队任务",value:j.value},null,8,["value"])]),_:1})]),_:1}),_(X,{gutter:12,class:"main-row"},{default:C(()=>[_(L,{span:16},{default:C(()=>[e("div",hs,[_(Ye,{ref_key:"workspaceRef",ref:F,host:de(l),scope:de(N).scope??"Platform",token:de(N).token??"","read-only":!1,"embed-ui":!0,onPick:R,onSelect:a,onReady:m},null,8,["host","scope","token"]),_(ms,{alarms:O.value,onLocate:G,onAck:B},null,8,["alarms"]),_(Je)])]),_:1}),_(L,{span:8,class:"side-col"},{default:C(()=>[_(z,{shadow:"never",class:"side-card workbench-card"},{header:C(()=>[r[1]||(r[1]=e("span",null,"车辆监控台",-1)),_(W,{link:"",type:"primary",size:"small",loading:V.value,onClick:k},{default:C(()=>[...r[0]||(r[0]=[J(" 刷新 ",-1)])]),_:1},8,["loading"])]),default:C(()=>[_(Et,{cars:b.value,missions:I.value,"selected-id":U.value,onSelect:K},null,8,["cars","missions","selected-id"])]),_:1}),_(z,{shadow:"never",class:"side-card detail-card"},{header:C(()=>[...r[2]||(r[2]=[e("span",null,"选中信息",-1)])]),default:C(()=>[_(es,{selection:d.value,"refresh-key":p.value,cars:b.value,missions:I.value},null,8,["selection","refresh-key","cars","missions"])]),_:1})]),_:1})]),_:1})])}}}),Ws=fe(ks,[["__scopeId","data-v-f1d93793"]]);export{Ws as default};