import{aI as Ae,aE as U,aH as a,r as Xe,bJ as l,I as wa,aB as r,ag as ut,b9 as _,aG as y,K as ka,J as ha,bq as T,ak as Ne,a3 as xa,ai as de,bj as we,aC as ee,b3 as Se,aD as X,bI as fe,ac as Sa,bh as A,a9 as _a,Q as dt,bt as D,aV as _t,aZ as rt,Z as Va,R as ct,E as pt,N as Ft,O as Tt,S as It,z as Et,a8 as zt,aa as mt,ab as ft,ax as ne,ad as Pt,a4 as Ca,bg as Je,G as Mt,ah as $a,bu as Aa,a1 as Ut,a0 as Lt,x as Na,T as Bt,y as Fa,bx as yt,X as F,b6 as Dt,b4 as Rt,aF as Ta,b2 as Ia,b7 as jt,bv as Ea,b8 as za,bw as Pa,Y}from"./index-Dg4NaXsE.js";/* empty css *//* empty css *//* empty css *//* empty css */import"./el-tooltip-l0sNRNKZ.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{W as Ma}from"./Workspace3D-DpUfTJl7.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{h as Re,a as je,r as J,n as Ua}from"./reflection-B_glb6eT.js";/* empty css *//* empty css *//* empty css *//* empty css */import{m as j,a as st,b as it}from"./mapEdit-TNAQr3Be.js";import{u as La}from"./useMapEditStream-BgR6WvRg.js";import"./useProjectionStream-BBHmpNXC.js";const Ba={class:"edit-top-bar"},Da=Ae({__name:"EditTopBar",props:{canUndo:{type:Boolean},canRedo:{type:Boolean},saving:{type:Boolean},viewFilter:{}},emits:["cmd"],setup(n,{emit:N}){const g=N;function f(C){g("cmd",C)}function h(C){return C?"☑":"☐"}return(C,i)=>{const k=Xe,u=ha,z=ka,$=wa,p=ut;return _(),U("div",Ba,[a(k,{type:"primary",class:"topbar-save-btn",loading:n.saving,onClick:i[0]||(i[0]=m=>f("project.save"))},{default:l(()=>[...i[3]||(i[3]=[y(" 保存 ",-1)])]),_:1},8,["loading"]),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,null,{default:l(()=>[a(u,{command:"file.import.dwg"},{default:l(()=>[...i[5]||(i[5]=[y("导入 .dwg/.dxf",-1)])]),_:1}),a(u,{command:"file.import.geojson"},{default:l(()=>[...i[6]||(i[6]=[y("导入 .geojson",-1)])]),_:1}),a(u,{command:"file.upload.image",divided:""},{default:l(()=>[...i[7]||(i[7]=[y("导入图片",-1)])]),_:1}),a(u,{command:"file.upload.model"},{default:l(()=>[...i[8]||(i[8]=[y("导入 CycleGUI 模型",-1)])]),_:1}),a(u,{command:"file.export.png",divided:""},{default:l(()=>[...i[9]||(i[9]=[y("导出 PNG",-1)])]),_:1}),a(u,{command:"file.export.svg"},{default:l(()=>[...i[10]||(i[10]=[y("导出 SVG",-1)])]),_:1}),a(u,{command:"file.export.json"},{default:l(()=>[...i[11]||(i[11]=[y("导出 JSON",-1)])]),_:1})]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[4]||(i[4]=[y("导入",-1)])]),_:1})]),_:1}),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,null,{default:l(()=>[a(u,{command:"edit.cut"},{default:l(()=>[...i[13]||(i[13]=[y("剪切 (Ctrl+X)",-1)])]),_:1}),a(u,{command:"edit.copy"},{default:l(()=>[...i[14]||(i[14]=[y("复制 (Ctrl+C)",-1)])]),_:1}),a(u,{command:"edit.paste"},{default:l(()=>[...i[15]||(i[15]=[y("粘贴 (Ctrl+V)",-1)])]),_:1}),a(u,{command:"edit.delete"},{default:l(()=>[...i[16]||(i[16]=[y("删除 (Del)",-1)])]),_:1}),a(u,{command:"edit.selectAll",divided:""},{default:l(()=>[...i[17]||(i[17]=[y("全选",-1)])]),_:1}),a(u,{command:"edit.invert"},{default:l(()=>[...i[18]||(i[18]=[y("反选",-1)])]),_:1})]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[12]||(i[12]=[y("编辑",-1)])]),_:1})]),_:1}),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,null,{default:l(()=>[a(u,{command:"edit.undo",disabled:!n.canUndo},{default:l(()=>[...i[20]||(i[20]=[y("撤销 (Ctrl+Z)",-1)])]),_:1},8,["disabled"]),a(u,{command:"edit.redo",disabled:!n.canRedo},{default:l(()=>[...i[21]||(i[21]=[y("重做 (Ctrl+Y)",-1)])]),_:1},8,["disabled"])]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[19]||(i[19]=[y("撤销",-1)])]),_:1})]),_:1}),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,null,{default:l(()=>[a(u,{command:"view.fitAll"},{default:l(()=>[...i[23]||(i[23]=[y("缩放至全屏",-1)])]),_:1}),a(u,{command:"view.fitSelection"},{default:l(()=>[...i[24]||(i[24]=[y("缩放至选中",-1)])]),_:1}),a(u,{command:"view.toggleGrid",divided:""},{default:l(()=>[...i[25]||(i[25]=[y("显示网格",-1)])]),_:1}),a(u,{command:"view.toggleScale"},{default:l(()=>[...i[26]||(i[26]=[y("显示比例尺",-1)])]),_:1}),a(u,{command:"view.toggle2D"},{default:l(()=>[...i[27]||(i[27]=[y("切换 2D / 3D",-1)])]),_:1})]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[22]||(i[22]=[y("视图",-1)])]),_:1})]),_:1}),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,null,{default:l(()=>[a(u,{command:"layer.new"},{default:l(()=>[...i[29]||(i[29]=[y("新建图层…",-1)])]),_:1}),a(u,{command:"layer.toggleVisibility"},{default:l(()=>[...i[30]||(i[30]=[y("切换显示图层…",-1)])]),_:1})]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[28]||(i[28]=[y("图层",-1)])]),_:1})]),_:1}),a($,{trigger:"click",onCommand:f},{dropdown:l(()=>[a(z,{class:"topbar-filter-menu"},{default:l(()=>[a(u,{disabled:"",class:"topbar-filter-header"},{default:l(()=>[...i[32]||(i[32]=[y("选择(可拾取)",-1)])]),_:1}),a(u,{command:"view.select.sites"},{default:l(()=>[y(T(h(n.viewFilter.selectFilter.sites))+" 站点",1)]),_:1}),a(u,{command:"view.select.tracks"},{default:l(()=>[y(T(h(n.viewFilter.selectFilter.tracks))+" 路径",1)]),_:1}),a(u,{command:"view.select.cars"},{default:l(()=>[y(T(h(n.viewFilter.selectFilter.cars))+" AGV",1)]),_:1}),a(u,{command:"view.select.decor"},{default:l(()=>[y(T(h(n.viewFilter.selectFilter.decor))+" 区域 / 装饰",1)]),_:1}),a(u,{divided:"",disabled:"",class:"topbar-filter-header"},{default:l(()=>[...i[33]||(i[33]=[y("对齐(鼠标吸附)",-1)])]),_:1}),a(u,{command:"view.snap.sites"},{default:l(()=>[y(T(h(n.viewFilter.alignSnap.sites))+" 吸附站点",1)]),_:1}),a(u,{command:"view.snap.cars"},{default:l(()=>[y(T(h(n.viewFilter.alignSnap.cars))+" 吸附 AGV",1)]),_:1}),a(u,{command:"view.snap.tracks"},{default:l(()=>[y(T(h(n.viewFilter.alignSnap.tracks))+" 吸附路径",1)]),_:1}),a(u,{divided:"",disabled:"",class:"topbar-filter-header"},{default:l(()=>[...i[34]||(i[34]=[y("显示内容",-1)])]),_:1}),a(u,{command:"view.show.sceneLabels"},{default:l(()=>[y(T(h(n.viewFilter.showViewport.sceneLabels))+" 场景图元标记",1)]),_:1}),a(u,{command:"view.show.scenePrimitives"},{default:l(()=>[y(T(h(n.viewFilter.showViewport.scenePrimitives))+" 场景图元",1)]),_:1}),a(u,{command:"view.show.cars"},{default:l(()=>[y(T(h(n.viewFilter.showViewport.cars))+" 车辆",1)]),_:1})]),_:1})]),default:l(()=>[a(k,{text:"",class:"topbar-btn"},{default:l(()=>[...i[31]||(i[31]=[y("过滤",-1)])]),_:1})]),_:1}),i[37]||(i[37]=r("div",{class:"spacer"},null,-1)),a(p,{content:"撤销 (Ctrl+Z)",placement:"bottom"},{default:l(()=>[a(k,{size:"small",disabled:!n.canUndo,class:"topbar-icon-btn",onClick:i[1]||(i[1]=m=>f("edit.undo"))},{default:l(()=>[...i[35]||(i[35]=[y("↶",-1)])]),_:1},8,["disabled"])]),_:1}),a(p,{content:"重做 (Ctrl+Y)",placement:"bottom"},{default:l(()=>[a(k,{size:"small",disabled:!n.canRedo,class:"topbar-icon-btn",onClick:i[2]||(i[2]=m=>f("edit.redo"))},{default:l(()=>[...i[36]||(i[36]=[y("↷",-1)])]),_:1},8,["disabled"])]),_:1})])}}}),Ra=Ne(Da,[["__scopeId","data-v-1082d582"]]),ja={class:"edit-tool-rail"},Oa={class:"rail-group-title"},Ya={class:"rail-group-text"},Ka={class:"rail-group-list"},Ha=["onClick"],Xa={class:"rail-btn-glyph"},Wa={class:"rail-btn-label"},Ga={key:0,class:"rail-divider"},qa={class:"rail-group rail-group-ai"},Za=Ae({__name:"EditToolRail",props:{activeTool:{}},emits:["select-tool","open-ai"],setup(n,{emit:N}){const g=n,f=N,h=[{id:"select",title:"选择",tools:[{id:"select.single",label:"单选",glyph:"⌖",tip:"点击拾取单个对象"},{id:"select.rect",label:"矩形框选",glyph:"▱"},{id:"select.lasso",label:"套索圈选",glyph:"◯"},{id:"select.byType.site",label:"仅站点",glyph:"·"},{id:"select.byType.polyline",label:"仅折线",glyph:"╱",tip:"仅 UITrack(直线/折线)"},{id:"select.byType.bezier",label:"仅贝塞尔",glyph:"∽",tip:"仅 UIBezierTrack"},{id:"select.byType.arc",label:"仅弧形",glyph:"◜",tip:"仅 UICircularArcTrack"},{id:"select.byType.decor",label:"仅装饰",glyph:"★"},{id:"select.byType.currentLayer",label:"当前图层",glyph:"▤",tip:"保留当前图层对象"},{id:"select.invert",label:"反选",glyph:"⇄"},{id:"select.clear",label:"清空选中",glyph:"⊘"}]},{id:"draw",title:"绘制",tools:[{id:"draw.site",label:"添加站点",glyph:"+",tip:"点击工具后在画布单击放置"},{id:"draw.sites.continuous",label:"连续站点",glyph:"⁂",tip:"切换工具或 Esc 退出"},{id:"draw.track.polyline",label:"折线路径",glyph:"─",tip:"依序点击两端站点"},{id:"draw.track.bezier",label:"贝塞尔路径",glyph:"∼",tip:"点两端站点 → 弹框输入中间控制点个数 → 连续点选每个控制点"},{id:"draw.track.arc",label:"弧形路径",glyph:"◜",tip:"点两端站点 → 输入半径(≥ |AB|/2,等于即半圆)"},{id:"draw.decor.line",label:"装饰线段",glyph:"╱"},{id:"draw.decor.rect",label:"装饰矩形",glyph:"▭"},{id:"draw.decor.circle",label:"装饰圆",glyph:"◯"},{id:"draw.decor.text",label:"装饰文本",glyph:"T"},{id:"draw.image",label:"插入图片",glyph:"🖼"},{id:"draw.model",label:"插入模型",glyph:"◎",tip:"CycleGUI 3D 模型 (obj/glb/gltf)"}]},{id:"transform",title:"变换",tools:[{id:"transform.move",label:"移动",glyph:"✥"},{id:"transform.rotate",label:"旋转",glyph:"⟳"},{id:"transform.scale",label:"缩放",glyph:"⤡"},{id:"transform.duplicate",label:"复制副本",glyph:"⎘",tip:"Ctrl+D"},{id:"transform.copy",label:"复制",glyph:"📋",tip:"Ctrl+C"},{id:"transform.paste",label:"粘贴",glyph:"📥",tip:"Ctrl+V"},{id:"transform.delete",label:"删除",glyph:"🗑",tip:"Delete"},{id:"transform.copyFields",label:"复制字段",glyph:"⇉",tip:"多选时第 1 个为源,其余为目标"}]},{id:"align",title:"对齐",tools:[{id:"align.left",label:"左对齐",glyph:"⫷"},{id:"align.right",label:"右对齐",glyph:"⫸"},{id:"align.top",label:"上对齐",glyph:"⫵"},{id:"align.bottom",label:"下对齐",glyph:"⫶"},{id:"align.centerH",label:"水平居中",glyph:"⇔"},{id:"align.centerV",label:"垂直居中",glyph:"⇕"},{id:"align.center",label:"整体居中",glyph:"⊕"},{id:"align.distributeH",label:"水平等距",glyph:"⇿"},{id:"align.distributeV",label:"垂直等距",glyph:"⇳"},{id:"align.toFirst",label:"对齐到首",glyph:"⏮"},{id:"align.toLast",label:"对齐到尾",glyph:"⏭"}]},{id:"batch",title:"批量生成",tools:[{id:"batch.linearH",label:"横向间距",glyph:"⇢"},{id:"batch.linearV",label:"纵向间距",glyph:"⇣"},{id:"batch.matrix",label:"矩阵生成",glyph:"#"},{id:"batch.alongPath",label:"沿路径采样",glyph:"⤳",tip:"先选 1+ 条路径,再点本工具"},{id:"batch.circular",label:"环形阵列",glyph:"◌"}]},{id:"show",title:"显示",tools:[{id:"show.controlPoints",label:"控制点",glyph:"⊙"},{id:"show.controlHandles",label:"控制柄",glyph:"⊝"}]}];function C(k){return k===g.activeTool}function i(k){f("select-tool",k)}return(k,u)=>{const z=ut,$=xa;return _(),U("div",ja,[a($,{class:"rail-scroll"},{default:l(()=>[(_(),U(de,null,we(h,(p,m)=>r("div",{key:p.id,class:"rail-group"},[r("div",Oa,[u[1]||(u[1]=r("span",{class:"rail-group-bar"},null,-1)),r("span",Ya,T(p.title),1),u[2]||(u[2]=r("span",{class:"rail-group-bar"},null,-1))]),r("div",Ka,[(_(!0),U(de,null,we(p.tools,M=>(_(),ee(z,{key:M.id,content:M.tip??M.label,placement:"right","show-after":280},{default:l(()=>[r("button",{class:Se(["rail-btn",{"rail-btn--active":C(M.id)}]),onClick:I=>i(M.id)},[r("span",Xa,T(M.glyph),1),r("span",Wa,T(M.label),1)],10,Ha)]),_:2},1032,["content"]))),128))]),mf("open-ai"))},[...u[3]||(u[3]=[r("span",{class:"rail-btn-glyph"},"✦",-1),r("span",{class:"rail-btn-label"},"AI 生图",-1)])])])]),_:1})])}}}),Ja=Ne(Za,[["__scopeId","data-v-6b284dea"]]),Qa={class:"edit-property-panel"},el={key:0,class:"empty-hint"},tl={key:1,class:"loading-hint"},al={key:2,class:"object-pane"},ll={class:"prop-card prop-card--header"},nl={class:"prop-card-row"},ol={class:"prop-id-block"},sl={class:"prop-id-tag"},il={class:"prop-type-tag"},rl={class:"prop-header-actions"},ul=["disabled"],dl={class:"prop-delete-icon"},cl={class:"prop-card-row prop-name-row"},pl={class:"prop-card-row prop-layer-row"},ml={key:0,class:"prop-card prop-card--geom"},fl={class:"prop-card-header"},yl=["title"],vl={class:"prop-card-flag-text"},bl={class:"prop-card-meta"},gl={class:"prop-grid"},wl={class:"prop-field-label"},kl={key:0,class:"prop-field-unit"},hl={key:1,class:"prop-card prop-card--style"},xl={class:"prop-card-header"},Sl={class:"prop-card-meta"},_l={class:"prop-grid"},Vl={class:"prop-field-label"},Cl={class:"prop-card prop-card--custom"},$l={class:"prop-card-header"},Al={class:"prop-card-meta"},Nl={key:0,class:"prop-grid"},Fl=["title"],Tl={class:"prop-field-row"},Il=["onClick"],El={key:1,class:"prop-empty-row"},zl={key:2,class:"prop-card prop-card--status"},Pl={class:"prop-card-header"},Ml={class:"prop-card-meta"},Ul={class:"prop-status-list"},Ll={class:"prop-status-key"},Bl=["title"],Dl={key:3,class:"prop-card prop-card--actions"},Rl={class:"prop-card-header"},jl={class:"prop-card-meta"},Ol={class:"prop-actions"},Yl=["disabled","onClick"],Kl={key:0,class:"prop-action-spinner"},Hl={class:"prop-action-label"},Xl={class:"defaults-pane"},Wl={key:0,class:"empty-hint defaults-empty"},Gl={class:"prop-card prop-card--style"},ql={class:"prop-card-header"},Zl={class:"prop-card-flag-text"},Jl={class:"prop-card"},Ql={class:"prop-card prop-card--style"},en={class:"prop-card-header"},tn={class:"prop-card-flag-text"},an={class:"prop-card"},ln={key:3,class:"loading-hint"},nn=Ae({__name:"EditPropertyPanel",props:{selectionCount:{},primary:{},fields:{},status:{},methods:{},loading:{type:Boolean},layers:{},defaults:{},layerRows:{},selectionKind:{},viewportStyle:{},viewportStyleLoading:{type:Boolean},viewportSyncing:{type:Boolean}},emits:["rename","change-layer","set-field","add-field","exec-action","save-defaults","layer-toggle","add-layer","delete","patch-viewport"],setup(n,{emit:N}){const g=n,f=N,h=A("object"),C=A(!1);let i=null;const k=A(null),u=A(null);fe(()=>g.viewportStyle,b=>{if(!b){k.value=null,u.value=null;return}k.value={...b.site},u.value={...b.track}},{immediate:!0,deep:!0}),fe(()=>g.selectionKind,b=>{(b==="site"||b==="track")&&(h.value="defaults")});function z(){C.value=!0,i&&clearTimeout(i),i=setTimeout(()=>{C.value=!1},1400)}fe(()=>g.viewportSyncing,(b,d)=>{d&&!b&&z()});function $(b){k.value&&(k.value={...k.value,...b},f("patch-viewport",{site:{...k.value}}))}function p(b){u.value&&(u.value={...u.value,...b},f("patch-viewport",{track:{...u.value}}))}const m=A(null),M=A(""),I=A(!1),v=A(!1);let q=null;function Q(){v.value=!0,q&&clearTimeout(q),q=setTimeout(()=>{v.value=!1},1200)}const ye=new Set(["id","name","layerName"]),W=new Set(["x","y","z","cx","cy","cz","dx","dy","dz","sx","sy","ex","ey","startX","startY","endX","endY","size","width","height","depth","angle","rotation","theta","scale","radius","r","siteA","siteB"]),ve=new Set(["color","displaySetting","direction","typeInfo","mustFree","imagePath","modelPath","fontFamily","fontSize","textColor","lineWidth","opacity"]),O={x:"X",y:"Y",z:"Z",size:"大小",width:"宽",height:"高",depth:"厚",angle:"角度",rotation:"旋转",theta:"θ",scale:"缩放",radius:"半径",siteA:"起点站",siteB:"终点站",startX:"起点 X",startY:"起点 Y",endX:"终点 X",endY:"终点 Y",cx:"中心 X",cy:"中心 Y",color:"颜色",displaySetting:"显示设置",direction:"方向",typeInfo:"类型信息",mustFree:"必须互斥",imagePath:"图片路径",modelPath:"模型路径",fontSize:"字号",textColor:"文字色",lineWidth:"线宽",opacity:"透明度"},se={x:"mm",y:"mm",z:"mm",cx:"mm",cy:"mm",cz:"mm",dx:"mm",dy:"mm",dz:"mm",startX:"mm",startY:"mm",endX:"mm",endY:"mm",width:"mm",height:"mm",depth:"mm",size:"mm",radius:"mm",angle:"°",rotation:"°",theta:"°",fontSize:"px",lineWidth:"px"},ie=ne(()=>g.fields.filter(b=>!ye.has(b.key))),te=ne(()=>ie.value.filter(b=>W.has(b.key))),x=ne(()=>ie.value.filter(b=>ve.has(b.key))),V=ne(()=>ie.value.filter(b=>!W.has(b.key)&&!ve.has(b.key)));function G(b){return O[b]??b}function oe(b){return se[b]??""}function ke(b){if(b==null||b==="")return;const d=Number(b);return Number.isFinite(d)?d:void 0}function re(b){return b.toLowerCase().includes("angle")||b.toLowerCase().includes("rotation")||b==="theta"?1:b==="scale"||b==="opacity"?.1:10}function ce(b){return W.has(b)}function _e(b,d){return b==="color"||b==="textColor"?!0:/^#[0-9a-fA-F]{3,8}$/.test(d)}function B(b,d){return d==="true"||d==="false"||d==="True"||d==="False"}function K(b){return b==="true"||b==="True"||b==="1"}const Z=ne(()=>{const b=(g.primary?.status??"").toLowerCase();return b?b.includes("error")||b.includes("alarm")||b.includes("failed")?"danger":b.includes("warn")||b.includes("idle")?"warning":b.includes("online")||b.includes("running")||b.includes("ready")||b.includes("ok")?"success":"info":"info"}),he=A("");fe(()=>g.primary?.name??"",b=>{he.value=b},{immediate:!0});function Qe(){Oe()}function Oe(){if(!g.primary)return;const b=he.value;b!==(g.primary.name??"")&&f("rename",b)}function Fe(b){f("change-layer",b)}function ae(b,d){f("set-field",b,d),W.has(b)&&Q()}function Ye(){f("add-field")}async function We(b){try{m.value=b,f("exec-action",b)}finally{m.value=null}}function Te(){f("save-defaults")}function Ie(b){f("layer-toggle",b)}function xe(){const b=M.value.trim();b&&(f("add-layer",b),M.value="")}function Ee(){g.selectionCount===0||I.value||(I.value=!0,f("delete"),setTimeout(()=>{I.value=!1},600))}return(b,d)=>{const ze=dt,ue=Pt,Pe=ut,be=ct,Ge=Va,Me=Ca,pe=It,ge=Et,Ue=zt,Le=_a,et=pt,H=Tt,Ve=Ft,Be=Xe,Ce=ft,qe=mt,tt=Sa;return _(),U("div",Qa,[a(tt,{modelValue:h.value,"onUpdate:modelValue":d[20]||(d[20]=c=>h.value=c),class:"prop-tabs"},{default:l(()=>[a(Le,{label:"对象",name:"object"},{default:l(()=>[n.selectionCount===0?(_(),U("div",el,[a(ze,{class:"empty-icon"},{default:l(()=>[a(D(_t))]),_:1}),d[21]||(d[21]=r("span",{class:"empty-title"},"未选中对象",-1)),d[22]||(d[22]=r("span",{class:"empty-desc"},"在画布上点击或框选以编辑属性。",-1))])):n.loading?(_(),U("div",tl,[a(ze,{class:"is-loading"},{default:l(()=>[a(D(rt))]),_:1}),d[23]||(d[23]=r("span",null,"加载属性…",-1))])):(_(),U("div",al,[r("section",ll,[r("div",nl,[r("div",ol,[r("span",sl,T(n.selectionCount>1?`多选 ${n.selectionCount}`:`#${n.primary?.id??"-"}`),1),r("span",il,T(n.primary?.typeName??"-"),1)]),r("div",rl,[n.primary?.status?(_(),ee(ue,{key:0,type:Z.value,size:"small",effect:"dark",class:"prop-status-tag"},{default:l(()=>[y(T(n.primary.status),1)]),_:1},8,["type"])):X("",!0),a(Pe,{content:n.selectionCount>1?`删除选中的 ${n.selectionCount} 个对象(可 Ctrl+Z 撤销)`:"删除该对象(可 Ctrl+Z 撤销)",placement:"top","show-after":220},{default:l(()=>[r("button",{type:"button",class:"prop-delete-btn",disabled:I.value,onClick:Ee},[r("span",dl,T(I.value?"⟳":"🗑"),1),d[24]||(d[24]=r("span",null,"删除",-1))],8,ul)]),_:1},8,["content"])])]),r("div",cl,[d[25]||(d[25]=r("label",{class:"prop-name-label"},"名称",-1)),n.primary?(_(),ee(be,{key:0,"model-value":he.value,size:"small",placeholder:"对象名","onUpdate:modelValue":d[0]||(d[0]=c=>he.value=c),onBlur:Qe,onChange:Oe},null,8,["model-value"])):X("",!0)]),r("div",pl,[d[26]||(d[26]=r("label",{class:"prop-name-label"},"图层",-1)),n.primary?(_(),ee(Me,{key:0,"model-value":n.primary.layer??"",size:"small",placeholder:"—",class:"prop-layer-select","onUpdate:modelValue":d[1]||(d[1]=c=>Fe(c))},{default:l(()=>[a(Ge,{label:"(无)",value:""}),(_(!0),U(de,null,we(n.layers,c=>(_(),ee(Ge,{key:c,label:c,value:c},null,8,["label","value"]))),128))]),_:1},8,["model-value"])):X("",!0)])]),te.value.length>0?(_(),U("section",ml,[r("header",fl,[d[28]||(d[28]=r("span",{class:"prop-card-title"},"位置 / 几何",-1)),r("span",{class:Se(["prop-card-flag",{"is-synced":v.value}]),title:v.value?"已同步到画布":"改动会立即同步到 SimpleLite 画布"},[d[27]||(d[27]=r("span",{class:"prop-card-flag-dot"},null,-1)),r("span",vl,T(v.value?"已同步":"同步到画布"),1)],10,yl),r("span",bl,T(te.value.length)+" 项",1)]),r("div",gl,[(_(!0),U(de,null,we(te.value,c=>(_(),U("div",{key:c.key,class:"prop-grid-item"},[r("label",wl,[y(T(G(c.key))+" ",1),oe(c.key)?(_(),U("span",kl,T(oe(c.key)),1)):X("",!0)]),ce(c.key)?(_(),ee(pe,{key:0,"model-value":ke(c.value),controls:!1,step:re(c.key),size:"small",class:"prop-field-num",onChange:R=>ae(c.key,R==null?"":String(R))},null,8,["model-value","step","onChange"])):(_(),ee(be,{key:1,"model-value":c.value,size:"small",spellcheck:"false",onChange:R=>ae(c.key,R)},null,8,["model-value","onChange"]))]))),128))])])):X("",!0),x.value.length>0?(_(),U("section",hl,[r("header",xl,[d[29]||(d[29]=r("span",{class:"prop-card-title"},"样式 / 外观",-1)),r("span",Sl,T(x.value.length)+" 项",1)]),r("div",_l,[(_(!0),U(de,null,we(x.value,c=>(_(),U("div",{key:c.key,class:"prop-grid-item"},[r("label",Vl,T(G(c.key)),1),_e(c.key,c.value)?(_(),ee(ge,{key:0,"model-value":c.value||"#ffffff","show-alpha":"",size:"small",onChange:R=>ae(c.key,R??"")},null,8,["model-value","onChange"])):B(c.key,c.value)?(_(),ee(Ue,{key:1,"model-value":K(c.value),size:"small",onChange:R=>ae(c.key,R?"true":"false")},null,8,["model-value","onChange"])):(_(),ee(be,{key:2,"model-value":c.value,size:"small",spellcheck:"false",onChange:R=>ae(c.key,R)},null,8,["model-value","onChange"]))]))),128))])])):X("",!0),r("section",Cl,[r("header",$l,[d[30]||(d[30]=r("span",{class:"prop-card-title"},"其它字段 / 自定义",-1)),r("span",Al,T(V.value.length)+" 项",1)]),V.value.length>0?(_(),U("div",Nl,[(_(!0),U(de,null,we(V.value,c=>(_(),U("div",{key:c.key,class:"prop-grid-item prop-grid-item--wide"},[r("label",{class:"prop-field-label",title:c.key},T(c.key),9,Fl),r("div",Tl,[a(be,{"model-value":c.value,size:"small",spellcheck:"false",onChange:R=>ae(c.key,R)},null,8,["model-value","onChange"]),a(Pe,{content:"删除该字段",placement:"top"},{default:l(()=>[r("button",{class:"prop-field-icon-btn",onClick:R=>ae(c.key,"")},"×",8,Il)]),_:2},1024)])]))),128))])):(_(),U("div",El,"无其它字段")),r("button",{class:"prop-add-field-btn",onClick:Ye},"+ 添加字段")]),n.status.length>0?(_(),U("section",zl,[r("header",Pl,[d[31]||(d[31]=r("span",{class:"prop-card-title"},"运行状态",-1)),r("span",Ml,T(n.status.length)+" 项",1)]),r("div",Ul,[(_(!0),U(de,null,we(n.status,c=>(_(),U("div",{key:c.key,class:"prop-status-item"},[r("span",Ll,T(c.key),1),r("span",{class:"prop-status-value",title:c.value},T(c.value),9,Bl)]))),128))])])):X("",!0),n.methods.length>0?(_(),U("section",Dl,[r("header",Rl,[d[32]||(d[32]=r("span",{class:"prop-card-title"},"操作",-1)),r("span",jl,T(n.methods.length)+" 项",1)]),r("div",Ol,[(_(!0),U(de,null,we(n.methods,c=>(_(),ee(Pe,{key:c.methodName,content:c.description||c.label||c.methodName,placement:"top","show-after":220},{default:l(()=>[r("button",{class:"prop-action-btn",disabled:m.value===c.methodName,onClick:R=>We(c.methodName)},[m.value===c.methodName?(_(),U("span",Kl,"⟳")):X("",!0),d[33]||(d[33]=r("span",{class:"prop-action-icon"},"▶",-1)),r("span",Hl,T(c.label||c.methodName),1)],8,Yl)]),_:2},1032,["content"]))),128))])])):X("",!0)]))]),_:1}),a(Le,{label:"类型默认",name:"defaults"},{default:l(()=>[r("div",Xl,[a(et,{type:"info",closable:!1,class:"defaults-alert"},{default:l(()=>[...d[34]||(d[34]=[y(" 视口样式与 SimpleLite「视口样式」对话框同步,修改后即时重绘画布;下方「新建默认」仅影响下次创建对象。 ",-1)])]),_:1}),n.selectionKind?n.selectionKind==="site"&&k.value?(_(),U(de,{key:1},[r("section",Gl,[r("header",ql,[d[38]||(d[38]=r("span",{class:"prop-card-title"},"站点视口样式",-1)),r("span",{class:Se(["prop-card-flag",{"is-synced":C.value}])},[d[37]||(d[37]=r("span",{class:"prop-card-flag-dot"},null,-1)),r("span",Zl,T(n.viewportSyncing?"同步中…":C.value?"已同步":"实时同步"),1)],2)]),a(Ve,{"label-width":"132px",size:"small",class:"defaults-form"},{default:l(()=>[a(H,{label:"整体大小倍率"},{default:l(()=>[a(pe,{"model-value":k.value.drawScale,min:.25,max:12,step:.1,controls:!0,"onUpdate:modelValue":d[2]||(d[2]=c=>$({drawScale:c??k.value.drawScale}))},null,8,["model-value"])]),_:1}),a(H,{label:"未选中圆点半径"},{default:l(()=>[a(pe,{"model-value":k.value.dotRadiusNormal,min:1,max:24,step:.5,"onUpdate:modelValue":d[3]||(d[3]=c=>$({dotRadiusNormal:c??k.value.dotRadiusNormal}))},null,8,["model-value"])]),_:1}),a(H,{label:"选中圆点半径"},{default:l(()=>[a(pe,{"model-value":k.value.dotRadiusSelected,min:1,max:32,step:.5,"onUpdate:modelValue":d[4]||(d[4]=c=>$({dotRadiusSelected:c??k.value.dotRadiusSelected}))},null,8,["model-value"])]),_:1}),a(H,{label:"选中环半径 (m)"},{default:l(()=>[a(pe,{"model-value":k.value.selectionRingM,min:.02,max:.8,step:.01,"onUpdate:modelValue":d[5]||(d[5]=c=>$({selectionRingM:c??k.value.selectionRingM}))},null,8,["model-value"])]),_:1}),a(H,{label:"站点颜色(未选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(k.value.colorNormalArgb),"onUpdate:modelValue":d[6]||(d[6]=c=>$({colorNormalArgb:D(Re)(c??"#ffffff")}))},null,8,["model-value"])]),_:1}),a(H,{label:"站点颜色(选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(k.value.colorSelectedArgb),"onUpdate:modelValue":d[7]||(d[7]=c=>$({colorSelectedArgb:D(Re)(c??"#ff0000")}))},null,8,["model-value"])]),_:1}),a(H,{label:"标签颜色(未选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(k.value.labelColorNormalArgb),"onUpdate:modelValue":d[8]||(d[8]=c=>$({labelColorNormalArgb:D(Re)(c??"#ffffff")}))},null,8,["model-value"])]),_:1}),a(H,{label:"标签颜色(选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(k.value.labelColorSelectedArgb),"onUpdate:modelValue":d[9]||(d[9]=c=>$({labelColorSelectedArgb:D(Re)(c??"#ff0000")}))},null,8,["model-value"])]),_:1})]),_:1})]),r("section",Jl,[d[40]||(d[40]=r("header",{class:"prop-card-header"},[r("span",{class:"prop-card-title"},"新建站点默认")],-1)),a(Ve,{"label-width":"132px",size:"small",class:"defaults-form"},{default:l(()=>[a(H,{label:"默认图层"},{default:l(()=>[a(be,{modelValue:n.defaults.site.layer,"onUpdate:modelValue":d[10]||(d[10]=c=>n.defaults.site.layer=c)},null,8,["modelValue"])]),_:1}),a(H,{label:"名字前缀"},{default:l(()=>[a(be,{modelValue:n.defaults.site.namePrefix,"onUpdate:modelValue":d[11]||(d[11]=c=>n.defaults.site.namePrefix=c)},null,8,["modelValue"])]),_:1}),a(Be,{size:"small",type:"primary",plain:"",onClick:Te},{default:l(()=>[...d[39]||(d[39]=[y("保存新建默认",-1)])]),_:1})]),_:1})])],64)):n.selectionKind==="track"&&u.value?(_(),U(de,{key:2},[r("section",Ql,[r("header",en,[d[42]||(d[42]=r("span",{class:"prop-card-title"},"路径视口样式",-1)),r("span",{class:Se(["prop-card-flag",{"is-synced":C.value}])},[d[41]||(d[41]=r("span",{class:"prop-card-flag-dot"},null,-1)),r("span",tn,T(n.viewportSyncing?"同步中…":C.value?"已同步":"实时同步"),1)],2)]),a(Ve,{"label-width":"132px",size:"small",class:"defaults-form"},{default:l(()=>[a(H,{label:"线宽倍率"},{default:l(()=>[a(pe,{"model-value":u.value.drawScale,min:.25,max:12,step:.1,"onUpdate:modelValue":d[12]||(d[12]=c=>p({drawScale:c??u.value.drawScale}))},null,8,["model-value"])]),_:1}),a(H,{label:"未选中线宽"},{default:l(()=>[a(pe,{"model-value":u.value.widthNormal,min:.4,max:8,step:.1,"onUpdate:modelValue":d[13]||(d[13]=c=>p({widthNormal:c??u.value.widthNormal}))},null,8,["model-value"])]),_:1}),a(H,{label:"选中线宽"},{default:l(()=>[a(pe,{"model-value":u.value.widthSelected,min:.4,max:12,step:.1,"onUpdate:modelValue":d[14]||(d[14]=c=>p({widthSelected:c??u.value.widthSelected}))},null,8,["model-value"])]),_:1}),a(H,{label:"显示方向箭头"},{default:l(()=>[a(Ue,{"model-value":u.value.showDirectionArrows,"onUpdate:modelValue":d[15]||(d[15]=c=>p({showDirectionArrows:!!c}))},null,8,["model-value"])]),_:1}),a(H,{label:"路径颜色(未选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(u.value.colorNormalArgb),"onUpdate:modelValue":d[16]||(d[16]=c=>p({colorNormalArgb:D(Re)(c??"#00ffff")}))},null,8,["model-value"])]),_:1}),a(H,{label:"路径颜色(选中)"},{default:l(()=>[a(ge,{"model-value":D(je)(u.value.colorSelectedArgb),"onUpdate:modelValue":d[17]||(d[17]=c=>p({colorSelectedArgb:D(Re)(c??"#ff0000")}))},null,8,["model-value"])]),_:1})]),_:1})]),r("section",an,[d[44]||(d[44]=r("header",{class:"prop-card-header"},[r("span",{class:"prop-card-title"},"新建路径默认")],-1)),a(Ve,{"label-width":"132px",size:"small",class:"defaults-form"},{default:l(()=>[a(H,{label:"默认图层"},{default:l(()=>[a(be,{modelValue:n.defaults.track.layer,"onUpdate:modelValue":d[18]||(d[18]=c=>n.defaults.track.layer=c)},null,8,["modelValue"])]),_:1}),a(Be,{size:"small",type:"primary",plain:"",onClick:Te},{default:l(()=>[...d[43]||(d[43]=[y("保存新建默认",-1)])]),_:1})]),_:1})])],64)):n.viewportStyleLoading?(_(),U("div",ln,[a(ze,{class:"is-loading"},{default:l(()=>[a(D(rt))]),_:1}),d[45]||(d[45]=r("span",null,"加载视口样式…",-1))])):X("",!0):(_(),U("div",Wl,[a(ze,{class:"empty-icon"},{default:l(()=>[a(D(_t))]),_:1}),d[35]||(d[35]=r("span",{class:"empty-title"},"请选中站点或路径",-1)),d[36]||(d[36]=r("span",{class:"empty-desc"},"在画布上选中一个站点或路径后,可在此调整对应视口样式。",-1))]))])]),_:1}),a(Le,{label:"图层",name:"layers"},{default:l(()=>[a(qe,{data:n.layerRows,size:"small",class:"layer-table"},{default:l(()=>[a(Ce,{prop:"name",label:"图层",width:"120"}),a(Ce,{label:"可见",width:"60"},{default:l(({row:c})=>[a(Ue,{modelValue:c.visible,"onUpdate:modelValue":R=>c.visible=R,onChange:R=>Ie(c)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),a(Ce,{label:"可选",width:"60"},{default:l(({row:c})=>[a(Ue,{modelValue:c.selectable,"onUpdate:modelValue":R=>c.selectable=R,onChange:R=>Ie(c)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1}),a(Ce,{label:"颜色"},{default:l(({row:c})=>[a(ge,{modelValue:c.color,"onUpdate:modelValue":R=>c.color=R,onChange:R=>Ie(c)},null,8,["modelValue","onUpdate:modelValue","onChange"])]),_:1})]),_:1},8,["data"]),a(be,{modelValue:M.value,"onUpdate:modelValue":d[19]||(d[19]=c=>M.value=c),size:"small",placeholder:"新图层名",class:"new-layer"},{append:l(()=>[a(Be,{onClick:xe},{default:l(()=>[...d[46]||(d[46]=[y("添加",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["modelValue"])])}}}),on=Ne(nn,[["__scopeId","data-v-781515fe"]]),sn={class:"edit-status-bar"},rn={class:"seg"},un={class:"seg"},dn={class:"seg"},cn={class:"seg"},pn={class:"seg"},mn={key:0,class:"seg ok"},fn={key:1,class:"seg warn"},yn=Ae({__name:"EditStatusBar",props:{selectedCount:{},mouseX:{},mouseY:{},toolLabel:{},snapOn:{type:Boolean},undoSize:{},redoSize:{},connected:{type:Boolean}},setup(n){function N(g){return Number.isFinite(g)?g.toFixed(0):"--"}return(g,f)=>(_(),U("div",sn,[r("span",rn,[f[0]||(f[0]=y(" 选中 ",-1)),r("b",null,T(n.selectedCount),1),f[1]||(f[1]=y(" 个 ",-1))]),r("span",un," 鼠标 ("+T(N(n.mouseX))+", "+T(N(n.mouseY))+") mm ",1),r("span",dn,[f[2]||(f[2]=y(" 当前工具:",-1)),r("b",null,T(n.toolLabel),1)]),r("span",cn,[f[3]||(f[3]=y(" 吸附:",-1)),r("b",{class:Se({on:n.snapOn,off:!n.snapOn})},T(n.snapOn?"开":"关"),3)]),f[4]||(f[4]=r("span",{class:"spacer"},null,-1)),r("span",pn,"历史 "+T(n.undoSize)+" / "+T(n.redoSize),1),n.connected?(_(),U("span",mn,"● 实时通道在线")):(_(),U("span",fn,"● 实时通道断开"))]))}}),vn=Ne(yn,[["__scopeId","data-v-6254b10f"]]),bn={class:"upload-hint"},gn={key:0,class:"ai-text"},wn={class:"ai-stat"},kn=Ae({__name:"AiGenerateDialog",props:{modelValue:{type:Boolean},configured:{type:Boolean},defaultBounds:{},defaultLayer:{}},emits:["update:modelValue","generated"],setup(n,{emit:N}){const g=n,f=N,h=yt(),C=A(!1),i=A(null),k=A(["r"]),u=Je({prompt:"",mode:"sites+tracks",referenceImageBase64:void 0,layer:g.defaultLayer??"ai-generated",constraints:""}),z=A(g.defaultBounds??[-1e4,-1e4,1e4,1e4]);fe(()=>g.defaultBounds,I=>{I&&(z.value=I)}),fe(()=>g.defaultLayer,I=>{I&&(u.layer=I)});function $(){f("update:modelValue",!1)}function p(){f("update:modelValue",!1),h.push("/admin/config/system")}async function m(I){if(!I.raw)return;const v=new FileReader;v.onload=()=>{const q=String(v.result||""),Q=q.includes(",")?q.split(",",2)[1]:q;u.referenceImageBase64=Q},v.readAsDataURL(I.raw)}async function M(){try{C.value=!0,u.bounds=z.value;const I=await j.aiMapGenerate(u);i.value=I,F.success(`AI 已生成 ${I.created?.length??0} 个对象`),f("generated",I)}catch(I){F.error(`AI 生图失败:${I.message}`)}finally{C.value=!1}}return(I,v)=>{const q=Bt,Q=pt,ye=ct,W=Tt,ve=dt,O=$a,se=Lt,ie=Ut,te=It,x=Ft,V=ft,G=Pt,oe=mt,ke=Fa,re=Na,ce=Xe,_e=Mt;return _(),ee(_e,{"model-value":n.modelValue,title:"AI 生图",width:"640px",class:"ai-generate-dialog","onUpdate:modelValue":v[9]||(v[9]=B=>f("update:modelValue",B)),onClose:$},{footer:l(()=>[a(ce,{onClick:$},{default:l(()=>[...v[20]||(v[20]=[y("关闭",-1)])]),_:1}),a(ce,{type:"primary",loading:C.value,disabled:!u.prompt.trim()||!n.configured,onClick:M},{default:l(()=>[...v[21]||(v[21]=[y(" 生成并落地 ",-1)])]),_:1},8,["loading","disabled"])]),default:l(()=>[n.configured?X("",!0):(_(),ee(Q,{key:0,type:"warning",closable:!1,class:"cfg-alert"},{default:l(()=>[v[11]||(v[11]=y(" 尚未配置 AI 服务(apiKey / endpoint)。请先到 ",-1)),a(q,{type:"primary",onClick:p},{default:l(()=>[...v[10]||(v[10]=[y("系统级配置 → AI 服务",-1)])]),_:1}),v[12]||(v[12]=y(" 完成配置。 ",-1))]),_:1})),a(x,{"label-width":"100px",size:"default"},{default:l(()=>[a(W,{label:"提示词",required:""},{default:l(()=>[a(ye,{modelValue:u.prompt,"onUpdate:modelValue":v[0]||(v[0]=B=>u.prompt=B),type:"textarea",rows:4,placeholder:"一条 U 型生产线,含 5 个工站,间距 2m,方向单向通行..."},null,8,["modelValue"])]),_:1}),a(W,{label:"参考图片"},{default:l(()=>[a(O,{drag:"","auto-upload":!1,"show-file-list":!1,accept:"image/*",onChange:m},{default:l(()=>[r("div",bn,[a(ve,null,{default:l(()=>[a(D(Aa))]),_:1}),r("span",null,T(u.referenceImageBase64?"已选择图片 (点击替换)":"拖入或点击上传参考图(可选,多模态)"),1)])]),_:1})]),_:1}),a(W,{label:"生成模式"},{default:l(()=>[a(ie,{modelValue:u.mode,"onUpdate:modelValue":v[1]||(v[1]=B=>u.mode=B)},{default:l(()=>[a(se,{value:"sites"},{default:l(()=>[...v[13]||(v[13]=[y("仅站点",-1)])]),_:1}),a(se,{value:"tracks"},{default:l(()=>[...v[14]||(v[14]=[y("仅路径",-1)])]),_:1}),a(se,{value:"sites+tracks"},{default:l(()=>[...v[15]||(v[15]=[y("站点+路径",-1)])]),_:1}),a(se,{value:"full"},{default:l(()=>[...v[16]||(v[16]=[y("完整地图",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),a(W,{label:"范围 (mm)"},{default:l(()=>[a(te,{modelValue:z.value[0],"onUpdate:modelValue":v[2]||(v[2]=B=>z.value[0]=B),placeholder:"x1",step:500},null,8,["modelValue"]),a(te,{modelValue:z.value[1],"onUpdate:modelValue":v[3]||(v[3]=B=>z.value[1]=B),placeholder:"y1",step:500,class:"ml"},null,8,["modelValue"]),a(te,{modelValue:z.value[2],"onUpdate:modelValue":v[4]||(v[4]=B=>z.value[2]=B),placeholder:"x2",step:500,class:"ml"},null,8,["modelValue"]),a(te,{modelValue:z.value[3],"onUpdate:modelValue":v[5]||(v[5]=B=>z.value[3]=B),placeholder:"y2",step:500,class:"ml"},null,8,["modelValue"])]),_:1}),a(W,{label:"图层"},{default:l(()=>[a(ye,{modelValue:u.layer,"onUpdate:modelValue":v[6]||(v[6]=B=>u.layer=B),placeholder:"ai-generated(默认)"},null,8,["modelValue"])]),_:1}),a(W,{label:"附加约束"},{default:l(()=>[a(ye,{modelValue:u.constraints,"onUpdate:modelValue":v[7]||(v[7]=B=>u.constraints=B),placeholder:"例如:单向通行、最小转弯半径 1500mm"},null,8,["modelValue"])]),_:1})]),_:1}),i.value?(_(),ee(re,{key:1,modelValue:k.value,"onUpdate:modelValue":v[8]||(v[8]=B=>k.value=B),class:"result-panel"},{default:l(()=>[a(ke,{title:"AI 返回 / 落地结果",name:"r"},{default:l(()=>[i.value.assistantText?(_(),U("div",gn,T(i.value.assistantText),1)):X("",!0),r("div",wn,[v[17]||(v[17]=y(" 落地对象 ",-1)),r("b",null,T(i.value.created?.length??0),1),v[18]||(v[18]=y(",工具调用次数 ",-1)),r("b",null,T(i.value.usedTools),1),v[19]||(v[19]=y("。 ",-1))]),a(oe,{data:i.value.created??[],size:"small","max-height":"220"},{default:l(()=>[a(V,{label:"工具",prop:"tool",width:"160"}),a(V,{label:"kind",prop:"kind",width:"80"}),a(V,{label:"id",prop:"id",width:"80"}),a(V,{label:"typeName",prop:"typeName"}),a(V,{label:"错误"},{default:l(({row:B})=>[B.error?(_(),ee(G,{key:0,type:"danger",size:"small"},{default:l(()=>[y(T(B.error),1)]),_:2},1024)):X("",!0)]),_:1})]),_:1},8,["data"])]),_:1})]),_:1},8,["modelValue"])):X("",!0)]),_:1},8,["model-value"])}}}),hn=Ne(kn,[["__scopeId","data-v-47584778"]]),xn={key:0,class:"aap-empty"},Sn=["onClick"],_n={class:"aap-bubble"},Vn={class:"aap-bubble-text"},Cn={key:0,class:"aap-meta"},$n={key:1,class:"aap-msg aap-msg--assistant"},An={class:"aap-bubble aap-bubble--loading"},Nn={class:"aap-toolbar"},Fn={class:"aap-input"},Vt=300,Ct=720,$t="mapEditor.aiAssistant.mode",Tn=Ae({__name:"AiAssistantPanel",props:{open:{type:Boolean},configured:{type:Boolean},width:{},defaultBounds:{},defaultLayer:{}},emits:["update:open","update:width","generated"],setup(n,{emit:N}){const g=n,f=N,h=ne(()=>Math.min(Ct,Math.max(Vt,g.width??360))),C=yt(),i=A([]),k=A(""),u=A(!1),z=A(null);function $(){const x=localStorage.getItem($t);return x==="sites"||x==="tracks"||x==="sites+tracks"||x==="full"?x:"sites+tracks"}const p=A($());fe(p,x=>{try{localStorage.setItem($t,x)}catch{}});let m=!1,M=0,I=0;function v(x){m=!0,M=x.clientX,I=h.value,x.currentTarget.setPointerCapture?.(x.pointerId),x.preventDefault()}function q(x){if(!m)return;const V=Math.min(Ct,Math.max(Vt,I+(M-x.clientX)));f("update:width",V)}function Q(x){m&&(m=!1,x.currentTarget.releasePointerCapture?.(x.pointerId))}Dt(()=>{m=!1});const ye=["生成一条横向直线,5 个站点,间距 2000mm","画一个 3×3 的站点矩阵,间距 2500mm","一条 U 型产线,含 5 个工站,单向通行"];function W(){f("update:open",!1)}function ve(){W(),C.push("/admin/config/system")}function O(x){k.value=x}function se(x){x instanceof KeyboardEvent&&x.key==="Enter"&&!x.shiftKey&&!x.isComposing&&(x.preventDefault(),te())}async function ie(){await Ia();const x=z.value;x&&(x.scrollTop=x.scrollHeight)}async function te(){const x=k.value.trim();if(!(!x||u.value||!g.configured)){i.value.push({role:"user",text:x}),k.value="",ie(),u.value=!0;try{const V={prompt:x,mode:p.value,bounds:g.defaultBounds,layer:g.defaultLayer},G=await j.aiMapGenerate(V),oe=G.created?.length??0;i.value.push({role:"assistant",text:G.assistantText?.trim()||`已根据你的描述生成并落地 ${oe} 个对象。`,meta:{created:oe,usedTools:G.usedTools??0}}),f("generated",G)}catch(V){const G=V.message;i.value.push({role:"assistant",text:`生成失败:${G}`}),F.error(`AI 助手生成失败:${G}`)}finally{u.value=!1,ie()}}}return(x,V)=>{const G=Bt,oe=pt,ke=dt,re=Lt,ce=Ut,_e=ct,B=Xe;return _(),U("div",{class:Se(["ai-assistant-panel",{"is-open":n.open}]),style:Rt({width:h.value+"px"}),role:"complementary","aria-label":"AI 助手"},[r("div",{class:"aap-resizer",title:"拖拽调整宽度",onPointerdown:v,onPointermove:q,onPointerup:Q,onPointercancel:Q},null,32),r("div",{class:"aap-header"},[V[2]||(V[2]=Ta('
AI 助手
用自然语言描述地图需求,自动生成站点 / 路径
',1)),r("button",{class:"aap-close",type:"button",title:"收起",onClick:W},"✕")]),n.configured?X("",!0):(_(),ee(oe,{key:0,type:"warning",closable:!1,class:"aap-alert"},{default:l(()=>[V[4]||(V[4]=y(" 尚未配置 AI 服务(apiKey / endpoint)。请先到 ",-1)),a(G,{type:"primary",onClick:ve},{default:l(()=>[...V[3]||(V[3]=[y("系统级配置 → AI 服务",-1)])]),_:1}),V[5]||(V[5]=y(" 完成配置。 ",-1))]),_:1})),r("div",{ref_key:"listRef",ref:z,class:"aap-messages"},[i.value.length===0?(_(),U("div",xn,[V[6]||(V[6]=r("div",{class:"aap-empty-title"},"试着这样说:",-1)),(_(),U(de,null,we(ye,(K,Z)=>r("button",{key:Z,type:"button",class:"aap-example",onClick:he=>O(K)},T(K),9,Sn)),64))])):X("",!0),(_(!0),U(de,null,we(i.value,(K,Z)=>(_(),U("div",{key:Z,class:Se(["aap-msg",`aap-msg--${K.role}`])},[r("div",_n,[r("div",Vn,T(K.text),1),K.role==="assistant"&&K.meta?(_(),U("div",Cn,[V[7]||(V[7]=y(" 落地对象 ",-1)),r("b",null,T(K.meta.created),1),V[8]||(V[8]=y(" · 工具调用 ",-1)),r("b",null,T(K.meta.usedTools),1)])):X("",!0)])],2))),128)),u.value?(_(),U("div",$n,[r("div",An,[a(ke,{class:"is-loading"},{default:l(()=>[a(D(rt))]),_:1}),V[9]||(V[9]=r("span",null,"AI 正在生成…",-1))])])):X("",!0)],512),r("div",Nn,[V[14]||(V[14]=r("span",{class:"aap-toolbar-label"},"生成模式",-1)),a(ce,{modelValue:p.value,"onUpdate:modelValue":V[0]||(V[0]=K=>p.value=K),size:"small"},{default:l(()=>[a(re,{value:"sites"},{default:l(()=>[...V[10]||(V[10]=[y("站点",-1)])]),_:1}),a(re,{value:"tracks"},{default:l(()=>[...V[11]||(V[11]=[y("路径",-1)])]),_:1}),a(re,{value:"sites+tracks"},{default:l(()=>[...V[12]||(V[12]=[y("站点+路径",-1)])]),_:1}),a(re,{value:"full"},{default:l(()=>[...V[13]||(V[13]=[y("完整",-1)])]),_:1})]),_:1},8,["modelValue"])]),r("div",Fn,[a(_e,{modelValue:k.value,"onUpdate:modelValue":V[1]||(V[1]=K=>k.value=K),type:"textarea",rows:3,resize:"none",disabled:!n.configured||u.value,placeholder:"例如:一条 U 型生产线,含 5 个工站,间距 2m,单向通行…(Enter 发送,Shift+Enter 换行)",onKeydown:se},null,8,["modelValue","disabled"]),a(B,{type:"primary",class:"aap-send",loading:u.value,disabled:!n.configured||!k.value.trim(),onClick:te},{default:l(()=>[...V[15]||(V[15]=[y("发送",-1)])]),_:1},8,["loading","disabled"])])],6)}}}),In=Ne(Tn,[["__scopeId","data-v-9fed2b0d"]]);function En(){const n=A("transform.move"),N=A({grid:!1,gridSizeMm:100,object:!0,endpoint:!0,midpoint:!1,toAngleDeg:void 0}),g=A(!0),f=A(!0),h=ne(()=>{const u=n.value;return u.startsWith("select.")?"select":u.startsWith("draw.")?"draw":u.startsWith("transform.")?"transform":u.startsWith("align.")?"align":u.startsWith("batch.")?"batch":u.startsWith("snap.")?"snap":"show"}),C=ne(()=>({"select.single":"单选","select.rect":"矩形框选","select.lasso":"圈选","select.byType.site":"按类型选 - 站点","select.byType.bezier":"按类型选 - 贝塞尔","select.byType.polyline":"按类型选 - 折线","select.byType.arc":"按类型选 - 弧","select.byType.decor":"按类型选 - 装饰物","select.byType.currentLayer":"按类型选 - 当前图层","select.invert":"反选","select.clear":"清空选中","draw.site":"添加站点","draw.sites.continuous":"连续添加站点","draw.track.polyline":"添加折线路径","draw.track.bezier":"添加贝塞尔路径","draw.track.arc":"添加弧形路径","draw.track.nurbs":"添加 NURBS 路径","draw.decor.line":"添加线段","draw.decor.rect":"添加矩形","draw.decor.circle":"添加圆","draw.decor.text":"添加文本","draw.image":"插入图片","draw.model":"插入 3D 模型","transform.move":"移动","transform.rotate":"旋转","transform.scale":"缩放","transform.duplicate":"复制副本","transform.copy":"复制","transform.paste":"粘贴","transform.delete":"删除","transform.copyFields":"复制字段","align.left":"左对齐","align.right":"右对齐","align.top":"上对齐","align.bottom":"下对齐","align.centerH":"水平居中","align.centerV":"垂直居中","align.center":"整体居中","align.distributeH":"水平等距","align.distributeV":"垂直等距","align.toFirst":"对齐到第一个","align.toLast":"对齐到最后一个","batch.linearH":"横向间隔生成","batch.linearV":"纵向间隔生成","batch.matrix":"矩阵生成","batch.alongPath":"沿路径采样生成","batch.circular":"环形阵列","snap.grid":"网格吸附","snap.object":"对象吸附","snap.endpoint":"端点吸附","snap.midpoint":"中点吸附","show.controlPoints":"显示控制点","show.controlHandles":"显示控制柄"})[n.value]??n.value);function i(u){n.value=u}function k(u){N.value={...N.value,[u]:!N.value[u]}}return{activeTool:n,snap:N,showControlPoints:g,showControlHandles:f,toolCategory:h,toolLabel:C,setTool:i,toggleSnap:k}}function $e(n,N){return`${n}:${N}`}function zn(){const n=A([]),N=A(null),g=ne(()=>n.value.map(m=>m.id)),f=ne(()=>n.value.length);function h(m,M){const I=$e(m,M);return n.value.some(v=>$e(v.kind,v.id)===I)}function C(m){h(m.kind,m.id)||(n.value=[...n.value,m],N.value=$e(m.kind,m.id))}function i(m,M){const I=$e(m,M);n.value=n.value.filter(v=>$e(v.kind,v.id)!==I),N.value===I&&(N.value=null)}function k(m){h(m.kind,m.id)?i(m.kind,m.id):C(m)}function u(m){n.value=m,N.value=m.length>0?$e(m[m.length-1].kind,m[m.length-1].id):null}function z(){n.value=[],N.value=null}function $(m){n.value=n.value.filter(M=>M.kind===m)}function p(m){n.value=[m],N.value=$e(m.kind,m.id)}return{items:n,ids:g,count:f,lastClickedKey:N,has:h,add:C,remove:i,toggle:k,set:u,clear:z,filterByKind:$,selectSingle:p}}function Pn(n={}){const N=n.maxDepth??20,g=A([]),f=A([]),h=A(!1),C=ne(()=>g.value.length>0&&!h.value),i=ne(()=>f.value.length>0&&!h.value);async function k(m){if(!h.value){h.value=!0;try{await m.apply(),g.value=[...g.value,m].slice(-N),f.value=[],n.onChange?.()}finally{h.value=!1}}}async function u(){if(!C.value)return;const m=g.value[g.value.length-1];h.value=!0;try{await m.revert(),g.value=g.value.slice(0,-1),f.value=[...f.value,m].slice(-N),n.onChange?.()}finally{h.value=!1}}async function z(){if(!i.value)return;const m=f.value[f.value.length-1];h.value=!0;try{await m.apply(),f.value=f.value.slice(0,-1),g.value=[...g.value,m].slice(-N),n.onChange?.()}finally{h.value=!1}}function $(){g.value=[],f.value=[],n.onChange?.()}function p(m,M){return{label:m,apply:async()=>{for(const I of M)await I.apply()},revert:async()=>{for(let I=M.length-1;I>=0;I--)await M[I].revert()}}}return{undoStack:g,redoStack:f,busy:h,canUndo:C,canRedo:i,run:k,undo:u,redo:z,clear:$,composite:p}}function Mn(n={}){function N(g){const f=g?.data;if(!f||typeof f!="object"||typeof f.type!="string")return;const h=f.type,C=f.payload;if(h==="workspace.pick"&&n.onPick&&C&&typeof C=="object"&&"x"in C&&"y"in C){const i=C;n.onPick({x:Number(i.x),y:Number(i.y),siteId:typeof i.siteId=="number"?i.siteId:void 0})}else if(h==="workspace.select"&&n.onSelect&&Array.isArray(C))n.onSelect({names:C});else if(h==="workspace.mouse"&&n.onMouse&&C&&typeof C=="object"&&"x"in C&&"y"in C){const i=C;n.onMouse({x:Number(i.x),y:Number(i.y)})}}jt(()=>window.addEventListener("message",N)),Dt(()=>window.removeEventListener("message",N))}function Un(n,N){if(n.length<2)return[];const g=[],f=n.map(p=>p.x),h=n.map(p=>p.y),C=Math.min(...f),i=Math.max(...f),k=Math.min(...h),u=Math.max(...h),z=f.reduce((p,m)=>p+m,0)/f.length,$=h.reduce((p,m)=>p+m,0)/h.length;switch(N){case"left":for(const p of n)g.push(me(p,{x:C}));break;case"right":for(const p of n)g.push(me(p,{x:i}));break;case"top":for(const p of n)g.push(me(p,{y:u}));break;case"bottom":for(const p of n)g.push(me(p,{y:k}));break;case"centerH":for(const p of n)g.push(me(p,{x:z}));break;case"centerV":for(const p of n)g.push(me(p,{y:$}));break;case"center":for(const p of n)g.push(me(p,{x:z,y:$}));break;case"distributeH":{const p=[...n].sort((M,I)=>M.x-I.x),m=(p[p.length-1].x-p[0].x)/(p.length-1);p.forEach((M,I)=>{const v=p[0].x+m*I;Math.abs(v-M.x)>.5&&g.push(me(M,{x:v}))});break}case"distributeV":{const p=[...n].sort((M,I)=>M.y-I.y),m=(p[p.length-1].y-p[0].y)/(p.length-1);p.forEach((M,I)=>{const v=p[0].y+m*I;Math.abs(v-M.y)>.5&&g.push(me(M,{y:v}))});break}case"toFirst":{const p=n[0];for(const m of n.slice(1))g.push(me(m,{x:p.x,y:p.y}));break}case"toLast":{const p=n[n.length-1];for(const m of n.slice(0,-1))g.push(me(m,{x:p.x,y:p.y}));break}}return g}function me(n,N){return{action:"patch",kind:n.kind,id:n.id,data:N}}function Ln(n,N,g,f){return Ot(n,g,N,g,f)}function Bn(n,N,g,f){return Ot(n,N,n,g,f)}function Ot(n,N,g,f,h){const C=[],i=Math.max(2,Math.floor(h.count));for(let k=0;k{const e=p.items.value;if(e.length!==1)return null;const t=e[0].kind;return t==="site"||t==="track"?t:null}),B=A(["g"]),K=A([{name:"g",visible:!0,selectable:!0,color:"#cccccc"}]),Z=Je({selectFilter:{sites:!0,tracks:!0,cars:!0,decor:!0},alignSnap:{sites:!0,cars:!0,tracks:!0},showViewport:{sceneLabels:!0,scenePrimitives:!0,cars:!0}});function he(){try{localStorage.setItem("mapEditor.viewFilter",JSON.stringify(Z))}catch{}}function Qe(){try{const e=localStorage.getItem("mapEditor.viewFilter");if(!e)return;const t=JSON.parse(e);t.selectFilter&&Object.assign(Z.selectFilter,t.selectFilter),t.alignSnap&&Object.assign(Z.alignSnap,t.alignSnap),t.showViewport&&Object.assign(Z.showViewport,t.showViewport)}catch{}}function Oe(){const e=Z.selectFilter,t=p.items.value.filter(o=>o.kind==="site"?e.sites:o.kind==="track"?e.tracks:o.kind==="car"?e.cars:o.kind==="special"?e.decor:!0);t.length!==p.items.value.length&&p.set(t)}const Fe=A(!1),ae=A({siteA:null}),Ye=A(!1),We=A(!1),Te=A("");function Ie(e){return e.map(t=>`${t.kind}:${t.id}`).sort().join(",")}const xe=A(!1),Ee=["draw.site","draw.sites.continuous","draw.track.polyline","draw.track.bezier","draw.track.arc","draw.track.nurbs"];async function b(){if(!xe.value){for(xe.value=!0;xe.value;){let e=null;try{e=await j.pick()}catch{break}if(!xe.value)break;const t=$.activeTool.value;if(!Ee.includes(t))break;if(t==="draw.site"){await c(e.x,e.y),F.success(`已添加站点 (${e.x.toFixed(0)}, ${e.y.toFixed(0)})`);break}else if(t==="draw.sites.continuous")await c(e.x,e.y);else if(t==="draw.track.polyline"||t==="draw.track.bezier"||t==="draw.track.arc"||t==="draw.track.nurbs"){const o=ae.value.siteA;if(await qe(e.siteId),o!=null&&ae.value.siteA==null){const s=t==="draw.track.bezier"?"贝塞尔路径":t==="draw.track.arc"?"弧形路径":t==="draw.track.nurbs"?"NURBS 路径":"直线路径";F.success(`已添加${s}`);break}}else break}xe.value=!1,Ee.includes($.activeTool.value)&&$.setTool("transform.move")}}const d=ne(()=>$.snap.value.grid||$.snap.value.object||$.snap.value.endpoint||$.snap.value.midpoint);async function ze(e){switch(e){case"edit.undo":await m.undo();break;case"edit.redo":await m.redo();break;case"edit.delete":await R();break;case"edit.selectAll":F.info("全选:请使用工具栏「按类型选」批量选中");break;case"edit.invert":F.info("反选功能后续实现");break;case"project.save":await ra();break;case"ai.open":await wt();break;case"file.upload.image":Ze("image");break;case"file.upload.model":Ze("model");break;case"view.fitAll":F.info("请在 3D 视口右键菜单使用「适配全部」");break;case"view.fitSelection":F.info("请在 3D 视口右键菜单使用「适配选中」");break;case"snap.toGrid":$.toggleSnap("grid");break;case"snap.toObject":$.toggleSnap("object");break;case"layer.new":await Le();break;case"layer.toggleVisibility":Fe.value=!0;break;case"view.select.sites":ue("selectFilter","sites");break;case"view.select.tracks":ue("selectFilter","tracks");break;case"view.select.cars":ue("selectFilter","cars");break;case"view.select.decor":ue("selectFilter","decor");break;case"view.snap.sites":ue("alignSnap","sites");break;case"view.snap.cars":ue("alignSnap","cars");break;case"view.snap.tracks":ue("alignSnap","tracks");break;case"view.show.sceneLabels":ue("showViewport","sceneLabels");break;case"view.show.scenePrimitives":ue("showViewport","scenePrimitives");break;case"view.show.cars":ue("showViewport","cars");break;default:F.info(`暂未实现的命令:${e}`)}}async function ue(e,t){const o=Z[e],s=t,w=o[s];o[s]=!o[s],he(),e==="selectFilter"&&Oe();const S={};S[e]={[s]:o[s]};try{await j.setViewFilter(S)}catch(E){console.warn("[MapEditor] 写后端 viewFilter 失败:",E),o[s]=w,he(),e==="selectFilter"&&Oe(),F({message:"过滤设置写入后端失败,已回滚本地状态;请检查 SimpleLite 是否连通后重试。",type:"warning",duration:5e3,showClose:!0})}}function Pe(e){return e==="bezier"?"贝塞尔路径":e==="nurbs"?"NURBS 路径":e==="arc"?"弧形路径":"直线路径"}async function be(e,t){const o=await Me(e),s=await Me(t);if(!o||!s)return F.warning(`无法拉到 site #${e} / #${t} 的 x,y,将不带 typeInfo 创建 track(圆心需手动设置)`),null;const S=Math.hypot(o.x-s.x,o.y-s.y)/2;let E;try{const L=await Y.prompt(`请输入半径 (mm),必须 ≥ ${S.toFixed(1)}(等于即半圆)`,"添加弧形路径",{inputValue:String(Math.ceil(S))});E=Number(L.value)}catch{return"cancelled"}return!Number.isFinite(E)||E0?-S/E:0,va=E>0?w/E:0,St=s==="left"?1:-1,nt=(e.x+t.x)/2+St*le*ya,ot=(e.y+t.y)/2+St*le*va,ba=Math.atan2(e.y-ot,e.x-nt)*180/Math.PI,ga=Math.atan2(t.y-ot,t.x-nt)*180/Math.PI;return["1",nt.toFixed(3),ot.toFixed(3),o.toFixed(3),ba.toFixed(3),ga.toFixed(3)].join(",")}function Ue(e){e&&(x.site.layer=e,x.track.layer=e,F.success(`默认图层已切到 "${e}"`))}async function Le(){try{const t=((await Y.prompt("请输入新图层名(同名会被忽略)","新建图层",{inputValue:""})).value??"").trim();if(!t)return;if(B.value.includes(t)){x.site.layer=t,x.track.layer=t,F.info(`图层 "${t}" 已存在,已切到该层`);return}gt(t),x.site.layer=t,x.track.layer=t,F.success(`已创建图层 "${t}",下次创建对象会落到该层`)}catch{}}async function et(e){if($.setTool(e),ae.value.siteA=null,xe.value=!1,e==="select.clear"){p.clear(),await J.clearSelection().catch(()=>{});return}if(Ee.includes(e)&&b(),e.startsWith("align.")){await Kt(e.replace("align.",""));return}if(e.startsWith("batch.")){await Ht(e);return}if(e==="transform.delete"){await R();return}if(e.startsWith("select.byType.")){const t=e.replace("select.byType.","");H(t);return}if(e==="show.controlPoints"&&($.showControlPoints.value=!$.showControlPoints.value),e==="show.controlHandles"&&($.showControlHandles.value=!$.showControlHandles.value),e==="draw.image"&&Ze("image"),e==="draw.model"&&Ze("model"),e==="transform.copyFields"){await Wt();return}}function H(e){e==="site"?p.filterByKind("site"):e==="polyline"||e==="bezier"||e==="arc"?p.items.value=p.items.value.filter(t=>{if(t.kind!=="track")return!1;const o=t.typeName.toLowerCase();return e==="polyline"?o==="uitrack":e==="bezier"?o.includes("bezier"):e==="arc"?o.includes("arc"):!1}):e==="decor"?p.filterByKind("special"):e==="currentLayer"&&O.value?.layer&&(p.items.value=p.items.value.filter(t=>t.layer===O.value.layer))}async function Ve(e){M.x=e.x,M.y=e.y;const t=$.activeTool.value;if(!(xe.value&&Ee.includes(t))&&!Ye.value){if(t==="draw.site"||t==="draw.sites.continuous"){await c(e.x,e.y);return}if(t==="draw.track.polyline"||t==="draw.track.bezier"||t==="draw.track.arc"||t==="draw.track.nurbs"){try{const o=await j.pick();await qe(o.siteId)}catch{}return}}}function Be(e){p.set(Ce(e))}function Ce(e){const t=[],o=Z.selectFilter;for(const s of e){const w=/^UI([A-Za-z]+)-(\d+)$/.exec(s)??/^([A-Za-z]+)-(\d+)$/.exec(s);if(!w)continue;const S=w[1],E=Number(w[2]),L=S.toLowerCase();let P;L==="site"?P="site":L==="car"||L==="vehicle"?P="car":L.includes("track")?P="track":P="special",!(P==="site"&&!o.sites)&&(P==="track"&&!o.tracks||P==="car"&&!o.cars||P==="special"&&!o.decor||t.push({kind:P,id:E,name:s,typeName:s.startsWith("UI")?`UI${S}`:S}))}return t}async function qe(e){if(e<=0){F.warning("请先拾取一个站点");return}if(ae.value.siteA==null){ae.value.siteA=e,F.success(`已选起点站 #${e},请再拾取终点站`);return}const t=ae.value.siteA,o=e;if(ae.value.siteA=null,t===o){F.warning("起止站点不能相同");return}const s=$.activeTool.value==="draw.track.bezier"?"bezier":$.activeTool.value==="draw.track.arc"?"arc":$.activeTool.value==="draw.track.nurbs"?"nurbs":"track";let w,S="";if(s==="bezier"||s==="nurbs"){const L=await tt(t,o,s);if(L==="cancelled")return;L!=null&&(w=L.typeInfo,S=`(控制点 ${L.midCount})`)}else if(s==="arc"){const L=await be(t,o);if(L==="cancelled")return;L!=null&&(w=L.typeInfo,S=`(半径 ${L.radius.toFixed(0)})`)}let E=-1;await m.run({label:`新建${Pe(s)} (${t}→${o})${S}`,apply:async()=>{const L={siteA:t,siteB:o,layer:x.track.layer};w&&(L.typeInfo=w),E=(await j.createTrack(s,L)).id},revert:async()=>{E>0&&await j.deleteObject("track",E)}}),Ge(s)}async function tt(e,t,o){const s=await Me(e),w=await Me(t);if(!s||!w)return F.warning(`无法拉到 site #${e} / #${t} 的 x,y,将不带 typeInfo 创建 track(控制点会用兜底直线)`),null;const S=Pe(o);let E;try{const P=await Y.prompt("请输入中间控制点个数(不含起止站点;默认 2,输入 0 则不带控制点直接连接两站点)",`创建${S}`,{inputValue:"2",inputPattern:/^\d+$/,inputErrorMessage:"请输入非负整数"});E=Math.max(0,Math.floor(Number(P.value)))}catch{return"cancelled"}if(E===0)return{typeInfo:pe([s,w],o==="bezier"?2:3),midCount:0};F.info(`请在画布上依次点选 ${E} 个中间控制点(任意位置;右键取消创建)`),Ye.value=!0;const L=[];try{for(let P=0;P{o=(await j.createSite({x:e,y:t,layer:x.site.layer,name:`${x.site.namePrefix}-${Date.now()%1e5}`})).id},revert:async()=>{o>0&&await j.deleteObject("site",o)}})}async function R(){const e=[...p.items.value];if(e.length===0)return;const t=[];for(const o of e)try{const s=await J.getBundle(o.kind,o.id);t.push({kind:o.kind,typeName:s.typeName,data:{...s.fields??{}}})}catch{}await m.run({label:`删除 ${e.length} 个对象`,apply:async()=>{const o=e.map(s=>({action:"delete",kind:s.kind,id:s.id}));await j.batch(o),p.clear()},revert:async()=>{const o=t.map(s=>({action:"create",kind:Yt(s.kind,s.typeName),data:s.data}));o.length&&(await j.batch(o),F.success(`已恢复 ${o.length} 个对象(注意:id 已重排)`))}})}function Yt(e,t){const o=(t??"").toLowerCase();if(e==="track")return o.includes("bezier")?"bezier":o.includes("arc")?"arc":o.includes("nurbs")?"nurbs":"track";if(e==="special"){if(o.includes("image"))return"image";if(o.includes("text"))return"text";if(o.includes("model"))return"model"}return e}async function Kt(e){const t=[];for(const s of p.items.value)if(s.kind!=="track")try{const w=await J.getBundle(s.kind,s.id),S=Number(w.fields?.x??0),E=Number(w.fields?.y??0);t.push({kind:s.kind,id:s.id,x:S,y:E})}catch{}if(t.length<2){F.warning("对齐需要选中至少 2 个对象");return}const o=Un(t,e);if(o.length===0){F.info("对齐无变化");return}await m.run({label:`对齐 (${e})`,apply:async()=>{await j.batch(o)},revert:async()=>{const s=t.map(w=>({action:"patch",kind:w.kind,id:w.id,data:{x:w.x,y:w.y}}));await j.batch(s)}})}async function Ht(e){if(e==="batch.linearH"||e==="batch.linearV"){const t=e==="batch.linearH"?"横向":"纵向";try{const{value:o}=await Y.prompt(`输入 ${t}站点数量`,"批量生成",{inputValue:"5",inputType:"number"}),s=Math.max(2,Math.floor(Number(o))),w=await Y.prompt("起点 X","批量生成",{inputValue:"0"}),S=await Y.prompt("起点 Y","批量生成",{inputValue:"0"}),E=await Y.prompt("终点 X","批量生成",{inputValue:"5000"}),L=await Y.prompt("终点 Y","批量生成",{inputValue:"0"}),P=e==="batch.linearH"?Ln(Number(w.value),Number(E.value),Number(S.value),{count:s,layer:x.site.layer}):Bn(Number(w.value),Number(S.value),Number(L.value),{count:s,layer:x.site.layer});await at(`${t}间隔生成 ${s}`,P)}catch{}return}if(e==="batch.matrix"){try{const t=Number((await Y.prompt("行数","矩阵生成",{inputValue:"3"})).value),o=Number((await Y.prompt("列数","矩阵生成",{inputValue:"3"})).value),s=Number((await Y.prompt("x1","矩阵生成",{inputValue:"0"})).value),w=Number((await Y.prompt("y1","矩阵生成",{inputValue:"0"})).value),S=Number((await Y.prompt("x2","矩阵生成",{inputValue:"5000"})).value),E=Number((await Y.prompt("y2","矩阵生成",{inputValue:"5000"})).value),L=Dn(s,w,S,E,{rows:t,cols:o,layer:x.site.layer});await at(`矩阵生成 ${t}×${o}`,L)}catch{}return}if(e==="batch.circular"){try{const t=Number((await Y.prompt("圆心 X","环形阵列",{inputValue:"0"})).value),o=Number((await Y.prompt("圆心 Y","环形阵列",{inputValue:"0"})).value),s=Number((await Y.prompt("半径 (mm)","环形阵列",{inputValue:"2000"})).value),w=Number((await Y.prompt("站点数量","环形阵列",{inputValue:"8"})).value),S=Rn(t,o,s,{count:w,layer:x.site.layer});await at(`环形阵列 r=${s} n=${w}`,S)}catch{}return}if(e==="batch.alongPath"){await Xt();return}}async function Xt(){const e=p.items.value.filter(w=>w.kind==="track");if(e.length===0){F.warning("请先选中至少 1 条路径");return}let t=500,o=!1;try{const{value:w}=await Y.prompt("输入采样间距 (mm)","沿路径采样",{inputValue:"500",inputType:"number"});t=Math.max(10,Math.floor(Number(w)));const{value:S}=await Y.prompt("是否包含端点?输入 1 包含,0 不包含","沿路径采样",{inputValue:"0"});o=Number(S)===1}catch{return}const s=[];await m.run({label:`沿 ${e.length} 条路径间距 ${t}mm 采样`,apply:async()=>{for(const w of e){const S=await j.sampleSitesAlongTrack(w.id,{spacingMm:t,includeEndpoints:o,layer:x.site.layer});s.push(...S.ids)}F.success(`已采样生成 ${s.length} 个站点`)},revert:async()=>{if(!s.length)return;const w=s.map(S=>({action:"delete",kind:"site",id:S}));await j.batch(w)}})}async function Wt(){if(p.items.value.length<2){F.warning("字段复制需要 ≥ 2 个选中对象(第 1 个为源,其余为目标)");return}const[e,...t]=p.items.value;try{const{value:o}=await Y.prompt("输入要复制的字段名(逗号分隔),例如:x,y,layerName","字段复制",{inputValue:"x,y"}),s=o.split(",").map(S=>S.trim()).filter(Boolean);if(!s.length)return;const w=new Map;for(const S of t)try{const E=await J.getBundle(S.kind,S.id),L={};for(const P of s)L[P]=String(E.fields?.[P]??"");w.set(`${S.kind}:${S.id}`,L)}catch{}await m.run({label:`字段复制 ${s.join(",")} → ${t.length} 个`,apply:async()=>{const S=await j.copyFieldsTo(e.kind,e.id,s,t.map(E=>({kind:E.kind,id:E.id})));F.success(`已复制 ${S.copied} 项字段`)},revert:async()=>{const S=t.flatMap(E=>{const L=w.get(`${E.kind}:${E.id}`);return L?[{action:"patch",kind:E.kind,id:E.id,data:L}]:[]});S.length&&await j.batch(S)}})}catch{}}async function at(e,t){if(t.length===0)return;let o=[];await m.run({label:e,apply:async()=>{o=(await j.batch(t)).results.filter(w=>w.ok&&w.action==="create"&&w.result?.id).map(w=>({kind:w.result.kind,id:w.result.id}))},revert:async()=>{const s=o.map(w=>({action:"delete",kind:w.kind,id:w.id}));s.length&&await j.batch(s)}}),F.success(`${e} 完成`)}async function Ke(){if(p.items.value.length===0){O.value=null,se.value=[],ie.value=[],te.value=[];return}const e=p.items.value[0];Gt();try{const t=await J.getBundle(e.kind,e.id);O.value=t.summary,se.value=Object.entries(t.fields).map(([o,s])=>({key:o,value:String(s)})),ie.value=t.methods,te.value=(t.status??[]).map(o=>({key:o.key,value:o.value}))}catch(t){F.error(`加载属性失败:${t.message}`)}finally{qt()}}function Gt(){ve.value=!0}function qt(){ve.value=!1}async function Zt(e){if(!O.value||p.items.value.length===0)return;const t=p.items.value[0],o=O.value.id,s=O.value.name??"";s!==e&&(await m.run({label:`重命名 ${s||"(无)"} → ${e}`,apply:async()=>{await J.setField(t.kind,o,"name",e)},revert:async()=>{try{await J.setField(t.kind,o,"name",s)}catch(w){F.warning(`回滚名称失败:${w.message}`)}}}),F.success("名称已更新"))}async function Jt(e){if(!O.value||p.items.value.length===0)return;const t=p.items.value[0],o=O.value.id,s=O.value.layer??"";s!==e&&(await m.run({label:`修改图层 ${s||"(无)"} → ${e}`,apply:async()=>{await J.setField(t.kind,o,"layerName",e)},revert:async()=>{try{await J.setField(t.kind,o,"layerName",s)}catch(w){F.warning(`回滚图层失败:${w.message}`)}}}),await Ke())}async function vt(e,t){if(!O.value)return;const o=p.items.value[0];let s;try{const w=await J.getBundle(o.kind,O.value.id);s=w.fields?.[e]!=null?String(w.fields[e]):void 0}catch{}await m.run({label:`修改 ${e}`,apply:async()=>{await J.setField(o.kind,O.value.id,e,t)},revert:async()=>{if(s!==void 0)try{await J.setField(o.kind,O.value.id,e,s)}catch(w){F.warning(`回滚 ${e} 失败:${w.message}`)}else F.warning(`回滚 ${e}:没拿到原值快照,仅本地撤销`)}}),await Ke()}async function Qt(){try{const e=(await Y.prompt("字段名","新增字段",{inputPattern:/^[A-Za-z0-9_]+$/})).value,t=(await Y.prompt("字段值","新增字段",{inputValue:""})).value;await vt(e,t)}catch{}}async function ea(e){if(O.value)try{await J.execute(p.items.value[0].kind,O.value.id,e),F.success(`已执行 ${e}`),await Ke()}catch(t){F.error(`执行失败:${t.message}`)}}function ta(){localStorage.setItem("mapEditor.defaults",JSON.stringify(x)),F.success("新建默认已保存(下次创建对象时生效)")}function bt(e){const t=e.site??e.Site,o=e.track??e.Track,s=(S,E,L)=>Number(S?.[E]??S?.[L]??0),w=(S,E,L)=>!!(S?.[E]??S?.[L]);return Ua({site:{drawScale:s(t,"drawScale","DrawScale"),dotRadiusNormal:s(t,"dotRadiusNormal","DotRadiusNormal"),dotRadiusSelected:s(t,"dotRadiusSelected","DotRadiusSelected"),selectionRingM:s(t,"selectionRingM","SelectionRingM"),colorNormalArgb:s(t,"colorNormalArgb","ColorNormalArgb"),colorSelectedArgb:s(t,"colorSelectedArgb","ColorSelectedArgb"),labelColorNormalArgb:s(t,"labelColorNormalArgb","LabelColorNormalArgb"),labelColorSelectedArgb:s(t,"labelColorSelectedArgb","LabelColorSelectedArgb")},track:{drawScale:s(o,"drawScale","DrawScale"),widthNormal:s(o,"widthNormal","WidthNormal"),widthSelected:s(o,"widthSelected","WidthSelected"),showDirectionArrows:w(o,"showDirectionArrows","ShowDirectionArrows"),colorNormalArgb:s(o,"colorNormalArgb","ColorNormalArgb"),colorSelectedArgb:s(o,"colorSelectedArgb","ColorSelectedArgb")}})}async function lt(){G.value=!0;try{const e=await J.getViewportStyle();V.value=bt(e)}catch(e){console.warn("[MapEditor] 加载视口样式失败:",e)}finally{G.value=!1}}function aa(e){e.site&&(ce.site=e.site,V.value&&(V.value={...V.value,site:{...e.site}})),e.track&&(ce.track=e.track,V.value&&(V.value={...V.value,track:{...e.track}})),ke&&clearTimeout(ke),ke=setTimeout(()=>{const t={...ce};ce={},la(t)},350)}async function la(e){const t=++re;oe.value=!0;try{const o={};e.site&&(o.site=e.site),e.track&&(o.track=e.track);const s=await J.patchViewportStyle(o);if(t!==re)return;V.value=bt(s)}catch(o){F.error(`视口样式更新失败:${o.message}`),await lt()}finally{t===re&&(oe.value=!1)}}function na(e){F.info("图层可见 / 可选切换暂时仅本地生效,后续接入反射 API")}function gt(e){K.value.find(t=>t.name===e)||(K.value=[...K.value,{name:e,visible:!0,selectable:!0,color:"#cccccc"}],B.value=[...B.value,e])}async function wt(){try{const e=await st.get();Q.value=!!e.configured}catch{Q.value=!1}I.value=!0}function oa(){try{v.value=localStorage.getItem(At)==="1";const e=Number(localStorage.getItem(Nt));Number.isFinite(e)&&e>=300&&e<=720&&(q.value=e)}catch{}}fe(v,e=>{try{localStorage.setItem(At,e?"1":"0")}catch{}}),fe(q,e=>{try{localStorage.setItem(Nt,String(Math.round(e)))}catch{}});async function sa(){if(!v.value)try{const e=await st.get();Q.value=!!e.configured}catch{Q.value=!1}v.value=!v.value}async function kt(e){De();const t=(e.created??[]).filter(s=>typeof s=="object"&&s!=null&&typeof s.id=="number"&&!s.error);if(t.length===0)return;const o={label:`AI 生图:落地 ${t.length} 个对象`,apply:async()=>{},revert:async()=>{const s=t.map(w=>({action:"delete",kind:w.kind,id:w.id}));await j.batch(s),F.success(`已撤销 AI 生图(删除 ${s.length} 个对象)`)}};await m.run(o)}function ia(){const e=new Date,t=o=>String(o).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}_${t(e.getHours())}-${t(e.getMinutes())}-${t(e.getSeconds())}`}async function ra(){const e=C.value||ia();W.value=!0;try{let t=await it.save(e,!1);if(!t.ok&&t.conflict){try{await Y.confirm(`地图「${e}」已存在,是否替换原地图文件?`,"替换确认",{type:"warning",confirmButtonText:"替换",cancelButtonText:"取消"})}catch{return}t=await it.save(e,!0)}if(!t.ok){F.error(`保存失败:${t.message}`);return}C.value=t.data.name,F.success(`已保存地图「${t.data.name}」`),await f.push({path:"/admin/maps"})}catch(t){F.error(`保存失败:${t.message}`)}finally{W.value=!1}}function Ze(e){z.value=e,u.value=e==="image"?"image/*":".obj,.glb,.gltf,.fbx,.cyclemodel",k.value?.click()}async function ua(e){const t=e.target,o=t.files?.[0];if(o)try{const s=await o.arrayBuffer(),w=da(s),S=await j.uploadAsset(o.name,w);F.success(`已上传:${S.fileName}`),z.value==="image"?await j.createImage({x:0,y:0,imagePath:S.savedPath,size:1e3}):await j.createModel({x:0,y:0,modelPath:S.savedPath,scale:1}),De()}catch(s){F.error(`上传失败:${s.message}`)}finally{t.value=""}}function da(e){let t="";const o=new Uint8Array(e);for(let s=0;s{M.x=e.x,M.y=e.y},onPick:e=>{Ve(e)},onSelect:e=>Be(e.names)});const ca=La({onWorkspaceShortcut:e=>{He(e.action)},onAlarm:()=>{},onObjectCreated:()=>De(),onObjectDeleted:()=>De(),onObjectPatched:()=>De(),onObjectBatchChanged:()=>De(),onViewportStyleUpdated:()=>{lt()},onSelectionDetail:e=>{if(!Array.isArray(e.names))return;const t=Ce(e.names),o=Ie(t);o!==Te.value&&(Te.value=o,p.set(t))}});function De(){Ke()}fe(()=>ca.connected.value,e=>We.value=e,{immediate:!0}),fe(()=>Ie(p.items.value),e=>{Ke(),Te.value=e,p.items.value.length===1&&J.setSelection(p.items.value[0].kind,p.items.value[0].id).catch(()=>{})});function pa(e){if(!(e instanceof HTMLElement))return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"||e.isContentEditable?!0:!!e.closest('.el-input, .el-textarea, .el-select, [contenteditable="true"]')}async function He(e){if(e==="undo"){if(!m.canUndo.value)return;await m.undo()}else if(e==="redo"){if(!m.canRedo.value)return;await m.redo()}else await R()}function ht(e){if(pa(e.target))return;const t=e.ctrlKey||e.metaKey;t&&e.key.toLowerCase()==="z"&&!e.shiftKey?(e.preventDefault(),He("undo")):t&&(e.key.toLowerCase()==="y"||e.key.toLowerCase()==="z"&&e.shiftKey)?(e.preventDefault(),He("redo")):e.key==="Delete"&&(e.preventDefault(),He("delete"))}function xt(e){const t=e.detail?.action;(t==="undo"||t==="redo"||t==="delete")&&He(t)}async function ma(){try{const e=await j.getViewFilter();Object.assign(Z.selectFilter,e.selectFilter),Object.assign(Z.alignSnap,e.alignSnap),Object.assign(Z.showViewport,e.showViewport),he()}catch(e){console.warn("[MapEditor] 拉后端 viewFilter 失败,沿用本地缓存:",e)}}jt(async()=>{document.addEventListener("keydown",ht,!0),window.addEventListener("workspace-shortcut",xt);try{const t=await st.get();Q.value=!!t.configured}catch{}const e=localStorage.getItem("mapEditor.defaults");if(e)try{Object.assign(x,JSON.parse(e))}catch{}oa(),Qe(),await ma(),await lt(),await fa()});async function fa(){const e=typeof g.query.map=="string"?g.query.map:"",t=g.query.new==="1";if(e)try{const o=await it.open(e);C.value=o.name,p.clear(),O.value=null,F.success(`已载入地图「${o.name}」:${o.sites} 站点 / ${o.tracks} 路径`)}catch(o){F.error(`载入地图失败:${o.message}`)}else t&&(C.value="")}return za(()=>{document.removeEventListener("keydown",ht,!0),window.removeEventListener("workspace-shortcut",xt)}),(e,t)=>{const o=ft,s=zt,w=Et,S=Xe,E=mt,L=Mt;return _(),U("div",jn,[a(Ra,{"can-undo":D(m).canUndo.value,"can-redo":D(m).canRedo.value,saving:W.value,"view-filter":Z,onCmd:ze},null,8,["can-undo","can-redo","saving","view-filter"]),r("div",On,[a(Ja,{"active-tool":D($).activeTool.value,onSelectTool:et,onOpenAi:wt},null,8,["active-tool"]),r("div",Yn,[a(Ma,{ref_key:"workspaceRef",ref:i,host:D(h),scope:D(N).scope??"Platform",token:D(N).token??"","read-only":!1,"embed-ui":!1,"canvas-only":!0,"hide-toolbar":!0,onPick:Ve,onSelect:Be},null,8,["host","scope","token"])]),a(on,{"selection-count":D(p).count.value,primary:O.value,fields:se.value,status:te.value,methods:ie.value,loading:ve.value,layers:B.value,defaults:x,"layer-rows":K.value,"selection-kind":_e.value,"viewport-style":V.value,"viewport-style-loading":G.value,"viewport-syncing":oe.value,onRename:Zt,onChangeLayer:Jt,onSetField:vt,onAddField:Qt,onExecAction:ea,onSaveDefaults:ta,onLayerToggle:na,onAddLayer:gt,onDelete:R,onPatchViewport:aa},null,8,["selection-count","primary","fields","status","methods","loading","layers","defaults","layer-rows","selection-kind","viewport-style","viewport-style-loading","viewport-syncing"]),r("button",{class:Se(["ai-assistant-fab",{"is-open":v.value}]),style:Rt(v.value?{right:q.value+"px"}:void 0),type:"button",title:v.value?"收起 AI 助手":"打开 AI 助手",onClick:sa},[...t[5]||(t[5]=[r("span",{class:"fab-glyph"},"✦",-1),r("span",{class:"fab-text"},[y("AI"),r("br"),y("助手")],-1)])],14,Kn),a(In,{open:v.value,"onUpdate:open":t[0]||(t[0]=P=>v.value=P),width:q.value,"onUpdate:width":t[1]||(t[1]=P=>q.value=P),configured:Q.value,"default-bounds":ye.value,"default-layer":x.site.layer,onGenerated:kt},null,8,["open","width","configured","default-bounds","default-layer"])]),a(vn,{"selected-count":D(p).count.value,"mouse-x":M.x,"mouse-y":M.y,"tool-label":D($).toolLabel.value,"snap-on":d.value,"undo-size":D(m).undoStack.value.length,"redo-size":D(m).redoStack.value.length,connected:We.value},null,8,["selected-count","mouse-x","mouse-y","tool-label","snap-on","undo-size","redo-size","connected"]),a(hn,{modelValue:I.value,"onUpdate:modelValue":t[2]||(t[2]=P=>I.value=P),configured:Q.value,"default-bounds":ye.value,"default-layer":x.site.layer,onGenerated:kt},null,8,["modelValue","configured","default-bounds","default-layer"]),a(L,{modelValue:Fe.value,"onUpdate:modelValue":t[4]||(t[4]=P=>Fe.value=P),title:"切换显示图层",width:"520px"},{footer:l(()=>[a(S,{onClick:t[3]||(t[3]=P=>Fe.value=!1)},{default:l(()=>[...t[6]||(t[6]=[y("关闭",-1)])]),_:1}),a(S,{type:"primary",onClick:Le},{default:l(()=>[...t[7]||(t[7]=[y("新建图层…",-1)])]),_:1})]),default:l(()=>[a(E,{data:K.value,size:"small",style:{width:"100%"}},{default:l(()=>[a(o,{prop:"name",label:"图层","min-width":"120"}),a(o,{label:"可见",width:"80"},{default:l(({row:P})=>[a(s,{modelValue:P.visible,"onUpdate:modelValue":le=>P.visible=le},null,8,["modelValue","onUpdate:modelValue"])]),_:1}),a(o,{label:"可选",width:"80"},{default:l(({row:P})=>[a(s,{modelValue:P.selectable,"onUpdate:modelValue":le=>P.selectable=le},null,8,["modelValue","onUpdate:modelValue"])]),_:1}),a(o,{label:"颜色",width:"100"},{default:l(({row:P})=>[a(w,{modelValue:P.color,"onUpdate:modelValue":le=>P.color=le,size:"small"},null,8,["modelValue","onUpdate:modelValue"])]),_:1}),a(o,{label:"默认层",width:"110"},{default:l(({row:P})=>[a(S,{size:"small",type:x.site.layer===P.name?"primary":"default",onClick:le=>Ue(P.name)},{default:l(()=>[y(T(x.site.layer===P.name?"当前默认":"设为默认"),1)]),_:2},1032,["type","onClick"])]),_:1})]),_:1},8,["data"])]),_:1},8,["modelValue"]),r("input",{ref_key:"fileInputRef",ref:k,type:"file",style:{display:"none"},accept:u.value,onChange:ua},null,40,Hn)])}}}),_o=Ne(Xn,[["__scopeId","data-v-704ddb94"]]);export{_o as default};