src/views/fysp/check/components/ArbitraryPhoto.vue
@@ -1,68 +1,291 @@
<template>
  <FYImageSelectDialog
    v-bind="$attrs"
    v-loading="loading"
    title="场景图片"
    :typeList="typesList"
    :typeImgMap="typesMap"
    :onContextMenu="showContextMenu"
    contextMenuStr="右键点击图片修改分类"
  ></FYImageSelectDialog>
  <!-- <div
    @click="closeContextMenu"
    @contextmenu="closeContextMenu"
    class="container"
  > -->
  <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>
          <el-row justify="space-between" class="menu-item">
            <span>{{ item.label }}</span>
            <el-icon><ArrowRight /></el-icon>
          </el-row>
        </template>
        <div
          v-for="(item1, index1) in item.children"
          :key="index1"
          class="menu-item"
          @click.stop="handleMenuItem(item1)"
        >
          {{ item1.label }}
        </div>
      </el-popover>
      <div class="menu-item" @click.stop="handleMenuItem(item)" v-else>
        {{ item.label }}
      </div>
    </template>
  </div>
  <!-- </div> -->
</template>
<script>
import mediafileApi from '@/api/fysp/mediafileApi.js';
import { $fysp } from '@/api/index.js';
import { enumMediaFile } from '@/enum/mediaFile.js';
export default {
  props: {
    subtask: {
      type: Object,
      efault: {}
      type: Object
    }
  },
  data() {
    return {
      // 无数据
      typesList: [],
      typesMap: new Map(),
      loading: true,
      // 右键图片弹出菜单控制
      showMenu: false,
      menuLoading: true,
      menuStyle: undefined,
      allMoveActions: [],
      closeContextMenuListenr: undefined,
      // 右键选中的图片
      selectedFileElement: undefined,
      selectedFile: undefined,
      selectedIndex: undefined,
      selectedTypeId: undefined
    };
  },
  computed: {
    menuItems() {
      return [
        // { label: '复制到剪贴板', action: 'copy' },
        {
          label: '移动到',
          children: this.allMoveActions.filter((v) => {
            return v.value != this.selectedTypeId;
          })
        }
      ];
    }
  },
  mounted() {
    this.getGroupImgs();
    this.closeContextMenuListenr = (event) => {
      if (
        this.$refs.menu &&
        !this.$refs.menu.contains(event.target) &&
        this.showMenu
      ) {
        // 如果点击不是在菜单内部且菜单是可见的
        this.showMenu = false; // 隐藏菜单
      }
    };
    document.addEventListener('click', this.closeContextMenuListenr);
    this.initMenuItems();
  },
  unmounted() {
    document.removeEventListener('click', this.closeContextMenuListenr);
  },
  methods: {
    // 图片分类
    getGroupImgs() {
      mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => {
        let typeList = [];
        let typeMap = new Map();
        function hasThisTypeName(typeName) {
          return typeList.map((item) => item.typeName).indexOf(typeName) != -1;
        }
        function addNewType(typeId, typeName, img) {
          typeList.push({
            typeId: typeId,
            typeName: typeName
          });
          typeMap.set(typeId, [img]);
        }
        function addToThisType(typeId, img) {
          typeMap.get(typeId).push(img);
        }
        const data = res.data;
        for (const e of data) {
          let img = {
            url: $fysp.imgUrl + e.extension1 + e.guid + '.jpg'
          };
          const businesstype = e.businesstype;
          const businesstypeid = e.businesstypeid;
          if (hasThisTypeName(businesstype)) {
            addToThisType(businesstypeid, img);
          } else {
            addNewType(businesstypeid, businesstype, img);
      mediafileApi
        .getRoutineByStGuid(this.subtask.stGuid)
        .then((res) => {
          this.loading = true;
          let typeList = [];
          let typeMap = new Map();
          const data = res.data;
          for (const e of data) {
            let img = {
              url: $fysp.imgUrl + e.extension1 + e.guid + '.jpg',
              data: e
            };
            const businesstype = e.businesstype;
            const businesstypeid = e.businesstypeid;
            if (
              typeList.find((item) => item.typeId == businesstypeid) !=
              undefined
            ) {
              typeMap.get(businesstypeid).push(img);
            } else {
              typeList.push({
                typeId: businesstypeid,
                typeName: businesstype
              });
              typeMap.set(businesstypeid, [img]);
            }
          }
        }
          this.typesList = typeList;
          this.typesMap = typeMap;
        })
        .finally(() => (this.loading = false));
    },
    // 图片右键点击事件
    showContextMenu(event, typeId, index) {
      this.showMenu = true;
      this.menuStyle = {
        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];
    },
    closeContextMenu() {
      this.showMenu = false;
    },
    handleMenuItem(item) {
      switch (item.action) {
        case 'copy':
          this.drawImageToCanvas();
          break;
        case 'move':
          this.selectedFile.data.businesstypeid = item.value;
          this.selectedFile.data.businesstype = item.label;
          this.changeMediaFileType(this.selectedFile);
          break;
        default:
          break;
      }
      this.closeContextMenu();
    },
    changeMediaFileType() {
      this.selectedFile.loading = true;
      const file = this.selectedFile.data;
      return mediafileApi
        .updateMediaFile(file)
        .then((res) => {
          if (res == 1) {
            const m = this.typesMap
              .get(this.selectedTypeId)
              .splice(this.selectedIndex, 1);
            if (!this.typesMap.has(file.businesstypeid)) {
              this.typesList.push({
                typeId: file.businesstypeid,
                typeName: file.businesstype
              });
              this.typesMap.set(file.businesstypeid, m);
            } else {
              this.typesMap.get(file.businesstypeid).push(m[0]);
            }
          }
        })
        .finally(() => (this.selectedFile.loading = false));
        this.typesList = typeList;
        this.typesMap = typeMap;
      });
      // setTimeout(() => {
      //   const m = this.typesMap
      //     .get(this.selectedTypeId)
      //     .splice(this.selectedIndex, 1);
      //   if (!this.typesMap.has(file.businesstypeid)) {
      //     this.typesList.push({
      //       typeId: file.businesstypeid,
      //       typeName: file.businesstype
      //     });
      //     this.typesMap.set(file.businesstypeid, m);
      //   } else {
      //     this.typesMap.get(file.businesstypeid).push(m[0]);
      //   }
      //   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));
    }
  }
};
</script>
<style scoped></style>
<style scoped>
.container {
  /* background-color: rgba(19, 211, 67, 0.514); */
  position: fixed;
  left: 0;
  top: 0;
  height: 100vh;
  width: 100vw;
  z-index: 10000;
}
.context-menu {
  position: fixed;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  min-width: 200px;
  z-index: 10001;
}
.menu-item {
  padding: 8px 16px;
  cursor: pointer;
  transition: background 0.2s;
}
.menu-item:hover {
  background-color: #f0f0f0;
}
</style>