yi-map-web 1.0.2 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"yi-map-web.umd.cjs","sources":["../src/components/mars-work/expand/task/CameraList.js","../src/components/mars-work/expand/task/CameraView.js","../src/components/mars-work/expand/task/MapRotate.js","../src/components/mars-work/expand/task/PointRotate.js","../src/components/mars-work/expand/task/RouteLine.js","../src/components/mars-work/expand/task/ZoomIn.js","../src/components/mars-work/expand/task/ZoomOut.js","../src/components/mars-work/expand/task/FlickerEntity.js","../src/components/mars-work/expand/graphic/CanvasBillboard.js","../src/components/mars-work/mars-map.vue","../src/components/mars-map/panels/ToolbarPanel.vue","../src/components/mars-map/panels/VisionPanel.vue","../src/components/mars-map/composables/useMap.ts","../src/components/mars-map/composables/useMeasure.ts","../src/components/mars-map/composables/useDraw.ts","../src/components/mars-map/composables/useVision.ts","../src/components/mars-map/MarsMapContainer.vue","../src/components/business/poi-marker/usePoiMarker.ts","../src/components/business/poi-marker/PoiMarkerLayer.vue","../src/components/business/poi-marker/PoiMarkerPanel.vue","../src/components/business/track/useTrack.ts","../src/components/business/track/TrackLayer.vue","../src/components/business/track/TrackPanel.vue","../src/index.ts"],"sourcesContent":["import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 视角列表播放(分步执行)\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n * @param {object[]} [options.list] 视角数组\r\n */\r\nexport class CameraList extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraViewList(this.options.list)\r\n }\r\n\r\n // 暂停(非必须)\r\n _pauseWork() {\r\n this._disableWork()\r\n }\r\n}\r\nmars3d.thing.Task.register(\"cameraList\", CameraList)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 单个视角定位\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.center] 视角参数\r\n */\r\nexport class CameraView extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraView(this.options.center, { duration: this._duration })\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n this._map.cancelFlyTo()\r\n }\r\n}\r\nmars3d.thing.Task.register(\"camera\", CameraView)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 地球自旋转\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.center] 初始视角\r\n * @param {number} [options.speed] 旋转速度\r\n */\r\nexport class MapRotate extends mars3d.TaskItem {\r\n constructor(options = {}) {\r\n super(options)\r\n\r\n this._speed = this.options.speed || 0.01\r\n this._center = this.options.center || { lat: 29.093038, lng: 108.804459, alt: 23321232.7, heading: 0, pitch: -90 }\r\n }\r\n\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraView(this._center, {\r\n duration: 1,\r\n complete: () => {\r\n this._map.on(mars3d.EventType.clockTick, this._map_onClockTick, this)\r\n }\r\n })\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n this._map.off(mars3d.EventType.clockTick, this._map_onClockTick, this)\r\n }\r\n\r\n _map_onClockTick() {\r\n if (this.isPause) {\r\n return // 暂停时不执行\r\n }\r\n\r\n this._map.scene.camera.rotate(mars3d.Cesium.Cartesian3.UNIT_Z, this._speed)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"mapRotate\", MapRotate)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 内或外旋转\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {boolean} [options.isRotateOut] true:绕外旋转 ,false:绕内旋转\r\n * @param {boolean} [options.direction=false] 旋转方向, true逆时针,false顺时针\r\n * @param {number} [options.time=60] 飞行一周所需时间(单位 秒),控制速度\r\n * @param {boolean} [options.autoStop] 是否自动停止\r\n * @param {number} [options.autoStopAngle] 自动停止的角度值(0-360度),未设置时不自动停止\r\n * @param {object} [options.point] 绕点旋转对应的中心点位置\r\n */\r\nexport class PointRotate extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n if (this.options.center) {\r\n this._map.setCameraView(this.options.center, { duration: 0 })\r\n }\r\n\r\n if (this.options.autoStop) {\r\n delete this.options.autoStopAngle // 是否自动停止\r\n }\r\n\r\n if (this.options.isRotateOut) {\r\n this._rotateOut = new mars3d.thing.RotateOut(this.options)\r\n this._map.addThing(this._rotateOut)\r\n } else {\r\n this._rotatePoint = new mars3d.thing.RotatePoint(this.options)\r\n this._map.addThing(this._rotatePoint)\r\n }\r\n\r\n if (this.options.isRotateOut) {\r\n this._rotateOut.start()\r\n } else {\r\n this._rotatePoint.start(this.options.point)\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._rotatePoint) {\r\n this._rotatePoint.stop()\r\n this._rotatePoint.destroy()\r\n delete this._rotatePoint\r\n }\r\n if (this._rotateOut) {\r\n this._rotateOut.stop()\r\n this._rotateOut.destroy()\r\n delete this._rotateOut\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"pointRotate\", PointRotate)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 按路线漫游\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.route] FixedRoute对应的构造参数\r\n */\r\nexport class RouteLine extends mars3d.TaskItem {\r\n // constructor(options) {\r\n // super(options)\r\n // }\r\n\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._graphicLayer = new mars3d.layer.GraphicLayer()\r\n this._map.addLayer(this._graphicLayer)\r\n\r\n const fixedRoute = new mars3d.graphic.FixedRoute(this.options.route)\r\n this._graphicLayer.addGraphic(fixedRoute)\r\n this._fixedRoute = fixedRoute\r\n\r\n fixedRoute.start()\r\n }\r\n\r\n // 暂停(非必须)\r\n _pauseWork(options) {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.pause()\r\n }\r\n }\r\n\r\n // 继续(非必须)\r\n _proceedWork() {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.proceed()\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.stop()\r\n delete this._fixedRoute\r\n }\r\n\r\n if (this._graphicLayer) {\r\n this._graphicLayer.destroy()\r\n delete this._graphicLayer\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"routeLine\", RouteLine)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 放大地图\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {number} [options.relativeAmount=2] 相对量\r\n */\r\nexport class ZoomIn extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.zoomIn(this.options.relativeAmount)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"zoomIn\", ZoomIn)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 缩小地图\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {number} [options.relativeAmount=2] 相对量\r\n */\r\nexport class ZoomOut extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.zoomOut(this.options.relativeAmount)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"zoomOut\", ZoomOut)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 矢量对象高亮闪烁(仅Entity)\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {string|number} [options.layerId] 图层ID\r\n * @param {string|number} [options.graphicId] 矢量对象ID\r\n *\r\n * @param {number} [options.step=10] 闪烁增量, 控制速度\r\n * @param {string} [options.color] 高亮的颜色\r\n * @param {number} [options.maxAlpha=0.3] 闪烁的最大透明度,从 0 到 maxAlpha 渐变\r\n */\r\nexport class FlickerEntity extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n const layer = this._map.getLayerById(this.options.layerId)\r\n if (layer) {\r\n layer.show = true\r\n layer.readyPromise.then(() => {\r\n this._graphic = layer.getGraphicById(this.options.graphicId)\r\n if (this._graphic) {\r\n this._graphic.show = true\r\n this._graphic.startFlicker({\r\n time: this._duration,\r\n step: this.options.step,\r\n maxAlpha: this.options.maxAlpha,\r\n color: this.options.color\r\n })\r\n }\r\n })\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._graphic) {\r\n this._graphic.stopFlicker()\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"flickerEntity\", FlickerEntity)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n// 通过Canvas绘制复杂或动态对象的图标点Graphic\r\nexport class CanvasBillboard extends mars3d.graphic.BillboardPrimitive {\r\n /**\r\n * 文字\r\n * @type {string}\r\n */\r\n get text() {\r\n return this.style.text\r\n }\r\n\r\n set text(val) {\r\n this.style.text = val\r\n\r\n this.label.text = val\r\n }\r\n\r\n /**\r\n * 对象添加到图层前创建一些对象的钩子方法,\r\n * 只会调用一次\r\n * @return {Promise<object>} 无\r\n * @private\r\n */\r\n _addedHook(style) {\r\n style.image = \"//data.mars3d.cn/img/marker/bg/textPnl.png\"\r\n style.label = {\r\n ...style,\r\n text: this.style.text,\r\n font_size: 55,\r\n color: style.textColor ?? \"#ffffff\",\r\n hasPixelOffset: true,\r\n pixelOffsetX: 0,\r\n pixelOffsetY: -36 * (style.scale ?? 1)\r\n }\r\n if (style.scaleByDistance) {\r\n style.label.pixelOffsetScaleByDistance = style.scaleByDistance\r\n }\r\n\r\n super._addedHook(style)\r\n }\r\n}\r\n\r\n// 注册下\r\nmars3d.GraphicUtil.register(\"canvasBillboard\", CanvasBillboard)\r\n","<!--\r\n 地图渲染组件\r\n-->\r\n\r\n<template>\r\n <div :id=\"withKeyId\" class=\"mars3d-container\"></div>\r\n</template>\r\n<script setup lang=\"ts\">\r\nimport * as mars3d from \"mars3d\";\r\nimport \"./expand/index\"; // 引入插件或注册扩展js\r\n\r\nimport { computed, onUnmounted, onMounted, toRaw } from \"vue\";\r\n// import { $alert, $message } from \"@mars/components/mars-ui/index\"\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n mapKey?: string; // 多个地图时,可传入key区分地图\r\n url?: string; // 传入的地图构造参数url,可为空,只传options\r\n options?: any; // 传入的地图构造参数options,可覆盖url内的参数\r\n }>(),\r\n {\r\n mapKey: \"default\",\r\n url: undefined,\r\n options: undefined,\r\n },\r\n);\r\n\r\n// 用于存放地球组件实例\r\nlet map: mars3d.Map; // 地图对象\r\n\r\n// 使用用户传入的 mapKey 拼接生成 withKeyId 作为当前显示容器的id\r\nconst withKeyId = computed(() => `mars3d-container-${props.mapKey}`);\r\n\r\n// onload事件将在地图渲染后触发\r\nconst emit = defineEmits([\"onload\"]);\r\n\r\nconst initMars3d = async () => {\r\n // 获取配置\r\n let mapOptions;\r\n if (props.url) {\r\n // 存在url时才读取\r\n mapOptions = await mars3d.Util.fetchJson({ url: props.url });\r\n if (props.options) {\r\n mapOptions = mars3d.Util.merge(mapOptions, toRaw(props.options)); // 合并配置\r\n }\r\n } else if (props.options) {\r\n mapOptions = toRaw(props.options);\r\n }\r\n // console.log(\"Map地图构造参数\", mapOptions);\r\n\r\n // 禁用控制台版权信息输出\r\n (mars3d as any).Util.showCopyright = false;\r\n\r\n map = new mars3d.Map(withKeyId.value, mapOptions);\r\n\r\n // 针对不同终端的优化配置\r\n if (mars3d.Util.isPCBroswer()) {\r\n map.zoomFactor = 2.0; // 鼠标滚轮放大的步长参数\r\n\r\n // IE浏览器优化\r\n if (window.navigator.userAgent.toLowerCase().indexOf(\"msie\") >= 0) {\r\n map.viewer.targetFrameRate = 20; // 限制帧率\r\n map.scene.requestRenderMode = false; // 取消实时渲染\r\n }\r\n } else {\r\n map.zoomFactor = 5.0; // 鼠标滚轮放大的步长参数\r\n\r\n // 移动设备上禁掉以下几个选项,可以相对更加流畅\r\n map.scene.requestRenderMode = false; // 取消实时渲染\r\n map.scene.fog.enabled = false;\r\n map.scene.skyAtmosphere.show = false;\r\n map.scene.globe.showGroundAtmosphere = false;\r\n }\r\n\r\n // 二三维切换不用动画\r\n if (map.viewer.sceneModePicker) {\r\n map.viewer.sceneModePicker.viewModel.duration = 0.0;\r\n }\r\n\r\n // 绑定当前项目的默认右键菜单\r\n // map.bindContextMenu(getContextMenu())\r\n\r\n // 隐藏右下角的Mars3D logo\r\n if ((map as any).mars3dLogo) {\r\n (map as any).mars3dLogo.show = false;\r\n }\r\n // 强制从DOM中移除logo元素\r\n setTimeout(() => {\r\n const logoElements = document.getElementsByClassName(\"mars3d-logo\");\r\n for (let i = 0; i < logoElements.length; i++) {\r\n logoElements[i].remove();\r\n }\r\n }, 100);\r\n\r\n // webgl渲染失败后,刷新页面\r\n // map.on(mars3d.EventType.renderError, async () => {\r\n // await $alert(\"程序内存消耗过大,请重启浏览器\")\r\n // window.location.reload()\r\n // })\r\n\r\n onMapLoad(); // map构造完成后的一些处理\r\n emit(\"onload\", map);\r\n};\r\n\r\n// map构造完成后的一些处理,可以按需注释和选用\r\nfunction onMapLoad() {\r\n // Mars3D地图内部使用,如右键菜单弹窗\r\n // @ts-ignore\r\n // window.globalAlert = $alert;\r\n // // @ts-ignore\r\n // window.globalMsg = $message;\r\n}\r\n\r\nonMounted(() => {\r\n initMars3d();\r\n});\r\n// 组件卸载之前销毁mars3d实例\r\nonUnmounted(() => {\r\n if (map) {\r\n map.destroy();\r\n map = null;\r\n }\r\n // console.log(\"map销毁完成\", map);\r\n});\r\n</script>\r\n\r\n<style lang=\"less\">\r\n/**cesium 工具按钮栏*/\r\n.cesium-viewer-toolbar {\r\n top: auto !important;\r\n bottom: 35px !important;\r\n left: 12px !important;\r\n right: auto !important;\r\n}\r\n\r\n.cesium-toolbar-button img {\r\n width: 22px;\r\n height: 100%;\r\n}\r\n.cesium-toolbar-button:hover img {\r\n width: 28px;\r\n}\r\n.cesium-svgPath-svg {\r\n scale: 0.8;\r\n}\r\n.cesium-svgPath-svg:hover {\r\n scale: 1;\r\n}\r\n.cesium-button .cesium-baseLayerPicker-selected {\r\n width: 100%;\r\n}\r\n\r\n.cesium-button:hover .cesium-baseLayerPicker-selected {\r\n width: 100%;\r\n}\r\n\r\n.cesium-viewer-toolbar > .cesium-toolbar-button,\r\n.cesium-navigationHelpButton-wrapper,\r\n.cesium-viewer-geocoderContainer {\r\n margin-bottom: 5px;\r\n float: left;\r\n clear: both;\r\n text-align: center;\r\n}\r\n\r\n.cesium-viewer-geocoderContainer form .cesium-geocoder-input {\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n}\r\n\r\n.cesium-button {\r\n background-color: rgba(39, 44, 54, 0.8);\r\n\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n\r\n color: #ffffff;\r\n fill: #e6e6e6;\r\n line-height: 38px;\r\n}\r\n\r\n.cesium-button:hover {\r\n background-color: rgba(51, 133, 255, 1);\r\n box-shadow: none;\r\n border: none;\r\n}\r\n\r\n/**cesium 底图切换面板*/\r\n.cesium-baseLayerPicker-dropDown {\r\n bottom: 0;\r\n left: 40px;\r\n max-height: 700px;\r\n margin-bottom: 5px;\r\n background-color: rgba(23, 49, 71, 0.7);\r\n}\r\n\r\n/**cesium 帮助面板*/\r\n.cesium-navigation-help {\r\n top: auto;\r\n bottom: 0;\r\n left: 40px;\r\n transform-origin: left bottom;\r\n background: none;\r\n background-color: rgba(23, 49, 71, 0.8);\r\n\r\n .cesium-navigation-help-instructions,\r\n .cesium-navigation-button {\r\n background: none;\r\n }\r\n\r\n .cesium-navigation-button-selected,\r\n .cesium-navigation-button-unselected:hover {\r\n background-color: rgba(1, 35, 22, 1);\r\n }\r\n}\r\n\r\n/**cesium 二维三维切换*/\r\n.cesium-sceneModePicker-wrapper {\r\n width: auto;\r\n}\r\n\r\n.cesium-sceneModePicker-wrapper .cesium-sceneModePicker-dropDown-icon {\r\n float: right;\r\n margin: 0 3px;\r\n}\r\n\r\n/**cesium POI查询输入框*/\r\n.cesium-viewer-geocoderContainer .search-results {\r\n left: 0;\r\n right: 40px;\r\n width: auto;\r\n z-index: 9999;\r\n}\r\n\r\n.cesium-geocoder-searchButton {\r\n width: 38px;\r\n height: 38px;\r\n background-color: rgba(39, 44, 54, 0.8);\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n fill: #e6e6e6;\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .cesium-geocoder-input {\r\n height: 40px;\r\n width: 40px;\r\n background-color: rgba(63, 72, 84, 0.7);\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .cesium-geocoder-input:focus {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .search-results {\r\n background-color: rgba(23, 49, 71, 0.8);\r\n}\r\n\r\n/**cesium info信息框*/\r\n.cesium-infoBox {\r\n top: 50px;\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.cesium-infoBox-title {\r\n background-color: rgba(23, 49, 71, 0.8);\r\n}\r\n\r\n/**cesium 任务栏的FPS信息*/\r\n.cesium-performanceDisplay-defaultContainer {\r\n top: auto;\r\n bottom: 35px;\r\n right: 50px;\r\n}\r\n\r\n.cesium-performanceDisplay-ms,\r\n.cesium-performanceDisplay-fps {\r\n color: #fff;\r\n}\r\n\r\n/**cesium tileset调试信息面板*/\r\n.cesium-viewer-cesiumInspectorContainer {\r\n top: 10px;\r\n left: 10px;\r\n right: auto;\r\n}\r\n\r\n.cesium-cesiumInspector {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n/**覆盖mars3d内部控件的颜色等样式*/\r\n.mars3d-compass .mars3d-compass-outer {\r\n fill: rgba(39, 44, 54, 0.8);\r\n}\r\n.mars3d-compass .mars3d-compass-inner {\r\n background: rgba(39, 44, 54, 0.8);\r\n fill: #fff;\r\n}\r\n\r\n.mars3d-contextmenu-ul,\r\n.mars3d-sub-menu {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n.mars3d-contextmenu-ul {\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n}\r\n\r\n.mars3d-contextmenu-ul > li > a:hover,\r\n.mars3d-sub-menu > li > a:hover,\r\n.mars3d-contextmenu-ul > li > a:focus,\r\n.mars3d-sub-menu > li > a:focus,\r\n.mars3d-contextmenu-ul > li > .active,\r\n.mars3d-sub-menu > li > .active {\r\n background-color: var(--mars-hover-color, #3ea6ff);\r\n}\r\n\r\n.mars3d-contextmenu-ul > .active > a,\r\n.mars3d-sub-menu > .active > a,\r\n.mars3d-contextmenu-ul > .active > a:hover,\r\n.mars3d-sub-menu > .active > a:hover,\r\n.mars3d-contextmenu-ul > .active > a:focus,\r\n.mars3d-sub-menu > .active > a:focus {\r\n background-color: var(--mars-hover-color, #3ea6ff);\r\n}\r\n\r\n/* Popup样式*/\r\n.mars3d-popup-color {\r\n color: var(--mars-text-color, #ffffff);\r\n}\r\n\r\n.mars3d-popup-background {\r\n // background: none会导致剖面的popup没有颜色\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n// .mars3d-popup-content-wrapper {\r\n// box-shadow: none !important;\r\n// padding: 0 !important;\r\n// background: var(--mars-base-border) !important;\r\n// border-radius: 4px;\r\n// }\r\n\r\n.mars3d-popup-content {\r\n margin: 15px;\r\n}\r\n.mars3d-popup-btn-custom {\r\n padding: 3px 10px;\r\n border: 1px solid #209ffd;\r\n background: #209ffd1c;\r\n color: var(--mars-text-color);\r\n}\r\n\r\n.mars3d-tooltip {\r\n color: var(--mars-text-color, #ffffff);\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n border: 1px solid var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.mars3d-tooltip-top:before {\r\n border-top-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-bottom:before {\r\n border-bottom-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-left:before {\r\n border-left-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-right:before {\r\n border-right-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n.mars3d-template-content label {\r\n padding-right: 6px;\r\n}\r\n\r\n/* all 中的html样式 */\r\n.mars3d-template-titile {\r\n height: 33px;\r\n line-height: 33px;\r\n padding-left: 10px;\r\n border-radius: 4px 4px 0px 0px;\r\n box-shadow:\r\n 0px 6px 12px -2px rgba(50, 50, 93, 0.15),\r\n 0px 3px 7px -3px rgba(0, 0, 0, 0.2);\r\n color: var(--mars-control-text) !important;\r\n background: var(--mars-msg-title-bg);\r\n font-family: var(--mars-font-family);\r\n\r\n a {\r\n font-size: 16px;\r\n color: var(--mars-msg-title-color, #479be0);\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.mars3d-template-content {\r\n margin-top: 0 !important;\r\n background-color: var(--mars-dropdown-bg);\r\n padding: 10px;\r\n color: #eaf2ff;\r\n\r\n label {\r\n padding-right: 6px;\r\n }\r\n\r\n input {\r\n color: var(--mars-text-color);\r\n background-color: transparent !important;\r\n padding: 4px 5px;\r\n }\r\n\r\n input::placeholder {\r\n color: #cdcdcd !important;\r\n }\r\n\r\n textarea {\r\n color: var(--mars-base-color);\r\n background-color: transparent !important;\r\n padding: 4px 5px;\r\n }\r\n\r\n textarea::placeholder {\r\n color: #cdcdcd !important;\r\n }\r\n}\r\n\r\n.mars3d-popup-btn-custom {\r\n padding: 3px 10px;\r\n border: 1px solid #209ffd;\r\n background: #209ffd1c;\r\n color: var(--mars-text-color, #ffffff);\r\n}\r\n\r\n.mars3d-popup-content {\r\n margin: 15px;\r\n}\r\n\r\n.mars3d-divGraphic:hover {\r\n z-index: 999 !important;\r\n}\r\n\r\n/* 隐藏Mars3D logo */\r\n.mars3d-logo {\r\n display: none !important;\r\n visibility: hidden !important;\r\n opacity: 0 !important;\r\n pointer-events: none;\r\n}\r\n</style>\r\n","<!--\r\n ToolbarPanel — 测量 & 绘制工具栏\r\n\r\n 改进点(相对原 RightPanel):\r\n - 测量与绘制合并为统一工具栏,去掉冗余的 selectedGraphic 等未使用 prop\r\n - 新增激活态高亮(activeDrawType prop)\r\n - 图标语义更准确(使用 title 提示用户功能)\r\n-->\r\n<template>\r\n <div class=\"toolbar-panel\" :class=\"{ collapsed: isCollapsed }\">\r\n <!-- 收起/展开 header -->\r\n <div class=\"panel-header\" @click=\"toggleCollapse\">\r\n <i\r\n :class=\"[\r\n 'toggle-icon',\r\n 'fa',\r\n isCollapsed ? 'fa-chevron-down' : 'fa-chevron-up',\r\n ]\"\r\n />\r\n </div>\r\n\r\n <div class=\"panel-content\" v-show=\"!isCollapsed\">\r\n <!-- 测量工具组 -->\r\n <div class=\"menu-group\">\r\n <div\r\n v-for=\"item in measureTools\"\r\n :key=\"item.tool\"\r\n class=\"menu-item\"\r\n :title=\"item.title\"\r\n @click=\"activateTool(item.tool)\"\r\n >\r\n <i :class=\"item.iconClasses\" />\r\n </div>\r\n </div>\r\n\r\n <div class=\"divider\" />\r\n\r\n <!-- 绘制工具组 -->\r\n <div class=\"menu-group\">\r\n <div\r\n v-for=\"item in drawTools\"\r\n :key=\"item.tool\"\r\n class=\"menu-item\"\r\n :class=\"{ active: activeDrawType === item.drawType }\"\r\n :title=\"item.title\"\r\n @click=\"activateTool(item.tool)\"\r\n >\r\n <i :class=\"item.iconClasses\" />\r\n </div>\r\n <div class=\"divider\" />\r\n <!-- 清除按钮 -->\r\n <div class=\"menu-item\" title=\"清除全部\" @click=\"emitClear\">\r\n <i class=\"fa-solid fa-trash-can\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\n// ─── Props ───────────────────────────────────────────────────────────────────\r\ndefineProps<{\r\n activeDrawType?: string | null;\r\n}>();\r\n\r\n// ─── Emits ───────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n toolActivate: [tool: string];\r\n clear: [];\r\n}>();\r\n\r\n// ─── State ───────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(false);\r\n\r\nconst toggleCollapse = () => {\r\n isCollapsed.value = !isCollapsed.value;\r\n};\r\nconst activateTool = (tool: string) => {\r\n emit(\"toolActivate\", tool);\r\n};\r\nconst emitClear = () => {\r\n emit(\"clear\");\r\n};\r\n\r\n// ─── 工具配置 ─────────────────────────────────────────────────────────────────\r\ninterface ToolItem {\r\n tool: string;\r\n title: string;\r\n iconClasses: string[];\r\n drawType?: string;\r\n}\r\n\r\nconst measureTools: ToolItem[] = [\r\n {\r\n tool: \"measureDistance\",\r\n title: \"测量距离\",\r\n iconClasses: [\"fa\", \"fa-arrows-alt-h\"], // 水平双向箭头,更准确表达距离\r\n },\r\n {\r\n tool: \"measureArea\",\r\n title: \"测量面积\",\r\n iconClasses: [\"fa\", \"fa-vector-square\"], // 矢量方块,更几何感、专业感\r\n },\r\n {\r\n tool: \"measureHeight\",\r\n title: \"测量高度差\",\r\n iconClasses: [\"fa\", \"fa-arrows-alt-v\"], // 垂直双向箭头,清晰表达高度\r\n },\r\n {\r\n tool: \"measureAngle\",\r\n title: \"测量角度\",\r\n iconClasses: [\"fa-solid\", \"fa-compass-drafting\"], // 绘图圆规图标,专业表达角度测量\r\n },\r\n];\r\n\r\nconst drawTools: ToolItem[] = [\r\n {\r\n tool: \"drawPoint\",\r\n title: \"点标记\",\r\n iconClasses: [\"fa\", \"fa-map-marker\"], // 地图标记点,比空心圆更直观\r\n drawType: \"point\",\r\n },\r\n {\r\n tool: \"drawLine\",\r\n title: \"线标记\",\r\n iconClasses: [\"fa\", \"fa-slash\"], // 斜线比短横线更像\"线\"的概念\r\n drawType: \"polyline\",\r\n },\r\n {\r\n tool: \"drawPolygon\",\r\n title: \"面标记\",\r\n iconClasses: [\"fa-solid\", \"fa-draw-polygon\"], // 多边形绘制图标,语义明确\r\n drawType: \"polygon\",\r\n },\r\n {\r\n tool: \"drawCircle\",\r\n title: \"圆标记\",\r\n iconClasses: [\"fa\", \"fa-circle\"], // 实心圆表示圆\r\n drawType: \"circle\",\r\n },\r\n {\r\n tool: \"drawRectangle\",\r\n title: \"矩形标记\",\r\n iconClasses: [\"fa-regular\", \"fa-square\"], // 空心方块,与圆标记风格统一\r\n drawType: \"rectangle\",\r\n },\r\n {\r\n tool: \"drawFreePolygon\",\r\n title: \"自由多边形\",\r\n iconClasses: [\"fa\", \"fa-pencil\"], // 铅笔表示自由绘制\r\n drawType: \"freePolygon\",\r\n },\r\n];\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.toolbar-panel {\r\n position: absolute;\r\n top: 10px;\r\n right: 0;\r\n width: 42px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px 0 0 6px;\r\n border-right: none;\r\n z-index: 999;\r\n transition: max-height 0.3s ease;\r\n max-height: calc(100vh - 120px);\r\n overflow-y: auto;\r\n backdrop-filter: blur(4px);\r\n\r\n &.collapsed {\r\n max-height: 38px;\r\n .panel-content {\r\n display: none;\r\n }\r\n .panel-header {\r\n padding: 8px;\r\n justify-content: center;\r\n border-radius: 6px 0 0 6px;\r\n }\r\n }\r\n\r\n .panel-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 0 0 0;\r\n cursor: pointer;\r\n user-select: none;\r\n\r\n .toggle-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n transition: all 0.3s ease;\r\n }\r\n\r\n &:hover .toggle-icon {\r\n color: #3ea6ff;\r\n }\r\n }\r\n\r\n .panel-content {\r\n padding: 6px 0;\r\n }\r\n\r\n .menu-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n .menu-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n border-radius: 3px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n\r\n &.active {\r\n background: rgba(62, 166, 255, 0.4);\r\n color: #fff;\r\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n i {\r\n font-size: 14px;\r\n line-height: 1;\r\n }\r\n }\r\n\r\n .divider {\r\n height: 1px;\r\n background: rgba(255, 255, 255, 0.08);\r\n margin: 6px 8px;\r\n }\r\n\r\n &::-webkit-scrollbar {\r\n width: 3px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n VisionPanel — 视角控制面板\r\n\r\n 职责:\r\n - 右下角悬浮按钮 + 弹出浮层\r\n - 四个功能:环绕飞行 / 移动到此处 / 第一视角 / 键盘漫游\r\n - 激活态通过 prop 传入,不在此处维护逻辑\r\n-->\r\n<template>\r\n <!-- 触发按钮 -->\r\n <div class=\"vision-button\" title=\"视觉功能\" @click=\"togglePopup\">\r\n <i class=\"fa fa-eye\" />\r\n </div>\r\n\r\n <!-- 弹出面板 -->\r\n <Transition name=\"vision-fade\">\r\n <div v-if=\"popupVisible\" class=\"vision-popup\">\r\n <div class=\"popup-header\">\r\n <span>视觉功能</span>\r\n <i class=\"fa fa-times close-icon\" @click=\"popupVisible = false\" />\r\n </div>\r\n <div class=\"popup-content\">\r\n <div\r\n v-for=\"item in visionItems\"\r\n :key=\"item.action\"\r\n class=\"popup-item\"\r\n :class=\"{ active: isActive(item) }\"\r\n @click=\"execute(item.action)\"\r\n >\r\n <i :class=\"['fa', item.icon]\" />\r\n <span>{{ getLabel(item) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </Transition>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\n// ─── Props ───────────────────────────────────────────────────────────────────\r\nconst props = defineProps<{\r\n circleFlyActive?: boolean;\r\n flyToActive?: boolean;\r\n firstPersonActive?: boolean;\r\n keyboardNavigateActive?: boolean;\r\n}>();\r\n\r\n// ─── Emits ───────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n visionExecute: [action: string];\r\n}>();\r\n\r\n// ─── State ───────────────────────────────────────────────────────────────────\r\nconst popupVisible = ref(false);\r\nconst togglePopup = () => { popupVisible.value = !popupVisible.value; };\r\nconst execute = (action: string) => { emit(\"visionExecute\", action); };\r\n\r\n// ─── 功能配置表 ───────────────────────────────────────────────────────────────\r\ninterface VisionItem {\r\n action: string;\r\n icon: string;\r\n label: string;\r\n activeLabel?: string;\r\n activeProp?: keyof typeof props;\r\n}\r\n\r\nconst visionItems: VisionItem[] = [\r\n {\r\n action: \"circleFly\",\r\n icon: \"fa-refresh\",\r\n label: \"环绕飞行\",\r\n activeLabel: \"关闭环绕飞行\",\r\n activeProp: \"circleFlyActive\",\r\n },\r\n {\r\n action: \"flyTo\",\r\n icon: \"fa-location-arrow\",\r\n label: \"移动到此处\",\r\n activeProp: \"flyToActive\",\r\n },\r\n {\r\n action: \"firstPerson\",\r\n icon: \"fa-user\",\r\n label: \"开启第一视角\",\r\n activeLabel: \"关闭第一视角\",\r\n activeProp: \"firstPersonActive\",\r\n },\r\n {\r\n action: \"keyboardNavigate\",\r\n icon: \"fa-keyboard-o\",\r\n label: \"开启键盘漫游\",\r\n activeLabel: \"关闭键盘漫游\",\r\n activeProp: \"keyboardNavigateActive\",\r\n },\r\n];\r\n\r\nconst isActive = (item: VisionItem) =>\r\n item.activeProp ? !!props[item.activeProp] : false;\r\n\r\nconst getLabel = (item: VisionItem) =>\r\n isActive(item) && item.activeLabel ? item.activeLabel : item.label;\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.vision-button {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 0;\r\n width: 42px;\r\n height: 42px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border-radius: 6px 0 0 6px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-right: none;\r\n z-index: 999;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n backdrop-filter: blur(4px);\r\n transition: all 0.2s ease;\r\n\r\n &:hover { \r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n i { font-size: 14px; }\r\n}\r\n\r\n.vision-popup {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 48px;\r\n width: 170px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border-radius: 6px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n backdrop-filter: blur(4px);\r\n z-index: 998;\r\n\r\n .popup-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 5px 5px 0 0;\r\n\r\n span { color: #e8f4ff; font-size: 13px; font-weight: 600; }\r\n\r\n .close-icon {\r\n color: #7a9ec0;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n &:hover { color: #3ea6ff; }\r\n }\r\n }\r\n\r\n .popup-content { padding: 6px 0; }\r\n\r\n .popup-item {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 12px;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n border-radius: 3px;\r\n margin: 0 4px;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &.active { \r\n background: rgba(62, 166, 255, 0.4);\r\n color: #fff;\r\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n i { margin-right: 10px; width: 16px; text-align: center; font-size: 14px; }\r\n span { font-size: 12px; }\r\n }\r\n}\r\n\r\n// 过渡动画\r\n.vision-fade-enter-active,\r\n.vision-fade-leave-active {\r\n transition: opacity 0.25s ease, transform 0.25s ease;\r\n}\r\n.vision-fade-enter-from,\r\n.vision-fade-leave-to {\r\n opacity: 0;\r\n transform: translateX(15px);\r\n}\r\n</style>\r\n","/**\r\n * useMap — 地图核心 composable\r\n *\r\n * 职责:\r\n * - 持有 mars3d.Map 实例\r\n * - 管理业务 GraphicLayer(绘图层)和 measureLayer(测量层)\r\n * - 暴露地图事件回调(点击坐标记录)\r\n * - 提供统一的图层/thing 注册接口,方便后续业务扩展\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\n\r\n// 使用 any 避免 Mars3D 类型定义过深导致的 TS 推断溢出\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyShallowRef<T> = { readonly value: T | null };\r\n\r\nexport function useMap() {\r\n const Cesium = mars3d.Cesium;\r\n\r\n // ─── 地图实例(shallowRef 避免深响应代理 Cesium 对象) ───────────────\r\n const mapRef = shallowRef<mars3d.Map | null>(null);\r\n\r\n // ─── 核心图层 ─────────────────────────────────────────────────────────\r\n const graphicLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n const measureLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── 选中图形 ─────────────────────────────────────────────────────────\r\n const selectedGraphic = ref<any>(null);\r\n\r\n // ─── 最后点击位置(视角跳转等功能共享) ──────────────────────────────\r\n const lastClickPosition = ref<{ lng: number; lat: number; alt: number } | null>(null);\r\n\r\n /**\r\n * 在地图加载完毕后调用,完成图层、事件的初始化\r\n */\r\n function initMap(map: mars3d.Map) {\r\n mapRef.value = map;\r\n\r\n // 业务绘图层\r\n const gLayer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(gLayer);\r\n graphicLayer.value = gLayer;\r\n\r\n // 测量专用图层\r\n const mLayer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(mLayer);\r\n measureLayer.value = mLayer;\r\n\r\n // ── 地图点击:记录坐标 ──────────────────────────────────────────\r\n map.on(mars3d.EventType.click, (event: any) => {\r\n if (event.lnglat) {\r\n lastClickPosition.value = event.lnglat;\r\n } else if (event.cartesian) {\r\n const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(event.cartesian);\r\n lastClickPosition.value = {\r\n lng: Cesium.Math.toDegrees(carto.longitude),\r\n lat: Cesium.Math.toDegrees(carto.latitude),\r\n alt: carto.height > 0 ? carto.height : 5000,\r\n };\r\n }\r\n });\r\n\r\n // ── 图形层交互事件 ────────────────────────────────────────────────\r\n gLayer.on(mars3d.EventType.click, (event: any) => {\r\n selectedGraphic.value = event.graphic;\r\n });\r\n gLayer.on(mars3d.EventType.mouseOver, (event: any) => {\r\n if (!selectedGraphic.value) {\r\n selectedGraphic.value = event.graphic;\r\n }\r\n });\r\n gLayer.on(mars3d.EventType.mouseOut, (event: any) => {\r\n if (selectedGraphic.value === event.graphic) {\r\n selectedGraphic.value = null;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 销毁地图(组件卸载时调用)\r\n */\r\n function destroyMap() {\r\n if (mapRef.value) {\r\n mapRef.value.destroy();\r\n mapRef.value = null;\r\n }\r\n }\r\n\r\n /**\r\n * 便捷方法:向业务图层添加 Graphic\r\n */\r\n function addGraphic(graphic: any) {\r\n graphicLayer.value?.addGraphic(graphic);\r\n }\r\n\r\n /**\r\n * 向地图添加自定义 Thing(供业务扩展)\r\n */\r\n function addThing(thing: any) {\r\n mapRef.value?.addThing(thing);\r\n }\r\n\r\n return {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n map: mapRef as AnyShallowRef<any>,\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n graphicLayer: graphicLayer as AnyShallowRef<any>,\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n measureLayer: measureLayer as AnyShallowRef<any>,\r\n selectedGraphic,\r\n lastClickPosition,\r\n initMap,\r\n destroyMap,\r\n addGraphic,\r\n addThing,\r\n };\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type UseMapReturn = ReturnType<typeof useMap>;\r\n","/**\r\n * useMeasure — 测量工具 composable\r\n *\r\n * 职责:\r\n * - 封装 mars3d.thing.Measure 的生命周期\r\n * - 提供 距离 / 面积 / 高度差 / 角度 四种测量方法\r\n * - 提供 clear 清除方法\r\n *\r\n * 依赖:useMap 返回的 map 与 measureLayer\r\n */\r\nimport { shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\nexport function useMeasure(mapContext: UseMapReturn) {\r\n const measureThing = shallowRef<mars3d.thing.Measure | null>(null);\r\n\r\n /** 在地图初始化后调用,注册 Measure thing */\r\n function initMeasure() {\r\n const map = mapContext.map.value;\r\n const layer = mapContext.measureLayer.value;\r\n if (!map || !layer) return;\r\n\r\n const m = new mars3d.thing.Measure({ graphicLayer: layer } as any);\r\n map.addThing(m);\r\n measureThing.value = m;\r\n }\r\n\r\n /** 测量距离 */\r\n function measureDistance(style?: Record<string, any>) {\r\n measureThing.value?.distance({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 测量面积 */\r\n function measureArea(style?: Record<string, any>) {\r\n measureThing.value?.area({\r\n style: { color: \"#3388ff\", opacity: 0.5, ...style },\r\n });\r\n }\r\n\r\n /** 测量高度差 */\r\n function measureHeight(style?: Record<string, any>) {\r\n measureThing.value?.height({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 测量角度 */\r\n function measureAngle(style?: Record<string, any>) {\r\n measureThing.value?.angle({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 清除所有测量结果 */\r\n function clearMeasure() {\r\n measureThing.value?.clear();\r\n mapContext.measureLayer.value?.clear();\r\n }\r\n\r\n return {\r\n measureThing,\r\n initMeasure,\r\n measureDistance,\r\n measureArea,\r\n measureHeight,\r\n measureAngle,\r\n clearMeasure,\r\n };\r\n}\r\n","/**\r\n * useDraw — 绘制工具 composable\r\n *\r\n * 职责:\r\n * - 封装六种图形绘制(点/线/面/圆/矩形/自由多边形)\r\n * - 统一管理 currentDraw 引用,保证绘制互斥\r\n * - 提供 stopDraw / clearDraw 方法\r\n *\r\n * 依赖:useMap 返回的 measureLayer(绘图结果复用测量层,也可传独立图层)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\n/** 支持的绘制类型枚举,方便外部类型提示 */\r\nexport type DrawType = \"point\" | \"polyline\" | \"polygon\" | \"circle\" | \"rectangle\" | \"freePolygon\";\r\n\r\nexport function useDraw(mapContext: UseMapReturn) {\r\n const currentDraw = shallowRef<any>(null);\r\n /** 当前激活的绘制类型,用于 UI 高亮 */\r\n const activeDrawType = ref<DrawType | null>(null);\r\n\r\n /** 获取绘制目标图层(复用 measureLayer,也可按需传其他层) */\r\n function getLayer() {\r\n return mapContext.measureLayer.value;\r\n }\r\n\r\n /** 内部启动绘制 */\r\n function startDraw(type: string, style: Record<string, any>, drawType: DrawType) {\r\n const layer = getLayer();\r\n if (!layer) return;\r\n stopDraw(); // 先停止上一次未完成的绘制\r\n currentDraw.value = layer.startDraw({ type, style });\r\n activeDrawType.value = drawType;\r\n }\r\n\r\n /** 绘制点 */\r\n function drawPoint(style?: Record<string, any>) {\r\n startDraw(\"point\", { pixelSize: 10, color: \"#ff0000\", ...style }, \"point\");\r\n }\r\n\r\n /** 绘制折线 */\r\n function drawLine(style?: Record<string, any>) {\r\n startDraw(\"polyline\", { width: 3, color: \"#3388ff\", ...style }, \"polyline\");\r\n }\r\n\r\n /** 绘制多边形 */\r\n function drawPolygon(style?: Record<string, any>) {\r\n startDraw(\"polygon\", { color: \"#3388ff\", opacity: 0.5, ...style }, \"polygon\");\r\n }\r\n\r\n /** 绘制圆 */\r\n function drawCircle(style?: Record<string, any>) {\r\n startDraw(\"circle\", { radius: 1000, color: \"#00ff00\", opacity: 0.3, ...style }, \"circle\");\r\n }\r\n\r\n /** 绘制矩形 */\r\n function drawRectangle(style?: Record<string, any>) {\r\n startDraw(\"rectangle\", { color: \"#3388ff\", opacity: 0.5, ...style }, \"rectangle\");\r\n }\r\n\r\n /** 绘制自由多边形(贴地) */\r\n function drawFreePolygon(style?: Record<string, any>) {\r\n startDraw(\r\n \"polygon\",\r\n { color: \"#3388ff\", opacity: 0.5, clampToGround: true, ...style },\r\n \"freePolygon\",\r\n );\r\n }\r\n\r\n /** 停止当前绘制,但保留已绘结果 */\r\n function stopDraw() {\r\n if (currentDraw.value) {\r\n getLayer()?.stopDraw();\r\n currentDraw.value = null;\r\n }\r\n activeDrawType.value = null;\r\n }\r\n\r\n /** 停止并清除所有绘制结果 */\r\n function clearDraw() {\r\n stopDraw();\r\n getLayer()?.clear();\r\n }\r\n\r\n return {\r\n currentDraw,\r\n activeDrawType,\r\n drawPoint,\r\n drawLine,\r\n drawPolygon,\r\n drawCircle,\r\n drawRectangle,\r\n drawFreePolygon,\r\n stopDraw,\r\n clearDraw,\r\n };\r\n}\r\n","/**\r\n * useVision — 视角控制 composable\r\n *\r\n * 职责:\r\n * - 封装环绕飞行(RotatePoint)\r\n * - 封装飞行到指定位置(flyTo / flyHome)\r\n * - 封装第一视角漫游(FirstPersonRoam)\r\n * - 封装键盘漫游(KeyboardRoam)\r\n * - 暴露各功能的激活状态,供 UI 显示切换文案\r\n *\r\n * 依赖:useMap 返回的 map 与 lastClickPosition\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\nexport function useVision(mapContext: UseMapReturn) {\r\n // ─── 状态 ──────────────────────────────────────────────────────────────\r\n const circleFlyActive = ref(false);\r\n const firstPersonActive = ref(false);\r\n const keyboardActive = ref(false);\r\n const flyToActive = ref(false);\r\n\r\n // ─── Thing 实例 ────────────────────────────────────────────────────────\r\n const rotatePoint = shallowRef<mars3d.thing.RotatePoint | null>(null);\r\n const firstPersonRoam = shallowRef<mars3d.thing.FirstPersonRoam | null>(null);\r\n const keyboardRoam = shallowRef<mars3d.thing.KeyboardRoam | null>(null);\r\n let initialCameraView: any = null;\r\n\r\n /** 获取地图实例(内部简写) */\r\n function getMap() {\r\n return mapContext.map.value;\r\n }\r\n\r\n // ─── 环绕飞行 ──────────────────────────────────────────────────────────\r\n function toggleCircleFly() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (rotatePoint.value) {\r\n if (rotatePoint.value.isStart) {\r\n rotatePoint.value.stop();\r\n }\r\n map.removeThing(rotatePoint.value);\r\n rotatePoint.value = null;\r\n circleFlyActive.value = false;\r\n return;\r\n }\r\n\r\n const center = map.getCenter();\r\n const rp = new mars3d.thing.RotatePoint({ distance: 5000, time: 30 });\r\n map.addThing(rp);\r\n rp.start(center);\r\n rotatePoint.value = rp;\r\n circleFlyActive.value = true;\r\n }\r\n\r\n // ─── 飞行到点击位置或地图中心 ──────────────────────────────────────────\r\n function flyTo() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n flyToActive.value = true;\r\n const done = () => setTimeout(() => { flyToActive.value = false; }, 2000);\r\n\r\n const pos = mapContext.lastClickPosition.value;\r\n if (pos) {\r\n const target = { ...pos, alt: pos.alt > 0 ? pos.alt : 5000 };\r\n map.setCameraView(target, { duration: 2, complete: done });\r\n } else {\r\n map.flyHome({ duration: 2 });\r\n done();\r\n }\r\n }\r\n\r\n // ─── 第一视角漫游 ──────────────────────────────────────────────────────\r\n function toggleFirstPerson() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (!firstPersonRoam.value) {\r\n const roam = new mars3d.thing.FirstPersonRoam({});\r\n map.addThing(roam);\r\n initialCameraView = map.getCameraView();\r\n roam.enabled = true;\r\n firstPersonRoam.value = roam;\r\n firstPersonActive.value = true;\r\n } else {\r\n const roam = firstPersonRoam.value;\r\n roam.enabled = !roam.enabled;\r\n firstPersonActive.value = roam.enabled;\r\n if (!roam.enabled && initialCameraView) {\r\n map.setCameraView(initialCameraView, { duration: 1 });\r\n } else if (roam.enabled) {\r\n initialCameraView = map.getCameraView();\r\n }\r\n }\r\n }\r\n\r\n // ─── 键盘漫游 ──────────────────────────────────────────────────────────\r\n function toggleKeyboardNavigate() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (!keyboardRoam.value) {\r\n const roam = new mars3d.thing.KeyboardRoam({});\r\n map.addThing(roam);\r\n roam.enabled = true;\r\n keyboardRoam.value = roam;\r\n keyboardActive.value = true;\r\n } else {\r\n const roam = keyboardRoam.value;\r\n roam.enabled = !roam.enabled;\r\n keyboardActive.value = roam.enabled;\r\n }\r\n }\r\n\r\n return {\r\n // 状态\r\n circleFlyActive,\r\n firstPersonActive,\r\n keyboardActive,\r\n flyToActive,\r\n // 方法\r\n toggleCircleFly,\r\n flyTo,\r\n toggleFirstPerson,\r\n toggleKeyboardNavigate,\r\n };\r\n}\r\n","<!--\r\n MarsMapContainer — 地图核心容器组件\r\n\r\n 功能:\r\n 1. 集成底层 MarsMap 渲染组件\r\n 2. 内置测量/绘制工具栏(ToolbarPanel)和视角控制面板(VisionPanel)\r\n 3. 组合所有 composable,通过 provide 向子组件/插槽透传地图上下文\r\n 4. 通过 default 插槽支持业务组件叠加(popup、图表、统计面板等)\r\n\r\n Props:\r\n - configUrl 地图配置 JSON 路径\r\n - mapKey 多地图时区分实例的 key(默认 \"default\")\r\n - hideToolbar 是否隐藏工具栏(默认 false)\r\n - hideVision 是否隐藏视觉控制按钮(默认 false)\r\n\r\n Expose(供父组件通过 ref 访问):\r\n - map\r\n - graphicLayer\r\n - measureLayer\r\n - selectedGraphic\r\n - addGraphic()\r\n - addThing()\r\n - measure(useMeasure 全量返回)\r\n - draw(useDraw 全量返回)\r\n - vision(useVision 全量返回)\r\n-->\r\n<template>\r\n <div class=\"mars-map-container\">\r\n <!-- 底层地图渲染 -->\r\n <MarsMap\r\n :url=\"configUrl\"\r\n :map-key=\"mapKey\"\r\n @onload=\"onMapLoad\"\r\n />\r\n\r\n <!-- 测量/绘制工具栏 -->\r\n <ToolbarPanel\r\n v-if=\"!hideToolbar\"\r\n :active-draw-type=\"draw.activeDrawType.value\"\r\n @tool-activate=\"handleToolActivate\"\r\n @clear=\"handleClear\"\r\n />\r\n\r\n <!-- 视角控制面板 -->\r\n <VisionPanel\r\n v-if=\"!hideVision\"\r\n :circle-fly-active=\"vision.circleFlyActive.value\"\r\n :fly-to-active=\"vision.flyToActive.value\"\r\n :first-person-active=\"vision.firstPersonActive.value\"\r\n :keyboard-navigate-active=\"vision.keyboardActive.value\"\r\n @vision-execute=\"handleVisionExecute\"\r\n />\r\n\r\n <!-- 业务插槽:自定义 UI 叠加层 -->\r\n <slot />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { provide } from \"vue\";\r\nimport MarsMap from \"../mars-work/mars-map.vue\";\r\nimport ToolbarPanel from \"./panels/ToolbarPanel.vue\";\r\nimport VisionPanel from \"./panels/VisionPanel.vue\";\r\n\r\nimport { useMap } from \"./composables/useMap\";\r\nimport { useMeasure } from \"./composables/useMeasure\";\r\nimport { useDraw } from \"./composables/useDraw\";\r\nimport { useVision } from \"./composables/useVision\";\r\n\r\n// ─── Props ──────────────────────────────────────────────────────────────────\r\nconst props = withDefaults(\r\n defineProps<{\r\n configUrl?: string;\r\n mapKey?: string;\r\n hideToolbar?: boolean;\r\n hideVision?: boolean;\r\n }>(),\r\n {\r\n configUrl: \"config/config.json\",\r\n mapKey: \"default\",\r\n hideToolbar: false,\r\n hideVision: false,\r\n },\r\n);\r\n\r\n// ─── Emits ──────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n /** 地图加载完成,回传 map 实例 */\r\n onload: [map: any];\r\n}>();\r\n\r\n// ─── Composables ────────────────────────────────────────────────────────────\r\nconst mapCtx = useMap();\r\nconst measure = useMeasure(mapCtx);\r\nconst draw = useDraw(mapCtx);\r\nconst vision = useVision(mapCtx);\r\n\r\n// ─── provide(供插槽内的业务组件直接 inject 使用) ──────────────────────────\r\nprovide(\"mapContext\", mapCtx);\r\nprovide(\"measureContext\", measure);\r\nprovide(\"drawContext\", draw);\r\nprovide(\"visionContext\", vision);\r\n\r\n// ─── 地图加载回调 ────────────────────────────────────────────────────────────\r\nfunction onMapLoad(map: any) {\r\n mapCtx.initMap(map);\r\n measure.initMeasure();\r\n emit(\"onload\", map);\r\n}\r\n\r\n// ─── 工具栏事件处理 ──────────────────────────────────────────────────────────\r\ntype ToolAction =\r\n | \"measureDistance\" | \"measureArea\" | \"measureHeight\" | \"measureAngle\"\r\n | \"drawPoint\" | \"drawLine\" | \"drawPolygon\" | \"drawCircle\" | \"drawRectangle\" | \"drawFreePolygon\";\r\n\r\nfunction handleToolActivate(tool: string) {\r\n switch (tool as ToolAction) {\r\n case \"measureDistance\": measure.measureDistance(); break;\r\n case \"measureArea\": measure.measureArea(); break;\r\n case \"measureHeight\": measure.measureHeight(); break;\r\n case \"measureAngle\": measure.measureAngle(); break;\r\n case \"drawPoint\": draw.drawPoint(); break;\r\n case \"drawLine\": draw.drawLine(); break;\r\n case \"drawPolygon\": draw.drawPolygon(); break;\r\n case \"drawCircle\": draw.drawCircle(); break;\r\n case \"drawRectangle\": draw.drawRectangle(); break;\r\n case \"drawFreePolygon\": draw.drawFreePolygon(); break;\r\n }\r\n}\r\n\r\nfunction handleClear() {\r\n measure.clearMeasure();\r\n draw.clearDraw();\r\n}\r\n\r\n// ─── 视角控制事件处理 ────────────────────────────────────────────────────────\r\ntype VisionAction = \"circleFly\" | \"flyTo\" | \"firstPerson\" | \"keyboardNavigate\";\r\n\r\nfunction handleVisionExecute(action: string) {\r\n switch (action as VisionAction) {\r\n case \"circleFly\": vision.toggleCircleFly(); break;\r\n case \"flyTo\": vision.flyTo(); break;\r\n case \"firstPerson\": vision.toggleFirstPerson(); break;\r\n case \"keyboardNavigate\": vision.toggleKeyboardNavigate(); break;\r\n }\r\n}\r\n\r\n// ─── Expose(父组件 ref 访问) ────────────────────────────────────────────────\r\ndefineExpose({\r\n map: mapCtx.map,\r\n graphicLayer: mapCtx.graphicLayer,\r\n measureLayer: mapCtx.measureLayer,\r\n selectedGraphic: mapCtx.selectedGraphic,\r\n lastClickPosition: mapCtx.lastClickPosition,\r\n addGraphic: mapCtx.addGraphic,\r\n addThing: mapCtx.addThing,\r\n measure,\r\n draw,\r\n vision,\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.mars-map-container {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n</style>\r\n","/**\r\n * usePoiMarker — POI 标注管理 composable\r\n *\r\n * 职责:\r\n * - 维护 POI 数据列表(纯数据层)\r\n * - 管理地图上对应的 BillboardEntity 图形(图形层)\r\n * - 提供 添加 / 删除 / 选中 / 飞行定位 操作\r\n * - 数据与图形保持双向同步(通过 graphicId 关联)\r\n *\r\n * 使用方式(在业务组件内):\r\n * const mapCtx = inject<UseMapReturn>('mapContext')!\r\n * const poi = usePoiMarker(mapCtx)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\n\r\n// ─── POI 数据类型 ─────────────────────────────────────────────────────────────\r\nexport interface PoiItem {\r\n id: string;\r\n name: string;\r\n lng: number;\r\n lat: number;\r\n alt: number;\r\n category: \"default\" | \"warning\" | \"info\";\r\n description?: string;\r\n /** 对应地图上的 Graphic 实例引用 */\r\n graphic?: any;\r\n}\r\n\r\n/** 分类颜色映射 */\r\nconst CATEGORY_ICON: Record<PoiItem[\"category\"], string> = {\r\n default: \"//data.mars3d.cn/img/marker/mark-blue.png\",\r\n warning: \"//data.mars3d.cn/img/marker/mark-red.png\",\r\n info: \"//data.mars3d.cn/img/marker/mark-green.png\",\r\n};\r\n\r\nlet _idCounter = 1;\r\n\r\nexport function usePoiMarker(mapCtx: UseMapReturn) {\r\n // ─── 独立业务图层(与测量层隔离) ─────────────────────────────────────────\r\n const poiLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── POI 数据列表 ──────────────────────────────────────────────────────────\r\n const poiList = ref<PoiItem[]>([]);\r\n\r\n // ─── 当前选中的 POI ────────────────────────────────────────────────────────\r\n const activePoiId = ref<string | null>(null);\r\n\r\n /** 在地图加载后调用,初始化专属图层 */\r\n function initPoiLayer() {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n const layer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(layer);\r\n poiLayer.value = layer;\r\n\r\n // 点击图层上的标注 → 选中对应 POI\r\n layer.on(mars3d.EventType.click, (e: any) => {\r\n const poiId = e.graphic?.attr?.poiId;\r\n if (poiId) selectPoi(poiId);\r\n });\r\n }\r\n\r\n /** 添加 POI(创建数据 + 在地图上生成图形) */\r\n function addPoi(params: Omit<PoiItem, \"id\" | \"graphic\">) {\r\n const layer = poiLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `poi-${_idCounter++}`;\r\n\r\n // 创建地图图形\r\n const graphic = new mars3d.graphic.BillboardEntity({\r\n position: [params.lng, params.lat, params.alt],\r\n style: {\r\n image: CATEGORY_ICON[params.category],\r\n scale: 1,\r\n horizontalOrigin: mars3d.Cesium.HorizontalOrigin.CENTER,\r\n verticalOrigin: mars3d.Cesium.VerticalOrigin.BOTTOM,\r\n clampToGround: false,\r\n // 标注文字\r\n label: {\r\n text: params.name,\r\n font_size: 14,\r\n color: \"#ffffff\",\r\n outline: true,\r\n outlineColor: \"#333333\",\r\n outlineWidth: 2,\r\n pixelOffset: new mars3d.Cesium.Cartesian2(0, -40),\r\n visibleDepth: false,\r\n },\r\n },\r\n // popup 弹窗(点击标注时自动展示)\r\n popup: buildPopupHtml(params),\r\n attr: { poiId: id, name: params.name },\r\n });\r\n\r\n layer.addGraphic(graphic);\r\n\r\n const poi: PoiItem = { ...params, id, graphic };\r\n poiList.value.push(poi);\r\n return poi;\r\n }\r\n\r\n /** 删除 POI */\r\n function removePoi(id: string) {\r\n const idx = poiList.value.findIndex((p) => p.id === id);\r\n if (idx === -1) return;\r\n\r\n const poi = poiList.value[idx];\r\n poi.graphic && poiLayer.value?.removeGraphic(poi.graphic);\r\n poiList.value.splice(idx, 1);\r\n\r\n if (activePoiId.value === id) activePoiId.value = null;\r\n }\r\n\r\n /** 选中 POI(高亮 + 视角飞行) */\r\n function selectPoi(id: string, flyTo = false) {\r\n activePoiId.value = id;\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi) return;\r\n\r\n // 高亮:放大图标\r\n poiList.value.forEach((p) => {\r\n if (p.graphic) {\r\n p.graphic.style.scale = p.id === id ? 1.4 : 1.0;\r\n }\r\n });\r\n\r\n if (flyTo) flyToPoi(id);\r\n }\r\n\r\n /** 更新 POI 名称(实时同步到图形和 popup) */\r\n function updatePoiName(id: string, newName: string) {\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi) return;\r\n\r\n poi.name = newName;\r\n\r\n // 同步更新图形 attr\r\n if (poi.graphic) {\r\n poi.graphic.attr = { ...poi.graphic.attr, name: newName };\r\n poi.graphic.popup = buildPopupHtml(poi);\r\n // 同步更新 label 文字\r\n if (poi.graphic.style?.label) {\r\n poi.graphic.style.label.text = newName;\r\n }\r\n poi.graphic.closePopup?.();\r\n }\r\n }\r\n\r\n /** 飞行到 POI 位置 */\r\n function flyToPoi(id: string) {\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi || !mapCtx.map.value) return;\r\n\r\n const map = mapCtx.map.value;\r\n\r\n // 以标注点高度为基准,飞行高度 = 标注高度 + 合理偏移\r\n const baseAlt = poi.alt > 1 ? poi.alt : 50;\r\n const flyAlt = baseAlt + 1500;\r\n\r\n // 不指定 pitch,让相机正上方俯视,定位最准确\r\n map.setCameraView({ lng: poi.lng, lat: poi.lat, alt: flyAlt }, { duration: 1.5 });\r\n }\r\n\r\n /** 清空所有 POI */\r\n function clearAll() {\r\n poiLayer.value?.clear();\r\n poiList.value = [];\r\n activePoiId.value = null;\r\n }\r\n\r\n /** 开启/关闭「点击地图添加标注」模式 */\r\n const isAddMode = ref(false);\r\n let _clickHandler: ((e: any) => void) | null = null;\r\n\r\n function toggleAddMode(\r\n onAdded?: (poi: PoiItem) => void,\r\n defaultName = \"新标注\",\r\n category: PoiItem[\"category\"] = \"default\",\r\n ) {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n if (isAddMode.value) {\r\n // 退出添加模式\r\n if (_clickHandler) {\r\n map.off(mars3d.EventType.click, _clickHandler);\r\n _clickHandler = null;\r\n }\r\n isAddMode.value = false;\r\n } else {\r\n // 进入添加模式:下一次点击地图即创建 POI\r\n isAddMode.value = true;\r\n _clickHandler = (e: any) => {\r\n // 优先取经纬度坐标,兜底用笛卡尔坐标转换\r\n let lng: number, lat: number, alt: number;\r\n\r\n if (e.lnglat) {\r\n lng = e.lnglat.lng;\r\n lat = e.lnglat.lat;\r\n alt = e.lnglat.alt ?? 0;\r\n } else if (e.cartesian) {\r\n const carto = mars3d.Cesium.Cartographic.fromCartesian(e.cartesian);\r\n lng = mars3d.Cesium.Math.toDegrees(carto.longitude);\r\n lat = mars3d.Cesium.Math.toDegrees(carto.latitude);\r\n alt = carto.height > 0 ? carto.height : 50; // terrain height fallback\r\n } else {\r\n return;\r\n }\r\n\r\n // 标注高度至少离地面 50m,避免贴地\r\n const finalAlt = alt > 1 ? alt : 50;\r\n\r\n const poi = addPoi({\r\n name: `${defaultName} ${_idCounter}`,\r\n lng,\r\n lat,\r\n alt: finalAlt,\r\n category,\r\n });\r\n if (poi) onAdded?.(poi);\r\n // 单次模式:添加完即退出\r\n toggleAddMode();\r\n };\r\n map.on(mars3d.EventType.click, _clickHandler);\r\n }\r\n }\r\n\r\n return {\r\n poiLayer,\r\n poiList,\r\n activePoiId,\r\n isAddMode,\r\n initPoiLayer,\r\n addPoi,\r\n removePoi,\r\n selectPoi,\r\n flyToPoi,\r\n updatePoiName,\r\n clearAll,\r\n toggleAddMode,\r\n };\r\n}\r\n\r\n// ─── 工具:生成 popup HTML ────────────────────────────────────────────────────\r\nfunction buildPopupHtml(poi: Omit<PoiItem, \"id\" | \"graphic\">) {\r\n return `\r\n <div style=\"padding:8px 12px;min-width:160px;\">\r\n <div style=\"font-size:15px;font-weight:bold;margin-bottom:6px;color:#fff;\">${poi.name}</div>\r\n <div style=\"font-size:12px;color:#adc6e5;line-height:1.8;\">\r\n <div>经度:${poi.lng.toFixed(6)}</div>\r\n <div>纬度:${poi.lat.toFixed(6)}</div>\r\n <div>高度:${poi.alt.toFixed(1)} m</div>\r\n ${poi.description ? `<div style=\"margin-top:4px;\">${poi.description}</div>` : \"\"}\r\n </div>\r\n </div>\r\n `;\r\n}\r\n\r\nexport type UsePoiMarkerReturn = ReturnType<typeof usePoiMarker>;\r\n","<!--\r\n PoiMarkerLayer — POI 标注地图层组件\r\n\r\n 职责:\r\n - 放置在 MarsMapContainer 的 <slot> 内\r\n - 通过 inject 获取地图上下文,完成图层初始化\r\n - 通过 provide 将 poiCtx 向子组件暴露(inject 只走父→子,不走兄弟)\r\n - 内部通过 <slot> 渲染 PoiMarkerPanel 等子组件,保证 provide/inject 链路正确\r\n - 对外 expose usePoiMarker 全量接口,供父组件 ref 访问\r\n\r\n 使用方式(PoiMarkerPanel 必须作为子内容传入,而非兄弟节点):\r\n <MarsMapContainer @onload=\"...\">\r\n <PoiMarkerLayer ref=\"poiLayerRef\">\r\n <PoiMarkerPanel />\r\n </PoiMarkerLayer>\r\n </MarsMapContainer>\r\n-->\r\n<template>\r\n <!-- provide/inject 需要父子关系,用 slot 渲染子组件 -->\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { inject, provide, watch, onUnmounted } from \"vue\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\nimport { usePoiMarker } from \"./usePoiMarker\";\r\n\r\n// ─── 注入地图上下文 ────────────────────────────────────────────────────────────\r\nconst mapCtx = inject<UseMapReturn>(\"mapContext\");\r\nif (!mapCtx) throw new Error(\"[PoiMarkerLayer] 必须放置在 MarsMapContainer 内部\");\r\n\r\n// ─── 初始化 POI 管理 composable ────────────────────────────────────────────────\r\nconst poi = usePoiMarker(mapCtx);\r\n\r\n// ─── 等待地图就绪后初始化图层 ─────────────────────────────────────────────────\r\n// map 在 MarsMapContainer onload 后才不为 null\r\nconst stopWatch = watch(\r\n () => mapCtx.map.value,\r\n (map) => {\r\n if (map) {\r\n poi.initPoiLayer();\r\n stopWatch(); // 只需初始化一次\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n\r\nonUnmounted(() => {\r\n poi.clearAll();\r\n});\r\n\r\n// ─── provide 给同级业务组件(PoiMarkerPanel 等)─────────────────────────────\r\nprovide(\"poiContext\", poi);\r\n\r\n// ─── expose 给父组件 ref ──────────────────────────────────────────────────────\r\ndefineExpose(poi);\r\n</script>\r\n","<!--\r\n PoiMarkerPanel — POI 标注管理面板(左侧)\r\n\r\n 功能:\r\n - 标注列表(名称 / 分类标签 / 定位 / 删除)\r\n - 添加模式切换按钮(点击地图新增标注)\r\n - 分类筛选标签\r\n - 点击列表项飞行到标注位置 + 地图高亮\r\n\r\n 数据来源:inject('poiContext'),由同级 PoiMarkerLayer 提供\r\n-->\r\n<template>\r\n <div\r\n ref=\"panelEl\"\r\n class=\"poi-panel\"\r\n :class=\"{ collapsed: isCollapsed }\"\r\n :style=\"\r\n !isCollapsed\r\n ? { left: pos.x + 'px', top: pos.y + 'px' }\r\n : { left: pos.x + 'px', top: pos.y + 'px' }\r\n \"\r\n >\r\n <!-- 面板标题栏(可拖拽) -->\r\n <div\r\n class=\"poi-panel__header\"\r\n :class=\"{ 'is-dragging': isDragging }\"\r\n @mousedown.prevent=\"startDrag\"\r\n @click=\"isDragging ? null : toggleCollapse()\"\r\n >\r\n <!-- 收缩后只显示图标 -->\r\n <template v-if=\"isCollapsed\">\r\n <div class=\"collapsed-icon-wrap\">\r\n <i class=\"fa fa-map-marker collapsed-icon\" />\r\n <span class=\"poi-count poi-count--collapsed\">{{\r\n filteredList.length\r\n }}</span>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span class=\"poi-panel__title\">\r\n <i class=\"fa fa-map-marker\" />\r\n POI 标注管理\r\n <span class=\"poi-count\">{{ filteredList.length }}</span>\r\n </span>\r\n <i class=\"fa fa-chevron-left collapse-icon\" />\r\n </template>\r\n </div>\r\n\r\n <div class=\"poi-panel__body\" v-show=\"!isCollapsed\">\r\n <!-- 操作栏 -->\r\n <div class=\"poi-panel__toolbar\">\r\n <button\r\n class=\"btn\"\r\n :class=\"{ 'btn--active': poi.isAddMode.value }\"\r\n @click=\"toggleAdd\"\r\n >\r\n <i :class=\"['fa', poi.isAddMode.value ? 'fa-times' : 'fa-plus']\" />\r\n {{ poi.isAddMode.value ? \"取消添加\" : \"点击地图添加\" }}\r\n </button>\r\n <button\r\n class=\"btn btn--danger\"\r\n @click=\"confirmClear\"\r\n :disabled=\"poi.poiList.value.length === 0\"\r\n >\r\n <i class=\"fa fa-trash-o\" /> 清空\r\n </button>\r\n </div>\r\n\r\n <!-- 分类筛选 -->\r\n <div class=\"poi-panel__filter\">\r\n <span\r\n v-for=\"cat in categories\"\r\n :key=\"cat.value\"\r\n class=\"filter-tag\"\r\n :class=\"{ active: activeCategory === cat.value }\"\r\n @click=\"activeCategory = cat.value\"\r\n >\r\n <i :class=\"['fa', cat.icon]\" :style=\"{ color: cat.color }\" />\r\n {{ cat.label }}\r\n </span>\r\n </div>\r\n\r\n <!-- POI 列表 -->\r\n <div class=\"poi-panel__list\">\r\n <TransitionGroup name=\"poi-list\">\r\n <div\r\n v-for=\"item in filteredList\"\r\n :key=\"item.id\"\r\n class=\"poi-item\"\r\n :class=\"{ 'poi-item--active': poi.activePoiId.value === item.id }\"\r\n @click=\"onSelect(item.id)\"\r\n >\r\n <!-- 分类色块 -->\r\n <span\r\n class=\"poi-item__dot\"\r\n :style=\"{ background: getCategoryColor(item.category) }\"\r\n />\r\n\r\n <div class=\"poi-item__info\">\r\n <!-- 编辑态:输入框 -->\r\n <input\r\n v-if=\"editingId === item.id\"\r\n class=\"poi-item__name-input\"\r\n v-model=\"editName\"\r\n @keydown.enter=\"saveEdit\"\r\n @keydown.escape=\"cancelEdit\"\r\n @click.stop\r\n ref=\"editInputEl\"\r\n />\r\n <!-- 正常态:名称 -->\r\n <div\r\n v-else\r\n class=\"poi-item__name\"\r\n @dblclick.stop=\"startEdit(item)\"\r\n >\r\n {{ item.name }}\r\n </div>\r\n <div class=\"poi-item__coord\">\r\n {{ item.lng.toFixed(4) }}, {{ item.lat.toFixed(4) }}\r\n </div>\r\n </div>\r\n\r\n <!-- 操作按钮 -->\r\n <div class=\"poi-item__actions\">\r\n <button\r\n class=\"icon-btn\"\r\n title=\"编辑名称\"\r\n @click.stop=\"startEdit(item)\"\r\n >\r\n <i class=\"fa fa-pencil\" />\r\n </button>\r\n <button\r\n class=\"icon-btn\"\r\n title=\"飞行定位\"\r\n @click.stop=\"onFlyTo(item.id)\"\r\n >\r\n <i class=\"fa fa-crosshairs\" />\r\n </button>\r\n <button\r\n class=\"icon-btn icon-btn--danger\"\r\n title=\"删除\"\r\n @click.stop=\"onRemove(item.id)\"\r\n >\r\n <i class=\"fa fa-times\" />\r\n </button>\r\n </div>\r\n </div>\r\n </TransitionGroup>\r\n\r\n <!-- 空状态 -->\r\n <div v-if=\"filteredList.length === 0\" class=\"poi-panel__empty\">\r\n <i class=\"fa fa-map-o\" />\r\n <p>\r\n {{\r\n poi.isAddMode.value ? \"请在地图上点击添加标注\" : \"暂无标注数据\"\r\n }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, computed, inject } from \"vue\";\r\nimport type { UsePoiMarkerReturn, PoiItem } from \"./usePoiMarker\";\r\n\r\n// ─── 注入 POI 上下文(由 PoiMarkerLayer provide) ────────────────────────────\r\nconst poi = inject<UsePoiMarkerReturn>(\"poiContext\");\r\nif (!poi) throw new Error(\"[PoiMarkerPanel] 必须与 PoiMarkerLayer 同级使用\");\r\n\r\n// ─── 面板状态 ─────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(true);\r\nconst toggleCollapse = () => {\r\n isCollapsed.value = !isCollapsed.value;\r\n};\r\n\r\n// ─── 拖拽移动 ─────────────────────────────────────────────────────────────────\r\nconst panelEl = ref<HTMLElement | null>(null);\r\nconst isDragging = ref(false);\r\n\r\n// 初始位置(可随需求调整)\r\nconst pos = reactive({ x: 10, y: 10 });\r\n\r\nlet dragStartX = 0;\r\nlet dragStartY = 0;\r\nlet origX = 0;\r\nlet origY = 0;\r\n\r\nfunction startDrag(e: MouseEvent) {\r\n isDragging.value = true;\r\n dragStartX = e.clientX;\r\n dragStartY = e.clientY;\r\n origX = pos.x;\r\n origY = pos.y;\r\n\r\n document.addEventListener(\"mousemove\", onDrag);\r\n document.addEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\nfunction onDrag(e: MouseEvent) {\r\n if (!isDragging.value) return;\r\n pos.x = origX + (e.clientX - dragStartX);\r\n pos.y = origY + (e.clientY - dragStartY);\r\n}\r\n\r\nfunction stopDrag() {\r\n isDragging.value = false;\r\n document.removeEventListener(\"mousemove\", onDrag);\r\n document.removeEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\n// ─── 分类筛选 ─────────────────────────────────────────────────────────────────\r\nconst categories = [\r\n { value: \"all\", label: \"全部\", icon: \"fa-list\", color: \"#aaa\" },\r\n { value: \"default\", label: \"普通\", icon: \"fa-map-marker\", color: \"#3ea6ff\" },\r\n {\r\n value: \"warning\",\r\n label: \"警告\",\r\n icon: \"fa-exclamation-triangle\",\r\n color: \"#ff6b6b\",\r\n },\r\n { value: \"info\", label: \"信息\", icon: \"fa-info-circle\", color: \"#52c41a\" },\r\n] as const;\r\n\r\nconst activeCategory = ref<string>(\"all\");\r\n\r\nconst filteredList = computed(() => {\r\n if (activeCategory.value === \"all\") return poi.poiList.value;\r\n return poi.poiList.value.filter((p) => p.category === activeCategory.value);\r\n});\r\n\r\nconst getCategoryColor = (cat: PoiItem[\"category\"]) => {\r\n const map: Record<string, string> = {\r\n default: \"#3ea6ff\",\r\n warning: \"#ff6b6b\",\r\n info: \"#52c41a\",\r\n };\r\n return map[cat] ?? \"#aaa\";\r\n};\r\n\r\n// ─── 添加模式 ─────────────────────────────────────────────────────────────────\r\nconst addCategory = ref<PoiItem[\"category\"]>(\"default\");\r\n\r\nfunction toggleAdd() {\r\n poi.toggleAddMode(\r\n undefined, // onAdded 回调(可按需传)\r\n \"标注点\",\r\n addCategory.value,\r\n );\r\n}\r\n\r\n// ─── 列表操作 ─────────────────────────────────────────────────────────────────\r\nfunction onSelect(id: string) {\r\n poi.selectPoi(id, true); // 选中并飞行\r\n}\r\n\r\nfunction onFlyTo(id: string) {\r\n poi.flyToPoi(id);\r\n}\r\n\r\nfunction onRemove(id: string) {\r\n poi.removePoi(id);\r\n}\r\n\r\n// ─── 编辑名称 ─────────────────────────────────────────────────────────────────\r\nconst editingId = ref<string | null>(null);\r\nconst editName = ref(\"\");\r\nconst editInputEl = ref<HTMLInputElement | null>(null);\r\n\r\nfunction startEdit(item: PoiItem) {\r\n editingId.value = item.id;\r\n editName.value = item.name;\r\n // DOM 更新后自动聚焦\r\n setTimeout(() => editInputEl.value?.select(), 30);\r\n}\r\n\r\nfunction saveEdit() {\r\n if (editingId.value && editName.value.trim()) {\r\n poi.updatePoiName(editingId.value, editName.value.trim());\r\n }\r\n cancelEdit();\r\n}\r\n\r\nfunction cancelEdit() {\r\n editingId.value = null;\r\n editName.value = \"\";\r\n}\r\n\r\nfunction confirmClear() {\r\n if (window.confirm(`确认清空全部 ${poi.poiList.value.length} 个标注?`)) {\r\n poi.clearAll();\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── 主面板 ────────────────────────────────────────────────────────────────────\r\n.poi-panel {\r\n position: absolute;\r\n width: 260px;\r\n height: auto;\r\n max-height: calc(100vh - 40px);\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px;\r\n z-index: 999;\r\n display: flex;\r\n flex-direction: column;\r\n backdrop-filter: blur(4px);\r\n transition: width 0.25s ease;\r\n\r\n // 收缩状态:只保留标题栏宽度,内容自适应高度\r\n &.collapsed {\r\n width: 46px;\r\n max-height: none;\r\n overflow: hidden;\r\n\r\n .poi-panel__title {\r\n display: none;\r\n }\r\n .poi-panel__body {\r\n display: none;\r\n }\r\n .collapse-icon {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n// ─── 标题栏 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__header {\r\n position: relative; // 为收缩态角标 absolute 定位提供参考\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 14px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 6px 0 0;\r\n cursor: grab;\r\n user-select: none;\r\n flex-shrink: 0;\r\n\r\n &.is-dragging {\r\n cursor: grabbing;\r\n }\r\n\r\n // 收缩后的图标态\r\n .collapsed-icon {\r\n display: none;\r\n color: #3ea6ff;\r\n font-size: 18px;\r\n }\r\n\r\n .poi-panel__title {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: #e8f4ff;\r\n font-size: 14px;\r\n font-weight: 600;\r\n\r\n .fa {\r\n color: #3ea6ff;\r\n font-size: 15px;\r\n }\r\n }\r\n\r\n .poi-count {\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 11px;\r\n padding: 1px 6px;\r\n border-radius: 10px;\r\n min-width: 18px;\r\n text-align: center;\r\n }\r\n\r\n .collapse-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n }\r\n}\r\n\r\n// 收缩态:图标自适应高度,角标定位在图标右上角\r\n.poi-panel.collapsed .poi-panel__header {\r\n flex-direction: column;\r\n align-items: flex-start; // 左对齐\r\n padding: 8px 10px 10px; // 底部留更多空间\r\n gap: 0;\r\n cursor: pointer;\r\n\r\n // 图标 + 角标一体化容器,图标在左下\r\n .collapsed-icon-wrap {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-top: 12px; // 往下一点\r\n margin-left: 2px;\r\n }\r\n\r\n .collapsed-icon {\r\n display: block;\r\n font-size: 20px;\r\n color: #3ea6ff;\r\n }\r\n\r\n // 角标:相对于图标容器定位,落在图标右上角\r\n .poi-count--collapsed {\r\n display: block;\r\n position: absolute;\r\n top: -10px;\r\n right: -12px;\r\n min-width: 16px;\r\n height: 16px;\r\n line-height: 16px;\r\n font-size: 10px;\r\n padding: 0 3px;\r\n background: #3ea6ff;\r\n color: #fff;\r\n border-radius: 8px;\r\n }\r\n}\r\n\r\n// ─── 面板体 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__body {\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n// ─── 操作栏 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__toolbar {\r\n display: flex;\r\n gap: 8px;\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .btn {\r\n flex: 1;\r\n padding: 6px 8px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.35);\r\n color: #fff;\r\n border-color: #3ea6ff;\r\n }\r\n &--danger {\r\n flex: 0 0 auto;\r\n border-color: rgba(255, 100, 100, 0.4);\r\n background: rgba(255, 100, 100, 0.1);\r\n color: #ffaaaa;\r\n &:hover:not(:disabled) {\r\n background: rgba(255, 100, 100, 0.25);\r\n color: #fff;\r\n }\r\n &:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 分类筛选 ──────────────────────────────────────────────────────────────────\r\n.poi-panel__filter {\r\n display: flex;\r\n gap: 6px;\r\n padding: 8px 12px;\r\n flex-wrap: wrap;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .filter-tag {\r\n padding: 3px 8px;\r\n border-radius: 12px;\r\n font-size: 11px;\r\n color: #7a9ec0;\r\n background: rgba(255, 255, 255, 0.06);\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(255, 255, 255, 0.12);\r\n color: #c8dff0;\r\n }\r\n &.active {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #3ea6ff;\r\n }\r\n }\r\n}\r\n\r\n// ─── 列表 ──────────────────────────────────────────────────────────────────────\r\n.poi-panel__list {\r\n overflow-y: auto;\r\n max-height: calc(100vh - 220px);\r\n padding: 6px 0;\r\n\r\n &::-webkit-scrollbar {\r\n width: 4px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n\r\n.poi-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n transition: background 0.15s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.1);\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.18);\r\n }\r\n\r\n &__dot {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n flex-shrink: 0;\r\n }\r\n\r\n &__info {\r\n flex: 1;\r\n min-width: 0;\r\n &-name {\r\n overflow: hidden;\r\n }\r\n }\r\n\r\n &__name {\r\n font-size: 13px;\r\n color: #d8ecff;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n cursor: text;\r\n\r\n &:hover {\r\n color: #a0d4ff;\r\n }\r\n }\r\n\r\n &__name-input {\r\n width: 100%;\r\n font-size: 13px;\r\n color: #e8f4ff;\r\n background: rgba(62, 166, 255, 0.15);\r\n border: 1px solid rgba(62, 166, 255, 0.5);\r\n border-radius: 3px;\r\n padding: 1px 5px;\r\n outline: none;\r\n font-family: inherit;\r\n\r\n &:focus {\r\n border-color: #3ea6ff;\r\n background: rgba(62, 166, 255, 0.22);\r\n }\r\n }\r\n\r\n &__coord {\r\n font-size: 11px;\r\n color: #5a7a9a;\r\n margin-top: 2px;\r\n font-family: monospace;\r\n }\r\n\r\n &__actions {\r\n display: flex;\r\n gap: 4px;\r\n flex-shrink: 0;\r\n opacity: 0;\r\n transition: opacity 0.15s ease;\r\n }\r\n\r\n &:hover &__actions {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.icon-btn {\r\n width: 22px;\r\n height: 22px;\r\n border: none;\r\n background: rgba(255, 255, 255, 0.08);\r\n color: #9dc8f0;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 11px;\r\n transition: all 0.15s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n &--danger:hover {\r\n background: rgba(255, 80, 80, 0.35);\r\n color: #fff;\r\n }\r\n}\r\n\r\n// ─── 空状态 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__empty {\r\n text-align: center;\r\n padding: 30px 20px;\r\n color: #4a6a8a;\r\n\r\n .fa {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: block;\r\n }\r\n p {\r\n font-size: 12px;\r\n margin: 0;\r\n line-height: 1.6;\r\n }\r\n}\r\n\r\n// ─── 列表动画 ──────────────────────────────────────────────────────────────────\r\n.poi-list-enter-active,\r\n.poi-list-leave-active {\r\n transition: all 0.25s ease;\r\n}\r\n.poi-list-enter-from {\r\n opacity: 0;\r\n transform: translateX(-12px);\r\n}\r\n.poi-list-leave-to {\r\n opacity: 0;\r\n transform: translateX(12px);\r\n}\r\n</style>\r\n","/**\r\n * useTrack — 轨迹管理 composable\r\n *\r\n * 职责:\r\n * - 维护轨迹数据列表(历史轨迹 + 实时轨迹)\r\n * - 管理地图上的折线图形(PolylinePrimitive / CorridorPrimitive)\r\n * - 提供历史轨迹回放(播放 / 暂停 / 倍速 / 进度拖拽)\r\n * - 提供实时轨迹推送(持续追加坐标点)\r\n * - 数据与图形保持双向同步\r\n *\r\n * 使用方式(在 TrackLayer 内):\r\n * const mapCtx = inject<UseMapReturn>('mapContext')!\r\n * const track = useTrack(mapCtx)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\n\r\n// ─── 数据类型 ─────────────────────────────────────────────────────────────────\r\n\r\n/** 轨迹点 */\r\nexport interface TrackPoint {\r\n time: number; // Unix 时间戳(毫秒)\r\n lng: number;\r\n lat: number;\r\n alt: number;\r\n}\r\n\r\n/** 单条轨迹 */\r\nexport interface TrackItem {\r\n id: string;\r\n name: string;\r\n /** 轨迹点列表(按时间排序) */\r\n points: TrackPoint[];\r\n /** 轨迹线图形 */\r\n lineGraphic?: any;\r\n /** 实时模式下:当前\"已绘制\"到的点索引 */\r\n realtimeDrawnIdx?: number;\r\n /** 实时模式下:当前实时点图形 */\r\n realtimePoint?: any;\r\n /** 实时模式下:当前车头图标 */\r\n realtimeHeading?: any;\r\n /** 实时模式下:所有线段图形(用于删除时统一清理) */\r\n realtimeLineSegments?: any[];\r\n /** 回放开始时间戳 */\r\n _playStartTime?: number;\r\n}\r\n\r\nlet _idCounter = 1;\r\n\r\nexport function useTrack(mapCtx: UseMapReturn) {\r\n // ─── 图层 ─────────────────────────────────────────────────────────────────\r\n const trackLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── 轨迹列表 ─────────────────────────────────────────────────────────────\r\n const trackList = ref<TrackItem[]>([]);\r\n\r\n // ─── 当前选中 / 回放的轨迹 ────────────────────────────────────────────────\r\n const activeTrackId = ref<string | null>(null);\r\n\r\n // ─── 回放状态 ─────────────────────────────────────────────────────────────\r\n const isPlaying = ref(false);\r\n const currentTime = ref(0); // 当前回放时间戳\r\n const playbackSpeed = ref(1); // 倍速(1x / 2x / 4x / 8x)\r\n const playbackProgress = ref(0); // 0~100 百分比\r\n\r\n // ─── 实时模式标记 ──────────────────────────────────────────────────────────\r\n const isRealtimeMode = ref(false);\r\n const activeRealtimeId = ref<string | null>(null);\r\n\r\n // ─── 回放定时器 ───────────────────────────────────────────────────────────\r\n let _playInterval: ReturnType<typeof setInterval> | null = null;\r\n let _realtimeInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n // ─── 初始化图层 ────────────────────────────────────────────────────────────\r\n function initTrackLayer() {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n const layer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(layer);\r\n trackLayer.value = layer;\r\n }\r\n\r\n // ─── 内部:绘制完整折线 ────────────────────────────────────────────────────\r\n function _buildLineGraphic(track: TrackItem) {\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n // 只画已有坐标\r\n const positions = track.points.map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n const line = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#3ea6ff\") as any,\r\n width: 3,\r\n opacity: 0.9,\r\n clampToGround: false,\r\n },\r\n attr: { trackId: track.id },\r\n });\r\n\r\n layer.addGraphic(line);\r\n return line;\r\n }\r\n\r\n // ─── 内部:实时追加一段线 ──────────────────────────────────────────────────\r\n function _appendRealtimeLine(track: TrackItem, fromIdx: number, toIdx: number) {\r\n const layer = trackLayer.value;\r\n if (!layer || toIdx <= fromIdx) return;\r\n\r\n const positions = track.points.slice(fromIdx, toIdx + 1)\r\n .map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n const segment = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#ff6b35\") as any,\r\n width: 4,\r\n opacity: 1,\r\n clampToGround: false,\r\n },\r\n });\r\n layer.addGraphic(segment);\r\n // 记录线段引用,用于删除时统一清理\r\n if (!track.realtimeLineSegments) {\r\n track.realtimeLineSegments = [];\r\n }\r\n track.realtimeLineSegments.push(segment);\r\n }\r\n\r\n // ─── 内部:更新实时点位图标 ─────────────────────────────────────────────────\r\n function _updateRealtimeMarker(track: TrackItem) {\r\n const layer = trackLayer.value;\r\n if (!layer) return;\r\n\r\n const lastPoint = track.points[track.realtimeDrawnIdx!];\r\n if (!lastPoint) return;\r\n\r\n // 更新图标位置\r\n if (track.realtimePoint) {\r\n track.realtimePoint.position = [lastPoint.lng, lastPoint.lat, lastPoint.alt];\r\n } else {\r\n const marker = new mars3d.graphic.BillboardEntity({\r\n position: [lastPoint.lng, lastPoint.lat, lastPoint.alt],\r\n style: {\r\n image: \"//data.mars3d.cn/img/marker/mark-blue.png\",\r\n scale: 1.2,\r\n horizontalOrigin: mars3d.Cesium.HorizontalOrigin.CENTER,\r\n verticalOrigin: mars3d.Cesium.VerticalOrigin.BOTTOM,\r\n },\r\n });\r\n layer.addGraphic(marker);\r\n track.realtimePoint = marker;\r\n }\r\n }\r\n\r\n // ─── 添加历史轨迹(从预置数据回放) ─────────────────────────────────────────\r\n function addTrack(points: TrackPoint[], name = \"轨迹\") {\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `track-${_idCounter++}`;\r\n const track: TrackItem = { id, name, points };\r\n track.lineGraphic = _buildLineGraphic(track);\r\n trackList.value.push(track);\r\n return track;\r\n }\r\n\r\n // ─── 开始实时轨迹推送 ──────────────────────────────────────────────────────\r\n function startRealtime(name = \"实时轨迹\") {\r\n if (activeRealtimeId.value) stopRealtime();\r\n\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `realtime-${_idCounter++}`;\r\n const track: TrackItem = {\r\n id,\r\n name,\r\n points: [],\r\n realtimeDrawnIdx: -1,\r\n };\r\n trackLayer.value = layer;\r\n trackList.value.push(track);\r\n activeRealtimeId.value = id;\r\n isRealtimeMode.value = true;\r\n return track;\r\n }\r\n\r\n // ─── 推送实时坐标点 ───────────────────────────────────────────────────────\r\n function pushRealtimePoint(id: string, lng: number, lat: number, alt = 0) {\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track) return;\r\n\r\n const point: TrackPoint = {\r\n time: Date.now(),\r\n lng,\r\n lat,\r\n alt,\r\n };\r\n track.points.push(point);\r\n track.realtimeDrawnIdx = track.points.length - 1;\r\n\r\n // 首次:直接建线和图标\r\n if (track.points.length === 1) {\r\n track.lineGraphic = _buildLineGraphic(track);\r\n _updateRealtimeMarker(track);\r\n } else {\r\n // 追加一段折线\r\n _appendRealtimeLine(track, track.points.length - 2, track.points.length - 1);\r\n _updateRealtimeMarker(track);\r\n }\r\n\r\n // 自动飞行跟随(最后一点)\r\n if (mapCtx.map.value) {\r\n mapCtx.map.value.flyToPoint(\r\n [lng, lat, alt + 50],\r\n { radius: 500, duration: 0.5 },\r\n );\r\n }\r\n }\r\n\r\n // ─── 停止实时推送(固化轨迹) ──────────────────────────────────────────────\r\n function stopRealtime(id?: string) {\r\n const targetId = id ?? activeRealtimeId.value;\r\n if (!targetId) return;\r\n\r\n const track = trackList.value.find((t) => t.id === targetId);\r\n if (track) {\r\n track.realtimeDrawnIdx = undefined;\r\n if (track.realtimePoint) {\r\n trackLayer.value?.removeGraphic(track.realtimePoint);\r\n track.realtimePoint = undefined;\r\n }\r\n }\r\n\r\n if (activeRealtimeId.value === targetId) {\r\n activeRealtimeId.value = null;\r\n isRealtimeMode.value = false;\r\n }\r\n }\r\n\r\n // ─── 历史轨迹回放 ─────────────────────────────────────────────────────────\r\n function play(trackId?: string) {\r\n const id = trackId ?? activeTrackId.value;\r\n if (!id) return;\r\n\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track || track.points.length < 2) return;\r\n\r\n if (activeTrackId.value !== id) {\r\n selectTrack(id);\r\n }\r\n\r\n isPlaying.value = true;\r\n _clearPlayInterval();\r\n\r\n const start = track.points[0].time;\r\n const end = track.points[track.points.length - 1].time;\r\n const totalMs = end - start;\r\n\r\n // 进度每帧更新\r\n _playInterval = setInterval(() => {\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (!track || !isPlaying.value) return;\r\n\r\n const elapsed = Date.now() - (track._playStartTime ?? Date.now());\r\n const total = end - start;\r\n const progress = Math.min(elapsed / total, 1);\r\n\r\n // 更新当前时间 → 驱动进度条\r\n currentTime.value = start + progress * total;\r\n playbackProgress.value = progress * 100;\r\n\r\n // 逐步绘制轨迹\r\n const targetIdx = Math.floor(progress * (track.points.length - 1));\r\n _updatePlaybackLine(track, targetIdx);\r\n }, 60);\r\n }\r\n\r\n function _updatePlaybackLine(track: TrackItem, toIdx: number) {\r\n const layer = trackLayer.value;\r\n if (!layer) return;\r\n\r\n // 清除旧线\r\n if (track.lineGraphic) {\r\n layer.removeGraphic(track.lineGraphic);\r\n }\r\n\r\n // 画到 toIdx 位置\r\n const positions = track.points.slice(0, toIdx + 1)\r\n .map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n track.lineGraphic = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#00ff88\") as any,\r\n width: 4,\r\n opacity: 1,\r\n clampToGround: false,\r\n },\r\n });\r\n layer.addGraphic(track.lineGraphic);\r\n\r\n // 画当前点位\r\n const pt = track.points[toIdx];\r\n mapCtx.map.value?.flyToPoint(\r\n [pt.lng, pt.lat, pt.alt + 200],\r\n { radius: 300, duration: 0 },\r\n );\r\n }\r\n\r\n function pause() {\r\n isPlaying.value = false;\r\n _clearPlayInterval();\r\n }\r\n\r\n function stop() {\r\n isPlaying.value = false;\r\n playbackProgress.value = 0;\r\n currentTime.value = 0;\r\n _clearPlayInterval();\r\n\r\n // 恢复整条轨迹\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (track && trackLayer.value) {\r\n if (track.lineGraphic) trackLayer.value.removeGraphic(track.lineGraphic);\r\n track.lineGraphic = _buildLineGraphic(track);\r\n }\r\n }\r\n\r\n function setSpeed(speed: number) {\r\n playbackSpeed.value = speed;\r\n if (isPlaying.value) {\r\n pause();\r\n play();\r\n }\r\n }\r\n\r\n /** 跳转到指定进度(0~100) */\r\n function seek(progress: number) {\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (!track) return;\r\n\r\n const targetIdx = Math.floor((progress / 100) * (track.points.length - 1));\r\n currentTime.value = track.points[targetIdx].time;\r\n playbackProgress.value = progress;\r\n _updatePlaybackLine(track, targetIdx);\r\n }\r\n\r\n // ─── 选中轨迹 ─────────────────────────────────────────────────────────────\r\n function selectTrack(id: string) {\r\n activeTrackId.value = id;\r\n stop();\r\n }\r\n\r\n /** 飞行到轨迹概览 */\r\n function flyToTrack(id: string) {\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track || !mapCtx.map.value) return;\r\n\r\n const first = track.points[0];\r\n mapCtx.map.value.flyToPoint(\r\n [first.lng, first.lat, first.alt + 2000],\r\n { radius: 3000, duration: 1.5 },\r\n );\r\n }\r\n\r\n // ─── 删除 / 清空 ───────────────────────────────────────────────────────────\r\n function removeTrack(id: string) {\r\n const idx = trackList.value.findIndex((t) => t.id === id);\r\n if (idx === -1) return;\r\n\r\n const track = trackList.value[idx];\r\n if (track.lineGraphic) trackLayer.value?.removeGraphic(track.lineGraphic);\r\n if (track.realtimePoint) trackLayer.value?.removeGraphic(track.realtimePoint);\r\n // 删除实时轨迹的所有线段\r\n if (track.realtimeLineSegments) {\r\n track.realtimeLineSegments.forEach((seg) => {\r\n trackLayer.value?.removeGraphic(seg);\r\n });\r\n }\r\n trackList.value.splice(idx, 1);\r\n\r\n if (activeTrackId.value === id) {\r\n activeTrackId.value = null;\r\n stop();\r\n }\r\n if (activeRealtimeId.value === id) {\r\n activeRealtimeId.value = null;\r\n isRealtimeMode.value = false;\r\n }\r\n }\r\n\r\n function clearAll() {\r\n stop();\r\n stopRealtime();\r\n trackLayer.value?.clear();\r\n trackList.value = [];\r\n activeTrackId.value = null;\r\n }\r\n\r\n // ─── 内部工具 ─────────────────────────────────────────────────────────────\r\n function _clearPlayInterval() {\r\n if (_playInterval) {\r\n clearInterval(_playInterval);\r\n _playInterval = null;\r\n }\r\n }\r\n\r\n return {\r\n trackLayer,\r\n trackList,\r\n activeTrackId,\r\n isPlaying,\r\n currentTime,\r\n playbackSpeed,\r\n playbackProgress,\r\n isRealtimeMode,\r\n activeRealtimeId,\r\n initTrackLayer,\r\n addTrack,\r\n startRealtime,\r\n pushRealtimePoint,\r\n stopRealtime,\r\n play,\r\n pause,\r\n stop,\r\n setSpeed,\r\n seek,\r\n selectTrack,\r\n flyToTrack,\r\n removeTrack,\r\n clearAll,\r\n };\r\n}\r\n\r\nexport type UseTrackReturn = ReturnType<typeof useTrack>;\r\n","<!--\r\n TrackLayer — 轨迹组件逻辑层\r\n\r\n 职责:\r\n - 放置在 MarsMapContainer 的 slot 内(通过 <slot /> 渲染子组件)\r\n - inject mapContext,初始化轨迹图层\r\n - provide trackContext,供子组件 inject 使用\r\n - expose useTrack 全量接口,供父组件 ref 访问\r\n\r\n 使用方式(Panel 必须作为子内容传入):\r\n <MarsMapContainer>\r\n <TrackLayer ref=\"trackLayerRef\">\r\n <TrackPanel />\r\n </TrackLayer>\r\n </MarsMapContainer>\r\n-->\r\n<template>\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { inject, provide, watch, onUnmounted } from \"vue\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\nimport { useTrack } from \"./useTrack\";\r\n\r\n// ─── 注入地图上下文 ──────────────────────────────────────────────────────────\r\nconst mapCtx = inject<UseMapReturn>(\"mapContext\");\r\nif (!mapCtx) throw new Error(\"[TrackLayer] 必须放置在 MarsMapContainer 内部\");\r\n\r\n// ─── 初始化轨迹管理 ──────────────────────────────────────────────────────────\r\nconst track = useTrack(mapCtx);\r\n\r\n// ─── 等待地图就绪后初始化图层 ───────────────────────────────────────────────\r\nconst stopWatch = watch(\r\n () => mapCtx.map.value,\r\n (map) => {\r\n if (map) {\r\n track.initTrackLayer();\r\n stopWatch();\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n\r\nonUnmounted(() => {\r\n track.clearAll();\r\n});\r\n\r\n// ─── provide 给子组件 ───────────────────────────────────────────────────────\r\nprovide(\"trackContext\", track);\r\n\r\n// ─── expose 给父组件 ref ───────────────────────────────────────────────────\r\ndefineExpose(track);\r\n</script>\r\n","<!--\r\n TrackPanel — 轨迹管理面板\r\n\r\n 功能:\r\n - 轨迹列表管理(添加历史轨迹 / 实时轨迹)\r\n - 历史轨迹回放控制(播放 / 暂停 / 停止 / 倍速 / 进度拖拽)\r\n - 实时轨迹推送(开始 / 追加模拟点 / 停止)\r\n - 拖拽移动 + 收缩图标态\r\n\r\n 数据来源:inject('trackContext'),由 TrackLayer provide\r\n-->\r\n<template>\r\n <div\r\n class=\"track-panel\"\r\n :class=\"{ collapsed: isCollapsed }\"\r\n :style=\"{ left: pos.x + 'px', top: pos.y + 'px' }\"\r\n >\r\n <!-- 标题栏(可拖拽) -->\r\n <div\r\n class=\"track-panel__header\"\r\n :class=\"{ 'is-dragging': isDragging }\"\r\n @mousedown.prevent=\"startDrag\"\r\n @click=\"isDragging ? null : toggleCollapse()\"\r\n >\r\n <template v-if=\"isCollapsed\">\r\n <div class=\"collapsed-icon-wrap\">\r\n <i class=\"fa fa-share-alt collapsed-icon\" />\r\n <span class=\"track-badge\">{{ track.trackList.value.length }}</span>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span class=\"track-panel__title\">\r\n <i class=\"fa fa-share-alt\" />\r\n 轨迹管理\r\n <span class=\"track-count\">{{ track.trackList.value.length }}</span>\r\n </span>\r\n <i class=\"fa fa-chevron-left collapse-icon\" />\r\n </template>\r\n </div>\r\n\r\n <!-- 面板体 -->\r\n <div class=\"track-panel__body\" v-show=\"!isCollapsed\">\r\n <!-- ── 操作栏 ── -->\r\n <div class=\"track-panel__toolbar\">\r\n <button class=\"btn btn--primary\" @click=\"addDemoTrack\">\r\n <i class=\"fa fa-plus\" /> 历史轨迹\r\n </button>\r\n <button\r\n class=\"btn\"\r\n :class=\"track.isRealtimeMode.value ? 'btn--active' : 'btn--info'\"\r\n @click=\"toggleRealtime\"\r\n >\r\n <i\r\n :class=\"['fa', track.isRealtimeMode.value ? 'fa-stop' : 'fa-bolt']\"\r\n />\r\n {{ track.isRealtimeMode.value ? \"停止推送\" : \"实时轨迹\" }}\r\n </button>\r\n <button\r\n class=\"btn btn--danger\"\r\n @click=\"confirmClear\"\r\n :disabled=\"track.trackList.value.length === 0\"\r\n >\r\n <i class=\"fa fa-trash-o\" />\r\n </button>\r\n </div>\r\n\r\n <!-- ── 回放控制(选中轨迹时显示) ── -->\r\n <div class=\"track-panel__playback\" v-if=\"track.activeTrackId.value\">\r\n <!-- 轨迹名称 -->\r\n <div class=\"playback__track-name\">\r\n <i class=\"fa fa-road\" />\r\n {{ activeTrackName }}\r\n <span class=\"playback__mode-badge\">历史回放</span>\r\n </div>\r\n\r\n <!-- 播放按钮组 -->\r\n <div class=\"playback__controls\">\r\n <button class=\"ctrl-btn\" @click=\"track.stop()\">\r\n <i class=\"fa fa-stop\" />\r\n </button>\r\n <button\r\n class=\"ctrl-btn ctrl-btn--play\"\r\n @click=\"track.isPlaying.value ? track.pause() : track.play()\"\r\n >\r\n <i\r\n :class=\"['fa', track.isPlaying.value ? 'fa-pause' : 'fa-play']\"\r\n />\r\n </button>\r\n <button class=\"ctrl-btn\" @click=\"track.play()\">\r\n <i class=\"fa fa-refresh\" />\r\n </button>\r\n </div>\r\n\r\n <!-- 倍速选择 -->\r\n <div class=\"playback__speed\">\r\n <span class=\"speed-label\">倍速</span>\r\n <div class=\"speed-btns\">\r\n <button\r\n v-for=\"s in speedOptions\"\r\n :key=\"s\"\r\n class=\"speed-btn\"\r\n :class=\"{ active: track.playbackSpeed.value === s }\"\r\n @click=\"track.setSpeed(s)\"\r\n >\r\n {{ s }}x\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- 进度条 -->\r\n <div class=\"playback__timeline\">\r\n <span class=\"time-label\">{{\r\n formatTime(track.currentTime.value)\r\n }}</span>\r\n <input\r\n type=\"range\"\r\n class=\"progress-slider\"\r\n min=\"0\"\r\n max=\"100\"\r\n step=\"0.1\"\r\n :value=\"track.playbackProgress.value\"\r\n @input=\"onSeek\"\r\n />\r\n <span class=\"time-label\">{{ formatTime(trackMaxTime) }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- ── 实时模式指示 ── -->\r\n <div\r\n class=\"track-panel__realtime-hint\"\r\n v-if=\"track.isRealtimeMode.value && !track.activeTrackId.value\"\r\n >\r\n <div class=\"realtime-pulse\">\r\n <i class=\"fa fa-bolt\" />\r\n 实时推送中\r\n <span class=\"blink-dot\" />\r\n </div>\r\n <div class=\"realtime-count\">\r\n 已推送 <strong>{{ realtimePointCount }}</strong> 个坐标点\r\n </div>\r\n </div>\r\n\r\n <!-- ── 轨迹列表 ── -->\r\n <div class=\"track-panel__list\">\r\n <TransitionGroup name=\"track-list\">\r\n <div\r\n v-for=\"item in track.trackList.value\"\r\n :key=\"item.id\"\r\n class=\"track-item\"\r\n :class=\"{\r\n 'track-item--active': track.activeTrackId.value === item.id,\r\n 'track-item--realtime': item.id.startsWith('realtime'),\r\n }\"\r\n @click=\"onSelectTrack(item.id)\"\r\n >\r\n <!-- 颜色条 -->\r\n <span\r\n class=\"track-item__bar\"\r\n :style=\"{\r\n background: item.id.startsWith('realtime')\r\n ? '#ff6b35'\r\n : '#3ea6ff',\r\n }\"\r\n />\r\n\r\n <div class=\"track-item__info\">\r\n <div class=\"track-item__name\">\r\n <i\r\n :class=\"[\r\n 'fa',\r\n item.id.startsWith('realtime') ? 'fa-bolt' : 'fa-road',\r\n ]\"\r\n />\r\n {{ item.name }}\r\n </div>\r\n <div class=\"track-item__meta\">\r\n {{ item.points.length }} 个点\r\n <span v-if=\"item.id.startsWith('realtime')\" class=\"realtime-tag\"\r\n >实时</span\r\n >\r\n </div>\r\n </div>\r\n\r\n <div class=\"track-item__actions\">\r\n <button\r\n class=\"icon-btn\"\r\n title=\"飞行\"\r\n @click.stop=\"track.flyToTrack(item.id)\"\r\n >\r\n <i class=\"fa fa-crosshairs\" />\r\n </button>\r\n <button\r\n class=\"icon-btn icon-btn--danger\"\r\n title=\"删除\"\r\n @click.stop=\"track.removeTrack(item.id)\"\r\n >\r\n <i class=\"fa fa-times\" />\r\n </button>\r\n </div>\r\n </div>\r\n </TransitionGroup>\r\n\r\n <!-- 空状态 -->\r\n <div\r\n v-if=\"track.trackList.value.length === 0\"\r\n class=\"track-panel__empty\"\r\n >\r\n <i class=\"fa fa-map-o\" />\r\n <p>暂无轨迹数据</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, inject, reactive } from \"vue\";\r\nimport type { UseTrackReturn } from \"./useTrack\";\r\n\r\n// ─── 注入轨迹上下文 ──────────────────────────────────────────────────────────\r\nconst track = inject<UseTrackReturn>(\"trackContext\");\r\nif (!track) throw new Error(\"[TrackPanel] 必须与 TrackLayer 同级使用\");\r\n\r\n// ─── 拖拽 ──────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(true);\r\nconst isDragging = ref(false);\r\nconst pos = reactive({ x: 10, y: 80 }); // 默认错开 POI 面板\r\n\r\nlet dragStartX = 0,\r\n dragStartY = 0,\r\n origX = 0,\r\n origY = 0;\r\n\r\nfunction toggleCollapse() {\r\n isCollapsed.value = !isCollapsed.value;\r\n}\r\n\r\nfunction startDrag(e: MouseEvent) {\r\n isDragging.value = true;\r\n dragStartX = e.clientX;\r\n dragStartY = e.clientY;\r\n origX = pos.x;\r\n origY = pos.y;\r\n document.addEventListener(\"mousemove\", onDrag);\r\n document.addEventListener(\"mouseup\", stopDrag);\r\n}\r\nfunction onDrag(e: MouseEvent) {\r\n if (!isDragging.value) return;\r\n pos.x = origX + (e.clientX - dragStartX);\r\n pos.y = origY + (e.clientY - dragStartY);\r\n}\r\nfunction stopDrag() {\r\n isDragging.value = false;\r\n document.removeEventListener(\"mousemove\", onDrag);\r\n document.removeEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\n// ─── 选中轨迹 ──────────────────────────────────────────────────────────────\r\nfunction onSelectTrack(id: string) {\r\n if (track.activeTrackId.value === id) return;\r\n track.selectTrack(id);\r\n track.stop();\r\n}\r\n\r\nconst activeTrackName = computed(() => {\r\n const t = track.trackList.value.find(\r\n (x) => x.id === track.activeTrackId.value,\r\n );\r\n return t?.name ?? \"\";\r\n});\r\n\r\nconst trackMaxTime = computed(() => {\r\n const t = track.trackList.value.find(\r\n (x) => x.id === track.activeTrackId.value,\r\n );\r\n if (!t || t.points.length < 2) return 0;\r\n return t.points[t.points.length - 1].time;\r\n});\r\n\r\n// ─── 倍速选项 ──────────────────────────────────────────────────────────────\r\nconst speedOptions = [1, 2, 4, 8];\r\n\r\n// ─── 进度拖拽 ─────────────────────────────────────────────────────────────\r\nfunction onSeek(e: Event) {\r\n const val = parseFloat((e.target as HTMLInputElement).value);\r\n track.seek(val);\r\n}\r\n\r\n// ─── 时间格式化 ────────────────────────────────────────────────────────────\r\nfunction formatTime(ts: number): string {\r\n if (!ts) return \"00:00\";\r\n const d = new Date(ts);\r\n return `${String(d.getMinutes()).padStart(2, \"0\")}:${String(d.getSeconds()).padStart(2, \"0\")}`;\r\n}\r\n\r\n// ─── 添加演示历史轨迹 ─────────────────────────────────────────────────────\r\nfunction addDemoTrack() {\r\n // 生成一段北京区域贴近实际的路径:方向惯性 + 高度随路线起伏\r\n const baseLng = 116.3974;\r\n const baseLat = 39.909;\r\n const points = [];\r\n let t = Date.now();\r\n\r\n // 初始方向角(弧度)\r\n let heading = Math.random() * Math.PI * 2;\r\n const STEP = 20; // 减少到 20 个点\r\n\r\n for (let i = 0; i < STEP; i++) {\r\n t += 5000 + Math.random() * 5000;\r\n // 方向每步微调 ±15°,模拟沿道路行驶\r\n heading += (Math.random() - 0.5) * (Math.PI / 6);\r\n const stepLng = baseLng + Math.cos(heading) * 0.004;\r\n const stepLat = baseLat + Math.sin(heading) * 0.002;\r\n const alt = 30 + Math.sin((i / STEP) * Math.PI) * 80; // 拱形起伏\r\n points.push({ time: t, lng: stepLng, lat: stepLat, alt });\r\n }\r\n\r\n track.addTrack(points, `轨迹 ${_counter++}`);\r\n}\r\n\r\nlet _counter = 1;\r\n\r\n// ─── 实时轨迹 ─────────────────────────────────────────────────────────────\r\nlet _realtimeTimer: ReturnType<typeof setInterval> | null = null;\r\nlet _currentRealtimeId: string | null = null;\r\n\r\nfunction toggleRealtime() {\r\n if (track.isRealtimeMode.value) {\r\n stopRealtime();\r\n } else {\r\n startRealtime();\r\n }\r\n}\r\n\r\nfunction startRealtime() {\r\n const id = track.startRealtime(`实时轨迹 ${_counter++}`)?.id;\r\n if (!id) return;\r\n _currentRealtimeId = id;\r\n\r\n // 天安门坐标(圆心)\r\n const CENTER_LNG = 116.397;\r\n const CENTER_LAT = 39.908;\r\n // 绕圈半径(约 400 米)\r\n const RADIUS_LNG = 0.004;\r\n const RADIUS_LAT = 0.003;\r\n // 总共 36 个点,每 10° 一个点,完成一圈\r\n const TOTAL_POINTS = 36;\r\n const ANGLE_STEP = (2 * Math.PI) / TOTAL_POINTS;\r\n // 初始角度随机,让起点不在固定位置\r\n let angle = Math.random() * 2 * Math.PI;\r\n let pushCount = 0;\r\n\r\n _realtimeTimer = setInterval(() => {\r\n pushCount++;\r\n // 沿圆形轨迹移动\r\n const lng = CENTER_LNG + Math.cos(angle) * RADIUS_LNG;\r\n const lat = CENTER_LAT + Math.sin(angle) * RADIUS_LAT;\r\n const alt = 40 + Math.sin(angle * 3) * 20; // 高度随位置微微起伏\r\n track.pushRealtimePoint(id, lng, lat, alt);\r\n\r\n // 角度递增,绘制下一位置\r\n angle += ANGLE_STEP;\r\n\r\n // 完成一圈后自动停止\r\n if (pushCount >= TOTAL_POINTS) {\r\n stopRealtime();\r\n }\r\n }, 800);\r\n}\r\n\r\nfunction stopRealtime() {\r\n if (_realtimeTimer) {\r\n clearInterval(_realtimeTimer);\r\n _realtimeTimer = null;\r\n }\r\n if (_currentRealtimeId) {\r\n track.stopRealtime(_currentRealtimeId);\r\n _currentRealtimeId = null;\r\n }\r\n}\r\n\r\nconst realtimePointCount = computed(() => {\r\n const t = track.trackList.value.find((x) => x.id === _currentRealtimeId);\r\n return t?.points.length ?? 0;\r\n});\r\n\r\n// ─── 清空 ─────────────────────────────────────────────────────────────────\r\nfunction confirmClear() {\r\n if (window.confirm(`确认清空全部 ${track.trackList.value.length} 条轨迹?`)) {\r\n stopRealtime();\r\n track.clearAll();\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── 主面板 ─────────────────────────────────────────────────────────────────\r\n.track-panel {\r\n position: absolute;\r\n width: 280px;\r\n height: auto;\r\n max-height: calc(100vh - 40px);\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px;\r\n z-index: 998;\r\n display: flex;\r\n flex-direction: column;\r\n backdrop-filter: blur(4px);\r\n transition: width 0.25s ease;\r\n\r\n &.collapsed {\r\n width: 46px;\r\n max-height: none;\r\n overflow: hidden;\r\n\r\n .track-panel__title {\r\n display: none;\r\n }\r\n .track-panel__body {\r\n display: none;\r\n }\r\n .collapse-icon {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n// ─── 标题栏 ────────────────────────────────────────────────────────────────\r\n.track-panel__header {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 14px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 6px 0 0;\r\n cursor: grab;\r\n user-select: none;\r\n flex-shrink: 0;\r\n\r\n &.is-dragging {\r\n cursor: grabbing;\r\n }\r\n\r\n .collapsed-icon {\r\n display: none;\r\n color: #ff6b35;\r\n font-size: 18px;\r\n }\r\n\r\n .track-panel__title {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: #e8f4ff;\r\n font-size: 14px;\r\n font-weight: 600;\r\n .fa {\r\n color: #ff6b35;\r\n font-size: 15px;\r\n }\r\n }\r\n\r\n // 展开态角标(红色)\r\n .track-count {\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 11px;\r\n padding: 1px 6px;\r\n border-radius: 10px;\r\n min-width: 18px;\r\n text-align: center;\r\n }\r\n\r\n .collapse-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n }\r\n}\r\n\r\n// 收缩态\r\n.track-panel.collapsed .track-panel__header {\r\n flex-direction: column;\r\n align-items: flex-start; // 左对齐\r\n padding: 8px 10px 10px; // 底部留更多空间\r\n gap: 0;\r\n cursor: pointer;\r\n\r\n // 图标 + 角标一体化容器,图标在左下,角标叠在图标右上\r\n .collapsed-icon-wrap {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-top: 12px; // 往下一点\r\n margin-left: 2px; // 往左一点\r\n }\r\n\r\n .collapsed-icon {\r\n display: block;\r\n color: #ff6b35;\r\n font-size: 18px;\r\n }\r\n\r\n // 角标:相对于图标容器定位,落在图标右上角\r\n .track-badge {\r\n position: absolute;\r\n top: -12px;\r\n right: -12px;\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 10px;\r\n font-weight: 600;\r\n min-width: 16px;\r\n height: 16px;\r\n line-height: 16px;\r\n text-align: center;\r\n border-radius: 8px;\r\n padding: 0 3px;\r\n }\r\n}\r\n\r\n// ─── 面板体 ────────────────────────────────────────────────────────────────\r\n.track-panel__body {\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n// ─── 操作栏 ───────────────────────────────────────────────────────────────\r\n.track-panel__toolbar {\r\n display: flex;\r\n gap: 6px;\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .btn {\r\n flex: 1;\r\n padding: 5px 8px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &--active {\r\n background: rgba(255, 100, 50, 0.35);\r\n color: #ffaa88;\r\n border-color: #ff6b35;\r\n }\r\n &--primary {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #fff;\r\n border-color: rgba(62, 166, 255, 0.6);\r\n }\r\n &--info {\r\n background: rgba(255, 107, 53, 0.2);\r\n color: #ffaa88;\r\n border-color: rgba(255, 107, 53, 0.5);\r\n }\r\n &--danger {\r\n flex: 0 0 auto;\r\n width: 36px;\r\n border-color: rgba(255, 80, 80, 0.4);\r\n background: rgba(255, 80, 80, 0.1);\r\n color: #ffaaaa;\r\n &:hover:not(:disabled) {\r\n background: rgba(255, 80, 80, 0.25);\r\n color: #fff;\r\n }\r\n &:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 回放控制 ─────────────────────────────────────────────────────────────\r\n.track-panel__playback {\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .playback__track-name {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 12px;\r\n color: #9dc8f0;\r\n margin-bottom: 8px;\r\n\r\n .fa {\r\n color: #00ff88;\r\n }\r\n .playback__mode-badge {\r\n background: rgba(0, 255, 136, 0.15);\r\n color: #00ff88;\r\n font-size: 10px;\r\n padding: 1px 6px;\r\n border-radius: 8px;\r\n margin-left: 4px;\r\n }\r\n }\r\n\r\n // 播放按钮组\r\n .playback__controls {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n margin-bottom: 8px;\r\n }\r\n\r\n // 单独控制按钮\r\n .ctrl-btn {\r\n width: 30px;\r\n height: 30px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 50%;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 12px;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n\r\n &--play {\r\n width: 38px;\r\n height: 38px;\r\n background: rgba(0, 200, 100, 0.2);\r\n border-color: rgba(0, 200, 100, 0.6);\r\n color: #00ff88;\r\n font-size: 15px;\r\n &:hover {\r\n background: rgba(0, 200, 100, 0.35);\r\n }\r\n }\r\n }\r\n\r\n // 倍速\r\n .playback__speed {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n margin-bottom: 8px;\r\n\r\n .speed-label {\r\n font-size: 11px;\r\n color: #5a7a9a;\r\n }\r\n .speed-btns {\r\n display: flex;\r\n gap: 4px;\r\n }\r\n .speed-btn {\r\n padding: 2px 7px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n background: rgba(255, 255, 255, 0.04);\r\n color: #7a9ec0;\r\n border-radius: 10px;\r\n font-size: 11px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #fff;\r\n }\r\n &.active {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #3ea6ff;\r\n border-color: #3ea6ff;\r\n }\r\n }\r\n }\r\n\r\n // 进度条\r\n .playback__timeline {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n\r\n .time-label {\r\n font-size: 10px;\r\n color: #5a7a9a;\r\n font-family: monospace;\r\n min-width: 36px;\r\n text-align: center;\r\n }\r\n\r\n .progress-slider {\r\n flex: 1;\r\n height: 4px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n background: rgba(62, 166, 255, 0.2);\r\n border-radius: 2px;\r\n outline: none;\r\n cursor: pointer;\r\n\r\n &::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #3ea6ff;\r\n cursor: pointer;\r\n box-shadow: 0 0 6px rgba(62, 166, 255, 0.6);\r\n }\r\n\r\n &::-moz-range-thumb {\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #3ea6ff;\r\n border: none;\r\n cursor: pointer;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 实时模式提示 ──────────────────────────────────────────────────────────\r\n.track-panel__realtime-hint {\r\n padding: 8px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n\r\n .realtime-pulse {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 12px;\r\n color: #ff6b35;\r\n .fa {\r\n color: #ff6b35;\r\n }\r\n }\r\n\r\n .blink-dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: #ff6b35;\r\n animation: blink 1s ease-in-out infinite;\r\n }\r\n\r\n .realtime-count {\r\n font-size: 11px;\r\n color: #7a9ec0;\r\n strong {\r\n color: #ff6b35;\r\n }\r\n }\r\n}\r\n\r\n@keyframes blink {\r\n 0%,\r\n 100% {\r\n opacity: 1;\r\n }\r\n 50% {\r\n opacity: 0.2;\r\n }\r\n}\r\n\r\n// ─── 轨迹列表 ─────────────────────────────────────────────────────────────\r\n.track-panel__list {\r\n overflow-y: auto;\r\n max-height: calc(100vh - 340px);\r\n padding: 6px 0;\r\n\r\n &::-webkit-scrollbar {\r\n width: 4px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n\r\n.track-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.1);\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.18);\r\n }\r\n &--realtime .track-item__bar {\r\n background: #ff6b35 !important;\r\n }\r\n\r\n &__bar {\r\n width: 3px;\r\n height: 30px;\r\n border-radius: 2px;\r\n background: #3ea6ff;\r\n flex-shrink: 0;\r\n }\r\n\r\n &__info {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n &__name {\r\n overflow: hidden;\r\n font-size: 13px;\r\n color: #ffffff;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n .fa {\r\n color: #8ab4d4;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n &__meta {\r\n font-size: 11px;\r\n color: #9dc8f0;\r\n margin-top: 2px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .realtime-tag {\r\n background: rgba(255, 107, 53, 0.2);\r\n color: #ff6b35;\r\n font-size: 10px;\r\n padding: 0 5px;\r\n border-radius: 6px;\r\n }\r\n\r\n &__actions {\r\n display: flex;\r\n gap: 4px;\r\n flex-shrink: 0;\r\n opacity: 0;\r\n transition: opacity 0.15s;\r\n }\r\n\r\n &:hover &__actions {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.icon-btn {\r\n width: 22px;\r\n height: 22px;\r\n border: none;\r\n background: rgba(255, 255, 255, 0.08);\r\n color: #9dc8f0;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 11px;\r\n transition: all 0.15s;\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n &--danger:hover {\r\n background: rgba(255, 80, 80, 0.35);\r\n color: #fff;\r\n }\r\n}\r\n\r\n// ─── 空状态 ────────────────────────────────────────────────────────────────\r\n.track-panel__empty {\r\n text-align: center;\r\n padding: 30px 20px;\r\n color: #4a6a8a;\r\n .fa {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: block;\r\n }\r\n p {\r\n font-size: 12px;\r\n margin: 0;\r\n }\r\n}\r\n\r\n// ─── 列表动画 ──────────────────────────────────────────────────────────────\r\n.track-list-enter-active,\r\n.track-list-leave-active {\r\n transition: all 0.25s ease;\r\n}\r\n.track-list-enter-from {\r\n opacity: 0;\r\n transform: translateX(-12px);\r\n}\r\n.track-list-leave-to {\r\n opacity: 0;\r\n transform: translateX(12px);\r\n}\r\n</style>\r\n","/**\r\n * Mars3D Vue3 Components - 统一导出入口\r\n *\r\n * @description 封装了 Mars3D 地图的基础能力(测量、绘制、视角控制)\r\n * 及业务组件(POI 标注、轨迹管理)的 Vue3 组件库\r\n *\r\n * @example\r\n * // 完整引入\r\n * import Mars3dVueComponents from '@your-org/mars3d-vue-components'\r\n * app.use(Mars3dVueComponents)\r\n *\r\n * // 按需引入\r\n * import { MarsMapContainer, useMap } from '@your-org/mars3d-vue-components'\r\n */\r\n\r\n// 引入全局样式(导航球、Cesium 控件等样式覆盖)\r\nimport \"./styles/mars3d-theme.css\";\r\n\r\n// 引入 Mars3D / Cesium 基础 CSS(导航球、罗盘、状态栏等控件样式)\r\nimport \"mars3d-cesium/Build/Cesium/Widgets/widgets.css\";\r\nimport \"mars3d/mars3d.css\";\r\n\r\n// ── 基础组件 ──────────────────────────────────────────────────────────────────\r\nexport { default as MarsMapContainer } from \"./components/mars-map/MarsMapContainer.vue\";\r\nexport { default as ToolbarPanel } from \"./components/mars-map/panels/ToolbarPanel.vue\";\r\nexport { default as VisionPanel } from \"./components/mars-map/panels/VisionPanel.vue\";\r\n\r\n// ── Composables ────────────────────────────────────────────────────────────────\r\nexport { useMap } from \"./components/mars-map/composables/useMap\";\r\nexport { useMeasure } from \"./components/mars-map/composables/useMeasure\";\r\nexport { useDraw } from \"./components/mars-map/composables/useDraw\";\r\nexport { useVision } from \"./components/mars-map/composables/useVision\";\r\n\r\n// ── 业务组件 ──────────────────────────────────────────────────────────────────\r\nexport { default as PoiMarkerLayer } from \"./components/business/poi-marker/PoiMarkerLayer.vue\";\r\nexport { default as PoiMarkerPanel } from \"./components/business/poi-marker/PoiMarkerPanel.vue\";\r\nexport { default as TrackLayer } from \"./components/business/track/TrackLayer.vue\";\r\nexport { default as TrackPanel } from \"./components/business/track/TrackPanel.vue\";\r\n\r\n// ── 业务 Composable ───────────────────────────────────────────────────────────\r\nexport { usePoiMarker } from \"./components/business/poi-marker/usePoiMarker\";\r\nexport { useTrack } from \"./components/business/track/useTrack\";\r\n\r\n// ── 类型导出 ─────────────────────────────────────────────────────────────────\r\nexport type { UseMapReturn } from \"./components/mars-map/composables/useMap\";\r\nexport type { DrawType } from \"./components/mars-map/composables/useDraw\";\r\nexport type {\r\n PoiItem,\r\n UsePoiMarkerReturn,\r\n} from \"./components/business/poi-marker/usePoiMarker\";\r\nexport type {\r\n TrackPoint,\r\n TrackItem,\r\n UseTrackReturn,\r\n} from \"./components/business/track/useTrack\";\r\n\r\n// ── 安装插件(完整引入时使用)─────────────────────────────────────────────────\r\nimport type { App, Component } from \"vue\";\r\nimport MarsMapContainer from \"./components/mars-map/MarsMapContainer.vue\";\r\nimport ToolbarPanel from \"./components/mars-map/panels/ToolbarPanel.vue\";\r\nimport VisionPanel from \"./components/mars-map/panels/VisionPanel.vue\";\r\nimport PoiMarkerLayer from \"./components/business/poi-marker/PoiMarkerLayer.vue\";\r\nimport PoiMarkerPanel from \"./components/business/poi-marker/PoiMarkerPanel.vue\";\r\nimport TrackLayer from \"./components/business/track/TrackLayer.vue\";\r\nimport TrackPanel from \"./components/business/track/TrackPanel.vue\";\r\n\r\nconst components: Record<string, Component> = {\r\n MarsMapContainer,\r\n ToolbarPanel,\r\n VisionPanel,\r\n PoiMarkerLayer,\r\n PoiMarkerPanel,\r\n TrackLayer,\r\n TrackPanel,\r\n};\r\n\r\nconst YiMapWeb = {\r\n install(app: App, options?: { prefix?: string }) {\r\n const prefix = options?.prefix ?? \"\";\r\n for (const [name, component] of Object.entries(components)) {\r\n app.component(prefix ? `${prefix}${name}` : name, component);\r\n }\r\n },\r\n};\r\n\r\nexport default YiMapWeb;\r\n"],"names":["mars3d","computed","toRaw","onMounted","onUnmounted","_createElementBlock","ref","_normalizeClass","_createElementVNode","_withDirectives","_hoisted_1","_hoisted_2","_Fragment","_renderList","_hoisted_4","_createVNode","_Transition","_openBlock","_hoisted_3","_toDisplayString","shallowRef","provide","MarsMap","_createBlock","_unref","_renderSlot","_idCounter","inject","watch","reactive","_normalizeStyle","_hoisted_5","_hoisted_6","_createTextVNode","_hoisted_8","_hoisted_10","_TransitionGroup","_hoisted_12","_withModifiers","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_19","track","_a","PoiMarkerLayer","TrackLayer"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAYO,MAAM,mBAAmBA,kBAAO,SAAS;AAAA;AAAA,IAE9C,gBAAgB;AACd,WAAK,KAAK,kBAAkB,KAAK,QAAQ,IAAI;AAAA,IAC/C;AAAA;AAAA,IAGA,aAAa;AACX,WAAK,aAAY;AAAA,IACnB;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,cAAc,UAAU;AAAA,ECV5C,MAAM,mBAAmBA,kBAAO,SAAS;AAAA;AAAA,IAE9C,gBAAgB;AACd,WAAK,KAAK,cAAc,KAAK,QAAQ,QAAQ,EAAE,UAAU,KAAK,WAAW;AAAA,IAC3E;AAAA;AAAA,IAGA,eAAe;AACb,WAAK,KAAK,YAAW;AAAA,IACvB;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,UAAU,UAAU;AAAA,ECVxC,MAAM,kBAAkBA,kBAAO,SAAS;AAAA,IAC7C,YAAY,UAAU,IAAI;AACxB,YAAM,OAAO;AAEb,WAAK,SAAS,KAAK,QAAQ,SAAS;AACpC,WAAK,UAAU,KAAK,QAAQ,UAAU,EAAE,KAAK,WAAW,KAAK,YAAY,KAAK,cAAY,SAAS,GAAG,OAAO,IAAG;AAAA,IAClH;AAAA;AAAA,IAGA,gBAAgB;AACd,WAAK,KAAK,cAAc,KAAK,SAAS;AAAA,QACpC,UAAU;AAAA,QACV,UAAU,MAAM;AACd,eAAK,KAAK,GAAGA,kBAAO,UAAU,WAAW,KAAK,kBAAkB,IAAI;AAAA,QACtE;AAAA,MACN,CAAK;AAAA,IACH;AAAA;AAAA,IAGA,eAAe;AACb,WAAK,KAAK,IAAIA,kBAAO,UAAU,WAAW,KAAK,kBAAkB,IAAI;AAAA,IACvE;AAAA,IAEA,mBAAmB;AACjB,UAAI,KAAK,SAAS;AAChB;AAAA,MACF;AAEA,WAAK,KAAK,MAAM,OAAO,OAAOA,kBAAO,OAAO,WAAW,QAAQ,KAAK,MAAM;AAAA,IAC5E;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,aAAa,SAAS;AAAA,EC5B1C,MAAM,oBAAoBA,kBAAO,SAAS;AAAA;AAAA,IAE/C,gBAAgB;AACd,UAAI,KAAK,QAAQ,QAAQ;AACvB,aAAK,KAAK,cAAc,KAAK,QAAQ,QAAQ,EAAE,UAAU,GAAG;AAAA,MAC9D;AAEA,UAAI,KAAK,QAAQ,UAAU;AACzB,eAAO,KAAK,QAAQ;AAAA,MACtB;AAEA,UAAI,KAAK,QAAQ,aAAa;AAC5B,aAAK,aAAa,IAAIA,kBAAO,MAAM,UAAU,KAAK,OAAO;AACzD,aAAK,KAAK,SAAS,KAAK,UAAU;AAAA,MACpC,OAAO;AACL,aAAK,eAAe,IAAIA,kBAAO,MAAM,YAAY,KAAK,OAAO;AAC7D,aAAK,KAAK,SAAS,KAAK,YAAY;AAAA,MACtC;AAEA,UAAI,KAAK,QAAQ,aAAa;AAC5B,aAAK,WAAW,MAAK;AAAA,MACvB,OAAO;AACL,aAAK,aAAa,MAAM,KAAK,QAAQ,KAAK;AAAA,MAC5C;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,cAAc;AACrB,aAAK,aAAa,KAAI;AACtB,aAAK,aAAa,QAAO;AACzB,eAAO,KAAK;AAAA,MACd;AACA,UAAI,KAAK,YAAY;AACnB,aAAK,WAAW,KAAI;AACpB,aAAK,WAAW,QAAO;AACvB,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,eAAe,WAAW;AAAA,EC5C9C,MAAM,kBAAkBA,kBAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAM7C,gBAAgB;AACd,WAAK,gBAAgB,IAAIA,kBAAO,MAAM,aAAY;AAClD,WAAK,KAAK,SAAS,KAAK,aAAa;AAErC,YAAM,aAAa,IAAIA,kBAAO,QAAQ,WAAW,KAAK,QAAQ,KAAK;AACnE,WAAK,cAAc,WAAW,UAAU;AACxC,WAAK,cAAc;AAEnB,iBAAW,MAAK;AAAA,IAClB;AAAA;AAAA,IAGA,WAAW,SAAS;AAClB,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,MAAK;AAAA,MACxB;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,QAAO;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,KAAI;AACrB,eAAO,KAAK;AAAA,MACd;AAEA,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc,QAAO;AAC1B,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,aAAa,SAAS;AAAA,EC5C1C,MAAM,eAAeA,kBAAO,SAAS;AAAA;AAAA,IAE1C,gBAAgB;AACd,WAAK,KAAK,OAAO,KAAK,QAAQ,cAAc;AAAA,IAC9C;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,UAAU,MAAM;AAAA,ECNpC,MAAM,gBAAgBA,kBAAO,SAAS;AAAA;AAAA,IAE3C,gBAAgB;AACd,WAAK,KAAK,QAAQ,KAAK,QAAQ,cAAc;AAAA,IAC/C;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,WAAW,OAAO;AAAA,ECDtC,MAAM,sBAAsBA,kBAAO,SAAS;AAAA;AAAA,IAEjD,gBAAgB;AACd,YAAM,QAAQ,KAAK,KAAK,aAAa,KAAK,QAAQ,OAAO;AACzD,UAAI,OAAO;AACT,cAAM,OAAO;AACb,cAAM,aAAa,KAAK,MAAM;AAC5B,eAAK,WAAW,MAAM,eAAe,KAAK,QAAQ,SAAS;AAC3D,cAAI,KAAK,UAAU;AACjB,iBAAK,SAAS,OAAO;AACrB,iBAAK,SAAS,aAAa;AAAA,cACzB,MAAM,KAAK;AAAA,cACX,MAAM,KAAK,QAAQ;AAAA,cACnB,UAAU,KAAK,QAAQ;AAAA,cACvB,OAAO,KAAK,QAAQ;AAAA,YAChC,CAAW;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,UAAU;AACjB,aAAK,SAAS,YAAW;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,iBAAiB,aAAa;AAAA,EC3ClD,MAAM,wBAAwBA,kBAAO,QAAQ,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKrE,IAAI,OAAO;AACT,aAAO,KAAK,MAAM;AAAA,IACpB;AAAA,IAEA,IAAI,KAAK,KAAK;AACZ,WAAK,MAAM,OAAO;AAElB,WAAK,MAAM,OAAO;AAAA,IACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,WAAW,OAAO;AAChB,YAAM,QAAQ;AACd,YAAM,QAAQ;AAAA,QACZ,GAAG;AAAA,QACH,MAAM,KAAK,MAAM;AAAA,QACjB,WAAW;AAAA,QACX,OAAO,MAAM,aAAa;AAAA,QAC1B,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,cAAc,OAAO,MAAM,SAAS;AAAA,MAC1C;AACI,UAAI,MAAM,iBAAiB;AACzB,cAAM,MAAM,6BAA6B,MAAM;AAAA,MACjD;AAEA,YAAM,WAAW,KAAK;AAAA,IACxB;AAAA,EACF;AAGAA,oBAAO,YAAY,SAAS,mBAAmB,eAAe;;;;;;;;;;;AC9B9D,YAAM,QAAQ;AAcd,UAAI;AAGJ,YAAM,YAAYC,IAAAA,SAAS,MAAM,oBAAoB,MAAM,MAAM,EAAE;AAGnE,YAAM,OAAO;AAEb,YAAM,aAAa,YAAY;AAE7B,YAAI;AACJ,YAAI,MAAM,KAAK;AAEb,uBAAa,MAAMD,kBAAO,KAAK,UAAU,EAAE,KAAK,MAAM,KAAK;AAC3D,cAAI,MAAM,SAAS;AACjB,yBAAaA,kBAAO,KAAK,MAAM,YAAYE,UAAM,MAAM,OAAO,CAAC;AAAA,UACjE;AAAA,QACF,WAAW,MAAM,SAAS;AACxB,uBAAaA,IAAAA,MAAM,MAAM,OAAO;AAAA,QAClC;AAICF,0BAAe,KAAK,gBAAgB;AAErC,cAAM,IAAIA,kBAAO,IAAI,UAAU,OAAO,UAAU;AAGhD,YAAIA,kBAAO,KAAK,eAAe;AAC7B,cAAI,aAAa;AAGjB,cAAI,OAAO,UAAU,UAAU,YAAA,EAAc,QAAQ,MAAM,KAAK,GAAG;AACjE,gBAAI,OAAO,kBAAkB;AAC7B,gBAAI,MAAM,oBAAoB;AAAA,UAChC;AAAA,QACF,OAAO;AACL,cAAI,aAAa;AAGjB,cAAI,MAAM,oBAAoB;AAC9B,cAAI,MAAM,IAAI,UAAU;AACxB,cAAI,MAAM,cAAc,OAAO;AAC/B,cAAI,MAAM,MAAM,uBAAuB;AAAA,QACzC;AAGA,YAAI,IAAI,OAAO,iBAAiB;AAC9B,cAAI,OAAO,gBAAgB,UAAU,WAAW;AAAA,QAClD;AAMA,YAAK,IAAY,YAAY;AAC1B,cAAY,WAAW,OAAO;AAAA,QACjC;AAEA,mBAAW,MAAM;AACf,gBAAM,eAAe,SAAS,uBAAuB,aAAa;AAClE,mBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,yBAAa,CAAC,EAAE,OAAA;AAAA,UAClB;AAAA,QACF,GAAG,GAAG;AASN,aAAK,UAAU,GAAG;AAAA,MACpB;AAWAG,UAAAA,UAAU,MAAM;AACd,mBAAA;AAAA,MACF,CAAC;AAEDC,UAAAA,YAAY,MAAM;AAChB,YAAI,KAAK;AACP,cAAI,QAAA;AACJ,gBAAM;AAAA,QACR;AAAA,MAEF,CAAC;;gCAtHCC,IAAAA,mBAAoD,OAAA;AAAA,UAA9C,IAAI,UAAA;AAAA,UAAW,OAAM;AAAA,QAAA;;;;;;;;;;;;;;;;AC+D7B,YAAM,OAAO;AAMb,YAAM,cAAcC,IAAAA,IAAI,KAAK;AAE7B,YAAM,iBAAiB,MAAM;AAC3B,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AACA,YAAM,eAAe,CAAC,SAAiB;AACrC,aAAK,gBAAgB,IAAI;AAAA,MAC3B;AACA,YAAM,YAAY,MAAM;AACtB,aAAK,OAAO;AAAA,MACd;AAUA,YAAM,eAA2B;AAAA,QAC/B;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,iBAAiB;AAAA;AAAA,QAAA;AAAA,QAEvC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,kBAAkB;AAAA;AAAA,QAAA;AAAA,QAExC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,iBAAiB;AAAA;AAAA,QAAA;AAAA,QAEvC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,YAAY,qBAAqB;AAAA;AAAA,QAAA;AAAA,MACjD;AAGF,YAAM,YAAwB;AAAA,QAC5B;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,eAAe;AAAA;AAAA,UACnC,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,UAAU;AAAA;AAAA,UAC9B,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,YAAY,iBAAiB;AAAA;AAAA,UAC3C,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,WAAW;AAAA;AAAA,UAC/B,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,cAAc,WAAW;AAAA;AAAA,UACvC,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,WAAW;AAAA;AAAA,UAC/B,UAAU;AAAA,QAAA;AAAA,MACZ;;gCAhJAD,IAAAA,mBA+CM,OAAA;AAAA,UA/CD,OAAKE,IAAAA,eAAA,CAAC,iBAAe,EAAA,WAAsB,YAAA,OAAW,CAAA;AAAA,QAAA;UAEzDC,IAAAA,mBAQM,OAAA;AAAA,YARD,OAAM;AAAA,YAAgB,SAAO;AAAA,UAAA;YAChCA,IAAAA,mBAME,KAAA;AAAA,cALC,OAAKD,IAAAA,eAAA;AAAA;;gBAA0D,YAAA,QAAW,oBAAA;AAAA,cAAA;;;UAQ/EE,mBAAAD,IAAAA,mBAkCM,OAlCNE,cAkCM;AAAA,YAhCJF,IAAAA,mBAUM,OAVNG,cAUM;AAAA,gCATJN,IAAAA,mBAQMO,IAAAA,UAAA,MAAAC,eAPW,cAAY,CAApB,SAAI;uBADbL,IAAAA,mBAQM,OAAA;AAAA,kBANH,KAAK,KAAK;AAAA,kBACX,OAAM;AAAA,kBACL,OAAO,KAAK;AAAA,kBACZ,SAAK,CAAA,WAAE,aAAa,KAAK,IAAI;AAAA,gBAAA;kBAE9BA,IAAAA,mBAA+B,KAAA;AAAA,oBAA3B,OAAKD,IAAAA,eAAE,KAAK,WAAW;AAAA,kBAAA;;;;sCAI/BC,IAAAA,mBAAuB,OAAA,EAAlB,OAAM,UAAA,GAAS,MAAA,EAAA;AAAA,YAGpBA,IAAAA,mBAgBM,OAhBNM,cAgBM;AAAA,gCAfJT,IAAAA,mBASMO,IAAAA,UAAA,MAAAC,eARW,WAAS,CAAjB,SAAI;uBADbL,IAAAA,mBASM,OAAA;AAAA,kBAPH,KAAK,KAAK;AAAA,kBACX,2BAAM,aAAW,EAAA,QACC,2BAAmB,KAAK,SAAA,CAAQ,CAAA;AAAA,kBACjD,OAAO,KAAK;AAAA,kBACZ,SAAK,CAAA,WAAE,aAAa,KAAK,IAAI;AAAA,gBAAA;kBAE9BA,IAAAA,mBAA+B,KAAA;AAAA,oBAA3B,OAAKD,IAAAA,eAAE,KAAK,WAAW;AAAA,kBAAA;;;wCAE7BC,IAAAA,mBAAuB,OAAA,EAAlB,OAAM,UAAA,GAAS,MAAA,EAAA;AAAA,cAEpBA,IAAAA,mBAEM,OAAA;AAAA,gBAFD,OAAM;AAAA,gBAAY,OAAM;AAAA,gBAAQ,SAAO;AAAA,cAAA;gBAC1CA,IAAAA,mBAAmC,KAAA,EAAhC,OAAM,wBAAA,GAAuB,MAAA,EAAA;AAAA,cAAA;;;yBA/BF,YAAA,KAAW;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACoBnD,YAAM,QAAQ;AAQd,YAAM,OAAO;AAKb,YAAM,eAAeF,IAAAA,IAAI,KAAK;AAC9B,YAAM,cAAc,MAAM;AAAE,qBAAa,QAAQ,CAAC,aAAa;AAAA,MAAO;AACtE,YAAM,UAAU,CAAC,WAAmB;AAAE,aAAK,iBAAiB,MAAM;AAAA,MAAG;AAWrE,YAAM,cAA4B;AAAA,QAChC;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,MACd;AAGF,YAAM,WAAW,CAAC,SAChB,KAAK,aAAa,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI;AAE/C,YAAM,WAAW,CAAC,SAChB,SAAS,IAAI,KAAK,KAAK,cAAc,KAAK,cAAc,KAAK;;;UA3F7DE,IAAAA,mBAEM,OAAA;AAAA,YAFD,OAAM;AAAA,YAAgB,OAAM;AAAA,YAAQ,SAAO;AAAA,UAAA;YAC9CA,IAAAA,mBAAuB,KAAA,EAApB,OAAM,YAAA,GAAW,MAAA,EAAA;AAAA,UAAA;UAItBO,IAAAA,YAmBaC,IAAAA,YAAA,EAnBD,MAAK,iBAAa;AAAA,iCAC5B,MAiBM;AAAA,cAjBK,aAAA,SAAXC,IAAAA,UAAA,GAAAZ,IAAAA,mBAiBM,OAjBNK,cAiBM;AAAA,gBAhBJF,IAAAA,mBAGM,OAHNG,cAGM;AAAA,kBAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAH,uBAAiB,cAAX,QAAI,EAAA;AAAA,kBACVA,IAAAA,mBAAkE,KAAA;AAAA,oBAA/D,OAAM;AAAA,oBAA0B,+CAAO,aAAA,QAAY;AAAA,kBAAA;;gBAExDA,IAAAA,mBAWM,OAXNU,cAWM;AAAA,oCAVJb,IAAAA,mBASMO,IAAAA,UAAA,MAAAC,eARW,aAAW,CAAnB,SAAI;2BADbL,IAAAA,mBASM,OAAA;AAAA,sBAPH,KAAK,KAAK;AAAA,sBACX,OAAKD,IAAAA,eAAA,CAAC,cAAY,EAAA,QACA,SAAS,IAAI,EAAA,CAAA,CAAA;AAAA,sBAC9B,SAAK,CAAA,WAAE,QAAQ,KAAK,MAAM;AAAA,oBAAA;sBAE3BC,IAAAA,mBAAgC,KAAA;AAAA,wBAA5B,OAAKD,IAAAA,eAAA,CAAA,MAAS,KAAK,IAAI,CAAA;AAAA,sBAAA;sBAC3BC,IAAAA,mBAAiC,QAAA,MAAAW,IAAAA,gBAAxB,SAAS,IAAI,CAAA,GAAA,CAAA;AAAA,oBAAA;;;;;;;;;;;;ACdzB,WAAS,SAAS;AACvB,UAAM,SAASnB,kBAAO;AAGtB,UAAM,SAASoB,IAAAA,WAA8B,IAAI;AAGjD,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AACtE,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AAGtE,UAAM,kBAAkBd,IAAAA,IAAS,IAAI;AAGrC,UAAM,oBAAoBA,IAAAA,IAAsD,IAAI;AAKpF,aAAS,QAAQ,KAAiB;AAChC,aAAO,QAAQ;AAGf,YAAM,SAAS,IAAIN,kBAAO,MAAM,aAAA;AAChC,UAAI,SAAS,MAAM;AACnB,mBAAa,QAAQ;AAGrB,YAAM,SAAS,IAAIA,kBAAO,MAAM,aAAA;AAChC,UAAI,SAAS,MAAM;AACnB,mBAAa,QAAQ;AAGrB,UAAI,GAAGA,kBAAO,UAAU,OAAO,CAAC,UAAe;AAC7C,YAAI,MAAM,QAAQ;AAChB,4BAAkB,QAAQ,MAAM;AAAA,QAClC,WAAW,MAAM,WAAW;AAC1B,gBAAM,QAAQ,OAAO,UAAU,MAAM,wBAAwB,MAAM,SAAS;AAC5E,4BAAkB,QAAQ;AAAA,YACxB,KAAK,OAAO,KAAK,UAAU,MAAM,SAAS;AAAA,YAC1C,KAAK,OAAO,KAAK,UAAU,MAAM,QAAQ;AAAA,YACzC,KAAK,MAAM,SAAS,IAAI,MAAM,SAAS;AAAA,UAAA;AAAA,QAE3C;AAAA,MACF,CAAC;AAGD,aAAO,GAAGA,kBAAO,UAAU,OAAO,CAAC,UAAe;AAChD,wBAAgB,QAAQ,MAAM;AAAA,MAChC,CAAC;AACD,aAAO,GAAGA,kBAAO,UAAU,WAAW,CAAC,UAAe;AACpD,YAAI,CAAC,gBAAgB,OAAO;AAC1B,0BAAgB,QAAQ,MAAM;AAAA,QAChC;AAAA,MACF,CAAC;AACD,aAAO,GAAGA,kBAAO,UAAU,UAAU,CAAC,UAAe;AACnD,YAAI,gBAAgB,UAAU,MAAM,SAAS;AAC3C,0BAAgB,QAAQ;AAAA,QAC1B;AAAA,MACF,CAAC;AAAA,IACH;AAKA,aAAS,aAAa;AACpB,UAAI,OAAO,OAAO;AAChB,eAAO,MAAM,QAAA;AACb,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAKA,aAAS,WAAW,SAAc;;AAChC,yBAAa,UAAb,mBAAoB,WAAW;AAAA,IACjC;AAKA,aAAS,SAAS,OAAY;;AAC5B,mBAAO,UAAP,mBAAc,SAAS;AAAA,IACzB;AAEA,WAAO;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;ACtGO,WAAS,WAAW,YAA0B;AACnD,UAAM,eAAeoB,IAAAA,WAAwC,IAAI;AAGjE,aAAS,cAAc;AACrB,YAAM,MAAM,WAAW,IAAI;AAC3B,YAAM,QAAQ,WAAW,aAAa;AACtC,UAAI,CAAC,OAAO,CAAC,MAAO;AAEpB,YAAM,IAAI,IAAIpB,kBAAO,MAAM,QAAQ,EAAE,cAAc,OAAc;AACjE,UAAI,SAAS,CAAC;AACd,mBAAa,QAAQ;AAAA,IACvB;AAGA,aAAS,gBAAgB,OAA6B;;AACpD,yBAAa,UAAb,mBAAoB,SAAS;AAAA,QAC3B,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,YAAY,OAA6B;;AAChD,yBAAa,UAAb,mBAAoB,KAAK;AAAA,QACvB,OAAO,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA;AAAA,MAAM;AAAA,IAEtD;AAGA,aAAS,cAAc,OAA6B;;AAClD,yBAAa,UAAb,mBAAoB,OAAO;AAAA,QACzB,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,aAAa,OAA6B;;AACjD,yBAAa,UAAb,mBAAoB,MAAM;AAAA,QACxB,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,eAAe;;AACtB,yBAAa,UAAb,mBAAoB;AACpB,uBAAW,aAAa,UAAxB,mBAA+B;AAAA,IACjC;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;ACvDO,WAAS,QAAQ,YAA0B;AAChD,UAAM,cAAcoB,IAAAA,WAAgB,IAAI;AAExC,UAAM,iBAAiBd,IAAAA,IAAqB,IAAI;AAGhD,aAAS,WAAW;AAClB,aAAO,WAAW,aAAa;AAAA,IACjC;AAGA,aAAS,UAAU,MAAc,OAA4B,UAAoB;AAC/E,YAAM,QAAQ,SAAA;AACd,UAAI,CAAC,MAAO;AACZ,eAAA;AACA,kBAAY,QAAQ,MAAM,UAAU,EAAE,MAAM,OAAO;AACnD,qBAAe,QAAQ;AAAA,IACzB;AAGA,aAAS,UAAU,OAA6B;AAC9C,gBAAU,SAAS,EAAE,WAAW,IAAI,OAAO,WAAW,GAAG,MAAA,GAAS,OAAO;AAAA,IAC3E;AAGA,aAAS,SAAS,OAA6B;AAC7C,gBAAU,YAAY,EAAE,OAAO,GAAG,OAAO,WAAW,GAAG,MAAA,GAAS,UAAU;AAAA,IAC5E;AAGA,aAAS,YAAY,OAA6B;AAChD,gBAAU,WAAW,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,SAAS;AAAA,IAC9E;AAGA,aAAS,WAAW,OAA6B;AAC/C,gBAAU,UAAU,EAAE,QAAQ,KAAM,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,QAAQ;AAAA,IAC1F;AAGA,aAAS,cAAc,OAA6B;AAClD,gBAAU,aAAa,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,WAAW;AAAA,IAClF;AAGA,aAAS,gBAAgB,OAA6B;AACpD;AAAA,QACE;AAAA,QACA,EAAE,OAAO,WAAW,SAAS,KAAK,eAAe,MAAM,GAAG,MAAA;AAAA,QAC1D;AAAA,MAAA;AAAA,IAEJ;AAGA,aAAS,WAAW;;AAClB,UAAI,YAAY,OAAO;AACrB,uBAAA,MAAA,mBAAY;AACZ,oBAAY,QAAQ;AAAA,MACtB;AACA,qBAAe,QAAQ;AAAA,IACzB;AAGA,aAAS,YAAY;;AACnB,eAAA;AACA,qBAAA,MAAA,mBAAY;AAAA,IACd;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AChFO,WAAS,UAAU,YAA0B;AAElD,UAAM,kBAAkBA,IAAAA,IAAI,KAAK;AACjC,UAAM,oBAAoBA,IAAAA,IAAI,KAAK;AACnC,UAAM,iBAAiBA,IAAAA,IAAI,KAAK;AAChC,UAAM,cAAcA,IAAAA,IAAI,KAAK;AAG7B,UAAM,cAAcc,IAAAA,WAA4C,IAAI;AACpE,UAAM,kBAAkBA,IAAAA,WAAgD,IAAI;AAC5E,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AACtE,QAAI,oBAAyB;AAG7B,aAAS,SAAS;AAChB,aAAO,WAAW,IAAI;AAAA,IACxB;AAGA,aAAS,kBAAkB;AACzB,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,YAAY,OAAO;AACrB,YAAI,YAAY,MAAM,SAAS;AAC7B,sBAAY,MAAM,KAAA;AAAA,QACpB;AACA,YAAI,YAAY,YAAY,KAAK;AACjC,oBAAY,QAAQ;AACpB,wBAAgB,QAAQ;AACxB;AAAA,MACF;AAEA,YAAM,SAAS,IAAI,UAAA;AACnB,YAAM,KAAK,IAAIpB,kBAAO,MAAM,YAAY,EAAE,UAAU,KAAM,MAAM,IAAI;AACpE,UAAI,SAAS,EAAE;AACf,SAAG,MAAM,MAAM;AACf,kBAAY,QAAQ;AACpB,sBAAgB,QAAQ;AAAA,IAC1B;AAGA,aAAS,QAAQ;AACf,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,kBAAY,QAAQ;AACpB,YAAM,OAAO,MAAM,WAAW,MAAM;AAAE,oBAAY,QAAQ;AAAA,MAAO,GAAG,GAAI;AAExE,YAAM,MAAM,WAAW,kBAAkB;AACzC,UAAI,KAAK;AACP,cAAM,SAAS,EAAE,GAAG,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,IAAA;AACtD,YAAI,cAAc,QAAQ,EAAE,UAAU,GAAG,UAAU,MAAM;AAAA,MAC3D,OAAO;AACL,YAAI,QAAQ,EAAE,UAAU,EAAA,CAAG;AAC3B,aAAA;AAAA,MACF;AAAA,IACF;AAGA,aAAS,oBAAoB;AAC3B,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,CAAC,gBAAgB,OAAO;AAC1B,cAAM,OAAO,IAAIA,kBAAO,MAAM,gBAAgB,CAAA,CAAE;AAChD,YAAI,SAAS,IAAI;AACjB,4BAAoB,IAAI,cAAA;AACxB,aAAK,UAAU;AACf,wBAAgB,QAAQ;AACxB,0BAAkB,QAAQ;AAAA,MAC5B,OAAO;AACL,cAAM,OAAO,gBAAgB;AAC7B,aAAK,UAAU,CAAC,KAAK;AACrB,0BAAkB,QAAQ,KAAK;AAC/B,YAAI,CAAC,KAAK,WAAW,mBAAmB;AACtC,cAAI,cAAc,mBAAmB,EAAE,UAAU,GAAG;AAAA,QACtD,WAAW,KAAK,SAAS;AACvB,8BAAoB,IAAI,cAAA;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAGA,aAAS,yBAAyB;AAChC,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,CAAC,aAAa,OAAO;AACvB,cAAM,OAAO,IAAIA,kBAAO,MAAM,aAAa,CAAA,CAAE;AAC7C,YAAI,SAAS,IAAI;AACjB,aAAK,UAAU;AACf,qBAAa,QAAQ;AACrB,uBAAe,QAAQ;AAAA,MACzB,OAAO;AACL,cAAM,OAAO,aAAa;AAC1B,aAAK,UAAU,CAAC,KAAK;AACrB,uBAAe,QAAQ,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA;AAAA,MAEL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;;;;;;;;;;;;AC3CA,YAAM,OAAO;AAMb,YAAM,SAAS,OAAA;AACf,YAAM,UAAU,WAAW,MAAM;AACjC,YAAM,OAAO,QAAQ,MAAM;AAC3B,YAAM,SAAS,UAAU,MAAM;AAG/BqB,UAAAA,QAAQ,cAAc,MAAM;AAC5BA,UAAAA,QAAQ,kBAAkB,OAAO;AACjCA,UAAAA,QAAQ,eAAe,IAAI;AAC3BA,UAAAA,QAAQ,iBAAiB,MAAM;AAG/B,eAAS,UAAU,KAAU;AAC3B,eAAO,QAAQ,GAAG;AAClB,gBAAQ,YAAA;AACR,aAAK,UAAU,GAAG;AAAA,MACpB;AAOA,eAAS,mBAAmB,MAAc;AACxC,gBAAQ,MAAA;AAAA,UACN,KAAK;AAAoB,oBAAQ,gBAAA;AAAmB;AAAA,UACpD,KAAK;AAAoB,oBAAQ,YAAA;AAAe;AAAA,UAChD,KAAK;AAAoB,oBAAQ,cAAA;AAAiB;AAAA,UAClD,KAAK;AAAoB,oBAAQ,aAAA;AAAgB;AAAA,UACjD,KAAK;AAAoB,iBAAK,UAAA;AAAa;AAAA,UAC3C,KAAK;AAAoB,iBAAK,SAAA;AAAY;AAAA,UAC1C,KAAK;AAAoB,iBAAK,YAAA;AAAe;AAAA,UAC7C,KAAK;AAAoB,iBAAK,WAAA;AAAc;AAAA,UAC5C,KAAK;AAAoB,iBAAK,cAAA;AAAiB;AAAA,UAC/C,KAAK;AAAoB,iBAAK,gBAAA;AAAmB;AAAA,QAAA;AAAA,MAErD;AAEA,eAAS,cAAc;AACrB,gBAAQ,aAAA;AACR,aAAK,UAAA;AAAA,MACP;AAKA,eAAS,oBAAoB,QAAgB;AAC3C,gBAAQ,QAAA;AAAA,UACN,KAAK;AAAqB,mBAAO,gBAAA;AAAmB;AAAA,UACpD,KAAK;AAAqB,mBAAO,MAAA;AAAS;AAAA,UAC1C,KAAK;AAAqB,mBAAO,kBAAA;AAAqB;AAAA,UACtD,KAAK;AAAqB,mBAAO,uBAAA;AAA0B;AAAA,QAAA;AAAA,MAE/D;AAGA,eAAa;AAAA,QACX,KAAK,OAAO;AAAA,QACZ,cAAc,OAAO;AAAA,QACrB,cAAc,OAAO;AAAA,QACrB,iBAAiB,OAAO;AAAA,QACxB,mBAAmB,OAAO;AAAA,QAC1B,YAAY,OAAO;AAAA,QACnB,UAAU,OAAO;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;;AApIC,eAAAJ,cAAA,GAAAZ,uBA4BM,OA5BNK,cA4BM;AAAA,UA1BJK,IAAAA,YAIEO,aAAA;AAAA,YAHC,KAAK,QAAA;AAAA,YACL,WAAS,QAAA;AAAA,YACT,UAAQ;AAAA,UAAA;WAKF,QAAA,gCADTC,IAAAA,YAKE,cAAA;AAAA;YAHC,oBAAkBC,IAAAA,MAAA,IAAA,EAAK,eAAe;AAAA,YACtC,gBAAe;AAAA,YACf,SAAO;AAAA,UAAA;WAKD,QAAA,+BADTD,IAAAA,YAOE,aAAA;AAAA;YALC,qBAAmBC,IAAAA,MAAA,MAAA,EAAO,gBAAgB;AAAA,YAC1C,iBAAeA,IAAAA,MAAA,MAAA,EAAO,YAAY;AAAA,YAClC,uBAAqBA,IAAAA,MAAA,MAAA,EAAO,kBAAkB;AAAA,YAC9C,4BAA0BA,IAAAA,MAAA,MAAA,EAAO,eAAe;AAAA,YAChD,iBAAgB;AAAA,UAAA;UAInBC,IAAAA,WAAQ,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,IAAA;AAAA,QAAA;;;;;ACvBZ,QAAM,gBAAqD;AAAA,IACzD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAS;AAAA,EACX;AAEA,MAAIC,eAAa;AAEV,WAAS,aAAa,QAAsB;AAEjD,UAAM,WAAWN,IAAAA,WAA6C,IAAI;AAGlE,UAAM,UAAUd,IAAAA,IAAe,EAAE;AAGjC,UAAM,cAAcA,IAAAA,IAAmB,IAAI;AAG3C,aAAS,eAAe;AACtB,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,YAAM,QAAQ,IAAIN,kBAAO,MAAM,aAAA;AAC/B,UAAI,SAAS,KAAK;AAClB,eAAS,QAAQ;AAGjB,YAAM,GAAGA,kBAAO,UAAU,OAAO,CAAC,MAAW;;AAC3C,cAAM,SAAQ,aAAE,YAAF,mBAAW,SAAX,mBAAiB;AAC/B,YAAI,iBAAiB,KAAK;AAAA,MAC5B,CAAC;AAAA,IACH;AAGA,aAAS,OAAO,QAAyC;AACvD,YAAM,QAAQ,SAAS;AACvB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,OAAO0B,cAAY;AAG9B,YAAM,UAAU,IAAI1B,kBAAO,QAAQ,gBAAgB;AAAA,QACjD,UAAU,CAAC,OAAO,KAAK,OAAO,KAAK,OAAO,GAAG;AAAA,QAC7C,OAAO;AAAA,UACL,OAAO,cAAc,OAAO,QAAQ;AAAA,UACpC,OAAO;AAAA,UACP,kBAAkBA,kBAAO,OAAO,iBAAiB;AAAA,UACjD,gBAAgBA,kBAAO,OAAO,eAAe;AAAA,UAC7C,eAAe;AAAA;AAAA,UAEf,OAAO;AAAA,YACL,MAAM,OAAO;AAAA,YACb,WAAW;AAAA,YACX,OAAO;AAAA,YACP,SAAS;AAAA,YACT,cAAc;AAAA,YACd,cAAc;AAAA,YACd,aAAa,IAAIA,kBAAO,OAAO,WAAW,GAAG,GAAG;AAAA,YAChD,cAAc;AAAA,UAAA;AAAA,QAChB;AAAA;AAAA,QAGF,OAAO,eAAe,MAAM;AAAA,QAC5B,MAAM,EAAE,OAAO,IAAI,MAAM,OAAO,KAAA;AAAA,MAAK,CACtC;AAED,YAAM,WAAW,OAAO;AAExB,YAAM,MAAe,EAAE,GAAG,QAAQ,IAAI,QAAA;AACtC,cAAQ,MAAM,KAAK,GAAG;AACtB,aAAO;AAAA,IACT;AAGA,aAAS,UAAU,IAAY;;AAC7B,YAAM,MAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACtD,UAAI,QAAQ,GAAI;AAEhB,YAAM,MAAM,QAAQ,MAAM,GAAG;AAC7B,UAAI,aAAW,cAAS,UAAT,mBAAgB,cAAc,IAAI;AACjD,cAAQ,MAAM,OAAO,KAAK,CAAC;AAE3B,UAAI,YAAY,UAAU,GAAI,aAAY,QAAQ;AAAA,IACpD;AAGA,aAAS,UAAU,IAAY,QAAQ,OAAO;AAC5C,kBAAY,QAAQ;AACpB,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,IAAK;AAGV,cAAQ,MAAM,QAAQ,CAAC,MAAM;AAC3B,YAAI,EAAE,SAAS;AACb,YAAE,QAAQ,MAAM,QAAQ,EAAE,OAAO,KAAK,MAAM;AAAA,QAC9C;AAAA,MACF,CAAC;AAED,UAAI,gBAAgB,EAAE;AAAA,IACxB;AAGA,aAAS,cAAc,IAAY,SAAiB;;AAClD,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,IAAK;AAEV,UAAI,OAAO;AAGX,UAAI,IAAI,SAAS;AACf,YAAI,QAAQ,OAAO,EAAE,GAAG,IAAI,QAAQ,MAAM,MAAM,QAAA;AAChD,YAAI,QAAQ,QAAQ,eAAe,GAAG;AAEtC,aAAI,SAAI,QAAQ,UAAZ,mBAAmB,OAAO;AAC5B,cAAI,QAAQ,MAAM,MAAM,OAAO;AAAA,QACjC;AACA,wBAAI,SAAQ,eAAZ;AAAA,MACF;AAAA,IACF;AAGA,aAAS,SAAS,IAAY;AAC5B,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,OAAO,CAAC,OAAO,IAAI,MAAO;AAE/B,YAAM,MAAM,OAAO,IAAI;AAGvB,YAAM,UAAU,IAAI,MAAM,IAAI,IAAI,MAAM;AACxC,YAAM,SAAS,UAAU;AAGzB,UAAI,cAAc,EAAE,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,OAAA,GAAU,EAAE,UAAU,KAAK;AAAA,IAClF;AAGA,aAAS,WAAW;;AAClB,qBAAS,UAAT,mBAAgB;AAChB,cAAQ,QAAQ,CAAA;AAChB,kBAAY,QAAQ;AAAA,IACtB;AAGA,UAAM,YAAYM,IAAAA,IAAI,KAAK;AAC3B,QAAI,gBAA2C;AAE/C,aAAS,cACP,SACA,cAAc,OACd,WAAgC,WAChC;AACA,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,UAAI,UAAU,OAAO;AAEnB,YAAI,eAAe;AACjB,cAAI,IAAIN,kBAAO,UAAU,OAAO,aAAa;AAC7C,0BAAgB;AAAA,QAClB;AACA,kBAAU,QAAQ;AAAA,MACpB,OAAO;AAEL,kBAAU,QAAQ;AAClB,wBAAgB,CAAC,MAAW;AAE1B,cAAI,KAAa,KAAa;AAE9B,cAAI,EAAE,QAAQ;AACZ,kBAAM,EAAE,OAAO;AACf,kBAAM,EAAE,OAAO;AACf,kBAAM,EAAE,OAAO,OAAO;AAAA,UACxB,WAAW,EAAE,WAAW;AACtB,kBAAM,QAAQA,kBAAO,OAAO,aAAa,cAAc,EAAE,SAAS;AAClE,kBAAMA,kBAAO,OAAO,KAAK,UAAU,MAAM,SAAS;AAClD,kBAAMA,kBAAO,OAAO,KAAK,UAAU,MAAM,QAAQ;AACjD,kBAAM,MAAM,SAAS,IAAI,MAAM,SAAS;AAAA,UAC1C,OAAO;AACL;AAAA,UACF;AAGA,gBAAM,WAAW,MAAM,IAAI,MAAM;AAEjC,gBAAM,MAAM,OAAO;AAAA,YACjB,MAAM,GAAG,WAAW,IAAI0B,YAAU;AAAA,YAClC;AAAA,YACA;AAAA,YACA,KAAK;AAAA,YACL;AAAA,UAAA,CACD;AACD,cAAI,wCAAe;AAEnB,wBAAA;AAAA,QACF;AACA,YAAI,GAAG1B,kBAAO,UAAU,OAAO,aAAa;AAAA,MAC9C;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAGA,WAAS,eAAe,KAAsC;AAC5D,WAAO;AAAA;AAAA,mFAE0E,IAAI,IAAI;AAAA;AAAA,kBAEzE,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,kBAClB,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,kBAClB,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,UAC1B,IAAI,cAAc,gCAAgC,IAAI,WAAW,WAAW,EAAE;AAAA;AAAA;AAAA;AAAA,EAIxF;;;;ACxOA,YAAM,SAAS2B,IAAAA,OAAqB,YAAY;AAChD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4CAA4C;AAGzE,YAAM,MAAM,aAAa,MAAM;AAI/B,YAAM,YAAYC,IAAAA;AAAAA,QAChB,MAAM,OAAO,IAAI;AAAA,QACjB,CAAC,QAAQ;AACP,cAAI,KAAK;AACP,gBAAI,aAAA;AACJ,sBAAA;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,WAAW,KAAA;AAAA,MAAK;AAGpBxB,UAAAA,YAAY,MAAM;AAChB,YAAI,SAAA;AAAA,MACN,CAAC;AAGDiB,UAAAA,QAAQ,cAAc,GAAG;AAGzB,eAAa,GAAG;;eApCdI,eAAQ,KAAA,QAAA,SAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqJV,YAAM,MAAME,IAAAA,OAA2B,YAAY;AACnD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,0CAA0C;AAGpE,YAAM,cAAcrB,IAAAA,IAAI,IAAI;AAC5B,YAAM,iBAAiB,MAAM;AAC3B,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AAGA,YAAM,UAAUA,IAAAA,IAAwB,IAAI;AAC5C,YAAM,aAAaA,IAAAA,IAAI,KAAK;AAG5B,YAAM,MAAMuB,IAAAA,SAAS,EAAE,GAAG,IAAI,GAAG,IAAI;AAErC,UAAI,aAAa;AACjB,UAAI,aAAa;AACjB,UAAI,QAAQ;AACZ,UAAI,QAAQ;AAEZ,eAAS,UAAU,GAAe;AAChC,mBAAW,QAAQ;AACnB,qBAAa,EAAE;AACf,qBAAa,EAAE;AACf,gBAAQ,IAAI;AACZ,gBAAQ,IAAI;AAEZ,iBAAS,iBAAiB,aAAa,MAAM;AAC7C,iBAAS,iBAAiB,WAAW,QAAQ;AAAA,MAC/C;AAEA,eAAS,OAAO,GAAe;AAC7B,YAAI,CAAC,WAAW,MAAO;AACvB,YAAI,IAAI,SAAS,EAAE,UAAU;AAC7B,YAAI,IAAI,SAAS,EAAE,UAAU;AAAA,MAC/B;AAEA,eAAS,WAAW;AAClB,mBAAW,QAAQ;AACnB,iBAAS,oBAAoB,aAAa,MAAM;AAChD,iBAAS,oBAAoB,WAAW,QAAQ;AAAA,MAClD;AAGA,YAAM,aAAa;AAAA,QACjB,EAAE,OAAO,OAAO,OAAO,MAAM,MAAM,WAAW,OAAO,OAAA;AAAA,QACrD,EAAE,OAAO,WAAW,OAAO,MAAM,MAAM,iBAAiB,OAAO,UAAA;AAAA,QAC/D;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,QAET,EAAE,OAAO,QAAQ,OAAO,MAAM,MAAM,kBAAkB,OAAO,UAAA;AAAA,MAAU;AAGzE,YAAM,iBAAiBvB,IAAAA,IAAY,KAAK;AAExC,YAAM,eAAeL,IAAAA,SAAS,MAAM;AAClC,YAAI,eAAe,UAAU,MAAO,QAAO,IAAI,QAAQ;AACvD,eAAO,IAAI,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,eAAe,KAAK;AAAA,MAC5E,CAAC;AAED,YAAM,mBAAmB,CAAC,QAA6B;AACrD,cAAM,MAA8B;AAAA,UAClC,SAAS;AAAA,UACT,SAAS;AAAA,UACT,MAAM;AAAA,QAAA;AAER,eAAO,IAAI,GAAG,KAAK;AAAA,MACrB;AAGA,YAAM,cAAcK,IAAAA,IAAyB,SAAS;AAEtD,eAAS,YAAY;AACnB,YAAI;AAAA,UACF;AAAA;AAAA,UACA;AAAA,UACA,YAAY;AAAA,QAAA;AAAA,MAEhB;AAGA,eAAS,SAAS,IAAY;AAC5B,YAAI,UAAU,IAAI,IAAI;AAAA,MACxB;AAEA,eAAS,QAAQ,IAAY;AAC3B,YAAI,SAAS,EAAE;AAAA,MACjB;AAEA,eAAS,SAAS,IAAY;AAC5B,YAAI,UAAU,EAAE;AAAA,MAClB;AAGA,YAAM,YAAYA,IAAAA,IAAmB,IAAI;AACzC,YAAM,WAAWA,IAAAA,IAAI,EAAE;AACvB,YAAM,cAAcA,IAAAA,IAA6B,IAAI;AAErD,eAAS,UAAU,MAAe;AAChC,kBAAU,QAAQ,KAAK;AACvB,iBAAS,QAAQ,KAAK;AAEtB,mBAAW,MAAA;;AAAM,mCAAY,UAAZ,mBAAmB;AAAA,WAAU,EAAE;AAAA,MAClD;AAEA,eAAS,WAAW;AAClB,YAAI,UAAU,SAAS,SAAS,MAAM,QAAQ;AAC5C,cAAI,cAAc,UAAU,OAAO,SAAS,MAAM,MAAM;AAAA,QAC1D;AACA,mBAAA;AAAA,MACF;AAEA,eAAS,aAAa;AACpB,kBAAU,QAAQ;AAClB,iBAAS,QAAQ;AAAA,MACnB;AAEA,eAAS,eAAe;AACtB,YAAI,OAAO,QAAQ,UAAU,IAAI,QAAQ,MAAM,MAAM,OAAO,GAAG;AAC7D,cAAI,SAAA;AAAA,QACN;AAAA,MACF;;gCAzRED,IAAAA,mBAoJM,OAAA;AAAA,mBAnJA;AAAA,UAAJ,KAAI;AAAA,UACJ,OAAKE,IAAAA,eAAA,CAAC,aAAW,EAAA,WACI,YAAA,MAAA,CAAW,CAAA;AAAA,UAC/B,OAAKuB,IAAAA;AAAAA,aAAW,YAAA,QAA+B,EAAA,MAAA,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,SAA6B,EAAA,MAAA,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,KAAA;AAAA,UAAA;AAAA;UAO7HtB,IAAAA,mBAuBM,OAAA;AAAA,YAtBJ,OAAKD,IAAAA,eAAA,CAAC,qBAAmB,EAAA,eACA,WAAA,MAAA,CAAU,CAAA;AAAA,YAClC,+BAAmB,WAAS,CAAA,SAAA,CAAA;AAAA,YAC5B,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAA,QAAU,OAAU,eAAA;AAAA,UAAc;YAG1B,YAAA,SACdU,IAAAA,UAAA,GAAAZ,IAAAA,mBAKM,OALNK,cAKM;AAAA,wCAJJF,IAAAA,mBAA6C,KAAA,EAA1C,OAAM,kCAAA,GAAiC,MAAA,EAAA;AAAA,cAC1CA,IAAAA,mBAES,QAFTG,cAESQ,IAAAA,gBADP,aAAA,MAAa,MAAM,GAAA,CAAA;AAAA,YAAA,wBAIzBd,IAAAA,mBAOWO,IAAAA,UAAA,EAAA,KAAA,KAAA;AAAA,cANTJ,IAAAA,mBAIO,QAJPU,cAIO;AAAA,0CAHLV,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,8DAAG,cAE9B,EAAA;AAAA,gBAAAA,IAAAA,mBAAwD,QAAxDM,cAAwDK,IAAAA,gBAA7B,aAAA,MAAa,MAAM,GAAA,CAAA;AAAA,cAAA;wCAEhDX,IAAAA,mBAA8C,KAAA,EAA3C,OAAM,sCAAkC,MAAA,EAAA;AAAA,YAAA;;UAI/CC,mBAAAD,IAAAA,mBA+GM,OA/GNuB,cA+GM;AAAA,YA7GJvB,IAAAA,mBAgBM,OAhBNwB,cAgBM;AAAA,cAfJxB,IAAAA,mBAOS,UAAA;AAAA,gBANP,2BAAM,OAAK,EAAA,eACcgB,eAAI,UAAU,MAAA,CAAK,CAAA;AAAA,gBAC3C,SAAO;AAAA,cAAA;gBAERhB,IAAAA,mBAAmE,KAAA;AAAA,kBAA/D,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,aAAA,SAAA,CAAA;AAAA,gBAAA;gBAA8BS,IAAAA,gBAAA,MACnEd,oBAAGK,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,SAAA,QAAA,GAAA,CAAA;AAAA,cAAA;cAExBhB,IAAAA,mBAMS,UAAA;AAAA,gBALP,OAAM;AAAA,gBACL,SAAO;AAAA,gBACP,UAAUgB,IAAAA,MAAA,GAAA,EAAI,QAAQ,MAAM,WAAM;AAAA,cAAA;gBAEnChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,oCAAG,QAC7B,EAAA;AAAA,cAAA;;YAIFA,IAAAA,mBAWM,OAXN0B,cAWM;AAAA,gCAVJ7B,IAAAA,mBASOO,IAAAA,UAAA,MAAAC,eARS,YAAU,CAAjB,QAAG;uBADZL,IAAAA,mBASO,QAAA;AAAA,kBAPJ,KAAK,IAAI;AAAA,kBACV,2BAAM,cAAY,EAAA,QACA,yBAAmB,IAAI,MAAA,CAAK,CAAA;AAAA,kBAC7C,SAAK,CAAA,WAAE,eAAA,QAAiB,IAAI;AAAA,gBAAA;kBAE7BA,IAAAA,mBAA6D,KAAA;AAAA,oBAAzD,OAAKD,IAAAA,eAAA,CAAA,MAAS,IAAI,IAAI,CAAA;AAAA,oBAAI,OAAKuB,IAAAA,eAAA,EAAA,OAAW,IAAI,OAAK;AAAA,kBAAA;sCAAM,MAC7DX,IAAAA,gBAAG,IAAI,KAAK,GAAA,CAAA;AAAA,gBAAA;;;YAKhBX,IAAAA,mBA2EM,OA3EN2B,eA2EM;AAAA,cA1EJpB,IAAAA,YA+DkBqB,IAAAA,iBAAA,EA/DD,MAAK,cAAU;AAAA,qCAE5B,MAA4B;AAAA,wCAD9B/B,IAAAA,mBA6DMO,IAAAA,UAAA,MAAAC,IAAAA,WA5DW,aAAA,OAAY,CAApB,SAAI;4CADbR,IAAAA,mBA6DM,OAAA;AAAA,sBA3DH,KAAK,KAAK;AAAA,sBACX,OAAKE,IAAAA,eAAA,CAAC,YAAU,EAAA,oBACciB,IAAAA,MAAA,GAAA,EAAI,YAAY,UAAU,KAAK,GAAA,CAAE,CAAA;AAAA,sBAC9D,SAAK,CAAA,WAAE,SAAS,KAAK,EAAE;AAAA,oBAAA;sBAGxBhB,IAAAA,mBAGE,QAAA;AAAA,wBAFA,OAAM;AAAA,wBACL,OAAKsB,IAAAA,eAAA,EAAA,YAAgB,iBAAiB,KAAK,QAAQ,GAAA;AAAA,sBAAA;sBAGtDtB,IAAAA,mBAsBM,OAtBN6B,eAsBM;AAAA,wBAnBI,UAAA,UAAc,KAAK,0CAD3BhC,IAAAA,mBAQE,SAAA;AAAA;0BANA,OAAM;AAAA,uFACG,SAAQ,QAAA;AAAA,0BAChB,WAAO;AAAA,yCAAQ,UAAQ,CAAA,OAAA,CAAA;AAAA,yCACP,YAAU,CAAA,QAAA,CAAA;AAAA,0BAAA;AAAA,0BAC1B,qDAAD,MAAA;AAAA,0BAAA,GAAW,CAAA,MAAA,CAAA;AAAA;mCACP;AAAA,0BAAJ,KAAI;AAAA,wBAAA;2CAJK,SAAA,KAAQ;AAAA,wBAAA,uBAOnBA,IAAAA,mBAMM,OAAA;AAAA;0BAJJ,OAAM;AAAA,0BACL,YAAQiC,IAAAA,cAAA,CAAA,WAAO,UAAU,IAAI,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA,GAE3BnB,IAAAA,gBAAA,KAAK,IAAI,GAAA,IAAAoB,aAAA;AAAA,wBAEd/B,IAAAA,mBAEM,OAFNgC,eAEMrB,IAAAA,gBADD,KAAK,IAAI,QAAO,CAAA,CAAA,IAAM,OAAEA,IAAAA,gBAAG,KAAK,IAAI,QAAO,CAAA,CAAA,GAAA,CAAA;AAAA,sBAAA;sBAKlDX,IAAAA,mBAsBM,OAtBNiC,eAsBM;AAAA,wBArBJjC,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,UAAU,IAAI,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE3B9B,IAAAA,mBAA0B,KAAA,EAAvB,OAAM,eAAA,GAAc,MAAA,EAAA;AAAA,wBAAA;wBAEzBA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,QAAQ,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE5B9B,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,wBAAA;wBAE7BA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,SAAS,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE7B9B,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,wBAAA;;;;;;;cAOnB,aAAA,MAAa,WAAM,KAA9BS,IAAAA,aAAAZ,IAAAA,mBAOM,OAPNqC,eAOM;AAAA,4CANJlC,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,gBACtBA,IAAAA,mBAII,KAAA,MAAAW,IAAAA,gBAFAK,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,gBAAA,QAAA,GAAA,CAAA;AAAA,cAAA;;;yBA1GS,YAAA,KAAW;AAAA,UAAA;;;;;;ACArD,MAAI,aAAa;AAEV,WAAS,SAAS,QAAsB;AAE7C,UAAM,aAAaJ,IAAAA,WAA6C,IAAI;AAGpE,UAAM,YAAYd,IAAAA,IAAiB,EAAE;AAGrC,UAAM,gBAAgBA,IAAAA,IAAmB,IAAI;AAG7C,UAAM,YAAYA,IAAAA,IAAI,KAAK;AAC3B,UAAM,cAAcA,IAAAA,IAAI,CAAC;AACzB,UAAM,gBAAgBA,IAAAA,IAAI,CAAC;AAC3B,UAAM,mBAAmBA,IAAAA,IAAI,CAAC;AAG9B,UAAM,iBAAiBA,IAAAA,IAAI,KAAK;AAChC,UAAM,mBAAmBA,IAAAA,IAAmB,IAAI;AAGhD,QAAI,gBAAuD;AAI3D,aAAS,iBAAiB;AACxB,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,YAAM,QAAQ,IAAIN,kBAAO,MAAM,aAAA;AAC/B,UAAI,SAAS,KAAK;AAClB,iBAAW,QAAQ;AAAA,IACrB;AAGA,aAAS,kBAAkB,OAAkB;AAC3C,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAGnB,YAAM,YAAY,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE3F,YAAM,OAAO,IAAIA,kBAAO,QAAQ,kBAAkB;AAAA,QAChD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,QAEjB,MAAM,EAAE,SAAS,MAAM,GAAA;AAAA,MAAG,CAC3B;AAED,YAAM,WAAW,IAAI;AACrB,aAAO;AAAA,IACT;AAGA,aAAS,oBAAoB,OAAkB,SAAiB,OAAe;AAC7E,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,SAAS,SAAS,QAAS;AAEhC,YAAM,YAAY,MAAM,OAAO,MAAM,SAAS,QAAQ,CAAC,EACpD,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE/D,YAAM,UAAU,IAAIA,kBAAO,QAAQ,kBAAkB;AAAA,QACnD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,MACjB,CACD;AACD,YAAM,WAAW,OAAO;AAExB,UAAI,CAAC,MAAM,sBAAsB;AAC/B,cAAM,uBAAuB,CAAA;AAAA,MAC/B;AACA,YAAM,qBAAqB,KAAK,OAAO;AAAA,IACzC;AAGA,aAAS,sBAAsB,OAAkB;AAC/C,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO;AAEZ,YAAM,YAAY,MAAM,OAAO,MAAM,gBAAiB;AACtD,UAAI,CAAC,UAAW;AAGhB,UAAI,MAAM,eAAe;AACvB,cAAM,cAAc,WAAW,CAAC,UAAU,KAAK,UAAU,KAAK,UAAU,GAAG;AAAA,MAC7E,OAAO;AACL,cAAM,SAAS,IAAIA,kBAAO,QAAQ,gBAAgB;AAAA,UAChD,UAAU,CAAC,UAAU,KAAK,UAAU,KAAK,UAAU,GAAG;AAAA,UACtD,OAAO;AAAA,YACL,OAAO;AAAA,YACP,OAAO;AAAA,YACP,kBAAkBA,kBAAO,OAAO,iBAAiB;AAAA,YACjD,gBAAgBA,kBAAO,OAAO,eAAe;AAAA,UAAA;AAAA,QAC/C,CACD;AACD,cAAM,WAAW,MAAM;AACvB,cAAM,gBAAgB;AAAA,MACxB;AAAA,IACF;AAGA,aAAS,SAAS,QAAsB,OAAO,MAAM;AACnD,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,SAAS,YAAY;AAChC,YAAM,QAAmB,EAAE,IAAI,MAAM,OAAA;AACrC,YAAM,cAAc,kBAAkB,KAAK;AAC3C,gBAAU,MAAM,KAAK,KAAK;AAC1B,aAAO;AAAA,IACT;AAGA,aAAS,cAAc,OAAO,QAAQ;AACpC,UAAI,iBAAiB,MAAO,cAAA;AAE5B,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,YAAY,YAAY;AACnC,YAAM,QAAmB;AAAA,QACvB;AAAA,QACA;AAAA,QACA,QAAQ,CAAA;AAAA,QACR,kBAAkB;AAAA,MAAA;AAEpB,iBAAW,QAAQ;AACnB,gBAAU,MAAM,KAAK,KAAK;AAC1B,uBAAiB,QAAQ;AACzB,qBAAe,QAAQ;AACvB,aAAO;AAAA,IACT;AAGA,aAAS,kBAAkB,IAAY,KAAa,KAAa,MAAM,GAAG;AACxE,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAoB;AAAA,QACxB,MAAM,KAAK,IAAA;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,YAAM,OAAO,KAAK,KAAK;AACvB,YAAM,mBAAmB,MAAM,OAAO,SAAS;AAG/C,UAAI,MAAM,OAAO,WAAW,GAAG;AAC7B,cAAM,cAAc,kBAAkB,KAAK;AAC3C,8BAAsB,KAAK;AAAA,MAC7B,OAAO;AAEL,4BAAoB,OAAO,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,SAAS,CAAC;AAC3E,8BAAsB,KAAK;AAAA,MAC7B;AAGA,UAAI,OAAO,IAAI,OAAO;AACpB,eAAO,IAAI,MAAM;AAAA,UACf,CAAC,KAAK,KAAK,MAAM,EAAE;AAAA,UACnB,EAAE,QAAQ,KAAK,UAAU,IAAA;AAAA,QAAI;AAAA,MAEjC;AAAA,IACF;AAGA,aAAS,aAAa,IAAa;;AACjC,YAAM,WAAW,MAAM,iBAAiB;AACxC,UAAI,CAAC,SAAU;AAEf,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AAC3D,UAAI,OAAO;AACT,cAAM,mBAAmB;AACzB,YAAI,MAAM,eAAe;AACvB,2BAAW,UAAX,mBAAkB,cAAc,MAAM;AACtC,gBAAM,gBAAgB;AAAA,QACxB;AAAA,MACF;AAEA,UAAI,iBAAiB,UAAU,UAAU;AACvC,yBAAiB,QAAQ;AACzB,uBAAe,QAAQ;AAAA,MACzB;AAAA,IACF;AAGA,aAAS,KAAK,SAAkB;AAC9B,YAAM,KAAK,WAAW,cAAc;AACpC,UAAI,CAAC,GAAI;AAET,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,SAAS,MAAM,OAAO,SAAS,EAAG;AAEvC,UAAI,cAAc,UAAU,IAAI;AAC9B,oBAAY,EAAE;AAAA,MAChB;AAEA,gBAAU,QAAQ;AAClB,yBAAA;AAEA,YAAM,QAAQ,MAAM,OAAO,CAAC,EAAE;AAC9B,YAAM,MAAM,MAAM,OAAO,MAAM,OAAO,SAAS,CAAC,EAAE;AAIlD,sBAAgB,YAAY,MAAM;AAChC,cAAM2C,SAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,YAAI,CAACA,UAAS,CAAC,UAAU,MAAO;AAEhC,cAAM,UAAU,KAAK,IAAA,KAASA,OAAM,kBAAkB,KAAK;AAC3D,cAAM,QAAQ,MAAM;AACpB,cAAM,WAAW,KAAK,IAAI,UAAU,OAAO,CAAC;AAG5C,oBAAY,QAAQ,QAAQ,WAAW;AACvC,yBAAiB,QAAQ,WAAW;AAGpC,cAAM,YAAY,KAAK,MAAM,YAAYA,OAAM,OAAO,SAAS,EAAE;AACjE,4BAAoBA,QAAO,SAAS;AAAA,MACtC,GAAG,EAAE;AAAA,IACP;AAEA,aAAS,oBAAoB,OAAkB,OAAe;;AAC5D,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO;AAGZ,UAAI,MAAM,aAAa;AACrB,cAAM,cAAc,MAAM,WAAW;AAAA,MACvC;AAGA,YAAM,YAAY,MAAM,OAAO,MAAM,GAAG,QAAQ,CAAC,EAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE/D,YAAM,cAAc,IAAI3C,kBAAO,QAAQ,kBAAkB;AAAA,QACvD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,MACjB,CACD;AACD,YAAM,WAAW,MAAM,WAAW;AAGlC,YAAM,KAAK,MAAM,OAAO,KAAK;AAC7B,mBAAO,IAAI,UAAX,mBAAkB;AAAA,QAChB,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG;AAAA,QAC7B,EAAE,QAAQ,KAAK,UAAU,EAAA;AAAA;AAAA,IAE7B;AAEA,aAAS,QAAQ;AACf,gBAAU,QAAQ;AAClB,yBAAA;AAAA,IACF;AAEA,aAAS,OAAO;AACd,gBAAU,QAAQ;AAClB,uBAAiB,QAAQ;AACzB,kBAAY,QAAQ;AACpB,yBAAA;AAGA,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,UAAI,SAAS,WAAW,OAAO;AAC7B,YAAI,MAAM,YAAa,YAAW,MAAM,cAAc,MAAM,WAAW;AACvE,cAAM,cAAc,kBAAkB,KAAK;AAAA,MAC7C;AAAA,IACF;AAEA,aAAS,SAAS,OAAe;AAC/B,oBAAc,QAAQ;AACtB,UAAI,UAAU,OAAO;AACnB,cAAA;AACA,aAAA;AAAA,MACF;AAAA,IACF;AAGA,aAAS,KAAK,UAAkB;AAC9B,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,UAAI,CAAC,MAAO;AAEZ,YAAM,YAAY,KAAK,MAAO,WAAW,OAAQ,MAAM,OAAO,SAAS,EAAE;AACzE,kBAAY,QAAQ,MAAM,OAAO,SAAS,EAAE;AAC5C,uBAAiB,QAAQ;AACzB,0BAAoB,OAAO,SAAS;AAAA,IACtC;AAGA,aAAS,YAAY,IAAY;AAC/B,oBAAc,QAAQ;AACtB,WAAA;AAAA,IACF;AAGA,aAAS,WAAW,IAAY;AAC9B,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,SAAS,CAAC,OAAO,IAAI,MAAO;AAEjC,YAAM,QAAQ,MAAM,OAAO,CAAC;AAC5B,aAAO,IAAI,MAAM;AAAA,QACf,CAAC,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,GAAI;AAAA,QACvC,EAAE,QAAQ,KAAM,UAAU,IAAA;AAAA,MAAI;AAAA,IAElC;AAGA,aAAS,YAAY,IAAY;;AAC/B,YAAM,MAAM,UAAU,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACxD,UAAI,QAAQ,GAAI;AAEhB,YAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,UAAI,MAAM,YAAa,kBAAW,UAAX,mBAAkB,cAAc,MAAM;AAC7D,UAAI,MAAM,cAAe,kBAAW,UAAX,mBAAkB,cAAc,MAAM;AAE/D,UAAI,MAAM,sBAAsB;AAC9B,cAAM,qBAAqB,QAAQ,CAAC,QAAQ;;AAC1C,WAAA4C,MAAA,WAAW,UAAX,gBAAAA,IAAkB,cAAc;AAAA,QAClC,CAAC;AAAA,MACH;AACA,gBAAU,MAAM,OAAO,KAAK,CAAC;AAE7B,UAAI,cAAc,UAAU,IAAI;AAC9B,sBAAc,QAAQ;AACtB,aAAA;AAAA,MACF;AACA,UAAI,iBAAiB,UAAU,IAAI;AACjC,yBAAiB,QAAQ;AACzB,uBAAe,QAAQ;AAAA,MACzB;AAAA,IACF;AAEA,aAAS,WAAW;;AAClB,WAAA;AACA,mBAAA;AACA,uBAAW,UAAX,mBAAkB;AAClB,gBAAU,QAAQ,CAAA;AAClB,oBAAc,QAAQ;AAAA,IACxB;AAGA,aAAS,qBAAqB;AAC5B,UAAI,eAAe;AACjB,sBAAc,aAAa;AAC3B,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;;;;AC3ZA,YAAM,SAASjB,IAAAA,OAAqB,YAAY;AAChD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AAGrE,YAAM,QAAQ,SAAS,MAAM;AAG7B,YAAM,YAAYC,IAAAA;AAAAA,QAChB,MAAM,OAAO,IAAI;AAAA,QACjB,CAAC,QAAQ;AACP,cAAI,KAAK;AACP,kBAAM,eAAA;AACN,sBAAA;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,WAAW,KAAA;AAAA,MAAK;AAGpBxB,UAAAA,YAAY,MAAM;AAChB,cAAM,SAAA;AAAA,MACR,CAAC;AAGDiB,UAAAA,QAAQ,gBAAgB,KAAK;AAG7B,eAAa,KAAK;;eAnChBI,eAAQ,KAAA,QAAA,SAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC2MV,YAAM,QAAQE,IAAAA,OAAuB,cAAc;AACnD,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kCAAkC;AAG9D,YAAM,cAAcrB,IAAAA,IAAI,IAAI;AAC5B,YAAM,aAAaA,IAAAA,IAAI,KAAK;AAC5B,YAAM,MAAMuB,IAAAA,SAAS,EAAE,GAAG,IAAI,GAAG,IAAI;AAErC,UAAI,aAAa,GACf,aAAa,GACb,QAAQ,GACR,QAAQ;AAEV,eAAS,iBAAiB;AACxB,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AAEA,eAAS,UAAU,GAAe;AAChC,mBAAW,QAAQ;AACnB,qBAAa,EAAE;AACf,qBAAa,EAAE;AACf,gBAAQ,IAAI;AACZ,gBAAQ,IAAI;AACZ,iBAAS,iBAAiB,aAAa,MAAM;AAC7C,iBAAS,iBAAiB,WAAW,QAAQ;AAAA,MAC/C;AACA,eAAS,OAAO,GAAe;AAC7B,YAAI,CAAC,WAAW,MAAO;AACvB,YAAI,IAAI,SAAS,EAAE,UAAU;AAC7B,YAAI,IAAI,SAAS,EAAE,UAAU;AAAA,MAC/B;AACA,eAAS,WAAW;AAClB,mBAAW,QAAQ;AACnB,iBAAS,oBAAoB,aAAa,MAAM;AAChD,iBAAS,oBAAoB,WAAW,QAAQ;AAAA,MAClD;AAGA,eAAS,cAAc,IAAY;AACjC,YAAI,MAAM,cAAc,UAAU,GAAI;AACtC,cAAM,YAAY,EAAE;AACpB,cAAM,KAAA;AAAA,MACR;AAEA,YAAM,kBAAkB5B,IAAAA,SAAS,MAAM;AACrC,cAAM,IAAI,MAAM,UAAU,MAAM;AAAA,UAC9B,CAAC,MAAM,EAAE,OAAO,MAAM,cAAc;AAAA,QAAA;AAEtC,gBAAO,uBAAG,SAAQ;AAAA,MACpB,CAAC;AAED,YAAM,eAAeA,IAAAA,SAAS,MAAM;AAClC,cAAM,IAAI,MAAM,UAAU,MAAM;AAAA,UAC9B,CAAC,MAAM,EAAE,OAAO,MAAM,cAAc;AAAA,QAAA;AAEtC,YAAI,CAAC,KAAK,EAAE,OAAO,SAAS,EAAG,QAAO;AACtC,eAAO,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC,EAAE;AAAA,MACvC,CAAC;AAGD,YAAM,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC;AAGhC,eAAS,OAAO,GAAU;AACxB,cAAM,MAAM,WAAY,EAAE,OAA4B,KAAK;AAC3D,cAAM,KAAK,GAAG;AAAA,MAChB;AAGA,eAAS,WAAW,IAAoB;AACtC,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,IAAI,IAAI,KAAK,EAAE;AACrB,eAAO,GAAG,OAAO,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,EAAE,WAAA,CAAY,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,MAC9F;AAGA,eAAS,eAAe;AAEtB,cAAM,UAAU;AAChB,cAAM,UAAU;AAChB,cAAM,SAAS,CAAA;AACf,YAAI,IAAI,KAAK,IAAA;AAGb,YAAI,UAAU,KAAK,OAAA,IAAW,KAAK,KAAK;AACxC,cAAM,OAAO;AAEb,iBAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,eAAK,MAAO,KAAK,OAAA,IAAW;AAE5B,sBAAY,KAAK,OAAA,IAAW,QAAQ,KAAK,KAAK;AAC9C,gBAAM,UAAU,UAAU,KAAK,IAAI,OAAO,IAAI;AAC9C,gBAAM,UAAU,UAAU,KAAK,IAAI,OAAO,IAAI;AAC9C,gBAAM,MAAM,KAAK,KAAK,IAAK,IAAI,OAAQ,KAAK,EAAE,IAAI;AAClD,iBAAO,KAAK,EAAE,MAAM,GAAG,KAAK,SAAS,KAAK,SAAS,KAAK;AAAA,QAC1D;AAEA,cAAM,SAAS,QAAQ,MAAM,UAAU,EAAE;AAAA,MAC3C;AAEA,UAAI,WAAW;AAGf,UAAI,iBAAwD;AAC5D,UAAI,qBAAoC;AAExC,eAAS,iBAAiB;AACxB,YAAI,MAAM,eAAe,OAAO;AAC9B,uBAAA;AAAA,QACF,OAAO;AACL,wBAAA;AAAA,QACF;AAAA,MACF;AAEA,eAAS,gBAAgB;;AACvB,cAAM,MAAK,WAAM,cAAc,QAAQ,UAAU,EAAE,MAAxC,mBAA2C;AACtD,YAAI,CAAC,GAAI;AACT,6BAAqB;AAGrB,cAAM,aAAa;AACnB,cAAM,aAAa;AAEnB,cAAM,aAAa;AACnB,cAAM,aAAa;AAEnB,cAAM,eAAe;AACrB,cAAM,aAAc,IAAI,KAAK,KAAM;AAEnC,YAAI,QAAQ,KAAK,OAAA,IAAW,IAAI,KAAK;AACrC,YAAI,YAAY;AAEhB,yBAAiB,YAAY,MAAM;AACjC;AAEA,gBAAM,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI;AAC3C,gBAAM,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI;AAC3C,gBAAM,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI;AACvC,gBAAM,kBAAkB,IAAI,KAAK,KAAK,GAAG;AAGzC,mBAAS;AAGT,cAAI,aAAa,cAAc;AAC7B,yBAAA;AAAA,UACF;AAAA,QACF,GAAG,GAAG;AAAA,MACR;AAEA,eAAS,eAAe;AACtB,YAAI,gBAAgB;AAClB,wBAAc,cAAc;AAC5B,2BAAiB;AAAA,QACnB;AACA,YAAI,oBAAoB;AACtB,gBAAM,aAAa,kBAAkB;AACrC,+BAAqB;AAAA,QACvB;AAAA,MACF;AAEA,YAAM,qBAAqBA,IAAAA,SAAS,MAAM;AACxC,cAAM,IAAI,MAAM,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,kBAAkB;AACvE,gBAAO,uBAAG,OAAO,WAAU;AAAA,MAC7B,CAAC;AAGD,eAAS,eAAe;AACtB,YAAI,OAAO,QAAQ,UAAU,MAAM,UAAU,MAAM,MAAM,OAAO,GAAG;AACjE,uBAAA;AACA,gBAAM,SAAA;AAAA,QACR;AAAA,MACF;;gCA5XEI,IAAAA,mBAwMM,OAAA;AAAA,UAvMJ,OAAKE,IAAAA,eAAA,CAAC,eAAa,EAAA,WACE,YAAA,MAAA,CAAW,CAAA;AAAA,UAC/B,kCAAe,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,KAAA,CAAA;AAAA,QAAA;UAGxCC,IAAAA,mBAoBM,OAAA;AAAA,YAnBJ,OAAKD,IAAAA,eAAA,CAAC,uBAAqB,EAAA,eACF,WAAA,MAAA,CAAU,CAAA;AAAA,YAClC,+BAAmB,WAAS,CAAA,SAAA,CAAA;AAAA,YAC5B,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAA,QAAU,OAAU,eAAA;AAAA,UAAc;YAE1B,YAAA,SACdU,IAAAA,UAAA,GAAAZ,IAAAA,mBAGM,OAHN,YAGM;AAAA,wCAFJG,IAAAA,mBAA4C,KAAA,EAAzC,OAAM,iCAAA,GAAgC,MAAA,EAAA;AAAA,cACzCA,IAAAA,mBAAmE,QAAnE,YAAmEW,IAAAA,gBAAtCK,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,MAAM,GAAA,CAAA;AAAA,YAAA,wBAG7DnB,IAAAA,mBAOWO,IAAAA,UAAA,EAAA,KAAA,KAAA;AAAA,cANTJ,IAAAA,mBAIO,QAJP,YAIO;AAAA,0CAHLA,IAAAA,mBAA6B,KAAA,EAA1B,OAAM,kBAAA,GAAiB,MAAA,EAAA;AAAA,8DAAG,UAE7B,EAAA;AAAA,gBAAAA,IAAAA,mBAAmE,QAAnE,YAAmEW,IAAAA,gBAAtCK,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,MAAM,GAAA,CAAA;AAAA,cAAA;wCAE3DhB,IAAAA,mBAA8C,KAAA,EAA3C,OAAM,sCAAkC,MAAA,EAAA;AAAA,YAAA;;UAK/CC,mBAAAD,IAAAA,mBA0KM,OA1KN,YA0KM;AAAA,YAxKJA,IAAAA,mBAqBM,OArBN,YAqBM;AAAA,cApBJA,IAAAA,mBAES,UAAA;AAAA,gBAFD,OAAM;AAAA,gBAAoB,SAAO;AAAA,cAAA;gBACvCA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,oCAAG,UAC1B,EAAA;AAAA,cAAA;cACAA,IAAAA,mBASS,UAAA;AAAA,gBARP,2BAAM,OACEgB,iBAAM,eAAe,QAAK,gBAAA,WAAA,CAAA;AAAA,gBACjC,SAAO;AAAA,cAAA;gBAERhB,IAAAA,mBAEE,KAAA;AAAA,kBADC,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,KAAA,EAAM,eAAe,QAAK,YAAA,SAAA,CAAA;AAAA,gBAAA;gBACzCS,IAAAA,gBAAA,MACFd,oBAAGK,IAAAA,MAAA,KAAA,EAAM,eAAe,QAAK,SAAA,MAAA,GAAA,CAAA;AAAA,cAAA;cAE/BhB,IAAAA,mBAMS,UAAA;AAAA,gBALP,OAAM;AAAA,gBACL,SAAO;AAAA,gBACP,UAAUgB,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,WAAM;AAAA,cAAA;gBAEvChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,cAAA;;YAKagB,UAAA,KAAA,EAAM,cAAc,SAA7DP,IAAAA,aAAAZ,IAAAA,mBA0DM,OA1DN,YA0DM;AAAA,cAxDJG,IAAAA,mBAIM,OAJN,YAIM;AAAA,4CAHJA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,oCAAG,MACxBW,oBAAG,gBAAA,KAAe,IAAG,KACrB,CAAA;AAAA,gBAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAX,IAAAA,mBAA8C,QAAA,EAAxC,OAAM,0BAAuB,QAAI,EAAA;AAAA,cAAA;cAIzCA,IAAAA,mBAeM,OAfN,aAeM;AAAA,gBAdJA,IAAAA,mBAES,UAAA;AAAA,kBAFD,OAAM;AAAA,kBAAY,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBACzChB,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,gBAAA;gBAEvBA,IAAAA,mBAOS,UAAA;AAAA,kBANP,OAAM;AAAA,kBACL,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAQA,IAAAA,MAAA,KAAA,EAAM,UAAUA,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBAE1DhB,IAAAA,mBAEE,KAAA;AAAA,oBADC,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAK,aAAA,SAAA,CAAA;AAAA,kBAAA;;gBAGxChB,IAAAA,mBAES,UAAA;AAAA,kBAFD,OAAM;AAAA,kBAAY,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBACzChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,gBAAA;;cAK5BA,IAAAA,mBAaM,OAbN,aAaM;AAAA,gBAZJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,IAAAA,mBAAmC,QAAA,EAA7B,OAAM,cAAA,GAAc,MAAE,EAAA;AAAA,gBAC5BA,IAAAA,mBAUM,OAVN,aAUM;AAAA,oCATJH,IAAAA,mBAQSO,IAAAA,UAAA,MAAAC,eAPK,cAAY,CAAjB,MAAC;2BADVL,IAAAA,mBAQS,UAAA;AAAA,sBANN,KAAK;AAAA,sBACN,OAAKD,IAAAA,eAAA,CAAC,aAAW,EAAA,QACCiB,IAAAA,MAAA,KAAA,EAAM,cAAc,UAAU,EAAA,CAAC,CAAA;AAAA,sBAChD,SAAK,CAAA,WAAEA,IAAAA,MAAA,KAAA,EAAM,SAAS,CAAC;AAAA,oBAAA,GAErBL,IAAAA,gBAAA,CAAC,IAAG,MACT,IAAA,WAAA;AAAA;;;cAKJX,IAAAA,mBAcM,OAdN,aAcM;AAAA,gBAbJA,IAAAA,mBAES,QAFT,aAESW,IAAAA,gBADP,WAAWK,IAAAA,MAAA,KAAA,EAAM,YAAY,KAAK,CAAA,GAAA,CAAA;AAAA,gBAEpChB,IAAAA,mBAQE,SAAA;AAAA,kBAPA,MAAK;AAAA,kBACL,OAAM;AAAA,kBACN,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,MAAK;AAAA,kBACJ,OAAOgB,IAAAA,MAAA,KAAA,EAAM,iBAAiB;AAAA,kBAC9B,SAAO;AAAA,gBAAA;gBAEVhB,uBAA8D,QAA9D,aAA8DW,IAAAA,gBAAlC,WAAW,aAAA,KAAY,CAAA,GAAA,CAAA;AAAA,cAAA;;YAO/CK,IAAAA,MAAA,KAAA,EAAM,eAAe,UAAUA,IAAAA,MAAA,KAAA,EAAM,cAAc,SAF3DP,IAAAA,UAAA,GAAAZ,IAAAA,mBAYM,OAZN,aAYM;AAAA,0CARJG,IAAAA,mBAIM,OAAA,EAJD,OAAM,oBAAgB;AAAA,gBACzBA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,cAAY;AAAA,oCAAG,SAExB;AAAA,gBAAAA,IAAAA,mBAA0B,QAAA,EAApB,OAAM,aAAW;AAAA,cAAA;cAEzBA,IAAAA,mBAEM,OAFN,aAEM;AAAA,gEAFsB,SACtB,EAAA;AAAA,gBAAAA,IAAAA,mBAAyC,oCAA9B,mBAAA,KAAkB,GAAA,CAAA;AAAA,gEAAY,UAC/C,EAAA;AAAA,cAAA;;YAIFA,IAAAA,mBAmEM,OAnEN,aAmEM;AAAA,cAlEJO,IAAAA,YAwDkBqB,IAAAA,iBAAA,EAxDD,MAAK,gBAAY;AAAA,qCAE9B,MAAqC;AAAA,mBADvCnB,IAAAA,UAAA,IAAA,GAAAZ,uBAsDMO,IAAAA,+BArDWY,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAxB,SAAI;4CADbnB,IAAAA,mBAsDM,OAAA;AAAA,sBApDH,KAAK,KAAK;AAAA,sBACX,2BAAM,cAAY;AAAA,wBAC6B,sBAAAmB,IAAAA,MAAA,KAAA,EAAM,cAAc,UAAU,KAAK;AAAA,gDAA2C,KAAK,GAAG,WAAU,UAAA;AAAA,sBAAA;sBAI9I,SAAK,CAAA,WAAE,cAAc,KAAK,EAAE;AAAA,oBAAA;sBAG7BhB,IAAAA,mBAOE,QAAA;AAAA,wBANA,OAAM;AAAA,wBACL,OAAKsB,IAAAA,eAAA;AAAA,sCAAiC,KAAK,GAAG,WAAU,UAAA;;;sBAO3DtB,IAAAA,mBAgBM,OAhBN,aAgBM;AAAA,wBAfJA,IAAAA,mBAQM,OARN,aAQM;AAAA,0BAPJA,IAAAA,mBAKE,KAAA;AAAA,4BAJC,OAAKD,IAAAA,eAAA;AAAA;8BAAoD,KAAK,GAAG,WAAU,UAAA,IAAA,YAAA;AAAA,4BAAA;;8CAI5E,MACFY,IAAAA,gBAAG,KAAK,IAAI,GAAA,CAAA;AAAA,wBAAA;wBAEdX,IAAAA,mBAKM,OALN,aAKM;AAAA,0BAJDyB,IAAAA,gBAAAd,IAAAA,gBAAA,KAAK,OAAO,MAAM,IAAG,QACxB,CAAA;AAAA,0BAAY,KAAK,GAAG,WAAU,UAAA,sBAA9Bd,uBAC8B,QAD9B,aACG,IAAE;;;sBAKTG,IAAAA,mBAeM,OAfN,aAeM;AAAA,wBAdJA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,uCAAYgB,UAAA,KAAA,EAAM,WAAW,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAErChB,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,wBAAA;wBAE7BA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,uCAAYgB,UAAA,KAAA,EAAM,YAAY,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAEtChB,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,wBAAA;;;;;;;cAQtBgB,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,WAAM,KADpCP,cAAA,GAAAZ,IAAAA,mBAMM,OANN,aAMM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBAFJG,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,gBACtBA,IAAAA,mBAAa,WAAV,UAAM,EAAA;AAAA,cAAA;;;yBAvKyB,YAAA,KAAW;AAAA,UAAA;;;;;;ACyBvD,QAAM,aAAwC;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,IAAA,gBACAqC;AAAAA,IACA;AAAA,IAAA,YACAC;AAAAA,IACA;AAAA,EACF;AAEA,QAAM,WAAW;AAAA,IACf,QAAQ,KAAU,SAA+B;AAC/C,YAAM,UAAS,mCAAS,WAAU;AAClC,iBAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,YAAI,UAAU,SAAS,GAAG,MAAM,GAAG,IAAI,KAAK,MAAM,SAAS;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"yi-map-web.umd.cjs","sources":["../src/components/mars-work/expand/task/CameraList.js","../src/components/mars-work/expand/task/CameraView.js","../src/components/mars-work/expand/task/MapRotate.js","../src/components/mars-work/expand/task/PointRotate.js","../src/components/mars-work/expand/task/RouteLine.js","../src/components/mars-work/expand/task/ZoomIn.js","../src/components/mars-work/expand/task/ZoomOut.js","../src/components/mars-work/expand/task/FlickerEntity.js","../src/components/mars-work/expand/graphic/CanvasBillboard.js","../src/components/mars-work/mars-map.vue","../src/components/mars-map/panels/ToolbarPanel.vue","../src/components/mars-map/panels/VisionPanel.vue","../src/components/mars-map/composables/useMap.ts","../src/components/mars-map/composables/useMeasure.ts","../src/components/mars-map/composables/useDraw.ts","../src/components/mars-map/composables/useVision.ts","../src/components/mars-map/MarsMapContainer.vue","../src/components/business/poi-marker/usePoiMarker.ts","../src/components/business/poi-marker/PoiMarkerLayer.vue","../src/components/business/poi-marker/PoiMarkerPanel.vue","../src/components/business/track/useTrack.ts","../src/components/business/track/TrackLayer.vue","../src/components/business/track/TrackPanel.vue","../src/index.ts"],"sourcesContent":["import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 视角列表播放(分步执行)\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n * @param {object[]} [options.list] 视角数组\r\n */\r\nexport class CameraList extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraViewList(this.options.list)\r\n }\r\n\r\n // 暂停(非必须)\r\n _pauseWork() {\r\n this._disableWork()\r\n }\r\n}\r\nmars3d.thing.Task.register(\"cameraList\", CameraList)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 单个视角定位\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.center] 视角参数\r\n */\r\nexport class CameraView extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraView(this.options.center, { duration: this._duration })\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n this._map.cancelFlyTo()\r\n }\r\n}\r\nmars3d.thing.Task.register(\"camera\", CameraView)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 地球自旋转\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.center] 初始视角\r\n * @param {number} [options.speed] 旋转速度\r\n */\r\nexport class MapRotate extends mars3d.TaskItem {\r\n constructor(options = {}) {\r\n super(options)\r\n\r\n this._speed = this.options.speed || 0.01\r\n this._center = this.options.center || { lat: 29.093038, lng: 108.804459, alt: 23321232.7, heading: 0, pitch: -90 }\r\n }\r\n\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.setCameraView(this._center, {\r\n duration: 1,\r\n complete: () => {\r\n this._map.on(mars3d.EventType.clockTick, this._map_onClockTick, this)\r\n }\r\n })\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n this._map.off(mars3d.EventType.clockTick, this._map_onClockTick, this)\r\n }\r\n\r\n _map_onClockTick() {\r\n if (this.isPause) {\r\n return // 暂停时不执行\r\n }\r\n\r\n this._map.scene.camera.rotate(mars3d.Cesium.Cartesian3.UNIT_Z, this._speed)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"mapRotate\", MapRotate)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 内或外旋转\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {boolean} [options.isRotateOut] true:绕外旋转 ,false:绕内旋转\r\n * @param {boolean} [options.direction=false] 旋转方向, true逆时针,false顺时针\r\n * @param {number} [options.time=60] 飞行一周所需时间(单位 秒),控制速度\r\n * @param {boolean} [options.autoStop] 是否自动停止\r\n * @param {number} [options.autoStopAngle] 自动停止的角度值(0-360度),未设置时不自动停止\r\n * @param {object} [options.point] 绕点旋转对应的中心点位置\r\n */\r\nexport class PointRotate extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n if (this.options.center) {\r\n this._map.setCameraView(this.options.center, { duration: 0 })\r\n }\r\n\r\n if (this.options.autoStop) {\r\n delete this.options.autoStopAngle // 是否自动停止\r\n }\r\n\r\n if (this.options.isRotateOut) {\r\n this._rotateOut = new mars3d.thing.RotateOut(this.options)\r\n this._map.addThing(this._rotateOut)\r\n } else {\r\n this._rotatePoint = new mars3d.thing.RotatePoint(this.options)\r\n this._map.addThing(this._rotatePoint)\r\n }\r\n\r\n if (this.options.isRotateOut) {\r\n this._rotateOut.start()\r\n } else {\r\n this._rotatePoint.start(this.options.point)\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._rotatePoint) {\r\n this._rotatePoint.stop()\r\n this._rotatePoint.destroy()\r\n delete this._rotatePoint\r\n }\r\n if (this._rotateOut) {\r\n this._rotateOut.stop()\r\n this._rotateOut.destroy()\r\n delete this._rotateOut\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"pointRotate\", PointRotate)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 按路线漫游\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {object} [options.route] FixedRoute对应的构造参数\r\n */\r\nexport class RouteLine extends mars3d.TaskItem {\r\n // constructor(options) {\r\n // super(options)\r\n // }\r\n\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._graphicLayer = new mars3d.layer.GraphicLayer()\r\n this._map.addLayer(this._graphicLayer)\r\n\r\n const fixedRoute = new mars3d.graphic.FixedRoute(this.options.route)\r\n this._graphicLayer.addGraphic(fixedRoute)\r\n this._fixedRoute = fixedRoute\r\n\r\n fixedRoute.start()\r\n }\r\n\r\n // 暂停(非必须)\r\n _pauseWork(options) {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.pause()\r\n }\r\n }\r\n\r\n // 继续(非必须)\r\n _proceedWork() {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.proceed()\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._fixedRoute) {\r\n this._fixedRoute.stop()\r\n delete this._fixedRoute\r\n }\r\n\r\n if (this._graphicLayer) {\r\n this._graphicLayer.destroy()\r\n delete this._graphicLayer\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"routeLine\", RouteLine)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 放大地图\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {number} [options.relativeAmount=2] 相对量\r\n */\r\nexport class ZoomIn extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.zoomIn(this.options.relativeAmount)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"zoomIn\", ZoomIn)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 缩小地图\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {number} [options.relativeAmount=2] 相对量\r\n */\r\nexport class ZoomOut extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n this._map.zoomOut(this.options.relativeAmount)\r\n }\r\n}\r\nmars3d.thing.Task.register(\"zoomOut\", ZoomOut)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n/**\r\n * 矢量对象高亮闪烁(仅Entity)\r\n *\r\n * @param {object} [options] 参数对象,包括以下:\r\n * @param {string} [options.name] 标题名称\r\n * @param {string} [options.type] 类型标识,自动赋值的,无需手动传入\r\n * @param {number} [options.start] 开始时间,相当于map.clock.startTime的秒数\r\n * @param {number} [options.duration] 时长\r\n *\r\n * @param {string|number} [options.layerId] 图层ID\r\n * @param {string|number} [options.graphicId] 矢量对象ID\r\n *\r\n * @param {number} [options.step=10] 闪烁增量, 控制速度\r\n * @param {string} [options.color] 高亮的颜色\r\n * @param {number} [options.maxAlpha=0.3] 闪烁的最大透明度,从 0 到 maxAlpha 渐变\r\n */\r\nexport class FlickerEntity extends mars3d.TaskItem {\r\n // 进入,激活开始处理事务\r\n _activateWork() {\r\n const layer = this._map.getLayerById(this.options.layerId)\r\n if (layer) {\r\n layer.show = true\r\n layer.readyPromise.then(() => {\r\n this._graphic = layer.getGraphicById(this.options.graphicId)\r\n if (this._graphic) {\r\n this._graphic.show = true\r\n this._graphic.startFlicker({\r\n time: this._duration,\r\n step: this.options.step,\r\n maxAlpha: this.options.maxAlpha,\r\n color: this.options.color\r\n })\r\n }\r\n })\r\n }\r\n }\r\n\r\n // 离开,释放相关对象\r\n _disableWork() {\r\n if (this._graphic) {\r\n this._graphic.stopFlicker()\r\n }\r\n }\r\n}\r\nmars3d.thing.Task.register(\"flickerEntity\", FlickerEntity)\r\n","import * as mars3d from \"mars3d\"\r\n\r\n// 通过Canvas绘制复杂或动态对象的图标点Graphic\r\nexport class CanvasBillboard extends mars3d.graphic.BillboardPrimitive {\r\n /**\r\n * 文字\r\n * @type {string}\r\n */\r\n get text() {\r\n return this.style.text\r\n }\r\n\r\n set text(val) {\r\n this.style.text = val\r\n\r\n this.label.text = val\r\n }\r\n\r\n /**\r\n * 对象添加到图层前创建一些对象的钩子方法,\r\n * 只会调用一次\r\n * @return {Promise<object>} 无\r\n * @private\r\n */\r\n _addedHook(style) {\r\n style.image = \"//data.mars3d.cn/img/marker/bg/textPnl.png\"\r\n style.label = {\r\n ...style,\r\n text: this.style.text,\r\n font_size: 55,\r\n color: style.textColor ?? \"#ffffff\",\r\n hasPixelOffset: true,\r\n pixelOffsetX: 0,\r\n pixelOffsetY: -36 * (style.scale ?? 1)\r\n }\r\n if (style.scaleByDistance) {\r\n style.label.pixelOffsetScaleByDistance = style.scaleByDistance\r\n }\r\n\r\n super._addedHook(style)\r\n }\r\n}\r\n\r\n// 注册下\r\nmars3d.GraphicUtil.register(\"canvasBillboard\", CanvasBillboard)\r\n","<!--\r\n 地图渲染组件\r\n-->\r\n\r\n<template>\r\n <div :id=\"withKeyId\" class=\"mars3d-container\"></div>\r\n</template>\r\n<script setup lang=\"ts\">\r\nimport * as mars3d from \"mars3d\";\r\nimport \"./expand/index\"; // 引入插件或注册扩展js\r\n\r\nimport { computed, onUnmounted, onMounted, toRaw } from \"vue\";\r\n// import { $alert, $message } from \"@mars/components/mars-ui/index\"\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n mapKey?: string; // 多个地图时,可传入key区分地图\r\n url?: string; // 传入的地图构造参数url,可为空,只传options\r\n options?: any; // 传入的地图构造参数options,可覆盖url内的参数\r\n }>(),\r\n {\r\n mapKey: \"default\",\r\n url: undefined,\r\n options: undefined,\r\n },\r\n);\r\n\r\n// 用于存放地球组件实例\r\nlet map: mars3d.Map; // 地图对象\r\n\r\n// 使用用户传入的 mapKey 拼接生成 withKeyId 作为当前显示容器的id\r\nconst withKeyId = computed(() => `mars3d-container-${props.mapKey}`);\r\n\r\n// onload事件将在地图渲染后触发\r\nconst emit = defineEmits([\"onload\"]);\r\n\r\nconst initMars3d = async () => {\r\n // 获取配置\r\n let mapOptions;\r\n if (props.url) {\r\n // 存在url时才读取\r\n mapOptions = await mars3d.Util.fetchJson({ url: props.url });\r\n if (props.options) {\r\n mapOptions = mars3d.Util.merge(mapOptions, toRaw(props.options)); // 合并配置\r\n }\r\n } else if (props.options) {\r\n mapOptions = toRaw(props.options);\r\n }\r\n // console.log(\"Map地图构造参数\", mapOptions);\r\n\r\n // 禁用控制台版权信息输出\r\n (mars3d as any).Util.showCopyright = false;\r\n\r\n map = new mars3d.Map(withKeyId.value, mapOptions);\r\n\r\n // 针对不同终端的优化配置\r\n if (mars3d.Util.isPCBroswer()) {\r\n map.zoomFactor = 2.0; // 鼠标滚轮放大的步长参数\r\n\r\n // IE浏览器优化\r\n if (window.navigator.userAgent.toLowerCase().indexOf(\"msie\") >= 0) {\r\n map.viewer.targetFrameRate = 20; // 限制帧率\r\n map.scene.requestRenderMode = false; // 取消实时渲染\r\n }\r\n } else {\r\n map.zoomFactor = 5.0; // 鼠标滚轮放大的步长参数\r\n\r\n // 移动设备上禁掉以下几个选项,可以相对更加流畅\r\n map.scene.requestRenderMode = false; // 取消实时渲染\r\n map.scene.fog.enabled = false;\r\n map.scene.skyAtmosphere.show = false;\r\n map.scene.globe.showGroundAtmosphere = false;\r\n }\r\n\r\n // 二三维切换不用动画\r\n if (map.viewer.sceneModePicker) {\r\n map.viewer.sceneModePicker.viewModel.duration = 0.0;\r\n }\r\n\r\n // 绑定当前项目的默认右键菜单\r\n // map.bindContextMenu(getContextMenu())\r\n\r\n // 隐藏右下角的Mars3D logo\r\n if ((map as any).mars3dLogo) {\r\n (map as any).mars3dLogo.show = false;\r\n }\r\n // 强制从DOM中移除logo元素\r\n setTimeout(() => {\r\n const logoElements = document.getElementsByClassName(\"mars3d-logo\");\r\n for (let i = 0; i < logoElements.length; i++) {\r\n logoElements[i].remove();\r\n }\r\n }, 100);\r\n\r\n // webgl渲染失败后,刷新页面\r\n // map.on(mars3d.EventType.renderError, async () => {\r\n // await $alert(\"程序内存消耗过大,请重启浏览器\")\r\n // window.location.reload()\r\n // })\r\n\r\n onMapLoad(); // map构造完成后的一些处理\r\n emit(\"onload\", map);\r\n};\r\n\r\n// map构造完成后的一些处理,可以按需注释和选用\r\nfunction onMapLoad() {\r\n // Mars3D地图内部使用,如右键菜单弹窗\r\n // @ts-ignore\r\n // window.globalAlert = $alert;\r\n // // @ts-ignore\r\n // window.globalMsg = $message;\r\n}\r\n\r\nonMounted(() => {\r\n initMars3d();\r\n});\r\n// 组件卸载之前销毁mars3d实例\r\nonUnmounted(() => {\r\n if (map) {\r\n map.destroy();\r\n map = null;\r\n }\r\n // console.log(\"map销毁完成\", map);\r\n});\r\n</script>\r\n\r\n<style lang=\"less\">\r\n/**cesium 工具按钮栏*/\r\n.cesium-viewer-toolbar {\r\n top: auto !important;\r\n bottom: 35px !important;\r\n left: 12px !important;\r\n right: auto !important;\r\n}\r\n\r\n.cesium-toolbar-button img {\r\n width: 22px;\r\n height: 100%;\r\n}\r\n.cesium-toolbar-button:hover img {\r\n width: 28px;\r\n}\r\n.cesium-svgPath-svg {\r\n scale: 0.8;\r\n}\r\n.cesium-svgPath-svg:hover {\r\n scale: 1;\r\n}\r\n.cesium-button .cesium-baseLayerPicker-selected {\r\n width: 100%;\r\n}\r\n\r\n.cesium-button:hover .cesium-baseLayerPicker-selected {\r\n width: 100%;\r\n}\r\n\r\n.cesium-viewer-toolbar > .cesium-toolbar-button,\r\n.cesium-navigationHelpButton-wrapper,\r\n.cesium-viewer-geocoderContainer {\r\n margin-bottom: 5px;\r\n float: left;\r\n clear: both;\r\n text-align: center;\r\n}\r\n\r\n.cesium-viewer-geocoderContainer form .cesium-geocoder-input {\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n}\r\n\r\n.cesium-button {\r\n background-color: rgba(39, 44, 54, 0.8);\r\n\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n\r\n color: #ffffff;\r\n fill: #e6e6e6;\r\n line-height: 38px;\r\n}\r\n\r\n.cesium-button:hover {\r\n background-color: rgba(51, 133, 255, 1);\r\n box-shadow: none;\r\n border: none;\r\n}\r\n\r\n/**cesium 底图切换面板*/\r\n.cesium-baseLayerPicker-dropDown {\r\n bottom: 0;\r\n left: 40px;\r\n max-height: 700px;\r\n margin-bottom: 5px;\r\n background-color: rgba(23, 49, 71, 0.7);\r\n}\r\n\r\n/**cesium 帮助面板*/\r\n.cesium-navigation-help {\r\n top: auto;\r\n bottom: 0;\r\n left: 40px;\r\n transform-origin: left bottom;\r\n background: none;\r\n background-color: rgba(23, 49, 71, 0.8);\r\n\r\n .cesium-navigation-help-instructions,\r\n .cesium-navigation-button {\r\n background: none;\r\n }\r\n\r\n .cesium-navigation-button-selected,\r\n .cesium-navigation-button-unselected:hover {\r\n background-color: rgba(1, 35, 22, 1);\r\n }\r\n}\r\n\r\n/**cesium 二维三维切换*/\r\n.cesium-sceneModePicker-wrapper {\r\n width: auto;\r\n}\r\n\r\n.cesium-sceneModePicker-wrapper .cesium-sceneModePicker-dropDown-icon {\r\n float: right;\r\n margin: 0 3px;\r\n}\r\n\r\n/**cesium POI查询输入框*/\r\n.cesium-viewer-geocoderContainer .search-results {\r\n left: 0;\r\n right: 40px;\r\n width: auto;\r\n z-index: 9999;\r\n}\r\n\r\n.cesium-geocoder-searchButton {\r\n width: 38px;\r\n height: 38px;\r\n background-color: rgba(39, 44, 54, 0.8);\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n fill: #e6e6e6;\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .cesium-geocoder-input {\r\n height: 40px;\r\n width: 40px;\r\n background-color: rgba(63, 72, 84, 0.7);\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .cesium-geocoder-input:focus {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.cesium-viewer-geocoderContainer .search-results {\r\n background-color: rgba(23, 49, 71, 0.8);\r\n}\r\n\r\n/**cesium info信息框*/\r\n.cesium-infoBox {\r\n top: 50px;\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.cesium-infoBox-title {\r\n background-color: rgba(23, 49, 71, 0.8);\r\n}\r\n\r\n/**cesium 任务栏的FPS信息*/\r\n.cesium-performanceDisplay-defaultContainer {\r\n top: auto;\r\n bottom: 35px;\r\n right: 50px;\r\n}\r\n\r\n.cesium-performanceDisplay-ms,\r\n.cesium-performanceDisplay-fps {\r\n color: #fff;\r\n}\r\n\r\n/**cesium tileset调试信息面板*/\r\n.cesium-viewer-cesiumInspectorContainer {\r\n top: 10px;\r\n left: 10px;\r\n right: auto;\r\n}\r\n\r\n.cesium-cesiumInspector {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n/**覆盖mars3d内部控件的颜色等样式*/\r\n.mars3d-compass .mars3d-compass-outer {\r\n fill: rgba(39, 44, 54, 0.8);\r\n}\r\n.mars3d-compass .mars3d-compass-inner {\r\n background: rgba(39, 44, 54, 0.8);\r\n fill: #fff;\r\n}\r\n\r\n.mars3d-contextmenu-ul,\r\n.mars3d-sub-menu {\r\n background-color: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n.mars3d-contextmenu-ul {\r\n border-radius: 2px;\r\n border-width: 1px;\r\n border-image: url(\"//data.mars3d.cn/img/control/border.svg\") 1 round stretch;\r\n}\r\n\r\n.mars3d-contextmenu-ul > li > a:hover,\r\n.mars3d-sub-menu > li > a:hover,\r\n.mars3d-contextmenu-ul > li > a:focus,\r\n.mars3d-sub-menu > li > a:focus,\r\n.mars3d-contextmenu-ul > li > .active,\r\n.mars3d-sub-menu > li > .active {\r\n background-color: var(--mars-hover-color, #3ea6ff);\r\n}\r\n\r\n.mars3d-contextmenu-ul > .active > a,\r\n.mars3d-sub-menu > .active > a,\r\n.mars3d-contextmenu-ul > .active > a:hover,\r\n.mars3d-sub-menu > .active > a:hover,\r\n.mars3d-contextmenu-ul > .active > a:focus,\r\n.mars3d-sub-menu > .active > a:focus {\r\n background-color: var(--mars-hover-color, #3ea6ff);\r\n}\r\n\r\n/* Popup样式*/\r\n.mars3d-popup-color {\r\n color: var(--mars-text-color, #ffffff);\r\n}\r\n\r\n.mars3d-popup-background {\r\n // background: none会导致剖面的popup没有颜色\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n// .mars3d-popup-content-wrapper {\r\n// box-shadow: none !important;\r\n// padding: 0 !important;\r\n// background: var(--mars-base-border) !important;\r\n// border-radius: 4px;\r\n// }\r\n\r\n.mars3d-popup-content {\r\n margin: 15px;\r\n}\r\n.mars3d-popup-btn-custom {\r\n padding: 3px 10px;\r\n border: 1px solid #209ffd;\r\n background: #209ffd1c;\r\n color: var(--mars-text-color);\r\n}\r\n\r\n.mars3d-tooltip {\r\n color: var(--mars-text-color, #ffffff);\r\n background: var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n border: 1px solid var(--mars-base-bg, rgba(63, 72, 84, 0.9));\r\n}\r\n\r\n.mars3d-tooltip-top:before {\r\n border-top-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-bottom:before {\r\n border-bottom-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-left:before {\r\n border-left-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n\r\n.mars3d-tooltip-right:before {\r\n border-right-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));\r\n}\r\n.mars3d-template-content label {\r\n padding-right: 6px;\r\n}\r\n\r\n/* all 中的html样式 */\r\n.mars3d-template-titile {\r\n height: 33px;\r\n line-height: 33px;\r\n padding-left: 10px;\r\n border-radius: 4px 4px 0px 0px;\r\n box-shadow:\r\n 0px 6px 12px -2px rgba(50, 50, 93, 0.15),\r\n 0px 3px 7px -3px rgba(0, 0, 0, 0.2);\r\n color: var(--mars-control-text) !important;\r\n background: var(--mars-msg-title-bg);\r\n font-family: var(--mars-font-family);\r\n\r\n a {\r\n font-size: 16px;\r\n color: var(--mars-msg-title-color, #479be0);\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.mars3d-template-content {\r\n margin-top: 0 !important;\r\n background-color: var(--mars-dropdown-bg);\r\n padding: 10px;\r\n color: #eaf2ff;\r\n\r\n label {\r\n padding-right: 6px;\r\n }\r\n\r\n input {\r\n color: var(--mars-text-color);\r\n background-color: transparent !important;\r\n padding: 4px 5px;\r\n }\r\n\r\n input::placeholder {\r\n color: #cdcdcd !important;\r\n }\r\n\r\n textarea {\r\n color: var(--mars-base-color);\r\n background-color: transparent !important;\r\n padding: 4px 5px;\r\n }\r\n\r\n textarea::placeholder {\r\n color: #cdcdcd !important;\r\n }\r\n}\r\n\r\n.mars3d-popup-btn-custom {\r\n padding: 3px 10px;\r\n border: 1px solid #209ffd;\r\n background: #209ffd1c;\r\n color: var(--mars-text-color, #ffffff);\r\n}\r\n\r\n.mars3d-popup-content {\r\n margin: 15px;\r\n}\r\n\r\n.mars3d-divGraphic:hover {\r\n z-index: 999 !important;\r\n}\r\n\r\n/* 隐藏Mars3D logo */\r\n.mars3d-logo {\r\n display: none !important;\r\n visibility: hidden !important;\r\n opacity: 0 !important;\r\n pointer-events: none;\r\n}\r\n</style>\r\n","<!--\r\n ToolbarPanel — 测量 & 绘制工具栏\r\n\r\n 改进点(相对原 RightPanel):\r\n - 测量与绘制合并为统一工具栏,去掉冗余的 selectedGraphic 等未使用 prop\r\n - 新增激活态高亮(activeDrawType prop)\r\n - 图标语义更准确(使用 title 提示用户功能)\r\n-->\r\n<template>\r\n <div class=\"toolbar-panel\" :class=\"{ collapsed: isCollapsed }\">\r\n <!-- 收起/展开 header -->\r\n <div class=\"panel-header\" @click=\"toggleCollapse\">\r\n <i\r\n :class=\"[\r\n 'toggle-icon',\r\n 'fa',\r\n isCollapsed ? 'fa-chevron-down' : 'fa-chevron-up',\r\n ]\"\r\n />\r\n </div>\r\n\r\n <div class=\"panel-content\" v-show=\"!isCollapsed\">\r\n <!-- 测量工具组 -->\r\n <div class=\"menu-group\">\r\n <div\r\n v-for=\"item in measureTools\"\r\n :key=\"item.tool\"\r\n class=\"menu-item\"\r\n :title=\"item.title\"\r\n @click=\"activateTool(item.tool)\"\r\n >\r\n <i :class=\"item.iconClasses\" />\r\n </div>\r\n </div>\r\n\r\n <div class=\"divider\" />\r\n\r\n <!-- 绘制工具组 -->\r\n <div class=\"menu-group\">\r\n <div\r\n v-for=\"item in drawTools\"\r\n :key=\"item.tool\"\r\n class=\"menu-item\"\r\n :class=\"{ active: activeDrawType === item.drawType }\"\r\n :title=\"item.title\"\r\n @click=\"activateTool(item.tool)\"\r\n >\r\n <i :class=\"item.iconClasses\" />\r\n </div>\r\n <div class=\"divider\" />\r\n <!-- 清除按钮 -->\r\n <div class=\"menu-item\" title=\"清除全部\" @click=\"emitClear\">\r\n <i class=\"fa-solid fa-trash-can\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\n// ─── Props ───────────────────────────────────────────────────────────────────\r\ndefineProps<{\r\n activeDrawType?: string | null;\r\n}>();\r\n\r\n// ─── Emits ───────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n toolActivate: [tool: string];\r\n clear: [];\r\n}>();\r\n\r\n// ─── State ───────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(false);\r\n\r\nconst toggleCollapse = () => {\r\n isCollapsed.value = !isCollapsed.value;\r\n};\r\nconst activateTool = (tool: string) => {\r\n emit(\"toolActivate\", tool);\r\n};\r\nconst emitClear = () => {\r\n emit(\"clear\");\r\n};\r\n\r\n// ─── 工具配置 ─────────────────────────────────────────────────────────────────\r\ninterface ToolItem {\r\n tool: string;\r\n title: string;\r\n iconClasses: string[];\r\n drawType?: string;\r\n}\r\n\r\nconst measureTools: ToolItem[] = [\r\n {\r\n tool: \"measureDistance\",\r\n title: \"测量距离\",\r\n iconClasses: [\"fa\", \"fa-arrows-alt-h\"], // 水平双向箭头,更准确表达距离\r\n },\r\n {\r\n tool: \"measureArea\",\r\n title: \"测量面积\",\r\n iconClasses: [\"fa\", \"fa-vector-square\"], // 矢量方块,更几何感、专业感\r\n },\r\n {\r\n tool: \"measureHeight\",\r\n title: \"测量高度差\",\r\n iconClasses: [\"fa\", \"fa-arrows-alt-v\"], // 垂直双向箭头,清晰表达高度\r\n },\r\n {\r\n tool: \"measureAngle\",\r\n title: \"测量角度\",\r\n iconClasses: [\"fa-solid\", \"fa-compass-drafting\"], // 绘图圆规图标,专业表达角度测量\r\n },\r\n];\r\n\r\nconst drawTools: ToolItem[] = [\r\n {\r\n tool: \"drawPoint\",\r\n title: \"点标记\",\r\n iconClasses: [\"fa\", \"fa-map-marker\"], // 地图标记点,比空心圆更直观\r\n drawType: \"point\",\r\n },\r\n {\r\n tool: \"drawLine\",\r\n title: \"线标记\",\r\n iconClasses: [\"fa\", \"fa-slash\"], // 斜线比短横线更像\"线\"的概念\r\n drawType: \"polyline\",\r\n },\r\n {\r\n tool: \"drawPolygon\",\r\n title: \"面标记\",\r\n iconClasses: [\"fa-solid\", \"fa-draw-polygon\"], // 多边形绘制图标,语义明确\r\n drawType: \"polygon\",\r\n },\r\n {\r\n tool: \"drawCircle\",\r\n title: \"圆标记\",\r\n iconClasses: [\"fa\", \"fa-circle\"], // 实心圆表示圆\r\n drawType: \"circle\",\r\n },\r\n {\r\n tool: \"drawRectangle\",\r\n title: \"矩形标记\",\r\n iconClasses: [\"fa-regular\", \"fa-square\"], // 空心方块,与圆标记风格统一\r\n drawType: \"rectangle\",\r\n },\r\n {\r\n tool: \"drawFreePolygon\",\r\n title: \"自由多边形\",\r\n iconClasses: [\"fa\", \"fa-pencil\"], // 铅笔表示自由绘制\r\n drawType: \"freePolygon\",\r\n },\r\n];\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.toolbar-panel {\r\n position: absolute;\r\n top: 10px;\r\n right: 0;\r\n width: 42px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px 0 0 6px;\r\n border-right: none;\r\n z-index: 999;\r\n transition: max-height 0.3s ease;\r\n max-height: calc(100vh - 120px);\r\n overflow-y: auto;\r\n backdrop-filter: blur(4px);\r\n\r\n &.collapsed {\r\n max-height: 38px;\r\n .panel-content {\r\n display: none;\r\n }\r\n .panel-header {\r\n padding: 8px;\r\n justify-content: center;\r\n border-radius: 6px 0 0 6px;\r\n }\r\n }\r\n\r\n .panel-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 0 0 0;\r\n cursor: pointer;\r\n user-select: none;\r\n\r\n .toggle-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n transition: all 0.3s ease;\r\n }\r\n\r\n &:hover .toggle-icon {\r\n color: #3ea6ff;\r\n }\r\n }\r\n\r\n .panel-content {\r\n padding: 6px 0;\r\n }\r\n\r\n .menu-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n\r\n .menu-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 8px;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n border-radius: 3px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n\r\n &.active {\r\n background: rgba(62, 166, 255, 0.4);\r\n color: #fff;\r\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n i {\r\n font-size: 14px;\r\n line-height: 1;\r\n }\r\n }\r\n\r\n .divider {\r\n height: 1px;\r\n background: rgba(255, 255, 255, 0.08);\r\n margin: 6px 8px;\r\n }\r\n\r\n &::-webkit-scrollbar {\r\n width: 3px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n</style>\r\n","<!--\r\n VisionPanel — 视角控制面板\r\n\r\n 职责:\r\n - 右下角悬浮按钮 + 弹出浮层\r\n - 四个功能:环绕飞行 / 移动到此处 / 第一视角 / 键盘漫游\r\n - 激活态通过 prop 传入,不在此处维护逻辑\r\n-->\r\n<template>\r\n <!-- 触发按钮 -->\r\n <div class=\"vision-button\" title=\"视觉功能\" @click=\"togglePopup\">\r\n <i class=\"fa fa-eye\" />\r\n </div>\r\n\r\n <!-- 弹出面板 -->\r\n <Transition name=\"vision-fade\">\r\n <div v-if=\"popupVisible\" class=\"vision-popup\">\r\n <div class=\"popup-header\">\r\n <span>视觉功能</span>\r\n <i class=\"fa fa-times close-icon\" @click=\"popupVisible = false\" />\r\n </div>\r\n <div class=\"popup-content\">\r\n <div\r\n v-for=\"item in visionItems\"\r\n :key=\"item.action\"\r\n class=\"popup-item\"\r\n :class=\"{ active: isActive(item) }\"\r\n @click=\"execute(item.action)\"\r\n >\r\n <i :class=\"['fa', item.icon]\" />\r\n <span>{{ getLabel(item) }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </Transition>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\n// ─── Props ───────────────────────────────────────────────────────────────────\r\nconst props = defineProps<{\r\n circleFlyActive?: boolean;\r\n flyToActive?: boolean;\r\n firstPersonActive?: boolean;\r\n keyboardNavigateActive?: boolean;\r\n}>();\r\n\r\n// ─── Emits ───────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n visionExecute: [action: string];\r\n}>();\r\n\r\n// ─── State ───────────────────────────────────────────────────────────────────\r\nconst popupVisible = ref(false);\r\nconst togglePopup = () => { popupVisible.value = !popupVisible.value; };\r\nconst execute = (action: string) => { emit(\"visionExecute\", action); };\r\n\r\n// ─── 功能配置表 ───────────────────────────────────────────────────────────────\r\ninterface VisionItem {\r\n action: string;\r\n icon: string;\r\n label: string;\r\n activeLabel?: string;\r\n activeProp?: keyof typeof props;\r\n}\r\n\r\nconst visionItems: VisionItem[] = [\r\n {\r\n action: \"circleFly\",\r\n icon: \"fa-refresh\",\r\n label: \"环绕飞行\",\r\n activeLabel: \"关闭环绕飞行\",\r\n activeProp: \"circleFlyActive\",\r\n },\r\n {\r\n action: \"flyTo\",\r\n icon: \"fa-location-arrow\",\r\n label: \"移动到此处\",\r\n activeProp: \"flyToActive\",\r\n },\r\n {\r\n action: \"firstPerson\",\r\n icon: \"fa-user\",\r\n label: \"开启第一视角\",\r\n activeLabel: \"关闭第一视角\",\r\n activeProp: \"firstPersonActive\",\r\n },\r\n {\r\n action: \"keyboardNavigate\",\r\n icon: \"fa-keyboard-o\",\r\n label: \"开启键盘漫游\",\r\n activeLabel: \"关闭键盘漫游\",\r\n activeProp: \"keyboardNavigateActive\",\r\n },\r\n];\r\n\r\nconst isActive = (item: VisionItem) =>\r\n item.activeProp ? !!props[item.activeProp] : false;\r\n\r\nconst getLabel = (item: VisionItem) =>\r\n isActive(item) && item.activeLabel ? item.activeLabel : item.label;\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n.vision-button {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 0;\r\n width: 42px;\r\n height: 42px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border-radius: 6px 0 0 6px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-right: none;\r\n z-index: 999;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n backdrop-filter: blur(4px);\r\n transition: all 0.2s ease;\r\n\r\n &:hover { \r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n i { font-size: 14px; }\r\n}\r\n\r\n.vision-popup {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 48px;\r\n width: 170px;\r\n background: rgba(23, 35, 50, 0.92);\r\n border-radius: 6px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n backdrop-filter: blur(4px);\r\n z-index: 998;\r\n\r\n .popup-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 5px 5px 0 0;\r\n\r\n span { color: #e8f4ff; font-size: 13px; font-weight: 600; }\r\n\r\n .close-icon {\r\n color: #7a9ec0;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: color 0.2s ease;\r\n &:hover { color: #3ea6ff; }\r\n }\r\n }\r\n\r\n .popup-content { padding: 6px 0; }\r\n\r\n .popup-item {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 12px;\r\n color: #e8f4ff;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n border-radius: 3px;\r\n margin: 0 4px;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &.active { \r\n background: rgba(62, 166, 255, 0.4);\r\n color: #fff;\r\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n i { margin-right: 10px; width: 16px; text-align: center; font-size: 14px; }\r\n span { font-size: 12px; }\r\n }\r\n}\r\n\r\n// 过渡动画\r\n.vision-fade-enter-active,\r\n.vision-fade-leave-active {\r\n transition: opacity 0.25s ease, transform 0.25s ease;\r\n}\r\n.vision-fade-enter-from,\r\n.vision-fade-leave-to {\r\n opacity: 0;\r\n transform: translateX(15px);\r\n}\r\n</style>\r\n","/**\r\n * useMap — 地图核心 composable\r\n *\r\n * 职责:\r\n * - 持有 mars3d.Map 实例\r\n * - 管理业务 GraphicLayer(绘图层)和 measureLayer(测量层)\r\n * - 暴露地图事件回调(点击坐标记录)\r\n * - 提供统一的图层/thing 注册接口,方便后续业务扩展\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\n\r\n// 使用 any 避免 Mars3D 类型定义过深导致的 TS 推断溢出\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyShallowRef<T> = { readonly value: T | null };\r\n\r\nexport function useMap() {\r\n const Cesium = mars3d.Cesium;\r\n\r\n // ─── 地图实例(shallowRef 避免深响应代理 Cesium 对象) ───────────────\r\n const mapRef = shallowRef<mars3d.Map | null>(null);\r\n\r\n // ─── 核心图层 ─────────────────────────────────────────────────────────\r\n const graphicLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n const measureLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── 选中图形 ─────────────────────────────────────────────────────────\r\n const selectedGraphic = ref<any>(null);\r\n\r\n // ─── 最后点击位置(视角跳转等功能共享) ──────────────────────────────\r\n const lastClickPosition = ref<{ lng: number; lat: number; alt: number } | null>(null);\r\n\r\n /**\r\n * 在地图加载完毕后调用,完成图层、事件的初始化\r\n */\r\n function initMap(map: mars3d.Map) {\r\n mapRef.value = map;\r\n\r\n // 业务绘图层\r\n const gLayer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(gLayer);\r\n graphicLayer.value = gLayer;\r\n\r\n // 测量专用图层\r\n const mLayer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(mLayer);\r\n measureLayer.value = mLayer;\r\n\r\n // ── 地图点击:记录坐标 ──────────────────────────────────────────\r\n map.on(mars3d.EventType.click, (event: any) => {\r\n if (event.lnglat) {\r\n lastClickPosition.value = event.lnglat;\r\n } else if (event.cartesian) {\r\n const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(event.cartesian);\r\n lastClickPosition.value = {\r\n lng: Cesium.Math.toDegrees(carto.longitude),\r\n lat: Cesium.Math.toDegrees(carto.latitude),\r\n alt: carto.height > 0 ? carto.height : 5000,\r\n };\r\n }\r\n });\r\n\r\n // ── 图形层交互事件 ────────────────────────────────────────────────\r\n gLayer.on(mars3d.EventType.click, (event: any) => {\r\n selectedGraphic.value = event.graphic;\r\n });\r\n gLayer.on(mars3d.EventType.mouseOver, (event: any) => {\r\n if (!selectedGraphic.value) {\r\n selectedGraphic.value = event.graphic;\r\n }\r\n });\r\n gLayer.on(mars3d.EventType.mouseOut, (event: any) => {\r\n if (selectedGraphic.value === event.graphic) {\r\n selectedGraphic.value = null;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * 销毁地图(组件卸载时调用)\r\n */\r\n function destroyMap() {\r\n if (mapRef.value) {\r\n mapRef.value.destroy();\r\n mapRef.value = null;\r\n }\r\n }\r\n\r\n /**\r\n * 便捷方法:向业务图层添加 Graphic\r\n */\r\n function addGraphic(graphic: any) {\r\n graphicLayer.value?.addGraphic(graphic);\r\n }\r\n\r\n /**\r\n * 向地图添加自定义 Thing(供业务扩展)\r\n */\r\n function addThing(thing: any) {\r\n mapRef.value?.addThing(thing);\r\n }\r\n\r\n return {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n map: mapRef as AnyShallowRef<any>,\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n graphicLayer: graphicLayer as AnyShallowRef<any>,\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n measureLayer: measureLayer as AnyShallowRef<any>,\r\n selectedGraphic,\r\n lastClickPosition,\r\n initMap,\r\n destroyMap,\r\n addGraphic,\r\n addThing,\r\n };\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type UseMapReturn = ReturnType<typeof useMap>;\r\n","/**\r\n * useMeasure — 测量工具 composable\r\n *\r\n * 职责:\r\n * - 封装 mars3d.thing.Measure 的生命周期\r\n * - 提供 距离 / 面积 / 高度差 / 角度 四种测量方法\r\n * - 提供 clear 清除方法\r\n *\r\n * 依赖:useMap 返回的 map 与 measureLayer\r\n */\r\nimport { shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\nexport function useMeasure(mapContext: UseMapReturn) {\r\n const measureThing = shallowRef<mars3d.thing.Measure | null>(null);\r\n\r\n /** 在地图初始化后调用,注册 Measure thing */\r\n function initMeasure() {\r\n const map = mapContext.map.value;\r\n const layer = mapContext.measureLayer.value;\r\n if (!map || !layer) return;\r\n\r\n const m = new mars3d.thing.Measure({ graphicLayer: layer } as any);\r\n map.addThing(m);\r\n measureThing.value = m;\r\n }\r\n\r\n /** 测量距离 */\r\n function measureDistance(style?: Record<string, any>) {\r\n measureThing.value?.distance({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 测量面积 */\r\n function measureArea(style?: Record<string, any>) {\r\n measureThing.value?.area({\r\n style: { color: \"#3388ff\", opacity: 0.5, ...style },\r\n });\r\n }\r\n\r\n /** 测量高度差 */\r\n function measureHeight(style?: Record<string, any>) {\r\n measureThing.value?.height({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 测量角度 */\r\n function measureAngle(style?: Record<string, any>) {\r\n measureThing.value?.angle({\r\n style: { color: \"#3388ff\", width: 3, ...style },\r\n });\r\n }\r\n\r\n /** 清除所有测量结果 */\r\n function clearMeasure() {\r\n measureThing.value?.clear();\r\n mapContext.measureLayer.value?.clear();\r\n }\r\n\r\n return {\r\n measureThing,\r\n initMeasure,\r\n measureDistance,\r\n measureArea,\r\n measureHeight,\r\n measureAngle,\r\n clearMeasure,\r\n };\r\n}\r\n","/**\r\n * useDraw — 绘制工具 composable\r\n *\r\n * 职责:\r\n * - 封装六种图形绘制(点/线/面/圆/矩形/自由多边形)\r\n * - 统一管理 currentDraw 引用,保证绘制互斥\r\n * - 提供 stopDraw / clearDraw 方法\r\n *\r\n * 依赖:useMap 返回的 measureLayer(绘图结果复用测量层,也可传独立图层)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\n/** 支持的绘制类型枚举,方便外部类型提示 */\r\nexport type DrawType = \"point\" | \"polyline\" | \"polygon\" | \"circle\" | \"rectangle\" | \"freePolygon\";\r\n\r\nexport function useDraw(mapContext: UseMapReturn) {\r\n const currentDraw = shallowRef<any>(null);\r\n /** 当前激活的绘制类型,用于 UI 高亮 */\r\n const activeDrawType = ref<DrawType | null>(null);\r\n\r\n /** 获取绘制目标图层(复用 measureLayer,也可按需传其他层) */\r\n function getLayer() {\r\n return mapContext.measureLayer.value;\r\n }\r\n\r\n /** 内部启动绘制 */\r\n function startDraw(type: string, style: Record<string, any>, drawType: DrawType) {\r\n const layer = getLayer();\r\n if (!layer) return;\r\n stopDraw(); // 先停止上一次未完成的绘制\r\n currentDraw.value = layer.startDraw({ type, style });\r\n activeDrawType.value = drawType;\r\n }\r\n\r\n /** 绘制点 */\r\n function drawPoint(style?: Record<string, any>) {\r\n startDraw(\"point\", { pixelSize: 10, color: \"#ff0000\", ...style }, \"point\");\r\n }\r\n\r\n /** 绘制折线 */\r\n function drawLine(style?: Record<string, any>) {\r\n startDraw(\"polyline\", { width: 3, color: \"#3388ff\", ...style }, \"polyline\");\r\n }\r\n\r\n /** 绘制多边形 */\r\n function drawPolygon(style?: Record<string, any>) {\r\n startDraw(\"polygon\", { color: \"#3388ff\", opacity: 0.5, ...style }, \"polygon\");\r\n }\r\n\r\n /** 绘制圆 */\r\n function drawCircle(style?: Record<string, any>) {\r\n startDraw(\"circle\", { radius: 1000, color: \"#00ff00\", opacity: 0.3, ...style }, \"circle\");\r\n }\r\n\r\n /** 绘制矩形 */\r\n function drawRectangle(style?: Record<string, any>) {\r\n startDraw(\"rectangle\", { color: \"#3388ff\", opacity: 0.5, ...style }, \"rectangle\");\r\n }\r\n\r\n /** 绘制自由多边形(贴地) */\r\n function drawFreePolygon(style?: Record<string, any>) {\r\n startDraw(\r\n \"polygon\",\r\n { color: \"#3388ff\", opacity: 0.5, clampToGround: true, ...style },\r\n \"freePolygon\",\r\n );\r\n }\r\n\r\n /** 停止当前绘制,但保留已绘结果 */\r\n function stopDraw() {\r\n if (currentDraw.value) {\r\n getLayer()?.stopDraw();\r\n currentDraw.value = null;\r\n }\r\n activeDrawType.value = null;\r\n }\r\n\r\n /** 停止并清除所有绘制结果 */\r\n function clearDraw() {\r\n stopDraw();\r\n getLayer()?.clear();\r\n }\r\n\r\n return {\r\n currentDraw,\r\n activeDrawType,\r\n drawPoint,\r\n drawLine,\r\n drawPolygon,\r\n drawCircle,\r\n drawRectangle,\r\n drawFreePolygon,\r\n stopDraw,\r\n clearDraw,\r\n };\r\n}\r\n","/**\r\n * useVision — 视角控制 composable\r\n *\r\n * 职责:\r\n * - 封装环绕飞行(RotatePoint)\r\n * - 封装飞行到指定位置(flyTo / flyHome)\r\n * - 封装第一视角漫游(FirstPersonRoam)\r\n * - 封装键盘漫游(KeyboardRoam)\r\n * - 暴露各功能的激活状态,供 UI 显示切换文案\r\n *\r\n * 依赖:useMap 返回的 map 与 lastClickPosition\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"./useMap\";\r\n\r\nexport function useVision(mapContext: UseMapReturn) {\r\n // ─── 状态 ──────────────────────────────────────────────────────────────\r\n const circleFlyActive = ref(false);\r\n const firstPersonActive = ref(false);\r\n const keyboardActive = ref(false);\r\n const flyToActive = ref(false);\r\n\r\n // ─── Thing 实例 ────────────────────────────────────────────────────────\r\n const rotatePoint = shallowRef<mars3d.thing.RotatePoint | null>(null);\r\n const firstPersonRoam = shallowRef<mars3d.thing.FirstPersonRoam | null>(null);\r\n const keyboardRoam = shallowRef<mars3d.thing.KeyboardRoam | null>(null);\r\n let initialCameraView: any = null;\r\n\r\n /** 获取地图实例(内部简写) */\r\n function getMap() {\r\n return mapContext.map.value;\r\n }\r\n\r\n // ─── 环绕飞行 ──────────────────────────────────────────────────────────\r\n function toggleCircleFly() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (rotatePoint.value) {\r\n if (rotatePoint.value.isStart) {\r\n rotatePoint.value.stop();\r\n }\r\n map.removeThing(rotatePoint.value);\r\n rotatePoint.value = null;\r\n circleFlyActive.value = false;\r\n return;\r\n }\r\n\r\n const center = map.getCenter();\r\n const rp = new mars3d.thing.RotatePoint({ distance: 5000, time: 30 });\r\n map.addThing(rp);\r\n rp.start(center);\r\n rotatePoint.value = rp;\r\n circleFlyActive.value = true;\r\n }\r\n\r\n // ─── 飞行到点击位置或地图中心 ──────────────────────────────────────────\r\n function flyTo() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n flyToActive.value = true;\r\n const done = () => setTimeout(() => { flyToActive.value = false; }, 2000);\r\n\r\n const pos = mapContext.lastClickPosition.value;\r\n if (pos) {\r\n const target = { ...pos, alt: pos.alt > 0 ? pos.alt : 5000 };\r\n map.setCameraView(target, { duration: 2, complete: done });\r\n } else {\r\n map.flyHome({ duration: 2 });\r\n done();\r\n }\r\n }\r\n\r\n // ─── 第一视角漫游 ──────────────────────────────────────────────────────\r\n function toggleFirstPerson() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (!firstPersonRoam.value) {\r\n const roam = new mars3d.thing.FirstPersonRoam({});\r\n map.addThing(roam);\r\n initialCameraView = map.getCameraView();\r\n roam.enabled = true;\r\n firstPersonRoam.value = roam;\r\n firstPersonActive.value = true;\r\n } else {\r\n const roam = firstPersonRoam.value;\r\n roam.enabled = !roam.enabled;\r\n firstPersonActive.value = roam.enabled;\r\n if (!roam.enabled && initialCameraView) {\r\n map.setCameraView(initialCameraView, { duration: 1 });\r\n } else if (roam.enabled) {\r\n initialCameraView = map.getCameraView();\r\n }\r\n }\r\n }\r\n\r\n // ─── 键盘漫游 ──────────────────────────────────────────────────────────\r\n function toggleKeyboardNavigate() {\r\n const map = getMap();\r\n if (!map) return;\r\n\r\n if (!keyboardRoam.value) {\r\n const roam = new mars3d.thing.KeyboardRoam({});\r\n map.addThing(roam);\r\n roam.enabled = true;\r\n keyboardRoam.value = roam;\r\n keyboardActive.value = true;\r\n } else {\r\n const roam = keyboardRoam.value;\r\n roam.enabled = !roam.enabled;\r\n keyboardActive.value = roam.enabled;\r\n }\r\n }\r\n\r\n return {\r\n // 状态\r\n circleFlyActive,\r\n firstPersonActive,\r\n keyboardActive,\r\n flyToActive,\r\n // 方法\r\n toggleCircleFly,\r\n flyTo,\r\n toggleFirstPerson,\r\n toggleKeyboardNavigate,\r\n };\r\n}\r\n","<!--\r\n MarsMapContainer — 地图核心容器组件\r\n\r\n 功能:\r\n 1. 集成底层 MarsMap 渲染组件\r\n 2. 内置测量/绘制工具栏(ToolbarPanel)和视角控制面板(VisionPanel)\r\n 3. 组合所有 composable,通过 provide 向子组件/插槽透传地图上下文\r\n 4. 通过 default 插槽支持业务组件叠加(popup、图表、统计面板等)\r\n\r\n Props:\r\n - configUrl 地图配置 JSON 路径\r\n - mapKey 多地图时区分实例的 key(默认 \"default\")\r\n - hideToolbar 是否隐藏工具栏(默认 false)\r\n - hideVision 是否隐藏视觉控制按钮(默认 false)\r\n\r\n Expose(供父组件通过 ref 访问):\r\n - map\r\n - graphicLayer\r\n - measureLayer\r\n - selectedGraphic\r\n - addGraphic()\r\n - addThing()\r\n - measure(useMeasure 全量返回)\r\n - draw(useDraw 全量返回)\r\n - vision(useVision 全量返回)\r\n-->\r\n<template>\r\n <div class=\"mars-map-container\">\r\n <!-- 底层地图渲染 -->\r\n <MarsMap\r\n :url=\"configUrl\"\r\n :map-key=\"mapKey\"\r\n @onload=\"onMapLoad\"\r\n />\r\n\r\n <!-- 测量/绘制工具栏 -->\r\n <ToolbarPanel\r\n v-if=\"!hideToolbar\"\r\n :active-draw-type=\"draw.activeDrawType.value\"\r\n @tool-activate=\"handleToolActivate\"\r\n @clear=\"handleClear\"\r\n />\r\n\r\n <!-- 视角控制面板 -->\r\n <VisionPanel\r\n v-if=\"!hideVision\"\r\n :circle-fly-active=\"vision.circleFlyActive.value\"\r\n :fly-to-active=\"vision.flyToActive.value\"\r\n :first-person-active=\"vision.firstPersonActive.value\"\r\n :keyboard-navigate-active=\"vision.keyboardActive.value\"\r\n @vision-execute=\"handleVisionExecute\"\r\n />\r\n\r\n <!-- 业务插槽:自定义 UI 叠加层 -->\r\n <slot />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { provide } from \"vue\";\r\nimport MarsMap from \"../mars-work/mars-map.vue\";\r\nimport ToolbarPanel from \"./panels/ToolbarPanel.vue\";\r\nimport VisionPanel from \"./panels/VisionPanel.vue\";\r\n\r\nimport { useMap } from \"./composables/useMap\";\r\nimport { useMeasure } from \"./composables/useMeasure\";\r\nimport { useDraw } from \"./composables/useDraw\";\r\nimport { useVision } from \"./composables/useVision\";\r\n\r\n// ─── Props ──────────────────────────────────────────────────────────────────\r\nconst props = withDefaults(\r\n defineProps<{\r\n configUrl?: string;\r\n mapKey?: string;\r\n hideToolbar?: boolean;\r\n hideVision?: boolean;\r\n }>(),\r\n {\r\n configUrl: \"config/config.json\",\r\n mapKey: \"default\",\r\n hideToolbar: false,\r\n hideVision: false,\r\n },\r\n);\r\n\r\n// ─── Emits ──────────────────────────────────────────────────────────────────\r\nconst emit = defineEmits<{\r\n /** 地图加载完成,回传 map 实例 */\r\n onload: [map: any];\r\n}>();\r\n\r\n// ─── Composables ────────────────────────────────────────────────────────────\r\nconst mapCtx = useMap();\r\nconst measure = useMeasure(mapCtx);\r\nconst draw = useDraw(mapCtx);\r\nconst vision = useVision(mapCtx);\r\n\r\n// ─── provide(供插槽内的业务组件直接 inject 使用) ──────────────────────────\r\nprovide(\"mapContext\", mapCtx);\r\nprovide(\"measureContext\", measure);\r\nprovide(\"drawContext\", draw);\r\nprovide(\"visionContext\", vision);\r\n\r\n// ─── 地图加载回调 ────────────────────────────────────────────────────────────\r\nfunction onMapLoad(map: any) {\r\n mapCtx.initMap(map);\r\n measure.initMeasure();\r\n emit(\"onload\", map);\r\n}\r\n\r\n// ─── 工具栏事件处理 ──────────────────────────────────────────────────────────\r\ntype ToolAction =\r\n | \"measureDistance\" | \"measureArea\" | \"measureHeight\" | \"measureAngle\"\r\n | \"drawPoint\" | \"drawLine\" | \"drawPolygon\" | \"drawCircle\" | \"drawRectangle\" | \"drawFreePolygon\";\r\n\r\nfunction handleToolActivate(tool: string) {\r\n switch (tool as ToolAction) {\r\n case \"measureDistance\": measure.measureDistance(); break;\r\n case \"measureArea\": measure.measureArea(); break;\r\n case \"measureHeight\": measure.measureHeight(); break;\r\n case \"measureAngle\": measure.measureAngle(); break;\r\n case \"drawPoint\": draw.drawPoint(); break;\r\n case \"drawLine\": draw.drawLine(); break;\r\n case \"drawPolygon\": draw.drawPolygon(); break;\r\n case \"drawCircle\": draw.drawCircle(); break;\r\n case \"drawRectangle\": draw.drawRectangle(); break;\r\n case \"drawFreePolygon\": draw.drawFreePolygon(); break;\r\n }\r\n}\r\n\r\nfunction handleClear() {\r\n measure.clearMeasure();\r\n draw.clearDraw();\r\n}\r\n\r\n// ─── 视角控制事件处理 ────────────────────────────────────────────────────────\r\ntype VisionAction = \"circleFly\" | \"flyTo\" | \"firstPerson\" | \"keyboardNavigate\";\r\n\r\nfunction handleVisionExecute(action: string) {\r\n switch (action as VisionAction) {\r\n case \"circleFly\": vision.toggleCircleFly(); break;\r\n case \"flyTo\": vision.flyTo(); break;\r\n case \"firstPerson\": vision.toggleFirstPerson(); break;\r\n case \"keyboardNavigate\": vision.toggleKeyboardNavigate(); break;\r\n }\r\n}\r\n\r\n// ─── Expose(父组件 ref 访问) ────────────────────────────────────────────────\r\ndefineExpose({\r\n map: mapCtx.map,\r\n graphicLayer: mapCtx.graphicLayer,\r\n measureLayer: mapCtx.measureLayer,\r\n selectedGraphic: mapCtx.selectedGraphic,\r\n lastClickPosition: mapCtx.lastClickPosition,\r\n addGraphic: mapCtx.addGraphic,\r\n addThing: mapCtx.addThing,\r\n measure,\r\n draw,\r\n vision,\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.mars-map-container {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n</style>\r\n","/**\r\n * usePoiMarker — POI 标注管理 composable\r\n *\r\n * 职责:\r\n * - 维护 POI 数据列表(纯数据层)\r\n * - 管理地图上对应的 BillboardEntity 图形(图形层)\r\n * - 提供 添加 / 删除 / 选中 / 飞行定位 操作\r\n * - 数据与图形保持双向同步(通过 graphicId 关联)\r\n *\r\n * 使用方式(在业务组件内):\r\n * const mapCtx = inject<UseMapReturn>('mapContext')!\r\n * const poi = usePoiMarker(mapCtx)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\n\r\n// ─── POI 数据类型 ─────────────────────────────────────────────────────────────\r\nexport interface PoiItem {\r\n id: string;\r\n name: string;\r\n lng: number;\r\n lat: number;\r\n alt: number;\r\n category: \"default\" | \"warning\" | \"info\";\r\n description?: string;\r\n /** 对应地图上的 Graphic 实例引用 */\r\n graphic?: any;\r\n}\r\n\r\n/** 分类颜色映射 */\r\nconst CATEGORY_ICON: Record<PoiItem[\"category\"], string> = {\r\n default: \"//data.mars3d.cn/img/marker/mark-blue.png\",\r\n warning: \"//data.mars3d.cn/img/marker/mark-red.png\",\r\n info: \"//data.mars3d.cn/img/marker/mark-green.png\",\r\n};\r\n\r\nlet _idCounter = 1;\r\n\r\nexport function usePoiMarker(mapCtx: UseMapReturn) {\r\n // ─── 独立业务图层(与测量层隔离) ─────────────────────────────────────────\r\n const poiLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── POI 数据列表 ──────────────────────────────────────────────────────────\r\n const poiList = ref<PoiItem[]>([]);\r\n\r\n // ─── 当前选中的 POI ────────────────────────────────────────────────────────\r\n const activePoiId = ref<string | null>(null);\r\n\r\n /** 在地图加载后调用,初始化专属图层 */\r\n function initPoiLayer() {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n const layer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(layer);\r\n poiLayer.value = layer;\r\n\r\n // 点击图层上的标注 → 选中对应 POI\r\n layer.on(mars3d.EventType.click, (e: any) => {\r\n const poiId = e.graphic?.attr?.poiId;\r\n if (poiId) selectPoi(poiId);\r\n });\r\n }\r\n\r\n /** 添加 POI(创建数据 + 在地图上生成图形) */\r\n function addPoi(params: Omit<PoiItem, \"id\" | \"graphic\">) {\r\n const layer = poiLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `poi-${_idCounter++}`;\r\n\r\n // 创建地图图形\r\n const graphic = new mars3d.graphic.BillboardEntity({\r\n position: [params.lng, params.lat, params.alt],\r\n style: {\r\n image: CATEGORY_ICON[params.category],\r\n scale: 1,\r\n horizontalOrigin: mars3d.Cesium.HorizontalOrigin.CENTER,\r\n verticalOrigin: mars3d.Cesium.VerticalOrigin.BOTTOM,\r\n clampToGround: false,\r\n // 标注文字\r\n label: {\r\n text: params.name,\r\n font_size: 14,\r\n color: \"#ffffff\",\r\n outline: true,\r\n outlineColor: \"#333333\",\r\n outlineWidth: 2,\r\n pixelOffset: new mars3d.Cesium.Cartesian2(0, -40),\r\n visibleDepth: false,\r\n },\r\n },\r\n // popup 弹窗(点击标注时自动展示)\r\n popup: buildPopupHtml(params),\r\n attr: { poiId: id, name: params.name },\r\n });\r\n\r\n layer.addGraphic(graphic);\r\n\r\n const poi: PoiItem = { ...params, id, graphic };\r\n poiList.value.push(poi);\r\n return poi;\r\n }\r\n\r\n /** 删除 POI */\r\n function removePoi(id: string) {\r\n const idx = poiList.value.findIndex((p) => p.id === id);\r\n if (idx === -1) return;\r\n\r\n const poi = poiList.value[idx];\r\n poi.graphic && poiLayer.value?.removeGraphic(poi.graphic);\r\n poiList.value.splice(idx, 1);\r\n\r\n if (activePoiId.value === id) activePoiId.value = null;\r\n }\r\n\r\n /** 选中 POI(高亮 + 视角飞行) */\r\n function selectPoi(id: string, flyTo = false) {\r\n activePoiId.value = id;\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi) return;\r\n\r\n // 高亮:放大图标\r\n poiList.value.forEach((p) => {\r\n if (p.graphic) {\r\n p.graphic.style.scale = p.id === id ? 1.4 : 1.0;\r\n }\r\n });\r\n\r\n if (flyTo) flyToPoi(id);\r\n }\r\n\r\n /** 更新 POI 名称(实时同步到图形和 popup) */\r\n function updatePoiName(id: string, newName: string) {\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi) return;\r\n\r\n poi.name = newName;\r\n\r\n // 同步更新图形 attr\r\n if (poi.graphic) {\r\n poi.graphic.attr = { ...poi.graphic.attr, name: newName };\r\n poi.graphic.popup = buildPopupHtml(poi);\r\n // 同步更新 label 文字\r\n if (poi.graphic.style?.label) {\r\n poi.graphic.style.label.text = newName;\r\n }\r\n poi.graphic.closePopup?.();\r\n }\r\n }\r\n\r\n /** 飞行到 POI 位置 */\r\n function flyToPoi(id: string) {\r\n const poi = poiList.value.find((p) => p.id === id);\r\n if (!poi || !mapCtx.map.value) return;\r\n\r\n const map = mapCtx.map.value;\r\n\r\n // 以标注点高度为基准,飞行高度 = 标注高度 + 合理偏移\r\n const baseAlt = poi.alt > 1 ? poi.alt : 50;\r\n const flyAlt = baseAlt + 1500;\r\n\r\n // 不指定 pitch,让相机正上方俯视,定位最准确\r\n map.setCameraView({ lng: poi.lng, lat: poi.lat, alt: flyAlt }, { duration: 1.5 });\r\n }\r\n\r\n /** 清空所有 POI */\r\n function clearAll() {\r\n poiLayer.value?.clear();\r\n poiList.value = [];\r\n activePoiId.value = null;\r\n }\r\n\r\n /** 开启/关闭「点击地图添加标注」模式 */\r\n const isAddMode = ref(false);\r\n let _clickHandler: ((e: any) => void) | null = null;\r\n\r\n function toggleAddMode(\r\n onAdded?: (poi: PoiItem) => void,\r\n defaultName = \"新标注\",\r\n category: PoiItem[\"category\"] = \"default\",\r\n ) {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n if (isAddMode.value) {\r\n // 退出添加模式\r\n if (_clickHandler) {\r\n map.off(mars3d.EventType.click, _clickHandler);\r\n _clickHandler = null;\r\n }\r\n isAddMode.value = false;\r\n } else {\r\n // 进入添加模式:下一次点击地图即创建 POI\r\n isAddMode.value = true;\r\n _clickHandler = (e: any) => {\r\n // 优先取经纬度坐标,兜底用笛卡尔坐标转换\r\n let lng: number, lat: number, alt: number;\r\n\r\n if (e.lnglat) {\r\n lng = e.lnglat.lng;\r\n lat = e.lnglat.lat;\r\n alt = e.lnglat.alt ?? 0;\r\n } else if (e.cartesian) {\r\n const carto = mars3d.Cesium.Cartographic.fromCartesian(e.cartesian);\r\n lng = mars3d.Cesium.Math.toDegrees(carto.longitude);\r\n lat = mars3d.Cesium.Math.toDegrees(carto.latitude);\r\n alt = carto.height > 0 ? carto.height : 50; // terrain height fallback\r\n } else {\r\n return;\r\n }\r\n\r\n // 标注高度至少离地面 50m,避免贴地\r\n const finalAlt = alt > 1 ? alt : 50;\r\n\r\n const poi = addPoi({\r\n name: `${defaultName} ${_idCounter}`,\r\n lng,\r\n lat,\r\n alt: finalAlt,\r\n category,\r\n });\r\n if (poi) onAdded?.(poi);\r\n // 单次模式:添加完即退出\r\n toggleAddMode();\r\n };\r\n map.on(mars3d.EventType.click, _clickHandler);\r\n }\r\n }\r\n\r\n return {\r\n poiLayer,\r\n poiList,\r\n activePoiId,\r\n isAddMode,\r\n initPoiLayer,\r\n addPoi,\r\n removePoi,\r\n selectPoi,\r\n flyToPoi,\r\n updatePoiName,\r\n clearAll,\r\n toggleAddMode,\r\n };\r\n}\r\n\r\n// ─── 工具:生成 popup HTML ────────────────────────────────────────────────────\r\nfunction buildPopupHtml(poi: Omit<PoiItem, \"id\" | \"graphic\">) {\r\n return `\r\n <div style=\"padding:8px 12px;min-width:160px;\">\r\n <div style=\"font-size:15px;font-weight:bold;margin-bottom:6px;color:#fff;\">${poi.name}</div>\r\n <div style=\"font-size:12px;color:#adc6e5;line-height:1.8;\">\r\n <div>经度:${poi.lng.toFixed(6)}</div>\r\n <div>纬度:${poi.lat.toFixed(6)}</div>\r\n <div>高度:${poi.alt.toFixed(1)} m</div>\r\n ${poi.description ? `<div style=\"margin-top:4px;\">${poi.description}</div>` : \"\"}\r\n </div>\r\n </div>\r\n `;\r\n}\r\n\r\nexport type UsePoiMarkerReturn = ReturnType<typeof usePoiMarker>;\r\n","<!--\r\n PoiMarkerLayer — POI 标注地图层组件\r\n\r\n 职责:\r\n - 放置在 MarsMapContainer 的 <slot> 内\r\n - 通过 inject 获取地图上下文,完成图层初始化\r\n - 通过 provide 将 poiCtx 向子组件暴露(inject 只走父→子,不走兄弟)\r\n - 内部通过 <slot> 渲染 PoiMarkerPanel 等子组件,保证 provide/inject 链路正确\r\n - 对外 expose usePoiMarker 全量接口,供父组件 ref 访问\r\n\r\n 使用方式(PoiMarkerPanel 必须作为子内容传入,而非兄弟节点):\r\n <MarsMapContainer @onload=\"...\">\r\n <PoiMarkerLayer ref=\"poiLayerRef\">\r\n <PoiMarkerPanel />\r\n </PoiMarkerLayer>\r\n </MarsMapContainer>\r\n-->\r\n<template>\r\n <!-- provide/inject 需要父子关系,用 slot 渲染子组件 -->\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { inject, provide, watch, onUnmounted } from \"vue\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\nimport { usePoiMarker } from \"./usePoiMarker\";\r\n\r\n// ─── 注入地图上下文 ────────────────────────────────────────────────────────────\r\nconst mapCtx = inject<UseMapReturn>(\"mapContext\");\r\nif (!mapCtx) throw new Error(\"[PoiMarkerLayer] 必须放置在 MarsMapContainer 内部\");\r\n\r\n// ─── 初始化 POI 管理 composable ────────────────────────────────────────────────\r\nconst poi = usePoiMarker(mapCtx);\r\n\r\n// ─── 等待地图就绪后初始化图层 ─────────────────────────────────────────────────\r\n// map 在 MarsMapContainer onload 后才不为 null\r\nconst stopWatch = watch(\r\n () => mapCtx.map.value,\r\n (map) => {\r\n if (map) {\r\n poi.initPoiLayer();\r\n stopWatch(); // 只需初始化一次\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n\r\nonUnmounted(() => {\r\n poi.clearAll();\r\n});\r\n\r\n// ─── provide 给同级业务组件(PoiMarkerPanel 等)─────────────────────────────\r\nprovide(\"poiContext\", poi);\r\n\r\n// ─── expose 给父组件 ref ──────────────────────────────────────────────────────\r\ndefineExpose(poi);\r\n</script>\r\n","<!--\r\n PoiMarkerPanel — POI 标注管理面板(左侧)\r\n\r\n 功能:\r\n - 标注列表(名称 / 分类标签 / 定位 / 删除)\r\n - 添加模式切换按钮(点击地图新增标注)\r\n - 分类筛选标签\r\n - 点击列表项飞行到标注位置 + 地图高亮\r\n\r\n 数据来源:inject('poiContext'),由同级 PoiMarkerLayer 提供\r\n-->\r\n<template>\r\n <div\r\n ref=\"panelEl\"\r\n class=\"poi-panel\"\r\n :class=\"{ collapsed: isCollapsed }\"\r\n :style=\"\r\n !isCollapsed\r\n ? { left: pos.x + 'px', top: pos.y + 'px' }\r\n : { left: pos.x + 'px', top: pos.y + 'px' }\r\n \"\r\n >\r\n <!-- 面板标题栏(可拖拽) -->\r\n <div\r\n class=\"poi-panel__header\"\r\n :class=\"{ 'is-dragging': isDragging }\"\r\n @mousedown.prevent=\"startDrag\"\r\n @click=\"isDragging ? null : toggleCollapse()\"\r\n >\r\n <!-- 收缩后只显示图标 -->\r\n <template v-if=\"isCollapsed\">\r\n <div class=\"collapsed-icon-wrap\">\r\n <i class=\"fa fa-map-marker collapsed-icon\" />\r\n <span class=\"poi-count poi-count--collapsed\">{{\r\n filteredList.length\r\n }}</span>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span class=\"poi-panel__title\">\r\n <i class=\"fa fa-map-marker\" />\r\n POI 标注管理\r\n <span class=\"poi-count\">{{ filteredList.length }}</span>\r\n </span>\r\n <i class=\"fa fa-chevron-left collapse-icon\" />\r\n </template>\r\n </div>\r\n\r\n <div class=\"poi-panel__body\" v-show=\"!isCollapsed\">\r\n <!-- 操作栏 -->\r\n <div class=\"poi-panel__toolbar\">\r\n <button\r\n class=\"btn\"\r\n :class=\"{ 'btn--active': poi.isAddMode.value }\"\r\n @click=\"toggleAdd\"\r\n >\r\n <i :class=\"['fa', poi.isAddMode.value ? 'fa-times' : 'fa-plus']\" />\r\n {{ poi.isAddMode.value ? \"取消添加\" : \"点击地图添加\" }}\r\n </button>\r\n <button\r\n class=\"btn btn--danger\"\r\n @click=\"confirmClear\"\r\n :disabled=\"poi.poiList.value.length === 0\"\r\n >\r\n <i class=\"fa fa-trash-o\" /> 清空\r\n </button>\r\n </div>\r\n\r\n <!-- 分类筛选 -->\r\n <div class=\"poi-panel__filter\">\r\n <span\r\n v-for=\"cat in categories\"\r\n :key=\"cat.value\"\r\n class=\"filter-tag\"\r\n :class=\"{ active: activeCategory === cat.value }\"\r\n @click=\"activeCategory = cat.value\"\r\n >\r\n <i :class=\"['fa', cat.icon]\" :style=\"{ color: cat.color }\" />\r\n {{ cat.label }}\r\n </span>\r\n </div>\r\n\r\n <!-- POI 列表 -->\r\n <div class=\"poi-panel__list\">\r\n <TransitionGroup name=\"poi-list\">\r\n <div\r\n v-for=\"item in filteredList\"\r\n :key=\"item.id\"\r\n class=\"poi-item\"\r\n :class=\"{ 'poi-item--active': poi.activePoiId.value === item.id }\"\r\n @click=\"onSelect(item.id)\"\r\n >\r\n <!-- 分类色块 -->\r\n <span\r\n class=\"poi-item__dot\"\r\n :style=\"{ background: getCategoryColor(item.category) }\"\r\n />\r\n\r\n <div class=\"poi-item__info\">\r\n <!-- 编辑态:输入框 -->\r\n <input\r\n v-if=\"editingId === item.id\"\r\n class=\"poi-item__name-input\"\r\n v-model=\"editName\"\r\n @keydown.enter=\"saveEdit\"\r\n @keydown.escape=\"cancelEdit\"\r\n @click.stop\r\n ref=\"editInputEl\"\r\n />\r\n <!-- 正常态:名称 -->\r\n <div\r\n v-else\r\n class=\"poi-item__name\"\r\n @dblclick.stop=\"startEdit(item)\"\r\n >\r\n {{ item.name }}\r\n </div>\r\n <div class=\"poi-item__coord\">\r\n {{ item.lng.toFixed(4) }}, {{ item.lat.toFixed(4) }}\r\n </div>\r\n </div>\r\n\r\n <!-- 操作按钮 -->\r\n <div class=\"poi-item__actions\">\r\n <button\r\n class=\"icon-btn\"\r\n title=\"编辑名称\"\r\n @click.stop=\"startEdit(item)\"\r\n >\r\n <i class=\"fa fa-pencil\" />\r\n </button>\r\n <button\r\n class=\"icon-btn\"\r\n title=\"飞行定位\"\r\n @click.stop=\"onFlyTo(item.id)\"\r\n >\r\n <i class=\"fa fa-crosshairs\" />\r\n </button>\r\n <button\r\n class=\"icon-btn icon-btn--danger\"\r\n title=\"删除\"\r\n @click.stop=\"onRemove(item.id)\"\r\n >\r\n <i class=\"fa fa-times\" />\r\n </button>\r\n </div>\r\n </div>\r\n </TransitionGroup>\r\n\r\n <!-- 空状态 -->\r\n <div v-if=\"filteredList.length === 0\" class=\"poi-panel__empty\">\r\n <i class=\"fa fa-map-o\" />\r\n <p>\r\n {{\r\n poi.isAddMode.value ? \"请在地图上点击添加标注\" : \"暂无标注数据\"\r\n }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive, computed, inject } from \"vue\";\r\nimport type { UsePoiMarkerReturn, PoiItem } from \"./usePoiMarker\";\r\n\r\n// ─── 注入 POI 上下文(由 PoiMarkerLayer provide) ────────────────────────────\r\nconst poi = inject<UsePoiMarkerReturn>(\"poiContext\");\r\nif (!poi) throw new Error(\"[PoiMarkerPanel] 必须与 PoiMarkerLayer 同级使用\");\r\n\r\n// ─── 面板状态 ─────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(true);\r\nconst toggleCollapse = () => {\r\n isCollapsed.value = !isCollapsed.value;\r\n};\r\n\r\n// ─── 拖拽移动 ─────────────────────────────────────────────────────────────────\r\nconst panelEl = ref<HTMLElement | null>(null);\r\nconst isDragging = ref(false);\r\n\r\n// 初始位置(可随需求调整)\r\nconst pos = reactive({ x: 10, y: 10 });\r\n\r\nlet dragStartX = 0;\r\nlet dragStartY = 0;\r\nlet origX = 0;\r\nlet origY = 0;\r\n\r\nfunction startDrag(e: MouseEvent) {\r\n isDragging.value = true;\r\n dragStartX = e.clientX;\r\n dragStartY = e.clientY;\r\n origX = pos.x;\r\n origY = pos.y;\r\n\r\n document.addEventListener(\"mousemove\", onDrag);\r\n document.addEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\nfunction onDrag(e: MouseEvent) {\r\n if (!isDragging.value) return;\r\n pos.x = origX + (e.clientX - dragStartX);\r\n pos.y = origY + (e.clientY - dragStartY);\r\n}\r\n\r\nfunction stopDrag() {\r\n isDragging.value = false;\r\n document.removeEventListener(\"mousemove\", onDrag);\r\n document.removeEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\n// ─── 分类筛选 ─────────────────────────────────────────────────────────────────\r\nconst categories = [\r\n { value: \"all\", label: \"全部\", icon: \"fa-list\", color: \"#aaa\" },\r\n { value: \"default\", label: \"普通\", icon: \"fa-map-marker\", color: \"#3ea6ff\" },\r\n {\r\n value: \"warning\",\r\n label: \"警告\",\r\n icon: \"fa-exclamation-triangle\",\r\n color: \"#ff6b6b\",\r\n },\r\n { value: \"info\", label: \"信息\", icon: \"fa-info-circle\", color: \"#52c41a\" },\r\n] as const;\r\n\r\nconst activeCategory = ref<string>(\"all\");\r\n\r\nconst filteredList = computed(() => {\r\n if (activeCategory.value === \"all\") return poi.poiList.value;\r\n return poi.poiList.value.filter((p) => p.category === activeCategory.value);\r\n});\r\n\r\nconst getCategoryColor = (cat: PoiItem[\"category\"]) => {\r\n const map: Record<string, string> = {\r\n default: \"#3ea6ff\",\r\n warning: \"#ff6b6b\",\r\n info: \"#52c41a\",\r\n };\r\n return map[cat] ?? \"#aaa\";\r\n};\r\n\r\n// ─── 添加模式 ─────────────────────────────────────────────────────────────────\r\nconst addCategory = ref<PoiItem[\"category\"]>(\"default\");\r\n\r\nfunction toggleAdd() {\r\n poi.toggleAddMode(\r\n undefined, // onAdded 回调(可按需传)\r\n \"标注点\",\r\n addCategory.value,\r\n );\r\n}\r\n\r\n// ─── 列表操作 ─────────────────────────────────────────────────────────────────\r\nfunction onSelect(id: string) {\r\n poi.selectPoi(id, true); // 选中并飞行\r\n}\r\n\r\nfunction onFlyTo(id: string) {\r\n poi.flyToPoi(id);\r\n}\r\n\r\nfunction onRemove(id: string) {\r\n poi.removePoi(id);\r\n}\r\n\r\n// ─── 编辑名称 ─────────────────────────────────────────────────────────────────\r\nconst editingId = ref<string | null>(null);\r\nconst editName = ref(\"\");\r\nconst editInputEl = ref<HTMLInputElement | null>(null);\r\n\r\nfunction startEdit(item: PoiItem) {\r\n editingId.value = item.id;\r\n editName.value = item.name;\r\n // DOM 更新后自动聚焦\r\n setTimeout(() => editInputEl.value?.select(), 30);\r\n}\r\n\r\nfunction saveEdit() {\r\n if (editingId.value && editName.value.trim()) {\r\n poi.updatePoiName(editingId.value, editName.value.trim());\r\n }\r\n cancelEdit();\r\n}\r\n\r\nfunction cancelEdit() {\r\n editingId.value = null;\r\n editName.value = \"\";\r\n}\r\n\r\nfunction confirmClear() {\r\n if (window.confirm(`确认清空全部 ${poi.poiList.value.length} 个标注?`)) {\r\n poi.clearAll();\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── 主面板 ────────────────────────────────────────────────────────────────────\r\n.poi-panel {\r\n position: absolute;\r\n width: 260px;\r\n height: auto;\r\n max-height: calc(100vh - 40px);\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px;\r\n z-index: 999;\r\n display: flex;\r\n flex-direction: column;\r\n backdrop-filter: blur(4px);\r\n transition: width 0.25s ease;\r\n\r\n // 收缩状态:只保留标题栏宽度,内容自适应高度\r\n &.collapsed {\r\n width: 46px;\r\n max-height: none;\r\n overflow: hidden;\r\n\r\n .poi-panel__title {\r\n display: none;\r\n }\r\n .poi-panel__body {\r\n display: none;\r\n }\r\n .collapse-icon {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n// ─── 标题栏 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__header {\r\n position: relative; // 为收缩态角标 absolute 定位提供参考\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 14px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 6px 0 0;\r\n cursor: grab;\r\n user-select: none;\r\n flex-shrink: 0;\r\n\r\n &.is-dragging {\r\n cursor: grabbing;\r\n }\r\n\r\n // 收缩后的图标态\r\n .collapsed-icon {\r\n display: none;\r\n color: #3ea6ff;\r\n font-size: 18px;\r\n }\r\n\r\n .poi-panel__title {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: #e8f4ff;\r\n font-size: 14px;\r\n font-weight: 600;\r\n\r\n .fa {\r\n color: #3ea6ff;\r\n font-size: 15px;\r\n }\r\n }\r\n\r\n .poi-count {\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 11px;\r\n padding: 1px 6px;\r\n border-radius: 10px;\r\n min-width: 18px;\r\n text-align: center;\r\n }\r\n\r\n .collapse-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n }\r\n}\r\n\r\n// 收缩态:图标自适应高度,角标定位在图标右上角\r\n.poi-panel.collapsed .poi-panel__header {\r\n flex-direction: column;\r\n align-items: flex-start; // 左对齐\r\n padding: 8px 10px 10px; // 底部留更多空间\r\n gap: 0;\r\n cursor: pointer;\r\n\r\n // 图标 + 角标一体化容器,图标在左下\r\n .collapsed-icon-wrap {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-top: 12px; // 往下一点\r\n margin-left: 2px;\r\n }\r\n\r\n .collapsed-icon {\r\n display: block;\r\n font-size: 20px;\r\n color: #3ea6ff;\r\n }\r\n\r\n // 角标:相对于图标容器定位,落在图标右上角\r\n .poi-count--collapsed {\r\n display: block;\r\n position: absolute;\r\n top: -10px;\r\n right: -12px;\r\n min-width: 16px;\r\n height: 16px;\r\n line-height: 16px;\r\n font-size: 10px;\r\n padding: 0 3px;\r\n background: #3ea6ff;\r\n color: #fff;\r\n border-radius: 8px;\r\n }\r\n}\r\n\r\n// ─── 面板体 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__body {\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n// ─── 操作栏 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__toolbar {\r\n display: flex;\r\n gap: 8px;\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .btn {\r\n flex: 1;\r\n padding: 6px 8px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.35);\r\n color: #fff;\r\n border-color: #3ea6ff;\r\n }\r\n &--danger {\r\n flex: 0 0 auto;\r\n border-color: rgba(255, 100, 100, 0.4);\r\n background: rgba(255, 100, 100, 0.1);\r\n color: #ffaaaa;\r\n &:hover:not(:disabled) {\r\n background: rgba(255, 100, 100, 0.25);\r\n color: #fff;\r\n }\r\n &:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 分类筛选 ──────────────────────────────────────────────────────────────────\r\n.poi-panel__filter {\r\n display: flex;\r\n gap: 6px;\r\n padding: 8px 12px;\r\n flex-wrap: wrap;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .filter-tag {\r\n padding: 3px 8px;\r\n border-radius: 12px;\r\n font-size: 11px;\r\n color: #7a9ec0;\r\n background: rgba(255, 255, 255, 0.06);\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n transition: all 0.2s ease;\r\n\r\n &:hover {\r\n background: rgba(255, 255, 255, 0.12);\r\n color: #c8dff0;\r\n }\r\n &.active {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #3ea6ff;\r\n }\r\n }\r\n}\r\n\r\n// ─── 列表 ──────────────────────────────────────────────────────────────────────\r\n.poi-panel__list {\r\n overflow-y: auto;\r\n max-height: calc(100vh - 220px);\r\n padding: 6px 0;\r\n\r\n &::-webkit-scrollbar {\r\n width: 4px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n\r\n.poi-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n transition: background 0.15s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.1);\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.18);\r\n }\r\n\r\n &__dot {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n flex-shrink: 0;\r\n }\r\n\r\n &__info {\r\n flex: 1;\r\n min-width: 0;\r\n &-name {\r\n overflow: hidden;\r\n }\r\n }\r\n\r\n &__name {\r\n font-size: 13px;\r\n color: #d8ecff;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n cursor: text;\r\n\r\n &:hover {\r\n color: #a0d4ff;\r\n }\r\n }\r\n\r\n &__name-input {\r\n width: 100%;\r\n font-size: 13px;\r\n color: #e8f4ff;\r\n background: rgba(62, 166, 255, 0.15);\r\n border: 1px solid rgba(62, 166, 255, 0.5);\r\n border-radius: 3px;\r\n padding: 1px 5px;\r\n outline: none;\r\n font-family: inherit;\r\n\r\n &:focus {\r\n border-color: #3ea6ff;\r\n background: rgba(62, 166, 255, 0.22);\r\n }\r\n }\r\n\r\n &__coord {\r\n font-size: 11px;\r\n color: #5a7a9a;\r\n margin-top: 2px;\r\n font-family: monospace;\r\n }\r\n\r\n &__actions {\r\n display: flex;\r\n gap: 4px;\r\n flex-shrink: 0;\r\n opacity: 0;\r\n transition: opacity 0.15s ease;\r\n }\r\n\r\n &:hover &__actions {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.icon-btn {\r\n width: 22px;\r\n height: 22px;\r\n border: none;\r\n background: rgba(255, 255, 255, 0.08);\r\n color: #9dc8f0;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 11px;\r\n transition: all 0.15s ease;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n &--danger:hover {\r\n background: rgba(255, 80, 80, 0.35);\r\n color: #fff;\r\n }\r\n}\r\n\r\n// ─── 空状态 ────────────────────────────────────────────────────────────────────\r\n.poi-panel__empty {\r\n text-align: center;\r\n padding: 30px 20px;\r\n color: #4a6a8a;\r\n\r\n .fa {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: block;\r\n }\r\n p {\r\n font-size: 12px;\r\n margin: 0;\r\n line-height: 1.6;\r\n }\r\n}\r\n\r\n// ─── 列表动画 ──────────────────────────────────────────────────────────────────\r\n.poi-list-enter-active,\r\n.poi-list-leave-active {\r\n transition: all 0.25s ease;\r\n}\r\n.poi-list-enter-from {\r\n opacity: 0;\r\n transform: translateX(-12px);\r\n}\r\n.poi-list-leave-to {\r\n opacity: 0;\r\n transform: translateX(12px);\r\n}\r\n</style>\r\n","/**\r\n * useTrack — 轨迹管理 composable\r\n *\r\n * 职责:\r\n * - 维护轨迹数据列表(历史轨迹 + 实时轨迹)\r\n * - 管理地图上的折线图形(PolylinePrimitive / CorridorPrimitive)\r\n * - 提供历史轨迹回放(播放 / 暂停 / 倍速 / 进度拖拽)\r\n * - 提供实时轨迹推送(持续追加坐标点)\r\n * - 数据与图形保持双向同步\r\n *\r\n * 使用方式(在 TrackLayer 内):\r\n * const mapCtx = inject<UseMapReturn>('mapContext')!\r\n * const track = useTrack(mapCtx)\r\n */\r\nimport { ref, shallowRef } from \"vue\";\r\nimport * as mars3d from \"mars3d\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\n\r\n// ─── 数据类型 ─────────────────────────────────────────────────────────────────\r\n\r\n/** 轨迹点 */\r\nexport interface TrackPoint {\r\n time: number; // Unix 时间戳(毫秒)\r\n lng: number;\r\n lat: number;\r\n alt: number;\r\n}\r\n\r\n/** 单条轨迹 */\r\nexport interface TrackItem {\r\n id: string;\r\n name: string;\r\n /** 轨迹点列表(按时间排序) */\r\n points: TrackPoint[];\r\n /** 轨迹线图形 */\r\n lineGraphic?: any;\r\n /** 实时模式下:当前\"已绘制\"到的点索引 */\r\n realtimeDrawnIdx?: number;\r\n /** 实时模式下:当前实时点图形 */\r\n realtimePoint?: any;\r\n /** 实时模式下:当前车头图标 */\r\n realtimeHeading?: any;\r\n /** 实时模式下:所有线段图形(用于删除时统一清理) */\r\n realtimeLineSegments?: any[];\r\n /** 回放开始时间戳 */\r\n _playStartTime?: number;\r\n}\r\n\r\nlet _idCounter = 1;\r\n\r\nexport function useTrack(mapCtx: UseMapReturn) {\r\n // ─── 图层 ─────────────────────────────────────────────────────────────────\r\n const trackLayer = shallowRef<mars3d.layer.GraphicLayer | null>(null);\r\n\r\n // ─── 轨迹列表 ─────────────────────────────────────────────────────────────\r\n const trackList = ref<TrackItem[]>([]);\r\n\r\n // ─── 当前选中 / 回放的轨迹 ────────────────────────────────────────────────\r\n const activeTrackId = ref<string | null>(null);\r\n\r\n // ─── 回放状态 ─────────────────────────────────────────────────────────────\r\n const isPlaying = ref(false);\r\n const currentTime = ref(0); // 当前回放时间戳\r\n const playbackSpeed = ref(1); // 倍速(1x / 2x / 4x / 8x)\r\n const playbackProgress = ref(0); // 0~100 百分比\r\n\r\n // ─── 实时模式标记 ──────────────────────────────────────────────────────────\r\n const isRealtimeMode = ref(false);\r\n const activeRealtimeId = ref<string | null>(null);\r\n\r\n // ─── 回放定时器 ───────────────────────────────────────────────────────────\r\n let _playInterval: ReturnType<typeof setInterval> | null = null;\r\n let _realtimeInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n // ─── 初始化图层 ────────────────────────────────────────────────────────────\r\n function initTrackLayer() {\r\n const map = mapCtx.map.value;\r\n if (!map) return;\r\n\r\n const layer = new mars3d.layer.GraphicLayer();\r\n map.addLayer(layer);\r\n trackLayer.value = layer;\r\n }\r\n\r\n // ─── 内部:绘制完整折线 ────────────────────────────────────────────────────\r\n function _buildLineGraphic(track: TrackItem) {\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n // 只画已有坐标\r\n const positions = track.points.map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n const line = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#3ea6ff\") as any,\r\n width: 3,\r\n opacity: 0.9,\r\n clampToGround: false,\r\n },\r\n attr: { trackId: track.id },\r\n });\r\n\r\n layer.addGraphic(line);\r\n return line;\r\n }\r\n\r\n // ─── 内部:实时追加一段线 ──────────────────────────────────────────────────\r\n function _appendRealtimeLine(track: TrackItem, fromIdx: number, toIdx: number) {\r\n const layer = trackLayer.value;\r\n if (!layer || toIdx <= fromIdx) return;\r\n\r\n const positions = track.points.slice(fromIdx, toIdx + 1)\r\n .map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n const segment = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#ff6b35\") as any,\r\n width: 4,\r\n opacity: 1,\r\n clampToGround: false,\r\n },\r\n });\r\n layer.addGraphic(segment);\r\n // 记录线段引用,用于删除时统一清理\r\n if (!track.realtimeLineSegments) {\r\n track.realtimeLineSegments = [];\r\n }\r\n track.realtimeLineSegments.push(segment);\r\n }\r\n\r\n // ─── 内部:更新实时点位图标 ─────────────────────────────────────────────────\r\n function _updateRealtimeMarker(track: TrackItem) {\r\n const layer = trackLayer.value;\r\n if (!layer) return;\r\n\r\n const lastPoint = track.points[track.realtimeDrawnIdx!];\r\n if (!lastPoint) return;\r\n\r\n // 更新图标位置\r\n if (track.realtimePoint) {\r\n track.realtimePoint.position = [lastPoint.lng, lastPoint.lat, lastPoint.alt];\r\n } else {\r\n const marker = new mars3d.graphic.BillboardEntity({\r\n position: [lastPoint.lng, lastPoint.lat, lastPoint.alt],\r\n style: {\r\n image: \"//data.mars3d.cn/img/marker/mark-blue.png\",\r\n scale: 1.2,\r\n horizontalOrigin: mars3d.Cesium.HorizontalOrigin.CENTER,\r\n verticalOrigin: mars3d.Cesium.VerticalOrigin.BOTTOM,\r\n },\r\n });\r\n layer.addGraphic(marker);\r\n track.realtimePoint = marker;\r\n }\r\n }\r\n\r\n // ─── 添加历史轨迹(从预置数据回放) ─────────────────────────────────────────\r\n function addTrack(points: TrackPoint[], name = \"轨迹\") {\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `track-${_idCounter++}`;\r\n const track: TrackItem = { id, name, points };\r\n track.lineGraphic = _buildLineGraphic(track);\r\n trackList.value.push(track);\r\n return track;\r\n }\r\n\r\n // ─── 开始实时轨迹推送 ──────────────────────────────────────────────────────\r\n function startRealtime(name = \"实时轨迹\") {\r\n if (activeRealtimeId.value) stopRealtime();\r\n\r\n const layer = trackLayer.value;\r\n if (!layer) return null;\r\n\r\n const id = `realtime-${_idCounter++}`;\r\n const track: TrackItem = {\r\n id,\r\n name,\r\n points: [],\r\n realtimeDrawnIdx: -1,\r\n };\r\n trackLayer.value = layer;\r\n trackList.value.push(track);\r\n activeRealtimeId.value = id;\r\n isRealtimeMode.value = true;\r\n return track;\r\n }\r\n\r\n // ─── 推送实时坐标点 ───────────────────────────────────────────────────────\r\n function pushRealtimePoint(id: string, lng: number, lat: number, alt = 0) {\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track) return;\r\n\r\n const point: TrackPoint = {\r\n time: Date.now(),\r\n lng,\r\n lat,\r\n alt,\r\n };\r\n track.points.push(point);\r\n track.realtimeDrawnIdx = track.points.length - 1;\r\n\r\n // 首次:直接建线和图标\r\n if (track.points.length === 1) {\r\n track.lineGraphic = _buildLineGraphic(track);\r\n _updateRealtimeMarker(track);\r\n } else {\r\n // 追加一段折线\r\n _appendRealtimeLine(track, track.points.length - 2, track.points.length - 1);\r\n _updateRealtimeMarker(track);\r\n }\r\n\r\n // 自动飞行跟随(最后一点)\r\n if (mapCtx.map.value) {\r\n mapCtx.map.value.flyToPoint(\r\n [lng, lat, alt + 50],\r\n { radius: 500, duration: 0.5 },\r\n );\r\n }\r\n }\r\n\r\n // ─── 停止实时推送(固化轨迹) ──────────────────────────────────────────────\r\n function stopRealtime(id?: string) {\r\n const targetId = id ?? activeRealtimeId.value;\r\n if (!targetId) return;\r\n\r\n const track = trackList.value.find((t) => t.id === targetId);\r\n if (track) {\r\n track.realtimeDrawnIdx = undefined;\r\n if (track.realtimePoint) {\r\n trackLayer.value?.removeGraphic(track.realtimePoint);\r\n track.realtimePoint = undefined;\r\n }\r\n }\r\n\r\n if (activeRealtimeId.value === targetId) {\r\n activeRealtimeId.value = null;\r\n isRealtimeMode.value = false;\r\n }\r\n }\r\n\r\n // ─── 历史轨迹回放 ─────────────────────────────────────────────────────────\r\n function play(trackId?: string) {\r\n const id = trackId ?? activeTrackId.value;\r\n if (!id) return;\r\n\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track || track.points.length < 2) return;\r\n\r\n if (activeTrackId.value !== id) {\r\n selectTrack(id);\r\n }\r\n\r\n isPlaying.value = true;\r\n _clearPlayInterval();\r\n\r\n const start = track.points[0].time;\r\n const end = track.points[track.points.length - 1].time;\r\n const totalMs = end - start;\r\n\r\n // 进度每帧更新\r\n _playInterval = setInterval(() => {\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (!track || !isPlaying.value) return;\r\n\r\n const elapsed = Date.now() - (track._playStartTime ?? Date.now());\r\n const total = end - start;\r\n const progress = Math.min(elapsed / total, 1);\r\n\r\n // 更新当前时间 → 驱动进度条\r\n currentTime.value = start + progress * total;\r\n playbackProgress.value = progress * 100;\r\n\r\n // 逐步绘制轨迹\r\n const targetIdx = Math.floor(progress * (track.points.length - 1));\r\n _updatePlaybackLine(track, targetIdx);\r\n }, 60);\r\n }\r\n\r\n function _updatePlaybackLine(track: TrackItem, toIdx: number) {\r\n const layer = trackLayer.value;\r\n if (!layer) return;\r\n\r\n // 清除旧线\r\n if (track.lineGraphic) {\r\n layer.removeGraphic(track.lineGraphic);\r\n }\r\n\r\n // 画到 toIdx 位置\r\n const positions = track.points.slice(0, toIdx + 1)\r\n .map((p) => [p.lng, p.lat, p.alt] as [number, number, number]);\r\n\r\n track.lineGraphic = new mars3d.graphic.PolylinePrimitive({\r\n positions,\r\n style: {\r\n color: mars3d.Cesium.Color.fromCssColorString(\"#00ff88\") as any,\r\n width: 4,\r\n opacity: 1,\r\n clampToGround: false,\r\n },\r\n });\r\n layer.addGraphic(track.lineGraphic);\r\n\r\n // 画当前点位\r\n const pt = track.points[toIdx];\r\n mapCtx.map.value?.flyToPoint(\r\n [pt.lng, pt.lat, pt.alt + 200],\r\n { radius: 300, duration: 0 },\r\n );\r\n }\r\n\r\n function pause() {\r\n isPlaying.value = false;\r\n _clearPlayInterval();\r\n }\r\n\r\n function stop() {\r\n isPlaying.value = false;\r\n playbackProgress.value = 0;\r\n currentTime.value = 0;\r\n _clearPlayInterval();\r\n\r\n // 恢复整条轨迹\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (track && trackLayer.value) {\r\n if (track.lineGraphic) trackLayer.value.removeGraphic(track.lineGraphic);\r\n track.lineGraphic = _buildLineGraphic(track);\r\n }\r\n }\r\n\r\n function setSpeed(speed: number) {\r\n playbackSpeed.value = speed;\r\n if (isPlaying.value) {\r\n pause();\r\n play();\r\n }\r\n }\r\n\r\n /** 跳转到指定进度(0~100) */\r\n function seek(progress: number) {\r\n const track = trackList.value.find((t) => t.id === activeTrackId.value);\r\n if (!track) return;\r\n\r\n const targetIdx = Math.floor((progress / 100) * (track.points.length - 1));\r\n currentTime.value = track.points[targetIdx].time;\r\n playbackProgress.value = progress;\r\n _updatePlaybackLine(track, targetIdx);\r\n }\r\n\r\n // ─── 选中轨迹 ─────────────────────────────────────────────────────────────\r\n function selectTrack(id: string) {\r\n activeTrackId.value = id;\r\n stop();\r\n }\r\n\r\n /** 飞行到轨迹概览 */\r\n function flyToTrack(id: string) {\r\n const track = trackList.value.find((t) => t.id === id);\r\n if (!track || !mapCtx.map.value) return;\r\n\r\n const first = track.points[0];\r\n mapCtx.map.value.flyToPoint(\r\n [first.lng, first.lat, first.alt + 2000],\r\n { radius: 3000, duration: 1.5 },\r\n );\r\n }\r\n\r\n // ─── 删除 / 清空 ───────────────────────────────────────────────────────────\r\n function removeTrack(id: string) {\r\n const idx = trackList.value.findIndex((t) => t.id === id);\r\n if (idx === -1) return;\r\n\r\n const track = trackList.value[idx];\r\n if (track.lineGraphic) trackLayer.value?.removeGraphic(track.lineGraphic);\r\n if (track.realtimePoint) trackLayer.value?.removeGraphic(track.realtimePoint);\r\n // 删除实时轨迹的所有线段\r\n if (track.realtimeLineSegments) {\r\n track.realtimeLineSegments.forEach((seg) => {\r\n trackLayer.value?.removeGraphic(seg);\r\n });\r\n }\r\n trackList.value.splice(idx, 1);\r\n\r\n if (activeTrackId.value === id) {\r\n activeTrackId.value = null;\r\n stop();\r\n }\r\n if (activeRealtimeId.value === id) {\r\n activeRealtimeId.value = null;\r\n isRealtimeMode.value = false;\r\n }\r\n }\r\n\r\n function clearAll() {\r\n stop();\r\n stopRealtime();\r\n trackLayer.value?.clear();\r\n trackList.value = [];\r\n activeTrackId.value = null;\r\n }\r\n\r\n // ─── 内部工具 ─────────────────────────────────────────────────────────────\r\n function _clearPlayInterval() {\r\n if (_playInterval) {\r\n clearInterval(_playInterval);\r\n _playInterval = null;\r\n }\r\n }\r\n\r\n return {\r\n trackLayer,\r\n trackList,\r\n activeTrackId,\r\n isPlaying,\r\n currentTime,\r\n playbackSpeed,\r\n playbackProgress,\r\n isRealtimeMode,\r\n activeRealtimeId,\r\n initTrackLayer,\r\n addTrack,\r\n startRealtime,\r\n pushRealtimePoint,\r\n stopRealtime,\r\n play,\r\n pause,\r\n stop,\r\n setSpeed,\r\n seek,\r\n selectTrack,\r\n flyToTrack,\r\n removeTrack,\r\n clearAll,\r\n };\r\n}\r\n\r\nexport type UseTrackReturn = ReturnType<typeof useTrack>;\r\n","<!--\r\n TrackLayer — 轨迹组件逻辑层\r\n\r\n 职责:\r\n - 放置在 MarsMapContainer 的 slot 内(通过 <slot /> 渲染子组件)\r\n - inject mapContext,初始化轨迹图层\r\n - provide trackContext,供子组件 inject 使用\r\n - expose useTrack 全量接口,供父组件 ref 访问\r\n\r\n 使用方式(Panel 必须作为子内容传入):\r\n <MarsMapContainer>\r\n <TrackLayer ref=\"trackLayerRef\">\r\n <TrackPanel />\r\n </TrackLayer>\r\n </MarsMapContainer>\r\n-->\r\n<template>\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { inject, provide, watch, onUnmounted } from \"vue\";\r\nimport type { UseMapReturn } from \"../../mars-map/composables/useMap\";\r\nimport { useTrack } from \"./useTrack\";\r\n\r\n// ─── 注入地图上下文 ──────────────────────────────────────────────────────────\r\nconst mapCtx = inject<UseMapReturn>(\"mapContext\");\r\nif (!mapCtx) throw new Error(\"[TrackLayer] 必须放置在 MarsMapContainer 内部\");\r\n\r\n// ─── 初始化轨迹管理 ──────────────────────────────────────────────────────────\r\nconst track = useTrack(mapCtx);\r\n\r\n// ─── 等待地图就绪后初始化图层 ───────────────────────────────────────────────\r\nconst stopWatch = watch(\r\n () => mapCtx.map.value,\r\n (map) => {\r\n if (map) {\r\n track.initTrackLayer();\r\n stopWatch();\r\n }\r\n },\r\n { immediate: true },\r\n);\r\n\r\nonUnmounted(() => {\r\n track.clearAll();\r\n});\r\n\r\n// ─── provide 给子组件 ───────────────────────────────────────────────────────\r\nprovide(\"trackContext\", track);\r\n\r\n// ─── expose 给父组件 ref ───────────────────────────────────────────────────\r\ndefineExpose(track);\r\n</script>\r\n","<!--\r\n TrackPanel — 轨迹管理面板\r\n\r\n 功能:\r\n - 轨迹列表管理(添加历史轨迹 / 实时轨迹)\r\n - 历史轨迹回放控制(播放 / 暂停 / 停止 / 倍速 / 进度拖拽)\r\n - 实时轨迹推送(开始 / 追加模拟点 / 停止)\r\n - 拖拽移动 + 收缩图标态\r\n\r\n 数据来源:inject('trackContext'),由 TrackLayer provide\r\n-->\r\n<template>\r\n <div\r\n class=\"track-panel\"\r\n :class=\"{ collapsed: isCollapsed }\"\r\n :style=\"{ left: pos.x + 'px', top: pos.y + 'px' }\"\r\n >\r\n <!-- 标题栏(可拖拽) -->\r\n <div\r\n class=\"track-panel__header\"\r\n :class=\"{ 'is-dragging': isDragging }\"\r\n @mousedown.prevent=\"startDrag\"\r\n @click=\"isDragging ? null : toggleCollapse()\"\r\n >\r\n <template v-if=\"isCollapsed\">\r\n <div class=\"collapsed-icon-wrap\">\r\n <i class=\"fa fa-share-alt collapsed-icon\" />\r\n <span class=\"track-badge\">{{ track.trackList.value.length }}</span>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <span class=\"track-panel__title\">\r\n <i class=\"fa fa-share-alt\" />\r\n 轨迹管理\r\n <span class=\"track-count\">{{ track.trackList.value.length }}</span>\r\n </span>\r\n <i class=\"fa fa-chevron-left collapse-icon\" />\r\n </template>\r\n </div>\r\n\r\n <!-- 面板体 -->\r\n <div class=\"track-panel__body\" v-show=\"!isCollapsed\">\r\n <!-- ── 操作栏 ── -->\r\n <div class=\"track-panel__toolbar\">\r\n <button class=\"btn btn--primary\" @click=\"addDemoTrack\">\r\n <i class=\"fa fa-plus\" /> 历史轨迹\r\n </button>\r\n <button\r\n class=\"btn\"\r\n :class=\"track.isRealtimeMode.value ? 'btn--active' : 'btn--info'\"\r\n @click=\"toggleRealtime\"\r\n >\r\n <i\r\n :class=\"['fa', track.isRealtimeMode.value ? 'fa-stop' : 'fa-bolt']\"\r\n />\r\n {{ track.isRealtimeMode.value ? \"停止推送\" : \"实时轨迹\" }}\r\n </button>\r\n <button\r\n class=\"btn btn--danger\"\r\n @click=\"confirmClear\"\r\n :disabled=\"track.trackList.value.length === 0\"\r\n >\r\n <i class=\"fa fa-trash-o\" />\r\n </button>\r\n </div>\r\n\r\n <!-- ── 回放控制(选中轨迹时显示) ── -->\r\n <div class=\"track-panel__playback\" v-if=\"track.activeTrackId.value\">\r\n <!-- 轨迹名称 -->\r\n <div class=\"playback__track-name\">\r\n <i class=\"fa fa-road\" />\r\n {{ activeTrackName }}\r\n <span class=\"playback__mode-badge\">历史回放</span>\r\n </div>\r\n\r\n <!-- 播放按钮组 -->\r\n <div class=\"playback__controls\">\r\n <button class=\"ctrl-btn\" @click=\"track.stop()\">\r\n <i class=\"fa fa-stop\" />\r\n </button>\r\n <button\r\n class=\"ctrl-btn ctrl-btn--play\"\r\n @click=\"track.isPlaying.value ? track.pause() : track.play()\"\r\n >\r\n <i\r\n :class=\"['fa', track.isPlaying.value ? 'fa-pause' : 'fa-play']\"\r\n />\r\n </button>\r\n <button class=\"ctrl-btn\" @click=\"track.play()\">\r\n <i class=\"fa fa-refresh\" />\r\n </button>\r\n </div>\r\n\r\n <!-- 倍速选择 -->\r\n <div class=\"playback__speed\">\r\n <span class=\"speed-label\">倍速</span>\r\n <div class=\"speed-btns\">\r\n <button\r\n v-for=\"s in speedOptions\"\r\n :key=\"s\"\r\n class=\"speed-btn\"\r\n :class=\"{ active: track.playbackSpeed.value === s }\"\r\n @click=\"track.setSpeed(s)\"\r\n >\r\n {{ s }}x\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- 进度条 -->\r\n <div class=\"playback__timeline\">\r\n <span class=\"time-label\">{{\r\n formatTime(track.currentTime.value)\r\n }}</span>\r\n <input\r\n type=\"range\"\r\n class=\"progress-slider\"\r\n min=\"0\"\r\n max=\"100\"\r\n step=\"0.1\"\r\n :value=\"track.playbackProgress.value\"\r\n @input=\"onSeek\"\r\n />\r\n <span class=\"time-label\">{{ formatTime(trackMaxTime) }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- ── 实时模式指示 ── -->\r\n <div\r\n class=\"track-panel__realtime-hint\"\r\n v-if=\"track.isRealtimeMode.value && !track.activeTrackId.value\"\r\n >\r\n <div class=\"realtime-pulse\">\r\n <i class=\"fa fa-bolt\" />\r\n 实时推送中\r\n <span class=\"blink-dot\" />\r\n </div>\r\n <div class=\"realtime-count\">\r\n 已推送 <strong>{{ realtimePointCount }}</strong> 个坐标点\r\n </div>\r\n </div>\r\n\r\n <!-- ── 轨迹列表 ── -->\r\n <div class=\"track-panel__list\">\r\n <TransitionGroup name=\"track-list\">\r\n <div\r\n v-for=\"item in track.trackList.value\"\r\n :key=\"item.id\"\r\n class=\"track-item\"\r\n :class=\"{\r\n 'track-item--active': track.activeTrackId.value === item.id,\r\n 'track-item--realtime': item.id.startsWith('realtime'),\r\n }\"\r\n @click=\"onSelectTrack(item.id)\"\r\n >\r\n <!-- 颜色条 -->\r\n <span\r\n class=\"track-item__bar\"\r\n :style=\"{\r\n background: item.id.startsWith('realtime')\r\n ? '#ff6b35'\r\n : '#3ea6ff',\r\n }\"\r\n />\r\n\r\n <div class=\"track-item__info\">\r\n <div class=\"track-item__name\">\r\n <i\r\n :class=\"[\r\n 'fa',\r\n item.id.startsWith('realtime') ? 'fa-bolt' : 'fa-road',\r\n ]\"\r\n />\r\n {{ item.name }}\r\n </div>\r\n <div class=\"track-item__meta\">\r\n {{ item.points.length }} 个点\r\n <span v-if=\"item.id.startsWith('realtime')\" class=\"realtime-tag\"\r\n >实时</span\r\n >\r\n </div>\r\n </div>\r\n\r\n <div class=\"track-item__actions\">\r\n <button\r\n class=\"icon-btn\"\r\n title=\"飞行\"\r\n @click.stop=\"track.flyToTrack(item.id)\"\r\n >\r\n <i class=\"fa fa-crosshairs\" />\r\n </button>\r\n <button\r\n class=\"icon-btn icon-btn--danger\"\r\n title=\"删除\"\r\n @click.stop=\"track.removeTrack(item.id)\"\r\n >\r\n <i class=\"fa fa-times\" />\r\n </button>\r\n </div>\r\n </div>\r\n </TransitionGroup>\r\n\r\n <!-- 空状态 -->\r\n <div\r\n v-if=\"track.trackList.value.length === 0\"\r\n class=\"track-panel__empty\"\r\n >\r\n <i class=\"fa fa-map-o\" />\r\n <p>暂无轨迹数据</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, inject, reactive } from \"vue\";\r\nimport type { UseTrackReturn } from \"./useTrack\";\r\n\r\n// ─── 注入轨迹上下文 ──────────────────────────────────────────────────────────\r\nconst track = inject<UseTrackReturn>(\"trackContext\");\r\nif (!track) throw new Error(\"[TrackPanel] 必须与 TrackLayer 同级使用\");\r\n\r\n// ─── 拖拽 ──────────────────────────────────────────────────────────────────\r\nconst isCollapsed = ref(true);\r\nconst isDragging = ref(false);\r\nconst pos = reactive({ x: 10, y: 80 }); // 默认错开 POI 面板\r\n\r\nlet dragStartX = 0,\r\n dragStartY = 0,\r\n origX = 0,\r\n origY = 0;\r\n\r\nfunction toggleCollapse() {\r\n isCollapsed.value = !isCollapsed.value;\r\n}\r\n\r\nfunction startDrag(e: MouseEvent) {\r\n isDragging.value = true;\r\n dragStartX = e.clientX;\r\n dragStartY = e.clientY;\r\n origX = pos.x;\r\n origY = pos.y;\r\n document.addEventListener(\"mousemove\", onDrag);\r\n document.addEventListener(\"mouseup\", stopDrag);\r\n}\r\nfunction onDrag(e: MouseEvent) {\r\n if (!isDragging.value) return;\r\n pos.x = origX + (e.clientX - dragStartX);\r\n pos.y = origY + (e.clientY - dragStartY);\r\n}\r\nfunction stopDrag() {\r\n isDragging.value = false;\r\n document.removeEventListener(\"mousemove\", onDrag);\r\n document.removeEventListener(\"mouseup\", stopDrag);\r\n}\r\n\r\n// ─── 选中轨迹 ──────────────────────────────────────────────────────────────\r\nfunction onSelectTrack(id: string) {\r\n if (track.activeTrackId.value === id) return;\r\n track.selectTrack(id);\r\n track.stop();\r\n}\r\n\r\nconst activeTrackName = computed(() => {\r\n const t = track.trackList.value.find(\r\n (x) => x.id === track.activeTrackId.value,\r\n );\r\n return t?.name ?? \"\";\r\n});\r\n\r\nconst trackMaxTime = computed(() => {\r\n const t = track.trackList.value.find(\r\n (x) => x.id === track.activeTrackId.value,\r\n );\r\n if (!t || t.points.length < 2) return 0;\r\n return t.points[t.points.length - 1].time;\r\n});\r\n\r\n// ─── 倍速选项 ──────────────────────────────────────────────────────────────\r\nconst speedOptions = [1, 2, 4, 8];\r\n\r\n// ─── 进度拖拽 ─────────────────────────────────────────────────────────────\r\nfunction onSeek(e: Event) {\r\n const val = parseFloat((e.target as HTMLInputElement).value);\r\n track.seek(val);\r\n}\r\n\r\n// ─── 时间格式化 ────────────────────────────────────────────────────────────\r\nfunction formatTime(ts: number): string {\r\n if (!ts) return \"00:00\";\r\n const d = new Date(ts);\r\n return `${String(d.getMinutes()).padStart(2, \"0\")}:${String(d.getSeconds()).padStart(2, \"0\")}`;\r\n}\r\n\r\n// ─── 添加演示历史轨迹 ─────────────────────────────────────────────────────\r\nfunction addDemoTrack() {\r\n // 生成一段北京区域贴近实际的路径:方向惯性 + 高度随路线起伏\r\n const baseLng = 116.3974;\r\n const baseLat = 39.909;\r\n const points = [];\r\n let t = Date.now();\r\n\r\n // 初始方向角(弧度)\r\n let heading = Math.random() * Math.PI * 2;\r\n const STEP = 20; // 减少到 20 个点\r\n\r\n for (let i = 0; i < STEP; i++) {\r\n t += 5000 + Math.random() * 5000;\r\n // 方向每步微调 ±15°,模拟沿道路行驶\r\n heading += (Math.random() - 0.5) * (Math.PI / 6);\r\n const stepLng = baseLng + Math.cos(heading) * 0.004;\r\n const stepLat = baseLat + Math.sin(heading) * 0.002;\r\n const alt = 30 + Math.sin((i / STEP) * Math.PI) * 80; // 拱形起伏\r\n points.push({ time: t, lng: stepLng, lat: stepLat, alt });\r\n }\r\n\r\n track.addTrack(points, `轨迹 ${_counter++}`);\r\n}\r\n\r\nlet _counter = 1;\r\n\r\n// ─── 实时轨迹 ─────────────────────────────────────────────────────────────\r\nlet _realtimeTimer: ReturnType<typeof setInterval> | null = null;\r\nlet _currentRealtimeId: string | null = null;\r\n\r\nfunction toggleRealtime() {\r\n if (track.isRealtimeMode.value) {\r\n stopRealtime();\r\n } else {\r\n startRealtime();\r\n }\r\n}\r\n\r\nfunction startRealtime() {\r\n const id = track.startRealtime(`实时轨迹 ${_counter++}`)?.id;\r\n if (!id) return;\r\n _currentRealtimeId = id;\r\n\r\n // 天安门坐标(圆心)\r\n const CENTER_LNG = 116.397;\r\n const CENTER_LAT = 39.908;\r\n // 绕圈半径(约 400 米)\r\n const RADIUS_LNG = 0.004;\r\n const RADIUS_LAT = 0.003;\r\n // 总共 36 个点,每 10° 一个点,完成一圈\r\n const TOTAL_POINTS = 36;\r\n const ANGLE_STEP = (2 * Math.PI) / TOTAL_POINTS;\r\n // 初始角度随机,让起点不在固定位置\r\n let angle = Math.random() * 2 * Math.PI;\r\n let pushCount = 0;\r\n\r\n _realtimeTimer = setInterval(() => {\r\n pushCount++;\r\n // 沿圆形轨迹移动\r\n const lng = CENTER_LNG + Math.cos(angle) * RADIUS_LNG;\r\n const lat = CENTER_LAT + Math.sin(angle) * RADIUS_LAT;\r\n const alt = 40 + Math.sin(angle * 3) * 20; // 高度随位置微微起伏\r\n track.pushRealtimePoint(id, lng, lat, alt);\r\n\r\n // 角度递增,绘制下一位置\r\n angle += ANGLE_STEP;\r\n\r\n // 完成一圈后自动停止\r\n if (pushCount >= TOTAL_POINTS) {\r\n stopRealtime();\r\n }\r\n }, 800);\r\n}\r\n\r\nfunction stopRealtime() {\r\n if (_realtimeTimer) {\r\n clearInterval(_realtimeTimer);\r\n _realtimeTimer = null;\r\n }\r\n if (_currentRealtimeId) {\r\n track.stopRealtime(_currentRealtimeId);\r\n _currentRealtimeId = null;\r\n }\r\n}\r\n\r\nconst realtimePointCount = computed(() => {\r\n const t = track.trackList.value.find((x) => x.id === _currentRealtimeId);\r\n return t?.points.length ?? 0;\r\n});\r\n\r\n// ─── 清空 ─────────────────────────────────────────────────────────────────\r\nfunction confirmClear() {\r\n if (window.confirm(`确认清空全部 ${track.trackList.value.length} 条轨迹?`)) {\r\n stopRealtime();\r\n track.clearAll();\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"less\" scoped>\r\n// ─── 主面板 ─────────────────────────────────────────────────────────────────\r\n.track-panel {\r\n position: absolute;\r\n width: 280px;\r\n height: auto;\r\n max-height: calc(100vh - 40px);\r\n background: rgba(23, 35, 50, 0.92);\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n border-radius: 6px;\r\n z-index: 998;\r\n display: flex;\r\n flex-direction: column;\r\n backdrop-filter: blur(4px);\r\n transition: width 0.25s ease;\r\n\r\n &.collapsed {\r\n width: 46px;\r\n max-height: none;\r\n overflow: hidden;\r\n\r\n .track-panel__title {\r\n display: none;\r\n }\r\n .track-panel__body {\r\n display: none;\r\n }\r\n .collapse-icon {\r\n display: none;\r\n }\r\n }\r\n}\r\n\r\n// ─── 标题栏 ────────────────────────────────────────────────────────────────\r\n.track-panel__header {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 14px;\r\n background: rgba(15, 25, 40, 0.9);\r\n border-radius: 6px 6px 0 0;\r\n cursor: grab;\r\n user-select: none;\r\n flex-shrink: 0;\r\n\r\n &.is-dragging {\r\n cursor: grabbing;\r\n }\r\n\r\n .collapsed-icon {\r\n display: none;\r\n color: #ff6b35;\r\n font-size: 18px;\r\n }\r\n\r\n .track-panel__title {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n color: #e8f4ff;\r\n font-size: 14px;\r\n font-weight: 600;\r\n .fa {\r\n color: #ff6b35;\r\n font-size: 15px;\r\n }\r\n }\r\n\r\n // 展开态角标(红色)\r\n .track-count {\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 11px;\r\n padding: 1px 6px;\r\n border-radius: 10px;\r\n min-width: 18px;\r\n text-align: center;\r\n }\r\n\r\n .collapse-icon {\r\n color: #7a9ec0;\r\n font-size: 12px;\r\n }\r\n}\r\n\r\n// 收缩态\r\n.track-panel.collapsed .track-panel__header {\r\n flex-direction: column;\r\n align-items: flex-start; // 左对齐\r\n padding: 8px 10px 10px; // 底部留更多空间\r\n gap: 0;\r\n cursor: pointer;\r\n\r\n // 图标 + 角标一体化容器,图标在左下,角标叠在图标右上\r\n .collapsed-icon-wrap {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-top: 12px; // 往下一点\r\n margin-left: 2px; // 往左一点\r\n }\r\n\r\n .collapsed-icon {\r\n display: block;\r\n color: #ff6b35;\r\n font-size: 18px;\r\n }\r\n\r\n // 角标:相对于图标容器定位,落在图标右上角\r\n .track-badge {\r\n position: absolute;\r\n top: -12px;\r\n right: -12px;\r\n background: #e74c3c;\r\n color: #fff;\r\n font-size: 10px;\r\n font-weight: 600;\r\n min-width: 16px;\r\n height: 16px;\r\n line-height: 16px;\r\n text-align: center;\r\n border-radius: 8px;\r\n padding: 0 3px;\r\n }\r\n}\r\n\r\n// ─── 面板体 ────────────────────────────────────────────────────────────────\r\n.track-panel__body {\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n// ─── 操作栏 ───────────────────────────────────────────────────────────────\r\n.track-panel__toolbar {\r\n display: flex;\r\n gap: 6px;\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .btn {\r\n flex: 1;\r\n padding: 5px 8px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.25);\r\n color: #fff;\r\n }\r\n &--active {\r\n background: rgba(255, 100, 50, 0.35);\r\n color: #ffaa88;\r\n border-color: #ff6b35;\r\n }\r\n &--primary {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #fff;\r\n border-color: rgba(62, 166, 255, 0.6);\r\n }\r\n &--info {\r\n background: rgba(255, 107, 53, 0.2);\r\n color: #ffaa88;\r\n border-color: rgba(255, 107, 53, 0.5);\r\n }\r\n &--danger {\r\n flex: 0 0 auto;\r\n width: 36px;\r\n border-color: rgba(255, 80, 80, 0.4);\r\n background: rgba(255, 80, 80, 0.1);\r\n color: #ffaaaa;\r\n &:hover:not(:disabled) {\r\n background: rgba(255, 80, 80, 0.25);\r\n color: #fff;\r\n }\r\n &:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 回放控制 ─────────────────────────────────────────────────────────────\r\n.track-panel__playback {\r\n padding: 10px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n\r\n .playback__track-name {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 12px;\r\n color: #9dc8f0;\r\n margin-bottom: 8px;\r\n\r\n .fa {\r\n color: #00ff88;\r\n }\r\n .playback__mode-badge {\r\n background: rgba(0, 255, 136, 0.15);\r\n color: #00ff88;\r\n font-size: 10px;\r\n padding: 1px 6px;\r\n border-radius: 8px;\r\n margin-left: 4px;\r\n }\r\n }\r\n\r\n // 播放按钮组\r\n .playback__controls {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n margin-bottom: 8px;\r\n }\r\n\r\n // 单独控制按钮\r\n .ctrl-btn {\r\n width: 30px;\r\n height: 30px;\r\n border: 1px solid rgba(62, 166, 255, 0.4);\r\n background: rgba(62, 166, 255, 0.1);\r\n color: #9dc8f0;\r\n border-radius: 50%;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 12px;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n\r\n &--play {\r\n width: 38px;\r\n height: 38px;\r\n background: rgba(0, 200, 100, 0.2);\r\n border-color: rgba(0, 200, 100, 0.6);\r\n color: #00ff88;\r\n font-size: 15px;\r\n &:hover {\r\n background: rgba(0, 200, 100, 0.35);\r\n }\r\n }\r\n }\r\n\r\n // 倍速\r\n .playback__speed {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n margin-bottom: 8px;\r\n\r\n .speed-label {\r\n font-size: 11px;\r\n color: #5a7a9a;\r\n }\r\n .speed-btns {\r\n display: flex;\r\n gap: 4px;\r\n }\r\n .speed-btn {\r\n padding: 2px 7px;\r\n border: 1px solid rgba(62, 166, 255, 0.3);\r\n background: rgba(255, 255, 255, 0.04);\r\n color: #7a9ec0;\r\n border-radius: 10px;\r\n font-size: 11px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.2);\r\n color: #fff;\r\n }\r\n &.active {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #3ea6ff;\r\n border-color: #3ea6ff;\r\n }\r\n }\r\n }\r\n\r\n // 进度条\r\n .playback__timeline {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n\r\n .time-label {\r\n font-size: 10px;\r\n color: #5a7a9a;\r\n font-family: monospace;\r\n min-width: 36px;\r\n text-align: center;\r\n }\r\n\r\n .progress-slider {\r\n flex: 1;\r\n height: 4px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n background: rgba(62, 166, 255, 0.2);\r\n border-radius: 2px;\r\n outline: none;\r\n cursor: pointer;\r\n\r\n &::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #3ea6ff;\r\n cursor: pointer;\r\n box-shadow: 0 0 6px rgba(62, 166, 255, 0.6);\r\n }\r\n\r\n &::-moz-range-thumb {\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 50%;\r\n background: #3ea6ff;\r\n border: none;\r\n cursor: pointer;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ─── 实时模式提示 ──────────────────────────────────────────────────────────\r\n.track-panel__realtime-hint {\r\n padding: 8px 12px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.07);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n\r\n .realtime-pulse {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 12px;\r\n color: #ff6b35;\r\n .fa {\r\n color: #ff6b35;\r\n }\r\n }\r\n\r\n .blink-dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n background: #ff6b35;\r\n animation: blink 1s ease-in-out infinite;\r\n }\r\n\r\n .realtime-count {\r\n font-size: 11px;\r\n color: #7a9ec0;\r\n strong {\r\n color: #ff6b35;\r\n }\r\n }\r\n}\r\n\r\n@keyframes blink {\r\n 0%,\r\n 100% {\r\n opacity: 1;\r\n }\r\n 50% {\r\n opacity: 0.2;\r\n }\r\n}\r\n\r\n// ─── 轨迹列表 ─────────────────────────────────────────────────────────────\r\n.track-panel__list {\r\n overflow-y: auto;\r\n max-height: calc(100vh - 340px);\r\n padding: 6px 0;\r\n\r\n &::-webkit-scrollbar {\r\n width: 4px;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: rgba(62, 166, 255, 0.3);\r\n border-radius: 2px;\r\n }\r\n}\r\n\r\n.track-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.1);\r\n }\r\n &--active {\r\n background: rgba(62, 166, 255, 0.18);\r\n }\r\n &--realtime .track-item__bar {\r\n background: #ff6b35 !important;\r\n }\r\n\r\n &__bar {\r\n width: 3px;\r\n height: 30px;\r\n border-radius: 2px;\r\n background: #3ea6ff;\r\n flex-shrink: 0;\r\n }\r\n\r\n &__info {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n &__name {\r\n overflow: hidden;\r\n font-size: 13px;\r\n color: #ffffff;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n .fa {\r\n color: #8ab4d4;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n &__meta {\r\n font-size: 11px;\r\n color: #9dc8f0;\r\n margin-top: 2px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .realtime-tag {\r\n background: rgba(255, 107, 53, 0.2);\r\n color: #ff6b35;\r\n font-size: 10px;\r\n padding: 0 5px;\r\n border-radius: 6px;\r\n }\r\n\r\n &__actions {\r\n display: flex;\r\n gap: 4px;\r\n flex-shrink: 0;\r\n opacity: 0;\r\n transition: opacity 0.15s;\r\n }\r\n\r\n &:hover &__actions {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.icon-btn {\r\n width: 22px;\r\n height: 22px;\r\n border: none;\r\n background: rgba(255, 255, 255, 0.08);\r\n color: #9dc8f0;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 11px;\r\n transition: all 0.15s;\r\n &:hover {\r\n background: rgba(62, 166, 255, 0.3);\r\n color: #fff;\r\n }\r\n &--danger:hover {\r\n background: rgba(255, 80, 80, 0.35);\r\n color: #fff;\r\n }\r\n}\r\n\r\n// ─── 空状态 ────────────────────────────────────────────────────────────────\r\n.track-panel__empty {\r\n text-align: center;\r\n padding: 30px 20px;\r\n color: #4a6a8a;\r\n .fa {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: block;\r\n }\r\n p {\r\n font-size: 12px;\r\n margin: 0;\r\n }\r\n}\r\n\r\n// ─── 列表动画 ──────────────────────────────────────────────────────────────\r\n.track-list-enter-active,\r\n.track-list-leave-active {\r\n transition: all 0.25s ease;\r\n}\r\n.track-list-enter-from {\r\n opacity: 0;\r\n transform: translateX(-12px);\r\n}\r\n.track-list-leave-to {\r\n opacity: 0;\r\n transform: translateX(12px);\r\n}\r\n</style>\r\n","/**\r\n * Mars3D Vue3 Components - 统一导出入口\r\n *\r\n * @description 封装了 Mars3D 地图的基础能力(测量、绘制、视角控制)\r\n * 及业务组件(POI 标注、轨迹管理)的 Vue3 组件库\r\n *\r\n * @example\r\n * // 完整引入\r\n * import Mars3dVueComponents from '@your-org/mars3d-vue-components'\r\n * app.use(Mars3dVueComponents)\r\n *\r\n * // 按需引入\r\n * import { MarsMapContainer, useMap } from '@your-org/mars3d-vue-components'\r\n *\r\n * // 样式导入(如果 CSS 未内联)\r\n * import '@your-org/mars3d-vue-components/dist/yi-map-web.css';\r\n */\r\n\r\n// 注意:CSS 样式已移至 ./styles/index.css\r\n// 组件库打包时会自动提取 CSS 到单独文件\r\n// 消费项目可以通过以下方式引入样式:\r\n// import 'yi-map-web/dist/yi-map-web.css';\r\n// 或\r\n// import 'yi-map-web/styles'; // 直接导入源样式文件\r\n\r\n// ── 基础组件 ──────────────────────────────────────────────────────────────────\r\nexport { default as MarsMapContainer } from \"./components/mars-map/MarsMapContainer.vue\";\r\nexport { default as ToolbarPanel } from \"./components/mars-map/panels/ToolbarPanel.vue\";\r\nexport { default as VisionPanel } from \"./components/mars-map/panels/VisionPanel.vue\";\r\n\r\n// ── Composables ────────────────────────────────────────────────────────────────\r\nexport { useMap } from \"./components/mars-map/composables/useMap\";\r\nexport { useMeasure } from \"./components/mars-map/composables/useMeasure\";\r\nexport { useDraw } from \"./components/mars-map/composables/useDraw\";\r\nexport { useVision } from \"./components/mars-map/composables/useVision\";\r\n\r\n// ── 业务组件 ──────────────────────────────────────────────────────────────────\r\nexport { default as PoiMarkerLayer } from \"./components/business/poi-marker/PoiMarkerLayer.vue\";\r\nexport { default as PoiMarkerPanel } from \"./components/business/poi-marker/PoiMarkerPanel.vue\";\r\nexport { default as TrackLayer } from \"./components/business/track/TrackLayer.vue\";\r\nexport { default as TrackPanel } from \"./components/business/track/TrackPanel.vue\";\r\n\r\n// ── 业务 Composable ───────────────────────────────────────────────────────────\r\nexport { usePoiMarker } from \"./components/business/poi-marker/usePoiMarker\";\r\nexport { useTrack } from \"./components/business/track/useTrack\";\r\n\r\n// ── 类型导出 ─────────────────────────────────────────────────────────────────\r\nexport type { UseMapReturn } from \"./components/mars-map/composables/useMap\";\r\nexport type { DrawType } from \"./components/mars-map/composables/useDraw\";\r\nexport type {\r\n PoiItem,\r\n UsePoiMarkerReturn,\r\n} from \"./components/business/poi-marker/usePoiMarker\";\r\nexport type {\r\n TrackPoint,\r\n TrackItem,\r\n UseTrackReturn,\r\n} from \"./components/business/track/useTrack\";\r\n\r\n// ── 安装插件(完整引入时使用)─────────────────────────────────────────────────\r\nimport type { App, Component } from \"vue\";\r\nimport MarsMapContainer from \"./components/mars-map/MarsMapContainer.vue\";\r\nimport ToolbarPanel from \"./components/mars-map/panels/ToolbarPanel.vue\";\r\nimport VisionPanel from \"./components/mars-map/panels/VisionPanel.vue\";\r\nimport PoiMarkerLayer from \"./components/business/poi-marker/PoiMarkerLayer.vue\";\r\nimport PoiMarkerPanel from \"./components/business/poi-marker/PoiMarkerPanel.vue\";\r\nimport TrackLayer from \"./components/business/track/TrackLayer.vue\";\r\nimport TrackPanel from \"./components/business/track/TrackPanel.vue\";\r\n\r\nconst components: Record<string, Component> = {\r\n MarsMapContainer,\r\n ToolbarPanel,\r\n VisionPanel,\r\n PoiMarkerLayer,\r\n PoiMarkerPanel,\r\n TrackLayer,\r\n TrackPanel,\r\n};\r\n\r\nconst YiMapWeb = {\r\n install(app: App, options?: { prefix?: string }) {\r\n const prefix = options?.prefix ?? \"\";\r\n for (const [name, component] of Object.entries(components)) {\r\n app.component(prefix ? `${prefix}${name}` : name, component);\r\n }\r\n },\r\n};\r\n\r\nexport default YiMapWeb;\r\n"],"names":["mars3d","computed","toRaw","onMounted","onUnmounted","_createElementBlock","ref","_normalizeClass","_createElementVNode","_withDirectives","_hoisted_1","_hoisted_2","_Fragment","_renderList","_hoisted_4","_createVNode","_Transition","_openBlock","_hoisted_3","_toDisplayString","shallowRef","provide","MarsMap","_createBlock","_unref","_renderSlot","_idCounter","inject","watch","reactive","_normalizeStyle","_hoisted_5","_hoisted_6","_createTextVNode","_hoisted_8","_hoisted_10","_TransitionGroup","_hoisted_12","_withModifiers","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_19","track","_a","PoiMarkerLayer","TrackLayer"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAYO,MAAM,mBAAmBA,kBAAO,SAAS;AAAA;AAAA,IAE9C,gBAAgB;AACd,WAAK,KAAK,kBAAkB,KAAK,QAAQ,IAAI;AAAA,IAC/C;AAAA;AAAA,IAGA,aAAa;AACX,WAAK,aAAY;AAAA,IACnB;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,cAAc,UAAU;AAAA,ECV5C,MAAM,mBAAmBA,kBAAO,SAAS;AAAA;AAAA,IAE9C,gBAAgB;AACd,WAAK,KAAK,cAAc,KAAK,QAAQ,QAAQ,EAAE,UAAU,KAAK,WAAW;AAAA,IAC3E;AAAA;AAAA,IAGA,eAAe;AACb,WAAK,KAAK,YAAW;AAAA,IACvB;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,UAAU,UAAU;AAAA,ECVxC,MAAM,kBAAkBA,kBAAO,SAAS;AAAA,IAC7C,YAAY,UAAU,IAAI;AACxB,YAAM,OAAO;AAEb,WAAK,SAAS,KAAK,QAAQ,SAAS;AACpC,WAAK,UAAU,KAAK,QAAQ,UAAU,EAAE,KAAK,WAAW,KAAK,YAAY,KAAK,cAAY,SAAS,GAAG,OAAO,IAAG;AAAA,IAClH;AAAA;AAAA,IAGA,gBAAgB;AACd,WAAK,KAAK,cAAc,KAAK,SAAS;AAAA,QACpC,UAAU;AAAA,QACV,UAAU,MAAM;AACd,eAAK,KAAK,GAAGA,kBAAO,UAAU,WAAW,KAAK,kBAAkB,IAAI;AAAA,QACtE;AAAA,MACN,CAAK;AAAA,IACH;AAAA;AAAA,IAGA,eAAe;AACb,WAAK,KAAK,IAAIA,kBAAO,UAAU,WAAW,KAAK,kBAAkB,IAAI;AAAA,IACvE;AAAA,IAEA,mBAAmB;AACjB,UAAI,KAAK,SAAS;AAChB;AAAA,MACF;AAEA,WAAK,KAAK,MAAM,OAAO,OAAOA,kBAAO,OAAO,WAAW,QAAQ,KAAK,MAAM;AAAA,IAC5E;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,aAAa,SAAS;AAAA,EC5B1C,MAAM,oBAAoBA,kBAAO,SAAS;AAAA;AAAA,IAE/C,gBAAgB;AACd,UAAI,KAAK,QAAQ,QAAQ;AACvB,aAAK,KAAK,cAAc,KAAK,QAAQ,QAAQ,EAAE,UAAU,GAAG;AAAA,MAC9D;AAEA,UAAI,KAAK,QAAQ,UAAU;AACzB,eAAO,KAAK,QAAQ;AAAA,MACtB;AAEA,UAAI,KAAK,QAAQ,aAAa;AAC5B,aAAK,aAAa,IAAIA,kBAAO,MAAM,UAAU,KAAK,OAAO;AACzD,aAAK,KAAK,SAAS,KAAK,UAAU;AAAA,MACpC,OAAO;AACL,aAAK,eAAe,IAAIA,kBAAO,MAAM,YAAY,KAAK,OAAO;AAC7D,aAAK,KAAK,SAAS,KAAK,YAAY;AAAA,MACtC;AAEA,UAAI,KAAK,QAAQ,aAAa;AAC5B,aAAK,WAAW,MAAK;AAAA,MACvB,OAAO;AACL,aAAK,aAAa,MAAM,KAAK,QAAQ,KAAK;AAAA,MAC5C;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,cAAc;AACrB,aAAK,aAAa,KAAI;AACtB,aAAK,aAAa,QAAO;AACzB,eAAO,KAAK;AAAA,MACd;AACA,UAAI,KAAK,YAAY;AACnB,aAAK,WAAW,KAAI;AACpB,aAAK,WAAW,QAAO;AACvB,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,eAAe,WAAW;AAAA,EC5C9C,MAAM,kBAAkBA,kBAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAM7C,gBAAgB;AACd,WAAK,gBAAgB,IAAIA,kBAAO,MAAM,aAAY;AAClD,WAAK,KAAK,SAAS,KAAK,aAAa;AAErC,YAAM,aAAa,IAAIA,kBAAO,QAAQ,WAAW,KAAK,QAAQ,KAAK;AACnE,WAAK,cAAc,WAAW,UAAU;AACxC,WAAK,cAAc;AAEnB,iBAAW,MAAK;AAAA,IAClB;AAAA;AAAA,IAGA,WAAW,SAAS;AAClB,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,MAAK;AAAA,MACxB;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,QAAO;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,aAAa;AACpB,aAAK,YAAY,KAAI;AACrB,eAAO,KAAK;AAAA,MACd;AAEA,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc,QAAO;AAC1B,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,aAAa,SAAS;AAAA,EC5C1C,MAAM,eAAeA,kBAAO,SAAS;AAAA;AAAA,IAE1C,gBAAgB;AACd,WAAK,KAAK,OAAO,KAAK,QAAQ,cAAc;AAAA,IAC9C;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,UAAU,MAAM;AAAA,ECNpC,MAAM,gBAAgBA,kBAAO,SAAS;AAAA;AAAA,IAE3C,gBAAgB;AACd,WAAK,KAAK,QAAQ,KAAK,QAAQ,cAAc;AAAA,IAC/C;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,WAAW,OAAO;AAAA,ECDtC,MAAM,sBAAsBA,kBAAO,SAAS;AAAA;AAAA,IAEjD,gBAAgB;AACd,YAAM,QAAQ,KAAK,KAAK,aAAa,KAAK,QAAQ,OAAO;AACzD,UAAI,OAAO;AACT,cAAM,OAAO;AACb,cAAM,aAAa,KAAK,MAAM;AAC5B,eAAK,WAAW,MAAM,eAAe,KAAK,QAAQ,SAAS;AAC3D,cAAI,KAAK,UAAU;AACjB,iBAAK,SAAS,OAAO;AACrB,iBAAK,SAAS,aAAa;AAAA,cACzB,MAAM,KAAK;AAAA,cACX,MAAM,KAAK,QAAQ;AAAA,cACnB,UAAU,KAAK,QAAQ;AAAA,cACvB,OAAO,KAAK,QAAQ;AAAA,YAChC,CAAW;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA,IAGA,eAAe;AACb,UAAI,KAAK,UAAU;AACjB,aAAK,SAAS,YAAW;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACAA,oBAAO,MAAM,KAAK,SAAS,iBAAiB,aAAa;AAAA,EC3ClD,MAAM,wBAAwBA,kBAAO,QAAQ,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKrE,IAAI,OAAO;AACT,aAAO,KAAK,MAAM;AAAA,IACpB;AAAA,IAEA,IAAI,KAAK,KAAK;AACZ,WAAK,MAAM,OAAO;AAElB,WAAK,MAAM,OAAO;AAAA,IACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,WAAW,OAAO;AAChB,YAAM,QAAQ;AACd,YAAM,QAAQ;AAAA,QACZ,GAAG;AAAA,QACH,MAAM,KAAK,MAAM;AAAA,QACjB,WAAW;AAAA,QACX,OAAO,MAAM,aAAa;AAAA,QAC1B,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,cAAc,OAAO,MAAM,SAAS;AAAA,MAC1C;AACI,UAAI,MAAM,iBAAiB;AACzB,cAAM,MAAM,6BAA6B,MAAM;AAAA,MACjD;AAEA,YAAM,WAAW,KAAK;AAAA,IACxB;AAAA,EACF;AAGAA,oBAAO,YAAY,SAAS,mBAAmB,eAAe;;;;;;;;;;;AC9B9D,YAAM,QAAQ;AAcd,UAAI;AAGJ,YAAM,YAAYC,IAAAA,SAAS,MAAM,oBAAoB,MAAM,MAAM,EAAE;AAGnE,YAAM,OAAO;AAEb,YAAM,aAAa,YAAY;AAE7B,YAAI;AACJ,YAAI,MAAM,KAAK;AAEb,uBAAa,MAAMD,kBAAO,KAAK,UAAU,EAAE,KAAK,MAAM,KAAK;AAC3D,cAAI,MAAM,SAAS;AACjB,yBAAaA,kBAAO,KAAK,MAAM,YAAYE,UAAM,MAAM,OAAO,CAAC;AAAA,UACjE;AAAA,QACF,WAAW,MAAM,SAAS;AACxB,uBAAaA,IAAAA,MAAM,MAAM,OAAO;AAAA,QAClC;AAICF,0BAAe,KAAK,gBAAgB;AAErC,cAAM,IAAIA,kBAAO,IAAI,UAAU,OAAO,UAAU;AAGhD,YAAIA,kBAAO,KAAK,eAAe;AAC7B,cAAI,aAAa;AAGjB,cAAI,OAAO,UAAU,UAAU,YAAA,EAAc,QAAQ,MAAM,KAAK,GAAG;AACjE,gBAAI,OAAO,kBAAkB;AAC7B,gBAAI,MAAM,oBAAoB;AAAA,UAChC;AAAA,QACF,OAAO;AACL,cAAI,aAAa;AAGjB,cAAI,MAAM,oBAAoB;AAC9B,cAAI,MAAM,IAAI,UAAU;AACxB,cAAI,MAAM,cAAc,OAAO;AAC/B,cAAI,MAAM,MAAM,uBAAuB;AAAA,QACzC;AAGA,YAAI,IAAI,OAAO,iBAAiB;AAC9B,cAAI,OAAO,gBAAgB,UAAU,WAAW;AAAA,QAClD;AAMA,YAAK,IAAY,YAAY;AAC1B,cAAY,WAAW,OAAO;AAAA,QACjC;AAEA,mBAAW,MAAM;AACf,gBAAM,eAAe,SAAS,uBAAuB,aAAa;AAClE,mBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,yBAAa,CAAC,EAAE,OAAA;AAAA,UAClB;AAAA,QACF,GAAG,GAAG;AASN,aAAK,UAAU,GAAG;AAAA,MACpB;AAWAG,UAAAA,UAAU,MAAM;AACd,mBAAA;AAAA,MACF,CAAC;AAEDC,UAAAA,YAAY,MAAM;AAChB,YAAI,KAAK;AACP,cAAI,QAAA;AACJ,gBAAM;AAAA,QACR;AAAA,MAEF,CAAC;;gCAtHCC,IAAAA,mBAAoD,OAAA;AAAA,UAA9C,IAAI,UAAA;AAAA,UAAW,OAAM;AAAA,QAAA;;;;;;;;;;;;;;;;AC+D7B,YAAM,OAAO;AAMb,YAAM,cAAcC,IAAAA,IAAI,KAAK;AAE7B,YAAM,iBAAiB,MAAM;AAC3B,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AACA,YAAM,eAAe,CAAC,SAAiB;AACrC,aAAK,gBAAgB,IAAI;AAAA,MAC3B;AACA,YAAM,YAAY,MAAM;AACtB,aAAK,OAAO;AAAA,MACd;AAUA,YAAM,eAA2B;AAAA,QAC/B;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,iBAAiB;AAAA;AAAA,QAAA;AAAA,QAEvC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,kBAAkB;AAAA;AAAA,QAAA;AAAA,QAExC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,iBAAiB;AAAA;AAAA,QAAA;AAAA,QAEvC;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,YAAY,qBAAqB;AAAA;AAAA,QAAA;AAAA,MACjD;AAGF,YAAM,YAAwB;AAAA,QAC5B;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,eAAe;AAAA;AAAA,UACnC,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,UAAU;AAAA;AAAA,UAC9B,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,YAAY,iBAAiB;AAAA;AAAA,UAC3C,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,WAAW;AAAA;AAAA,UAC/B,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,cAAc,WAAW;AAAA;AAAA,UACvC,UAAU;AAAA,QAAA;AAAA,QAEZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa,CAAC,MAAM,WAAW;AAAA;AAAA,UAC/B,UAAU;AAAA,QAAA;AAAA,MACZ;;gCAhJAD,IAAAA,mBA+CM,OAAA;AAAA,UA/CD,OAAKE,IAAAA,eAAA,CAAC,iBAAe,EAAA,WAAsB,YAAA,OAAW,CAAA;AAAA,QAAA;UAEzDC,IAAAA,mBAQM,OAAA;AAAA,YARD,OAAM;AAAA,YAAgB,SAAO;AAAA,UAAA;YAChCA,IAAAA,mBAME,KAAA;AAAA,cALC,OAAKD,IAAAA,eAAA;AAAA;;gBAA0D,YAAA,QAAW,oBAAA;AAAA,cAAA;;;UAQ/EE,mBAAAD,IAAAA,mBAkCM,OAlCNE,cAkCM;AAAA,YAhCJF,IAAAA,mBAUM,OAVNG,cAUM;AAAA,gCATJN,IAAAA,mBAQMO,IAAAA,UAAA,MAAAC,eAPW,cAAY,CAApB,SAAI;uBADbL,IAAAA,mBAQM,OAAA;AAAA,kBANH,KAAK,KAAK;AAAA,kBACX,OAAM;AAAA,kBACL,OAAO,KAAK;AAAA,kBACZ,SAAK,CAAA,WAAE,aAAa,KAAK,IAAI;AAAA,gBAAA;kBAE9BA,IAAAA,mBAA+B,KAAA;AAAA,oBAA3B,OAAKD,IAAAA,eAAE,KAAK,WAAW;AAAA,kBAAA;;;;sCAI/BC,IAAAA,mBAAuB,OAAA,EAAlB,OAAM,UAAA,GAAS,MAAA,EAAA;AAAA,YAGpBA,IAAAA,mBAgBM,OAhBNM,cAgBM;AAAA,gCAfJT,IAAAA,mBASMO,IAAAA,UAAA,MAAAC,eARW,WAAS,CAAjB,SAAI;uBADbL,IAAAA,mBASM,OAAA;AAAA,kBAPH,KAAK,KAAK;AAAA,kBACX,2BAAM,aAAW,EAAA,QACC,2BAAmB,KAAK,SAAA,CAAQ,CAAA;AAAA,kBACjD,OAAO,KAAK;AAAA,kBACZ,SAAK,CAAA,WAAE,aAAa,KAAK,IAAI;AAAA,gBAAA;kBAE9BA,IAAAA,mBAA+B,KAAA;AAAA,oBAA3B,OAAKD,IAAAA,eAAE,KAAK,WAAW;AAAA,kBAAA;;;wCAE7BC,IAAAA,mBAAuB,OAAA,EAAlB,OAAM,UAAA,GAAS,MAAA,EAAA;AAAA,cAEpBA,IAAAA,mBAEM,OAAA;AAAA,gBAFD,OAAM;AAAA,gBAAY,OAAM;AAAA,gBAAQ,SAAO;AAAA,cAAA;gBAC1CA,IAAAA,mBAAmC,KAAA,EAAhC,OAAM,wBAAA,GAAuB,MAAA,EAAA;AAAA,cAAA;;;yBA/BF,YAAA,KAAW;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACoBnD,YAAM,QAAQ;AAQd,YAAM,OAAO;AAKb,YAAM,eAAeF,IAAAA,IAAI,KAAK;AAC9B,YAAM,cAAc,MAAM;AAAE,qBAAa,QAAQ,CAAC,aAAa;AAAA,MAAO;AACtE,YAAM,UAAU,CAAC,WAAmB;AAAE,aAAK,iBAAiB,MAAM;AAAA,MAAG;AAWrE,YAAM,cAA4B;AAAA,QAChC;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,QAEd;AAAA,UACE,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,QAAA;AAAA,MACd;AAGF,YAAM,WAAW,CAAC,SAChB,KAAK,aAAa,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI;AAE/C,YAAM,WAAW,CAAC,SAChB,SAAS,IAAI,KAAK,KAAK,cAAc,KAAK,cAAc,KAAK;;;UA3F7DE,IAAAA,mBAEM,OAAA;AAAA,YAFD,OAAM;AAAA,YAAgB,OAAM;AAAA,YAAQ,SAAO;AAAA,UAAA;YAC9CA,IAAAA,mBAAuB,KAAA,EAApB,OAAM,YAAA,GAAW,MAAA,EAAA;AAAA,UAAA;UAItBO,IAAAA,YAmBaC,IAAAA,YAAA,EAnBD,MAAK,iBAAa;AAAA,iCAC5B,MAiBM;AAAA,cAjBK,aAAA,SAAXC,IAAAA,UAAA,GAAAZ,IAAAA,mBAiBM,OAjBNK,cAiBM;AAAA,gBAhBJF,IAAAA,mBAGM,OAHNG,cAGM;AAAA,kBAFJ,OAAA,CAAA,MAAA,OAAA,CAAA,IAAAH,uBAAiB,cAAX,QAAI,EAAA;AAAA,kBACVA,IAAAA,mBAAkE,KAAA;AAAA,oBAA/D,OAAM;AAAA,oBAA0B,+CAAO,aAAA,QAAY;AAAA,kBAAA;;gBAExDA,IAAAA,mBAWM,OAXNU,cAWM;AAAA,oCAVJb,IAAAA,mBASMO,IAAAA,UAAA,MAAAC,eARW,aAAW,CAAnB,SAAI;2BADbL,IAAAA,mBASM,OAAA;AAAA,sBAPH,KAAK,KAAK;AAAA,sBACX,OAAKD,IAAAA,eAAA,CAAC,cAAY,EAAA,QACA,SAAS,IAAI,EAAA,CAAA,CAAA;AAAA,sBAC9B,SAAK,CAAA,WAAE,QAAQ,KAAK,MAAM;AAAA,oBAAA;sBAE3BC,IAAAA,mBAAgC,KAAA;AAAA,wBAA5B,OAAKD,IAAAA,eAAA,CAAA,MAAS,KAAK,IAAI,CAAA;AAAA,sBAAA;sBAC3BC,IAAAA,mBAAiC,QAAA,MAAAW,IAAAA,gBAAxB,SAAS,IAAI,CAAA,GAAA,CAAA;AAAA,oBAAA;;;;;;;;;;;;ACdzB,WAAS,SAAS;AACvB,UAAM,SAASnB,kBAAO;AAGtB,UAAM,SAASoB,IAAAA,WAA8B,IAAI;AAGjD,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AACtE,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AAGtE,UAAM,kBAAkBd,IAAAA,IAAS,IAAI;AAGrC,UAAM,oBAAoBA,IAAAA,IAAsD,IAAI;AAKpF,aAAS,QAAQ,KAAiB;AAChC,aAAO,QAAQ;AAGf,YAAM,SAAS,IAAIN,kBAAO,MAAM,aAAA;AAChC,UAAI,SAAS,MAAM;AACnB,mBAAa,QAAQ;AAGrB,YAAM,SAAS,IAAIA,kBAAO,MAAM,aAAA;AAChC,UAAI,SAAS,MAAM;AACnB,mBAAa,QAAQ;AAGrB,UAAI,GAAGA,kBAAO,UAAU,OAAO,CAAC,UAAe;AAC7C,YAAI,MAAM,QAAQ;AAChB,4BAAkB,QAAQ,MAAM;AAAA,QAClC,WAAW,MAAM,WAAW;AAC1B,gBAAM,QAAQ,OAAO,UAAU,MAAM,wBAAwB,MAAM,SAAS;AAC5E,4BAAkB,QAAQ;AAAA,YACxB,KAAK,OAAO,KAAK,UAAU,MAAM,SAAS;AAAA,YAC1C,KAAK,OAAO,KAAK,UAAU,MAAM,QAAQ;AAAA,YACzC,KAAK,MAAM,SAAS,IAAI,MAAM,SAAS;AAAA,UAAA;AAAA,QAE3C;AAAA,MACF,CAAC;AAGD,aAAO,GAAGA,kBAAO,UAAU,OAAO,CAAC,UAAe;AAChD,wBAAgB,QAAQ,MAAM;AAAA,MAChC,CAAC;AACD,aAAO,GAAGA,kBAAO,UAAU,WAAW,CAAC,UAAe;AACpD,YAAI,CAAC,gBAAgB,OAAO;AAC1B,0BAAgB,QAAQ,MAAM;AAAA,QAChC;AAAA,MACF,CAAC;AACD,aAAO,GAAGA,kBAAO,UAAU,UAAU,CAAC,UAAe;AACnD,YAAI,gBAAgB,UAAU,MAAM,SAAS;AAC3C,0BAAgB,QAAQ;AAAA,QAC1B;AAAA,MACF,CAAC;AAAA,IACH;AAKA,aAAS,aAAa;AACpB,UAAI,OAAO,OAAO;AAChB,eAAO,MAAM,QAAA;AACb,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAKA,aAAS,WAAW,SAAc;;AAChC,yBAAa,UAAb,mBAAoB,WAAW;AAAA,IACjC;AAKA,aAAS,SAAS,OAAY;;AAC5B,mBAAO,UAAP,mBAAc,SAAS;AAAA,IACzB;AAEA,WAAO;AAAA;AAAA,MAEL,KAAK;AAAA;AAAA,MAEL;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;ACtGO,WAAS,WAAW,YAA0B;AACnD,UAAM,eAAeoB,IAAAA,WAAwC,IAAI;AAGjE,aAAS,cAAc;AACrB,YAAM,MAAM,WAAW,IAAI;AAC3B,YAAM,QAAQ,WAAW,aAAa;AACtC,UAAI,CAAC,OAAO,CAAC,MAAO;AAEpB,YAAM,IAAI,IAAIpB,kBAAO,MAAM,QAAQ,EAAE,cAAc,OAAc;AACjE,UAAI,SAAS,CAAC;AACd,mBAAa,QAAQ;AAAA,IACvB;AAGA,aAAS,gBAAgB,OAA6B;;AACpD,yBAAa,UAAb,mBAAoB,SAAS;AAAA,QAC3B,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,YAAY,OAA6B;;AAChD,yBAAa,UAAb,mBAAoB,KAAK;AAAA,QACvB,OAAO,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA;AAAA,MAAM;AAAA,IAEtD;AAGA,aAAS,cAAc,OAA6B;;AAClD,yBAAa,UAAb,mBAAoB,OAAO;AAAA,QACzB,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,aAAa,OAA6B;;AACjD,yBAAa,UAAb,mBAAoB,MAAM;AAAA,QACxB,OAAO,EAAE,OAAO,WAAW,OAAO,GAAG,GAAG,MAAA;AAAA,MAAM;AAAA,IAElD;AAGA,aAAS,eAAe;;AACtB,yBAAa,UAAb,mBAAoB;AACpB,uBAAW,aAAa,UAAxB,mBAA+B;AAAA,IACjC;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;ACvDO,WAAS,QAAQ,YAA0B;AAChD,UAAM,cAAcoB,IAAAA,WAAgB,IAAI;AAExC,UAAM,iBAAiBd,IAAAA,IAAqB,IAAI;AAGhD,aAAS,WAAW;AAClB,aAAO,WAAW,aAAa;AAAA,IACjC;AAGA,aAAS,UAAU,MAAc,OAA4B,UAAoB;AAC/E,YAAM,QAAQ,SAAA;AACd,UAAI,CAAC,MAAO;AACZ,eAAA;AACA,kBAAY,QAAQ,MAAM,UAAU,EAAE,MAAM,OAAO;AACnD,qBAAe,QAAQ;AAAA,IACzB;AAGA,aAAS,UAAU,OAA6B;AAC9C,gBAAU,SAAS,EAAE,WAAW,IAAI,OAAO,WAAW,GAAG,MAAA,GAAS,OAAO;AAAA,IAC3E;AAGA,aAAS,SAAS,OAA6B;AAC7C,gBAAU,YAAY,EAAE,OAAO,GAAG,OAAO,WAAW,GAAG,MAAA,GAAS,UAAU;AAAA,IAC5E;AAGA,aAAS,YAAY,OAA6B;AAChD,gBAAU,WAAW,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,SAAS;AAAA,IAC9E;AAGA,aAAS,WAAW,OAA6B;AAC/C,gBAAU,UAAU,EAAE,QAAQ,KAAM,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,QAAQ;AAAA,IAC1F;AAGA,aAAS,cAAc,OAA6B;AAClD,gBAAU,aAAa,EAAE,OAAO,WAAW,SAAS,KAAK,GAAG,MAAA,GAAS,WAAW;AAAA,IAClF;AAGA,aAAS,gBAAgB,OAA6B;AACpD;AAAA,QACE;AAAA,QACA,EAAE,OAAO,WAAW,SAAS,KAAK,eAAe,MAAM,GAAG,MAAA;AAAA,QAC1D;AAAA,MAAA;AAAA,IAEJ;AAGA,aAAS,WAAW;;AAClB,UAAI,YAAY,OAAO;AACrB,uBAAA,MAAA,mBAAY;AACZ,oBAAY,QAAQ;AAAA,MACtB;AACA,qBAAe,QAAQ;AAAA,IACzB;AAGA,aAAS,YAAY;;AACnB,eAAA;AACA,qBAAA,MAAA,mBAAY;AAAA,IACd;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AChFO,WAAS,UAAU,YAA0B;AAElD,UAAM,kBAAkBA,IAAAA,IAAI,KAAK;AACjC,UAAM,oBAAoBA,IAAAA,IAAI,KAAK;AACnC,UAAM,iBAAiBA,IAAAA,IAAI,KAAK;AAChC,UAAM,cAAcA,IAAAA,IAAI,KAAK;AAG7B,UAAM,cAAcc,IAAAA,WAA4C,IAAI;AACpE,UAAM,kBAAkBA,IAAAA,WAAgD,IAAI;AAC5E,UAAM,eAAeA,IAAAA,WAA6C,IAAI;AACtE,QAAI,oBAAyB;AAG7B,aAAS,SAAS;AAChB,aAAO,WAAW,IAAI;AAAA,IACxB;AAGA,aAAS,kBAAkB;AACzB,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,YAAY,OAAO;AACrB,YAAI,YAAY,MAAM,SAAS;AAC7B,sBAAY,MAAM,KAAA;AAAA,QACpB;AACA,YAAI,YAAY,YAAY,KAAK;AACjC,oBAAY,QAAQ;AACpB,wBAAgB,QAAQ;AACxB;AAAA,MACF;AAEA,YAAM,SAAS,IAAI,UAAA;AACnB,YAAM,KAAK,IAAIpB,kBAAO,MAAM,YAAY,EAAE,UAAU,KAAM,MAAM,IAAI;AACpE,UAAI,SAAS,EAAE;AACf,SAAG,MAAM,MAAM;AACf,kBAAY,QAAQ;AACpB,sBAAgB,QAAQ;AAAA,IAC1B;AAGA,aAAS,QAAQ;AACf,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,kBAAY,QAAQ;AACpB,YAAM,OAAO,MAAM,WAAW,MAAM;AAAE,oBAAY,QAAQ;AAAA,MAAO,GAAG,GAAI;AAExE,YAAM,MAAM,WAAW,kBAAkB;AACzC,UAAI,KAAK;AACP,cAAM,SAAS,EAAE,GAAG,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,IAAA;AACtD,YAAI,cAAc,QAAQ,EAAE,UAAU,GAAG,UAAU,MAAM;AAAA,MAC3D,OAAO;AACL,YAAI,QAAQ,EAAE,UAAU,EAAA,CAAG;AAC3B,aAAA;AAAA,MACF;AAAA,IACF;AAGA,aAAS,oBAAoB;AAC3B,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,CAAC,gBAAgB,OAAO;AAC1B,cAAM,OAAO,IAAIA,kBAAO,MAAM,gBAAgB,CAAA,CAAE;AAChD,YAAI,SAAS,IAAI;AACjB,4BAAoB,IAAI,cAAA;AACxB,aAAK,UAAU;AACf,wBAAgB,QAAQ;AACxB,0BAAkB,QAAQ;AAAA,MAC5B,OAAO;AACL,cAAM,OAAO,gBAAgB;AAC7B,aAAK,UAAU,CAAC,KAAK;AACrB,0BAAkB,QAAQ,KAAK;AAC/B,YAAI,CAAC,KAAK,WAAW,mBAAmB;AACtC,cAAI,cAAc,mBAAmB,EAAE,UAAU,GAAG;AAAA,QACtD,WAAW,KAAK,SAAS;AACvB,8BAAoB,IAAI,cAAA;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAGA,aAAS,yBAAyB;AAChC,YAAM,MAAM,OAAA;AACZ,UAAI,CAAC,IAAK;AAEV,UAAI,CAAC,aAAa,OAAO;AACvB,cAAM,OAAO,IAAIA,kBAAO,MAAM,aAAa,CAAA,CAAE;AAC7C,YAAI,SAAS,IAAI;AACjB,aAAK,UAAU;AACf,qBAAa,QAAQ;AACrB,uBAAe,QAAQ;AAAA,MACzB,OAAO;AACL,cAAM,OAAO,aAAa;AAC1B,aAAK,UAAU,CAAC,KAAK;AACrB,uBAAe,QAAQ,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA;AAAA,MAEL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;;;;;;;;;;;;AC3CA,YAAM,OAAO;AAMb,YAAM,SAAS,OAAA;AACf,YAAM,UAAU,WAAW,MAAM;AACjC,YAAM,OAAO,QAAQ,MAAM;AAC3B,YAAM,SAAS,UAAU,MAAM;AAG/BqB,UAAAA,QAAQ,cAAc,MAAM;AAC5BA,UAAAA,QAAQ,kBAAkB,OAAO;AACjCA,UAAAA,QAAQ,eAAe,IAAI;AAC3BA,UAAAA,QAAQ,iBAAiB,MAAM;AAG/B,eAAS,UAAU,KAAU;AAC3B,eAAO,QAAQ,GAAG;AAClB,gBAAQ,YAAA;AACR,aAAK,UAAU,GAAG;AAAA,MACpB;AAOA,eAAS,mBAAmB,MAAc;AACxC,gBAAQ,MAAA;AAAA,UACN,KAAK;AAAoB,oBAAQ,gBAAA;AAAmB;AAAA,UACpD,KAAK;AAAoB,oBAAQ,YAAA;AAAe;AAAA,UAChD,KAAK;AAAoB,oBAAQ,cAAA;AAAiB;AAAA,UAClD,KAAK;AAAoB,oBAAQ,aAAA;AAAgB;AAAA,UACjD,KAAK;AAAoB,iBAAK,UAAA;AAAa;AAAA,UAC3C,KAAK;AAAoB,iBAAK,SAAA;AAAY;AAAA,UAC1C,KAAK;AAAoB,iBAAK,YAAA;AAAe;AAAA,UAC7C,KAAK;AAAoB,iBAAK,WAAA;AAAc;AAAA,UAC5C,KAAK;AAAoB,iBAAK,cAAA;AAAiB;AAAA,UAC/C,KAAK;AAAoB,iBAAK,gBAAA;AAAmB;AAAA,QAAA;AAAA,MAErD;AAEA,eAAS,cAAc;AACrB,gBAAQ,aAAA;AACR,aAAK,UAAA;AAAA,MACP;AAKA,eAAS,oBAAoB,QAAgB;AAC3C,gBAAQ,QAAA;AAAA,UACN,KAAK;AAAqB,mBAAO,gBAAA;AAAmB;AAAA,UACpD,KAAK;AAAqB,mBAAO,MAAA;AAAS;AAAA,UAC1C,KAAK;AAAqB,mBAAO,kBAAA;AAAqB;AAAA,UACtD,KAAK;AAAqB,mBAAO,uBAAA;AAA0B;AAAA,QAAA;AAAA,MAE/D;AAGA,eAAa;AAAA,QACX,KAAK,OAAO;AAAA,QACZ,cAAc,OAAO;AAAA,QACrB,cAAc,OAAO;AAAA,QACrB,iBAAiB,OAAO;AAAA,QACxB,mBAAmB,OAAO;AAAA,QAC1B,YAAY,OAAO;AAAA,QACnB,UAAU,OAAO;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;;AApIC,eAAAJ,cAAA,GAAAZ,uBA4BM,OA5BNK,cA4BM;AAAA,UA1BJK,IAAAA,YAIEO,aAAA;AAAA,YAHC,KAAK,QAAA;AAAA,YACL,WAAS,QAAA;AAAA,YACT,UAAQ;AAAA,UAAA;WAKF,QAAA,gCADTC,IAAAA,YAKE,cAAA;AAAA;YAHC,oBAAkBC,IAAAA,MAAA,IAAA,EAAK,eAAe;AAAA,YACtC,gBAAe;AAAA,YACf,SAAO;AAAA,UAAA;WAKD,QAAA,+BADTD,IAAAA,YAOE,aAAA;AAAA;YALC,qBAAmBC,IAAAA,MAAA,MAAA,EAAO,gBAAgB;AAAA,YAC1C,iBAAeA,IAAAA,MAAA,MAAA,EAAO,YAAY;AAAA,YAClC,uBAAqBA,IAAAA,MAAA,MAAA,EAAO,kBAAkB;AAAA,YAC9C,4BAA0BA,IAAAA,MAAA,MAAA,EAAO,eAAe;AAAA,YAChD,iBAAgB;AAAA,UAAA;UAInBC,IAAAA,WAAQ,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,IAAA;AAAA,QAAA;;;;;ACvBZ,QAAM,gBAAqD;AAAA,IACzD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAS;AAAA,EACX;AAEA,MAAIC,eAAa;AAEV,WAAS,aAAa,QAAsB;AAEjD,UAAM,WAAWN,IAAAA,WAA6C,IAAI;AAGlE,UAAM,UAAUd,IAAAA,IAAe,EAAE;AAGjC,UAAM,cAAcA,IAAAA,IAAmB,IAAI;AAG3C,aAAS,eAAe;AACtB,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,YAAM,QAAQ,IAAIN,kBAAO,MAAM,aAAA;AAC/B,UAAI,SAAS,KAAK;AAClB,eAAS,QAAQ;AAGjB,YAAM,GAAGA,kBAAO,UAAU,OAAO,CAAC,MAAW;;AAC3C,cAAM,SAAQ,aAAE,YAAF,mBAAW,SAAX,mBAAiB;AAC/B,YAAI,iBAAiB,KAAK;AAAA,MAC5B,CAAC;AAAA,IACH;AAGA,aAAS,OAAO,QAAyC;AACvD,YAAM,QAAQ,SAAS;AACvB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,OAAO0B,cAAY;AAG9B,YAAM,UAAU,IAAI1B,kBAAO,QAAQ,gBAAgB;AAAA,QACjD,UAAU,CAAC,OAAO,KAAK,OAAO,KAAK,OAAO,GAAG;AAAA,QAC7C,OAAO;AAAA,UACL,OAAO,cAAc,OAAO,QAAQ;AAAA,UACpC,OAAO;AAAA,UACP,kBAAkBA,kBAAO,OAAO,iBAAiB;AAAA,UACjD,gBAAgBA,kBAAO,OAAO,eAAe;AAAA,UAC7C,eAAe;AAAA;AAAA,UAEf,OAAO;AAAA,YACL,MAAM,OAAO;AAAA,YACb,WAAW;AAAA,YACX,OAAO;AAAA,YACP,SAAS;AAAA,YACT,cAAc;AAAA,YACd,cAAc;AAAA,YACd,aAAa,IAAIA,kBAAO,OAAO,WAAW,GAAG,GAAG;AAAA,YAChD,cAAc;AAAA,UAAA;AAAA,QAChB;AAAA;AAAA,QAGF,OAAO,eAAe,MAAM;AAAA,QAC5B,MAAM,EAAE,OAAO,IAAI,MAAM,OAAO,KAAA;AAAA,MAAK,CACtC;AAED,YAAM,WAAW,OAAO;AAExB,YAAM,MAAe,EAAE,GAAG,QAAQ,IAAI,QAAA;AACtC,cAAQ,MAAM,KAAK,GAAG;AACtB,aAAO;AAAA,IACT;AAGA,aAAS,UAAU,IAAY;;AAC7B,YAAM,MAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACtD,UAAI,QAAQ,GAAI;AAEhB,YAAM,MAAM,QAAQ,MAAM,GAAG;AAC7B,UAAI,aAAW,cAAS,UAAT,mBAAgB,cAAc,IAAI;AACjD,cAAQ,MAAM,OAAO,KAAK,CAAC;AAE3B,UAAI,YAAY,UAAU,GAAI,aAAY,QAAQ;AAAA,IACpD;AAGA,aAAS,UAAU,IAAY,QAAQ,OAAO;AAC5C,kBAAY,QAAQ;AACpB,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,IAAK;AAGV,cAAQ,MAAM,QAAQ,CAAC,MAAM;AAC3B,YAAI,EAAE,SAAS;AACb,YAAE,QAAQ,MAAM,QAAQ,EAAE,OAAO,KAAK,MAAM;AAAA,QAC9C;AAAA,MACF,CAAC;AAED,UAAI,gBAAgB,EAAE;AAAA,IACxB;AAGA,aAAS,cAAc,IAAY,SAAiB;;AAClD,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,IAAK;AAEV,UAAI,OAAO;AAGX,UAAI,IAAI,SAAS;AACf,YAAI,QAAQ,OAAO,EAAE,GAAG,IAAI,QAAQ,MAAM,MAAM,QAAA;AAChD,YAAI,QAAQ,QAAQ,eAAe,GAAG;AAEtC,aAAI,SAAI,QAAQ,UAAZ,mBAAmB,OAAO;AAC5B,cAAI,QAAQ,MAAM,MAAM,OAAO;AAAA,QACjC;AACA,wBAAI,SAAQ,eAAZ;AAAA,MACF;AAAA,IACF;AAGA,aAAS,SAAS,IAAY;AAC5B,YAAM,MAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACjD,UAAI,CAAC,OAAO,CAAC,OAAO,IAAI,MAAO;AAE/B,YAAM,MAAM,OAAO,IAAI;AAGvB,YAAM,UAAU,IAAI,MAAM,IAAI,IAAI,MAAM;AACxC,YAAM,SAAS,UAAU;AAGzB,UAAI,cAAc,EAAE,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,OAAA,GAAU,EAAE,UAAU,KAAK;AAAA,IAClF;AAGA,aAAS,WAAW;;AAClB,qBAAS,UAAT,mBAAgB;AAChB,cAAQ,QAAQ,CAAA;AAChB,kBAAY,QAAQ;AAAA,IACtB;AAGA,UAAM,YAAYM,IAAAA,IAAI,KAAK;AAC3B,QAAI,gBAA2C;AAE/C,aAAS,cACP,SACA,cAAc,OACd,WAAgC,WAChC;AACA,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,UAAI,UAAU,OAAO;AAEnB,YAAI,eAAe;AACjB,cAAI,IAAIN,kBAAO,UAAU,OAAO,aAAa;AAC7C,0BAAgB;AAAA,QAClB;AACA,kBAAU,QAAQ;AAAA,MACpB,OAAO;AAEL,kBAAU,QAAQ;AAClB,wBAAgB,CAAC,MAAW;AAE1B,cAAI,KAAa,KAAa;AAE9B,cAAI,EAAE,QAAQ;AACZ,kBAAM,EAAE,OAAO;AACf,kBAAM,EAAE,OAAO;AACf,kBAAM,EAAE,OAAO,OAAO;AAAA,UACxB,WAAW,EAAE,WAAW;AACtB,kBAAM,QAAQA,kBAAO,OAAO,aAAa,cAAc,EAAE,SAAS;AAClE,kBAAMA,kBAAO,OAAO,KAAK,UAAU,MAAM,SAAS;AAClD,kBAAMA,kBAAO,OAAO,KAAK,UAAU,MAAM,QAAQ;AACjD,kBAAM,MAAM,SAAS,IAAI,MAAM,SAAS;AAAA,UAC1C,OAAO;AACL;AAAA,UACF;AAGA,gBAAM,WAAW,MAAM,IAAI,MAAM;AAEjC,gBAAM,MAAM,OAAO;AAAA,YACjB,MAAM,GAAG,WAAW,IAAI0B,YAAU;AAAA,YAClC;AAAA,YACA;AAAA,YACA,KAAK;AAAA,YACL;AAAA,UAAA,CACD;AACD,cAAI,wCAAe;AAEnB,wBAAA;AAAA,QACF;AACA,YAAI,GAAG1B,kBAAO,UAAU,OAAO,aAAa;AAAA,MAC9C;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAGA,WAAS,eAAe,KAAsC;AAC5D,WAAO;AAAA;AAAA,mFAE0E,IAAI,IAAI;AAAA;AAAA,kBAEzE,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,kBAClB,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,kBAClB,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,UAC1B,IAAI,cAAc,gCAAgC,IAAI,WAAW,WAAW,EAAE;AAAA;AAAA;AAAA;AAAA,EAIxF;;;;ACxOA,YAAM,SAAS2B,IAAAA,OAAqB,YAAY;AAChD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4CAA4C;AAGzE,YAAM,MAAM,aAAa,MAAM;AAI/B,YAAM,YAAYC,IAAAA;AAAAA,QAChB,MAAM,OAAO,IAAI;AAAA,QACjB,CAAC,QAAQ;AACP,cAAI,KAAK;AACP,gBAAI,aAAA;AACJ,sBAAA;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,WAAW,KAAA;AAAA,MAAK;AAGpBxB,UAAAA,YAAY,MAAM;AAChB,YAAI,SAAA;AAAA,MACN,CAAC;AAGDiB,UAAAA,QAAQ,cAAc,GAAG;AAGzB,eAAa,GAAG;;eApCdI,eAAQ,KAAA,QAAA,SAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqJV,YAAM,MAAME,IAAAA,OAA2B,YAAY;AACnD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,0CAA0C;AAGpE,YAAM,cAAcrB,IAAAA,IAAI,IAAI;AAC5B,YAAM,iBAAiB,MAAM;AAC3B,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AAGA,YAAM,UAAUA,IAAAA,IAAwB,IAAI;AAC5C,YAAM,aAAaA,IAAAA,IAAI,KAAK;AAG5B,YAAM,MAAMuB,IAAAA,SAAS,EAAE,GAAG,IAAI,GAAG,IAAI;AAErC,UAAI,aAAa;AACjB,UAAI,aAAa;AACjB,UAAI,QAAQ;AACZ,UAAI,QAAQ;AAEZ,eAAS,UAAU,GAAe;AAChC,mBAAW,QAAQ;AACnB,qBAAa,EAAE;AACf,qBAAa,EAAE;AACf,gBAAQ,IAAI;AACZ,gBAAQ,IAAI;AAEZ,iBAAS,iBAAiB,aAAa,MAAM;AAC7C,iBAAS,iBAAiB,WAAW,QAAQ;AAAA,MAC/C;AAEA,eAAS,OAAO,GAAe;AAC7B,YAAI,CAAC,WAAW,MAAO;AACvB,YAAI,IAAI,SAAS,EAAE,UAAU;AAC7B,YAAI,IAAI,SAAS,EAAE,UAAU;AAAA,MAC/B;AAEA,eAAS,WAAW;AAClB,mBAAW,QAAQ;AACnB,iBAAS,oBAAoB,aAAa,MAAM;AAChD,iBAAS,oBAAoB,WAAW,QAAQ;AAAA,MAClD;AAGA,YAAM,aAAa;AAAA,QACjB,EAAE,OAAO,OAAO,OAAO,MAAM,MAAM,WAAW,OAAO,OAAA;AAAA,QACrD,EAAE,OAAO,WAAW,OAAO,MAAM,MAAM,iBAAiB,OAAO,UAAA;AAAA,QAC/D;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,QAET,EAAE,OAAO,QAAQ,OAAO,MAAM,MAAM,kBAAkB,OAAO,UAAA;AAAA,MAAU;AAGzE,YAAM,iBAAiBvB,IAAAA,IAAY,KAAK;AAExC,YAAM,eAAeL,IAAAA,SAAS,MAAM;AAClC,YAAI,eAAe,UAAU,MAAO,QAAO,IAAI,QAAQ;AACvD,eAAO,IAAI,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,eAAe,KAAK;AAAA,MAC5E,CAAC;AAED,YAAM,mBAAmB,CAAC,QAA6B;AACrD,cAAM,MAA8B;AAAA,UAClC,SAAS;AAAA,UACT,SAAS;AAAA,UACT,MAAM;AAAA,QAAA;AAER,eAAO,IAAI,GAAG,KAAK;AAAA,MACrB;AAGA,YAAM,cAAcK,IAAAA,IAAyB,SAAS;AAEtD,eAAS,YAAY;AACnB,YAAI;AAAA,UACF;AAAA;AAAA,UACA;AAAA,UACA,YAAY;AAAA,QAAA;AAAA,MAEhB;AAGA,eAAS,SAAS,IAAY;AAC5B,YAAI,UAAU,IAAI,IAAI;AAAA,MACxB;AAEA,eAAS,QAAQ,IAAY;AAC3B,YAAI,SAAS,EAAE;AAAA,MACjB;AAEA,eAAS,SAAS,IAAY;AAC5B,YAAI,UAAU,EAAE;AAAA,MAClB;AAGA,YAAM,YAAYA,IAAAA,IAAmB,IAAI;AACzC,YAAM,WAAWA,IAAAA,IAAI,EAAE;AACvB,YAAM,cAAcA,IAAAA,IAA6B,IAAI;AAErD,eAAS,UAAU,MAAe;AAChC,kBAAU,QAAQ,KAAK;AACvB,iBAAS,QAAQ,KAAK;AAEtB,mBAAW,MAAA;;AAAM,mCAAY,UAAZ,mBAAmB;AAAA,WAAU,EAAE;AAAA,MAClD;AAEA,eAAS,WAAW;AAClB,YAAI,UAAU,SAAS,SAAS,MAAM,QAAQ;AAC5C,cAAI,cAAc,UAAU,OAAO,SAAS,MAAM,MAAM;AAAA,QAC1D;AACA,mBAAA;AAAA,MACF;AAEA,eAAS,aAAa;AACpB,kBAAU,QAAQ;AAClB,iBAAS,QAAQ;AAAA,MACnB;AAEA,eAAS,eAAe;AACtB,YAAI,OAAO,QAAQ,UAAU,IAAI,QAAQ,MAAM,MAAM,OAAO,GAAG;AAC7D,cAAI,SAAA;AAAA,QACN;AAAA,MACF;;gCAzRED,IAAAA,mBAoJM,OAAA;AAAA,mBAnJA;AAAA,UAAJ,KAAI;AAAA,UACJ,OAAKE,IAAAA,eAAA,CAAC,aAAW,EAAA,WACI,YAAA,MAAA,CAAW,CAAA;AAAA,UAC/B,OAAKuB,IAAAA;AAAAA,aAAW,YAAA,QAA+B,EAAA,MAAA,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,SAA6B,EAAA,MAAA,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,KAAA;AAAA,UAAA;AAAA;UAO7HtB,IAAAA,mBAuBM,OAAA;AAAA,YAtBJ,OAAKD,IAAAA,eAAA,CAAC,qBAAmB,EAAA,eACA,WAAA,MAAA,CAAU,CAAA;AAAA,YAClC,+BAAmB,WAAS,CAAA,SAAA,CAAA;AAAA,YAC5B,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAA,QAAU,OAAU,eAAA;AAAA,UAAc;YAG1B,YAAA,SACdU,IAAAA,UAAA,GAAAZ,IAAAA,mBAKM,OALNK,cAKM;AAAA,wCAJJF,IAAAA,mBAA6C,KAAA,EAA1C,OAAM,kCAAA,GAAiC,MAAA,EAAA;AAAA,cAC1CA,IAAAA,mBAES,QAFTG,cAESQ,IAAAA,gBADP,aAAA,MAAa,MAAM,GAAA,CAAA;AAAA,YAAA,wBAIzBd,IAAAA,mBAOWO,IAAAA,UAAA,EAAA,KAAA,KAAA;AAAA,cANTJ,IAAAA,mBAIO,QAJPU,cAIO;AAAA,0CAHLV,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,8DAAG,cAE9B,EAAA;AAAA,gBAAAA,IAAAA,mBAAwD,QAAxDM,cAAwDK,IAAAA,gBAA7B,aAAA,MAAa,MAAM,GAAA,CAAA;AAAA,cAAA;wCAEhDX,IAAAA,mBAA8C,KAAA,EAA3C,OAAM,sCAAkC,MAAA,EAAA;AAAA,YAAA;;UAI/CC,mBAAAD,IAAAA,mBA+GM,OA/GNuB,cA+GM;AAAA,YA7GJvB,IAAAA,mBAgBM,OAhBNwB,cAgBM;AAAA,cAfJxB,IAAAA,mBAOS,UAAA;AAAA,gBANP,2BAAM,OAAK,EAAA,eACcgB,eAAI,UAAU,MAAA,CAAK,CAAA;AAAA,gBAC3C,SAAO;AAAA,cAAA;gBAERhB,IAAAA,mBAAmE,KAAA;AAAA,kBAA/D,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,aAAA,SAAA,CAAA;AAAA,gBAAA;gBAA8BS,IAAAA,gBAAA,MACnEd,oBAAGK,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,SAAA,QAAA,GAAA,CAAA;AAAA,cAAA;cAExBhB,IAAAA,mBAMS,UAAA;AAAA,gBALP,OAAM;AAAA,gBACL,SAAO;AAAA,gBACP,UAAUgB,IAAAA,MAAA,GAAA,EAAI,QAAQ,MAAM,WAAM;AAAA,cAAA;gBAEnChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,oCAAG,QAC7B,EAAA;AAAA,cAAA;;YAIFA,IAAAA,mBAWM,OAXN0B,cAWM;AAAA,gCAVJ7B,IAAAA,mBASOO,IAAAA,UAAA,MAAAC,eARS,YAAU,CAAjB,QAAG;uBADZL,IAAAA,mBASO,QAAA;AAAA,kBAPJ,KAAK,IAAI;AAAA,kBACV,2BAAM,cAAY,EAAA,QACA,yBAAmB,IAAI,MAAA,CAAK,CAAA;AAAA,kBAC7C,SAAK,CAAA,WAAE,eAAA,QAAiB,IAAI;AAAA,gBAAA;kBAE7BA,IAAAA,mBAA6D,KAAA;AAAA,oBAAzD,OAAKD,IAAAA,eAAA,CAAA,MAAS,IAAI,IAAI,CAAA;AAAA,oBAAI,OAAKuB,IAAAA,eAAA,EAAA,OAAW,IAAI,OAAK;AAAA,kBAAA;sCAAM,MAC7DX,IAAAA,gBAAG,IAAI,KAAK,GAAA,CAAA;AAAA,gBAAA;;;YAKhBX,IAAAA,mBA2EM,OA3EN2B,eA2EM;AAAA,cA1EJpB,IAAAA,YA+DkBqB,IAAAA,iBAAA,EA/DD,MAAK,cAAU;AAAA,qCAE5B,MAA4B;AAAA,wCAD9B/B,IAAAA,mBA6DMO,IAAAA,UAAA,MAAAC,IAAAA,WA5DW,aAAA,OAAY,CAApB,SAAI;4CADbR,IAAAA,mBA6DM,OAAA;AAAA,sBA3DH,KAAK,KAAK;AAAA,sBACX,OAAKE,IAAAA,eAAA,CAAC,YAAU,EAAA,oBACciB,IAAAA,MAAA,GAAA,EAAI,YAAY,UAAU,KAAK,GAAA,CAAE,CAAA;AAAA,sBAC9D,SAAK,CAAA,WAAE,SAAS,KAAK,EAAE;AAAA,oBAAA;sBAGxBhB,IAAAA,mBAGE,QAAA;AAAA,wBAFA,OAAM;AAAA,wBACL,OAAKsB,IAAAA,eAAA,EAAA,YAAgB,iBAAiB,KAAK,QAAQ,GAAA;AAAA,sBAAA;sBAGtDtB,IAAAA,mBAsBM,OAtBN6B,eAsBM;AAAA,wBAnBI,UAAA,UAAc,KAAK,0CAD3BhC,IAAAA,mBAQE,SAAA;AAAA;0BANA,OAAM;AAAA,uFACG,SAAQ,QAAA;AAAA,0BAChB,WAAO;AAAA,yCAAQ,UAAQ,CAAA,OAAA,CAAA;AAAA,yCACP,YAAU,CAAA,QAAA,CAAA;AAAA,0BAAA;AAAA,0BAC1B,qDAAD,MAAA;AAAA,0BAAA,GAAW,CAAA,MAAA,CAAA;AAAA;mCACP;AAAA,0BAAJ,KAAI;AAAA,wBAAA;2CAJK,SAAA,KAAQ;AAAA,wBAAA,uBAOnBA,IAAAA,mBAMM,OAAA;AAAA;0BAJJ,OAAM;AAAA,0BACL,YAAQiC,IAAAA,cAAA,CAAA,WAAO,UAAU,IAAI,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA,GAE3BnB,IAAAA,gBAAA,KAAK,IAAI,GAAA,IAAAoB,aAAA;AAAA,wBAEd/B,IAAAA,mBAEM,OAFNgC,eAEMrB,IAAAA,gBADD,KAAK,IAAI,QAAO,CAAA,CAAA,IAAM,OAAEA,IAAAA,gBAAG,KAAK,IAAI,QAAO,CAAA,CAAA,GAAA,CAAA;AAAA,sBAAA;sBAKlDX,IAAAA,mBAsBM,OAtBNiC,eAsBM;AAAA,wBArBJjC,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,UAAU,IAAI,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE3B9B,IAAAA,mBAA0B,KAAA,EAAvB,OAAM,eAAA,GAAc,MAAA,EAAA;AAAA,wBAAA;wBAEzBA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,QAAQ,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE5B9B,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,wBAAA;wBAE7BA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,SAAK8B,IAAAA,cAAA,CAAA,WAAO,SAAS,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAE7B9B,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,wBAAA;;;;;;;cAOnB,aAAA,MAAa,WAAM,KAA9BS,IAAAA,aAAAZ,IAAAA,mBAOM,OAPNqC,eAOM;AAAA,4CANJlC,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,gBACtBA,IAAAA,mBAII,KAAA,MAAAW,IAAAA,gBAFAK,IAAAA,MAAA,GAAA,EAAI,UAAU,QAAK,gBAAA,QAAA,GAAA,CAAA;AAAA,cAAA;;;yBA1GS,YAAA,KAAW;AAAA,UAAA;;;;;;ACArD,MAAI,aAAa;AAEV,WAAS,SAAS,QAAsB;AAE7C,UAAM,aAAaJ,IAAAA,WAA6C,IAAI;AAGpE,UAAM,YAAYd,IAAAA,IAAiB,EAAE;AAGrC,UAAM,gBAAgBA,IAAAA,IAAmB,IAAI;AAG7C,UAAM,YAAYA,IAAAA,IAAI,KAAK;AAC3B,UAAM,cAAcA,IAAAA,IAAI,CAAC;AACzB,UAAM,gBAAgBA,IAAAA,IAAI,CAAC;AAC3B,UAAM,mBAAmBA,IAAAA,IAAI,CAAC;AAG9B,UAAM,iBAAiBA,IAAAA,IAAI,KAAK;AAChC,UAAM,mBAAmBA,IAAAA,IAAmB,IAAI;AAGhD,QAAI,gBAAuD;AAI3D,aAAS,iBAAiB;AACxB,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,CAAC,IAAK;AAEV,YAAM,QAAQ,IAAIN,kBAAO,MAAM,aAAA;AAC/B,UAAI,SAAS,KAAK;AAClB,iBAAW,QAAQ;AAAA,IACrB;AAGA,aAAS,kBAAkB,OAAkB;AAC3C,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAGnB,YAAM,YAAY,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE3F,YAAM,OAAO,IAAIA,kBAAO,QAAQ,kBAAkB;AAAA,QAChD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,QAEjB,MAAM,EAAE,SAAS,MAAM,GAAA;AAAA,MAAG,CAC3B;AAED,YAAM,WAAW,IAAI;AACrB,aAAO;AAAA,IACT;AAGA,aAAS,oBAAoB,OAAkB,SAAiB,OAAe;AAC7E,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,SAAS,SAAS,QAAS;AAEhC,YAAM,YAAY,MAAM,OAAO,MAAM,SAAS,QAAQ,CAAC,EACpD,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE/D,YAAM,UAAU,IAAIA,kBAAO,QAAQ,kBAAkB;AAAA,QACnD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,MACjB,CACD;AACD,YAAM,WAAW,OAAO;AAExB,UAAI,CAAC,MAAM,sBAAsB;AAC/B,cAAM,uBAAuB,CAAA;AAAA,MAC/B;AACA,YAAM,qBAAqB,KAAK,OAAO;AAAA,IACzC;AAGA,aAAS,sBAAsB,OAAkB;AAC/C,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO;AAEZ,YAAM,YAAY,MAAM,OAAO,MAAM,gBAAiB;AACtD,UAAI,CAAC,UAAW;AAGhB,UAAI,MAAM,eAAe;AACvB,cAAM,cAAc,WAAW,CAAC,UAAU,KAAK,UAAU,KAAK,UAAU,GAAG;AAAA,MAC7E,OAAO;AACL,cAAM,SAAS,IAAIA,kBAAO,QAAQ,gBAAgB;AAAA,UAChD,UAAU,CAAC,UAAU,KAAK,UAAU,KAAK,UAAU,GAAG;AAAA,UACtD,OAAO;AAAA,YACL,OAAO;AAAA,YACP,OAAO;AAAA,YACP,kBAAkBA,kBAAO,OAAO,iBAAiB;AAAA,YACjD,gBAAgBA,kBAAO,OAAO,eAAe;AAAA,UAAA;AAAA,QAC/C,CACD;AACD,cAAM,WAAW,MAAM;AACvB,cAAM,gBAAgB;AAAA,MACxB;AAAA,IACF;AAGA,aAAS,SAAS,QAAsB,OAAO,MAAM;AACnD,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,SAAS,YAAY;AAChC,YAAM,QAAmB,EAAE,IAAI,MAAM,OAAA;AACrC,YAAM,cAAc,kBAAkB,KAAK;AAC3C,gBAAU,MAAM,KAAK,KAAK;AAC1B,aAAO;AAAA,IACT;AAGA,aAAS,cAAc,OAAO,QAAQ;AACpC,UAAI,iBAAiB,MAAO,cAAA;AAE5B,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,KAAK,YAAY,YAAY;AACnC,YAAM,QAAmB;AAAA,QACvB;AAAA,QACA;AAAA,QACA,QAAQ,CAAA;AAAA,QACR,kBAAkB;AAAA,MAAA;AAEpB,iBAAW,QAAQ;AACnB,gBAAU,MAAM,KAAK,KAAK;AAC1B,uBAAiB,QAAQ;AACzB,qBAAe,QAAQ;AACvB,aAAO;AAAA,IACT;AAGA,aAAS,kBAAkB,IAAY,KAAa,KAAa,MAAM,GAAG;AACxE,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAoB;AAAA,QACxB,MAAM,KAAK,IAAA;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEF,YAAM,OAAO,KAAK,KAAK;AACvB,YAAM,mBAAmB,MAAM,OAAO,SAAS;AAG/C,UAAI,MAAM,OAAO,WAAW,GAAG;AAC7B,cAAM,cAAc,kBAAkB,KAAK;AAC3C,8BAAsB,KAAK;AAAA,MAC7B,OAAO;AAEL,4BAAoB,OAAO,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,SAAS,CAAC;AAC3E,8BAAsB,KAAK;AAAA,MAC7B;AAGA,UAAI,OAAO,IAAI,OAAO;AACpB,eAAO,IAAI,MAAM;AAAA,UACf,CAAC,KAAK,KAAK,MAAM,EAAE;AAAA,UACnB,EAAE,QAAQ,KAAK,UAAU,IAAA;AAAA,QAAI;AAAA,MAEjC;AAAA,IACF;AAGA,aAAS,aAAa,IAAa;;AACjC,YAAM,WAAW,MAAM,iBAAiB;AACxC,UAAI,CAAC,SAAU;AAEf,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AAC3D,UAAI,OAAO;AACT,cAAM,mBAAmB;AACzB,YAAI,MAAM,eAAe;AACvB,2BAAW,UAAX,mBAAkB,cAAc,MAAM;AACtC,gBAAM,gBAAgB;AAAA,QACxB;AAAA,MACF;AAEA,UAAI,iBAAiB,UAAU,UAAU;AACvC,yBAAiB,QAAQ;AACzB,uBAAe,QAAQ;AAAA,MACzB;AAAA,IACF;AAGA,aAAS,KAAK,SAAkB;AAC9B,YAAM,KAAK,WAAW,cAAc;AACpC,UAAI,CAAC,GAAI;AAET,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,SAAS,MAAM,OAAO,SAAS,EAAG;AAEvC,UAAI,cAAc,UAAU,IAAI;AAC9B,oBAAY,EAAE;AAAA,MAChB;AAEA,gBAAU,QAAQ;AAClB,yBAAA;AAEA,YAAM,QAAQ,MAAM,OAAO,CAAC,EAAE;AAC9B,YAAM,MAAM,MAAM,OAAO,MAAM,OAAO,SAAS,CAAC,EAAE;AAIlD,sBAAgB,YAAY,MAAM;AAChC,cAAM2C,SAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,YAAI,CAACA,UAAS,CAAC,UAAU,MAAO;AAEhC,cAAM,UAAU,KAAK,IAAA,KAASA,OAAM,kBAAkB,KAAK;AAC3D,cAAM,QAAQ,MAAM;AACpB,cAAM,WAAW,KAAK,IAAI,UAAU,OAAO,CAAC;AAG5C,oBAAY,QAAQ,QAAQ,WAAW;AACvC,yBAAiB,QAAQ,WAAW;AAGpC,cAAM,YAAY,KAAK,MAAM,YAAYA,OAAM,OAAO,SAAS,EAAE;AACjE,4BAAoBA,QAAO,SAAS;AAAA,MACtC,GAAG,EAAE;AAAA,IACP;AAEA,aAAS,oBAAoB,OAAkB,OAAe;;AAC5D,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAO;AAGZ,UAAI,MAAM,aAAa;AACrB,cAAM,cAAc,MAAM,WAAW;AAAA,MACvC;AAGA,YAAM,YAAY,MAAM,OAAO,MAAM,GAAG,QAAQ,CAAC,EAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAA6B;AAE/D,YAAM,cAAc,IAAI3C,kBAAO,QAAQ,kBAAkB;AAAA,QACvD;AAAA,QACA,OAAO;AAAA,UACL,OAAOA,kBAAO,OAAO,MAAM,mBAAmB,SAAS;AAAA,UACvD,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,QAAA;AAAA,MACjB,CACD;AACD,YAAM,WAAW,MAAM,WAAW;AAGlC,YAAM,KAAK,MAAM,OAAO,KAAK;AAC7B,mBAAO,IAAI,UAAX,mBAAkB;AAAA,QAChB,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG;AAAA,QAC7B,EAAE,QAAQ,KAAK,UAAU,EAAA;AAAA;AAAA,IAE7B;AAEA,aAAS,QAAQ;AACf,gBAAU,QAAQ;AAClB,yBAAA;AAAA,IACF;AAEA,aAAS,OAAO;AACd,gBAAU,QAAQ;AAClB,uBAAiB,QAAQ;AACzB,kBAAY,QAAQ;AACpB,yBAAA;AAGA,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,UAAI,SAAS,WAAW,OAAO;AAC7B,YAAI,MAAM,YAAa,YAAW,MAAM,cAAc,MAAM,WAAW;AACvE,cAAM,cAAc,kBAAkB,KAAK;AAAA,MAC7C;AAAA,IACF;AAEA,aAAS,SAAS,OAAe;AAC/B,oBAAc,QAAQ;AACtB,UAAI,UAAU,OAAO;AACnB,cAAA;AACA,aAAA;AAAA,MACF;AAAA,IACF;AAGA,aAAS,KAAK,UAAkB;AAC9B,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc,KAAK;AACtE,UAAI,CAAC,MAAO;AAEZ,YAAM,YAAY,KAAK,MAAO,WAAW,OAAQ,MAAM,OAAO,SAAS,EAAE;AACzE,kBAAY,QAAQ,MAAM,OAAO,SAAS,EAAE;AAC5C,uBAAiB,QAAQ;AACzB,0BAAoB,OAAO,SAAS;AAAA,IACtC;AAGA,aAAS,YAAY,IAAY;AAC/B,oBAAc,QAAQ;AACtB,WAAA;AAAA,IACF;AAGA,aAAS,WAAW,IAAY;AAC9B,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AACrD,UAAI,CAAC,SAAS,CAAC,OAAO,IAAI,MAAO;AAEjC,YAAM,QAAQ,MAAM,OAAO,CAAC;AAC5B,aAAO,IAAI,MAAM;AAAA,QACf,CAAC,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,GAAI;AAAA,QACvC,EAAE,QAAQ,KAAM,UAAU,IAAA;AAAA,MAAI;AAAA,IAElC;AAGA,aAAS,YAAY,IAAY;;AAC/B,YAAM,MAAM,UAAU,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACxD,UAAI,QAAQ,GAAI;AAEhB,YAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,UAAI,MAAM,YAAa,kBAAW,UAAX,mBAAkB,cAAc,MAAM;AAC7D,UAAI,MAAM,cAAe,kBAAW,UAAX,mBAAkB,cAAc,MAAM;AAE/D,UAAI,MAAM,sBAAsB;AAC9B,cAAM,qBAAqB,QAAQ,CAAC,QAAQ;;AAC1C,WAAA4C,MAAA,WAAW,UAAX,gBAAAA,IAAkB,cAAc;AAAA,QAClC,CAAC;AAAA,MACH;AACA,gBAAU,MAAM,OAAO,KAAK,CAAC;AAE7B,UAAI,cAAc,UAAU,IAAI;AAC9B,sBAAc,QAAQ;AACtB,aAAA;AAAA,MACF;AACA,UAAI,iBAAiB,UAAU,IAAI;AACjC,yBAAiB,QAAQ;AACzB,uBAAe,QAAQ;AAAA,MACzB;AAAA,IACF;AAEA,aAAS,WAAW;;AAClB,WAAA;AACA,mBAAA;AACA,uBAAW,UAAX,mBAAkB;AAClB,gBAAU,QAAQ,CAAA;AAClB,oBAAc,QAAQ;AAAA,IACxB;AAGA,aAAS,qBAAqB;AAC5B,UAAI,eAAe;AACjB,sBAAc,aAAa;AAC3B,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;;;;AC3ZA,YAAM,SAASjB,IAAAA,OAAqB,YAAY;AAChD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AAGrE,YAAM,QAAQ,SAAS,MAAM;AAG7B,YAAM,YAAYC,IAAAA;AAAAA,QAChB,MAAM,OAAO,IAAI;AAAA,QACjB,CAAC,QAAQ;AACP,cAAI,KAAK;AACP,kBAAM,eAAA;AACN,sBAAA;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,WAAW,KAAA;AAAA,MAAK;AAGpBxB,UAAAA,YAAY,MAAM;AAChB,cAAM,SAAA;AAAA,MACR,CAAC;AAGDiB,UAAAA,QAAQ,gBAAgB,KAAK;AAG7B,eAAa,KAAK;;eAnChBI,eAAQ,KAAA,QAAA,SAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC2MV,YAAM,QAAQE,IAAAA,OAAuB,cAAc;AACnD,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kCAAkC;AAG9D,YAAM,cAAcrB,IAAAA,IAAI,IAAI;AAC5B,YAAM,aAAaA,IAAAA,IAAI,KAAK;AAC5B,YAAM,MAAMuB,IAAAA,SAAS,EAAE,GAAG,IAAI,GAAG,IAAI;AAErC,UAAI,aAAa,GACf,aAAa,GACb,QAAQ,GACR,QAAQ;AAEV,eAAS,iBAAiB;AACxB,oBAAY,QAAQ,CAAC,YAAY;AAAA,MACnC;AAEA,eAAS,UAAU,GAAe;AAChC,mBAAW,QAAQ;AACnB,qBAAa,EAAE;AACf,qBAAa,EAAE;AACf,gBAAQ,IAAI;AACZ,gBAAQ,IAAI;AACZ,iBAAS,iBAAiB,aAAa,MAAM;AAC7C,iBAAS,iBAAiB,WAAW,QAAQ;AAAA,MAC/C;AACA,eAAS,OAAO,GAAe;AAC7B,YAAI,CAAC,WAAW,MAAO;AACvB,YAAI,IAAI,SAAS,EAAE,UAAU;AAC7B,YAAI,IAAI,SAAS,EAAE,UAAU;AAAA,MAC/B;AACA,eAAS,WAAW;AAClB,mBAAW,QAAQ;AACnB,iBAAS,oBAAoB,aAAa,MAAM;AAChD,iBAAS,oBAAoB,WAAW,QAAQ;AAAA,MAClD;AAGA,eAAS,cAAc,IAAY;AACjC,YAAI,MAAM,cAAc,UAAU,GAAI;AACtC,cAAM,YAAY,EAAE;AACpB,cAAM,KAAA;AAAA,MACR;AAEA,YAAM,kBAAkB5B,IAAAA,SAAS,MAAM;AACrC,cAAM,IAAI,MAAM,UAAU,MAAM;AAAA,UAC9B,CAAC,MAAM,EAAE,OAAO,MAAM,cAAc;AAAA,QAAA;AAEtC,gBAAO,uBAAG,SAAQ;AAAA,MACpB,CAAC;AAED,YAAM,eAAeA,IAAAA,SAAS,MAAM;AAClC,cAAM,IAAI,MAAM,UAAU,MAAM;AAAA,UAC9B,CAAC,MAAM,EAAE,OAAO,MAAM,cAAc;AAAA,QAAA;AAEtC,YAAI,CAAC,KAAK,EAAE,OAAO,SAAS,EAAG,QAAO;AACtC,eAAO,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC,EAAE;AAAA,MACvC,CAAC;AAGD,YAAM,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC;AAGhC,eAAS,OAAO,GAAU;AACxB,cAAM,MAAM,WAAY,EAAE,OAA4B,KAAK;AAC3D,cAAM,KAAK,GAAG;AAAA,MAChB;AAGA,eAAS,WAAW,IAAoB;AACtC,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,IAAI,IAAI,KAAK,EAAE;AACrB,eAAO,GAAG,OAAO,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,EAAE,WAAA,CAAY,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,MAC9F;AAGA,eAAS,eAAe;AAEtB,cAAM,UAAU;AAChB,cAAM,UAAU;AAChB,cAAM,SAAS,CAAA;AACf,YAAI,IAAI,KAAK,IAAA;AAGb,YAAI,UAAU,KAAK,OAAA,IAAW,KAAK,KAAK;AACxC,cAAM,OAAO;AAEb,iBAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,eAAK,MAAO,KAAK,OAAA,IAAW;AAE5B,sBAAY,KAAK,OAAA,IAAW,QAAQ,KAAK,KAAK;AAC9C,gBAAM,UAAU,UAAU,KAAK,IAAI,OAAO,IAAI;AAC9C,gBAAM,UAAU,UAAU,KAAK,IAAI,OAAO,IAAI;AAC9C,gBAAM,MAAM,KAAK,KAAK,IAAK,IAAI,OAAQ,KAAK,EAAE,IAAI;AAClD,iBAAO,KAAK,EAAE,MAAM,GAAG,KAAK,SAAS,KAAK,SAAS,KAAK;AAAA,QAC1D;AAEA,cAAM,SAAS,QAAQ,MAAM,UAAU,EAAE;AAAA,MAC3C;AAEA,UAAI,WAAW;AAGf,UAAI,iBAAwD;AAC5D,UAAI,qBAAoC;AAExC,eAAS,iBAAiB;AACxB,YAAI,MAAM,eAAe,OAAO;AAC9B,uBAAA;AAAA,QACF,OAAO;AACL,wBAAA;AAAA,QACF;AAAA,MACF;AAEA,eAAS,gBAAgB;;AACvB,cAAM,MAAK,WAAM,cAAc,QAAQ,UAAU,EAAE,MAAxC,mBAA2C;AACtD,YAAI,CAAC,GAAI;AACT,6BAAqB;AAGrB,cAAM,aAAa;AACnB,cAAM,aAAa;AAEnB,cAAM,aAAa;AACnB,cAAM,aAAa;AAEnB,cAAM,eAAe;AACrB,cAAM,aAAc,IAAI,KAAK,KAAM;AAEnC,YAAI,QAAQ,KAAK,OAAA,IAAW,IAAI,KAAK;AACrC,YAAI,YAAY;AAEhB,yBAAiB,YAAY,MAAM;AACjC;AAEA,gBAAM,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI;AAC3C,gBAAM,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI;AAC3C,gBAAM,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI;AACvC,gBAAM,kBAAkB,IAAI,KAAK,KAAK,GAAG;AAGzC,mBAAS;AAGT,cAAI,aAAa,cAAc;AAC7B,yBAAA;AAAA,UACF;AAAA,QACF,GAAG,GAAG;AAAA,MACR;AAEA,eAAS,eAAe;AACtB,YAAI,gBAAgB;AAClB,wBAAc,cAAc;AAC5B,2BAAiB;AAAA,QACnB;AACA,YAAI,oBAAoB;AACtB,gBAAM,aAAa,kBAAkB;AACrC,+BAAqB;AAAA,QACvB;AAAA,MACF;AAEA,YAAM,qBAAqBA,IAAAA,SAAS,MAAM;AACxC,cAAM,IAAI,MAAM,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,kBAAkB;AACvE,gBAAO,uBAAG,OAAO,WAAU;AAAA,MAC7B,CAAC;AAGD,eAAS,eAAe;AACtB,YAAI,OAAO,QAAQ,UAAU,MAAM,UAAU,MAAM,MAAM,OAAO,GAAG;AACjE,uBAAA;AACA,gBAAM,SAAA;AAAA,QACR;AAAA,MACF;;gCA5XEI,IAAAA,mBAwMM,OAAA;AAAA,UAvMJ,OAAKE,IAAAA,eAAA,CAAC,eAAa,EAAA,WACE,YAAA,MAAA,CAAW,CAAA;AAAA,UAC/B,kCAAe,IAAI,IAAC,MAAA,KAAc,IAAI,IAAC,KAAA,CAAA;AAAA,QAAA;UAGxCC,IAAAA,mBAoBM,OAAA;AAAA,YAnBJ,OAAKD,IAAAA,eAAA,CAAC,uBAAqB,EAAA,eACF,WAAA,MAAA,CAAU,CAAA;AAAA,YAClC,+BAAmB,WAAS,CAAA,SAAA,CAAA;AAAA,YAC5B,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAE,WAAA,QAAU,OAAU,eAAA;AAAA,UAAc;YAE1B,YAAA,SACdU,IAAAA,UAAA,GAAAZ,IAAAA,mBAGM,OAHN,YAGM;AAAA,wCAFJG,IAAAA,mBAA4C,KAAA,EAAzC,OAAM,iCAAA,GAAgC,MAAA,EAAA;AAAA,cACzCA,IAAAA,mBAAmE,QAAnE,YAAmEW,IAAAA,gBAAtCK,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,MAAM,GAAA,CAAA;AAAA,YAAA,wBAG7DnB,IAAAA,mBAOWO,IAAAA,UAAA,EAAA,KAAA,KAAA;AAAA,cANTJ,IAAAA,mBAIO,QAJP,YAIO;AAAA,0CAHLA,IAAAA,mBAA6B,KAAA,EAA1B,OAAM,kBAAA,GAAiB,MAAA,EAAA;AAAA,8DAAG,UAE7B,EAAA;AAAA,gBAAAA,IAAAA,mBAAmE,QAAnE,YAAmEW,IAAAA,gBAAtCK,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,MAAM,GAAA,CAAA;AAAA,cAAA;wCAE3DhB,IAAAA,mBAA8C,KAAA,EAA3C,OAAM,sCAAkC,MAAA,EAAA;AAAA,YAAA;;UAK/CC,mBAAAD,IAAAA,mBA0KM,OA1KN,YA0KM;AAAA,YAxKJA,IAAAA,mBAqBM,OArBN,YAqBM;AAAA,cApBJA,IAAAA,mBAES,UAAA;AAAA,gBAFD,OAAM;AAAA,gBAAoB,SAAO;AAAA,cAAA;gBACvCA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,oCAAG,UAC1B,EAAA;AAAA,cAAA;cACAA,IAAAA,mBASS,UAAA;AAAA,gBARP,2BAAM,OACEgB,iBAAM,eAAe,QAAK,gBAAA,WAAA,CAAA;AAAA,gBACjC,SAAO;AAAA,cAAA;gBAERhB,IAAAA,mBAEE,KAAA;AAAA,kBADC,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,KAAA,EAAM,eAAe,QAAK,YAAA,SAAA,CAAA;AAAA,gBAAA;gBACzCS,IAAAA,gBAAA,MACFd,oBAAGK,IAAAA,MAAA,KAAA,EAAM,eAAe,QAAK,SAAA,MAAA,GAAA,CAAA;AAAA,cAAA;cAE/BhB,IAAAA,mBAMS,UAAA;AAAA,gBALP,OAAM;AAAA,gBACL,SAAO;AAAA,gBACP,UAAUgB,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,WAAM;AAAA,cAAA;gBAEvChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,cAAA;;YAKagB,UAAA,KAAA,EAAM,cAAc,SAA7DP,IAAAA,aAAAZ,IAAAA,mBA0DM,OA1DN,YA0DM;AAAA,cAxDJG,IAAAA,mBAIM,OAJN,YAIM;AAAA,4CAHJA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,oCAAG,MACxBW,oBAAG,gBAAA,KAAe,IAAG,KACrB,CAAA;AAAA,gBAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAX,IAAAA,mBAA8C,QAAA,EAAxC,OAAM,0BAAuB,QAAI,EAAA;AAAA,cAAA;cAIzCA,IAAAA,mBAeM,OAfN,aAeM;AAAA,gBAdJA,IAAAA,mBAES,UAAA;AAAA,kBAFD,OAAM;AAAA,kBAAY,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBACzChB,IAAAA,mBAAwB,KAAA,EAArB,OAAM,aAAA,GAAY,MAAA,EAAA;AAAA,gBAAA;gBAEvBA,IAAAA,mBAOS,UAAA;AAAA,kBANP,OAAM;AAAA,kBACL,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAQA,IAAAA,MAAA,KAAA,EAAM,UAAUA,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBAE1DhB,IAAAA,mBAEE,KAAA;AAAA,oBADC,OAAKD,IAAAA,eAAA,CAAA,MAASiB,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAK,aAAA,SAAA,CAAA;AAAA,kBAAA;;gBAGxChB,IAAAA,mBAES,UAAA;AAAA,kBAFD,OAAM;AAAA,kBAAY,SAAK,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEgB,IAAAA,MAAA,KAAA,EAAM,KAAA;AAAA,gBAAI;kBACzChB,IAAAA,mBAA2B,KAAA,EAAxB,OAAM,gBAAA,GAAe,MAAA,EAAA;AAAA,gBAAA;;cAK5BA,IAAAA,mBAaM,OAbN,aAaM;AAAA,gBAZJ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAAA,IAAAA,mBAAmC,QAAA,EAA7B,OAAM,cAAA,GAAc,MAAE,EAAA;AAAA,gBAC5BA,IAAAA,mBAUM,OAVN,aAUM;AAAA,oCATJH,IAAAA,mBAQSO,IAAAA,UAAA,MAAAC,eAPK,cAAY,CAAjB,MAAC;2BADVL,IAAAA,mBAQS,UAAA;AAAA,sBANN,KAAK;AAAA,sBACN,OAAKD,IAAAA,eAAA,CAAC,aAAW,EAAA,QACCiB,IAAAA,MAAA,KAAA,EAAM,cAAc,UAAU,EAAA,CAAC,CAAA;AAAA,sBAChD,SAAK,CAAA,WAAEA,IAAAA,MAAA,KAAA,EAAM,SAAS,CAAC;AAAA,oBAAA,GAErBL,IAAAA,gBAAA,CAAC,IAAG,MACT,IAAA,WAAA;AAAA;;;cAKJX,IAAAA,mBAcM,OAdN,aAcM;AAAA,gBAbJA,IAAAA,mBAES,QAFT,aAESW,IAAAA,gBADP,WAAWK,IAAAA,MAAA,KAAA,EAAM,YAAY,KAAK,CAAA,GAAA,CAAA;AAAA,gBAEpChB,IAAAA,mBAQE,SAAA;AAAA,kBAPA,MAAK;AAAA,kBACL,OAAM;AAAA,kBACN,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,MAAK;AAAA,kBACJ,OAAOgB,IAAAA,MAAA,KAAA,EAAM,iBAAiB;AAAA,kBAC9B,SAAO;AAAA,gBAAA;gBAEVhB,uBAA8D,QAA9D,aAA8DW,IAAAA,gBAAlC,WAAW,aAAA,KAAY,CAAA,GAAA,CAAA;AAAA,cAAA;;YAO/CK,IAAAA,MAAA,KAAA,EAAM,eAAe,UAAUA,IAAAA,MAAA,KAAA,EAAM,cAAc,SAF3DP,IAAAA,UAAA,GAAAZ,IAAAA,mBAYM,OAZN,aAYM;AAAA,0CARJG,IAAAA,mBAIM,OAAA,EAJD,OAAM,oBAAgB;AAAA,gBACzBA,IAAAA,mBAAwB,KAAA,EAArB,OAAM,cAAY;AAAA,oCAAG,SAExB;AAAA,gBAAAA,IAAAA,mBAA0B,QAAA,EAApB,OAAM,aAAW;AAAA,cAAA;cAEzBA,IAAAA,mBAEM,OAFN,aAEM;AAAA,gEAFsB,SACtB,EAAA;AAAA,gBAAAA,IAAAA,mBAAyC,oCAA9B,mBAAA,KAAkB,GAAA,CAAA;AAAA,gEAAY,UAC/C,EAAA;AAAA,cAAA;;YAIFA,IAAAA,mBAmEM,OAnEN,aAmEM;AAAA,cAlEJO,IAAAA,YAwDkBqB,IAAAA,iBAAA,EAxDD,MAAK,gBAAY;AAAA,qCAE9B,MAAqC;AAAA,mBADvCnB,IAAAA,UAAA,IAAA,GAAAZ,uBAsDMO,IAAAA,+BArDWY,IAAAA,MAAA,KAAA,EAAM,UAAU,QAAxB,SAAI;4CADbnB,IAAAA,mBAsDM,OAAA;AAAA,sBApDH,KAAK,KAAK;AAAA,sBACX,2BAAM,cAAY;AAAA,wBAC6B,sBAAAmB,IAAAA,MAAA,KAAA,EAAM,cAAc,UAAU,KAAK;AAAA,gDAA2C,KAAK,GAAG,WAAU,UAAA;AAAA,sBAAA;sBAI9I,SAAK,CAAA,WAAE,cAAc,KAAK,EAAE;AAAA,oBAAA;sBAG7BhB,IAAAA,mBAOE,QAAA;AAAA,wBANA,OAAM;AAAA,wBACL,OAAKsB,IAAAA,eAAA;AAAA,sCAAiC,KAAK,GAAG,WAAU,UAAA;;;sBAO3DtB,IAAAA,mBAgBM,OAhBN,aAgBM;AAAA,wBAfJA,IAAAA,mBAQM,OARN,aAQM;AAAA,0BAPJA,IAAAA,mBAKE,KAAA;AAAA,4BAJC,OAAKD,IAAAA,eAAA;AAAA;8BAAoD,KAAK,GAAG,WAAU,UAAA,IAAA,YAAA;AAAA,4BAAA;;8CAI5E,MACFY,IAAAA,gBAAG,KAAK,IAAI,GAAA,CAAA;AAAA,wBAAA;wBAEdX,IAAAA,mBAKM,OALN,aAKM;AAAA,0BAJDyB,IAAAA,gBAAAd,IAAAA,gBAAA,KAAK,OAAO,MAAM,IAAG,QACxB,CAAA;AAAA,0BAAY,KAAK,GAAG,WAAU,UAAA,sBAA9Bd,uBAC8B,QAD9B,aACG,IAAE;;;sBAKTG,IAAAA,mBAeM,OAfN,aAeM;AAAA,wBAdJA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,uCAAYgB,UAAA,KAAA,EAAM,WAAW,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAErChB,IAAAA,mBAA8B,KAAA,EAA3B,OAAM,mBAAA,GAAkB,MAAA,EAAA;AAAA,wBAAA;wBAE7BA,IAAAA,mBAMS,UAAA;AAAA,0BALP,OAAM;AAAA,0BACN,OAAM;AAAA,0BACL,uCAAYgB,UAAA,KAAA,EAAM,YAAY,KAAK,EAAE,GAAA,CAAA,MAAA,CAAA;AAAA,wBAAA;0BAEtChB,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,wBAAA;;;;;;;cAQtBgB,IAAAA,MAAA,KAAA,EAAM,UAAU,MAAM,WAAM,KADpCP,cAAA,GAAAZ,IAAAA,mBAMM,OANN,aAMM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,gBAFJG,IAAAA,mBAAyB,KAAA,EAAtB,OAAM,cAAA,GAAa,MAAA,EAAA;AAAA,gBACtBA,IAAAA,mBAAa,WAAV,UAAM,EAAA;AAAA,cAAA;;;yBAvKyB,YAAA,KAAW;AAAA,UAAA;;;;;;AC4BvD,QAAM,aAAwC;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,IAAA,gBACAqC;AAAAA,IACA;AAAA,IAAA,YACAC;AAAAA,IACA;AAAA,EACF;AAEA,QAAM,WAAW;AAAA,IACf,QAAQ,KAAU,SAA+B;AAC/C,YAAM,UAAS,mCAAS,WAAU;AAClC,iBAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,YAAI,UAAU,SAAS,GAAG,MAAM,GAAG,IAAI,KAAK,MAAM,SAAS;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;;;;;;;;;;;;;;;;;"}