<!--
 * @Author: SunTao 328867980@qq.com
 * @Date: 2025-01-02 11:56:20
 * @LastEditors: SunTao 328867980@qq.com
 * @LastEditTime: 2025-01-02 17:26:35
 * @FilePath: \znxjxt-ui\src\views\xj\inspection\task-management\components\task-map.vue
 * @Description: 巡检任务-地图弹窗
-->
<template>
  <div class="content">
    <!-- 多选框切换坐标类型 -->
    <div class="check-box">
      <el-cascader
        ref="screenCascader"
        v-model="mapCareSelect"
        placeholder="病害类型筛选"
        :options="defectCascaderList"
        collapse-tags
        :props="{
          multiple: true,
          emitPath: false,
          children: 'subTypes',
        }"
        @change="changeMapCareSelect"
        clearable
      ></el-cascader>
    </div>
    <fssm-map ref="taskMap" @feature-select="featureSelect"></fssm-map>

    <!-- 查看点位图片弹窗 -->
    <el-dialog
      title="查看点位"
      :visible.sync="showImageDialog"
      width="85rem"
      append-to-body
      destroy-on-close
      @close="screenImgCancel"
    >
      <div class="image-container" ref="imageContainer" v-if="showImageDialog">
        <img
          :src="screenImage.imageUrl"
          alt="Main Image"
          ref="mainImage"
          @load="updateScreenRects"
        />
        <div
          v-for="(rect, index) in screenRects"
          :key="index"
          class="rect-overlay"
          :style="getScreenRectStyle(rect)"
        ></div>
        <div class="rect-image">
          采集时间:
          {{ screenImage.createTime }} 起始桩号：
          {{ screenImage.stakeStart || "暂无数据" }} 终止桩号：
          {{ screenImage.stakeEnd || "暂无数据" }}
          病害类型
          {{ screenImage.iconTypeName || "暂无数据" }}
          病害面积：{{
            screenImage.targetArea
              ? `${screenImage.targetArea}平方米`
              : "暂无数据"
          }}
          病害长度：{{
            screenImage.targetLen * 1 <= 0
              ? "暂无数据"
              : `${screenImage.targetLen}米`
          }}
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
// 接口
import { getDefectPoint } from "@/api/xj/task";
import FssmMap from "@/components/map/fssm-map.vue";
import { Feature } from "ol";
import { Point } from "ol/geom";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import { Style, Icon } from "ol/style";
export default {
  name: "TaskMap",
  components: {
    FssmMap,
  },
  props: {
    // 弹窗传的数据
    dialogItem: {
      type: Object,
      default: () => {},
    },
    // 病害类型筛选下拉数据
    defectCascaderList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      // 病害类型筛选绑定
      mapCareSelect: [],
      // 地图打点图层
      markLayerPoints: null,
      // 中心点集合(过滤后得点位)
      centerPiont: [],
      // 中心点集合（所有点位）
      drawPointList: [],
      // 查看大图点位图片数据
      screenImage: {},
      // 查看大图点位图片弹窗显隐控制
      showImageDialog: false,
      // 查看大图点位图片弹窗红框数据
      screenRects: [],
    };
  },
  mounted() {
    this.getMapPoint();
  },
  methods: {
    /**
     * @description: 病害类型筛选改变事件
     * @return {void}
     */
    changeMapCareSelect(value) {
      if (value.length > 0) {
        this.centerPiont = this.drawPointList.filter((item) => {
          return value.includes(item.iconType);
        });
      } else {
        this.centerPiont = this.drawPointList;
      }
      this.drawPoint();
    },

    /**
     * @description: 获取地图点位的方法
     * @return {void}
     */
    getMapPoint() {
      getDefectPoint({ id: this.dialogItem.extId }).then(({ code, data }) => {
        if (code === 200) {
          this.drawPointList = data.map((item) => {
            if (item.geometry) {
              return {
                ...item,
                geometry: [item.geometry[0], item.geometry[1]],
              };
            }
            return [];
          });
          this.centerPiont = data.map((item) => {
            if (item.geometry) {
              return {
                ...item,
                geometry: [item.geometry[0], item.geometry[1]],
              };
            }
            return [];
          });
          // 修改地图中心点位
          const pointArray = data.map((item) => {
            if (item.geometry) {
              return [item.geometry[0], item.geometry[1]];
            }
            return [];
          });
          this.fitMapToPoints(pointArray);
          this.drawPoint();
        }
      });
    },

    /**
     * @description: 根据点位计算地图中心点
     * @return {void}
     */
    fitMapToPoints(points) {
      if (points.length > 0) {
        // 创建一个空的 extent
        let extent = [Infinity, Infinity, -Infinity, -Infinity];
        // 计算所有点的边界框（extent）
        points.forEach((point) => {
          extent = [
            Math.min(extent[0], point[0]),
            Math.min(extent[1], point[1]),
            Math.max(extent[2], point[0]),
            Math.max(extent[3], point[1]),
          ];
        });
        this.$nextTick(() => {
          // 获取地图实例
          const map = this.$refs.taskMap.instance.get("map");

          // 使用 fit 方法根据边界框计算最佳缩放级别
          map.getView().fit(extent, {
            duration: 500, // 动画持续时间
            padding: [10, 10, 10, 10], // 边缘填充
          });
        });
      }
    },

    /**
     * @description: 绘制地图点位
     * @return {void}
     */
    drawPoint() {
      const features = [];
      this.centerPiont.forEach((element) => {
        // 修改坐标样式
        const point = new Point(element.geometry);
        const feature = new Feature({
          geometry: point,
          data: element,
          // 自己设置一个标识
          type: "icon",
        });
        // 设置点位样式
        feature.setStyle([
          new Style({
            image: new Icon({
              crossOrigin: "anonymous",
              src: require(`@/assets/screen/index/${element.iconTypeName}.png`),
              // size: [40, 40],
              scale: 0.5, // 图标缩放比例
              displacement: [0, 30],
            }),
          }),
        ]);
        features.push(feature);
      });
      //设置地图的数据源
      const pointSource = new VectorSource({
        features,
      });
      if (!this.markLayerPoints) {
        this.markLayerPoints = new VectorLayer({
          source: pointSource,
          properties: {
            type: "point",
          },
        });
        this.$nextTick(() => {
          const map = this.$refs.taskMap.instance.get("map");
          map.addLayer(this.markLayerPoints);
        });
      } else {
        this.markLayerPoints.setSource(pointSource);
      }
    },

    /**
     * @description: 图标点击事件
     * @return {void}
     */
    featureSelect(e) {
      const map = this.$refs.taskMap.instance.get("map");
      const selectedFeatures = e.selected;
      let feature = selectedFeatures[0];
      if (selectedFeatures.length > 0) {
        // console.log(feature.getProperties(), "feature");
        // 获取点位数据
        const selectFeature = feature.getProperties().data;
        this.screenImage = selectFeature;
        this.showImageDialog = true;
      } else {
        // 聚合点
        // 放大地图层级
        map.getView().animate({
          center: feature.getGeometry().getCoordinates(),
          zoom: map.getView().getZoom() + 1,
        });
      }
    },

    /**
     * @description: 图片位置信息获取
     * @return {void}
     */
    updateScreenRects() {
      1;
      this.screenRects = [];
      const image = this.$refs.mainImage;
      const rects = this.screenImage?.rect?.split(",").map(Number) || [];
      this.screenRects = [
        {
          left: rects[0],
          top: rects[1],
          width: rects[2],
          height: rects[3],
        },
      ];
    },

    /**
     * @description: 图片红框位置
     * @param {object} left
     * @param {object} top
     * @param {object} width
     * @param {object} height
     * @return {object}
     */
    getScreenRectStyle({ left, top, width, height }) {
      const image = this.$refs.mainImage;
      const container = this.$refs.imageContainer;
      if (!image || !container) return {};

      const scaleX = container.clientWidth / image.naturalWidth;
      const scaleY = container.clientHeight / image.naturalHeight;
      const scale = Math.min(scaleX, scaleY);

      const renderedWidth = image.naturalWidth * scale;
      const renderedHeight = image.naturalHeight * scale;

      const offsetX = (container.clientWidth - renderedWidth) / 2;
      const offsetY = (container.clientHeight - renderedHeight) / 2;

      return {
        position: "absolute",
        left: `${left * scale + offsetX}px`,
        top: `${top * scale + offsetY}px`,
        width: `${width * scale}px`,
        height: `${height * scale}px`,
        border: "2px solid #FF0000",
        boxSizing: "border-box",
      };
    },

    /**
     * @description: 关闭查看点位大图弹窗
     * @return {void}
     */
    screenImgCancel() {
      this.$refs.taskMap.removeSelectClick();
      this.showImageDialog = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.content {
  width: 100%;
  height: 45rem;
  position: relative;

  .check-box {
    position: absolute;
    z-index: 1;
  }
}

/* 查看大图弹窗 */
.image-container {
  position: relative;
  width: 100%;
  height: 80%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.image-container img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.rect-overlay {
  position: absolute;
  pointer-events: none;
  border: 2px solid red;
}

// 图片信息
.rect-image {
  width: 90%;
  position: absolute;
  top: 0;
  font-size: 1.2rem;
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.5);
}
</style>
