<!--
 * @Author: ysh
 * @Date: 2024-06-21 18:51:49
 * @LastEditors: wrh
 * @LastEditTime: 2026-02-03 11:35:08
-->
<template>
  <div class="warpper-container">
    <!-- 地图 -->
    <div class="map-container" id="maps" tabindex="0"></div>
    <!-- 鼠标移动坐标 -->
    <div id="mouse-position"></div>
    <!-- 项目点位是否显示 -->
    <div class="projectpoint-switch">
      <el-checkbox fill="#fff" v-model="checkedCluster" label="项目点位" border size="large" @change="switchCluster" />
    </div>
    <!-- 工具栏列表 -->
    <div class="tool-box">
      <div class="item">
        <el-tooltip effect="dark" content="图层" placement="right">
          <div class="layers" @click="layersOpen = !layersOpen"></div>
        </el-tooltip>
      </div>
      <div class="item">
        <el-tooltip effect="dark" content="矩形框选" placement="right">
          <div class="select" @click="rectSelect()"></div>
        </el-tooltip>
      </div>
      <div class="item">
        <el-tooltip effect="dark" content="多边形框选" placement="right">
          <div class="selectM" @click="polygonSelect()"></div>
        </el-tooltip>
      </div>
      <div class="item">
        <el-tooltip effect="dark" content="视角复位" placement="right">
          <div class="view" @click="resetView()"></div>
        </el-tooltip>
      </div>
    </div>
    <!-- 信息提示框 -->
    <el-alert class="alter-position" title="开始矩形框选，按下ESC取消框选，按下Enter搜索框选范围内的项目" type="warning" show-icon
      v-if="selectedInfo" @close="selectedInfo = false" />
    <!-- 地图样式 -->
    <div class="switch-map">
      <switch-map></switch-map>
    </div>
    <!-- <transition-group appear name="animate__animated animate__bounce" enter-active-class="animate__fadeInLeft"
      leave-active-class="animate__fadeOutLeft"> -->
    <div class="layer-type dialog_wrap" v-if="layersOpen" @mousedown.stop="move">
      <div class="layer-content">
        <div class="layer-header">
          图层管理
          <span class="layer-closer" @click="closeLayer"></span>
        </div>
        <el-tabs v-model="activeName" class="demo-tabs">
          <el-tab-pane label="项目图层" name="first">
            <project-layer :proTree="projectList" :maps="map"></project-layer>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
    <!-- </transition-group> -->
    <!-- 项目信息弹出框 -->
    <div id="popup" class="ol-popup" v-if="clickFeature != null">
      <span class="ol-popup-closer" @click="closePopup"></span>
      <div id="popup-content">
        <el-descriptions :column="1" border v-if="clickFeature.type == 'projectPoint'">
          <el-descriptions-item label="项目编号" width="130px">
            {{ clickFeature.projectNumber }}
          </el-descriptions-item>
          <el-descriptions-item label="项目名称" width="130px">
            {{ clickFeature.projectName }}
          </el-descriptions-item>
          <el-descriptions-item label="项目负责人" width="130px">
            {{ getUserName(clickFeature.projectLeader) }}
          </el-descriptions-item>
          <el-descriptions-item label="存放地址" width="130px">
            {{ clickFeature.storageAddress == '' || clickFeature.storageAddress == null ? '暂无' :
              clickFeature.storageAddress }}
          </el-descriptions-item>
        </el-descriptions>

        <div v-if="clickFeature.type == 'featurePoint'">
          <div class="title">项目编号:{{ clickFeature.projectNumber }}</div>
          <el-descriptions :column="1" border>
            <el-descriptions-item label="名称" width="130px">
              <!-- {{ clickFeature.selectFeatures.values_.name }} -->
            </el-descriptions-item>
          </el-descriptions>
        </div>
      </div>
      <div class="look-achi" @click="openProject" v-if="clickFeature.type == 'projectPoint'">成果目录>></div>
    </div>
    <!-- 项目目录 -->
    <div class="right-project" :class="{ closeProBox: isOpenPro }">
      <div class="result-click" @click="isOpenPro = !isOpenPro">
        <i class="el-icon-d-arrow-left" v-if="isOpenPro"></i>
        <i class="el-icon-d-arrow-right" v-if="!isOpenPro"></i>
      </div>
      <div class="right-content">
        <div class="header">项目列表</div>
        <!-- 搜索栏 -->
        <div class="search-box">
          <el-input v-model="searchVal" placeholder="请输入......" @keyup.enter="queryProject">
            <template #prepend>
              <el-select v-model="searchType" placeholder="请选择" style="width: 125px">
                <el-option label="按项目编号" value="1" />
                <el-option label="按项目名称" value="2" />
                <el-option label="按项目类别" value="3" />
              </el-select>
            </template>
            <template #append>
              <el-button icon="el-icon-search" @click="queryProject" />
            </template>
          </el-input>
        </div>
        <el-divider />
        <!-- 项目数据 -->
        <div class="pro-catalogue" v-loading="loading">
          <el-table ref="myTable" :data="projectList" :height="tableHeight" border style="width: 100%;"
            :row-class-name="tableRowClassName" @row-click="handleRowClick">
            <el-table-column type="expand">
              <template slot-scope="props">
                <div class="expand-info">
                  <el-descriptions :column="2">
                    <el-descriptions-item label="存放地址" class="desLabel" :span="2">
                      {{ props.row.storageAddress == '' || props.row.storageAddress == null ? '暂无' :
                        props.row.storageAddress
                      }}
                    </el-descriptions-item>
                    <el-descriptions-item label="甲方单位" class="desLabel" :span="2">{{ props.row.partyA == null
                      ? '暂无' :
                      props.row.partyA.partyAName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="联系人" class="desLabel">{{ props.row.contactPerson == null ? '暂无' :
                      props.row.contactPerson
                    }}</el-descriptions-item>
                    <el-descriptions-item label="联系电话" class="desLabel">{{ props.row.telephone == null ? '暂无' :
                      props.row.telephone
                    }}</el-descriptions-item>
                    <el-descriptions-item label="项目类型" class="desLabel">{{ props.row.projectType == null ? '暂无' :
                      props.row.projectType
                    }}</el-descriptions-item>
                    <el-descriptions-item label="技术负责人" class="desLabel">{{ props.row.technicalDirectorUser == null ? '暂无'
                      :
                      props.row.technicalDirectorUser.nickName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="技术设计人" class="desLabel">{{ props.row.technicalDesignerUser == null ? '暂无'
                      :
                      props.row.technicalDesignerUser.nickName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="承担部门" class="desLabel">{{ props.row.undertakingSector == null ? '暂无' :
                      props.row.undertakingDeptName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="质量检查员" class="desLabel">{{ props.row.qualityInspectorName == null ? '暂无'
                      :
                      props.row.qualityInspectorName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="项目登记时间" class="desLabel" :span="2">{{ props.row.registerTime ==
                      null ? '暂无' :
                      props.row.registerTime
                    }}</el-descriptions-item>
                    <el-descriptions-item label="项目登记人" class="desLabel">{{ props.row.projectRegistrantUser == null ? '暂无'
                      :
                      props.row.projectRegistrantUser.nickName
                    }}</el-descriptions-item>
                    <el-descriptions-item label="进场时间" class="desLabel">{{ props.row.approachTime == null ? '暂无' :
                      props.row.entryTime
                    }}</el-descriptions-item>
                    <el-descriptions-item label="撤场时间" class="desLabel">{{ props.row.withdrawalTime == null ? '暂无' :
                      props.row.exitTime
                    }}</el-descriptions-item>
                    <el-descriptions-item label="项目要求完成时间" class="desLabel">{{ props.row.requiredCompletionDate == null
                      ? '暂无' :
                      props.row.requiredCompletionDate
                    }}</el-descriptions-item>
                  </el-descriptions>
                  <div class="look-achi" @click="lookThisAchi(props.row)">
                    查看成果>>
                  </div>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="kml范围" width="95" align="center" :formatter="formatterKmlurl" />
            <el-table-column prop="projectNumber" label="项目编号" width="95" align="center" />
            <el-table-column prop="projectName" label="项目名称" width="180" align="center" />
            <el-table-column prop="projectLeader" label="负责人" align="center">
              <template slot-scope="scope">
                {{ getUserName(scope.row.projectLeader) }}
              </template>
            </el-table-column>
          </el-table>
          <el-pagination @current-change="handleCurrentChange" :current-page.sync="queryParams.pageNum"
            :page-size="queryParams.pageSize" layout="total, prev, pager, next" :total="total">
          </el-pagination>
          <!-- <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
            :limit.sync="queryParams.pageSize" @pagination="getProjectList" /> -->
        </div>

        <!-- 成果目录 -->
        <div class="achi-list dialog_wrap" v-if="dialogTableVisible" @mousedown.stop="move">
          <div class="achi-content">
            <div class="achi-header">
              成果目录
              <span class="achi-closer" @click="closeAchi"></span>
            </div>
            <div class="achi-projectNumber">项目编号:{{ dialogTitle }}</div>
            <el-table :data="achiDialogData" height="400px">
              <el-table-column type="expand">
                <template #default="props">
                  <el-descriptions :column="2" size="small">
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="成果名称">{{
                        props.row.achiName
                      }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="数据年份">{{
                        props.row.dataYear }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="成果类型">{{ selectDictLabel(dict.type.cmc_achi_type, props.row.resultType)
                      }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="文件类型">{{
                        props.row.fileType }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="工作量">{{
                        props.row.workLoad }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="单位">{{
                        props.row.unit }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="大地基准">{{
                        props.row.geodeticDatum }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="分辨率">{{
                        props.row.resolution }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="比例尺或等级">{{ selectDictLabel(dict.type.cmc_scale_grade, props.row.scaleGrade)
                      }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="数据类型">{{
                        props.row.dataType }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="存放地址">{{
                        props.row.storageAddress }}</el-descriptions-item>
                    <el-descriptions-item min-width="195px" label-class-name="my-label" class-name="my-content"
                      label="提交时间">{{
                        props.row.submitDate }}</el-descriptions-item>
                  </el-descriptions>
                </template>
              </el-table-column>
              <el-table-column type="index" label="序号" width="50px" align="center" />
              <el-table-column prop="achiName" label="成果名称" align="center" show-overflow-tooltip />
              <el-table-column prop="dataYear" label="数据年份" align="center" />
            </el-table>
          </div>
        </div>
      </div>
    </div>


  </div>
</template>

<script>
import { Tianditu, ZhongKe, ArcGISBlue, Autonavi, google, terrain, vect } from '@/utils/maps'
import { listProject, getProject } from '@/api/oa/project/project'
import { getInfoByProjectNumbers } from '@/api/file/project'
import ProjectLayer from './index/projectLayer.vue';
import SwitchMap from './index/switchMap.vue';
import sjxActive from '@/assets/images/gis/sjd.png';
// ---------------------------------ol引用------------------------------------------------
import 'ol/ol.css'
import { Map, View } from 'ol';
// import XYZ from 'ol/source/XYZ';
// import VectorSource from 'ol/source/Vector';
import KML from 'ol/format/KML';
import Overlay from 'ol/Overlay';
import Feature from 'ol/Feature';
import { toLonLat } from 'ol/proj';
import TileLayer from 'ol/layer/Tile';
// import Draw from 'ol/interaction/Draw';
import { createBox } from 'ol/interaction/Draw';
import { Select, DragBox, Draw } from "ol/interaction";
import { platformModifierKeyOnly, never } from 'ol/events/condition';
import VectorLayer from 'ol/layer/Vector';
import { boundingExtent } from 'ol/extent';
import { Cluster, Vector as VectorSource, XYZ } from 'ol/source';
import { Point, Polygon, MultiPolygon, MultiLineString } from 'ol/geom';
import { toStringXY, createStringXY, toStringHDMS } from 'ol/coordinate';
import { Circle, Fill, Stroke, Style, RegularShape, Icon, Text } from 'ol/style';
import { MousePosition, ScaleLine, defaults as defaultControls } from 'ol/control';
import { getAchievementByProject, listAchievement } from "@/api/file/achievement";
export default {
  components: { SwitchMap, ProjectLayer },
  dicts: ['cmc_achi_type', 'cmc_scale_grade'],
  data() {
    return {
      queryParams: {
        pageNum: 1,
        pageSize: 10
      },
      map: {},
      control: null,
      view: null,
      select: null,
      popup: null,
      clusters: null,
      checkedCluster: true,
      drawBox: null,
      activeName: 'first',
      isDrawing: false,
      viewCenter: [105.55, 34.18],
      layersOpen: false,
      isOpenPro: false, //项目列表是否展开
      searchVal: '',
      searchType: '',
      projectList: [],
      allproTableData: [],
      achiDialogData: [],
      clusters: null,
      total: 0,
      loading: true,
      tableHeight: 0,
      selectedInfo: false,
      clickFeature: {},
      clickDatas: {
        selectFeatures: null,
        selectProjectNumber: "",
        type: '',
      },
      seletctedCluters: [],
      dialogTitle: '',
      dialogTableVisible: false,
    }
  },
  mounted() {
    this.setTableDomHeight();
    this.initMap();
    this.observer();
    let param = {
      pageNum: 1,
      pageSize: 10000,
    }
    if (this.$store.getters.roles.includes('projectLeader') && !this.$store.getters.roles.includes('leader')) {
      param.projectLeader = this.$store.getters.userId
      this.queryParams.projectLeader = this.$store.getters.userId
    }
    this.getProjectCluster(param); //地图数据集cluster对应allproTableData，此值不变    
    this.getProjectList(this.queryParams); //项目列表对应projectList，此值随搜索变化
  },
  methods: {
    // 设置侧边项目目录的高度
    setTableDomHeight() {
      let dom = document.querySelector('.right-project');
      dom.style.height = window.innerHeight - 110 + 'px'; //减去110为页头的高度
      let height = dom.offsetHeight - 28 + 25 - 179 //表格的高度，减去表头179，边距25，以及页码28
      this.resetHeight().then(() => {
        this.tableHeight = height
      })
    },
    resetHeight() {
      return new Promise((resolve, rehect) => {
        this.tableHeight = 0;
        resolve()
      })
    },
    // 初始化地图
    initMap() {
      this.view = new View({
        projection: "EPSG:4326", // 坐标系，有EPSG:4326和EPSG:3857
        center: this.viewCenter, // 中心点
        zoom: 5, // // 地图缩放级别(打开页面时默认级别)
        maxZoom: 20,
        minZoom: 1,  // 地图缩放最小级别
      })
      this.popup = new Overlay({
        element: document.getElementById('popup'),
        autoPan: {
          animation: {
            duration: 250,
          },
        },
      })
      this.control = new MousePosition({
        coordinateFormat: this.formatCoordinate(4),
        projection: 'EPSG:4326',
        className: 'custom-mouse-position',
        target: document.getElementById('mouse-position'),
      });
      this.map = new Map({
        target: 'maps',
        controls: defaultControls().extend([this.control]),
        layers: [
          Autonavi, Tianditu, ZhongKe,
          new TileLayer({//标注
            source: new XYZ({
              url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
            }),
            properties: {
              name: '标注'
            },
          }),
        ],
        view: this.view,
      })
      this.$store.commit('SET_MAP', this.map)
      this.map.addOverlay(this.popup);
      this.mapClick(this.map);
      // this.clickFeaturePopInfo();
      this.addKeyDownFun()
    },
    observer() {
      let that = this;
      // 选择需要观察变动的节点
      const targetNode = document.querySelector('.sidebar-container');
      // 观察器的配置（需要观察什么变动）
      const config = { attributes: true, childList: true, subtree: true }
      // 当观察到变动时执行的回调函数
      const callback = function (mutationsList, observer) {
        for (let mutation of mutationsList) {
          if (mutation.type === 'childList') {
          } else if (mutation.type === 'attributes') {
            that.map.updateSize();
          }
        }
      }
      // 创建一个观察器实例并传入回调函数
      const observer = new MutationObserver(callback);
      // 以上述配置开始观察目标节点
      observer.observe(targetNode, config);
    },
    addKeyDownFun() {
      // 添加键盘事件监听器  
      window.addEventListener('keydown', (event) => {
        if (event.key === 'Escape') { // 检查是否按下了 ESC 键  
          // 停止当前的绘制（或清除框选）  
          if (this.drawBox && this.drawBox.getActive()) {
            this.drawBox.finishDrawing(); // 如果有正在进行的绘制，结束它  
            // 如果需要清除之前的绘制结果，可以在这里添加逻辑  
            this.map.removeInteraction(this.drawBox);
          }
        }
      });
    },
    // 地图点击事件
    mapClick(map) {
      let that = this;
      map.on('singleclick', function (evt) {
        if (!that.isDrawing) {
          const coordinate = evt.coordinate;
          let features = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
            // 如果只需要知道有特征，而不关心具体是哪个，这里可以返回 true  
            // OpenLayers 会继续查找更多特征，但我们不需要  
            return feature.get('features');
          });
          // features 现在是一个数组，包含了在点击像素位置找到的所有特征  
          if (features && features.length > 0) {
            // 如果只有一个特征  
            if (features.length === 1) {
              let feature = features[0]; // 直接从数组中取第一个特征
              let projectId = feature.projectId;
              // 假设 getProject 是一个返回 Promise 的函数  
              getProject(projectId).then(res => {
                if (res.data) {
                  // 假设 this 在这里指向 Vue 组件实例或其他上下文  
                  that.clickFeature = res.data;
                  that.clickFeature.type = 'projectPoint';
                  that.popup.setPosition(coordinate);
                }
              })
            } else {
              // 如果有多个特征，这里可以根据需要处理  
              that.popup.setPosition(undefined);
            }
          } else {
            that.popup.setPosition(undefined);
          }


          that.clusters.getFeatures(evt.pixel).then((clickedFeatures) => {
            if (clickedFeatures.length) {
              // Get clustered Coordinates
              const features = clickedFeatures[0].get('features');
              if (features.length > 1) {
                const extent = boundingExtent(
                  features.map((r) => r.getGeometry().getCoordinates())
                );
                that.map.getView().fit(extent, { duration: 1000, padding: [100, 100, 100, 100] });
              }
            }
          });
        }
      })

      /* 键盘事件 */
      document.onkeydown = function (event) {
        let e = event || window.event || arguments.callee.caller.arguments[0];
        if (e && e.keyCode == 27) {
          if (that.drawBox.getActive()) {
            that.drawBox.finishDrawing();
            that.selectedInfo = false;
            that.map.removeInteraction(that.drawBox);
          }
        } else if (e && e.keyCode == 13) {
          let newArray = that.seletctedCluters.join(',');
          getInfoByProjectNumbers({ projectNumber: newArray, pageSize: that.queryParams.pageSize, pageNum: that.queryParams.pageNum }).then(res => {
            if (res.total > 0) {
              that.projectList = res.rows;
              that.total = res.total;
              if (that.isOpenPro == true) {
                that.isOpenPro = false;
              }
            } else {
              that.projectList = that.allproTableData;
              that.total = that.allproTableData.length;
            }
          })
        }
      };
    },

    clickFeaturePopInfo() {
      let that = this;
      if (that.select !== null) {
        that.map.removeInteraction(that.select);
      }
      that.select = new Select({
        style: this.selectedStyle
      })
      if (that.select !== null) {
        that.map.addInteraction(that.select);
        that.select.on('select', function (e) {
          if (e.target.getFeatures().getArray().length == 1) {
            that.clickFeature = e.target.getFeatures().getArray()[0];
            let properties = that.clickFeature.getProperties();
            if (!properties.features) {
              let fatherLayers = e.target.featureLayerAssociation_;
              // for (let layers in fatherLayers) {
              //   datas.selectProjectNumber = fatherLayers[layers].values_.title;
              // }
              let coordinate = e.mapBrowserEvent.coordinate;
              that.popup.setPosition(coordinate);
              that.clickFeature.type = 'featurePoint';
            }
          }
        })
      }
    },
    /* 关闭信息框 */
    closePopup() {
      this.popup.setPosition(undefined);
    },
    /* 关闭成果框 */
    closeAchi() {
      this.dialogTableVisible = false;
      this.dialogTitle = '';
      this.achiDialogData = [];
    },
    /* 关闭图层框 */
    closeLayer() {
      this.layersOpen = false;
    },
    openProject() {
      this.dialogTableVisible = true;
      let projectId = this.clickFeature.projectId;
      this.dialogTitle = this.clickFeature.projectNumber;
      listAchievement({ projectId: projectId, pageSize: 50, pageNum: 1 }).then(res => {
        if (res.total == 0) {
          this.$message.error('暂无成果，请添加');
          this.achiDialogData = [];
        } else {
          this.dialogTableVisible = true;
          this.achiDialogData = res.rows;
        }
      })
    },
    formatCoordinate(fractionDigits) {
      return (
        /**
         * @param {Coordinate} coordinate Coordinate.
         * @return {string} String XY.
         */
        function (coordinate) {
          return '经纬度：' + toStringXY(coordinate, fractionDigits);
        }
      );
    },
    resetView() {
      this.map.getView().setCenter(this.viewCenter);
      this.map.getView().setZoom(5)
    },
    rectSelect() {
      let that = this;
      that.select = new Select({
        condition: never,
        style: that.selectedStyle
      });
      // 创建框选图层
      let drawLayer = new VectorLayer({
        source: new VectorSource(),
      });
      // 创建绘制工具
      that.drawBox = new Draw({
        source: drawLayer.getSource(),
        type: 'Circle',
        geometryFunction: createBox()
      });
      that.drawBox.on('drawstart', function () {
        that.selectedInfo = true;
        that.seletctedCluters = [];
        that.select.getFeatures().clear();
        that.isDrawing = true;
        // drawLayer.getSource().clear();
      });
      // 结束绘制
      that.drawBox.on('drawend', function (e) {
        if (e.feature) {
          // 获取框选范围
          let geometry = e.feature.getGeometry();
          let extent = geometry.getExtent();
          // 查询框选范围内的所有点
          that.getLayerByName('clusters').getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
            that.select.getFeatures().push(feature);
          });
          // 遍历被选中的要素
          let selected = [];
          let selectedFeatures = that.select.getFeatures();
          for (let i = 0; i < selectedFeatures.getLength(); i++) {
            let feature = selectedFeatures.item(i);
            feature = feature.get('features');
            if (feature.length == 1) {
              let name = feature[0].name;
              selected.push(name);
            } else {
              for (let f of feature) {
                let name = f.name;
                selected.push(name);
              }
            }
            that.seletctedCluters = selected;
          }
        }
        that.isDrawing = false;
      })
      that.map.addInteraction(that.select);
      that.map.addInteraction(that.drawBox);
    },
    polygonSelect() {
      let that = this;
      that.select = new Select({
        condition: never,
        style: that.selectedStyle
      });
      // 创建框选图层
      let drawLayer = new VectorLayer({
        source: new VectorSource(),
      });
      // 创建绘制工具
      that.drawBox = new Draw({
        source: drawLayer.getSource(),
        type: 'Polygon',
      });
      that.drawBox.on('drawstart', function () {
        that.selectedInfo = true;
        that.seletctedCluters = [];
        that.select.getFeatures().clear();
        that.isDrawing = true;
        // drawLayer.getSource().clear();
      });
      // 结束绘制
      that.drawBox.on('drawend', function (e) {
        if (e.feature) {
          // 获取框选范围
          let geometry = e.feature.getGeometry();
          let extent = geometry.getExtent();
          // 查询框选范围内的所有点
          that.getLayerByName('clusters').getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
            let coordinates = feature.getGeometry().getCoordinates();
            // 判断该点是否在圆内部
            if (geometry.intersectsCoordinate(coordinates)) {
              that.select.getFeatures().push(feature);
            }
          });
          // 遍历被选中的要素
          let selected = [];
          let selectedFeatures = that.select.getFeatures();
          for (let i = 0; i < selectedFeatures.getLength(); i++) {
            let feature = selectedFeatures.item(i);
            feature = feature.get('features');
            if (feature.length == 1) {
              let name = feature[0].name;
              selected.push(name);
            } else {
              for (let f of feature) {
                let name = f.name;
                selected.push(name);
              }
            }
            that.seletctedCluters = selected;
          }
        }
        that.isDrawing = false;
      })
      that.map.addInteraction(that.select);
      that.map.addInteraction(that.drawBox);
    },
    /* 通过图层名称获取图层 */
    getLayerByName(name) {
      let allLayers = this.map.getLayers().getArray();
      let layer = undefined;
      if (allLayers.length) {
        for (let i = 0; i < allLayers.length; i++) {
          if (allLayers[i].get('name') === name) {
            layer = allLayers[i];
            break;
          }
        }
      }
      return layer;
    },
    getProjectCluster(queryParams) {
      this.loading = true
      listProject(queryParams).then(res => {
        let data = res.rows;
        this.total = res.total;
        this.allproTableData = data;
        this.loading = false;
        this.addProjectCluster(data);
      })
    },
    getProjectList(queryParams) {
      this.loading = true
      listProject(queryParams).then(res => {
        let data = res.rows;
        this.total = res.total;
        this.projectList = data;
        this.loading = false
      })
    },
    /* 格式化表格显示 */
    formatterKmlurl(row, cloumn) {
      if (row.projectKml == "" || row.projectKml == null) {
        return "无";
      } else {
        return "有";
      }
    },
    // 添加项目点在地图上
    addProjectCluster(data) {
      let features = []
      for (let d of data) {
        if (d.kmlLat && d.kmlLng) {
          let f = new Feature(new Point([Number(d.kmlLng), Number(d.kmlLat)]));
          f.name = d.projectNumber;
          f.projectId = d.projectId;
          features.push(f);
        }
      }
      let source = new VectorSource({
        features: features,
      });
      let clusterSource = new Cluster({
        distance: 100,     //群集之间的最小距离（以像素为单位）。
        source: source,	   //数据源
      });
      this.clusters = new VectorLayer({
        name: 'clusters',
        source: clusterSource,
        style: this.clusterStyle,
        zIndex: 99
      })
      this.map.addLayer(this.clusters);
      this.map.on('click', (e) => {
        this.clusters.getFeatures(e.pixel).then((clickedFeatures) => {
          if (clickedFeatures.length) {
            // Get clustered Coordinates
            const features = clickedFeatures[0].get('features');
            if (features.length > 1) {
              const extent = boundingExtent(
                features.map((r) => r.getGeometry().getCoordinates())
              );
              this.map.getView().fit(extent, { duration: 1000, padding: [100, 100, 100, 100] });
            }
          }
        });
      });
    },
    handleCurrentChange(val) {
      this.queryParams.pageNum = val
      if (this.seletctedCluters != []) {
        let newArray = this.seletctedCluters.join(',');
        getInfoByProjectNumbers({ projectNumber: newArray, pageSize: this.queryParams.pageSize, pageNum: this.queryParams.pageNum }).then(res => {
          if (res.total > 0) {
            this.projectList = res.rows;
            this.total = res.total;
          } else {
            that.projectList = that.allproTableData;
            that.total = that.allproTableData.length;
          }
        })
      }
      else
        this.getProjectList(this.queryParams)
    },
    /* 得到项目的点位绘制到地图上 */
    clusterStyle(feature, resolution) {
      let styleCache = {};
      const size = feature.get('features').length;
      let style = styleCache[size];
      if (!style) {
        style = [
          new Style({
            image: new Circle({
              radius: 20,
              fill: new Fill({
                color: 'rgba(107,72,255,0.4)',
              }),
            }),
            text: new Text({
              text: this.getText(feature, resolution),
              backgroundFill: new Fill({
                color: '#000',
              }),
              fill: new Fill({
                color: '#fff',
              }),
              backgroundStroke: new Stroke({
                color: '#EFDC05',
                width: 2,
              }),
              padding: [0, 5, 0, 5],
              // stroke: new Stroke({
              //   color: 'rgba(0, 0, 0, 0.6)',
              //   width: 3,
              // }),
              font: '18px Calibri,sans-serif',
              offsetY: -30
            })
          }),
          new Style({
            image: new Circle({
              radius: 14,
              fill: new Fill({
                color: 'rgba(107,72,255,0.9)',
              }),
            }),
            text: new Text({
              text: size.toString(),
              fill: new Fill({
                color: '#fff',
              }),
              stroke: new Stroke({
                color: 'rgba(0, 0, 0, 0.6)',
                width: 3,
              }),
            })
          })
        ];
        styleCache[size] = style;
      }
      return style;
    },
    /* 被选中的样式 */
    selectedStyle(feature, resolution) {
      let styleCache = {};
      let f = feature.get('features');
      if (f) {
        const size = feature.get('features').length;
        let style = styleCache[size];
        if (!style) {
          style = [
            new Style({
              image: new Circle({
                radius: 20,
                fill: new Fill({
                  color: 'rgba(255,0,0,0.4)',
                }),
              }),
              text: new Text({
                text: this.getText(feature, resolution),
                fill: new Fill({
                  color: '#fff',
                }),
                stroke: new Stroke({
                  color: 'rgba(0, 0, 0, 0.6)',
                  width: 3,
                }),
                font: '18px Calibri,sans-serif',
                offsetY: -30
              })
            }),
            new Style({
              image: new Circle({
                radius: 14,
                fill: new Fill({
                  color: 'rgba(255,0,0,0.9)',
                }),
              }),
              text: new Text({
                text: size.toString(),
                fill: new Fill({
                  color: '#fff',
                }),
                stroke: new Stroke({
                  color: 'rgba(0, 0, 0, 0.6)',
                  width: 3,
                }),
              })
            })
          ];
          styleCache[size] = style;
        }
        return style;
      } else {
        let style = new Style({
          // fill: new Fill({
          //   color: [75, 126, 255, 0.6]
          // }),
          stroke: new Stroke({
            width: 2,
            color: '#FFFFFF',
            lineDash: [8, 4],
            lineCap: 'butt'
          }),
          image: new Icon({
            src: sjxActive,
            crossOrigin: 'anonymous',
          })
        })
        return style
      }
    },
    getText(feature, resolution) {
      let features = feature.get('features');
      let reo = resolution * 100;
      let text;
      if (reo > 2) {
        text = '';
      } else {
        if (features.length == 1) {
          text = features[0].name;
        }
      }
      return text;
    },
    queryProject() {
      let type = this.searchType;
      let param;
      if (type == "1") {
        param = {
          pageNum: 1,
          pageSize: 9999999,
          projectNumber: this.searchVal
        }
      } else if (type == "2") {
        param = {
          pageNum: 1,
          pageSize: 9999999,
          projectName: this.searchVal
        }
      } else if (type == "3") {
        param = {
          pageNum: 1,
          pageSize: 9999999,
          projectType: this.searchVal
        }
      }
      if (this.$store.getters.roles.includes('projectLeader') && !this.$store.getters.roles.includes('leader')) {
        param.projectLeader = this.$store.getters.userId
      }
      listProject(param).then(res => {
        let data = res.rows;
        this.projectList = data;
      })
    },
    /* 开关聚合项目点 */
    switchCluster(val) {
      this.clusters.setVisible(val);
    },
    tableRowClassName() {

    },
    handleRowClick() {

    },
    lookThisAchi(row) {
      let projectId = row.projectId;
      this.dialogTitle = row.projectNumber;
      listAchievement({ projectId: projectId, pageSize: 50, pageNum: 1 }).then(res => {
        if (res.total == 0) {
          this.$message.error('暂无成果，请添加');
          this.achiDialogData = [];
        } else {
          this.dialogTableVisible = true;
          this.achiDialogData = res.rows;
        }
      })
    },
    // 移动box
    move(e) {
      e.stopPropagation();
      let odiv = e.target; //获取目标元素
      if (odiv.className instanceof SVGAnimatedString) {
        return
      }
      if (odiv.className.includes("dialog_wrap")) {
        //算出鼠标相对元素的位置
        let disX = e.clientX - odiv.offsetLeft;
        let disY = e.clientY - odiv.offsetTop;
        document.onmousemove = (e) => {
          //鼠标按下并移动的事件
          //用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
          let left = e.clientX - disX;
          let top = e.clientY - disY;

          //绑定元素位置到positionX和positionY上面
          // this.positionX = top;
          // this.positionY = left;

          //移动当前元素
          odiv.style.left = left + "px";
          odiv.style.top = top + "px";
        };
        document.body.onselectstart = document.body.ondrag = () => { return false }
        document.onmouseup = (e) => {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      } else {
        document.onmousemove = null;
        document.onmouseup = null;
        document.body.onselectstart = document.body.ondrag = () => { return true }
      }
    },
  }
}
</script>

<style lang="scss" scoped>
.warpper-container {
  position: relative;

  .projectpoint-switch {
    position: absolute;
    top: 10px;
    left: 60px;
    width: 100px;
    height: 50px;
    color: #fff;
  }
}

.map-container {
  width: 100%;
  height: calc(100vh - 84px);
}

/* 鼠标移动，坐标样式 */
#mouse-position {
  width: 220px;
  height: 40px;
  line-height: 40px;
  position: absolute;
  top: 0px;
  left: 50%;
  transform: translate(-50%, 0%);
  padding-left: 15px;
  color: #fff;
}

.achi-list {
  width: 425px;
  min-height: 300px;
  background-color: #fff;
  position: absolute;
  top: 55px;
  right: 520px;
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 0 10px rgba($color: #000000, $alpha: 0.5);
  cursor: move;

  .achi-content {
    cursor: default;
  }

  .achi-projectNumber {
    padding-left: 20px;
    font-size: 14px;
    font-family: '微软雅黑';
  }

  .achi-header {
    text-align: center;
    line-height: 40px;
    font-weight: bold;
    font-family: '黑体';
    position: relative;

    .achi-closer {
      text-decoration: none;
      position: absolute;
      top: 2px;
      right: 8px;
    }

    .achi-closer:after {
      content: "✖";
      cursor: pointer;
    }

    .achi-closer:hover:after {
      color: #409EFF;
    }
  }

}

.tool-box {
  position: absolute;
  top: 60px;
  left: 8px;
  width: 50px;
  border-radius: 5px;
  // background-color: #fff;

  .item {
    margin-top: 10px;
    width: 40px;
    height: 40px;
    padding: 6px;
    background-color: rgba($color: #000000, $alpha: 0.5);
    border-radius: 50%;
    cursor: pointer;
  }

  .view {
    width: 100%;
    height: 100%;
    background: url('~@/assets/images/gis/home.png') no-repeat;
    background-size: contain;
  }

  .layers {
    width: 100%;
    height: 100%;
    background: url('~@/assets/images/gis/layers.png') no-repeat;
    background-size: contain;
  }

  .select {
    width: 100%;
    height: 100%;
    background: url('~@/assets/images/gis/select.png') no-repeat;
    background-size: contain;
  }

  .selectM {
    width: 100%;
    height: 100%;
    background: url('~@/assets/images/gis/selectM.png') no-repeat;
    background-size: contain;
  }
}

.right-project {
  width: 500px;
  // min-height: 600px;
  max-height: calc(100vh - 110px);
  padding: 10px;
  position: absolute;
  top: 10px;
  right: 0;
  background-color: #fff;
  box-shadow: v-bind(--el - box - shadow - dark);
  transition: all 0.6s ease-in-out;

  .header {
    width: 100%;
    text-align: center;
    line-height: 50px;
    font-size: 22px;
    font-weight: 700;
  }

  .expand-info {
    .desLabel {
      font-weight: bold;
    }

    .look-achi {
      text-align: right;
      color: #409EFF;
      cursor: pointer;
    }

    .look-achi:hover {
      color: #1165b8;
    }
  }

  .result-click {
    width: 36px;
    height: 36px;
    position: absolute;
    top: 0;
    left: -36px;
    font-size: 16px;
    transform: translate(0, 0);
    background-color: #fff;
    text-align: center;
    padding: 10px;
    border-radius: 4px 0 0 4px;
    cursor: pointer;
  }

  .search-box {
    padding: 0px 15px;
  }
}

.closeProBox {
  right: -500px;
}

// 弹出框
.ol-popup {
  position: absolute;
  background-color: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  padding: 25px;
  border-radius: 10px;
  // border: 1px solid #cccccc;
  bottom: 17px;
  left: -168px;
  min-width: 361px;

  .ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
  }

  .ol-popup-closer:after {
    content: "✖";
    cursor: pointer;
  }

  .ol-popup-closer:hover:after {
    color: #409EFF;
  }


  .look-achi {
    text-align: right;
    color: #409EFF;
    cursor: pointer;
    font-size: 14px;
    margin-top: 10px;
    font-family: '微软雅黑';
  }

  .title {
    font-size: 14px;
    font-family: 'Times New Roman', '黑体', Times, serif, ;
  }
}

.ol-popup:after,
.ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}

.ol-popup:after {
  border-top-color: #fff;
  border-width: 10px;
  left: 50%;
  transform: translate(-50%, 0);
  margin-left: -10px;
}

.ol-popup:before {
  border-top-color: #fff;
  border-width: 11px;
  left: 50%;
  transform: translate(-50%, 0);
  margin-left: -11px;
}

.layer-type {
  position: absolute;
  top: 70px;
  left: 53px;
  width: 300px;
  padding: 12px 10px;
  background-color: #fff;
  border-radius: 5px;
  cursor: move;

  .title {
    font-size: 16px;
    text-align: center;
    line-height: 45px;
  }

  .layer-content {
    cursor: default;
    position: relative;

    .layer-header {
      text-align: center;
      line-height: 40px;
      font-weight: bold;
      font-family: '黑体';
      position: relative;

      .layer-closer {
        text-decoration: none;
        position: absolute;
        top: 2px;
        right: 8px;
      }

      .layer-closer:after {
        content: "✖";
        cursor: pointer;
      }

      .layer-closer:hover:after {
        color: #409EFF;
      }
    }
  }
}

.alter-position {
  width: 470px;
  position: absolute;
  left: 50%;
  top: 10px;
  transform: translate(-50%, 0);
}

.switch-map {
  position: absolute;
  bottom: 0;
  left: 0;
}
</style>