<!--
 * @Author: SunTao 328867980@qq.com
 * @Date: 2024-11-01 17:25:06
 * @LastEditors: SunTao 328867980@qq.com
 * @LastEditTime: 2024-12-24 15:43:51
 * @FilePath: \znxjxt-ui\src\views\xj\inspection\confirmation-management\components\image-dialog.vue
 * @Description: 病害确认-影像模式弹窗
-->

<template>
  <div class="content">
    <div class="image-content">
      <!-- 图片展示 -->
      <div class="sidebar" ref="sidebar" @scroll="handleScroll">
        <img
          v-for="(item, index) in defectData"
          :key="item.id"
          :src="item.media[0].img"
          :alt="'Image ' + (index + 1)"
          @click="showImage(index)"
          :class="{ selected: currentIndex === index }"
        />
      </div>
      <!-- 右侧区域 -->
      <div class="main-content">
        <div class="image-form">
          <el-form
            :model="imgForm"
            ref="imgForm"
            size="small"
            :inline="true"
            label-width="5rem"
          >
            <el-form-item label="路段名称">
              <el-select
                v-model="imgForm.segmentId"
                placeholder="请选择路段名称"
                :style="{ width: '8rem' }"
                clearable
              >
                <el-option
                  v-for="item in roadTypeList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item label-width="3rem" label="类型">
              <el-cascader
                v-model="imgForm.defectType"
                :options="tableDefect"
                :props="{
                  checkStrictly: false,
                  emitPath: false,
                  children: 'subTypes',
                }"
                clearable
              ></el-cascader>
            </el-form-item>
            <el-form-item label="公里桩">
              <el-input
                v-model="imgForm.stakeStart"
                placeholder="起始公里桩"
                style="width: 7rem"
                clearable
              />
              <span style="margin: 0 5px">-</span>
              <el-input
                v-model="imgForm.stakeEnd"
                placeholder="终止公里桩"
                style="width: 7rem"
                clearable
              />
            </el-form-item>
            <el-button
              type="primary"
              icon="el-icon-search"
              size="mini"
              @click="handleQuery"
              >搜索</el-button
            >
            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
              >重置</el-button
            >
            <!-- <el-row :gutter="24">
              <el-col :span="6">
                <el-button
                  type="primary"
                  icon="el-icon-search"
                  size="mini"
                  @click="handleQuery"
                  >搜索</el-button
                >
                <el-button
                  icon="el-icon-refresh"
                  size="mini"
                  @click="resetQuery"
                  >重置</el-button
                >
              </el-col>
            </el-row> -->
          </el-form>
        </div>
        <!-- 图片展示 -->
        <div class="image-view" ref="imageView">
          <div class="view-info">
            采集时间:
            {{ new Date(rectsItem.createdTime).toLocaleString() }} 起始桩号:
            {{ rectsItem.stakeStart || "暂无数据" }} 终止桩号:
            {{ rectsItem.stakeEnd || "暂无数据" }}
            病害类型：{{ rectsItem.defectTypeName || "暂无数据" }}
          </div>
          <div
            class="view-content"
            ref="imageContainer"
            @mousewheel="handleWeel"
            :style="`width:${elWidth}rem;height:${elHeight}rem;`"
          >
            <img
              :src="currentImage"
              alt="Main Image"
              :draggable="false"
              ref="mainImage"
              @load="updateRects"
            />
            <div
              class="rect-overlay"
              v-for="(rect, index) in rects"
              :key="index"
              :style="getRectStyle(rect)"
            ></div>
            <!-- <div class="view-info">
              采集时间:
              {{ new Date(rectsItem.createdTime).toLocaleString() }} 起始桩号:
              {{ rectsItem.stakeStart || "暂无数据" }} 终止桩号:
              {{ rectsItem.stakeEnd || "暂无数据" }}
              病害类型：{{ rectsItem.defectTypeName || "暂无数据" }} 路产状态:
              {{ filterState(rectsItem.state) }}
            </div> -->
          </div>
        </div>
        <div class="image-bottom">
          <img
            v-for="(mediaItem, index) in currentThumbnails"
            :key="'thumb-' + index"
            :src="mediaItem.img"
            :alt="'Thumb ' + (index + 1)"
            @click="showThumbnailImage(index)"
            :class="{ selected: selectedThumbnail === index }"
          />
        </div>
      </div>
    </div>
    <div class="footer">
      <el-button type="success" size="mini" @click="changeDefect(2)"
        >是病害(Y)</el-button
      >
      <el-button type="warning" size="mini" @click="changeDefect(3)"
        >不是病害(N)</el-button
      >
    </div>
  </div>
</template>

<script>
import {
  getSegment,
  getDefectStatus,
  mergeDefect,
  listDefect,
} from "@/api/xj/confirmation";
export default {
  name: "ImageDialog",
  props: {
    tableDefect: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      // 左侧图片数据
      defectData: [],
      // 表单绑定
      imgForm: {
        // 路段名称
        segmentId: "",
        // 病害类型
        defectType: "",
        // 公里桩
        stakeStart: "",
        stakeEnd: "",
      },
      // 路段下拉数据
      roadTypeList: [],
      // 病害状态下拉选项
      defectStatus: [],
      // 分页绑定
      params: {
        page: 1,
        size: 10,
      },
      // 图片病害位置信息
      rects: [],
      // 当前展示的index
      currentIndex: "0",
      // 点击的index绑定
      selectedThumbnail: null,
      // 图片下方数据
      rectsItem: {},

      initWidth: 0, // 父元素的宽-自适应值
      initHeight: 0, // 父元素的高-自适应值
      // 缩放比例
      zoom: 1,
      // 容器宽
      elWidth: 0, // 元素宽
      // 容器高
      elHeight: 0, // 元素高
      elLeft: 0, // 元素的左偏移量
      elTop: 0, // 元素的右偏移量
    };
  },
  computed: {
    currentImage() {
      const thumbnails = this.currentThumbnails;
      return (
        thumbnails[this.selectedThumbnail]?.img || thumbnails[0]?.img || ""
      );
    },
    currentThumbnails() {
      return this.defectData[this.currentIndex]?.media || [];
    },
  },
  created() {
    this.getSegmentList();
    this.getDefectStatusList();
  },
  mounted() {
    this.getList();
    this.showImage(0);
    this.scrollInit();
    this.initBodySize();
    window.addEventListener("keydown", this.handleKeydown);
    window.addEventListener("resize", this.updateRects);
  },
  methods: {
    // 页面初始化
    initBodySize() {
      this.initWidth = this.$refs.imageView.clientWidth; // 拿到父元素宽
      this.initHeight = this.initWidth * ((1080 * 0.31) / (1920 - 1080 * 0.02)); // 根据宽计算高实现自适应
      this.elWidth = this.initWidth * (100 / (1920 / 1.2));
      this.elHeight = this.initHeight * (100 / (1080 / 2.08));
    },
    // 初始化与绑定监听事件方法
    scrollInit() {
      // 获取要绑定事件的元素
      const nav = this.$refs.imageView;

      let flag; // 鼠标按下
      let downX; // 鼠标点击的x下标
      let downY;
      let scrollLeft; // 当前元素滚动条的偏移量
      let scrollTop; // 当前元素滚动条的偏移量
      nav.addEventListener("mousedown", function (event) {
        flag = true;
        downX = event.clientX; // 获取到点击的x下标
        downY = event.clientY;
        scrollLeft = this.scrollLeft; // 获取当前元素滚动条的偏移量
        scrollTop = this.scrollTop;
      });
      nav.addEventListener("mousemove", function (event) {
        if (flag) {
          // 判断是否是鼠标按下滚动元素区域
          let moveX = event.clientX; // 获取移动的x轴
          let moveY = event.clientY;
          let scrollX = moveX - downX; // 当前移动的x轴下标减去刚点击下去的x轴下标得到鼠标滑动距离
          let scrollY = moveY - downY; // 当前移动的x轴下标减去刚点击下去的x轴下标得到鼠标滑动距离
          this.scrollLeft = scrollLeft - scrollX; // 鼠标按下的滚动条偏移量减去当前鼠标的滑动距离
          this.scrollTop = scrollTop - scrollY;
        }
      });
      // 鼠标抬起停止拖动
      nav.addEventListener("mouseup", function () {
        flag = false;
      });
      // 鼠标离开元素停止拖动
      nav.addEventListener("mouseleave", function (event) {
        flag = false;
      });
    },
    // 拖拽开始事件
    dragstart(e) {
      this.startclientX = e.clientX; // 记录拖拽元素初始位置
      this.startclientY = e.clientY;
    },
    // 拖拽完成事件
    dragend(e) {
      let x = e.clientX - this.startclientX; // 计算偏移量
      let y = e.clientY - this.startclientY;
      this.elLeft += x; // 实现拖拽元素随偏移量移动
      this.elTop += y;
    },
    // 滚轮放大缩小事件
    handleWeel(e) {
      if (e.wheelDelta < 0) {
        this.zoom -= 0.25;
      } else {
        this.zoom += 0.25;
      }
      if (this.zoom >= 5.5) {
        this.zoom = 5.5;
        return;
      }
      if (this.zoom <= 0.75) {
        this.zoom = 0.75;
        this.elLeft = 0;
        this.elTop = 0;
        return;
      }

      this.elWidth = this.initWidth * (100 / (1920 / 1.2)) * this.zoom;
      this.elHeight = this.initHeight * (100 / (1080 / 2)) * this.zoom;
    },

    /* 获取路段下拉数据 */
    getSegmentList() {
      getSegment().then(({ code, data }) => {
        if (code === 200) {
          this.roadTypeList = data;
        }
      });
    },

    /* 查询病害状态下拉数据 */
    getDefectStatusList() {
      getDefectStatus().then(({ data, code }) => {
        if (code === 200) {
          this.defectStatus = data;
        }
      });
    },

    /* 过滤列表病害状态 */
    filterState(value) {
      let a = null;
      [a] = this.defectStatus.filter((item) => {
        return item.value === value;
      });
      if (a) {
        return a.label;
      }
    },

    /* 获取左侧图片列表 */
    getList() {
      this.loading = true;
      const data = {
        ...this.imgForm,
        ...this.params,
      };
      listDefect(data)
        .then(({ code, rows }) => {
          if (code === 200) {
            this.defectData = rows;
            this.loading = false;
          }
        })
        .catch(() => {
          this.loading = false;
        });
    },

    /* 点击搜索事件 */
    handleQuery() {
      const stakeReg = /^K\d{4}\+\d{3}$/;
      if (this.imgForm.stakeStart) {
        if (stakeReg.test(this.imgForm.stakeStart)) {
          this.defectData = [];
          this.params = {
            page: 1,
            size: 10,
          };
          this.getList();
          this.showImage(0);
        } else {
          this.$modal.msgWarning("请按照'K0000+000'格式填写公里桩进行修改");
        }
      } else if (this.imgForm.stakeEnd) {
        if (stakeReg.test(this.imgForm.stakeEnd)) {
          this.defectData = [];
          this.params = {
            page: 1,
            size: 10,
          };
          this.getList();
          this.showImage(0);
        } else {
          this.$modal.msgWarning("请按照'K0000+000'格式填写公里桩进行修改");
        }
      } else {
        this.defectData = [];
        this.params = {
          page: 1,
          size: 10,
        };
        this.getList();
        this.showImage(0);
      }
    },

    /* 重置事件 */
    resetQuery() {
      this.defectData = [];
      this.imgForm = {
        segmentId: "",
        defectType: "",
        stakeStart: "",
        stakeEnd: "",
      };
      this.params = {
        page: 1,
        size: 10,
      };
      this.getList();
      this.showImage(0);
    },

    /* 左侧点击图片事件 */
    showImage(index) {
      this.initBodySize();
      this.zoom = 1;
      this.currentIndex = index;
      this.selectedThumbnail = 0; // Reset to the first thumbnail when changing the main item
      this.scrollToCurrentImage();
      this.$nextTick(() => {
        this.updateRects();
      });
    },
    showThumbnailImage(index) {
      this.selectedThumbnail = index;
      this.updateRects();
    },
    scrollToCurrentImage() {
      const sidebarImages = this.$refs.sidebar.querySelectorAll("img");
      const currentImageElement = sidebarImages[this.currentIndex];
      if (currentImageElement) {
        currentImageElement.scrollIntoView({
          behavior: "smooth",
          block: "center",
        });
      }
    },

    /* 图片位置信息获取 */
    updateRects() {
      // this.rects = [];
      this.rectsItem = {};
      if (this.defectData.length > 0) {
        const image = this.$refs.mainImage;
        const rects =
          this.defectData[this.currentIndex]?.media[
            this.selectedThumbnail
          ]?.rect
            ?.split(",")
            .map(Number) || [];
        this.rects = [
          {
            left: rects[0],
            top: rects[1],
            width: rects[2],
            height: rects[3],
          },
        ];
        this.rectsItem = this.defectData[this.currentIndex];
      }
    },

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

      const scaleX = (this.elWidth * 16) / image.naturalWidth;
      const scaleY = (this.elHeight * 16) / image.naturalHeight;
      const scale = Math.min(scaleX, scaleY);

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

      const offsetX = (this.elWidth * 16 - renderedWidth) / 2;
      const offsetY = (this.elHeight * 16 - 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 #ffffff",
        boxSizing: "border-box",
      };
    },

    /* 滚动触发事件 */
    handleScroll() {
      // 滚动高度+容器高度  滚动区域高度
      const sidebar = this.$refs.sidebar;
      if (
        sidebar.scrollTop + sidebar.clientHeight >= sidebar.scrollHeight - 1 &&
        !this.loading
      ) {
        this.loadMoreImages();
      }
    },

    /* 加载更多图片方法 */
    loadMoreImages() {
      this.params.size += 10;
      this.getList();
    },

    /* 是病害/不是病害点击事件 */
    changeDefect(value) {
      if (this.defectData.length > 0) {
        mergeDefect({
          status: value,
          snapShotIds: [this.defectData[this.currentIndex].snapshotId],
        })
          .then(({ code, msg }) => {
            if (code === 200) {
              this.defectData.splice(this.currentIndex, 1);
              // this.currentIndex + 1;
              this.$modal.msgSuccess("修改成功");
            } else {
              this.$modal.msgWarning(msg);
            }
          })
          .finally(() => {
            this.showImage(this.currentIndex);
            if (this.defectData.length < 4) {
              this.getList();
            }
          });
      }
    },

    /* 键盘事件 */
    handleKeydown(event) {
      if (event.key === "ArrowUp") {
        event.preventDefault();
        if (this.currentIndex > 0) {
          this.initBodySize();
          this.zoom = 1;
          this.currentIndex--;
          this.selectedThumbnail = 0; // Reset when changing main images via keyboard
          this.scrollToCurrentImage();
          this.updateRects();
        }
      } else if (event.key === "ArrowDown") {
        event.preventDefault();
        if (this.currentIndex <= this.defectData.length - 1) {
          this.initBodySize();
          this.zoom = 1;
          this.currentIndex === this.defectData.length - 1
            ? this.currentIndex
            : this.currentIndex++;
          this.selectedThumbnail = 0; // Reset when changing main images via keyboard
          this.scrollToCurrentImage();
          this.updateRects();
        } else {
          this.loadMoreImages();
        }
      } else if (event.keyCode === 89) {
        // 确认病害
        this.changeDefect(2);
      } else if (event.keyCode === 78) {
        // 不是病害
        this.changeDefect(3);
      }
    },
  },
  beforeDestroy() {
    window.removeEventListener("keydown", this.handleKeydown);
    window.removeEventListener("resize", this.updateRects);
  },
};
</script>

<style lang="scss" scoped>
.content {
  width: 100%;
  height: 46rem;
}

.image-content {
  width: 100%;
  height: 95%;
  display: flex;
  flex-direction: row;

  .sidebar {
    width: 20rem;
    height: calc(100% - 2.5rem);
    padding: 10px;
    overflow-y: auto;
  }

  .main-content {
    width: calc(100% - 20rem);
    padding: 10px;
    display: flex;
    flex-direction: column;
  }
}

.sidebar img {
  width: 100%;
  margin-bottom: 5px;
  cursor: pointer;
  border-radius: 3px;
  transition: transform 0.2s, border 0.2s;
  box-sizing: border-box;
}

.sidebar img.selected {
  border: 3px solid #00aaff;
  transform: scale(1.03);
}

// form表单
.image-form {
  height: 7%;
  width: 100%;
}

// 图片大图预览
.image-view {
  height: 78%;
  width: 100%;
  background-color: rgb(228, 247, 248);
  overflow: auto;

  &::-webkit-scrollbar {
    display: none;
  }

  .view-content {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    position: relative;
  }

  .view-content img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
  }

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

  .view-info {
    width: 60%;
    position: absolute;
    left: 30%;
    top: 17%;
    z-index: 1;
    color: #ffffff;
    background-color: rgba(13, 49, 126, 0.486);
  }
}

// 图片小图预览
.image-bottom {
  width: 100%;
  height: 15%;
  display: flex;
  justify-content: center;
  overflow-x: auto;
  padding: 10px;
  gap: 10px;
  background-color: rgb(244, 244, 228);

  img {
    width: 7rem;
    height: 4rem;
    cursor: pointer;
    border-radius: 3px;
    transition: transform 0.2s, border 0.2s;
    box-sizing: border-box;
  }

  img.selected {
    border: 3px solid #00aaff;
  }
}

.footer {
  width: 100%;
  height: 5%;
  display: flex;
  justify-content: flex-end;
}
</style>
