<template>
  <div class="image-preview-container">
    <!-- 工具栏 -->
    <div class="preview-toolbar">
      <!-- 放大按钮 -->
      <a-button
        type="link"
        icon="zoom-in"
        @click="handleZoomIn"
        :disabled="scale >= maxScale"
      />
      <!-- 缩小按钮 -->
      <a-button
        type="link"
        icon="zoom-out"
        @click="handleZoomOut"
        :disabled="scale <= minScale"
      />
      <!-- 重置按钮 -->
      <a-button
        type="link"
        icon="sync"
        @click="handleReset"
      />
      <a-divider type="vertical"/>
      <!-- 左转按钮 -->
      <a-button
        type="link"
        icon="undo"
        @click="handleRotateLeft"
      />
      <!-- 右转按钮 -->
      <a-button
        type="link"
        icon="redo"
        @click="handleRotateRight"
      />
      <a-divider type="vertical"/>
      <!-- 当前缩放比例显示 -->
      <span class="scale-info">{{ Math.round(scale * 100) }}%</span>
    </div>

    <!-- 图片内容区域 -->
    <div class="preview-content" @wheel.prevent="handleWheel">
      <div class="preview-image-wrapper">
        <!-- 图片显示 -->
        <img
          v-if="src && !fullImageError"
          :src="src"
          :alt="alt"
          class="preview-image"
          :style="imageStyle"
          @mousedown="handleDragStart"
          @mousemove="handleDragMove"
          @mouseup="handleDragEnd"
          @mouseleave="handleDragEnd"
        />

        <!-- 图片加载错误提示 -->
        <div v-if="fullImageError" class="preview-error">
          <a-icon type="picture" style="font-size: 48px; color: #d9d9d9;"/>
          <p>图片加载失败</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'ImagePreview',
  props: {
    src: { // 图片地址
      type: String,
      required: true
    },
    alt: { // 图片 alt 属性
      type: String,
      default: '图片'
    }
  },
  data () {
    return {
      // 缩放相关
      scale: 1, // 当前缩放比例
      rotate: 0, // 当前旋转角度
      minScale: 0.1, // 最小缩放
      maxScale: 5, // 最大缩放
      scaleStep: 0.1, // 每次缩放步长

      // 拖拽相关
      translateX: 0, // X轴偏移
      translateY: 0, // Y轴偏移
      isDragging: false, // 是否正在拖拽
      dragStartX: 0, // 拖拽起点 X
      dragStartY: 0, // 拖拽起点 Y
      startTranslateX: 0, // 拖拽起始偏移 X
      startTranslateY: 0, // 拖拽起始偏移 Y

      // 图片加载错误状态
      fullImageError: false
    }
  },
  computed: {
    // 图片样式
    imageStyle () {
      return {
        // transform 包含平移、缩放和旋转
        transform: `translate(${this.translateX}px, ${this.translateY}px) scale(${this.scale}) rotate(${this.rotate}deg)`,
        // 拖拽时取消动画，防止滞后
        transition: this.isDragging ? 'none' : 'transform 0.3s ease',
        // 拖拽光标样式
        cursor: this.isDragging ? 'grabbing' : (this.scale > 1 ? 'grab' : 'default')
      }
    }
  },
  methods: {
    /**
     * 放大图片
     */
    handleZoomIn () {
      if (this.scale < this.maxScale) {
        this.scale = Math.min(this.scale + this.scaleStep, this.maxScale) // 避免超过最大值
      }
    },

    /**
     * 缩小图片
     */
    handleZoomOut () {
      if (this.scale > this.minScale) {
        this.scale = Math.max(this.scale - this.scaleStep, this.minScale) // 避免低于最小值
        // 缩小到 1 或以下重置偏移
        if (this.scale <= 1) {
          this.translateX = 0
          this.translateY = 0
        }
      }
    },

    /**
     * 向左旋转图片 90 度
     */
    handleRotateLeft () {
      this.rotate -= 90
    },

    /**
     * 向右旋转图片 90 度
     */
    handleRotateRight () {
      this.rotate += 90
    },

    /**
     * 重置图片状态
     */
    handleReset () {
      this.scale = 1
      this.rotate = 0
      this.translateX = 0
      this.translateY = 0
    },

    /**
     * 开始拖拽
     * @param {MouseEvent} event
     */
    handleDragStart (event) {
      if (this.scale <= 1) return // 缩放 <=1 时不可拖拽
      event.preventDefault()
      this.isDragging = true
      this.dragStartX = event.clientX
      this.dragStartY = event.clientY
      this.startTranslateX = this.translateX
      this.startTranslateY = this.translateY
    },

    /**
     * 拖拽移动
     * @param {MouseEvent} event
     */
    handleDragMove (event) {
      if (!this.isDragging) return
      event.preventDefault()
      const deltaX = event.clientX - this.dragStartX // 当前偏移 X
      const deltaY = event.clientY - this.dragStartY // 当前偏移 Y
      this.translateX = this.startTranslateX + deltaX
      this.translateY = this.startTranslateY + deltaY
    },

    /**
     * 结束拖拽
     */
    handleDragEnd (event) {
      if (!this.isDragging) return
      event.preventDefault()
      this.isDragging = false
    },

    /**
     * 鼠标滚轮缩放
     * @param {WheelEvent} event
     */
    handleWheel (event) {
      const delta = event.deltaY || event.wheelDelta
      if (delta > 0) this.handleZoomOut() // 向下滚动缩小
      else this.handleZoomIn() // 向上滚动放大
    }
  }
}
</script>

<style lang="less" scoped>
/* 整个预览容器 */
.image-preview-container {
  width: 100%;
  height: 100%;
  position: relative; /* 方便工具栏绝对定位 */
}

/* 工具栏样式 */
.preview-toolbar {
  position: absolute;        /* 悬浮在图片上方 */
  top: 16px;                 /* 距离顶部 16px */
  left: 50%;                 /* 居中 */
  transform: translateX(-50%);
  z-index: 10;               /* 确保在图片上层 */
  background: rgba(255, 255, 255, 0.95); /* 半透明白色背景 */
  border-radius: 8px;        /* 圆角 */
  padding: 8px 16px;         /* 内边距 */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* 阴影 */
  display: flex;
  align-items: center;
  gap: 8px;                  /* 按钮间距 */

  /* 工具栏按钮样式 */
  .ant-btn-link {
    color: #333;
    padding: 4px 8px;
    height: 32px;
    width: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;

    &:hover:not(:disabled) { /* 悬停状态 */
      color: #1890ff;
      background: rgba(24, 144, 255, 0.1);
      border-radius: 4px;
    }

    &:disabled { /* 禁用状态 */
      color: #d9d9d9;
      cursor: not-allowed;
    }
  }

  /* 分割线样式 */
  .ant-divider-vertical {
    height: 20px;
    margin: 0 4px;
    background: #e8e8e8;
  }

  /* 显示缩放比例 */
  .scale-info {
    color: #666;
    font-size: 12px;
    min-width: 40px;
    text-align: center;
    user-select: none; /* 禁止选中文本 */
  }
}

/* 图片内容区域 */
.preview-content {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;        /* 垂直居中 */
  justify-content: center;    /* 水平居中 */
  background: #fafafa;        /* 灰色背景 */
  overflow: hidden;           /* 超出隐藏 */
}

/* 图片包裹容器 */
.preview-image-wrapper {
  display: flex;
  align-items: center;        /* 垂直居中 */
  justify-content: center;    /* 水平居中 */
  width: 100%;
  height: 100%;
  //overflow: auto;             /* 超出可滚动 */
  position: relative;
}

/* 图片样式 */
.preview-image {
  max-width: 100%;            /* 最大宽度不超过容器 */
  max-height: 100%;           /* 最大高度不超过容器 */
  object-fit: contain;        /* 保持比例显示 */
  user-select: none;          /* 禁止选中图片 */
  transform-origin: center center; /* 旋转、缩放中心 */
  -webkit-user-drag: none;    /* 禁止图片拖拽 */
}

/* 图片加载错误提示 */
.preview-error {
  display: flex;
  flex-direction: column;     /* 图标和文字垂直排列 */
  align-items: center;        /* 水平居中 */
  justify-content: center;    /* 垂直居中 */
  gap: 16px;                  /* 图标和文字间距 */
  color: #999;

  p {
    margin: 0;
    font-size: 14px;
  }
}
</style>
