<template>
  <div class="cesium-container">
    <div id="cesiumViewer" ref="cesiumViewer"></div>

    <drawing-toolbar
      :draw-dom-click="drawDomClick"
      :drawing-mode="drawingMode"
      :has-entities="allEntities.length > 0"
      :tool-mode="toolMode"
      @toggle-drawing="toggleDrawing"
      @clear-all="clearAll"
      @export-data="exportData"
      @import-data="importData"
      @locate="handleLocate"
    />
    <measurement-panel
      v-if="measurementResult"
      :result="measurementResult"
      @close="measurementResult = null"
    />
    <hover-tooltip
      v-if="hoverTooltip.visible"
      :visible="hoverTooltip.visible"
      :content="hoverTooltip.content"
      :style="{
        left: hoverTooltip.position.x + 'px',
        top: hoverTooltip.position.y + 'px'
      }"
    />
    <context-menu
      v-if="contextMenu.visible"
      :visible="contextMenu.visible"
      :position="contextMenu.position"
      :entity-data="contextMenu.entityData"
      @delete="deleteEntityFromContextMenu"
      @update-property="updateEntityProperty"
    />
    <!-- 地图右下角：比例尺 + 经纬度 -->
    <div class="map-info-panel">
      <div class="scale-bar">
        <span class="scale-bar-text">{{ scaleBarText }}</span>
        <div class="scale-bar-line" :style="{ width: scaleBarWidthPx + 'px' }">
          <span class="scale-bar-tick scale-bar-tick-left"></span>
          <span class="scale-bar-tick scale-bar-tick-right"></span>
        </div>
      </div>
      <div class="coordinates-display">
        {{ coordinatesText }}
      </div>
    </div>
  </div>
</template>
<script>
import * as Cesium from 'cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'
import DrawingToolbar from './DrawingToolbar.vue'
import MeasurementPanel from './MeasurementPanel.vue'
import HoverTooltip from './HoverTooltip.vue'
import ContextMenu from './ContextMenu.vue'
import axios from 'axios'
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
export default {
  name: 'CesiumMap',
  props: {
    drawDomClick: {
      type: Boolean,
      default: false,
      // 增加 props 类型校验，方便调试
      validator(val) {
        const isBoolean = typeof val === 'boolean'
        if (!isBoolean) {
          console.error('drawDomClick 必须是布尔值，当前值：', val, '类型：', typeof val)
        }
        return isBoolean
      }
    },
    toolMode: {
      type: String,
      default: 'airspace' // 'airspace' or 'ranging'
    },
  },
  watch: {
    drawDomClick: {
      immediate: true, // 组件初始化时立即执行一次
      handler(newVal, oldVal) {
        // 可选：如果需要在值变化时执行额外逻辑（比如初始化地图）
        if (newVal) {
          // this.initMap()
        }
      }
    }
  },
  data() {
    return {
      viewer: null,
      // 绘制相关
      drawingMode: null, // 'point', 'line', 'polygon', 'rectangle', 'circle'
      drawingHandler: null,
      tempEntity: null,      // 最终实体
      tempPreviewEntity: null, // 预览实体（新增）
      drawingPoints: [],
      drawingPointEntities: [], // 存储线绘制时的点实体
      drawingStartPoint: null,
      isDrawing: false,
      activeCursorPosition: null, // 实时鼠标位置
      // 实体管理
      allEntities: [], // 所有绘制的实体
      entityCounter: 0,
      selectedEntity: null, // 当前选中的实体
      // 测量结果
      measurementResult: null,
      // 悬停提示
      hoverTooltip: {
        visible: false,
        content: '',
        position: { x: 0, y: 0 }
      },
      // 右键菜单
      contextMenu: {
        visible: false,
        position: { x: 0, y: 0 },
        entityData: null
      },
      // 默认样式
      defaultStyles: {
        point: { color: '#FF0000', size: 12 },
        line: { color: '#00FF00', width: 3 },
        polygon: { color: '#0000FF', opacity: 0.5, width: 2 },
        rectangle: { color: '#FFA500', opacity: 0.3, width: 2 },
        circle: { color: '#800080', opacity: 0.4, width: 2 },
        sector: { color: '#FF6347', opacity: 0.5, width: 2 },
        arrow: { color: '#FF0000', width: 6 },
        text: { color: '#000000', font: '48px Microsoft YaHei, PingFang SC, sans-serif', backgroundColor: 'rgba(255, 255, 255, 0.8)' },
        image: { width: 150, height: 150 }
      },
      // 鼠标经纬度
      coordinatesText: '经度: --, 纬度: --',
      // 比例尺（高德风格）
      scaleBarText: '--',
      scaleBarWidthPx: 80
    }
  },
  components: {
    DrawingToolbar,
    MeasurementPanel,
    HoverTooltip,
    ContextMenu
  },
  mounted() {
    console.log(this.drawDomClick,999999)
    // this.initMap()
    this.checkCesiumLoaded()
  },
  beforeDestroy() {
    // 销毁鼠标悬停事件处理器
    if (this.hoverHandler) {
      this.hoverHandler.destroy();
      this.hoverHandler = null;
    }
    this.destroyViewer()
  },
  methods: {
    preventContextMenu(e) {
      e.preventDefault();
    },
    clearAllWaypoints() {
      console.log(">>> [执行深度清理] 正在清除所有航迹残留...");
      // 清除所有带业务标记的实体（点和线）
      const entities = this.viewer.entities.values;
      for (let i = entities.length - 1; i >= 0; i--) {
        const entity = entities[i];
        const props = entity.properties;
        // 航点 (isMissionWaypoint)
        const isWp = props && props.isMissionWaypoint;
        // 航线 (isMissionRouteLine)
        const isLine = props && props.isMissionRouteLine;
        // 绘制时的临时 ID
        const isTemp = entity.id && String(entity.id).includes('temp_wp_');

        if (isWp || isLine || isTemp) {
          this.viewer.entities.remove(entity);
        }
      }
      if (this.tempPreviewEntity) {
        this.viewer.entities.remove(this.tempPreviewEntity);
        this.tempPreviewEntity = null;
      }
      // 清理手动维护的记录数组，只移除与航线相关的实体
      if (this.allEntities) {
        // 过滤掉与航线相关的实体，保留用户绘制的线段等实体
        this.allEntities = this.allEntities.filter(item => {
          // 检查实体是否与航线相关
          const isRouteRelated = item.type === 'route' || item.routeId || 
            (item.entity && item.entity.properties && 
             (item.entity.properties.isMissionWaypoint || item.entity.properties.isMissionRouteLine));
          
          // 如果是航线相关实体，从地图中移除
          if (isRouteRelated && item.entity) {
            this.viewer.entities.remove(item.entity);
            return false;
          }
          
          // 保留非航线相关实体
          return true;
        });
      }
      // 重置坐标缓存
      if (this.drawingPoints) {
        this.drawingPoints = [];
      }

      console.log(">>> [清理完毕] 航迹已清空，用户绘制的实体已保留。");
    },
    updateWaypointGraphicById(dbId, newName) {
      const entities = this.viewer.entities.values;

      // 1. 精确查找
      const target = entities.find(e => {
        // 必须确保实体有 properties 且包含 dbId
        if (e.properties && e.properties.dbId) {
          // 【核心修复】使用 .getValue() 获取包装内的原始值
          // 同时使用 == (非严格等于) 兼容字符串与数字对比
          return e.properties.dbId.getValue() === dbId;
        }
        return false;
      });

      if (target) {
        // 2. 同步修改实体的属性与 Label 文字
        target.name = newName;
        if (target.label) {
          target.label.text = newName;
        }
        console.log(`>>> [地图同步成功] ID:${dbId} 已重命名为: ${newName}`);
      } else {
        // 调试辅助：打印当前地图上所有可用的 ID，看看数据到底对不对
        const availableIds = entities
          .filter(e => e.properties && e.properties.dbId)
          .map(e => e.properties.dbId.getValue());
        console.warn(`>>> [地图同步失败] 尝试匹配 ID: ${dbId}, 但地图现有 ID 列表为:`, availableIds);
      }
    },
    // 新建航线绘制
    startMissionRouteDrawing() {
      this.stopDrawing(); // 停止其他可能存在的绘制
      this.drawingPoints = [];
      let activeCursorPosition = null;
      this.isDrawing = true;
      this.drawingHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
      window.addEventListener('contextmenu', this.preventContextMenu, true);
      // 鼠标移动预览逻辑
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          activeCursorPosition = newPosition;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 左键点击逻辑
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (!position) return;
        this.drawingPoints.push(position);
        const wpIndex = this.drawingPoints.length;
        // 绘制业务航点
        this.viewer.entities.add({
          id: `temp_wp_${wpIndex}`,
          name: `WP${wpIndex}`,
          position: position,
          properties: {
            isMissionWaypoint: true, // 这是一个永久的业务标记
            originalIndex: wpIndex,   // 存下它是第几个点
            temp: true
          },
          point: {
            pixelSize: 10,
            color: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.fromCssColorString('#0078FF'),
            outlineWidth: 3,
            disableDepthTestDistance: Number.POSITIVE_INFINITY // 保证不被地形遮挡
          },
          label: {
            text: `WP${wpIndex}`,
            font: '12px MicroSoft YaHei',
            pixelOffset: new Cesium.Cartesian2(0, -20),
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE
          }
        });
        //  第一次点击后，创建动态黑白斑马线
        if (this.drawingPoints.length === 1) {
          this.tempPreviewEntity = this.viewer.entities.add({
            polyline: {
              positions: new Cesium.CallbackProperty(() => {
                if (this.drawingPoints.length > 0 && activeCursorPosition) {
                  return [...this.drawingPoints, activeCursorPosition];
                }
                return this.drawingPoints;
              }, false),
              width: 4,
              // 黑白斑马材质
              material: new Cesium.PolylineDashMaterialProperty({
                color: Cesium.Color.WHITE,      // 主色：白
                gapColor: Cesium.Color.BLACK,   // 间隙色：黑
                dashLength: 20.0                // 斑马纹长度
              }),
              clampToGround: true
            }
          });
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 右键点击逻辑（结束绘制、抛出数据、恢复右键）
      this.drawingHandler.setInputAction(() => {
        if (this.drawingPoints.length > 1) {
          // 转换坐标并传回给 childRoom/index.vue
          const latLngPoints = this.drawingPoints.map((p, index) => {
            const coords = this.cartesianToLatLng(p);
            return {
              id: index + 1,
              name: `WP${index + 1}`,
              lat: coords.lat,
              lng: coords.lng,
              alt: 500,  // 默认业务属性
              speed: 600 // 默认业务属性
            };
          });
          this.$emit('draw-complete', latLngPoints);
        } else {
          this.$message.info('点数不足，航线已取消');
        }
        // 清理并恢复环境
        this.stopDrawing();
        setTimeout(() => {
          window.removeEventListener('contextmenu', this.preventContextMenu, true);
        }, 200);
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    renderRouteWaypoints(waypoints, routeId = 'default') {
      if (!waypoints || waypoints.length < 1) return;
      const positions = [];
      // 1. 遍历并绘制航点标记
      waypoints.forEach((wp, index) => {
        const lon = parseFloat(wp.lng);
        const lat = parseFloat(wp.lat);
        const pos = Cesium.Cartesian3.fromDegrees(lon, lat, parseFloat(wp.altitude || wp.alt || 500));
        positions.push(pos);
        this.viewer.entities.add({
          id: `wp_${routeId}_${wp.id}`,
          name: wp.name || `WP${index + 1}`,
          position: pos,
          properties: {
            isMissionWaypoint: true,
            routeId: routeId,
            dbId: wp.id,
          },
          point: {
            pixelSize: 10,
            color: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.fromCssColorString('#0078FF'),
            outlineWidth: 3,
            disableDepthTestDistance: Number.POSITIVE_INFINITY
          },
          label: {
            text: wp.name || `WP${index + 1}`,
            font: '12px MicroSoft YaHei',
            pixelOffset: new Cesium.Cartesian2(0, -20),
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE
          }
        });
      });
      // 2. 绘制连线（仅当点数 > 1 时）
      if (positions.length > 1) {
        const routeEntity = this.viewer.entities.add({
          id: `route-line-${routeId}`,
          polyline: {
            positions: positions,
            width: 4,
            material: new Cesium.PolylineDashMaterialProperty({
              color: Cesium.Color.WHITE,
              gapColor: Cesium.Color.BLACK,
              dashLength: 20.0
            }),
            clampToGround: true
          },
          properties: {isMissionRouteLine: true, routeId: routeId}
        });
        this.allEntities.push({id: `route-line-${routeId}`, entity: routeEntity, type: 'line'});
      }
    },
    removeRouteById(routeId) {
      // 从地图上移除所有属于该 routeId 的实体
      const entityList = this.viewer.entities.values;
      for (let i = entityList.length - 1; i >= 0; i--) {
        const entity = entityList[i];
        // 获取 entity 身上绑定的 routeId 属性
        if (entity.properties && entity.properties.routeId) {
          // Cesium 的属性系统比较特殊，需要 getValue() 拿原始值
          const id = entity.properties.routeId.getValue();
          if (id === routeId) {
            this.viewer.entities.remove(entity);
          }
        }
      }
      // 同时清理你本地维护的 allEntities 数组
      this.allEntities = this.allEntities.filter(item => item.id !== routeId);
    },
    checkCesiumLoaded() {
      if (typeof Cesium === 'undefined') {
        console.error('Cesium未加载，请检查CDN链接');
        // 可以设置重试机制
        setTimeout(() => {
          if (typeof Cesium !== 'undefined') {
            this.initMap();
          } else {
            console.error('Cesium加载失败');
          }
        }, 1000);
      } else {
        this.initMap();
      }
    },
    initMap() {
      try {
        // 确保 Cesium 已加载
        Cesium.buildModuleUrl.setBaseUrl(window.CESIUM_BASE_URL)
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJjN2MzMmE5OS01NGU3LTQzOGQtYjdjZi1mNGIwZTFjZjQ0NmEiLCJpZCI6MTQ0MDc2LCJpYXQiOjE2ODU3NjY1OTN9.iCmFY-5WNdvyAT-EO2j-unrFm4ZN9J6aSuB2wElQZ-I'
        this.viewer = new Cesium.Viewer('cesiumViewer', {
          animation: false,
          fullscreenButton: false,
          baseLayerPicker: false,
          navigationInstructionsInitiallyVisible: false,
          geocoder: false,
          homeButton: false,
          infoBox: false,
          sceneModePicker: false,
          selectionIndicator: false,
          timeline: false,
          navigationHelpButton: false,
          sceneMode: Cesium.SceneMode.SCENE2D,
          mapProjection: new Cesium.WebMercatorProjection(),
          imageryProvider: false,
          terrainProvider: new Cesium.EllipsoidTerrainProvider(),
          baseLayer: false
        })
        this.viewer.cesiumWidget.creditContainer.style.display = "none"
        this.loadOfflineMap()
        this.setup2DConstraints()
        // 初始视野：中国中心（仅中国瓦片时无需世界瓦片，国外区域会无瓦片显示为空白）
        this.viewer.camera.setView({
          destination: Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 12000000),
          orientation: {
            heading: 0,
            pitch: -Cesium.Math.PI_OVER_TWO,
            roll: 0
          }
        })
        this.initScaleBar()
        this.initPointMovement()
        this.initRightClickHandler()
        this.initHoverHandler()
        this.initMouseCoordinates()
        console.log('Cesium离线二维地图已加载')
        console.log('Cesium离线二维地图已加载')
        // 1. 定义全局拾取处理器
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
        this.handler.setInputAction((click) => {
          // 隐藏右键菜单
          this.contextMenu.visible = false;
          
          if (this.isDrawing) return;

          const pickedObject = this.viewer.scene.pick(click.position);
          if (Cesium.defined(pickedObject) && pickedObject.id) {
            const entity = pickedObject.id;

            // --- 修正后的安全日志 ---
            console.log(">>> [点击检测] 实体ID:", entity.id);

            // 获取属性时必须传入当前仿真时间
            const now = Cesium.JulianDate.now();
            const props = entity.properties ? entity.properties.getValue(now) : null;

            console.log(">>> [点击检测] 业务数据详情:", props);

            if (props && props.isMissionWaypoint) {
              const dbId = props.dbId;
              const routeId = props.routeId;
              console.log(`>>> [地图触发] 点击了点 ${dbId}, 属于航线 ${routeId}`);
              // 关键：把航线 ID 也传给父组件
              this.$emit('open-waypoint-dialog', dbId, routeId);
            }
          }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      } catch (error) {
        console.error('地图错误:', error)
        // 如果Cesium加载失败，显示错误信息
        this.showErrorMessage();
      }
    },
    initRightClickHandler() {
      // 创建屏幕空间事件处理器
      this.rightClickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      // 右键点击事件：显示上下文菜单
      this.rightClickHandler.setInputAction((click) => {
        // 如果正在绘制，不处理右键操作
        if (this.isDrawing) {
          return;
        }
        
        // 隐藏之前可能显示的菜单
        this.contextMenu.visible = false;
        
        const pickedObject = this.viewer.scene.pick(click.position)
        if (Cesium.defined(pickedObject) && pickedObject.id) {
          const pickedEntity = pickedObject.id
          // 查找对应的实体数据
          let entityData = this.allEntities.find(e => e.entity === pickedEntity || e === pickedEntity)
          // 特殊处理：如果点击的是线段上的点，找到对应的线实体
          if (!entityData) {
            // 检查是否是线段上的点
            for (const lineEntity of this.allEntities) {
              if (lineEntity.type === 'line' && lineEntity.pointEntities) {
                if (lineEntity.pointEntities.includes(pickedEntity)) {
                  entityData = lineEntity
                  break
                }
              }
            }
          }
          if (entityData) {
            // 显示上下文菜单
            this.contextMenu = {
              visible: true,
              position: {
                x: click.position.x,
                y: click.position.y
              },
              entityData: entityData
            };
          }
        }
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    },
    // 初始化鼠标悬停事件处理器
    initHoverHandler() {
      // 创建屏幕空间事件处理器
      this.hoverHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      // 鼠标移动事件：检测是否悬停在线上
      this.hoverHandler.setInputAction((movement) => {
        // 如果正在绘制，不处理悬停操作
        if (this.isDrawing) {
          this.hoverTooltip.visible = false;
          return;
        }
        const pickedObject = this.viewer.scene.pick(movement.endPosition)
        if (Cesium.defined(pickedObject) && pickedObject.id) {
          const pickedEntity = pickedObject.id
          // 查找对应的实体数据
          let entityData = this.allEntities.find(e => e.entity === pickedEntity || e === pickedEntity)
          // 特殊处理：如果悬停的是线段上的点，找到对应的线实体
          if (!entityData) {
            // 检查是否是线段上的点
            for (const lineEntity of this.allEntities) {
              if (lineEntity.type === 'line' && lineEntity.pointEntities) {
                if (lineEntity.pointEntities.includes(pickedEntity)) {
                  entityData = lineEntity
                  break
                }
              }
            }
          }
          // 如果是线实体，显示长度信息
          if (entityData && entityData.type === 'line') {
            const length = this.calculateLineLength(entityData.positions)
            // 显示小框提示
            this.hoverTooltip = {
              visible: true,
              content: `长度：${length.toFixed(2)} 米`,
              position: {
                x: movement.endPosition.x + 10,
                y: movement.endPosition.y - 10
              }
            };
          } else {
            // 如果不是线实体，隐藏信息
            this.hoverTooltip.visible = false;
          }
        } else {
          // 如果没有悬停在任何实体上，隐藏信息
          this.hoverTooltip.visible = false;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
    },
    showErrorMessage() {
      const container = document.getElementById('cesiumViewer');
      if (container) {
        container.innerHTML = `
          <div style="
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: #f5f5f5;
            color: #666;
            font-family: Arial, sans-serif;
          ">
            <h3 style="margin-bottom: 20px;">地图加载失败</h3>
            <p>可能的原因：</p>
            <ul style="text-align: left; margin: 10px 0;">
              <li>网络连接问题</li>
              <li>Cesium CDN资源未加载</li>
              <li>浏览器兼容性问题</li>
            </ul>
            <button onclick="location.reload()" style="
              margin-top: 20px;
              padding: 10px 20px;
              background: #4dabf7;
              color: white;
              border: none;
              border-radius: 4px;
              cursor: pointer;
            ">
              重新加载
            </button>
          </div>
        `;
      }
    },
    setup2DConstraints() {
      const scene = this.viewer.scene
      const controller = scene.screenSpaceCameraController
      controller.enableTilt = false
      controller.enableRotate = false
      controller.enableLook = false
      scene.screenSpaceCameraController.maximumPitch = 0
      scene.screenSpaceCameraController.minimumPitch = 0
    },
    loadOfflineMap() {
      this.viewer.imageryLayers.removeAll()
      try {
        // 使用本地瓦片（tiles 目录，结构：z/x/y.png）替代高德在线地图
        const origin = typeof window !== 'undefined' ? window.location.origin : ''
        const tilesUrl = origin + '/tiles/{z}/{x}/{reverseY}.png'
        const tilingScheme = new Cesium.WebMercatorTilingScheme()
        const chinaRect = Cesium.Rectangle.fromDegrees(73.5, 18.0, 135.0, 53.5)
        // 底层：全球 0–8 级（境外和中国在 0–8 级都显示）
        const worldTiles = new Cesium.UrlTemplateImageryProvider({
          url: tilesUrl,
          minimumLevel: 0,
          maximumLevel: 8,
          tilingScheme,
          credit: ''
        })
        this.viewer.imageryLayers.addImageryProvider(worldTiles)
        // 顶层：仅中国范围 0–14 级（中国内可缩放到 14 级，境外不请求）
        const chinaTiles = new Cesium.UrlTemplateImageryProvider({
          url: tilesUrl,
          minimumLevel: 0,
          maximumLevel: 14,
          rectangle: chinaRect,
          tilingScheme,
          credit: ''
        })
        this.viewer.imageryLayers.addImageryProvider(chinaTiles)
      } catch (error) {
        console.error('加载本地瓦片失败:', error)
        this.showGridLayer()
      }
    },
    showGridLayer() {
      const gridProvider = new Cesium.GridImageryProvider()
      this.viewer.imageryLayers.addImageryProvider(gridProvider)
      this.addCoordinateLabels()
    },
    addCoordinateLabels() {
      for (let lon = -180; lon <= 180; lon += 30) {
        for (let lat = -90; lat <= 90; lat += 30) {
          this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(lon, lat),
            label: {
              text: `${lat}°N\n${lon}°E`,
              font: '12px sans-serif',
              fillColor: Cesium.Color.BLACK,
              outlineColor: Cesium.Color.WHITE,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              verticalOrigin: Cesium.VerticalOrigin.CENTER,
              pixelOffset: new Cesium.Cartesian2(10, 0)
            }
          })
        }
      }
    },
    // ================== 绘制功能 ==================
    toggleDrawing(mode) {
      if (mode === null) {
        // 当模式为null时，直接停止绘制
        this.stopDrawing()
        this.drawingMode = null
      } else if (this.drawingMode === mode) {
        // 停止当前绘制
        this.stopDrawing()
        this.drawingMode = null
      } else {
        // 停止之前的绘制
        if (this.drawingMode) {
          this.stopDrawing()
        }
        // 开始新的绘制
        this.drawingMode = mode
        this.startDrawing(mode)
      }
    },
    startDrawing(mode) {
      this.stopDrawing()
      this.drawingPoints = []
      this.drawingStartPoint = null
      this.isDrawing = true
      this.drawingHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      // 根据模式设置不同的鼠标样式和事件
      switch (mode) {
        case 'point':
          this.startPointDrawing()
          break
        case 'line':
          this.startLineDrawing()
          break
        case 'polygon':
          this.startPolygonDrawing()
          break
        case 'rectangle':
          this.startRectangleDrawing()
          break
        case 'circle':
          this.startCircleDrawing()
          break
        case 'sector':
          this.startSectorDrawing()
          break
        case 'arrow':
          this.startArrowDrawing()
          break
        case 'text':
          this.startTextDrawing()
          break
        case 'image':
          this.startImageDrawing()
          break
      }
      this.viewer.scene.canvas.style.cursor = 'crosshair'
      console.log(`开始绘制 ${this.getTypeName(mode)}`)
    },
    stopDrawing() {
      if (this.drawingHandler) {
        this.drawingHandler.destroy();
        this.drawingHandler = null;
      }
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      // 确保也清理预览实体
      if (this.tempPreviewEntity) {
        this.viewer.entities.remove(this.tempPreviewEntity);
        this.tempPreviewEntity = null;
      }
      // 清理点实体
      if (this.drawingPointEntities) {
        this.drawingPointEntities.forEach(pointEntity => {
          this.viewer.entities.remove(pointEntity);
        });
        this.drawingPointEntities = [];
      }
      this.drawingPoints = [];
      this.drawingStartPoint = null;
      this.isDrawing = false;
      this.activeCursorPosition = null;
      // 重新初始化右键点击删除处理器
      if (!this.rightClickHandler) {
        this.initRightClickHandler();
      }
      // 隐藏测量结果和小框提示
      this.measurementResult = null;
      this.hoverTooltip.visible = false;
      this.viewer.scene.canvas.style.cursor = 'default';
    },
    cancelDrawing() {
      // 取消绘制，清理临时实体和状态
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      if (this.tempPreviewEntity) {
        this.viewer.entities.remove(this.tempPreviewEntity);
        this.tempPreviewEntity = null;
      }
      if (this.drawingPointEntities) {
        this.drawingPointEntities.forEach(pointEntity => {
          this.viewer.entities.remove(pointEntity);
        });
        this.drawingPointEntities = [];
      }
      this.drawingPoints = [];
      this.activeCursorPosition = null;
      // 隐藏小框提示
      this.hoverTooltip.visible = false;
    },
    // ********************************************************************
    // 绘制点
    startPointDrawing() {
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position)
        if (position) {
          const {lat, lng} = this.cartesianToLatLng(position)
          this.addPointEntity(lat, lng)
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    },
    // 绘制线
    startLineDrawing() {
      this.drawingPoints = [];
      this.drawingPointEntities = []; // 存储点实体
      // 清除可能存在的旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      if (this.tempPreviewEntity) this.viewer.entities.remove(this.tempPreviewEntity);
      this.tempEntity = null;
      this.tempPreviewEntity = null;
      // 1. 鼠标移动事件：更新坐标变量并实时计算线段长度
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          this.activeCursorPosition = newPosition;
          // 当已经有至少一个点时，实时计算线段长度
          if (this.drawingPoints.length > 0) {
            // 计算从最后一个点到当前鼠标位置的线段长度
            const tempPositions = [...this.drawingPoints, newPosition];
            const length = this.calculateLineLength(tempPositions);
            // 更新小框提示，显示实时长度
            this.hoverTooltip = {
              visible: true,
              content: `长度：${length.toFixed(2)} 米`,
              position: {
                x: movement.endPosition.x + 10,
                y: movement.endPosition.y - 10
              }
            };
          } else {
            // 如果没有点，隐藏提示
            this.hoverTooltip.visible = false;
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 2. 鼠标点击事件：确定点位
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          this.drawingPoints.push(position);
          // 创建点实体并添加到场景中
          this.entityCounter++;
          const pointId = `point_${this.entityCounter}`;
          const pointEntity = this.viewer.entities.add({
            id: pointId,
            position: position,
            point: {
              pixelSize: this.defaultStyles.point.size,
              color: Cesium.Color.fromCssColorString(this.defaultStyles.point.color),
              outlineColor: Cesium.Color.WHITE,
              outlineWidth: 2
            }
          });
          this.drawingPointEntities.push(pointEntity);
          // 移除旧的预览虚线
          if (this.tempPreviewEntity) {
            this.viewer.entities.remove(this.tempPreviewEntity);
            this.tempPreviewEntity = null;
          }
          // 创建或更新实线
          if (this.drawingPoints.length > 1) {
            if (this.tempEntity) {
              this.viewer.entities.remove(this.tempEntity);
            }
            this.tempEntity = this.viewer.entities.add({
              polyline: {
                positions: this.drawingPoints,
                width: this.defaultStyles.line.width,
                material: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
                clampToGround: true
              }
            });
          }
          // 创建新的预览虚线（使用 CallbackProperty 实现实时更新）
          this.tempPreviewEntity = this.viewer.entities.add({
            polyline: {
              positions: new Cesium.CallbackProperty(() => {
                if (this.activeCursorPosition) {
                  return [this.drawingPoints[this.drawingPoints.length - 1], this.activeCursorPosition];
                }
                return [this.drawingPoints[this.drawingPoints.length - 1]];
              }, false),
              width: this.defaultStyles.line.width,
              material: new Cesium.PolylineDashMaterialProperty({
                color: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
                dashLength: 16
              }),
              clampToGround: true
            }
          });
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 3. 右键完成绘制
      this.drawingHandler.setInputAction(() => {
        // 移除临时实体
        if (this.tempPreviewEntity) {
          this.viewer.entities.remove(this.tempPreviewEntity);
          this.tempPreviewEntity = null;
        }
        if (this.tempEntity) {
          this.viewer.entities.remove(this.tempEntity);
          this.tempEntity = null;
        }
        if (this.drawingPoints.length > 1) {
          this.finishLineDrawing();
        } else {
          // 取消绘制时，移除所有点实体
          this.drawingPointEntities.forEach(pointEntity => {
            this.viewer.entities.remove(pointEntity);
          });
          this.drawingPointEntities = [];
          this.cancelDrawing();
        }
        // 重置鼠标位置
        this.activeCursorPosition = null;
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    finishLineDrawing() {
      // 将预览线段转换为最终线段
      if (this.drawingPoints.length > 1) {
        // 移除预览线段
        if (this.tempPreviewEntity) {
          this.viewer.entities.remove(this.tempPreviewEntity);
          this.tempPreviewEntity = null;
        }
        // 创建最终的实线实体
        const entity = this.addLineEntity([...this.drawingPoints], [...this.drawingPointEntities]);
        // 计算长度
        const length = this.calculateLineLength([...this.drawingPoints]);
        // 不显示测量面板，使用小框提示
        // this.measurementResult = {
        //   distance: length,
        //   type: 'line'
        // };
        // 重置绘制点数组，保持绘制状态以继续绘制
        this.drawingPoints = [];
        this.drawingPointEntities = [];
        this.tempEntity = null;
        return entity;
      } else {
        // 取消绘制时，移除所有点实体
        this.drawingPointEntities.forEach(pointEntity => {
          this.viewer.entities.remove(pointEntity);
        });
        this.drawingPointEntities = [];
        this.cancelDrawing();
        return null;
      }
    },
    // 绘制多边形
    startPolygonDrawing() {
      this.drawingPoints = [];
      // 1. 清理旧实体
      // 移除之前可能遗留的实体，确保干净的画布
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      if (this.tempPreviewEntity) this.viewer.entities.remove(this.tempPreviewEntity);
      this.tempEntity = null;
      this.tempPreviewEntity = null;
      // 2. 鼠标移动事件：只负责更新坐标变量，不涉及繁重的绘图逻辑
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          this.activeCursorPosition = newPosition;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 3. 鼠标点击事件：添加关键点
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          this.drawingPoints.push(position);
          // === 关键逻辑：点击第一个点时，创建唯一的“动态多边形” ===
          if (this.drawingPoints.length === 1) {
            this.activeCursorPosition = position; // 初始化鼠标位置
            this.tempEntity = this.viewer.entities.add({
              // --- 填充面配置 ---
              polygon: {
                // hierarchy 使用 CallbackProperty 实现动态填充
                hierarchy: new Cesium.CallbackProperty(() => {
                  // 组合：已确定的点 + 当前鼠标位置
                  if (this.activeCursorPosition) {
                    return new Cesium.PolygonHierarchy([...this.drawingPoints, this.activeCursorPosition]);
                  }
                  return new Cesium.PolygonHierarchy(this.drawingPoints);
                }, false),
                // 使用半透明颜色，方便看到地图底图
                material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
                // 确保贴地
                perPositionHeight: false
              },
              // --- 边框线配置 ---
              polyline: {
                // positions 使用 CallbackProperty 实现动态闭合线
                positions: new Cesium.CallbackProperty(() => {
                  if (this.activeCursorPosition) {
                    // 闭合回路：[所有点, 鼠标位置, 回到起点]
                    return [...this.drawingPoints, this.activeCursorPosition, this.drawingPoints[0]];
                  }
                  return this.drawingPoints;
                }, false),
                width: this.defaultStyles.line.width,
                // 边框使用虚线，表示正在编辑中
                material: new Cesium.PolylineDashMaterialProperty({
                  color: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
                  dashLength: 16
                }),
                clampToGround: true
              }
            });
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 4. 右键完成绘制
      this.drawingHandler.setInputAction(() => {
        if (this.drawingPoints.length >= 3) {
          this.finishPolygonDrawing(); // 调用原有的完成逻辑
        } else {
          this.cancelDrawing(); // 点数不够则取消
        }
        // 重置状态
        this.activeCursorPosition = null;
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    finishPolygonDrawing() {
      const positions = [...this.drawingPoints]
      const entity = this.addPolygonEntity(positions)
      // 计算面积
      const area = this.calculatePolygonArea(positions)
      this.measurementResult = {
        area: area,
        type: 'polygon'
      }
      // 重置绘制点数组，保持绘制状态以继续绘制
      this.drawingPoints = []
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity)
        this.tempEntity = null
      }
      return entity
    },
    // 绘制矩形（优化版：两点定矩形，实时预览）
    startRectangleDrawing() {
      // 重置绘制状态
      this.drawingPoints = []; // 存储起点和终点
      // 1. 清理旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      this.tempEntity = null;
      // 2. 鼠标移动事件：更新鼠标位置
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          this.activeCursorPosition = newPosition;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 3. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          // --- 情况A：第一次点击（确定起点） ---
          if (this.drawingPoints.length === 0) {
            this.drawingPoints.push(position);
            this.activeCursorPosition = position; // 初始化鼠标位置
            // 创建动态预览矩形
            this.tempEntity = this.viewer.entities.add({
              rectangle: {
                // 关键：使用 CallbackProperty 动态计算矩形范围
                coordinates: new Cesium.CallbackProperty(() => {
                  if (this.drawingPoints.length > 0 && this.activeCursorPosition) {
                    // 使用 Cesium 内置工具，根据两个点（对角）自动计算矩形范围
                    return Cesium.Rectangle.fromCartesianArray([this.drawingPoints[0], this.activeCursorPosition]);
                  }
                  return Cesium.Rectangle.fromDegrees(0, 0, 0, 0);
                }, false),
                // 样式：半透明填充 + 边框
                material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
                outline: true,
                outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
                outlineWidth: 2,
                clampToGround: true // 贴地
              }
            });
          }
          // --- 情况B：第二次点击（确定终点） ---
          else if (this.drawingPoints.length === 1) {
            this.drawingPoints.push(position);
            // 停止监听鼠标移动，因为形状已确定
            this.activeCursorPosition = null;
            // 调用完成逻辑
            this.finishRectangleDrawing();
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 4. 右键取消
      this.drawingHandler.setInputAction(() => {
        this.cancelDrawing();
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    finishRectangleDrawing() {
      // 1. 获取最终的矩形范围对象
      const rect = Cesium.Rectangle.fromCartesianArray(this.drawingPoints);
      // 2. 移除动态预览的临时实体
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      // 3. 创建最终显示的静态实体
      this.entityCounter++;
      const id = `rectangle_${this.entityCounter}`;
      const finalEntity = this.viewer.entities.add({
        id: id,
        rectangle: {
          coordinates: rect,
          material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
          outlineWidth: this.defaultStyles.polygon.width,
          clampToGround: true
        }
      });
      // 4. 记录到实体列表
      const entityData = {
        id: id,
        type: 'rectangle',
        points: this.drawingPoints.map(p => this.cartesianToLatLng(p)),
        positions: this.drawingPoints,
        entity: finalEntity,
        color: this.defaultStyles.polygon.color,
        opacity: this.defaultStyles.polygon.opacity,
        width: this.defaultStyles.polygon.width,
        label: `矩形 ${this.entityCounter}`
      };
      this.allEntities.push(entityData);
      // 5. 计算并显示面积
      const area = this.calculateRectangleArea(rect);
      this.measurementResult = {
        area: area,
        type: 'rectangle'
      };
      // 6. 重置状态，保持绘制状态以继续绘制
      this.drawingPoints = [];
    },
    // 计算矩形面积（辅助方法）
    calculateRectangleArea(rectangle) {
      // 获取地球椭球体对象
      const ellipsoid = this.viewer.scene.globe.ellipsoid;
      // 方法一：使用 Cesium 几何管道计算（更精确，但需要特定模块支持）
      // const geometry = new Cesium.RectangleGeometry({ rectangle: rectangle });
      // const geometryInstance = Cesium.RectangleGeometry.createGeometry(geometry);
      // ...比较复杂
      // 方法二：使用采样估算（简单且足够精确）
      // 获取矩形的四个角（弧度）
      const west = rectangle.west;
      const south = rectangle.south;
      const east = rectangle.east;
      const north = rectangle.north;
      // 计算中心点的纬度
      const centerLat = (south + north) / 2;
      // 计算宽度（东西向距离）：使用余弦定理校正纬度影响
      // 地球半径约为 6378137 米
      const R = 6378137;
      const width = (east - west) * R * Math.cos(centerLat);
      // 计算高度（南北向距离）
      const height = (north - south) * R;
      // 面积 = 宽 * 高
      const area = Math.abs(width * height);
      return area;
    },
    // 绘制圆形
    startCircleDrawing() {
      // 重置绘制状态
      this.drawingPoints = []; // 存储圆心
      this.activeCursorPosition = null;
      // 1. 清理旧实体
      if (this.tempEntity) {
        try {
          this.viewer.entities.remove(this.tempEntity);
        } catch (e) {
          console.warn('Failed to remove temp entity:', e);
        }
        this.tempEntity = null;
      }
      if (this.tempPreviewEntity) {
        try {
          this.viewer.entities.remove(this.tempPreviewEntity);
        } catch (e) {
          console.warn('Failed to remove temp preview entity:', e);
        }
        this.tempPreviewEntity = null;
      }
      // 2. 重置事件处理器
      this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      this.drawingHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
      // 3. 鼠标移动事件
      this.drawingHandler.setInputAction((movement) => {
        try {
          const newPosition = this.getClickPosition(movement.endPosition);
          if (newPosition) {
            this.activeCursorPosition = newPosition;
          }
        } catch (e) {
          console.warn('Mouse move error:', e);
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 4. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        try {
          const position = this.getClickPosition(click.position);
          if (position) {
            // --- 情况A：第一次点击（确定圆心） ---
            if (this.drawingPoints.length === 0) {
              this.drawingPoints.push(position);
              this.activeCursorPosition = position;
              // 创建动态预览圆形
              if (this.tempEntity) {
                try {
                  this.viewer.entities.remove(this.tempEntity);
                } catch (e) {
                  console.warn('Failed to remove existing temp entity:', e);
                }
                this.tempEntity = null;
              }
              // 确保有有效的圆心位置
              if (position) {
                // 先创建一个固定半径的临时圆，避免半径为0的情况
                const initialRadius = 100; // 初始半径设为100米
                this.tempEntity = this.viewer.entities.add({
                  position: position, // 直接使用确定的圆心位置
                  ellipse: {
                    // 关键：使用 CallbackProperty 动态计算半径（半长轴和半短轴）
                    semiMajorAxis: new Cesium.CallbackProperty(() => {
                      try {
                        if (this.activeCursorPosition && this.drawingPoints.length > 0 && this.drawingPoints[0]) {
                          const center = this.drawingPoints[0];
                          const edge = this.activeCursorPosition;
                          if (center && edge && typeof center.x === 'number' && typeof edge.x === 'number') {
                            const distance = Cesium.Cartesian3.distance(center, edge);
                            return isFinite(distance) && distance > 0 ? distance : initialRadius;
                          }
                        }
                        return initialRadius;
                      } catch (e) {
                        return initialRadius;
                      }
                    }, false),
                    semiMinorAxis: new Cesium.CallbackProperty(() => {
                      try {
                        if (this.activeCursorPosition && this.drawingPoints.length > 0 && this.drawingPoints[0]) {
                          const center = this.drawingPoints[0];
                          const edge = this.activeCursorPosition;
                          if (center && edge && typeof center.x === 'number' && typeof edge.x === 'number') {
                            const distance = Cesium.Cartesian3.distance(center, edge);
                            return isFinite(distance) && distance > 0 ? distance : initialRadius;
                          }
                        }
                        return initialRadius;
                      } catch (e) {
                        return initialRadius;
                      }
                    }, false),
                    // 样式设置
                    material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(0.5),
                    outline: true,
                    outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
                    outlineWidth: 2,
                    // height: 0, // 如果需要贴地可开启或使用 heightReference
                  }
                });
              }
            }
            // --- 情况B：第二次点击（确定边缘/半径） ---
            else if (this.drawingPoints.length === 1) {
              // 记录边缘点（虽然圆只需要圆心和半径，但记录下来方便后续处理）
              this.drawingPoints.push(position);
              this.activeCursorPosition = null; // 停止动态更新
              // 传递边缘点位置去结束绘制
              this.finishCircleDrawing(position);
            }
          }
        } catch (e) {
          console.warn('Mouse click error:', e);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 5. 右键取消
      this.drawingHandler.setInputAction(() => {
        try {
          this.cancelDrawing();
        } catch (e) {
          console.warn('Right click error:', e);
        }
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    finishCircleDrawing(edgePosition) {
      const centerPoint = this.drawingPoints[0];
      // 1. 计算最终半径
      const radius = Cesium.Cartesian3.distance(centerPoint, edgePosition);
      // 2. 移除动态预览实体
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      // 3. 创建最终显示的静态实体
      this.entityCounter++;
      const id = `circle_${this.entityCounter}`;
      const finalEntity = this.viewer.entities.add({
        id: id,
        position: centerPoint,
        ellipse: {
          semiMajorAxis: radius,
          semiMinorAxis: radius,
          material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color).withAlpha(this.defaultStyles.polygon.opacity),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
          outlineWidth: this.defaultStyles.polygon.width
        }
      });
      // 4. 记录实体
      const entityData = {
        id: id,
        type: 'circle',
        points: [centerPoint, edgePosition].map(p => this.cartesianToLatLng(p)),
        positions: [centerPoint, edgePosition],
        entity: finalEntity,
        color: this.defaultStyles.polygon.color,
        opacity: this.defaultStyles.polygon.opacity,
        width: this.defaultStyles.polygon.width,
        radius: radius,
        label: `圆形 ${this.entityCounter}`
      };
      this.allEntities.push(entityData);
      // 5. 计算面积 (π * r²) 并显示
      // 半径单位是米，面积单位是平方米
      const area = Math.PI * Math.pow(radius, 2);
      this.measurementResult = {
        radius: radius, // 也可以额外显示半径
        area: area,
        type: 'circle'
      };
      // 6. 重置状态，保持绘制状态以继续绘制
      this.drawingPoints = [];
      this.activeCursorPosition = null;
    },
    // 绘制扇形
    startSectorDrawing() {
      // 重置绘制状态
      this.drawingPoints = []; // 存储圆心、半径端点、角度端点
      // 1. 清理旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      if (this.tempPreviewEntity) this.viewer.entities.remove(this.tempPreviewEntity);
      this.tempEntity = null;
      this.tempPreviewEntity = null;
      // 2. 鼠标移动事件
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          this.activeCursorPosition = newPosition;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 3. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          // --- 情况A：第一次点击（确定圆心） ---
          if (this.drawingPoints.length === 0) {
            this.drawingPoints.push(position);
            this.activeCursorPosition = position;
            // 创建动态预览半径线
            this.tempPreviewEntity = this.viewer.entities.add({
              polyline: {
                positions: new Cesium.CallbackProperty(() => {
                  if (this.drawingPoints.length > 0 && this.activeCursorPosition) {
                    return [this.drawingPoints[0], this.activeCursorPosition];
                  }
                  return [];
                }, false),
                width: this.defaultStyles.sector.width,
                material: new Cesium.PolylineDashMaterialProperty({
                  color: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
                  dashLength: 16
                }),
                clampToGround: true
              }
            });
          }
          // --- 情况B：第二次点击（确定半径） ---
          else if (this.drawingPoints.length === 1) {
            this.drawingPoints.push(position);
            this.activeCursorPosition = position; // 更新 activeCursorPosition 为实际点击位置
            const centerPoint = this.drawingPoints[0];
            const radiusPoint = this.drawingPoints[1];
            const fixedRadius = Cesium.Cartesian3.distance(centerPoint, radiusPoint);
            // 移除半径预览线
            if (this.tempPreviewEntity) {
              this.viewer.entities.remove(this.tempPreviewEntity);
              this.tempPreviewEntity = null;
            }
            // 创建动态预览扇形
            this.tempEntity = this.viewer.entities.add({
              polygon: {
                hierarchy: new Cesium.CallbackProperty(() => {
                  if (this.drawingPoints.length > 1 && this.activeCursorPosition) {
                    const centerPoint = this.drawingPoints[0];
                    const radiusPoint = this.drawingPoints[1];
                    if (!isFinite(fixedRadius) || fixedRadius === 0) {
                      return new Cesium.PolygonHierarchy([]);
                    }
                    const startAngle = this.calculatePointAngle(centerPoint, radiusPoint);
                    const endAngle = this.calculatePointAngle(centerPoint, this.activeCursorPosition);
                    const positions = this.generateSectorPositions(centerPoint, fixedRadius, startAngle, endAngle);
                    return new Cesium.PolygonHierarchy(positions);
                  }
                  return new Cesium.PolygonHierarchy([]);
                }, false),
                material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(0.5),
                outline: true,
                outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
                outlineWidth: this.defaultStyles.sector.width
              }
            });
          }
          // --- 情况C：第三次点击（确定角度） ---
          else if (this.drawingPoints.length === 2) {
            this.drawingPoints.push(position);
            this.activeCursorPosition = null; // 停止动态更新
            // 传递角度点位置去结束绘制
            this.finishSectorDrawing(this.drawingPoints[0], this.drawingPoints[1], this.drawingPoints[2]);
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 4. 右键取消
      this.drawingHandler.setInputAction(() => {
        this.cancelDrawing();
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    // 完成扇形绘制
    finishSectorDrawing(centerPoint, radiusPoint, anglePoint) {
      const radius = Cesium.Cartesian3.distance(centerPoint, radiusPoint);
      const startAngle = this.calculatePointAngle(centerPoint, radiusPoint);
      const endAngle = this.calculatePointAngle(centerPoint, anglePoint);
      // 1. 移除动态预览实体
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      // 2. 生成扇形顶点
      const positions = this.generateSectorPositions(centerPoint, radius, startAngle, endAngle);
      // 3. 创建最终显示的静态实体
      const finalEntity = this.viewer.entities.add({
        id: 'sector-' + new Date().getTime(),
        name: `扇形 ${this.entityCounter}`,
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(positions),
          material: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color).withAlpha(0.5),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.sector.color),
          outlineWidth: this.defaultStyles.sector.width,
          perPositionHeight: false
        }
      });
      // 4. 记录实体
      this.entityCounter++;
      const entityData = {
        id: `sector_${this.entityCounter}`,
        type: 'sector',
        center: this.cartesianToLatLng(centerPoint),
        radius: radius,
        startAngle: startAngle,
        endAngle: endAngle,
        positions: positions,
        entity: finalEntity,
        color: this.defaultStyles.sector.color,
        opacity: 0.5,
        width: this.defaultStyles.sector.width,
        label: `扇形 ${this.entityCounter}`
      };
      this.allEntities.push(entityData);
      // 5. 重置状态，保持绘制状态以继续绘制
      this.drawingPoints = [];
    },
    // 计算角度
    calculateAngle(center, start, end) {
      const startLL = Cesium.Cartographic.fromCartesian(start);
      const endLL = Cesium.Cartographic.fromCartesian(end);
      const centerLL = Cesium.Cartographic.fromCartesian(center);
      // 计算两点相对于圆心的角度
      const startAngle = Math.atan2(startLL.latitude - centerLL.latitude, startLL.longitude - centerLL.longitude);
      const endAngle = Math.atan2(endLL.latitude - centerLL.latitude, endLL.longitude - centerLL.longitude);
      // 返回角度差
      return endAngle - startAngle;
    },
    // 计算角度差
    calculateAngleDiff(center, start, end) {
      const startLL = Cesium.Cartographic.fromCartesian(start);
      const endLL = Cesium.Cartographic.fromCartesian(end);
      const centerLL = Cesium.Cartographic.fromCartesian(center);
      // 计算两点相对于圆心的角度
      const startAngle = Math.atan2(startLL.latitude - centerLL.latitude, startLL.longitude - centerLL.longitude);
      const endAngle = Math.atan2(endLL.latitude - centerLL.latitude, endLL.longitude - centerLL.longitude);
      // 计算角度差（确保为正值）
      let angleDiff = endAngle - startAngle;
      if (angleDiff < 0) {
        angleDiff += 2 * Math.PI;
      }
      // 确保角度差在合理范围内
      return Math.max(0.1, Math.min(Math.PI * 2, angleDiff));
    },
    // 计算点相对于圆心的角度
    calculatePointAngle(center, point) {
      const pointLL = Cesium.Cartographic.fromCartesian(point);
      const centerLL = Cesium.Cartographic.fromCartesian(center);
      // 计算点相对于圆心的角度
      const angle = Math.atan2(pointLL.latitude - centerLL.latitude, pointLL.longitude - centerLL.longitude);
      return angle;
    },
    // 生成扇形顶点位置
    generateSectorPositions(center, radius, startAngle, endAngle) {
      const positions = [];
      const centerLL = Cesium.Cartographic.fromCartesian(center);
      // 添加圆心
      positions.push(center);
      // 计算角度差（顺时针方向）
      let angleDiff = startAngle - endAngle;
      if (angleDiff < 0) {
        angleDiff += 2 * Math.PI;
      }
      // 确保角度差不为零
      angleDiff = Math.max(0.01, angleDiff);
      // 计算扇形的顶点数（根据角度差确定，确保平滑）
      const numPoints = Math.max(5, Math.ceil(angleDiff * 180 / Math.PI / 10));
      const angleStep = angleDiff / (numPoints - 1);
      // 生成扇形的顶点（顺时针方向）
      for (let i = 0; i < numPoints; i++) {
        const currentAngle = startAngle - i * angleStep;
        const distance = radius / 6378137; // 转换为弧度
        const lat = centerLL.latitude + Math.sin(currentAngle) * distance;
        const lng = centerLL.longitude + Math.cos(currentAngle) * distance / Math.cos(centerLL.latitude);
        const position = Cesium.Cartesian3.fromRadians(lng, lat);
        positions.push(position);
      }
      // 闭合扇形
      positions.push(center);
      return positions;
    },
    // 计算两点之间的距离（米）
    calculateDistance(point1, point2) {
      return Cesium.Cartesian3.distance(point1, point2);
    },
    // 绘制箭头
    startArrowDrawing() {
      this.drawingPoints = []; // 存储起点和终点
      // 1. 清理旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      if (this.tempPreviewEntity) this.viewer.entities.remove(this.tempPreviewEntity);
      this.tempEntity = null;
      this.tempPreviewEntity = null;
      // 2. 鼠标移动事件
      this.drawingHandler.setInputAction((movement) => {
        const newPosition = this.getClickPosition(movement.endPosition);
        if (newPosition) {
          this.activeCursorPosition = newPosition;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // 3. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          this.drawingPoints.push(position);
          // --- 情况A：第一次点击（确定起点） ---
          if (this.drawingPoints.length === 1) {
            this.activeCursorPosition = position; // 初始化鼠标位置
            // 创建动态预览箭头
            this.tempPreviewEntity = this.viewer.entities.add({
              polyline: {
                // 使用 CallbackProperty 动态获取位置
                positions: new Cesium.CallbackProperty(() => {
                  // 只有当有点且鼠标位置存在时才渲染
                  if (this.drawingPoints.length > 0 && this.activeCursorPosition) {
                    // 获取最后一个已确认的点
                    const lastPoint = this.drawingPoints[this.drawingPoints.length - 1];
                    // 返回 [最后一个点, 当前鼠标位置]
                    return [lastPoint, this.activeCursorPosition];
                  }
                  return [];
                }, false),
                width: 8, // 增加宽度以获得更大的箭头头部
                // 使用箭头材质
                material: new Cesium.PolylineArrowMaterialProperty(
                  Cesium.Color.fromCssColorString(this.defaultStyles.arrow.color)
                ),
                clampToGround: true, // 贴地
                widthInMeters: false // 使用像素宽度模式
              }
            });
          }
          // --- 情况B：第二次点击（确定终点） ---
          else {
            // 停止监听鼠标移动，因为形状已确定
            this.activeCursorPosition = null;
            // 调用完成逻辑
            this.finishArrowDrawing();
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 4. 右键取消
      this.drawingHandler.setInputAction(() => {
        this.cancelDrawing();
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    // 完成箭头绘制
    finishArrowDrawing() {
      // 将预览箭头转换为最终箭头
      if (this.drawingPoints.length > 1) {
        // 移除预览箭头
        if (this.tempPreviewEntity) {
          this.viewer.entities.remove(this.tempPreviewEntity);
          this.tempPreviewEntity = null;
        }
        // 创建最终的箭头实体
        const entity = this.addArrowEntity([...this.drawingPoints]);
        // 重置绘制点数组，保持绘制状态以继续绘制
        this.drawingPoints = [];
        return entity;
      } else {
        this.cancelDrawing();
        return null;
      }
    },
    // 添加箭头实体
    addArrowEntity(positions) {
      this.entityCounter++
      const id = `arrow_${this.entityCounter}`
      // 创建箭头实体，使用固定宽度以确保等比例放大
      const entity = this.viewer.entities.add({
        id: id,
        name: `箭头 ${this.entityCounter}`,
        polyline: {
          positions: positions,
          width: 8, // 增加宽度以获得更大的箭头头部
          material: new Cesium.PolylineArrowMaterialProperty(
            Cesium.Color.fromCssColorString(this.defaultStyles.arrow.color)
          ),
          clampToGround: true,
          // 使用像素宽度模式，确保箭头在缩放时保持比例
          widthInMeters: false
        }
      })
      const entityData = {
        id,
        type: 'arrow',
        points: positions.map(p => this.cartesianToLatLng(p)),
        positions: positions,
        entity: entity,
        color: this.defaultStyles.arrow.color,
        width: this.defaultStyles.arrow.width,
        label: `箭头 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    // 绘制文本框
    startTextDrawing() {
      // 1. 清理旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      this.tempEntity = null;
      // 2. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          // 弹出输入框，让用户输入文本内容
          const text = prompt('请输入文本内容:', '文本');
          if (text) {
            // 创建文本实体
            this.addTextEntity(position, text);
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 3. 右键取消
      this.drawingHandler.setInputAction(() => {
        this.cancelDrawing();
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    // 添加文本实体
    addTextEntity(position, text) {
      this.entityCounter++
      const id = `text_${this.entityCounter}`
      // 获取经纬度坐标
      const {lat, lng} = this.cartesianToLatLng(position)
      const entity = this.viewer.entities.add({
        id: id,
        name: `文本 ${this.entityCounter}`,
        position: position,
        label: {
          text: text,
          font: this.defaultStyles.text.font,
          fillColor: Cesium.Color.fromCssColorString(this.defaultStyles.text.color),
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          backgroundColor: Cesium.Color.fromCssColorString(this.defaultStyles.text.backgroundColor),
          backgroundPadding: new Cesium.Cartesian2(10, 5),
          pixelOffset: new Cesium.Cartesian2(0, 0),
          // 随地图缩放调整大小
          scaleByDistance: new Cesium.NearFarScalar(
            1000,  // 近距离（米）
            1.0,   // 近距离时的缩放比例
            500000, // 远距离（米）
            0.1    // 远距离时的缩放比例（不为0，保持可见）
          ),
          // 随地图缩放调整透明度
          translucencyByDistance: new Cesium.NearFarScalar(
            1000,  // 近距离（米）
            1.0,   // 近距离时的透明度
            500000, // 远距离（米）
            0.3    // 远距离时的透明度
          )
        }
      })
      const entityData = {
        id,
        type: 'text',
        lat,
        lng,
        text: text,
        position: position,
        entity: entity,
        color: this.defaultStyles.text.color,
        font: this.defaultStyles.text.font,
        backgroundColor: this.defaultStyles.text.backgroundColor,
        label: `文本 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    // 绘制图片
    startImageDrawing() {
      // 1. 清理旧实体
      if (this.tempEntity) this.viewer.entities.remove(this.tempEntity);
      this.tempEntity = null;
      // 2. 鼠标点击事件
      this.drawingHandler.setInputAction((click) => {
        const position = this.getClickPosition(click.position);
        if (position) {
          // 创建一个隐藏的文件输入元素
          const fileInput = document.createElement('input');
          fileInput.type = 'file';
          fileInput.accept = 'image/*';
          // 监听文件选择事件
          fileInput.onchange = (e) => {
            const file = e.target.files[0];
            if (file) {
              // 创建 FormData 对象用于上传
              const formData = new FormData();
              formData.append('file', file);
              // 上传文件到服务器
              this.uploadImage(formData, position);
            }
          };
          // 触发文件选择对话框
          fileInput.click();
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // 3. 右键取消
      this.drawingHandler.setInputAction(() => {
        this.cancelDrawing();
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    },
    // 上传图片
    uploadImage(formData, position) {
      // 显示加载状态
      this.$modal.loading('图片上传中，请稍候...');
      try {
        // 创建请求配置
        const config = {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        };
        // 发送请求 - 使用项目封装的 request 实例
        request.post('/common/upload', formData, config)
          .then((response) => {
            this.$modal.closeLoading();
            if (response.code === 200) {
              // 上传成功，获取图片 URL
              let imageUrl = response.url;
              // 创建图片实体
              this.addImageEntity(position, imageUrl);
            } else {
              this.$modal.msgError('图片上传失败：' + (response.msg || '未知错误'));
            }
          })
          .catch((error) => {
            this.$modal.closeLoading();
            if (error.response) {
              // 服务器返回错误
              if (error.response.data && error.response.data.msg) {
                this.$modal.msgError('图片上传失败：' + error.response.data.msg);
              } else {
                this.$modal.msgError('图片上传失败：服务器返回错误 ' + error.response.status);
              }
            } else if (error.request) {
              // 请求发送但没有收到响应
              this.$modal.msgError('图片上传失败：无法连接到服务器，请检查网络');
            } else {
              // 请求配置错误
              this.$modal.msgError('图片上传失败：' + error.message);
            }
          });
      } catch (error) {
        this.$modal.closeLoading();
        this.$modal.msgError('图片上传失败：' + error.message);
      }
    },
    // 添加图片实体
    addImageEntity(position, imageUrl) {
      this.entityCounter++
      const id = `image_${this.entityCounter}`
      // 获取经纬度坐标
      const {lat, lng} = this.cartesianToLatLng(position)
      const entity = this.viewer.entities.add({
        id: id,
        name: `图片 ${this.entityCounter}`,
        position: position,
        billboard: {
          image: imageUrl,
          width: this.defaultStyles.image.width,
          height: this.defaultStyles.image.height,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          // 随地图缩放调整大小
          scaleByDistance: new Cesium.NearFarScalar(
            1000,  // 近距离（米）
            1.0,   // 近距离时的缩放比例
            500000, // 远距离（米）
            0.1    // 远距离时的缩放比例（不为0，保持可见）
          ),
          // 随地图缩放调整透明度
          translucencyByDistance: new Cesium.NearFarScalar(
            1000,  // 近距离（米）
            1.0,   // 近距离时的透明度
            500000, // 远距离（米）
            0.3    // 远距离时的透明度
          )
        }
      })
      const entityData = {
        id,
        type: 'image',
        lat,
        lng,
        imageUrl: imageUrl,
        position: position,
        entity: entity,
        width: this.defaultStyles.image.width,
        height: this.defaultStyles.image.height,
        label: `图片 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    // ================== 实体创建方法 ==================
    addPointEntity(lat, lng) {
      this.entityCounter++
      const id = `point_${this.entityCounter}`
      const entity = this.viewer.entities.add({
        id: id,
        name: `点 ${this.entityCounter}`,
        position: Cesium.Cartesian3.fromDegrees(lng, lat),
        point: {
          pixelSize: this.defaultStyles.point.size,
          color: Cesium.Color.fromCssColorString(this.defaultStyles.point.color),
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2
        },
        label: {
          text: `${this.entityCounter}`,
          font: '14px Arial',
          fillColor: Cesium.Color.WHITE,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER
        }
      })
      const entityData = {
        id,
        type: 'point',
        lat,
        lng,
        entity: entity,
        color: this.defaultStyles.point.color,
        size: this.defaultStyles.point.size,
        label: `点 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      // 添加点击事件
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    addLineEntity(positions, pointEntities = []) {
      this.entityCounter++
      const id = `line_${this.entityCounter}`
      const entity = this.viewer.entities.add({
        id: id,
        name: `线 ${this.entityCounter}`,
        polyline: {
          positions: positions,
          width: this.defaultStyles.line.width,
          material: Cesium.Color.fromCssColorString(this.defaultStyles.line.color),
          clampToGround: true
        }
      })
      const entityData = {
        id,
        type: 'line',
        points: positions.map(p => this.cartesianToLatLng(p)),
        positions: positions,
        entity: entity,
        pointEntities: pointEntities, // 存储点实体
        color: this.defaultStyles.line.color,
        width: this.defaultStyles.line.width,
        label: `线 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    addPolygonEntity(positions) {
      this.entityCounter++
      const id = `polygon_${this.entityCounter}`
      // 闭合多边形
      const polygonPositions = [...positions, positions[0]]
      const entity = this.viewer.entities.add({
        id: id,
        name: `面 ${this.entityCounter}`,
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(polygonPositions),
          material: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color)
            .withAlpha(this.defaultStyles.polygon.opacity),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.polygon.color),
          outlineWidth: this.defaultStyles.polygon.width
        }
      })
      const entityData = {
        id,
        type: 'polygon',
        points: positions.map(p => this.cartesianToLatLng(p)),
        positions: polygonPositions,
        entity: entity,
        color: this.defaultStyles.polygon.color,
        opacity: this.defaultStyles.polygon.opacity,
        width: this.defaultStyles.polygon.width,
        label: `面 ${this.entityCounter}`
      }
      this.allEntities.push(entityData)
      entity.clickHandler = (e) => {
        this.selectEntity(entityData)
        e.stopPropagation()
      }
      return entityData
    },
    addRectangleEntity(coordinates) {
      this.entityCounter++
      const id = `rectangle_${this.entityCounter}`
      const entity = this.viewer.entities.add({
        id: id,
        name: `矩形 ${this.entityCounter}`,
        rectangle: {
          coordinates: coordinates,
          material: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color)
            .withAlpha(this.defaultStyles.rectangle.opacity),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.rectangle.color),
          outlineWidth: this.defaultStyles.rectangle.width
        }
      })
      // 【重要修改】直接把 entity 推入数组，修复清除功能的 bug
      this.allEntities.push(entity)
      return entity
    },
    addCircleEntity(center, radius) {
      // 确保半径有效
      const validRadius = Math.max(radius, 1)
      this.entityCounter++
      const id = `circle_${this.entityCounter}`
      const entity = this.viewer.entities.add({
        id: id,
        name: `圆形 ${this.entityCounter}`,
        position: center, // 圆心位置
        // 【优化】使用 ellipse (椭圆) 绘制圆形
        ellipse: {
          semiMinorAxis: validRadius, // 半短轴 = 半径
          semiMajorAxis: validRadius, // 半长轴 = 半径
          material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color)
            .withAlpha(this.defaultStyles.circle.opacity),
          outline: true,
          outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color),
          outlineWidth: this.defaultStyles.circle.width
        }
      })
      // 【重要修改】直接把 entity 推入数组
      this.allEntities.push(entity)
      return entity
    },
    // ================== 工具方法 ==================
    getClickPosition(pixelPosition) {
      const cartesian = this.viewer.camera.pickEllipsoid(pixelPosition, this.viewer.scene.globe.ellipsoid)
      return cartesian
    },
    cartesianToLatLng(cartesian) {
      const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
      return {
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        lng: Cesium.Math.toDegrees(cartographic.longitude)
      }
    },
    calculateRectangle(start, end) {
      const startLL = this.cartesianToLatLng(start)
      const endLL = this.cartesianToLatLng(end)
      return Cesium.Rectangle.fromDegrees(
        Math.min(startLL.lng, endLL.lng),
        Math.min(startLL.lat, endLL.lat),
        Math.max(startLL.lng, endLL.lng),
        Math.max(startLL.lat, endLL.lat)
      )
    },
    calculateCircle(center, radius, segments) {
      const positions = []
      const centerLL = Cesium.Cartographic.fromCartesian(center)
      for (let i = 0; i < segments; i++) {
        const angle = (i / segments) * Math.PI * 2
        const lat = centerLL.latitude + (radius / 6378137) * Math.sin(angle)
        const lon = centerLL.longitude + (radius / 6378137) * Math.cos(angle) / Math.cos(centerLL.latitude)
        positions.push(Cesium.Cartesian3.fromRadians(lon, lat))
      }
      return positions
    },
    calculateLineLength(positions) {
      if (!positions || positions.length < 2) {
        return 0;
      }
      let totalLength = 0
      for (let i = 0; i < positions.length - 1; i++) {
        totalLength += Cesium.Cartesian3.distance(positions[i], positions[i + 1])
      }
      return totalLength
    },
    calculatePolygonArea(positions) {
      if (positions.length < 3) return 0
      let area = 0
      const n = positions.length
      for (let i = 0; i < n; i++) {
        const j = (i + 1) % n
        const p1 = Cesium.Cartographic.fromCartesian(positions[i])
        const p2 = Cesium.Cartographic.fromCartesian(positions[j])
        area += p1.longitude * p2.latitude - p2.longitude * p1.latitude
      }
      area = Math.abs(area) * 6378137 * 6378137 / 2
      return area
    },
    // ================== 实体管理 ==================
    selectEntity(entity) {
      this.selectedEntity = entity
      // 居中显示
      if (entity.type === 'point') {
        this.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(entity.lng, entity.lat, 1000),
          duration: 1.0
        })
      } else if (entity.positions && entity.positions.length > 0) {
        const rectangle = Cesium.Rectangle.fromCartographicArray(
          entity.positions.map(p => Cesium.Cartographic.fromCartesian(p))
        )
        this.viewer.camera.flyTo({
          destination: rectangle,
          duration: 1.0
        })
      }
    },
    updateEntityStyle(entityData = null) {
      const data = entityData || this.selectedEntity
      if (!data || !data.entity) return
      const entity = data.entity
      switch (data.type) {
        case 'point':
          if (entity.point) {
            entity.point.color = Cesium.Color.fromCssColorString(data.color)
            entity.point.pixelSize = data.size
          }
          break
        case 'line':
          if (entity.polyline) {
            entity.polyline.material = Cesium.Color.fromCssColorString(data.color)
            entity.polyline.width = data.width
          }
          break
        case 'polygon':
          if (entity.polygon) {
            entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
            entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color)
            entity.polygon.outlineWidth = data.width
          }
          break
        case 'rectangle':
          if (entity.rectangle) {
            entity.rectangle.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
            entity.rectangle.outlineColor = Cesium.Color.fromCssColorString(data.color)
            entity.rectangle.outlineWidth = data.width
          }
          break
        case 'circle':
          if (entity.ellipse) {
            entity.ellipse.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
            entity.ellipse.outlineColor = Cesium.Color.fromCssColorString(data.color)
            entity.ellipse.outlineWidth = data.width
          }
          break
        case 'sector':
          if (entity.polygon) {
            entity.polygon.material = Cesium.Color.fromCssColorString(data.color).withAlpha(data.opacity)
            entity.polygon.outlineColor = Cesium.Color.fromCssColorString(data.color)
            entity.polygon.outlineWidth = data.width
          }
          break
        case 'arrow':
          if (entity.polyline) {
            entity.polyline.material = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(data.color))
            entity.polyline.width = data.width
          }
          break
        case 'text':
          if (entity.label) {
            entity.label.fillColor = Cesium.Color.fromCssColorString(data.color)
            entity.label.font = data.font
          }
          break
      }
    },
    updateEntityLabel() {
      if (!this.selectedEntity || !this.selectedEntity.entity) return
      const entity = this.selectedEntity.entity
      entity.name = this.selectedEntity.label
      // 如果是点，更新标签
      if (this.selectedEntity.type === 'point') {
        entity.label.text = this.selectedEntity.label
      }
    },
    deleteSelectedEntity() {
      if (this.selectedEntity) {
        this.removeEntity(this.selectedEntity.id)
        this.selectedEntity = null
      }
    },
    // 从右键菜单删除实体
    deleteEntityFromContextMenu() {
      if (this.contextMenu.entityData) {
        const entityData = this.contextMenu.entityData
        if (entityData.id) {
          this.removeEntity(entityData.id)
        } else if (entityData.entity && entityData.entity.id) {
          this.removeEntity(entityData.entity.id)
        }
        // 隐藏右键菜单
        this.contextMenu.visible = false
      }
    },
    // 更新实体属性
    updateEntityProperty(property, value) {
      if (this.contextMenu.entityData) {
        const entityData = this.contextMenu.entityData
        // 更新实体数据
        entityData[property] = value
        // 更新实体样式
        this.updateEntityStyle(entityData)
        // 隐藏右键菜单
        this.contextMenu.visible = false
      }
    },
    removeEntity(id) {
      // 查找对应的实体数据
      const index = this.allEntities.findIndex(e =>
        e.id === id ||
        (e.entity && e.entity.id === id) ||
        (e.type === 'line' && e.pointEntities && e.pointEntities.some(p => p.id === id))
      )
      if (index > -1) {
        const entity = this.allEntities[index]
        // 从地图中移除
        if (entity instanceof Cesium.Entity) {
          // 情况 A: 直接是 Cesium Entity 对象
          this.viewer.entities.remove(entity)
        } else if (entity.entity) {
          // 情况 B: 包装对象，包含 entity 属性
          this.viewer.entities.remove(entity.entity)
        }
        // 移除线实体相关的点实体
        if (entity.type === 'line' && entity.pointEntities) {
          entity.pointEntities.forEach(pointEntity => {
            this.viewer.entities.remove(pointEntity)
          })
        }
        // 从数组中移除
        this.allEntities.splice(index, 1)
        // 如果删除的是选中的实体，清空选中状态
        if (this.selectedEntity && (this.selectedEntity.id === id || (this.selectedEntity.entity && this.selectedEntity.entity.id === id))) {
          this.selectedEntity = null
        }
      }
    },
    clearAll() {
      // 1. 检查数组是否有内容
      if (this.allEntities && this.allEntities.length > 0) {
        // 2. 遍历每一个对象进行删除
        this.allEntities.forEach(item => {
          try {
            // 情况 A: 数组里存的是原生的 Cesium Entity (点、线通常是这种情况)
            if (item instanceof Cesium.Entity) {
              this.viewer.entities.remove(item);
            }
            // 情况 B: 数组里存的是包装对象 (你的矩形、圆可能是这种 { entity: ... })
            else if (item.entity && item.entity instanceof Cesium.Entity) {
              this.viewer.entities.remove(item.entity);
            }
            // 情况 C: 兜底方案，尝试通过 ID 删除
            else if (item.id) {
              this.viewer.entities.removeById(item.id);
            }
            // 移除线实体相关的点实体
            if (item.type === 'line' && item.pointEntities) {
              item.pointEntities.forEach(pointEntity => {
                this.viewer.entities.remove(pointEntity);
              });
            }
          } catch (e) {
            console.warn('删除实体失败:', e);
          }
        });
      }
      // 3. 清空数组
      this.allEntities = [];
      // 4. 清理可能残留的绘制过程中的临时图形
      if (this.tempEntity) {
        this.viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }
      if (this.tempPreviewEntity) {
        this.viewer.entities.remove(this.tempPreviewEntity);
        this.tempPreviewEntity = null;
      }
      // 5. 重置其他状态（如测量面板、绘制状态）
      this.measurementResult = null;
      this.stopDrawing();
    },
    // ================== 其他方法 ==================
    getTypeName(type) {
      const names = {
        point: '点',
        line: '线',
        polygon: '面',
        rectangle: '矩形',
        circle: '圆形',
        sector: '扇形',
        arrow: '箭头',
        text: '文本',
        image: '图片'
      }
      return names[type] || type
    },
    exportData() {
      const data = {
        version: '1.0',
        date: new Date().toISOString(),
        entities: this.allEntities.map(entity => ({
          id: entity.id,
          type: entity.type,
          label: entity.label,
          color: entity.color,
          data: entity.type === 'point' ? {
            lat: entity.lat,
            lng: entity.lng
          } : entity.type === 'line' || entity.type === 'polygon' ? {
            points: entity.points
          } : entity.type === 'rectangle' ? {
            coordinates: entity.coordinates
          } : {
            center: entity.center,
            radius: entity.radius
          }
        }))
      }
      const blob = new Blob([JSON.stringify(data, null, 2)], {type: 'application/json'})
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `cesium-drawing-${new Date().toISOString().slice(0, 10)}.json`
      a.click()
      URL.revokeObjectURL(url)
      console.log('数据已导出', data)
    },
    importData() {
      const input = document.createElement('input')
      input.type = 'file'
      input.accept = '.json'
      input.onchange = (e) => {
        const file = e.target.files[0]
        if (!file) return
        const reader = new FileReader()
        reader.onload = (event) => {
          try {
            const data = JSON.parse(event.target.result)
            if (data.entities && Array.isArray(data.entities)) {
              data.entities.forEach(entityData => {
                this.importEntity(entityData)
              })
              console.log('数据已导入', data)
              this.$message.success(`成功导入 ${data.entities.length} 个实体`)
            } else {
              this.$message.error('文件格式不正确')
            }
          } catch (error) {
            console.error('导入失败', error)
            this.$message.error('文件解析失败')
          }
        }
        reader.readAsText(file)
      }
      input.click()
    },
    importEntity(entityData) {
      let entity
      const color = entityData.color || '#008aff'
      switch (entityData.type) {
        case 'point':
          entity = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(entityData.data.lng, entityData.data.lat),
            point: {
              pixelSize: 10,
              color: Cesium.Color.fromCssColorString(color),
              outlineColor: Cesium.Color.WHITE,
              outlineWidth: 2
            },
            label: {
              text: entityData.label || '点',
              font: '14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              pixelOffset: new Cesium.Cartesian2(0, -10)
            }
          })
          break
        case 'line':
          const linePositions = entityData.data.points.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat))
          entity = this.viewer.entities.add({
            polyline: {
              positions: linePositions,
              width: 3,
              material: Cesium.Color.fromCssColorString(color),
              clampToGround: true
            },
            label: {
              text: entityData.label || '线',
              font: '14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              position: linePositions[0]
            }
          })
          break
        case 'polygon':
          const polygonPositions = entityData.data.points.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat))
          entity = this.viewer.entities.add({
            polygon: {
              hierarchy: polygonPositions,
              material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString(color),
              outlineWidth: 2
            },
            label: {
              text: entityData.label || '面',
              font: '14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              position: polygonPositions[0]
            }
          })
          break
        case 'rectangle':
          const rectCoords = entityData.data.coordinates
          entity = this.viewer.entities.add({
            rectangle: {
              coordinates: Cesium.Rectangle.fromDegrees(rectCoords.west, rectCoords.south, rectCoords.east, rectCoords.north),
              material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString(color),
              outlineWidth: 2
            },
            label: {
              text: entityData.label || '矩形',
              font: '14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              position: Cesium.Cartesian3.fromDegrees((rectCoords.west + rectCoords.east) / 2, (rectCoords.south + rectCoords.north) / 2)
            }
          })
          break
        case 'circle':
          // 检查半径是否有效
          const radius = entityData.data.radius || 1000
          if (radius <= 0) {
            this.$message.error('圆形半径必须大于0')
            return
          }
          entity = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(entityData.data.center.lng, entityData.data.center.lat),
            ellipse: {
              semiMinorAxis: radius,
              semiMajorAxis: radius,
              material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString(color),
              outlineWidth: 2
            },
            label: {
              text: entityData.label || '圆形',
              font: '14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              pixelOffset: new Cesium.Cartesian2(0, -10)
            }
          })
          break
      }
      if (entity) {
        this.allEntities.push({
          id: entity.id,
          type: entityData.type,
          label: entityData.label,
          color: color,
          ...entityData.data
        })
      }
    },
    handleLocate() {
      const h = this.$createElement
      this.$msgbox({
        title: '定位',
        message: h('div', {style: 'padding: 10px 0;'}, [
          h('div', {style: 'margin-bottom: 15px;'}, [
            h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '经度：'),
            h('input', {
              attrs: {
                type: 'number',
                placeholder: '例如 116.40',
                step: '0.000001',
                value: '116.3974'
              },
              style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;',
              ref: 'lngInput'
            })
          ]),
          h('div', null, [
            h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '纬度：'),
            h('input', {
              attrs: {
                type: 'number',
                placeholder: '例如 39.90',
                step: '0.000001',
                value: '39.9093'
              },
              style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;',
              ref: 'latInput'
            })
          ])
        ]),
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            const lngInput = instance.$el.querySelector('input[placeholder="例如 116.40"]')
            const latInput = instance.$el.querySelector('input[placeholder="例如 39.90"]')
            const lng = parseFloat(lngInput.value)
            const lat = parseFloat(latInput.value)
            if (!lng || !lat || isNaN(lng) || isNaN(lat)) {
              this.$message.error('请输入有效的经度和纬度！')
              return
            }
            if (lng < -180 || lng > 180 || lat < -90 || lat > 90) {
              this.$message.error('经纬度超出有效范围！')
              return
            }
            if (this.viewer) {
              this.viewer.camera.flyTo({
                destination: Cesium.Cartesian3.fromDegrees(lng, lat, 5000),
                orientation: {
                  heading: Cesium.Math.toRadians(0.0),
                  pitch: Cesium.Math.toRadians(-90.0),
                  roll: 0.0
                },
                duration: 2
              })
              this.$message.success(`已定位到经度 ${lng.toFixed(4)}，纬度 ${lat.toFixed(4)}`)
            }
            done()
          } else {
            this.$message.info('已取消定位')
            done()
          }
        }
      }).catch(() => {
        this.$message.info('已取消定位')
      })
    },
    initScaleBar() {
      const that = this
      const update = () => {
        that.updateScaleBar()
      }
      update()
      this.viewer.camera.changed.addEventListener(update)
      this.viewer.camera.moveEnd.addEventListener(update)
      this.scaleBarCleanup = () => {
        that.viewer.camera.changed.removeEventListener(update)
        that.viewer.camera.moveEnd.removeEventListener(update)
      }
    },
    /** 根据当前视口计算比例尺（兼容 2D/WebMercator，多位置尝试 pick + 视口宽度备用） */
    getScaleBarInfo() {
      if (!this.viewer || !this.viewer.scene.canvas) return null
      const canvas = this.viewer.scene.canvas
      const w = canvas.clientWidth
      const h = canvas.clientHeight
      if (w <= 0 || h <= 0) return null
      const ellipsoid = this.viewer.scene.globe.ellipsoid
      const camera = this.viewer.camera
      const barPx = 80
      const centerX = w / 2
      // 多组参考点尝试（2D 下 pickEllipsoid 可能只在部分区域有效）
      const tryPoints = [
        [centerX - barPx / 2, h - 50],
        [centerX + barPx / 2, h - 50]
      ].concat([
        [centerX - barPx / 2, h / 2],
        [centerX + barPx / 2, h / 2]
      ])
      let leftCartesian = null
      let rightCartesian = null
      leftCartesian = camera.pickEllipsoid(new Cesium.Cartesian2(tryPoints[0][0], tryPoints[0][1]), ellipsoid)
      rightCartesian = camera.pickEllipsoid(new Cesium.Cartesian2(tryPoints[1][0], tryPoints[1][1]), ellipsoid)
      if (!leftCartesian || !rightCartesian) {
        leftCartesian = camera.pickEllipsoid(new Cesium.Cartesian2(tryPoints[2][0], tryPoints[2][1]), ellipsoid)
        rightCartesian = camera.pickEllipsoid(new Cesium.Cartesian2(tryPoints[3][0], tryPoints[3][1]), ellipsoid)
      }
      if (leftCartesian && rightCartesian) {
        const rawMeters = Cesium.Cartesian3.distance(leftCartesian, rightCartesian)
        if (rawMeters > 0) {
          const niceMeters = this.niceScaleValue(rawMeters)
          const widthPx = Math.round((niceMeters / rawMeters) * barPx)
          const text = niceMeters >= 1000 ? `${(niceMeters / 1000).toFixed(0)} 公里` : `${Math.round(niceMeters)} 米`
          return { text, widthPx, niceMeters }
        }
      }
      // 2D/WebMercator 备用：用整屏宽度对应的地理范围计算（四角 pick 得到视口矩形）
      const leftBottom = camera.pickEllipsoid(new Cesium.Cartesian2(0, h - 20), ellipsoid)
      const rightBottom = camera.pickEllipsoid(new Cesium.Cartesian2(w, h - 20), ellipsoid)
      if (leftBottom && rightBottom) {
        const widthMeters = Cesium.Cartesian3.distance(leftBottom, rightBottom)
        if (widthMeters > 0) {
          const metersPerPx = widthMeters / w
          const rawMeters = metersPerPx * barPx
          const niceMeters = this.niceScaleValue(rawMeters)
          const widthPx = Math.round(niceMeters / metersPerPx)
          const text = niceMeters >= 1000 ? `${(niceMeters / 1000).toFixed(0)} 公里` : `${Math.round(niceMeters)} 米`
          return { text, widthPx: Math.min(120, Math.max(40, widthPx)), niceMeters }
        }
      }
      // 最后备用：从 2D 相机视锥估算（正交宽度 -> 米）
      if (this.viewer.scene.mode === Cesium.SceneMode.SCENE2D && camera.frustum && camera.frustum.right !== undefined) {
        const frustumWidth = camera.frustum.right - camera.frustum.left
        if (frustumWidth > 0) {
          const metersPerPx = frustumWidth / w
          const rawMeters = metersPerPx * barPx
          const niceMeters = this.niceScaleValue(rawMeters)
          const widthPx = Math.round(niceMeters / metersPerPx)
          const text = niceMeters >= 1000 ? `${(niceMeters / 1000).toFixed(0)} 公里` : `${Math.round(niceMeters)} 米`
          return { text, widthPx: Math.min(120, Math.max(40, widthPx)), niceMeters }
        }
      }
      return null
    },
    /** 将实际距离圆整为易读的刻度值（米） */
    niceScaleValue(meters) {
      const candidates = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000]
      let best = candidates[0]
      for (let i = 0; i < candidates.length; i++) {
        if (candidates[i] <= meters * 1.5) best = candidates[i]
      }
      return best
    },
    updateScaleBar() {
      const info = this.getScaleBarInfo()
      if (info) {
        this.scaleBarText = info.text
        this.scaleBarWidthPx = Math.min(120, Math.max(40, info.widthPx))
      } else {
        this.scaleBarText = '--'
        this.scaleBarWidthPx = 80
      }
      this.$nextTick()
    },
    initPointMovement() {
      // 创建屏幕空间事件处理器
      this.pointMovementHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      let selectedPoint = null
      let selectedLineEntity = null
      let pointIndex = -1
      let originalCameraController = null
      let isMoving = false
      // 鼠标按下事件：选择点
      this.pointMovementHandler.setInputAction((click) => {
        const pickedObject = this.viewer.scene.pick(click.position)
        if (Cesium.defined(pickedObject) && pickedObject.id) {
          const pickedEntity = pickedObject.id
          // 检查是否点击了点实体
          if (pickedEntity.point) {
            // 查找包含该点的线实体
            for (const lineEntity of this.allEntities) {
              if (lineEntity.type === 'line' && lineEntity.pointEntities) {
                const index = lineEntity.pointEntities.indexOf(pickedEntity)
                if (index !== -1) {
                  selectedPoint = pickedEntity
                  selectedLineEntity = lineEntity
                  pointIndex = index
                  isMoving = true
                  // 禁用相机控制器，使地图固定
                  originalCameraController = this.viewer.scene.screenSpaceCameraController.enableInputs
                  this.viewer.scene.screenSpaceCameraController.enableInputs = false
                  break
                }
              }
            }
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
      // 鼠标移动事件：移动点
      this.pointMovementHandler.setInputAction((movement) => {
        if (isMoving && selectedPoint && selectedLineEntity) {
          const newPosition = this.getClickPosition(movement.endPosition)
          if (newPosition) {
            // 更新点的位置
            selectedPoint.position = newPosition
            // 创建新的位置数组，确保 Cesium 能够检测到变化
            const newPositions = [...selectedLineEntity.positions]
            newPositions[pointIndex] = newPosition
            // 移除旧的线段实体
            this.viewer.entities.remove(selectedLineEntity.entity)
            // 清除所有可能存在的重复线段
            const entitiesToRemove = []
            this.viewer.entities.values.forEach(e => {
              if (e.id && e.id === selectedLineEntity.id) {
                entitiesToRemove.push(e)
              }
            })
            entitiesToRemove.forEach(e => {
              this.viewer.entities.remove(e)
            })
            // 创建新的线段实体
            const newEntity = this.viewer.entities.add({
              id: selectedLineEntity.id,
              name: selectedLineEntity.label,
              polyline: {
                positions: newPositions,
                width: selectedLineEntity.width,
                material: Cesium.Color.fromCssColorString(selectedLineEntity.color),
                clampToGround: true
              }
            })
            // 更新线实体的引用和位置数组
            selectedLineEntity.entity = newEntity
            selectedLineEntity.positions = newPositions
            // 更新点数据
            selectedLineEntity.points[pointIndex] = this.cartesianToLatLng(newPosition)
            // 重新计算距离（只更新线段旁边的小框，不显示右下角弹窗）
            const length = this.calculateLineLength(selectedLineEntity.positions)

            // 强制刷新地图渲染
            this.viewer.scene.requestRender()
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

      // 鼠标释放事件：结束移动
      this.pointMovementHandler.setInputAction(() => {
        // 恢复相机控制器
        if (originalCameraController !== null) {
          this.viewer.scene.screenSpaceCameraController.enableInputs = originalCameraController
          originalCameraController = null
        }


        isMoving = false
        selectedPoint = null
        selectedLineEntity = null
        pointIndex = -1
      }, Cesium.ScreenSpaceEventType.LEFT_UP)
    },

    // 初始化鼠标经纬度显示
    initMouseCoordinates() {
      // 创建屏幕空间事件处理器
      this.mouseCoordinatesHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      // 鼠标移动事件：更新经纬度
      this.mouseCoordinatesHandler.setInputAction((movement) => {
        const cartesian = this.viewer.camera.pickEllipsoid(movement.endPosition, this.viewer.scene.globe.ellipsoid)
        if (cartesian) {
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
          const longitude = Cesium.Math.toDegrees(cartographic.longitude)
          const latitude = Cesium.Math.toDegrees(cartographic.latitude)
          this.coordinatesText = `经度: ${longitude.toFixed(6)}, 纬度: ${latitude.toFixed(6)}`
        } else {
          this.coordinatesText = '经度: --, 纬度: --'
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
    },
    destroyViewer() {
      this.stopDrawing()
      this.clearAll()

      if (this.pointMovementHandler) {
        this.pointMovementHandler.destroy()
        this.pointMovementHandler = null
      }

      if (this.rightClickHandler) {
        this.rightClickHandler.destroy()
        this.rightClickHandler = null
      }

      if (this.mouseCoordinatesHandler) {
        this.mouseCoordinatesHandler.destroy()
        this.mouseCoordinatesHandler = null
      }

      if (typeof this.scaleBarCleanup === 'function') {
        this.scaleBarCleanup()
        this.scaleBarCleanup = null
      }

      if (this.viewer) {
        this.viewer.destroy()
        this.viewer = null
      }
    }
  }
}
</script>

<style scoped>
.cesium-container {
  width: 100vw;
  height: 100vh;
  position: relative;
}

#cesiumViewer {
  width: 100%;
  height: 100%;
}

/* 自定义比例尺样式 */
:deep(.scale-bar-container) {
  user-select: none;
  pointer-events: none;
}

/* 隐藏Cesium的默认控件 */
:deep(.cesium-viewer-bottom) {
  display: none !important;
}

:deep(.cesium-credit-logoContainer) {
  display: none !important;
}

:deep(.cesium-credit-textContainer) {
  display: none !important;
}

/* 地图右下角信息面板：比例尺在上、经纬度在下，整体略下移减少遮挡 */
.map-info-panel {
  position: absolute;
  bottom: 10px;
  right: 12px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  z-index: 1000;
  pointer-events: none;
}

/* 比例尺：高德风格，浅色底、圆角、刻度线 */
.scale-bar {
  background: rgba(255, 255, 255, 0.65);
  color: #333;
  padding: 4px 8px 6px;
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 60px;
}
.scale-bar-text {
  font-size: 12px;
  font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif;
  margin-bottom: 4px;
  color: #555;
}
.scale-bar-line {
  height: 2px;
  background: #555;
  position: relative;
  flex-shrink: 0;
}
.scale-bar-tick {
  position: absolute;
  top: 0;
  width: 2px;
  height: 6px;
  background: #555;
}
.scale-bar-tick-left {
  left: 0;
  top: -4px;
}
.scale-bar-tick-right {
  right: 0;
  left: auto;
  top: -4px;
}

/* 经纬度显示（在比例尺下方） */
.map-info-panel .coordinates-display {
  position: static;
  bottom: auto;
  right: auto;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 13px;
  font-family: Arial, sans-serif;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  min-width: 200px;
  text-align: right;
}
</style>
