<template>
  <div>
    <div class="home-header">
      <img @click="drawStartPoint" src="@/assets/image/start.png" />
      <img @click="drawEndPoint" src="@/assets/image/end.png" />
      <img @click="drawViaPoint" src="@/assets/image/add.png" />
      <img @click="drawAvoidPoint" src="@/assets/image/avoidP.png" />
      <img @click="drawAvoidArea" src="@/assets/image/updown.png" />
      <div @click="clear" class="sure">清除</div>
      <div @click="calculateShortestPath" class="sure">确定</div>
      <div @click="hadBuffer" class="sure">路线隐蔽规划</div>
      <div @click="pointBuffer" class="sure">点隐蔽规划</div>
      <!-- <div class="control-panel">
        <button @click="drawStartPoint">绘制起点</button>
        <button @click="drawEndPoint">绘制终点</button>
        <button @click="drawViaPoint">绘制途经点</button>
        <button @click="drawAvoidPoint">绘制避让点</button>
        <button @click="drawAvoidArea">绘制避让区域</button>
        <button @click="calculateShortestPath">计算最短路径</button>
        <button @click="clear">清除所有</button>
      </div> -->
    </div>
    <div class="home">
      <div class="main-container">
        <div class="control-panel">
          <div class="title">参数</div>
          <el-form
            @submit.native.prevent="calculateShortestPath"
            label-width="120px"
            label-position="left"
            size="mini"
            :model="form"
          >
            <el-form-item label="起点">
              <el-input
                v-model="form.startPoint"
                @blur="pointsChange('startPoint')"
                @clear="pointsChange('startPoint')"
                clearable
              ></el-input>
            </el-form-item>
            <el-form-item label="终点">
              <el-input
                v-model="form.endPoint"
                @blur="pointsChange('endPoint')"
                @clear="pointsChange('endPoint')"
                clearable
              ></el-input>
            </el-form-item>
            <el-form-item label="途经点">
              <div v-for="(item, index) in form.viaPoints" :key="index">
                <el-input
                  v-model="item.points"
                  placeholder=""
                  @blur="pointsChange('viaPoints', item)"
                  @clear="pointsChange('viaPoints', item)"
                  clearable
                ></el-input>
              </div>
            </el-form-item>
            <el-form-item label="避让点">
              <div v-for="(item, index) in form.avoidPoints" :key="index">
                <el-input
                  v-model="item.points"
                  placeholder=""
                  @blur="pointsChange('avoidPoints', item)"
                  @clear="pointsChange('avoidPoints', item)"
                  clearable
                ></el-input>
              </div>
            </el-form-item>
            <el-form-item label="避让区域">
              <div v-for="(item, index) in form.avoidAreas" :key="index">
                <el-input
                  v-model="item.points"
                  placeholder=""
                  @blur="pointsChange('avoidAreas', item)"
                  @clear="pointsChange('avoidAreas', item)"
                  clearable
                ></el-input>
              </div>
            </el-form-item>
          </el-form>
          <input type="file" ref="fileInput" @change="handleFileUpload" style="display: none" />
          <div class="importJson" @click="triggerFileUpload">导入json文件</div>
        </div>
        <div class="control-panel">
          <div class="title">隐蔽添加</div>
          <el-form label-width="120px" label-position="left" size="mini">
            <el-form-item label="缓冲半径（m）">
              <el-input v-model="hideform.radius"></el-input>
            </el-form-item>
            <el-form-item label="面积冗余（%）">
              <el-input v-model="hideform.redundancy" placeholder=""></el-input>
            </el-form-item>
          </el-form>
        </div>
        <div class="control-panel">
          <div class="title">
            <span>机动属性</span>
            <div class="joinCheck">
              <el-checkbox v-model="join"></el-checkbox>
              <span>参与路线规划</span>
            </div>
          </div>
          <el-form @submit.native.prevent="calculateShortestPath" label-width="120px" label-position="left" size="mini">
            <el-form-item label="宽度">
              <el-input v-model="inputform.width"></el-input>
            </el-form-item>
            <el-form-item label="载重（吨）">
              <el-input v-model="inputform.load" placeholder=""></el-input>
            </el-form-item>
            <el-form-item label="最小转弯半径">
              <el-input v-model="inputform.minTurnRadius" placeholder=""></el-input>
            </el-form-item>
          </el-form>
          <div class="importJson" @click="openDialog">数据选择</div>
        </div>
      </div>
      <div id="map"></div>
      <div class="main-container" style="width: 452px">
        <div class="control-panel" style="width: 452px">
          <div style="font-size: 14px; margin-bottom: 10px">
            详细路线：<br />
            起点（{{ form.startPoint }}）， 途经点（{{
              form.viaPoints.length > 0 && form.viaPoints[0].points
                ? form.viaPoints.map((item) => item.points).join(';')
                : ''
            }}), 避让点（{{
              form.avoidPoints.length > 0 && form.avoidPoints[0].points
                ? form.avoidPoints.map((item) => item.points).join(';')
                : ''
            }}), 终点（{{ form.endPoint }}）, 避让区域（{{
              form.avoidAreas.length > 0 && form.avoidAreas[0].points
                ? form.avoidAreas.map((item) => item.points).join(';')
                : ''
            }})。<br />
            装备参数:最大车辆宽度{{ inputform.width || 0 }},最小转弯半径{{
              inputform.minTurnRadius || 0
            }}，最大车辆载重{{ inputform.load || 0 }}吨
          </div>
          <vxe-table ref="xTable" :data="infoList" style="max-height: 50vh; overflow: hidden; overflow-y: auto">
            <vxe-column field="编码" title="编码" width="65px"></vxe-column>
            <vxe-column field="名称" title="名称" width="80px"></vxe-column>
            <vxe-column field="宽度" title="路宽"></vxe-column>
            <vxe-column field="曲率半" title="曲率"></vxe-column>
            <vxe-column field="载重吨" title="载重"></vxe-column>
            <vxe-column field="水深" title="水深"></vxe-column>
            <vxe-column field="净空高" title="净空高" width="65px"></vxe-column>
          </vxe-table>
          <vxe-table :data="factoriesWithVehicles" style="margin-top: 10px">
            <vxe-column field="options.style.properties.FID_1" title="厂房id"></vxe-column>
            <vxe-column field="area" title="面积(㎡)">
              <template v-slot="{row}">
                {{ row.area.toFixed(2) }}
              </template>
            </vxe-column>
            <vxe-column field="vehicles" title="车辆">
              <template v-slot="{row}">
                {{ row.vehicles.map((item) => item.name).join(',') }}
              </template>
            </vxe-column>
          </vxe-table>
        </div>
      </div>
      <el-dialog :visible.sync="dialogVisible" title="车辆选择" width="800px">
        <div style="margin-bottom: 10px">
          <el-button type="primary" size="mini" @click="handleAdd">新增</el-button>
        </div>
        <vxe-table
          height="300px"
          ref="vxeTable"
          :data="tableData"
          :row-config="{isCurrent: true, isHover: true, keyField: 'id'}"
          :checkbox-config="{checkField: 'checked', highlight: true}"
          @checkbox-change="handleSelectionChange"
          @checkbox-all="handleSelectionChange"
          @close="closeSelection"
          align="center"
        >
          <vxe-column type="checkbox" width="50"></vxe-column>
          <vxe-column field="name" title="名称" width="100">
            <template v-slot="{row}">
              <el-input v-if="row.editing" v-model="row.name" size="mini"></el-input>
              <span v-else>{{ row.name }}</span>
            </template>
          </vxe-column>
          <vxe-column field="long" title="长度" width="100">
            <template v-slot="{row}">
              <el-input v-if="row.editing" v-model="row.long" size="mini"></el-input>
              <span v-else>{{ row.long }}</span>
            </template>
          </vxe-column>
          <vxe-column field="width" title="宽度" width="100">
            <template v-slot="{row}">
              <el-input v-if="row.editing" v-model="row.width" size="mini"></el-input>
              <span v-else>{{ row.width }}</span>
            </template>
          </vxe-column>
          <vxe-column field="load" title="载重（吨）" width="100">
            <template v-slot="{row}">
              <el-input v-if="row.editing" v-model="row.load" size="mini"></el-input>
              <span v-else>{{ row.load }}</span>
            </template>
          </vxe-column>
          <vxe-column field="minTurnRadius" title="最小转弯半径">
            <template v-slot="{row}">
              <el-input v-if="row.editing" v-model="row.minTurnRadius" size="mini"></el-input>
              <span v-else>{{ row.minTurnRadius }}</span>
            </template>
          </vxe-column>
          <vxe-column title="操作" width="100">
            <template v-slot="{row}">
              <el-button v-if="!row.editing" type="text" size="mini" @click="handleEdit(row)">编辑</el-button>
              <el-button v-else type="text" size="mini" @click="handleSave(row)">保存</el-button>
              <el-button type="text" size="mini" @click="handleDelete(row)">删除</el-button>
            </template>
          </vxe-column>
        </vxe-table>
        <div slot="footer" class="dialog-footer">
          <el-button size="mini" @click="closeSelection">取消</el-button>
          <el-button type="primary" size="mini" @click="confirmSelection">确定</el-button>
          <el-button type="primary" size="mini" @click="suerCofirm">保存</el-button>
        </div>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import Cookies from 'js-cookie'
import axios from 'axios'
import iniParser from 'ini-parser'
import configIni from '/public/config.ini'

export default {
  data() {
    return {
      dialogVisible: false,
      tableData: [],
      multipleSelection: [],
      inputform: {
        width: 0,
        load: 0,
        minTurnRadius: 0,
      },
      form: {
        startPoint: '',
        endPoint: '',
        viaPoints: [{points: '', time: ''}],
        avoidPoints: [{points: '', time: ''}],
        avoidAreas: [{points: '', time: ''}],
      },
      viewer: null,
      graphicLayer: null,
      polygonZAM: null,
      pointQD: null,
      pointZD: null,
      shortestPathLayer: null,
      shortestPathList: [],
      infoList: [],
      roadNetworkLayer: null,
      roadNetworkGeoJSON: null,
      mapOptions: null,
      viaPoints: [], // 途经点
      avoidPoints: [], // 避让点
      avoidAreas: [], // 避让区域
      roadNetworkGeoJSONBuild: null,
      hideform: {
        radius: 3000,
        redundancy: 10,
      },
      join: false,
      bufferLayerList: [], // 缓冲区信息
      factoryGeoJSON: [], // 拿到的所有的厂房数据
      accordFactoryInfo: [], // 在缓冲区 符合条件的厂房
      factoriesWithVehicles: [], // 塞入车的厂房集合
      accordFactoryLayer: null, // 隐蔽规划
      accordPoint: null, // 隐蔽规划点
    }
  },
  async mounted() {
    this.viewer = null
    await this.getMapOption()
    this.$nextTick(async () => {
      await this.initMap()
    })
  },
  beforeDestroy() {
    this.destroyMap()
  },
  methods: {
    destroyMap() {
      this.clear()
    },
    async getMapOption() {
      await fetch('./config/map.json')
        .then((response) => {
          return response.json()
        })
        .then((data) => {
          this.mapOptions = data.map3d
        })
        .catch((error) => {})
    },
    async initMap() {
      const parsedData = iniParser.parse(configIni)
      this.viewer = new window.mars3d.Map(
        'map',
        {
          ...this.mapOptions,
          scene: {
            ...this.mapOptions.scene,
            // mode: Cesium.SceneMode.SCENE2D,
            center: {
              lat: 27.729862392917948,
              lng: 114.27980291774088,
              alt: 45000,
              heading: 5,
              pitch: -35,
            },
          },
          // basemaps: [
          //   {
          //     id: "image-tdss",
          //     name: "影像图",
          //     type: "xyz",
          //     // url: `http:/www.tdss.website:280/tiles/img_c/{z}/{x}/{y}`,
          //     url: `http://${parsedData.http.address}:${parsedData.http.port}/web/imgs/{z}/{x}/{y}`,
          //     // crs: "EPSG:4490",
          //     crs: "EPSG:3857",
          //     show: true
          //   }
          // ],
        } || {}
      )
      this.graphicLayer = new window.mars3d.layer.GraphicLayer()
      this.viewer.addLayer(this.graphicLayer)

      this.shortestPathLayer = new window.mars3d.layer.GraphicLayer()
      this.viewer.addLayer(this.shortestPathLayer)

      this.accordFactoryLayer = new window.mars3d.layer.GraphicLayer()
      this.viewer.addLayer(this.accordFactoryLayer)
      this.loadShapefile() // 拿到路网数据
      // 添加地图点击事件监听，用于结束绘制
      this.viewer.on(mars3d.EventType.dblClick, (event) => {
        // 如果正在绘制，点击地图可以结束绘制（除了绘制点）
        this.graphicLayer.stopDraw()
      })
    },
    clear() {
      this.graphicLayer.stopDraw()
      // 清除起点
      if (this.pointQD) {
        this.pointQD.remove()
        this.pointQD = null
        this.form.startPoint = ''
      }

      // 清除终点
      if (this.pointZD) {
        this.pointZD.remove()
        this.pointZD = null
        this.form.endPoint = ''
      }
      if (this.viaPoints.length > 0) {
        // 清除途经点
        this.viaPoints.forEach((point) => {
          point.remove()
        })
        this.viaPoints = []
        this.form.viaPoints = [{points: '', time: ''}]
      }

      if (this.avoidPoints.length > 0) {
        // 清除避让点
        this.avoidPoints.forEach((point) => {
          point.remove()
        })
        this.avoidPoints = []
        this.form.avoidPoints = [{points: '', time: ''}]
      }

      if (this.avoidAreas.length > 0) {
        // 清除避让区域
        this.avoidAreas.forEach((area) => {
          area.remove()
        })
        this.avoidAreas = []
        this.form.avoidAreas = [{points: '', time: ''}]
      }
      if (this.shortestPathLayer) {
        // 清除最短路径图层
        this.shortestPathLayer.clear()
        this.infoList = []
        this.shortestPathList = []
      }
      if (this.accordFactoryLayer) {
        // 清除路线隐蔽规划
        this.accordFactoryLayer.clear()
        this.accordFactoryInfo = []
        this.bufferLayerList = []
        this.factoriesWithVehicles = []
      }
    },
    async loadShapefile() {
      try {
        // 1. 读取本地 SHP（浏览器）
        // const shpBuffer = await fetch('./config/map/data/dlfs_lines.zip').then(r => r.arrayBuffer());
        // const shpJson = await shp(shpBuffer);   // {features: [...]}

        // 1. 读取本地 jeojson
        const shpBuffer = await fetch('./config/dao.geojson')
          .then((response) => {
            return response.json()
          })
          .then((data) => {
            return data
          })
          .catch((error) => {})

        // 2. 处理 GeoJSON 数据
        this.roadNetworkGeoJSON = shpBuffer
        /// 3. 将 GeoJSON 数据添加到 graphicLayer
        this.roadNetworkGeoJSON.features.forEach((feature) => {
          // ====网路图=====
          const graphicLine = new window.mars3d.graphic.PolylineEntity({
            positions: feature.geometry.coordinates[0],
            style: {
              color: '#FF0000',
              width: 2,
              outline: false,
            },
          })
          this.graphicLayer.addGraphic(graphicLine)
        })
        this.roadNetworkGeoJSONBuild = this.buildGraph(this.roadNetworkGeoJSON)
        this.loadFactoryGeoJson() // 拿到厂房数据
      } catch (error) {
        console.error('加载 Shapefile 数据失败:', error)
      }
    },
    // 获取厂房的数据
    async loadFactoryGeoJson() {
      try {
        const shpBuffer = await fetch('./config/factory.geojson')
          .then((response) => {
            return response.json()
          })
          .then((data) => {
            return data
          })
          .catch((error) => {})
        this.factoryGeoJSON = shpBuffer
      } catch (error) {
        console.error('加载厂房数据失败:', error)
      }
    },
    // 去绘制点 进行隐蔽规划
    pointBuffer() {
      if (this.shortestPathList.length > 0 || this.accordFactoryInfo > 0) {
        this.$message.warning('请先清空路线以及路线隐蔽规划')
        return
      }
      if (this.accordPoint) {
        this.accordPoint.remove()
        this.accordPoint = null
      }
      if (this.accordFactoryLayer) {
        // 清除点的隐蔽规划
        this.accordFactoryLayer.clear()
        this.accordFactoryInfo = []
        this.factoriesWithVehicles = []
      }
      this.accordFactoryLayer.startDraw({
        type: 'point',
        style: {
          pixelSize: 10,
          color: '#55ff33',
        },
        success: (graphic) => {
          this.accordPoint = graphic
          try {
            // 创建缓冲区的宽度
            const bufferWidth = this.hideform.radius // 避让区的宽度（单位：米）
            // 获取绘制的点的坐标
            const pointCoordinates = [
              graphic.toGeoJSON().geometry.coordinates[0],
              graphic.toGeoJSON().geometry.coordinates[1],
            ]
            // 创建点的 GeoJSON 特征
            const pointFeature = {
              type: 'Feature',
              geometry: {
                type: 'Point',
                coordinates: pointCoordinates,
              },
              properties: {},
            }
            // 使用 Turf.js 计算缓冲区
            let buffered = turf.buffer(pointFeature, bufferWidth / 1000, {units: 'kilometers'})

            // 将缓冲区存储到数组中
            this.bufferLayerList.push(buffered)
            const polygon = new window.mars3d.graphic.PolygonEntity({
              positions: buffered.geometry.coordinates[0],
              style: {
                color: '#d4e5db',
                opacity: 0.5,
                outline: true,
                outlineWidth: 1,
                outlineColor: '#ffffff',
              },
              time: new Date().getTime(),
            })
            this.accordFactoryLayer.addGraphic(polygon)
            // 检查缓冲区内的厂房
            this.checkFactoryInBuffer('point', pointCoordinates)
          } catch (error) {
            console.error('缓冲区生成或检查异常:', error)
          }
        },
      })
    },
    // 获取当前路线的缓冲区
    hadBuffer() {
      if (this.shortestPathList.length == 0) {
        this.$message.warning('请先进行路线规划')
        return
      }
      if (JSON.parse(Cookies.get('minTurnRadius')).length == 0) {
        this.$message.warning('请先选择车辆')
        return
      }
      try {
        // =======检查几何对象的类型 缓冲区========
        for (const feature of this.shortestPathList[0]) {
          //  this.shortestPathList[0].forEach((feature) => {
          // 创建缓冲区的宽度
          const bufferWidth = this.hideform.radius // 避让区的宽度（单位：米）
          if (feature.geometry.type === 'LineString') {
            const positions = feature.geometry.coordinates[0]
            // 确保每条线至少有 2 个点
            if (positions.length < 2) {
              console.warn('无效的线，跳过:', feature)
              return
            }
            try {
              // 使用 Turf.js 计算缓冲区
              var buffered = turf.buffer(feature, bufferWidth / 1000, {units: 'kilometers'})

              // 将缓冲区存储到数组中
              this.bufferLayerList.push(buffered)
            } catch (error) {
              console.error('缓冲分析异常:', error)
            }
          } else if (feature.geometry.type === 'MultiLineString') {
            // 遍历每个线段
            feature.geometry.coordinates.forEach((lineCoordinates) => {
              // 检查每个线段是否有效
              if (lineCoordinates.length < 2) {
                console.warn('多线段中的无效的线段，跳过:', lineCoordinates)
                return
              }

              // 创建单个线段的 GeoJSON 特征
              const lineFeature = {
                type: 'Feature',
                geometry: {
                  type: 'LineString',
                  coordinates: lineCoordinates,
                },
                properties: feature.properties,
              }
              try {
                // 使用 Turf.js 计算缓冲区
                var buffered = turf.buffer(lineFeature, bufferWidth / 1000, {units: 'kilometers'})

                // 将缓冲区存储到数组中
                this.bufferLayerList.push(buffered)
              } catch (error) {
                console.error('缓冲分析异常:', error)
              }
            })
          } else {
            console.warn('不支持的几何类型:', feature.geometry.type)
          }
        }

        // 去筛选在缓存区的厂房
        this.checkFactoryInBuffer('line')
      } catch (error) {
        console.error('处理路径列表时发生错误:', error)
      }
    },
    checkFactoryInBuffer(type, pointInfo) {
      if (!this.factoryGeoJSON || !this.bufferLayerList.length) {
        this.$message.warning('厂房数据或缓冲区数据未加载')
        return
      }
      if (JSON.parse(Cookies.get('minTurnRadius')).length == 0) {
        this.$message.warning('请先选择车辆')
        return
      }

      // 将缓冲区数据转换为 Turf.js 的 FeatureCollection
      // 遍历每个厂房
      const factoryGeoJSON = JSON.parse(JSON.stringify(this.factoryGeoJSON))
      const factoryPromises = factoryGeoJSON.features.map((factory) => {
        return new Promise((resolve, reject) => {
          // 检查几何对象的类型
          if (factory.geometry.type === 'MultiPolygon') {
            // 创建多边形集合（MultiPolygon）
            const factoryMultiPoly = turf.multiPolygon(factory.geometry.coordinates)
            // 计算整个多边形集合的面积
            const area = turf.area(factoryMultiPoly)
            // 计算工厂多边形集合的边界框
            const [minX, minY, maxX, maxY] = turf.bbox(factoryMultiPoly)

            // 筛选与工厂边界框相交的缓冲区
            const candidates = this.bufferLayerList.filter((buffer) => {
              const [bminX, bminY, bmaxX, bmaxY] = turf.bbox(buffer)
              return !(bmaxX < minX || bminX > maxX || bmaxY < minY || bminY > maxY)
            })
            // 精确相交检测
            let isInside = false
            for (const buffer of candidates) {
              if (turf.booleanIntersects(factoryMultiPoly, buffer)) {
                // 如果工厂在缓冲区内，绘制所有多边形
                isInside = true
                this.drawFactory(factory.geometry.coordinates, factory, area, pointInfo)
                break
              }
            }
            // 如果工厂不在任何缓冲区内
            resolve()
          } else {
            reject(new Error('不支持的几何类型'))
          }
        })
      })
      // 确保所有工厂处理完成后进行排序
      Promise.allSettled(factoryPromises)
        .then(async (results) => {
          // 只有路线隐蔽规划需要塞入车辆 点的不需要
          // 所有工厂处理完成，进行排序 按照距离近到远
          this.accordFactoryInfo.sort((a, b) => a.distance - b.distance)
          // 拿到当前的车队车辆信息 并且算出面积 按照从大到小排序
          const areaList = JSON.parse(Cookies.get('minTurnRadius'))
          areaList.map((item) => {
            item.area = Number(item.long) * Number(item.width)
          })
          areaList.sort((a, b) => b.area - a.area)
          // 初始化每个工厂的剩余面积
          this.accordFactoryInfo.forEach((factory) => {
            factory.remainingArea = factory.area // 记录每个工厂的剩余可用面积
            factory.vehicles = [] // 确保每个工厂都有一个 vehicles 属性
          })
          // 遍历每个车辆，尝试塞入工厂
          areaList.forEach((vehicle) => {
            let isPlaced = false

            // 遍历每个工厂，尝试塞入车辆
            for (let i = 0; i < this.accordFactoryInfo.length; i++) {
              const factory = this.accordFactoryInfo[i]

              // 检查工厂是否还有剩余面积
              if (factory.remainingArea >= vehicle.area) {
                // 塞入车辆
                factory.vehicles.push({
                  ...vehicle,
                  remainingArea: factory.remainingArea - vehicle.area, // 记录车辆塞入后的工厂剩余面积
                })

                // 更新工厂的剩余面积
                factory.remainingArea -= vehicle.area

                // 标记车辆已放置
                isPlaced = true
                break
              }
            }

            // 如果车辆没有被放置，可以在这里处理（例如记录日志或显示警告）
            if (!isPlaced) {
              console.warn(`车辆 ${vehicle.id} 无法放置在任何工厂中`)
            }
          })

          // 更新 this.accordFactoryInfo
          this.accordFactoryInfo = this.accordFactoryInfo.map((factory) => {
            // 确保每个工厂都有 vehicles 属性
            if (!factory.vehicles) {
              factory.vehicles = []
            }
            // 确保 remainingArea 是一个数字且大于 0
            factory.area = factory.area > 0 ? factory.area : 0
            return factory
          })
          // 过滤出有车辆的工厂
          const factoriesWithVehicles = this.accordFactoryInfo.filter((factory) => factory.vehicles.length > 0)
          this.factoriesWithVehicles = factoriesWithVehicles
          await this.showAreaInfoDialog(factoriesWithVehicles)
        })
        .catch((error) => {
          console.error('数据有问题', error)
        })
    },
    drawFactory(factoryMultiPoly, factory, area, pointInfo) {
      // 获取当前多边形集合的中心点
      const center = turf.center(turf.multiPolygon(factory.geometry.coordinates))
      // 将中心点转换为 Mars3D 的 LngLatPoint 对象
      const popupPosition = new mars3d.LngLatPoint(center.geometry.coordinates[0], center.geometry.coordinates[1])
      // 遍历每个多边形集合
      factory.geometry.coordinates[0].forEach((coordGroup) => {
        // 创建一个多边形图形
        const graphic = new window.mars3d.graphic.PolygonEntity({
          positions: coordGroup.map((coord) => Cesium.Cartesian3.fromDegrees(coord[0], coord[1], 0)),
          style: {
            color: 'red',
            opacity: 0.4,
            outline: true,
            outlineWidth: 1,
            outlineColor: '#ffffff',
            properties: {...factory.properties},
          },
          time: new Date().getTime(),
        })
        this.accordFactoryLayer.addGraphic(graphic)
        // 计算多边形中心与参考点的距离
        const point = pointInfo && pointInfo.length > 0 ? pointInfo : this.form.endPoint.split(',').map(Number)
        const distance = turf.distance(center.geometry.coordinates, point, {units: 'kilometers'}) * 1000 // 米
        // 将多边形图形添加到地图层
        this.accordFactoryInfo.push({
          ...graphic,
          distance: distance,
          popupPosition: popupPosition,
          area:
            this.hideform.redundancy && this.hideform.redundancy != 0 && area > 0
              ? area * (100 - this.hideform.redundancy) * 0.01
              : area > 0
              ? area
              : 0, // 如果 area 不是有效值，设置为 0 或其他默认值
        })
      })
    },
    // 显示面积信息弹框的方法
    async showAreaInfoDialog(info) {
      const graphics = this.accordFactoryLayer.getGraphics()
      const promises = []
      info.forEach((item) => {
        graphics.forEach((ele) => {
          if (
            ele.options.time === item.options.time &&
            ele.options.style.properties.FID_1 === item.options.style.properties.FID_1
          ) {
            const textInfo = `${item.area.toFixed(2)}㎡ \n（${item.vehicles.map((e) => e.name).join(',')}）`
            const labelGraphic = new window.mars3d.graphic.LabelEntity({
              id: 'label',
              position: item.popupPosition,
              style: {
                text: String(textInfo), // 必须字符串
                font_family: '楷体',
                font_size: 24,
                color: '#ffffff',
                outline: true,
                outlineColor: '#000000',
                background: true,
                backgroundColor: '#2f705f',
              },
            })
            // 使用 Promise 确保标签添加完成后继续执行
            const promise = new Promise((resolve, reject) => {
              this.accordFactoryLayer.addGraphic(labelGraphic, () => {
                resolve()
              })
            })

            promises.push(promise)
          }
        })
      })
      this.$message.success('路线隐蔽规划成功')
      const popupPositionList = info.map((item) => item.popupPosition)
      let minLng = Infinity
      let maxLng = -Infinity
      let minLat = Infinity
      let maxLat = -Infinity

      popupPositionList.forEach((point) => {
        if (point.lng < minLng) minLng = point.lng
        if (point.lng > maxLng) maxLng = point.lng
        if (point.lat < minLat) minLat = point.lat
        if (point.lat > maxLat) maxLat = point.lat
      })
      // 创建一个矩形区域，包含所有点
      const rectangle = Cesium.Rectangle.fromDegrees(minLng, minLat, maxLng, maxLat)

      this.viewer.scene.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(
          (minLng + maxLng) / 2, // 中心经度
          (minLat + maxLat) / 2, // 中心纬度
          1000 // 增加高度，确保视野范围足够大
        ),
        orientation: {
          heading: Cesium.Math.toRadians(0), // 方位角
          pitch: Cesium.Math.toRadians(-90), // 俯仰角
          roll: 0.0, // 翻滚角
        },
        duration: 2, // 飞行动画持续时间，单位为秒
      })
    },
    // 弹框
    async openDialog() {
      this.multipleSelection = []
      await fetch('./data/minTurnRadius.json')
        .then((response) => {
          return response.json()
        })
        .then(async (data) => {
          this.dialogVisible = true
          this.tableData = data
          await this.$nextTick(() => {
            this.multipleSelection = JSON.parse(Cookies.get('minTurnRadius'))
            this.multipleSelection.forEach((item) => {
              this.$refs.vxeTable.setCheckboxRowKey(item.id, true)
            })
          })
        })
        .catch((error) => {})
    },
    handleSelectionChange({records}) {
      this.multipleSelection = records
    },
    closeSelection() {
      this.dialogVisible = false
    },
    confirmSelection() {
      if (this.multipleSelection.length === 0) {
        this.$message.warning('请至少选择一行数据')
        return
      }
      Cookies.set('minTurnRadius', this.multipleSelection)
      const maxValues = this.multipleSelection.reduce(
        (acc, item) => {
          acc.width = Math.max(acc.width, item.width)
          acc.load = Math.max(acc.load, item.load)
          acc.minTurnRadius = Math.max(acc.minTurnRadius, item.minTurnRadius)
          return acc
        },
        {width: 0, load: 0, minTurnRadius: 0}
      )
      this.inputform.width = maxValues.width
      this.inputform.load = maxValues.load
      this.inputform.minTurnRadius = maxValues.minTurnRadius
      this.closeSelection()
    },
    /** 增删改查 */
    handleAdd() {
      const newRow = {
        id: this.tableData.length + 1,
        name: '',
        long: null,
        width: null,
        load: null,
        minTurnRadius: null,
        editing: true,
      }
      this.tableData.push(newRow)
    },
    handleDelete(row) {
      const index = this.tableData.findIndex((item) => item.id === row.id)
      if (index !== -1) {
        this.tableData.splice(index, 1)
      }
    },
    handleEdit(row) {
      this.$set(row, 'editing', true)
    },
    handleSave(row) {
      this.$set(row, 'editing', false)
    },
    // 保存列表数据
    suerCofirm() {
      const parsedData = iniParser.parse(configIni)
      axios
        .post(
          `http://${parsedData.http.address}:${parsedData.http.port}/api/equpment`,
          JSON.stringify(this.tableData),
          {
            headers: {
              Authorization: 'Bearer your_token_here',
              'Content-Type': 'application/json',
            },
          }
        )
        .then((response) => {
          this.$message.success('保存成功')
        })
        .catch((error) => {})
    },
    // 导入json文件
    triggerFileUpload() {
      this.$refs.fileInput.click()
    },
    handleFileUpload(event) {
      const file = event.target.files[0]
      if (file) {
        const reader = new FileReader()
        reader.onload = (e) => {
          try {
            const uploadedJson = JSON.parse(e.target.result)
            this.importJson(uploadedJson)
          } catch (error) {
            console.error('解析 JSON 文件失败:', error)
            this.$message.error('解析 JSON 文件失败')
          }
        }
        reader.readAsText(file)
      }
    },
    async importJson(uploadedJson) {
      if (!uploadedJson) {
        this.$message.warning('请先选择一个 JSON 文件')
        return
      }
      // 清除现有数据
      this.clear()
      // 加载起点
      if (uploadedJson.startPoint) {
        this.form.startPoint = uploadedJson.startPoint
        this.addPointToMap('startPoint', this.form.startPoint)
      }

      // 加载终点
      if (uploadedJson.endPoint) {
        this.form.endPoint = uploadedJson.endPoint
        this.addPointToMap('endPoint', this.form.endPoint)
      }

      // 加载途经点
      if (uploadedJson.viaPoints) {
        this.form.viaPoints = uploadedJson.viaPoints
        uploadedJson.viaPoints.forEach((viaPoint) => {
          this.addPointToMap('viaPoints', viaPoint, viaPoint.time)
        })
      }

      // 加载避让点
      if (uploadedJson.avoidPoints) {
        this.form.avoidPoints = uploadedJson.avoidPoints
        uploadedJson.avoidPoints.forEach((avoidPoint) => {
          this.addPointToMap('avoidPoints', avoidPoint, avoidPoint.time)
        })
      }

      // 加载避让区域
      if (uploadedJson.avoidAreas) {
        this.form.avoidAreas = uploadedJson.avoidAreas
        uploadedJson.avoidAreas.forEach((avoidArea) => {
          const time = Date.now()
          this.addPolygonToMap('avoidAreas', avoidArea, avoidArea.time)
        })
      }
    },
    addPointToMap(type, point, time) {
      const coords = time ? point.points.split(',').map(Number) : point.split(',').map(Number)
      const graphic = new window.mars3d.graphic.PointEntity({
        position: new window.mars3d.LngLatPoint(coords[0], coords[1]),
        style: {
          pixelSize: 10,
          color: type === 'startPoint' ? 'red' : type === 'endPoint' ? 'red' : type === 'viaPoints' ? 'blue' : 'orange',
          label: {
            text:
              type === 'startPoint'
                ? '起点'
                : type === 'endPoint'
                ? '终点'
                : type === 'viaPoints'
                ? '途经点'
                : '避让点',
            font_size: 20,
            color: '#ffffff',
            outline: true,
            outlineColor: '#000000',
            pixelOffsetY: -20,
          },
          time: time,
        },
      })
      this.graphicLayer.addGraphic(graphic)

      if (type === 'startPoint') {
        this.pointQD = graphic
      } else if (type === 'endPoint') {
        this.pointZD = graphic
      } else if (type === 'viaPoints') {
        this.viaPoints.push(graphic)
      } else if (type === 'avoidPoints') {
        this.avoidPoints.push(graphic)
      }
    },
    addPolygonToMap(type, area, time) {
      const coords = JSON.parse(area.points)
      const graphic = new window.mars3d.graphic.PolygonEntity({
        positions: coords.map((coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])),
        style: {
          color: 'red',
          opacity: 0.4,
          clampToGround: true,
          outline: true,
          outlineWidth: 1,
          outlineColor: '#ffffff',
          time: time,
        },
      })
      this.graphicLayer.addGraphic(graphic)

      if (type === 'avoidAreas') {
        this.avoidAreas.push(graphic)
      }
    },
    // 输入框失去焦点 反向编辑点
    pointsChange(type, row) {
      if (type === 'startPoint') {
        if (
          (!this.form.startPoint ||
            this.form.startPoint == '' ||
            this.form.startPoint == null ||
            this.form.startPoint == undefined) &&
          this.pointQD
        ) {
          this.pointQD.remove()
          this.pointQD = null
          return
        }
        if (this.pointQD == null || this.pointQD == undefined || this.pointQD == '') {
          this.addPointToMap('startPoint', this.form.startPoint)
        } else {
          this.updatePointPosition(this.pointQD, this.form.startPoint)
        }
      } else if (type === 'endPoint') {
        if (
          (!this.form.endPoint ||
            this.form.endPoint == '' ||
            this.form.endPoint == null ||
            this.form.endPoint == undefined) &&
          this.pointZD
        ) {
          this.pointZD.remove()
          this.pointZD = null
          return
        }
        if (this.pointZD == null || this.pointZD == undefined || this.pointZD == '') {
          this.addPointToMap('endPoint', this.form.endPoint)
        } else {
          this.updatePointPosition(this.pointZD, this.form.endPoint)
        }
      } else if (type === 'viaPoints') {
        if (!row.points) {
          const graphic = this.viaPoints.find((viaPoint) => viaPoint.style.time === row.time)
          if (this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') {
            // 如果只剩下一个空项，不删除图形，清空输入框值
            this.form.viaPoints[0].points = ''
            graphic?.remove()
            this.viaPoints = this.viaPoints.filter((viaPoint) => viaPoint.style.time !== row.time)
          } else {
            this.form.viaPoints = this.form.viaPoints.filter((viaPoint) => viaPoint.time !== row.time)
          }
          graphic?.remove()
          this.viaPoints = this.viaPoints.filter((viaPoint) => viaPoint.style.time !== row.time)
        } else {
          const graphic = this.viaPoints.find((viaPoint) => viaPoint.style.time === row.time)
          this.updatePointPosition(graphic, row.points)
        }
      } else if (type === 'avoidPoints') {
        if (!row.points) {
          const graphic = this.avoidPoints.find((avoidPoint) => avoidPoint.style.time === row.time)
          if (this.form.avoidPoints.length === 1 && this.form.avoidPoints[0].points === '') {
            // 如果只剩下一个空项，不删除图形，清空输入框值
            this.form.avoidPoints[0].points = ''
          } else {
            this.form.avoidPoints = this.form.avoidPoints.filter((avoidPoint) => avoidPoint.time !== row.time)
          }
          graphic?.remove()
          this.avoidPoints = this.avoidPoints.filter((avoidPoint) => avoidPoint.style.time !== row.time)
        } else {
          const graphic = this.avoidPoints.find((avoidPoint) => avoidPoint.style.time === row.time)
          this.updatePointPosition(graphic, row.points)
        }
      } else if (type === 'avoidAreas') {
        if (!row.points) {
          const graphic = this.avoidAreas.find((avoidArea) => avoidArea.style.time === row.time)
          if (this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') {
            // 如果只剩下一个空项，不删除图形，清空输入框值
            this.form.avoidAreas[0].points = ''
          } else {
            this.form.avoidAreas = this.form.avoidAreas.filter((avoidArea) => avoidArea.time !== row.time)
          }
          graphic?.remove()
          this.avoidAreas = this.avoidAreas.filter((avoidArea) => avoidArea.style.time !== row.time)
        } else {
          const graphic = this.avoidAreas.find((avoidArea) => avoidArea.style.time === row.time)
          this.updatePolygonPosition(graphic, row.points)
        }
      }
    },
    handleEmptyArray(type) {
      if (type === 'viaPoints' && this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') {
        this.form.viaPoints = []
      } else if (
        type === 'avoidPoints' &&
        this.form.avoidPoints.length === 1 &&
        this.form.avoidPoints[0].points === ''
      ) {
        this.form.avoidPoints = []
      } else if (type === 'avoidAreas' && this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') {
        this.form.avoidAreas = []
      }
    },
    updatePointPosition(graphic, pointsStr) {
      if (!graphic) return
      const coords = pointsStr.split(',').map(Number)
      if (coords.length === 2) {
        graphic.position = new window.mars3d.LngLatPoint(coords[0], coords[1])
      }
    },
    updatePolygonPosition(graphic, pointsStr) {
      if (!graphic) return
      try {
        const coords = JSON.parse(pointsStr)
        graphic.positions = coords.map((coord) => new window.mars3d.LngLatPoint(coord[0], coord[1]))
      } catch (error) {
        graphic.remove()
      }
    },
    drawStartPoint() {
      if (this.pointQD) {
        this.pointQD.remove()
        this.pointQD = null
        this.form.startPoint = ''
      }
      this.graphicLayer.startDraw({
        type: 'point',
        style: {
          pixelSize: 10,
          color: 'red',
          label: {
            text: '起点',
            font_size: 20,
            color: '#ffffff',
            outline: true,
            outlineColor: '#000000',
            pixelOffsetY: -20,
          },
        },
        success: (graphic) => {
          this.pointQD = graphic
          this.form.startPoint = [
            graphic.toGeoJSON().geometry.coordinates[0],
            graphic.toGeoJSON().geometry.coordinates[1],
          ].join(',')
        },
      })
    },
    drawEndPoint() {
      if (this.pointZD) {
        this.pointZD.remove()
        this.pointZD = null
        this.form.endPoint = ''
      }
      this.graphicLayer.startDraw({
        type: 'point',
        style: {
          pixelSize: 10,
          color: 'red',
          label: {
            text: '终点',
            font_size: 20,
            color: '#ffffff',
            outline: true,
            outlineColor: '#000000',
            pixelOffsetY: -20,
          },
        },
        success: (graphic) => {
          this.pointZD = graphic
          this.form.endPoint = [
            graphic.toGeoJSON().geometry.coordinates[0],
            graphic.toGeoJSON().geometry.coordinates[1],
          ].join(',')
        },
      })
    },
    // 途经点
    drawViaPoint() {
      const time = Date.now()
      this.graphicLayer.startDraw({
        type: 'point',
        style: {
          pixelSize: 10,
          color: 'blue',
          label: {
            text: '途经点',
            font_size: 20,
            color: '#ffffff',
            outline: true,
            outlineColor: '#000000',
            pixelOffsetY: -20,
          },
          time: time,
        },
        success: (graphic) => {
          this.viaPoints.push(graphic)
          const points = [
            graphic.toGeoJSON().geometry.coordinates[0],
            graphic.toGeoJSON().geometry.coordinates[1],
          ].join(',')
          if (
            this.form.viaPoints.length == 1 &&
            this.form.viaPoints[0].points == '' &&
            !this.form.viaPoints[0].points
          ) {
            this.form.viaPoints[0].points = points
            this.form.viaPoints[0].time = time
          } else {
            this.form.viaPoints.push({points, time})
          }
        },
      })
    },
    // 避让点
    drawAvoidPoint() {
      const time = Date.now()
      this.graphicLayer.startDraw({
        type: 'point',
        style: {
          pixelSize: 10,
          color: 'orange',
          label: {
            text: '避让点',
            font_size: 20,
            color: '#ffffff',
            outline: true,
            outlineColor: '#000000',
            pixelOffsetY: -20,
          },
          time: time,
        },
        success: (graphic) => {
          this.avoidPoints.push(graphic)
          const points = [
            graphic.toGeoJSON().geometry.coordinates[0],
            graphic.toGeoJSON().geometry.coordinates[1],
          ].join(',')
          if (
            this.form.avoidPoints.length == 1 &&
            this.form.avoidPoints[0].points == '' &&
            !this.form.avoidPoints[0].points
          ) {
            this.form.avoidPoints[0].points = points
            this.form.avoidPoints[0].time = time
          } else {
            this.form.avoidPoints.push({points, time})
          }
        },
      })
    },
    // 避让区域
    drawAvoidArea() {
      const time = Date.now()
      this.graphicLayer.startDraw({
        type: 'polygon',
        drawEndEventType: window.mars3d.EventType.dblClick,
        style: {
          color: '#ff0000',
          opacity: 0.4,
          clampToGround: true,
          outline: true,
          outlineWidth: 1,
          outlineColor: '#ffffff',
          time: time,
        },
        success: (graphic) => {
          this.avoidAreas.push(graphic)
          const avoidAreasGeoJSON = graphic.toGeoJSON()
          const points = JSON.stringify(avoidAreasGeoJSON.geometry.coordinates[0])
          if (
            this.form.avoidAreas.length == 1 &&
            this.form.avoidAreas[0].points == '' &&
            !this.form.avoidAreas[0].points
          ) {
            this.form.avoidAreas[0].points = points
            this.form.avoidAreas[0].time = time
          } else {
            this.form.avoidAreas.push({points, time})
          }
        },
      })
    },
    // 1. 构建路网拓扑图（经纬度坐标直接处理
    buildGraph(geojson) {
      const graph = {}
      const nodeCoords = {} // 存储节点经纬度

      geojson.features.forEach((road) => {
        const startNode = road.properties.FNODE_
        const endNode = road.properties.TNODE_
        const coords = road.geometry.coordinates

        // 记录节点经纬度（取首尾点）
        if (!nodeCoords[startNode]) {
          nodeCoords[startNode] = coords[0][0]
        }
        if (!nodeCoords[endNode]) {
          nodeCoords[endNode] = coords[coords.length - 1][0]
        }
        // 计算边权重（距离，单位：米）
        const distance =
          turf.distance(turf.point(coords[0][0]), turf.point(coords[coords.length - 1][0]), {units: 'kilometers'}) *
          1000

        // 构建邻接表（双向图）
        graph[startNode] = graph[startNode] || {}
        graph[startNode][endNode] = distance

        graph[endNode] = graph[endNode] || {}
        graph[endNode][startNode] = distance
      })
      return {graph, nodeCoords}
    },
    // 2. 匹配最近路网节点（经纬度坐标）
    findNearestNode(pointCoord, nodeCoords) {
      let nearestNode = null
      let minDist = 10000

      for (const [node, coord] of Object.entries(nodeCoords)) {
        const dist = turf.distance(turf.point(pointCoord), turf.point(coord), {
          units: 'meters',
        })

        if (dist < minDist) {
          minDist = dist
          nearestNode = node
        }
      }
      return nearestNode
    },
    // 3. 路径规划主函数（经纬度坐标输入） - 支持途经点 + 避让点/区域
    async planRoute(startCoord, endCoord, viaPoints = [], avoidObstacles = null) {
      const {graph, nodeCoords} = this.roadNetworkGeoJSONBuild

      // 按顺序组合点：起点 -> 途经点 -> 终点
      const points = [startCoord]
      if (viaPoints && viaPoints.length > 0) {
        viaPoints.forEach((viaPoint) => {
          points.push(viaPoint.geometry.coordinates)
        })
      }
      points.push(endCoord)
      const fullPath = []
      const infoList = []
      for (let i = 0; i < points.length - 1; i++) {
        const segmentStart = points[i]
        const segmentEnd = points[i + 1]

        // 匹配最近节点
        const startNode = this.findNearestNode(segmentStart, nodeCoords)
        const endNode = this.findNearestNode(segmentEnd, nodeCoords)

        if (!startNode || !endNode) {
          console.log('无法匹配到路网节点，请检查坐标是否在路网范围内')
          continue
        }
        // 构建临时 graph
        const tempGraph = JSON.parse(JSON.stringify(graph))

        // 删除避让点节点
        if (avoidObstacles) {
          const obstacleNodes = []
          for (const [node, coord] of Object.entries(nodeCoords)) {
            const pt = turf.point(coord)
            avoidObstacles.features.forEach((ob) => {
              if (turf.booleanPointInPolygon(pt.geometry, ob.geometry)) obstacleNodes.push(node)
            })
          }
          obstacleNodes.forEach((node) => delete tempGraph[node])

          // 删除与避让区域相交的边
          for (const [node, edges] of Object.entries(tempGraph)) {
            for (const targetNode of Object.keys(edges)) {
              if (!tempGraph[targetNode]) {
                // 避让点节点已经删除
                delete tempGraph[node][targetNode]
                continue
              }
              const line = turf.lineString([nodeCoords[node], nodeCoords[targetNode]])
              avoidObstacles.features.forEach((area) => {
                if (turf.booleanCrosses(line, area)) {
                  delete tempGraph[node][targetNode]
                }
              })
            }
          }
        }

        // Dijkstra 计算最短路径
        const pathNodes = dijkstra.find_path(tempGraph, startNode, endNode)
        if (!pathNodes || pathNodes.length === 0) {
          console.log('未找到可行路径段:', i)
          continue
        }

        // 生成路径几何
        for (let j = 0; j < pathNodes.length - 1; j++) {
          const currentNode = pathNodes[j]
          const nextNode = pathNodes[j + 1]
          let segment = {}
          // 是否参与路线规划 是 加入机动属性的判断 否就正常走
          if (!this.join) {
            segment = this.roadNetworkGeoJSON.features.find(
              (f) =>
                (f.properties.FNODE_ == currentNode && f.properties.TNODE_ == nextNode) ||
                (f.properties.FNODE_ == nextNode && f.properties.TNODE_ == currentNode)
            )
          } else {
            segment = this.roadNetworkGeoJSON.features.find(
              (f) =>
                ((f.properties.FNODE_ == currentNode && f.properties.TNODE_ == nextNode) ||
                  (f.properties.FNODE_ == nextNode && f.properties.TNODE_ == currentNode)) &&
                f.properties.载重吨 >= this.inputform.load &&
                f.properties.宽度 >= this.inputform.width &&
                f.properties.曲率半 <= this.inputform.minTurnRadius
            )
          }
          if (segment) {
            fullPath.push(...segment.geometry.coordinates[0])
            infoList.push(segment)
          }
        }
      }

      return {fullPath, infoList}
    },
    async calculateShortestPath() {
      if (!this.pointQD || !this.pointZD || !this.roadNetworkGeoJSON) {
        this.$message.warning('请先加载路网数据并绘制障碍面、起点和终点！')
        return
      }
      this.shortestPathLayer.clear()
      this.shortestPathList = []
      this.infoList = []
      const startPoint = turf.point(this.pointQD.toGeoJSON().geometry.coordinates).geometry.coordinates // 起点
      const endPoint = turf.point(this.pointZD.toGeoJSON().geometry.coordinates).geometry.coordinates // 终点
      // 途经点
      const viaPointsGeoJSON = this.viaPoints.map((point) => point.toGeoJSON()) || []
      const viaPointsTurf = viaPointsGeoJSON.map((p) => turf.point(p.geometry.coordinates))
      // 避让点
      const avoidPointsGeoJSON = this.avoidPoints.map((point) => point.toGeoJSON()) || []
      const avoidPointsPolygons = avoidPointsGeoJSON.map((point) => {
        return turf.circle(
          turf.point(point.geometry.coordinates),
          1000, // 半径10米（根据需求调整）
          {steps: 32, units: 'meters'} // 显式指定单位
        )
      })
      // 避让区域
      const avoidAreasGeoJSON = this.avoidAreas.map((area) => area.toGeoJSON({closure: true})) || []
      const obstaclesGeoJSON = turf.featureCollection([...avoidPointsPolygons, ...avoidAreasGeoJSON])
      const route = await this.planRoute(startPoint, endPoint, viaPointsTurf, obstaclesGeoJSON)
      this.drawPath(route)
    },

    // 单独的路径绘制方法
    drawPath(path) {
      const positions = path
      if (positions.fullPath.length == 0) return
      const polyline = new window.mars3d.graphic.PolylinePrimitive({
        positions: positions.fullPath,
        style: {
          clampToGround: true,
          color: '#55ff33',
          width: 8,
        },
      })
      this.shortestPathLayer.addGraphic(polyline)
      this.shortestPathList.push(path.infoList)
      this.infoList = path.infoList.map((item) => item.properties)
    },
    /** 隐蔽规划 */
    concealed() {},
  },
}
</script>

<style scoped>
.home-header {
  height: 60px;
  line-height: 60px;
  display: flex;
  align-items: center;
  padding-left: 34px;
  box-sizing: border-box;
  background: #abc6bc;
}
.home-header img {
  height: 24px;
  width: 24px;
  margin-right: 12px;
  cursor: pointer;
}
.sure {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  /* padding: 4px 12px; */
  gap: 10px;
  background: #176363;
  border-radius: 4px;
  min-width: 14px;
  padding: 0 10px;
  height: 24px;
  color: #ffffff;
  font-weight: 400;
  font-size: 14px;
  margin-right: 10px;
  cursor: pointer;
}
.dialog-body {
  max-height: 500px;
}
.home {
  display: flex;
  height: calc(100% - 60px);
  background: #abc6bc;
}
.main-container {
  width: 340px;
  height: 100%;
  background: #d4e5db;
  overflow: hidden;
  overflow-y: auto;
  scrollbar-width: none; /* 隐藏滚动条（Firefox） */
}

.main-container::-webkit-scrollbar {
  display: none; /* 隐藏滚动条（Chrome, Safari, Edge） */
}

.control-panel {
  width: 340px;
  padding: 20px 26px;
  background-size: cover;
  box-sizing: border-box;
}

.control-panel .title {
  /* text-align: center; */
  margin-bottom: 10px;
  color: #1c1c1c;
  display: flex;
  justify-content: space-between;
}
.control-panel .title .joinCheck {
  font-size: 14px;
  color: #555;
}
.el-checkbox {
  margin-right: 5px !important;
}

.importJson {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  background: #2f705f;
  border-radius: 4px;
  color: #fff;
  width: 260px;
  height: 24px;
  font-size: 14px;
  text-align: center;
  margin-left: 20px;
  cursor: pointer;
}

.form-group {
  margin-bottom: 10px;
}

.form-group input,
.form-group textarea {
  width: 100%;
  padding: 5px;
  border-radius: 3px;
  border: none;
}

.form-actions {
  display: flex;
  justify-content: space-between;
}

#map,
#mapbox,
.el-main {
  flex: 1;
  width: calc(100vw- 792px);
  height: 100%;
}
.popDiloag {
  width: 100px;
  font-size: 16px;
  background: #d4e5db;
  color: #1c1c1c;
}
.popDiloag .popDiloag-title {
  font-weight: 500;
}
</style>
