<template>
  <div class="app-container">
    <div class="tool-card">
      <div class="converter-layout">
        <!-- 右侧: 预览 & Canvas 结果 -->
        <div id="captureTarget" style="position: fixed; left: -100000px">
          <div v-html="editableHtml"> </div>
        </div>
        <div class="preview-panel">
          <div class="canvas-result">
            <canvas id="outputCanvas" v-show="canvasGenerated"></canvas>
            <!-- <div class="canvas-buttons" v-if="canvasGenerated">
              <button @click="downloadCanvasAsImage" class="download">
                📥 下载图片
              </button>
              <button @click="exportToPDF" class="pdf"> 📄 导出PDF </button>
              <button @click="printCanvas" class="print"> 🖨️ 打印 </button>
            </div> -->
          </div>
        </div>
      </div>
    </div>
    <!-- 图片素材区域 -->
    <div class="images-panel">
      <!-- 公用章 -->
      <div class="seal-section">
        <div class="panel-title">公用章</div>
        <div class="images-grid">
          <div
            v-for="(img, index) in publicImages"
            :key="'public-' + index"
            class="drag-item"
            draggable="true"
            @dragstart="handleDragStart($event, img, index, 'public')"
          >
            <img :src="img.imgUrl" :alt="img.name" />
            <div class="drag-item-name">{{ img.name }}</div>
          </div>
          <div v-if="!publicImages.length" class="no-data">暂无公用章</div>
        </div>
      </div>
      <!-- 个人章 -->
      <div class="seal-section">
        <div class="panel-title">个人章</div>
        <div class="images-grid">
          <div
            v-for="(img, index) in privateImages"
            :key="'private-' + index"
            class="drag-item"
            draggable="true"
            @dragstart="handleDragStart($event, img, index, 'private')"
          >
            <img :src="img.imgUrl" :alt="img.name" />
            <div class="drag-item-name">{{ img.name }}</div>
          </div>
          <div v-if="!privateImages.length" class="no-data">暂无个人章</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import {
    getSealPage,
    getPrivateSealPage
  } from '@/api/bpm/components/sealManagement';
  import { getUserDetail } from '@/api/system/organization/index';
  // 引入 html2canvas 和 jsPDF
  import html2canvas from 'html2canvas';
  import jsPDF from 'jspdf';
  //   const imageUrl = [
  //     require('@/assets/0.jpg'),
  //     require('@/assets/1.jpg'),
  //     require('@/assets/2.jpg'),
  //     require('@/assets/3.jpg'),
  //     require('@/assets/4.jpg'),
  //     require('@/assets/5.jpg')
  //   ]; // 使用相对路径或别名路径
  //   // 默认精美的示例HTML + CSS (内联样式丰富，展示能力)
  //   const DEFAULT_HTML = `
  //  <div class="container">
  //         <div class="img-area">
  //             <img class="my-photo" alt="loading" src="${imageUrl[0]}">
  //         </div>
  //         <div class="img-area">
  //             <img class="my-photo" alt="loading"  src="${imageUrl[1]}">
  //         </div>
  //              <div class="img-area">
  //             <img class="my-photo" alt="loading"  src="${imageUrl[2]}">
  //         </div>      <div class="img-area">
  //             <img class="my-photo" alt="loading"  src="${imageUrl[3]}">
  //         </div>      <div class="img-area">
  //             <img class="my-photo" alt="loading"  src="${imageUrl[4]}">
  //         </div>      <div class="img-area">
  //             <img class="my-photo" alt="loading"  src="${imageUrl[5]}">
  //         </div>
  // </div>
  // `;

  export default {
    name: 'HtmlToCanvas',
    data() {
      return {
        editableHtml: '',
        previewHtml: '',
        canvasGenerated: false,
        publicImages: [],
        privateImages: [],
        droppedImages: [],
        selectedImage: null,
        baseCanvasData: null, // 缓存基础内容的 Canvas 数据
        _isMoving: false, // 是否正在移动图片
        _currentMoveImageId: null, // 当前正在移动的图片ID
        _moveHandler: null, // 移动事件处理函数引用
        _mouseUpHandler: null, // 鼠标释放事件处理函数引用
        _dragOverHandler: null, // dragover事件处理函数引用
        _dropHandler: null, // drop事件处理函数引用
        _contextMenuHandler: null // contextmenu事件处理函数引用
      };
    },
    created() {
      // 获取公用章列表
      getSealPage({
        size: 999,
        pageNum: 1,
        status: 1,
        approvalStatus: 2,
        sealHolderId: this.$store.state.user.info.userId
      }).then((res) => {
        this.publicImages = res.list;
      });
      // 获取个人章列表
      getUserDetail(this.$store.state.user.info.userId).then((res) => {
        if (res.signature?.[0]) {
          this.privateImages = [
            {
              imgUrl: res.signature[0].url,
              name: res.name
            }
          ];
          console.log(this.privateImages, 'this.privateImages ');
        }
      });
    },
    mounted() {
      // 组件挂载后自动渲染一次
      this.$nextTick(() => {
        this.renderToCanvas();
      });

      // 保存组件实例引用，用于事件处理器
      window._aaComponentInstance = this;

      // 创建全局安全移除函数
      window._safeRemoveElement = function (element) {
        try {
          if (
            element &&
            element.parentNode &&
            document.body.contains(element)
          ) {
            element.parentNode.removeChild(element);
            return true;
          }
        } catch (err) {
          console.warn('安全移除元素时发生警告:', err);
        }
        return false;
      };
    },
    beforeDestroy() {
      // 清理移动事件监听器
      this._cancelMove();
      // 清理 Canvas 事件监听器
      const canvas = document.getElementById('outputCanvas');
      if (canvas) {
        if (this._dragOverHandler) {
          canvas.removeEventListener('dragover', this._dragOverHandler);
        }
        if (this._dropHandler) {
          canvas.removeEventListener('drop', this._dropHandler);
        }
        if (this._contextMenuHandler) {
          canvas.removeEventListener('contextmenu', this._contextMenuHandler);
        }
      }
      // 清理引用
      if (window._aaComponentInstance === this) {
        window._aaComponentInstance = null;
      }
      if (window._safeRemoveElement) {
        window._safeRemoveElement = null;
      }
    },
    methods: {
      // 获取组件实例
      getComponentInstance() {
        return window._aaComponentInstance || this;
      },

      // 安全的移除DOM元素
      safeRemoveElement(elementId) {
        try {
          const element = document.getElementById(elementId);
          if (window._safeRemoveElement) {
            return window._safeRemoveElement(element);
          }
          // 回退方案
          if (
            element &&
            element.parentNode &&
            document.body.contains(element)
          ) {
            element.parentNode.removeChild(element);
            return true;
          }
          return false;
        } catch (err) {
          console.warn(`移除元素 ${elementId} 时发生警告:`, err);
          return false;
        }
      },

      // 安全移除所有菜单
      safeRemoveAllMenus() {
        try {
          const existingMenus = document.querySelectorAll('[id^="menu_"]');

          // 使用倒序循环，避免在移除时影响NodeList
          for (let i = existingMenus.length - 1; i >= 0; i--) {
            const menu = existingMenus[i];
            if (menu && document.body.contains(menu) && menu.parentNode) {
              try {
                menu.parentNode.removeChild(menu);
              } catch (err) {
                console.warn('移除菜单时发生警告:', err);
              }
            }
          }
        } catch (err) {
          console.warn('移除所有菜单时发生错误:', err);
        }
      },
      // 设置 Canvas 拖放区域和点击事件
      setupCanvasDropZone() {
        const canvas = document.getElementById('outputCanvas');
        if (!canvas) {
          console.log('Canvas 元素不存在');
          return;
        }

        console.log('设置拖放区域和点击事件，Canvas ID:', canvas.id);
        console.log('Canvas 尺寸:', canvas.width, 'x', canvas.height);
        console.log(
          'Canvas 可见性:',
          canvas.style.display,
          canvas.style.visibility
        );
        console.log('Canvas 位置:', canvas.getBoundingClientRect());

        // 先移除旧的事件监听器，防止重复绑定
        if (this._dragOverHandler) {
          canvas.removeEventListener('dragover', this._dragOverHandler);
        }
        if (this._dropHandler) {
          canvas.removeEventListener('drop', this._dropHandler);
        }
        if (this._contextMenuHandler) {
          canvas.removeEventListener('contextmenu', this._contextMenuHandler);
        }

        // 创建事件处理函数并保存引用
        this._dragOverHandler = (e) => {
          e.preventDefault();
          e.dataTransfer.dropEffect = 'copy';
        };

        this._dropHandler = (e) => {
          e.preventDefault();
          console.log('触发 drop 事件');
          const imageData = e.dataTransfer.getData('imageData');
          console.log('获取到的 imageData:', imageData);
          if (imageData) {
            const data = JSON.parse(imageData);
            console.log('解析后的数据:', data);
            this.addImageToCanvas(data, e.offsetX, e.offsetY);
          }
        };

        this._contextMenuHandler = (e) => {
          e.preventDefault();
          this.handleCanvasRightClick(e);
        };

        // 添加新的事件监听器
        canvas.addEventListener('dragover', this._dragOverHandler);
        canvas.addEventListener('drop', this._dropHandler);
        canvas.addEventListener('contextmenu', this._contextMenuHandler);
      },

      // 处理拖拽开始
      handleDragStart(e, img, index, type) {
        const data = {
          url: img.imgUrl,
          name: img.name,
          version: img.version,
          imgId: type == 'public' ? img.id : ''
        };
        e.dataTransfer.setData('imageData', JSON.stringify(data));
        e.dataTransfer.effectAllowed = 'copy';
        console.log('拖拽开始:', data);
      },

      // 添加图片到 Canvas
      addImageToCanvas(data, x, y) {
        const canvas = document.getElementById('outputCanvas');
        if (!canvas || !this.canvasGenerated) {
          console.log('请先渲染 Canvas');

          return;
        }

        console.log('Canvas 尺寸:', canvas.width, canvas.height);
        console.log('拖放位置:', x, y);

        const ctx = canvas.getContext('2d');
        const img = new Image();
        img.crossOrigin = 'anonymous';

        img.onload = () => {
          console.log('图片加载成功，原始尺寸:', img.width, img.height);

          // 默认图片大小为 100x100
          const width = 100;
          const height = 100;
          const posX = x - width / 2;
          const posY = y - height / 2;

          console.log('绘制位置:', posX, posY, '尺寸:', width, height);

          // 绘制图片
          ctx.drawImage(img, posX, posY, width, height);

          const imageId = `img_${Date.now()}_${Math.random()
            .toString(36)
            .substr(2, 9)}`;

          this.droppedImages.push({
            id: imageId,
            imgId: data.imgId,
            imgUrl: data.url,
            version: data.version,
            x: posX,
            y: posY,
            width,
            height,
            originalWidth: img.width,
            originalHeight: img.height
          });

          console.log('已添加的图片数量:', this.droppedImages.length);
          this.$message({
            showClose: true,
            message: '操作成功',
            type: 'success'
          });

          // 设置图片可再次拖动和调整（通过右键菜单）
          // 不再创建覆盖层，仅通过右键菜单操作
        };

        img.onerror = (err) => {
          console.error('图片加载失败:', err);
          this.$message({
            showClose: true,
            message: '操作失败',
            type: 'error'
          });
          // this.showMessage('⚠️ 图片加载失败', 'error');
        };

        img.src = data.url;
      },

      // 重新绘制整个 Canvas
      redrawCanvas() {
        const canvas = document.getElementById('outputCanvas');
        if (!canvas || !this.canvasGenerated) return;

        const ctx = canvas.getContext('2d');

        try {
          // 清空 Canvas
          ctx.clearRect(0, 0, canvas.width, canvas.height);

          // 如果有缓存的基础内容，直接绘制
          if (this.baseCanvasData) {
            ctx.drawImage(this.baseCanvasData, 0, 0);
          } else {
            // 如果没有缓存，重新渲染基础内容
            console.warn('没有缓存的基础内容，可能需要重新渲染');
            return;
          }

          // 重新绘制所有拖入的图片
          this.droppedImages.forEach((image) => {
            const img = new Image();
            img.onload = () => {
              ctx.drawImage(img, image.x, image.y, image.width, image.height);
            };
            img.src = image.imgUrl;
          });

          console.log(
            'Canvas 已快速重绘，包含基础内容和',
            this.droppedImages.length,
            '张图片'
          );

          // 确保事件监听仍然有效
          setTimeout(() => {
            this.setupCanvasDropZone();
          }, 100);
        } catch (error) {
          console.error('重新绘制 Canvas 失败:', error);
        }
      },

      // 显示图片控制菜单
      showImageControls(imageId, x, y) {
        console.log('显示图片控制菜单，位置:', x, y, '图片ID:', imageId);

        // 保存组件实例引用
        const self = this;

        // 先移除可能存在的其他菜单
        this.safeRemoveAllMenus();

        // 定义菜单选项（使用局部变量 self）
        const options = [
          { text: '放大', action: () => self.resizeImage(imageId, 1.2) },
          { text: '缩小', action: () => self.resizeImage(imageId, 0.8) },
          { text: '移动', action: () => self.startMoveImage(imageId, x, y) },
          { text: '删除', action: () => self.removeImage(imageId) }
        ];

        const menu = document.createElement('div');
        menu.id = `menu_${imageId}`;
        menu.style.position = 'fixed';

        // 调整位置，避免菜单超出屏幕边界
        const menuWidth = 120;
        const menuHeight = options.length * 40 + 16; // 估算高度

        let left = x;
        let top = y;

        // 如果菜单会超出右侧边界，向左移动
        if (left + menuWidth > window.innerWidth) {
          left = window.innerWidth - menuWidth - 10;
        }

        // 如果菜单会超出底部边界，向上移动
        if (top + menuHeight > window.innerHeight) {
          top = window.innerHeight - menuHeight - 10;
        }

        menu.style.left = `${left}px`;
        menu.style.top = `${top}px`;
        menu.style.background = 'white';
        menu.style.border = '1px solid #e2e8f0';
        menu.style.borderRadius = '8px';
        menu.style.padding = '8px 0';
        menu.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.1)';
        menu.style.zIndex = '9999'; // 使用更高的 z-index
        menu.style.minWidth = `${menuWidth}px`;
        menu.style.opacity = '1';
        menu.style.visibility = 'visible';
        menu.style.display = 'block';

        console.log('菜单位置 - 原始:', x, y, '调整后:', left, top);

        options.forEach((option) => {
          const item = document.createElement('div');
          item.innerText = option.text;
          item.style.padding = '8px 16px';
          item.style.cursor = 'pointer';
          item.style.fontSize = '14px';
          item.style.color = '#374151';

          item.addEventListener('mouseenter', () => {
            item.style.background = '#f3f4f6';
          });

          item.addEventListener('mouseleave', () => {
            item.style.background = 'white';
          });

          item.addEventListener('click', () => {
            option.action();
            // 直接移除当前菜单
            const menuToRemove = document.getElementById(`menu_${imageId}`);
            if (window._safeRemoveElement) {
              window._safeRemoveElement(menuToRemove);
            }
          });

          menu.appendChild(item);
        });

        document.body.appendChild(menu);
        console.log('菜单已添加到 DOM，父元素:', menu.parentElement?.tagName);

        // 点击其他地方关闭菜单
        const closeMenu = (e) => {
          console.log('closeMenu 被调用，目标:', e.target);
          const currentMenu = document.getElementById(`menu_${imageId}`);
          if (!currentMenu || !document.body.contains(currentMenu)) {
            // 菜单已经不存在，移除监听器
            document.removeEventListener('click', closeMenu);
            return;
          }

          if (e.target !== currentMenu && !currentMenu.contains(e.target)) {
            // 使用全局安全函数移除菜单
            if (window._safeRemoveElement) {
              window._safeRemoveElement(currentMenu);
            }
            document.removeEventListener('click', closeMenu);
          }
        };

        setTimeout(() => {
          console.log('添加全局点击监听器');
          document.addEventListener('click', closeMenu);
        }, 0);
      },

      // 调整图片大小
      resizeImage(imageId, factor) {
        const imageIndex = this.droppedImages.findIndex(
          (img) => img.id === imageId
        );
        if (imageIndex === -1) return;

        const image = this.droppedImages[imageIndex];
        image.width *= factor;
        image.height *= factor;

        this.redrawCanvas();
      },

      // 处理 Canvas 右键点击
      handleCanvasRightClick(e) {
        console.log('Canvas 右键点击事件触发');

        const canvas = document.getElementById('outputCanvas');
        if (!canvas) {
          console.log('Canvas 元素不存在');
          return;
        }

        console.log(
          'Canvas 元素存在，droppedImages 数量:',
          this.droppedImages.length
        );

        if (this.droppedImages.length === 0) {
          console.log('没有已添加的图片');
          return;
        }

        const rect = canvas.getBoundingClientRect();
        console.log('Canvas 边界矩形:', rect);

        const scaleX = canvas.width / rect.width;
        const scaleY = canvas.height / rect.height;

        // 计算点击位置相对于 Canvas 的坐标
        const clickX = (e.clientX - rect.left) * scaleX;
        const clickY = (e.clientY - rect.top) * scaleY;

        console.log('右键点击位置 - 屏幕:', e.clientX, e.clientY);
        console.log('右键点击位置 - Canvas相对:', clickX, clickY);

        // 查找点击到的图片
        let clickedImage = null;
        for (const image of this.droppedImages) {
          console.log(
            '检查图片:',
            image.id,
            '位置:',
            image.x,
            image.y,
            '尺寸:',
            image.width,
            image.height
          );
          if (
            clickX >= image.x &&
            clickX <= image.x + image.width &&
            clickY >= image.y &&
            clickY <= image.y + image.height
          ) {
            clickedImage = image;
            break;
          }
        }

        if (clickedImage) {
          console.log('点击到图片:', clickedImage.id);
          this.showImageControls(clickedImage.id, e.clientX, e.clientY);
        } else {
          console.log('未点击到任何图片');
          // 可以在这里添加其他右键功能，比如添加新图片等
        }
      },

      // 开始移动图片
      startMoveImage(imageId, menuX, menuY) {
        console.log('开始移动图片，图片ID:', imageId);

        // 关闭菜单
        this.safeRemoveElement(`menu_${imageId}`);

        const canvas = document.getElementById('outputCanvas');
        if (!canvas) {
          console.error('Canvas 元素未找到');
          return;
        }

        const imageIndex = this.droppedImages.findIndex(
          (img) => img.id === imageId
        );
        if (imageIndex === -1) {
          console.error('图片未找到，ID:', imageId);
          return;
        }

        const image = this.droppedImages[imageIndex];
        console.log('找到图片:', image);

        // 如果已经在移动中，先移除旧的事件监听器
        if (this._isMoving) {
          this._cancelMove();
        }

        // 设置移动状态标志
        this._isMoving = true;
        this._currentMoveImageId = imageId;

        // 创建一个临时指示器
        const indicator = document.createElement('div');
        indicator.id = `move_indicator_${imageId}`;
        indicator.style.position = 'fixed';
        indicator.style.left = `${menuX}px`;
        indicator.style.top = `${menuY}px`;
        indicator.style.width = '40px';
        indicator.style.height = '40px';
        indicator.style.background = 'rgba(59, 130, 246, 0.3)';
        indicator.style.border = '2px dashed #3b82f6';
        indicator.style.borderRadius = '50%';
        indicator.style.zIndex = '3000';
        indicator.style.pointerEvents = 'none';
        document.body.appendChild(indicator);
        console.log('指示器已创建并添加到DOM');

        // 显示提示
        this.$message({
          showClose: true,
          message: '📍 移动鼠标调整位置，释放鼠标完成移动',
          type: 'info'
        });

        // 保存事件处理函数引用，用于后续移除
        this._moveHandler = (e) => {
          console.log('moveHandler 被调用，鼠标位置:', e.clientX, e.clientY);
          const rect = canvas.getBoundingClientRect();
          const scaleX = canvas.width / rect.width;
          const scaleY = canvas.height / rect.height;

          // 计算相对于 canvas 的位置
          const newX = (e.clientX - rect.left) * scaleX - image.width / 2;
          const newY = (e.clientY - rect.top) * scaleY - image.height / 2;

          // 限制在 canvas 范围内
          image.x = Math.max(0, Math.min(newX, canvas.width - image.width));
          image.y = Math.max(0, Math.min(newY, canvas.height - image.height));

          // 更新指示器位置
          indicator.style.left = `${e.clientX - 20}px`;
          indicator.style.top = `${e.clientY - 20}px`;

          // 使用组件实例引用
          const component = window._aaComponentInstance || this;
          if (component && component.redrawCanvas) {
            component.redrawCanvas();
          }
        };

        this._mouseUpHandler = (e) => {
          console.log(
            'mouseUpHandler 被调用，位置:',
            e.clientX,
            e.clientY,
            '目标:',
            e.target
          );

          // 无论在哪里释放鼠标，都完成移动
          console.log('鼠标释放，完成移动');

          // 确保只处理一次
          if (indicator.parentNode) {
            console.log('指示器仍在DOM中，移除事件监听器');
            document.removeEventListener('mousemove', this._moveHandler);
            document.removeEventListener('mouseup', this._mouseUpHandler);
            indicator.remove();
            // 重置移动状态
            this._isMoving = false;
            this._currentMoveImageId = null;
            this._moveHandler = null;
            this._mouseUpHandler = null;
            // 使用组件实例引用
            const component = window._aaComponentInstance || this;
            if (component) {
              this.$message({
                showClose: true,
                message: '图片已移动',
                type: 'success'
              });
            }
          } else {
            console.log('指示器已不在DOM中');
          }
        };

        // 确保事件只绑定一次
        console.log('绑定事件监听器');
        document.removeEventListener('mousemove', this._moveHandler);
        document.removeEventListener('mouseup', this._mouseUpHandler);
        document.addEventListener('mousemove', this._moveHandler);
        document.addEventListener('mouseup', this._mouseUpHandler);
      },

      // 删除图片
      removeImage(imageId) {
        const imageIndex = this.droppedImages.findIndex(
          (img) => img.id === imageId
        );
        if (imageIndex === -1) return;

        this.droppedImages.splice(imageIndex, 1);

        // 删除控制菜单
        this.safeRemoveElement(`menu_${imageId}`);

        // 如果正在移动这张图片，取消移动状态
        if (this._currentMoveImageId === imageId) {
          this._cancelMove();
        }

        this.redrawCanvas();
        this.$message({
          showClose: true,
          message: '🗑️ 图片已删除',
          type: 'success'
        });
      },

      // 取消移动操作
      _cancelMove() {
        if (this._moveHandler) {
          document.removeEventListener('mousemove', this._moveHandler);
        }
        if (this._mouseUpHandler) {
          document.removeEventListener('mouseup', this._mouseUpHandler);
        }
        // 移除指示器
        if (this._currentMoveImageId) {
          const indicator = document.getElementById(
            `move_indicator_${this._currentMoveImageId}`
          );
          if (indicator && indicator.parentNode) {
            indicator.remove();
          }
        }
        // 重置状态
        this._isMoving = false;
        this._currentMoveImageId = null;
        this._moveHandler = null;
        this._mouseUpHandler = null;
      },

      // 渲染Canvas核心函数
      async renderToCanvas() {
        const targetElement = document.getElementById('captureTarget');
        if (!targetElement) {
          console.warn('未找到目标元素');
          return;
        }

        // 显示加载状态
        const canvasResultDiv = document.querySelector('.canvas-result');
        const originalMsg = canvasResultDiv.querySelector('p');
        if (originalMsg) originalMsg.style.display = 'none';

        // 添加加载提示
        let loadingMsg = document.getElementById('tempLoadingMsg');
        if (!loadingMsg) {
          loadingMsg = document.createElement('div');
          loadingMsg.id = 'tempLoadingMsg';
          loadingMsg.innerText = '⏳ 渲染中，请稍候...';
          loadingMsg.style.padding = '12px';
          loadingMsg.style.color = '#2563eb';
          loadingMsg.style.fontSize = '14px';
          canvasResultDiv.appendChild(loadingMsg);
        }

        try {
          // 使用 html2canvas 进行转换
          const canvas = await html2canvas(targetElement, {
            scale: 1, // 1倍分辨率，避免过大
            backgroundColor: '#ffffff',
            useCORS: true, // 尝试跨域图片
            logging: false,
            allowTaint: false,
            imageTimeout: 5000,
            windowWidth: targetElement.scrollWidth,
            windowHeight: targetElement.scrollHeight
          });

          // 移除加载提示
          const temp = document.getElementById('tempLoadingMsg');
          if (temp) temp.remove();

          // 获取输出canvas元素并绘制
          const outputCanvas = document.getElementById('outputCanvas');
          outputCanvas.width = canvas.width;
          outputCanvas.height = canvas.height;
          // 移除内联样式，使用实际像素尺寸
          outputCanvas.style.width = canvas.width + 'px';
          outputCanvas.style.height = canvas.height + 'px';
          const ctx = outputCanvas.getContext('2d');
          ctx.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
          ctx.drawImage(canvas, 0, 0);

          // 保存基础内容的 Canvas 数据（用于快速重绘）
          this.baseCanvasData = canvas;

          this.canvasGenerated = true;

          // 设置 Canvas 拖放区域和事件监听
          this.setupCanvasDropZone();

          // 显示成功提示
          // this.showMessage('✅ 渲染成功！可下载图片', 'success');
        } catch (error) {
          console.error('html2canvas 渲染失败: ', error);
          const temp = document.getElementById('tempLoadingMsg');
          if (temp) temp.remove();
          this.canvasGenerated = false;
          // this.showMessage('⚠️ 渲染失败，请检查HTML结构或外部资源', 'error');
        }
      },

      // 导出为 PDF（使用 jsPDF）
      exportToPDF() {
        const outputCanvas = document.getElementById('outputCanvas');
        if (
          !this.canvasGenerated ||
          !outputCanvas ||
          outputCanvas.width === 0
        ) {
          // this.showMessage(
          //   '请先点击"渲染至Canvas"生成图像后再导出PDF',
          //   'error'
          // );
          return;
        }

        try {
          const imgData = outputCanvas.toDataURL('image/png');
          // 使用 Canvas 的 CSS 尺寸（显示尺寸），而不是内部像素尺寸
          const canvasWidth =
            parseFloat(outputCanvas.style.width) || outputCanvas.width;
          const canvasHeight =
            parseFloat(outputCanvas.style.height) || outputCanvas.height;

          // 创建 PDF 实例，横向或纵向根据 Canvas 尺寸决定
          const orientation = canvasWidth > canvasHeight ? 'l' : 'p';
          // 使用 'mm' 单位，并根据 96 DPI 转换为毫米
          // 96 DPI 下：1px = 25.4 / 96 mm ≈ 0.2646 mm
          const DPI = 96;
          const pxToMm = 25.4 / DPI;
          const pdfWidth = canvasWidth * pxToMm;
          const pdfHeight = canvasHeight * pxToMm;

          const pdf = new jsPDF(orientation, 'mm', [pdfWidth, pdfHeight]);

          // 将 Canvas 图片添加到 PDF
          pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);

          // 获取 PDF 文件流并触发事件
          const pdfBlob = pdf.output('blob');
          const pdfFile = new File([pdfBlob], `canvas-${Date.now()}.pdf`, {
            type: 'application/pdf'
          });

          // 触发 PDF 生成事件，父组件可以监听此事件
          this.$emit('pdf-generated', {
            pdfFile,
            droppedImages: this.droppedImages
          });

          // 保存 PDF
          // const timestamp = new Date()
          //   .toISOString()
          //   .slice(0, 19)
          //   .replace(/:/g, '-');
          // pdf.save(`canvas-${timestamp}.pdf`);

          // this.showMessage('✅ PDF 导出成功', 'success');
        } catch (err) {
          console.error('PDF 导出失败', err);
          // this.showMessage('PDF 导出失败，请稍后重试', 'error');
        }
      },

      // 重新渲染基础内容（当 HTML 内容变化时调用）
      async refreshBaseContent() {
        try {
          const targetElement = document.getElementById('captureTarget');
          if (!targetElement) return;

          const newCanvas = await html2canvas(targetElement, {
            scale: 1,
            backgroundColor: '#ffffff',
            useCORS: true,
            logging: false,
            allowTaint: false,
            imageTimeout: 5000,
            width: 1000,
            windowWidth: targetElement.scrollWidth,
            windowHeight: targetElement.scrollHeight
          });

          this.baseCanvasData = newCanvas;

          // 更新主 Canvas
          const outputCanvas = document.getElementById('outputCanvas');
          if (outputCanvas && this.canvasGenerated) {
            const ctx = outputCanvas.getContext('2d');
            ctx.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
            ctx.drawImage(newCanvas, 0, 0);

            // 重新绘制所有拖入的图片
            this.droppedImages.forEach((image) => {
              const img = new Image();
              img.onload = () => {
                ctx.drawImage(img, image.x, image.y, image.width, image.height);
              };
              img.src = image.imgUrl;
            });
          }

          console.log('基础内容已更新');
        } catch (error) {
          console.error('更新基础内容失败:', error);
        }
      },

      // 获取 PDF 文件流（用于直接上传）
      getPDFFile() {
        const outputCanvas = document.getElementById('outputCanvas');
        if (
          !this.canvasGenerated ||
          !outputCanvas ||
          outputCanvas.width === 0
        ) {
          // this.showMessage(
          //   '请先点击"渲染至Canvas"生成图像后再获取PDF',
          //   'error'
          // );
          return Promise.reject(new Error('Canvas 未生成'));
        }

        return new Promise((resolve, reject) => {
          try {
            const imgData = outputCanvas.toDataURL('image/png');
            const canvasWidth = outputCanvas.width;
            const canvasHeight = outputCanvas.height;

            // 创建 PDF 实例
            const orientation = canvasWidth > canvasHeight ? 'l' : 'p';
            const pdf = new jsPDF(orientation, 'px', [
              canvasWidth,
              canvasHeight
            ]);

            // 将 Canvas 图片添加到 PDF
            pdf.addImage(imgData, 'PNG', 0, 0, canvasWidth, canvasHeight);

            // 获取 PDF 文件流
            const pdfBlob = pdf.output('blob');
            const pdfFile = new File([pdfBlob], `canvas-${Date.now()}.pdf`, {
              type: 'application/pdf'
            });

            resolve(pdfFile);
          } catch (err) {
            console.error('获取 PDF 文件流失败', err);
            reject(err);
          }
        });
      },

      // 打印 Canvas / 另存为 PDF
      printCanvas() {
        const outputCanvas = document.getElementById('outputCanvas');
        if (
          !this.canvasGenerated ||
          !outputCanvas ||
          outputCanvas.width === 0
        ) {
          // this.showMessage('请先点击"渲染至Canvas"生成图像后再打印', 'error');
          return;
        }

        try {
          // 创建新窗口用于打印
          const printWindow = window.open('', '_blank');
          const dataUrl = outputCanvas.toDataURL('image/png');

          printWindow.document.write(`
            <!DOCTYPE html>
            <html>
            <head>
              <title>打印图片</title>
              <style>
                body {
                  margin: 0;
                  padding: 20px;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                }
                img {
                  max-width: 100%;
                  height: auto;
                }
                @media print {
                  body {
                    padding: 0;
                  }
                  img {
                    max-width: 100%;
                    page-break-inside: avoid;
                  }
                }
              </style>
            </head>
            <body>
              <img src="${dataUrl}" onload="window.print(); window.close();" />
            </body>
            </html>
          `);
          printWindow.document.close();

          // this.showMessage('✅ 已打开打印窗口，可选择另存为PDF', 'success');
        } catch (err) {
          console.error('打印失败', err);
          // this.showMessage('打印失败，请检查浏览器设置', 'error');
        }
      },

      init(html) {
        this.editableHtml = html;
        this.previewHtml = html;
        this.$nextTick(() => {
          this.renderToCanvas();
        });
      }
    }
  };
</script>

<style scoped>
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  .app-container {
    max-width: 1400px;
    width: 100%;
    margin: 0 auto;
    padding: 24px 20px;
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background: linear-gradient(145deg, #e0eafc 0%, #cfdef3 100%);
  }

  .tool-card {
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(2px);
    border-radius: 2rem;
    box-shadow: 0 25px 45px -12px rgba(0, 0, 0, 0.3),
      0 1px 2px rgba(0, 0, 0, 0.05);
    overflow: hidden;
    padding: 1.8rem 2rem 2rem 2rem;
    width: 100%;
  }

  h1 {
    font-size: 2rem;
    font-weight: 700;
    background: linear-gradient(135deg, #1a2a6c, #3b82f6, #8b5cf6);
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    letter-spacing: -0.3px;
    margin-bottom: 0.35rem;
  }

  .sub {
    color: #4a5568;
    border-left: 4px solid #3b82f6;
    padding-left: 14px;
    margin-bottom: 1.8rem;
    font-weight: 500;
    font-size: 0.95rem;
  }

  .converter-layout {
    display: flex;
    justify-content: center;
  }

  .editor-panel {
    flex: 1.2;
    min-width: 280px;
    background: #f8fafc;
    border-radius: 1.5rem;
    padding: 1.25rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
    border: 1px solid #e2e8f0;
  }

  .panel-title {
    font-weight: 600;
    font-size: 1.2rem;
    color: #0f172a;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 2px solid #cbd5e1;
    padding-bottom: 8px;
  }

  .html-editor {
    width: 100%;
    height: 360px;
    background: #1e293b;
    color: #e2e8f0;
    font-family: 'Fira Code', 'Cascadia Code', monospace;
    font-size: 13px;
    line-height: 1.5;
    padding: 1rem;
    border-radius: 1rem;
    border: none;
    resize: vertical;
    outline: none;
    margin-bottom: 1rem;
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2);
  }

  .html-editor:focus {
    border: 1px solid #3b82f6;
    background: #0f172a;
  }

  .toolbar {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 8px;
    margin-bottom: 16px;
  }

  button {
    background: white;
    border: 1px solid #cbd5e1;
    padding: 8px 18px;
    border-radius: 40px;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    transition: 0.2s;
    color: #1e293b;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  }

  button.primary {
    background: #3b82f6;
    border-color: #3b82f6;
    color: white;
    box-shadow: 0 4px 8px rgba(59, 130, 246, 0.3);
  }

  button.primary:hover {
    background: #2563eb;
    transform: translateY(-1px);
  }

  button.download {
    background: #10b981;
    border-color: #10b981;
    color: white;
  }

  button.download:hover {
    background: #059669;
    transform: translateY(-1px);
  }

  button.pdf {
    background: #8b5cf6;
    border-color: #8b5cf6;
    color: white;
  }

  button.pdf:hover {
    background: #7c3aed;
    transform: translateY(-1px);
  }

  button.print {
    background: #8b5cf6;
    border-color: #8b5cf6;
    color: white;
  }

  button.print:hover {
    background: #7c3aed;
    transform: translateY(-1px);
  }

  .canvas-buttons {
    display: flex;
    gap: 12px;
    justify-content: center;
    margin-top: 16px;
  }

  button:hover {
    background: #f1f5f9;
    transform: translateY(-1px);
  }

  .info-message {
    font-size: 0.8rem;
    color: #2563eb;
    background: #eff6ff;
    padding: 6px 12px;
    border-radius: 40px;
    display: inline-block;
  }

  .preview-panel {
    flex: 1;
    min-width: 0;
    background: #ffffff;
    border-radius: 1.5rem;
    padding: 1.25rem;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
    border: 1px solid #eef2ff;
    display: flex;
    flex-direction: column;
  }

  .images-panel {
    flex: 0 0 300px;
    background: #ffffff;
    border-radius: 1.5rem;
    padding: 1.25rem;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
    border: 1px solid #eef2ff;
    display: flex;
    flex-direction: column;
    position: fixed;
    right: 2rem;
    top: 40px;
    max-height: calc(100vh - 80px);
    overflow-y: auto;
    z-index: 100;
  }

  .seal-section {
    margin-bottom: 1rem;
  }

  .seal-section:last-child {
    margin-bottom: 0;
  }

  .no-data {
    grid-column: 1 / -1;
    text-align: center;
    color: #94a3b8;
    padding: 20px 0;
    font-size: 14px;
  }

  .images-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    /* flex: 1; */
    overflow-y: auto;
  }

  .drag-item {
    background: #f8fafc;
    border: 2px solid #e2e8f0;
    border-radius: 12px;
    padding: 8px;
    cursor: move;
    transition: all 0.2s;
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 130px; /* 固定高度：图片80px + 内边距8px*2 + 文字区域 */
    justify-content: space-between;
  }

  .drag-item:hover {
    border-color: #3b82f6;
    background: #eff6ff;
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
  }

  .drag-item img {
    width: 100%;
    height: 80px;
    object-fit: contain; /* 改为contain，确保完整显示图片 */
    border-radius: 8px;
    pointer-events: none;
    background-color: #f1f5f9; /* 添加背景色，防止透明图片看不清 */
  }

  .drag-item-name {
    font-size: 12px;
    color: #64748b;
    margin-top: 6px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;
    line-height: 1.4;
    padding: 0 4px;
    max-height: 32px; /* 限制文字最大高度 */
  }

  .preview-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 1rem;
    flex-wrap: wrap;
  }

  .badge {
    background: #e6f0ff;
    padding: 4px 12px;
    border-radius: 30px;
    font-size: 0.75rem;
    font-weight: 500;
    color: #1e40af;
  }

  .canvas-area {
    background: #f1f5f9;
    border-radius: 1.2rem;
    padding: 1rem;
    text-align: center;
    min-height: 280px;
  }

  .target-element {
    background: white;
    border-radius: 1rem;
    padding: 1rem;
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.05);
    max-width: 100%;
    overflow: auto;
  }

  hr {
    margin: 0.8rem 0;
    border-color: #e2e8f0;
  }

  .canvas-result {
    margin-top: 1rem;
    background: #ffffffd9;
    border-radius: 1rem;
    padding: 0.8rem;
    text-align: center;
  }

  .canvas-result p {
    font-size: 0.8rem;
    color: #475569;
  }

  canvas {
    border-radius: 12px;
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
    background: white;
  }

  footer {
    margin-top: 1.5rem;
    text-align: center;
    font-size: 0.75rem;
    color: #334155;
  }

  @media (max-width: 780px) {
    .tool-card {
      padding: 1rem;
    }
    .html-editor {
      height: 260px;
    }
    .converter-layout {
      justify-content: center;
      /* flex-wrap: wrap;
      padding-right: 0;
      gap: 1rem; */
    }
    .images-panel {
      position: relative;
      right: auto;
      top: auto;
      width: 100%;
      max-height: 300px; /* 在小屏幕下限制最大高度 */
      order: 2; /* 在移动端将图片区域放在底部 */
      margin-top: 1rem;
    }
    .drag-item {
      height: 120px; /* 在小屏幕下稍微减小高度 */
    }
    .drag-item img {
      height: 70px; /* 在小屏幕下减小图片高度 */
    }
  }
</style>
