riku
2025-09-18 c1d2051abc8ca88cd07f0d7c56c0dbf8165d5c33
src/views/fysp/check/components/ArbitraryPhoto.vue
@@ -14,7 +14,12 @@
    @contextmenu="closeContextMenu"
    class="container"
  > -->
  <div v-if="showMenu" ref="menu" :style="menuStyle" class="context-menu">
  <div
    v-if="showMenu && !menuLoading"
    ref="menu"
    :style="menuStyle"
    class="context-menu"
  >
    <template v-for="(item, index) in menuItems" :key="index">
      <el-popover v-if="item.children" placement="right-start" trigger="hover">
        <template #reference>
@@ -58,22 +63,12 @@
      loading: true,
      // 右键图片弹出菜单控制
      showMenu: false,
      menuLoading: true,
      menuStyle: undefined,
      // menuItems: [
      //   { label: '复制图片', action: 'copy' },
      //   {
      //     label: '移动到',
      //     children: [
      //       {
      //         action: 'move',
      //         label: v.typeName,
      //         value: v.typeId
      //       }
      //     ]
      //   }
      // ],
      allMoveActions: [],
      closeContextMenuListenr: undefined,
      // 右键选中的图片
      selectedFileElement: undefined,
      selectedFile: undefined,
      selectedIndex: undefined,
      selectedTypeId: undefined
@@ -81,21 +76,14 @@
  },
  computed: {
    menuItems() {
      const sceneTypeId = this.subtask.sceneTypeId;
      const items = enumMediaFile(sceneTypeId, false)
        .filter((v) => {
          return v.value != this.selectedTypeId;
        })
        .map((v) => {
          return {
            action: 'move',
            label: v.label,
            value: v.value
          };
        });
      return [
        // { label: '复制图片', action: 'copy' },
        { label: '移动到', children: items }
        // { label: '复制到剪贴板', action: 'copy' },
        {
          label: '移动到',
          children: this.allMoveActions.filter((v) => {
            return v.value != this.selectedTypeId;
          })
        }
      ];
    }
  },
@@ -112,6 +100,8 @@
      }
    };
    document.addEventListener('click', this.closeContextMenuListenr);
    this.initMenuItems();
  },
  unmounted() {
    document.removeEventListener('click', this.closeContextMenuListenr);
@@ -158,6 +148,7 @@
        left: `${event.clientX}px`,
        top: `${event.clientY}px`
      };
      this.selectedFileElement = event.target;
      this.selectedTypeId = typeId;
      this.selectedIndex = index;
      this.selectedFile = this.typesMap.get(typeId)[index];
@@ -168,6 +159,7 @@
    handleMenuItem(item) {
      switch (item.action) {
        case 'copy':
          this.drawImageToCanvas();
          break;
        case 'move':
          this.selectedFile.data.businesstypeid = item.value;
@@ -217,6 +209,53 @@
      //   }
      //   this.selectedFile.loading = false;
      // }, 2000);
    },
    drawImageToCanvas() {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = this.selectedFileElement; // 获取DOM引用
      // img.crossOrigin = 'Anonymous';
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      this.copyCanvasToClipboard(canvas);
      const dataUrl = canvas.toDataURL('image/png'); // 可以选择其他格式如'image/jpeg'
      // 创建一个临时的textarea元素来复制文本
      const tempTextArea = document.createElement('textarea');
      document.body.appendChild(tempTextArea);
      tempTextArea.value = dataUrl;
      tempTextArea.select();
      document.execCommand('copy');
      document.body.removeChild(tempTextArea);
    },
    copyCanvasToClipboard(canvas) {
      canvas.toBlob((blob) => {
        const item = new ClipboardItem({ 'image/png': blob }); // 你可以根据需要改变格式,如 "image/jpeg"
        navigator.clipboard.write([item]).then(
          () => {
            console.log('Image copied to clipboard');
          },
          (err) => {
            console.error('Could not copy image: ', err);
          }
        );
      }, 'image/png'); // 同样,这里也可以指定其他格式,如 'image/jpeg'
    },
    // 初始化场景图片的类型菜单
    initMenuItems() {
      this.menuLoading = true;
      const sceneTypeId = this.subtask.sceneTypeId;
      enumMediaFile(sceneTypeId, false)
        .then((res) => {
          this.allMoveActions = res.map((v) => {
            return {
              action: 'move',
              label: v.label,
              value: v.value
            };
          });
        })
        .finally(() => (this.menuLoading = false));
    }
  }
};