<!--
 * @Author: SunTao 328867980@qq.com
 * @Date: 2024-10-22 15:30:25
 * @LastEditors: SunTao 328867980@qq.com
 * @LastEditTime: 2025-01-08 16:11:18
 * @FilePath: \znxjxt-ui\src\views\big-screen\components\img-dialog.vue
 * @Description: 大屏查看图片弹窗
-->

<template>
  <div
    class="app"
    v-loading="loading"
    element-loading-background="rgba(0, 0, 0, 0.8)"
  >
    <div class="left-list">
      <div class="img-top">
        <div
          class="img-top-div"
          :class="labelCheck === 'aim' ? 'img-top-div-click' : ''"
          @click.stop="changeImgType('aim')"
        >
          目标维度
        </div>
        <div
          class="img-top-div"
          :class="labelCheck === 'aria' ? 'img-top-div-click' : ''"
          @click.stop="changeImgType('aria')"
        >
          空间维度
        </div>
      </div>
      <div class="sidebar" ref="sidebar" @scroll="handleScroll">
        <img
          v-for="(item, index) in defectData"
          :key="`${item.id}-${index}`"
          :src="item.url"
          :alt="'Image ' + (index + 1)"
          @click="showImage(index)"
          :class="{ selected: currentIndex === index }"
        />
      </div>
    </div>

    <div class="main-content">
      <!-- 搜索表单 -->
      <div class="toolbar">
        <el-form
          :model="imgForm"
          ref="imgForm"
          size="small"
          :inline="true"
          label-width="6rem"
        >
          <el-form-item label="路段名称">
            <el-select
              v-model="imgForm.segmentId"
              placeholder="请选择路段名称"
              :popper-append-to-body="false"
              filterable
              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="病害类型">
            <el-select
              v-model="imgForm.defectType"
              placeholder="请选择病害类型"
              :popper-append-to-body="false"
              clearable
            >
              <el-option
                v-for="item in defectTypeList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>

          <el-form-item label="公里桩">
            <el-input
              v-model="imgForm.stakeStart"
              placeholder="起始公里桩"
              style="width: 8rem"
              clearable
            />
            <span style="margin: 0 5px">-</span>
            <el-input
              v-model="imgForm.stakeEnd"
              placeholder="终止公里桩"
              style="width: 8rem"
              clearable
            />
          </el-form-item>
          <el-button
            type="primary"
            class="btn-submit"
            size="mini"
            @click="handleQuery"
            >搜索</el-button
          >
          <el-button class="btn-cancel" size="mini" @click="resetQuery"
            >重置</el-button
          >
        </el-form>
      </div>
      <!-- 图片展示 -->
      <div class="image-viewer">
        <div class="image-container" ref="imageContainer">
          <div
            class="rect-overlay"
            v-for="(item, index) in checkedRectList"
            :key="`rect-overlay-${index}`"
            :style="getRectStyle(item.rectPosition, index)"
            @click="clickImage(item)"
          >
            <div :style="{ color: colorList[index] }" class="rect-overlay-text">
              目标详情>>
            </div>
          </div>
          <div class="rect-image">
            <el-checkbox-group
              v-model="checkedRect"
              @change="handleCheckedRectChange"
            >
              <el-checkbox
                class="image-info"
                v-for="(item, index) in rectItem"
                :label="item.id"
                :key="`image-info-${index}`"
                :style="{ color: colorList[index] }"
                >采集时间:
                {{ new Date(item.createdTime).toLocaleString() }} 起始桩号:
                {{ item.stakeStart || "暂无数据" }} 终止桩号:
                {{ item.stakeEnd || "暂无数据" }}
                病害类型:
                {{ item.type || "暂无数据" }}
                <span v-if="bottomTipClick === '1'">
                  病害面积：{{ item.area }}平方米 病害长度：{{
                    item.length * 1 <= 0 ? "暂无数据" : `${item.length}米`
                  }}
                </span>
              </el-checkbox>
            </el-checkbox-group>
          </div>
          <img
            :src="currentImage"
            alt="Main Image"
            ref="mainImage"
            @load="updateRects"
          />
        </div>
      </div>
      <!-- 小图展示 -->
      <div class="thumbnail-row">
        <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>
</template>

<script>
import {
  defeaseList,
  getSegment,
  getItemTypes,
  getMediaIndex,
} from "@/api/xj/screen/index";
import throttle from "lodash/throttle";
import debounce from "lodash/debounce";
export default {
  name: "ImgDialog",
  props: {
    bottomTipClick: {
      type: String,
      default: "",
    },
    imageItem: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      // 维度选择
      labelCheck: "aim",
      // 目标维度事件
      aimList: [],
      // 空间维度数据
      ariaList: [],
      // 左侧图片数据
      defectData: [],
      // 当前选择的index
      currentIndex: null,
      // 下方点击的index绑定
      selectedThumbnail: 0,
      // 选中框绑定
      checkedRect: [],
      // 顶端选中框数据
      checkedRectList: [],
      // 加载状态
      loading: false,
      // 表单绑定
      imgForm: {
        // 点击详情传的id
        id: null,
        // 路段名称
        segmentId: "",
        // 病害类型
        defectType: "",
        // 起始公里桩
        stakeStart: "",
        // 终止公里桩
        stakeEnd: "",
      },
      // 路段下拉数据
      roadTypeList: [],
      // 病害类型下拉数据
      defectTypeList: [],
      // 分页绑定
      params: {
        page: 1,
        size: 10,
      },
      pageTip: 1,
      // 图片病害位置红框信息
      rectItem: [],
      // 图片病害框的颜色
      colorList: ["#FFFFFF", "#07E8E2", "#DD9F18", "#994EFF", "#08B4A6"],
    };
  },
  computed: {
    /**
     * @description: 当前展示的图片url
     * @param {*}
     * @return {*}
     */
    currentImage() {
      if (
        this.defectData.length > 0 &&
        this.defectData.length > this.currentIndex
      ) {
        // this.showImage(this.currentIndex);
        const index = this.defectData[this.currentIndex].items.length - 1;
        if (index !== this.selectedThumbnail) {
          return this.defectData[this.currentIndex].items[
            this.selectedThumbnail
          ]?.img;
        }
        return this.defectData[this.currentIndex].items[index]?.img;
      }
    },

    /**
     * @description: 下方小列表数据
     * @param {*}
     * @return {*}
     */
    currentThumbnails() {
      return this.defectData[this.currentIndex]?.items || [];
    },
  },
  watch: {
    imageItem: {
      handler() {
        this.getMediaBySnapshotid();
      },
      deep: true,
      immediate: true,
    },
    bottomTipClick: {
      handler() {
        this.getDefectType();
      },
    },
  },
  created() {
    this.getSegmentList();
    this.getDefectType();
  },
  methods: {
    /**
     * @description: 获取路段下拉数据
     * @param {*}
     * @return {*}
     */
    getSegmentList() {
      getSegment({ routeId: "" }).then(({ code, data }) => {
        if (code === 200) {
          this.roadTypeList = data;
        }
      });
    },

    /**
     * @description: 获取病害类型下拉数据
     * @param {*}
     * @return {*}
     */
    getDefectType() {
      getItemTypes({ classType: this.bottomTipClick }).then(
        ({ code, data }) => {
          if (code === 200) {
            this.defectTypeList = data;
          }
        }
      );
    },

    /**
     * @description: 根据传回来的快照id查图片详细数据
     * @param {*}
     * @return {*}
     */
    getMediaBySnapshotid() {
      this.loading = true;
      getMediaIndex({
        classType: this.bottomTipClick,
        id: this.imageItem.snapshotId,
      })
        .then(({ code, data }) => {
          if (code === 200) {
            this.currentIndex = data.index;
            this.pageTip = data.page;
            this.params.page = data.page;
            this.params.size = data.size;
            this.imgForm.segmentId = data.segmentId.toString();
            this.getList();
          }
        })
        .finally(() => {
          setTimeout(() => {
            if (this.pageTip > 1) {
              this.loadMoreTopImages();
            }
          }, 500);
        });
    },

    /**
     * @description: 切换维度事件
     * @param {*}
     * @return {*}
     */
    changeImgType(type) {
      if (this.labelCheck != type) {
        this.labelCheck = type;
        if (type === "aria") {
          this.defectData = this.ariaList;
          if (this.currentIndex > this.ariaList.length - 1) {
            this.showImage(this.ariaList.length - 1);
          }
        } else {
          this.defectData = this.aimList;
          if (this.currentIndex < this.aimList.length - 1) {
            this.showImage(this.currentIndex);
          }
        }
      }
    },

    /**
     * @description: 向下获取图片列表
     * @param {*}
     * @return {*}
     */
    getList() {
      this.loading = true;
      const data = {
        classType: this.bottomTipClick,
        ...this.imgForm,
        ...this.params,
      };
      defeaseList(data)
        .then(({ code, data }) => {
          if (code === 200) {
            this.aimList.push(...data.aim);
            this.ariaList.push(...data.aria);
            if (this.labelCheck === "aria") {
              this.defectData = this.ariaList;
            } else {
              this.defectData = this.aimList;
            }
          }
        })
        .finally(() => {
          this.showImage(this.currentIndex);
          this.loading = false;
        });
    },

    /**
     * @description: 向上获取列表数据
     * @param {*}
     * @return {*}
     */
    getListTop() {
      this.loading = true;
      const data = {
        classType: this.bottomTipClick,
        ...this.imgForm,
        page: this.pageTip,
        size: this.params.size,
      };
      defeaseList(data)
        .then(({ code, data }) => {
          if (code === 200) {
            this.aimList.unshift(...data.aim);
            this.ariaList.unshift(...data.aria);
            this.currentIndex += this.params.size;
            if (this.labelCheck === "aria") {
              this.defectData = this.ariaList;
            } else {
              this.defectData = this.aimList;
            }
          }
        })
        .finally(() => {
          this.showImage(this.currentIndex);
          this.loading = false;
        });
    },

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

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

    /**
     * @description: 左侧点击图片事件
     * @param {*}
     * @return {*}
     */
    showImage(index) {
      this.currentIndex = index;
      const indexInfo = this.defectData[this.currentIndex]?.items.length - 1;
      this.selectedThumbnail = indexInfo; // Reset to the first thumbnail when changing the main item
      this.$nextTick(() => {
        this.scrollToCurrentImage();
        this.updateRects();
      });
    },

    /**
     * @description: 点击下方小列表
     * @param {*}
     * @return {*}
     */
    showThumbnailImage(index) {
      this.selectedThumbnail = index;
      this.updateRects();
    },

    /**
     * @description: 使图片展示在父级容器可视区域
     * @param {*}
     * @return {*}
     */
    scrollToCurrentImage: debounce(function () {
      if (this.$refs.sidebar) {
        const sidebarImages = this.$refs.sidebar.querySelectorAll("img");
        const currentImageElement = sidebarImages[this.currentIndex];
        if (currentImageElement) {
          currentImageElement.scrollIntoView({
            behavior: "smooth",
            block: "center",
          });
        }
      }
    }, 100),
    /**
     * @description: 滚动触发事件
     * @param {*}
     * @return {*}
     */
    handleScroll: debounce(function () {
      const sidebar = this.$refs.sidebar;
      // 滚动到顶加载数据
      if (sidebar.scrollTop < 2 && this.pageTip > 1 && !this.loading) {
        this.loadMoreTopImages();
      }

      // 滚动到底加载数据
      // 滚动高度+容器高度  滚动区域高度
      if (
        sidebar.scrollTop + sidebar.clientHeight >= sidebar.scrollHeight - 1 &&
        !this.loading
      ) {
        this.loadMoreBottomImages();
      }
      // if (this.currentIndex === this.defectData.length - 1) {
      //   this.loadMoreBottomImages();
      // } else if (this.currentIndex === 0) {
      //   this.loadMoreTopImages();
      // }
    }, 100),

    /**
     * @description: 向下加载更多图片方法
     * @param {*}
     * @return {*}
     */
    loadMoreBottomImages() {
      this.params.page += 1;
      this.getList();
    },

    /**
     * @description: 向上加载更多图片
     * @param {*}
     * @return {*}
     */
    loadMoreTopImages() {
      this.pageTip -= 1;
      // this.params.page -= 1;
      // this.currentIndex += this.params.size;
      this.getListTop();
    },

    /**
     * @description: 点击目标详情/空间维度事件
     * @param {*}
     * @return {*}
     */
    clickImage(item) {
      if (this.labelCheck === "aim") {
        this.labelCheck = "aria";
        this.defectData = this.ariaList;
        const index = this.ariaList.findIndex((it) => it.id === item.id) || 0;
        this.showImage(index);
      } else {
        this.labelCheck = "aim";
        this.defectData = this.aimList;
        const index = this.aimList.findIndex((it) => it.id === item.id) || 0;
        this.showImage(index);
      }
    },

    /**
     * @description: 键盘事件
     * @param {*}
     * @return {*}
     */
    handleKeydown: throttle(function (event) {
      if (event.key === "ArrowUp" && !this.loading) {
        event.preventDefault();
        if (this.currentIndex > 0) {
          this.currentIndex--;
          const index = this.defectData[this.currentIndex].items.length - 1;
          this.selectedThumbnail = index; // Reset when changing main images via keyboard
          this.scrollToCurrentImage();
          this.updateRects();
        }
      } else if (event.key === "ArrowDown" && !this.loading) {
        event.preventDefault();
        if (this.currentIndex < this.defectData.length - 1) {
          this.currentIndex === this.defectData.length - 1
            ? this.currentIndex
            : this.currentIndex++;
          const index = this.defectData[this.currentIndex].items.length - 1;
          this.selectedThumbnail = index; // Reset when changing main images via keyboard
          this.scrollToCurrentImage();
          this.updateRects();
        } else {
          this.loadMoreBottomImages();
        }
      }
    }, 100),

    /**
     * @description: 选择框修改事件
     * @param {*} val
     * @return {*}
     */
    handleCheckedRectChange(val) {
      this.checkedRectList = this.rectItem.filter((item) => {
        return val.includes(item.id);
      });
    },

    /**
     * @description: 图片位置信息获取
     * @param {*} val
     * @return {*}
     */
    updateRects() {
      this.rectItem = [];
      if (this.defectData.length > 0) {
        if (
          this.selectedThumbnail >
          this.defectData[this.currentIndex]?.items.length - 1
        ) {
          this.selectedThumbnail =
            this.defectData[this.currentIndex]?.items.length - 1;
        }
        this.rectItem = this.defectData[this.currentIndex]?.items[
          this.selectedThumbnail
        ].children.map((item) => {
          return {
            ...item,
            rectPosition: item.rect?.split(",").map(Number),
          };
        });
        this.checkedRectList = this.rectItem;
        this.checkedRect = this.rectItem?.map((item) => item.id);
      }
    },

    /**
     * @description: 图片红框位置
     * @param {*}
     * @return {*}
     */
    getRectStyle([left, top, width, height], index) {
      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",
        border: `2px solid ${this.colorList[index]}`,
      };
    },
  },
  mounted() {
    window.addEventListener("keydown", this.handleKeydown);
    window.addEventListener("resize", this.updateRects);
  },
  beforeDestroy() {
    window.removeEventListener("keydown", this.handleKeydown);
    window.removeEventListener("resize", this.updateRects);
  },
};
</script>

<style lang="scss" scoped>
.app {
  width: 100%;
  // height: 54rem;
  height: calc(100vh - 3rem);
  display: flex;
  flex-direction: row;
  background-color: #2e3a46;
}

.left-list {
  width: 16rem;
  height: 100%;

  .img-top {
    width: 100%;
    height: 2.5rem;
    display: flex;
    justify-content: center;

    .img-top-div {
      cursor: pointer;
      width: 30%;
      height: 90%;
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px solid #00aaff;
      border-radius: 4px;
      color: #ffffff;
    }

    .img-top-div-click {
      background-color: rgb(69, 91, 140);
    }
  }

  .sidebar {
    width: 15.5rem;
    height: calc(100% - 2.5rem);
    // height: 815px;
    background-color: #1f292e;
    padding: 10px;
    overflow-y: auto;
  }

  .sidebar::-webkit-scrollbar {
    width: 8px;
  }

  .sidebar::-webkit-scrollbar-track {
    background: #2e3a46;
    border-radius: 10px;
  }

  .sidebar::-webkit-scrollbar-thumb {
    background: #444c51;
    border-radius: 10px;
  }

  .sidebar::-webkit-scrollbar-thumb:hover {
    background: #00aaff;
  }

  .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.05);
  }
}

.main-content {
  width: calc(100% - 250px);
  height: 100%;
  background-color: #1b2126;
  padding: 10px;
  display: flex;
  flex-direction: column;
}

.toolbar {
  width: 100%;
  height: 4rem;
  display: flex;
  align-items: center;
  background-color: #333c42;
  padding: 5px;
  border-bottom: 1px solid #333c42;

  ::v-deep .el-form {
    width: 100%;

    .el-form-item--small .el-form-item__label {
      color: #ffffff;
    }

    .el-select {
      width: 12rem;

      .el-input--small .el-input__inner {
        color: #ffffff;
        background-color: #333c42;
      }

      .el-select-dropdown {
        background-color: #102649;
        border-color: #08204f;

        .el-scrollbar {
          .el-select-dropdown__wrap {
            .el-scrollbar__view {
              .el-select-dropdown__item {
                color: #ffffff;
              }

              .el-select-dropdown__item:hover {
                background-color: #2b4c7e;
              }

              .el-select-dropdown__item.selected {
                background-color: #2b4c7e;
              }

              .el-select-dropdown__item.hover {
                background-color: #2b4c7e;
              }
            }

            .el-select-dropdown__list {
              background-color: #333c42;
            }
          }
        }
      }
    }

    .el-input--small .el-input__inner {
      color: #ffffff;
      background-color: #333c42;
    }
  }
}

.image-container {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;

  ::v-deep .image-info {
    width: 100%;
    background-color: rgba(0, 0, 0, 0.5);

    .el-checkbox__input.is-checked + .el-checkbox__label {
      color: inherit;
      font-size: 1.1rem;
      line-height: 1.1rem;
    }

    .el-checkbox__label {
      color: inherit;
      font-size: 1.1rem;
      line-height: 1.1rem;
    }
  }
}

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

// 画框样式
.rect-overlay {
  position: absolute;

  // pointer-events: none;
  // border: 2px solid red;
  &:hover {
    opacity: 0.7;
  }

  > div {
    cursor: pointer;
    white-space: nowrap;
    position: absolute;
    top: -1.2rem;
  }
}

// 图片信息
.rect-image {
  width: 70%;
  position: absolute;
  top: 0;
}

.image-viewer {
  // height: 43rem;
  height: calc(100% - 9rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #22272b;
  position: relative;
}

.thumbnail-row {
  display: flex;
  justify-content: center;
  overflow-x: auto;
  padding: 10px;
  background-color: #333c42;
  gap: 10px;
}

.thumbnail-row img {
  width: 100px;
  height: 60px;
  cursor: pointer;
  border-radius: 3px;
  transition: transform 0.2s, border 0.2s;
  box-sizing: border-box;
}

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

// 按钮样式
.btn-submit {
  background-color: transparent;
  background-image: url("~@/assets/screen/index/btn-submit.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-position: 50%;
  border-color: transparent;
  color: #ffffff;

  &:active {
    color: #0d9ee2;
  }
}

.btn-cancel {
  background-color: transparent;
  background-image: url("~@/assets/screen/index/btn-cancel.png");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-position: 50%;
  border-color: transparent;
  color: #ffffff;

  &:active {
    color: #0d9ee2;
  }
}
</style>
