Riku
2025-09-20 32eedf2857255cf29985ffc0cc73e75eccda39bf
src/components/FYImageSelectDialog.vue
@@ -8,35 +8,55 @@
    destroy-on-close
    :close-on-press-escape="false"
  >
    <!-- <div class="main"> -->
    <el-row justify="end" v-if="!readonly">
      <el-text size="small" type="info" class="m-r-8"
        >最多选择{{ maxSelect }}张图片</el-text
      >
      <el-button
        size="small"
        type="primary"
        @click="handleSubmit"
        :disabled="selectedImgUrlList.length == 0"
        >确定</el-button
      >
      <el-button size="small" type="primary" @click="handleCancel"
        >取消</el-button
      >
    <el-row justify="end">
      <el-space v-if="onContextMenu != undefined">
        <el-switch
          v-model="useContextMenu"
          inline-prompt
          active-text="开"
          inactive-text="关"
        />
        <el-text size="small" type="info">
          {{ `(${contextMenuStr})` }}
        </el-text>
      </el-space>
      <div v-if="!readonly">
        <el-text size="small" type="info" class="m-r-8"
          >最多选择{{ maxSelect }}张图片</el-text
        >
        <el-button
          size="small"
          type="primary"
          @click="handleSubmit"
          :disabled="selectedImgUrlList.length == 0"
          >确定</el-button
        >
        <el-button size="small" type="primary" @click="handleCancel"
          >取消</el-button
        >
      </div>
    </el-row>
    <div class="center">
      <el-tabs v-if="typeList.length > 0" v-model="activeId" type="card">
        <el-tab-pane
          v-for="item in typeList"
          :key="item.typeId"
          :label="
            item.typeName + ' (' + typeImgMap.get(item.typeId).length + ')'
          "
          :name="item.typeId"
      <el-scrollbar class="scrollbar-flex-content">
        <el-tabs
          v-if="typeList.length > 0"
          v-model="activeId"
          type="card"
          stretch
        >
        </el-tab-pane>
      </el-tabs>
          <el-tab-pane
            v-for="item in typeList"
            :key="item.typeId"
            :label="
              item.typeName + ' (' + typeImgMap.get(item.typeId).length + ')'
            "
            :name="item.typeId"
          >
          </el-tab-pane>
        </el-tabs>
      </el-scrollbar>
      <el-scrollbar height="70vh">
        <div
          v-if="typeImgMap.get(activeId) && typeImgMap.get(activeId).length > 0"
@@ -49,8 +69,12 @@
            :class="[img.isSelect ? 'selected' : 'noActive', 'image']"
            fit="cover"
            :src="img.url"
            :preview-src-list="readonly ? typeImgMap.get(activeId).map((v) => v.url) : []"
            :preview-src-list="
              readonly ? typeImgMap.get(activeId).map((v) => v.url) : []
            "
            crossOrigin="Anonymous"
            :initial-index="i"
            @contextmenu="(e) => showContextMenu(e, i)"
            @click="onSelect(img, i)"
            @load="onOneImgLoadSuccess(img)"
            @error="onOneImgLoadError(img)"
@@ -61,7 +85,6 @@
        </el-row>
      </el-scrollbar>
    </div>
    <!-- </div> -->
  </el-dialog>
</template>
<script setup>
@@ -86,22 +109,28 @@
    type: Boolean,
    default: false
  },
  defaultFile: {
    type: Array,
    default: () => []
  },
  // 图片可选数量,当传入数字时,代表图片数量
  maxSelect: {
    type: Number,
    default: 3
  },
  // 图片右键点击事件
  onContextMenu: {
    type: Function
  },
  contextMenuStr: {
    type: String,
    default: '右键点击图片移动'
  }
});
const emit = defineEmits(['submit', 'cancel', 'update:dialogVisible']);
const activeId = ref('');
// const typeImgMap = ref(new Map());
const selectedImgUrlList = ref([]);
const useContextMenu = ref(false);
let loadedImgCount = ref(0);
// 加载状态
@@ -158,20 +187,6 @@
  }
}
function handleOpen() {
  // if (props.typeImgMap.get(activeId.value) == undefined) {
  //     return;
  //   }
  //   props.typeImgMap.get(activeId.value).forEach((i) => {
  //     if (i.isSelect == true) {
  //       return;
  //     }
  //     props.defaultFile.forEach((imgItem) => {
  //       if (imgItem.url == i.url) {
  //         i.isSelect = true;
  //         selectedImgUrlList.value.push(i);
  //       }
  //     });
  //   });
  emit('update:dialogVisible', true);
}
function handleClose() {
@@ -189,6 +204,14 @@
  emit('update:dialogVisible', false);
}
// 图片右键点击事件
function showContextMenu(event, index) {
  if (props.onContextMenu && useContextMenu.value) {
    event.preventDefault();
    props.onContextMenu(event, activeId.value, index);
  }
}
watch(
  () => props.typeList,
  (nV, oV) => {
@@ -198,49 +221,12 @@
  },
  { immediate: true }
);
// watch(
//   () => props.defaultFile,
//   (nV, oV) => {
//     if (props.typeImgMap.get(activeId.value) == undefined) {
//       return;
//     }
//     props.typeImgMap.get(activeId.value).forEach((i) => {
//       if (i.isSelect == true) {
//         return;
//       }
//       nV.forEach((imgItem) => {
//         if (imgItem.url == i.url) {
//           i.isSelect = true;
//           selectedImgUrlList.value.push(i);
//         }
//       });
//     });
//   },
//   { deep: true, immediate: true }
// );
// watch(
//   () => props.typeImgMap,
//   (newMap, oldMap) => {
//     if (newMap.get(activeId.value) == undefined) {
//       return;
//     }
//     newMap.get(activeId.value).forEach((i) => {
//       if (i.isSelect == true) {
//         return;
//       }
//       props.defaultFile.forEach((imgItem) => {
//         if (imgItem.url == i.url) {
//           i.isSelect = true;
//           selectedImgUrlList.value.push(i);
//         }
//       });
//     });
//   },
//   { immediate: true }
// );
</script>
<style scoped>
.scrollbar-flex-content {
  display: flex;
  width: 100%;
}
.center {
  display: flex;
  flex-direction: column;