<template>
  <div id="controlPanelBox">
    <div>
      <div class="sceneNameBox">
        <div class="">
          场景名称：
          <el-cascader
            :disabled="$route.query.sceneId"
            v-model="SceneValue"
            placeholder="试试搜索：距离"
            :options="SceneList"
            :props="{ expandTrigger: 'hover' }"
            @change="handleChange"
            filterable
          ></el-cascader>
          <el-tooltip
            v-if="SceneValue && SceneRule[SceneValue].functionalDefinition"
            :content="SceneRule[SceneValue].functionalDefinition"
            placement="bottom"
            :popper-style="{ maxWidth: '300px' }"
          >
            <el-icon
              style="margin-left: 1rem; width: 1rem; height: 1rem"
              v-show="SceneValue && SceneRule[SceneValue].functionalDefinition"
              ><QuestionFilled
            /></el-icon>
          </el-tooltip>
        </div>
        <div>
          <el-button type="primary" @click="sendGeometriesToBackend"
            >发送<i class="el-icon-s-promotion el-icon--right"></i
          ></el-button>
        </div>
      </div>
      <el-divider></el-divider>
      <div
        v-if="
          SceneValue &&
          SceneRule[SceneValue] &&
          (SceneRule[SceneValue].elementTypes.includes('point') ||
            SceneRule[SceneValue].elementTypes.includes('polyline') ||
            SceneRule[SceneValue].elementTypes.includes('polygon'))
        "
      >
        元素个数：{{
          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].numberOf : ""
        }}
      </div>
      <div>
        参数类型：{{
          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].elementTypes : ""
        }}
      </div>
      <div>
        接口地址：{{
          SceneValue && SceneRule[SceneValue] ? SceneRule[SceneValue].apiUrl : ""
        }}
      </div>
    </div>
    <el-divider></el-divider>
    <div>
      <!-- 元素文本渲染和操作区域 -->
      <el-tabs tab-position="left" style="height: calc(100vh - 370px)" class="demo-tabs">
        <el-tab-pane label="入参">
          <div
            v-if="
              SceneValue &&
              SceneRule[SceneValue] &&
              SceneRule[SceneValue].elementTypes.includes('file')
            "
          >
            <el-upload
              v-model:file-list="fileList"
              class="upload-demo"
              action=""
              :limit="1"
              :on-change="handleFileChange"
              :on-exceed="handleExceed"
              :on-remove="uploadRemove"
              :auto-upload="false"
            >
              <el-button type="primary">上传文件</el-button>
            </el-upload>
          </div>
          <div v-if="SceneValue && SceneRule[SceneValue]">
            <div
              v-for="item in SceneRule[SceneValue].elementTypes"
              :key="item"
              style="margin-top: 0.5rem"
            >
              <div
                v-if="SceneValue && SceneRule[SceneValue] && SceneRule[SceneValue][item]"
              >
                {{ item }}：<el-select
                  v-if="SceneRule[SceneValue][item]"
                  v-model="params[item]"
                  :placeholder="'请选择' + item"
                  style="width: 240px"
                >
                  <el-option
                    v-for="item in SceneRule[SceneValue][item]"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </div>
              <div v-if="['lon', 'lat', 'filePath', 'EPSILON'].includes(item)">
                {{ item }}:
                <el-input
                  v-model="params[item]"
                  style="width: 240px"
                  :placeholder="'请输入' + item"
                />
              </div>
            </div>
          </div>
          <json-viewer
            v-if="
              SceneValue &&
              SceneRule[SceneValue] &&
              (SceneRule[SceneValue].elementTypes.includes('point') ||
                SceneRule[SceneValue].elementTypes.includes('polyline') ||
                SceneRule[SceneValue].elementTypes.includes('polygon'))
            "
            :value="jsonData"
            :editable="true"
            :preview-mode="false"
            style="
              pointer-events: auto;
              max-height: calc(100vh - 370px) !important;
              overflow-y: scroll !important;
            "
            copyable
            @input="handleJsonInput"
          />
        </el-tab-pane>
        <el-tab-pane label="返回">
          <div
            v-if="backData.message || backData.error"
            :style="{
              backgroundColor: backData.code === 200 ? '#67C23A' : '#F56C6C',
              color: '#fff',
              padding: '5px 10px',
              fontSize: '14px',
            }"
          >
            {{ backData.message || backData.error }}
          </div>
          <json-viewer
            :value="backData.content"
            :editable="true"
            :preview-mode="false"
            style="
              pointer-events: auto;
              max-height: calc(100vh - 370px) !important;
              overflow-y: scroll !important;
            "
            copyable
        /></el-tab-pane>
      </el-tabs>
    </div>
    <!-- 绘制工具栏 -->
    <div
      class="toolbar"
      v-if="
        SceneValue &&
        SceneRule[SceneValue] &&
        (SceneRule[SceneValue].elementTypes.includes('point') ||
          SceneRule[SceneValue].elementTypes.includes('polyline') ||
          SceneRule[SceneValue].elementTypes.includes('polygon'))
      "
    >
      <div
        class="tool-item"
        @click="activateDraw('point')"
        :class="{ active: currentTool === 'point' }"
      >
        绘制点
        <el-tooltip
          content="绘制开关，蓝色状态代表开启，再次点击结束绘制，地图左键点击选点，"
          placement="right"
        >
          <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
        </el-tooltip>
      </div>
      <div
        class="tool-item"
        @click="activateDraw('polyline')"
        :class="{ active: currentTool === 'polyline' }"
      >
        绘制线<el-tooltip
          content="绘制线最少需要两个点，鼠标左键点击选点，点之间自动连线，鼠标右键结束绘制"
          placement="right"
        >
          <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
        </el-tooltip>
      </div>
      <div
        class="tool-item"
        @click="activateDraw('polygon')"
        :class="{ active: currentTool === 'polygon' }"
      >
        绘制面<el-tooltip
          content="绘制面最少需要三个点，鼠标左键点击选点，面自动必合，鼠标右键结束绘制"
          placement="right"
        >
          <el-icon style="width: 1rem; height: 1rem"><QuestionFilled /></el-icon>
        </el-tooltip>
      </div>
      <!-- <div class="tool-item" @click="startHoleDrawing" :class="{ active: isDrawingHole }">
        绘制镂空
      </div> -->
      <div class="tool-item" @click="clearAll">清除所有</div>
    </div>
  </div>
</template>

<script>
import skszk from "../../api/skszk";
// 控制面板
export default {
  name: "ControlPanel",
  // 2. 接收父组件传递的 props（单向数据流，子组件不能直接修改）
  props: {
    btnText: {
      type: String, // 类型限制
      default: "默认按钮", // 默认值
      required: false, // 是否必传
    },
    showCount: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      currentFile: null, // 当前选中的文件
      fileList: [],
      // 其他参数
      params: {
        unit: "",
        outFileType: "",
        outPrj: "",
        inPrj: "",
        lon: "",
        lat: "",
      },
      // 请求参数
      jsonData: {},
      // 返回参数
      backData: {},
      // 当前场景值
      SceneValue: "",
      // 场景列表
      SceneList: [
        {
          value: "1.5.1",
          label: "1.5.1拓扑计算",
          children: [
            {
              value: "1.5.1.1",
              label: "点线面拓扑关系",
            },
          ],
        },
        {
          value: "1.5.2",
          label: "1.5.2空间量算",
          children: [
            {
              value: "1.5.2.1",
              label: "两点欧氏距离",
            },
            {
              value: "1.5.2.2",
              label: "点到线的最短距离",
            },
            {
              value: "1.5.2.3",
              label: "点到面的最短距离",
            },
            {
              value: "1.5.2.4",
              label: "面到面的最短距离",
            },
            {
              value: "1.5.2.5",
              label: "折线距离（累加线段长度）",
            },
            {
              value: "1.5.2.6",
              label: "平面面积、不规则面面积",
            },
            {
              value: "1.5.2.7",
              label: "曲面面积,考虑地形起伏",
            },
            {
              value: "1.5.2.8",
              label: "单点高程查询",
            },
            {
              value: "1.5.2.9",
              label: "两点高程差",
            },
            {
              value: "1.5.2.10",
              label: "区域高程统计",
            },
            {
              value: "1.5.4.5",
              label: "缓冲区计算",
            },
          ],
        },
        {
          value: "1.5.3",
          label: "1.5.3几何运算",
          children: [
            {
              value: "1.5.3.1",
              label: "并集运算",
            },
            {
              value: "1.5.3.2",
              label: "交集运算",
            },
            {
              value: "1.5.3.3",
              label: "差集运算",
            },
            {
              value: "1.5.3.4",
              label: "几何参数计算",
            },
          ],
        },
        {
          value: "1.5.4",
          label: "1.5.4关系分析",
          children: [
            {
              value: "1.5.4.1",
              label: "邻接关系分析",
            },
            {
              value: "1.5.4.2",
              label: "包含关系分析",
            },
            {
              value: "1.5.4.3",
              label: "相交关系分析",
            },
            {
              value: "1.5.4.4",
              label: "相离关系分析",
            },
          ],
        },
        {
          value: "1.5.5",
          label: "1.5.5非空间数据转换",
          children: [
            {
              value: "1.5.5.1",
              label: "非空间数据转空间数据",
            },
          ],
        },
        {
          value: "1.5.6",
          label: "1.5.6坐标转换",
          children: [
            {
              value: "1.5.6.1",
              label: "单点的坐标转换接口",
            },
          ],
        },
        {
          value: "1.5.7",
          label: "1.5.7时空数据格式转换",
          children: [
            {
              value: "1.5.7.1",
              label: "文件格式转换",
            },
            {
              value: "1.5.7.2",
              label: "转换文件下载",
            },
          ],
        },
      ],
      // 场景规则
      SceneRule: {
        "1.5.1.1": {
          // 功能描述
          functionalDefinition:
            "拓扑计算功能聚焦于深度解析大批量数据的点、线、面之间的拓扑关系，能够精准判断点与线、面的位置关系，以及线、面之间的相交、平行、邻接、包含等复杂状态。借助四叉树、R 树等精心设计的数据结构，结合 Douglas - Peucker 等高效算法，确保在处理海量空间数据时，也能快速且准确地输出分析结果。",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/topology/geoJsonToGeoJson",
        },
        "1.5.2.1": {
          // 功能描述
          functionalDefinition:
            "计算两个点要素之间的最短空间距离，单位支持米、千米。操作逻辑为：用户通过接口输入两点经纬度坐标，或在系统内部地图上点击选择两点，系统基于坐标系参数计算欧氏距离。例如：计算青浦区某学校与社区卫生服务中心的直线距离，用于公共服务覆盖半径评估；计算两个监测点位的直线距离，用于监测设备信号覆盖范围判断。",
          // 元素类型
          elementTypes: ["point", "point", "unit"],
          // 单位
          unit: [
            {
              value: "METER",
              label: "米",
            },
            {
              value: "KILOMETER",
              label: "千米",
            },
          ],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/spatialMeasure/pointToPoint",
        },
        "1.5.2.2": {
          // 功能描述
          functionalDefinition: "计算点和线要素之间的最短空间距离，单位支持米、千米",
          // 元素类型
          elementTypes: ["point", "polyline", "unit"],
          // 单位
          unit: [
            {
              value: "METER",
              label: "米",
            },
            {
              value: "KILOMETER",
              label: "千米",
            },
          ],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/spatialMeasure/pointToLine",
        },
        "1.5.2.3": {
          // 功能描述
          functionalDefinition: "计算点和面要素之间的最短空间距离，单位支持米、千米",
          // 元素类型
          elementTypes: ["point", "polygon", "unit"],
          // 单位
          unit: [
            {
              value: "METER",
              label: "米",
            },
            {
              value: "KILOMETER",
              label: "千米",
            },
          ],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/spatialMeasure/pointToPolygon",
        },
        "1.5.2.4": {
          // 功能描述
          functionalDefinition: "计算两个面要素之间的最短空间距离，单位支持米、千米",
          // 元素类型
          elementTypes: ["polygon", "polygon", "unit"],
          // 单位
          unit: [
            {
              value: "METER",
              label: "米",
            },
            {
              value: "KILOMETER",
              label: "千米",
            },
          ],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/spatialMeasure/PolygonToPolygon",
        },
        "1.5.2.5": {
          // 功能描述
          functionalDefinition: "计算多条线段组成的折线总长度，单位支持米、千米",
          // 元素类型
          elementTypes: ["polyline", "unit"],
          // 单位
          unit: [
            {
              value: "METER",
              label: "米",
            },
            {
              value: "KILOMETER",
              label: "千米",
            },
          ],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/spatialMeasure/calculatePolylineDistance",
        },
        "1.5.2.6": {
          // 功能描述
          functionalDefinition:
            "计算面要素在二维平面上的投影面积，单位支持平方米、公顷、平方千米切换",
          // 元素类型
          elementTypes: ["polygon", "unit"],
          // 单位
          unit: [
            {
              value: "SQUARE_METER",
              label: "平方米",
            },
            {
              value: "HECTARE",
              label: "公顷",
            },
            {
              value: "SQUARE_KILOMETER",
              label: "平方千米",
            },
          ],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/spatialMeasure/calculatePlaneAreaInGeometry",
        },
        "1.5.2.7": {
          // 功能描述
          functionalDefinition:
            "结合 DEM 高程数据，计算面要素在三维地形上的实际曲面面积（考虑地形起伏），精度依赖 DEM 数据分辨率。，单位支持平方米、公顷、平方千米切换",
          // 元素类型
          elementTypes: ["polygon", "unit"],
          // 单位
          unit: [
            {
              value: "SQUARE_METER",
              label: "平方米",
            },
            {
              value: "HECTARE",
              label: "公顷",
            },
            {
              value: "SQUARE_KILOMETER",
              label: "平方千米",
            },
          ],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/spatialMeasure/calculateSurfaceAreaInGeometry",
        },
        "1.5.2.8": {
          // 功能描述
          functionalDefinition:
            "查询单个点要素的海拔高度（基于 CGCS2000 大地高程基准），单位为米",
          // 元素类型
          elementTypes: ["point"],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/spatialMeasure/getPointElevationInGeometry",
        },
        "1.5.2.9": {
          // 功能描述
          functionalDefinition:
            "计算两个点要素之间的高程差值，支持正负值显示（正值表示前者高于后者，负值相反）",
          // 元素类型
          elementTypes: ["point", "point"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/spatialMeasure/calculateElevationDiffInGeometry",
        },
        "1.5.2.10": {
          // 功能描述
          functionalDefinition:
            "查询单个面要素的海拔高度（基于 CGCS2000 大地高程基准），单位为米",
          // 元素类型
          elementTypes: ["polygon"],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/spatialMeasure/calculateAreaElevationStatsInGeometry",
        },
        "1.5.3.1": {
          // 功能描述
          functionalDefinition:
            "将两个或多个不重叠 / 部分重叠的面要素，合并为一个连续的新面要素（消除重叠部分，保留所有要素的覆盖范围）",
          // 元素类型
          elementTypes: ["polygon"],
          // 元素个数
          minNumberOf: 2,
          // 后台接口路径
          apiUrl: "/geometry/union",
        },
        "1.5.3.2": {
          // 功能描述
          functionalDefinition:
            "提取两个或多个面要素之间的重叠区域，生成新的面要素（仅保留所有要素共同覆盖的范围）",
          // 元素类型
          elementTypes: ["polygon"],
          // 元素个数
          minNumberOf: 2,
          // 后台接口路径
          apiUrl: "/geometry/intersection",
        },
        "1.5.3.3": {
          // 功能描述
          functionalDefinition:
            "以一个面要素（称为 “源面”）为基础，减去与另一个面要素（称为 “裁剪面”）的重叠区域，生成新的面要素（保留源面中未被裁剪面覆盖的部分）",
          // 元素类型
          elementTypes: ["polygon"],
          // 元素个数
          minNumberOf: 2,
          // 后台接口路径
          apiUrl: "/geometry/difference",
        },
        "1.5.3.4": {
          // 功能描述
          functionalDefinition:
            "计算面要素的参数（面积、周长、中心坐标、最小外接矩形等）",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon"],
          // 元素个数
          numberOf: 1,
          // 后台接口路径
          apiUrl: "/geometry/parameters",
        },
        "1.5.4.1": {
          // 功能描述
          functionalDefinition:
            "判断两个面要素是否 “边界接触但不重叠”，且距离小于等于自定义阈值（默认 1 米，可通过接口参数调整），核心用于 “相邻区域联动” 场景",
          // 元素类型
          elementTypes: ["polygon", "polygon", "EPSILON"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/relationAnalys/adjacent",
        },
        "1.5.4.2": {
          // 功能描述
          functionalDefinition:
            "判断一个要素（含点、线、面）是否完全位于另一个面要素内部，且无任何部分超出，核心用于 “归属界定” 场景",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon", "EPSILON"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/relationAnalys/include",
        },
        "1.5.4.3": {
          // 功能描述
          functionalDefinition:
            "判断两个要素（点与线、点与面、线与线、线与面、面与面）是否存在空间重叠（含部分重叠），核心用于 “交叉影响” 场景",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon", "EPSILON"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/relationAnalys/intersect",
        },
        "1.5.4.4": {
          // 功能描述
          functionalDefinition:
            "判断两个要素（点、线、面）之间无任何空间接触（含边界接触），且最小距离大于自定义阈值（默认 10 米，可通过接口参数调整），核心用于 “无关联排除” 场景",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon", "EPSILON"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/relationAnalys/parting",
        },
        "1.5.4.5": {
          // 功能描述
          functionalDefinition:
            "以一个核心要素（点、线、面）为中心，按自定义半径（如 500 米、1 千米）划定范围，查询范围内所有目标要素（如设施、地块、道路），核心用于 “资源覆盖范围” 场景。由于不是我负责，暂时为缓冲区计算功能。​",
          // 元素类型
          elementTypes: ["point", "polyline", "polygon", "EPSILON"],
          // 元素个数
          numberOf: 2,
          // 后台接口路径
          apiUrl: "/relationAnalys/neighbor",
        },
        "1.5.5.1": {
          // 功能描述
          functionalDefinition:
            "非空间数据转空间数据功能支持常见格式的非空间数据转换，如 CSV、Excel 表格数据等。通过与地理编码服务紧密结合，关联空间参考信息（如地址、行政区域、关联 ID），转换为带坐标的空间要素（点、线、面），将表格中的地址、坐标等信息转换为具有空间位置的矢量数据的功能，并依据用户设定规则赋予属性信息。核心解决 “业务数据与地图引擎关联” 的问题，实现 “数据可视化” 与 “空间分析” 的联动。在智慧城市建设中，整合人口、环境、交通等多源非空间数据，实现数据融合分析，为城市精细化管理提供数据支持；在地理大数据分析中，拓展非空间数据的应用维度，挖掘数据潜在价值。",
          // 元素类型
          elementTypes: ["file"],
          // 元素个数
          numberOf: 0,
          // 后台接口路径
          apiUrl: "/nonStandardToStandard/importFile",
        },
        "1.5.6.1": {
          // 功能描述
          functionalDefinition:
            "坐标转换是基于青浦区三维数字底板的坐标系统（SH2000投影坐标系），将空间要素的坐标在不同坐标系之间进行转换的功能，包括地理坐标系（如 WGS84、上海 2000 等）和投影坐标系（如高斯 - 克吕格投影、UTM 投影等）",
          // 元素类型
          elementTypes: ["lon", "lat", "inPrj", "outPrj"],
          inPrj: [
            {
              value: "WGS84",
              label: "WGS84",
            },
            {
              value: "SH2000",
              label: "SH2000",
            },
            {
              value: "UTM",
              label: "UTM",
            },
          ],
          outPrj: [
            {
              value: "WGS84",
              label: "WGS84",
            },
            {
              value: "SH2000",
              label: "SH2000",
            },
            {
              value: "UTM",
              label: "UTM",
            },
          ],
          // 元素个数
          numberOf: 0,
          // 后台接口路径
          apiUrl: "/coordinateSystemTransformation/pointTransformation",
        },
        "1.5.7.1": {
          // 功能描述
          functionalDefinition:
            "时空数据格式转换是将青浦区三维数字底板中的时空数据（含空间坐标与时间属性的数据，如轨迹数据、时序监测数据），在不同标准数据格式之间进行转换的功能，如 Shapefile、GeoJSON、KML、NetCDF 等。核心支持 “矢量数据格式转换”“栅格数据格式转换”“时空轨迹数据格式转换” 三类转换，确保数据能在不同 GIS 软件、不同应用系统之间兼容流转，不同部门、不同系统之间顺利读取和处理时空数据；在大数据存储和管理时，根据不同应用场景和存储需求，选择合适的数据格式。提高数据存储和访问效率，满足数据共享、分析、展示的多场景需求。",
          // 元素类型
          elementTypes: ["file", "outFileType", "lonKey", "latKey"],
          outFileType: [
            {
              value: "geoJson",
              label: "geoJson",
            },
            {
              value: "shp",
              label: "shp",
            },
            {
              value: "csv",
              label: "csv",
            },
            {
              value: "xlsx",
              label: "xlsx",
            },
          ],
          // 元素个数
          numberOf: 0,
          // 后台接口路径
          apiUrl: "/spatiotemporal_data_format_conversion/fileFormatConversion",
        },
        "1.5.7.2": {
          // 功能描述
          functionalDefinition: "转换文件下载",
          // 元素类型
          elementTypes: ["filePath"],
          // 元素个数
          numberOf: 0,
          // 后台接口路径
          apiUrl: "/spatiotemporal_data_format_conversion/downloadFile",
        },
      },
      currentTool: null,
      drawingMode: null,
      handler: null,
      drawnEntities: [],
      geometries: [], // 存储绘制的几何对象
      // 绘制状态相关
      currentEntity: null, // 当前正在绘制的实体
      currentPositions: [], // 当前正在绘制的位置数组
      isDrawingHole: false, // 是否正在绘制镂空
      currentPolygonEntity: null, // 当前要添加镂空的多边形实体
      currentPolygonGeometry: null, // 当前要添加镂空的多边形几何对象
      tempEntity: null, // 临时预览实体
    };
  },
  mounted() {
    this.SceneValue = this.$route.query.sceneId ? this.$route.query.sceneId : "";
  },

  beforeUnmount() {
    // 组件卸载前清理资源
    this.deactivateDraw();
    if (this.handler) {
      this.handler.destroy();
    }
  },
  methods: {
    handleExceed(file) {
      this.$message({
        message: "最多只能上传一个文件",
        type: "warning",
      });
    },
    handleFileChange(file, fileList) {
      this.currentFile = file; // 注意：Element UI Plus 无需 .raw
    },
    uploadRemove() {
      this.currentFile = null;
    },
    handleJsonInput(value) {
      this.jsonData = JSON.parse(value);
    },
    handleChange(emit) {
      this.params.unit = "";
      this.currentFile = null;
      // 清除所有地图中的元素
      this.clearAll();
      this.jsonData = {};
      this.backData = {};
      this.SceneValue = emit[emit.length - 1];
    },
    // 初始化绘制处理器
    initDrawHandler() {
      // 创建绘制处理器
      this.handler = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas);
    },

    // 激活绘制工具
    activateDraw(type) {
      // 取消镂空绘制模式
      this.isDrawingHole = false;
      // 如果已经是当前激活的工具，则取消激活
      if (this.currentTool === type) {
        this.deactivateDraw();
        return;
      }
      // 先取消之前的绘制模式
      this.deactivateDraw();
      // 设置当前工具
      this.currentTool = type;
      this.drawingMode = type;
      // 重置当前绘制状态
      this.resetDrawingState();
      switch (type) {
        case "point":
          this.drawPoint();
          break;
        case "polyline":
          this.drawPolyline();
          break;
        case "polygon":
          this.drawPolygon();
          break;
      }
    },

    // 重置绘制状态
    resetDrawingState() {
      this.currentPositions = [];
      this.currentEntity = null;
      // 移除临时预览实体
      if (this.tempEntity) {
        viewer.entities.remove(this.tempEntity);
        viewer.scene.requestRender();
        this.tempEntity = null;
      }
    },

    // 取消绘制模式
    deactivateDraw() {
      if (this.handler) {
        // 移除所有事件监听器
        this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
      }
      // 重置状态
      this.resetDrawingState();
      this.currentTool = null;
      this.drawingMode = null;
      this.isDrawingHole = false;
    },

    // 绘制点
    drawPoint() {
      const that = this;
      this.handler.setInputAction(function (event) {
        const ray = viewer.camera.getPickRay(event.position);
        const position = viewer.scene.globe.pick(ray, viewer.scene);
        if (position) {
          const cartographic = SkyScenery.Cartographic.fromCartesian(position);
          const longitude = SkyScenery.Math.toDegrees(cartographic.longitude);
          const latitude = SkyScenery.Math.toDegrees(cartographic.latitude);
          // 创建点实体（实时渲染）
          const entity = viewer.entities.add({
            position: position,
            point: {
              show: true,
              color: SkyScenery.Color.RED,
              pixelSize: 10,
              outlineColor: SkyScenery.Color.WHITE,
              outlineWidth: 2,
            },
          });
          viewer.scene.requestRender();
          that.drawnEntities.push(entity);
          // 转换为geometry格式并保存
          const geometry = {
            type: "Point",
            coordinates: [longitude, latitude],
          };
          that.geometries.push(geometry);
          that.changeGeometries();
          console.log("绘制了点:", geometry);
        }
      }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
    },

    // 绘制线
    drawPolyline() {
      const that = this;
      // 鼠标移动时更新临时线（实时渲染预览）
      this.handler.setInputAction(function (event) {
        if (that.currentPositions.length > 0) {
          const ray = viewer.camera.getPickRay(event.endPosition);
          const endPosition = viewer.scene.globe.pick(ray, viewer.scene);

          if (endPosition) {
            const tempPositions = [...that.currentPositions, endPosition];

            // 更新临时预览实体
            if (!that.tempEntity) {
              that.tempEntity = viewer.entities.add({
                polyline: {
                  show: true,
                  positions: tempPositions,
                  material: SkyScenery.Color.BLUE.withAlpha(0.5),
                  width: 3,
                },
              });
              viewer.scene.requestRender();
            } else {
              that.tempEntity.polyline.positions = tempPositions;
            }
          }
        }
      }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);

      // 左键点击添加点
      this.handler.setInputAction(function (event) {
        const ray = viewer.camera.getPickRay(event.position);
        const position = viewer.scene.globe.pick(ray, viewer.scene);

        if (position) {
          that.currentPositions.push(position.clone());

          // 如果是第一个点，不需要更新实体
          if (that.currentPositions.length > 1) {
            // 如果已有实体，更新它
            if (that.currentEntity) {
              viewer.entities.remove(that.currentEntity);
            }

            // 创建当前实体（实时渲染）
            that.currentEntity = viewer.entities.add({
              polyline: {
                show: true,
                positions: [...that.currentPositions],
                material: SkyScenery.Color.BLUE,
                width: 3,
              },
            });
            viewer.scene.requestRender();
          }
        }
      }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);

      // 右键点击完成绘制
      this.handler.setInputAction(function () {
        if (that.currentPositions.length > 1) {
          // 移除临时预览实体
          if (that.tempEntity) {
            viewer.entities.remove(that.tempEntity);
            that.tempEntity = null;
          }

          // 否则创建线
          // 确保当前实体存在
          if (!that.currentEntity) {
            that.currentEntity = viewer.entities.add({
              polyline: {
                show: true,
                positions: [...that.currentPositions],
                material: SkyScenery.Color.BLUE,
                width: 3,
              },
            });
          }

          that.drawnEntities.push(that.currentEntity);
          viewer.scene.requestRender();

          // 转换为geometry格式并保存
          const coordinates = [];
          that.currentPositions.forEach((pos) => {
            const cartographic = SkyScenery.Cartographic.fromCartesian(pos);
            coordinates.push([
              SkyScenery.Math.toDegrees(cartographic.longitude),
              SkyScenery.Math.toDegrees(cartographic.latitude),
            ]);
          });

          const geometry = {
            type: "LineString",
            coordinates: coordinates,
          };
          that.geometries.push(geometry);
          that.changeGeometries();
          console.log("绘制了线:", geometry);
          // 取消当前绘制模式
          that.deactivateDraw();
        }
      }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
    },

    // 绘制面
    drawPolygon() {
      const that = this;

      // 鼠标移动时更新临时面（实时渲染预览）
      this.handler.setInputAction(function (event) {
        if (that.currentPositions.length > 0) {
          const ray = viewer.camera.getPickRay(event.endPosition);
          const endPosition = viewer.scene.globe.pick(ray, viewer.scene);

          if (endPosition) {
            // 为了预览效果，临时闭合多边形
            const tempPositions = [
              ...that.currentPositions,
              endPosition,
              that.currentPositions[0],
            ];

            // 更新临时预览实体
            if (!that.tempEntity) {
              that.tempEntity = viewer.entities.add({
                polygon: {
                  show: true,
                  hierarchy: new SkyScenery.PolygonHierarchy(tempPositions),
                  material: new SkyScenery.ColorMaterialProperty(
                    new SkyScenery.Color(0, 0, 1, 0.2)
                  ),
                  outline: true,
                  outlineColor: SkyScenery.Color.BLUE.withAlpha(0.5),
                  outlineWidth: 2,
                },
              });
              viewer.scene.requestRender();
            } else {
              that.tempEntity.polygon.hierarchy = new SkyScenery.PolygonHierarchy(
                tempPositions
              );
            }
          }
        }
      }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);

      // 左键点击添加点
      this.handler.setInputAction(function (event) {
        const ray = viewer.camera.getPickRay(event.position);
        const position = viewer.scene.globe.pick(ray, viewer.scene);

        if (position) {
          // 检查是否点击了第一个点附近（自动闭合）
          if (
            that.currentPositions.length > 2 &&
            that.isPositionNearFirst(position, that.currentPositions[0])
          ) {
            // 完成多边形绘制
            that.finalizePolygonDrawing();
            that.deactivateDraw();
            return;
          }

          that.currentPositions.push(position.clone());

          // 如果有足够的点，更新多边形实体（实时渲染）
          if (that.currentPositions.length > 2) {
            // 闭合多边形
            const closedPositions = [...that.currentPositions, that.currentPositions[0]];
            // 如果已有实体，更新它
            if (that.currentEntity) {
              viewer.entities.remove(that.currentEntity);
            }

            // 创建当前实体
            that.currentEntity = viewer.entities.add({
              polygon: {
                show: true,
                hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
                material: new SkyScenery.ColorMaterialProperty(
                  new SkyScenery.Color(0, 0, 1, 0.3)
                ),
                outline: true,
                outlineColor: SkyScenery.Color.BLUE,
                outlineWidth: 2,
              },
            });
            viewer.scene.requestRender();
          }
        }
      }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);

      // 右键点击完成绘制
      this.handler.setInputAction(function () {
        if (that.currentPositions.length > 2) {
          that.finalizePolygonDrawing();
          // 取消当前绘制模式
          that.deactivateDraw();
        }
      }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
    },

    // 完成多边形绘制
    finalizePolygonDrawing() {
      // 移除临时预览实体
      if (this.tempEntity) {
        viewer.entities.remove(this.tempEntity);
        this.tempEntity = null;
      }

      // 确保多边形是闭合的
      let closedPositions = [...this.currentPositions];
      // 创建最终的多边形实体
      if (this.currentEntity) {
        viewer.entities.remove(this.currentEntity);
      }

      this.currentEntity = viewer.entities.add({
        polygon: {
          show: true,
          hierarchy: new SkyScenery.PolygonHierarchy(closedPositions),
          material: new SkyScenery.ColorMaterialProperty(
            new SkyScenery.Color(0, 0, 1, 0.3)
          ),
          outline: true,
          outlineColor: SkyScenery.Color.BLUE,
          outlineWidth: 2,
        },
      });
      viewer.scene.requestRender();

      this.drawnEntities.push(this.currentEntity);

      // 转换为geometry格式并保存（不包含重复的最后一个点）
      const coordinates = [];
      const mainRing = [];
      for (let i = 0; i < closedPositions.length; i++) {
        const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[i]);
        mainRing.push([
          SkyScenery.Math.toDegrees(cartographic.longitude),
          SkyScenery.Math.toDegrees(cartographic.latitude),
        ]);
      }
      const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[0]);
      mainRing.push([
        SkyScenery.Math.toDegrees(cartographic.longitude),
        SkyScenery.Math.toDegrees(cartographic.latitude),
      ]);
      coordinates.push(mainRing);

      const geometry = {
        type: "Polygon",
        coordinates: coordinates, // GeoJSON格式
        holes: [], // 用于存储镂空区域
      };

      // 保存实体和几何对象的关联
      this.currentEntity.geometryRef = geometry;
      this.geometries.push(geometry);
      this.changeGeometries();
      console.log("绘制了面:", geometry);
    },

    // 开始绘制镂空
    startHoleDrawing() {
      // 如果已经在绘制镂空，则取消
      if (this.isDrawingHole) {
        this.isDrawingHole = false;
        this.deactivateDraw();
        return;
      }

      // 取消其他绘制模式
      this.deactivateDraw();

      // 设置为镂空绘制模式
      this.isDrawingHole = true;

      console.log("请点击一个多边形以添加镂空");

      // 设置点击事件选择多边形
      const that = this;
      this.handler.setInputAction(function (event) {
        // 拾取实体
        const pickedObject = viewer.scene.pick(event.position);
        if (pickedObject && pickedObject.id && pickedObject.id.polygon) {
          const polygonEntity = pickedObject.id;

          // 检查是否有对应的几何对象
          if (polygonEntity.geometryRef && polygonEntity.geometryRef.type === "Polygon") {
            that.currentPolygonEntity = polygonEntity;
            that.currentPolygonGeometry = polygonEntity.geometryRef;

            console.log("已选择多边形，现在绘制镂空区域");

            // 开始绘制镂空区域（使用多边形绘制逻辑，但最后添加为镂空）
            that.resetDrawingState();
            that.drawHole();
          } else {
            console.log("选择的不是有效的多边形");
          }
        } else {
          console.log("未选中任何多边形");
        }
      }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
    },

    // 绘制镂空区域
    drawHole() {
      const that = this;

      // 清除之前的事件
      this.handler.removeInputAction(SkyScenery.ScreenSpaceEventType.LEFT_CLICK);

      // 鼠标移动时更新临时镂空区域
      this.handler.setInputAction(function (event) {
        if (that.currentPositions.length > 0) {
          const ray = viewer.camera.getPickRay(event.endPosition);
          const endPosition = viewer.scene.globe.pick(ray, viewer.scene);

          if (endPosition) {
            // 为了预览效果，临时闭合多边形
            const tempPositions = [
              ...that.currentPositions,
              endPosition,
              that.currentPositions[0],
            ];

            // 更新临时预览实体
            if (!that.tempEntity) {
              that.tempEntity = viewer.entities.add({
                polygon: {
                  show: true,
                  hierarchy: new SkyScenery.PolygonHierarchy(tempPositions),
                  material: new SkyScenery.ColorMaterialProperty(
                    new SkyScenery.Color(1, 0, 0, 0.3)
                  ),
                  outline: true,
                  outlineColor: SkyScenery.Color.RED,
                  outlineWidth: 2,
                },
              });
              viewer.scene.requestRender();
            } else {
              that.tempEntity.polygon.hierarchy = new SkyScenery.PolygonHierarchy(
                tempPositions
              );
            }
          }
        }
      }, SkyScenery.ScreenSpaceEventType.MOUSE_MOVE);

      // 左键点击添加点
      this.handler.setInputAction(function (event) {
        const ray = viewer.camera.getPickRay(event.position);
        const position = viewer.scene.globe.pick(ray, viewer.scene);

        if (position) {
          // 检查是否点击了第一个点附近（自动闭合）
          if (
            that.currentPositions.length > 2 &&
            that.isPositionNearFirst(position, that.currentPositions[0])
          ) {
            // 完成镂空绘制
            that.finalizeHoleDrawing();
            return;
          }

          that.currentPositions.push(position.clone());
        }
      }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);

      // 右键点击完成绘制
      this.handler.setInputAction(function () {
        if (that.currentPositions.length > 2) {
          that.finalizeHoleDrawing();
        }
      }, SkyScenery.ScreenSpaceEventType.RIGHT_CLICK);
    },

    // 完成镂空绘制
    finalizeHoleDrawing() {
      // 移除临时预览实体
      if (this.tempEntity) {
        viewer.entities.remove(this.tempEntity);
        viewer.scene.requestRender();
        this.tempEntity = null;
      }

      // 确保镂空区域是闭合的
      let closedPositions = [...this.currentPositions];

      // 转换为几何坐标
      const holeCoordinates = [];
      for (let i = 0; i < closedPositions.length; i++) {
        const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[i]);
        holeCoordinates.push([
          SkyScenery.Math.toDegrees(cartographic.longitude),
          SkyScenery.Math.toDegrees(cartographic.latitude),
        ]);
      }

      const cartographic = SkyScenery.Cartographic.fromCartesian(closedPositions[0]);
      holeCoordinates.push([
        SkyScenery.Math.toDegrees(cartographic.longitude),
        SkyScenery.Math.toDegrees(cartographic.latitude),
      ]);
      // 添加到几何对象的镂空数组
      if (!this.currentPolygonGeometry.holes) {
        this.currentPolygonGeometry.holes = [];
      }
      this.currentPolygonGeometry.holes.push(holeCoordinates);

      // 更新多边形的层级结构以包含镂空
      const polygonHierarchy = this.buildPolygonHierarchyWithHoles(
        this.currentPolygonGeometry.coordinates[0],
        this.currentPolygonGeometry.holes
      );

      // 更新实体显示
      this.currentPolygonEntity.polygon.hierarchy = polygonHierarchy;

      console.log("添加了镂空区域:", holeCoordinates);
      console.log("更新后的多边形几何:", this.currentPolygonGeometry);

      // 重置状态
      this.resetDrawingState();
      this.isDrawingHole = false;
      this.currentPolygonEntity = null;
      this.currentPolygonGeometry = null;

      // 取消绘制模式
      this.deactivateDraw();
    },

    // 构建包含镂空的多边形层级结构
    buildPolygonHierarchyWithHoles(outerRing, holes) {
      // 将外部环转换为Cartesian3数组
      const outerRingPositions = [];
      outerRing.forEach((coord) => {
        const cartesian = SkyScenery.Cartesian3.fromDegrees(coord[0], coord[1]);
        outerRingPositions.push(cartesian);
      });
      // 闭合外部环
      outerRingPositions.push(outerRingPositions[0]);

      // 创建层级结构
      const hierarchy = new SkyScenery.PolygonHierarchy(outerRingPositions);

      // 添加镂空
      if (holes && holes.length > 0) {
        hierarchy.holes = holes.map((hole) => {
          const holePositions = [];
          hole.forEach((coord) => {
            const cartesian = SkyScenery.Cartesian3.fromDegrees(coord[0], coord[1]);
            holePositions.push(cartesian);
          });
          // 闭合镂空环
          holePositions.push(holePositions[0]);
          return new SkyScenery.PolygonHierarchy(holePositions);
        });
      }
      return hierarchy;
    },

    // 检查点是否靠近第一个点
    isPositionNearFirst(position, firstPosition, tolerance = 10) {
      // 单位：米
      const distance = SkyScenery.Cartesian3.distance(position, firstPosition);
      return distance < tolerance;
    },
    changeGeometries() {
      let requestData = {};
      const geometriesToSend = this.geometries;
      let FeatureCollectionFeatures = [];
      geometriesToSend.forEach((item) => {
        FeatureCollectionFeatures.push({
          type: "Feature",
          properties: {},
          geometry: {
            type: item.type,
            coordinates: item.coordinates,
          },
        });
      });
      // 构造请求数据
      requestData = {
        type: "FeatureCollection",
        features: FeatureCollectionFeatures,
        timestamp: new Date().getTime(),
      };
      if (
        this.SceneValue &&
        this.SceneRule[this.SceneValue] &&
        this.SceneRule[this.SceneValue].elementTypes &&
        this.SceneRule[this.SceneValue].elementTypes.includes("unit") &&
        this.params.unit
      ) {
        requestData.unit = this.params.unit;
      }
      if (
        this.SceneValue &&
        this.SceneRule[this.SceneValue] &&
        this.SceneRule[this.SceneValue].elementTypes &&
        this.SceneRule[this.SceneValue].elementTypes.includes("EPSILON") &&
        this.params.EPSILON
      ) {
        requestData.EPSILON = this.params.EPSILON;
      }
      this.jsonData = requestData;
      return requestData;
    },
    // 发送几何数据到后台接口
    sendGeometriesToBackend() {
      // 这里使用axios发送请求，需要确保项目中已安装并导入axios
      let requestData;
      let requestUrl = this.SceneRule[this.SceneValue].apiUrl;
      if (
        this.SceneRule[this.SceneValue].elementTypes.includes("point") ||
        this.SceneRule[this.SceneValue].elementTypes.includes("polyline") ||
        this.SceneRule[this.SceneValue].elementTypes.includes("polygon")
      ) {
        requestData = this.changeGeometries();
      } else {
        requestData = new FormData();
        this.SceneRule[this.SceneValue].elementTypes.forEach((key) => {
          if (key == "file") {
            if (!this.currentFile) {
              return this.$message({
                message: "请选择文件",
                type: "error",
              });
            }
            requestData.append("file", this.currentFile.raw);
          } else {
            requestData.append(key, this.params[key]);
          }
        });
      }
      let that = this;
      // 实际项目中使用以下代码发送请求
      skszk
        .topology(requestUrl, requestData)
        .then((res) => {
          if (requestUrl.indexOf("downloadFile") == -1) {
            that.backData = res;
            if (res.code && res.code == 200) {
              that.$message({
                message: res.message,
                type: "success",
              });
            } else {
              that.$message({
                message: res.content,
                type: "error",
              });
            }
          } else {
            const blob = res; // 响应体是 Blob 类型
            if (!blob) {
              that.$message.error("下载失败：文件流为空");
              reject("文件流为空");
              return;
            }
            let _downloadFile = that.params.filePath + "";
            let fileName = _downloadFile.substring(
              _downloadFile.indexOf("down_files") + 11
            );
            // D:\work\backCode\one_map_portal_server\down_files\0378b1c2e92a4c36ab447f552c0c7888.xlsx
            // 替换原代码中创建 url 的逻辑，先加校验
            console.log("blob 类型：", Object.prototype.toString.call(blob)); // 正常应输出 [object Blob]
            console.log("blob 大小：", blob.size); // 正常应大于 0

            if (!(blob instanceof Blob) || blob.size === 0) {
              this.$message.error("文件流解析失败，无法生成下载链接");
              return;
            }
            const url = window.URL.createObjectURL(blob); // 将 Blob 转为临时 URL
            const link = document.createElement("a");
            link.href = url;
            link.download = fileName; // 设置下载文件名
            link.style.display = "none";
            document.body.appendChild(link);
            link.click(); // 触发点击下载
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url); // 销毁临时 URL，避免内存泄漏
          }
        })
        .catch((error) => {
          console.error("后台接口调用失败:", error);
        });
    },

    // 清除所有绘制的元素
    clearAll() {
      // 移除所有实体
      this.drawnEntities.forEach((entity) => {
        viewer.entities.remove(entity);
      });
      viewer.scene.requestRender();
      // 清空数组
      this.drawnEntities = [];
      this.geometries = [];
      this.changeGeometries();
      // 取消当前绘制模式
      this.deactivateDraw();

      console.log("已清除所有绘制的元素");
    },
  },
};
</script>

<style lang="less" scoped>
// 操作栏样式
#controlPanelBox {
  width: calc(30vw - 2rem);
  min-width: 500px;
  height: calc(100vh - 120px - 2rem);
  display: flex;
  flex-direction: column;
  padding: 1rem;
  position: fixed;
  top: 70px;
  right: 0;
  background: #fff;
}

// 绘制按钮区域
.toolbar {
  position: absolute;
  top: 10px;
  left: -120px;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 8px;
  padding: 3px 5px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tool-item {
  padding: 10px 20px;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.3s ease;
  user-select: none;
  font-size: 14px;
}

.tool-item:hover {
  background: #f0f0f0;
}

.tool-item.active {
  background: #409eff;
  color: white;
}
.sceneNameBox {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
</style>
