From 0796eebe3520fafb0ac5d36ee584af81506d7e9c Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期六, 20 九月 2025 14:05:52 +0800
Subject: [PATCH] 2025.9.20 数据产品(待完成)

---
 src/components/FYImageSelectDialog.vue |  144 ++++++++++++++++++++++++++++--------------------
 1 files changed, 84 insertions(+), 60 deletions(-)

diff --git a/src/components/FYImageSelectDialog.vue b/src/components/FYImageSelectDialog.vue
index 279ddca..c35bc94 100644
--- a/src/components/FYImageSelectDialog.vue
+++ b/src/components/FYImageSelectDialog.vue
@@ -1,14 +1,27 @@
 <template>
   <el-dialog
-    :title="title"
     :model-value="dialogVisible"
-    @opened="$emit('update:dialogVisible', true)"
-    @closed="$emit('update:dialogVisible', false)"
-    width="66%"
+    @opened="handleOpen"
+    @closed="handleClose"
+    top="5vh"
+    width="68%"
     destroy-on-close
+    :close-on-press-escape="false"
   >
-    <div class="main" v-loading="loading">
-      <el-row justify="end" v-if="!readonly">
+    <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
         >
@@ -22,10 +35,17 @@
         <el-button size="small" type="primary" @click="handleCancel"
           >鍙栨秷</el-button
         >
-      </el-row>
+      </div>
+    </el-row>
 
-      <div class="center">
-        <el-tabs v-if="typeList.length > 0" v-model="activeId" type="card">
+    <div class="center">
+      <el-scrollbar class="scrollbar-flex-content">
+        <el-tabs
+          v-if="typeList.length > 0"
+          v-model="activeId"
+          type="card"
+          stretch
+        >
           <el-tab-pane
             v-for="item in typeList"
             :key="item.typeId"
@@ -36,34 +56,41 @@
           >
           </el-tab-pane>
         </el-tabs>
-        <el-scrollbar
+      </el-scrollbar>
+      <el-scrollbar height="70vh">
+        <div
           v-if="typeImgMap.get(activeId) && typeImgMap.get(activeId).length > 0"
           class="imgs"
         >
           <el-image
+            v-loading="img.loading"
             v-for="(img, i) in typeImgMap.get(activeId)"
             :key="i"
             :class="[img.isSelect ? 'selected' : 'noActive', 'image']"
             fit="cover"
             :src="img.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"
-            @error="onOneImgLoadError"
+            @load="onOneImgLoadSuccess(img)"
+            @error="onOneImgLoadError(img)"
           />
-        </el-scrollbar>
+        </div>
         <el-row v-else justify="space-between">
           <el-empty description="鏆傛棤璁板綍" />
         </el-row>
-      </div>
+      </el-scrollbar>
     </div>
   </el-dialog>
 </template>
 <script setup>
-import { ref, watch, computed } from 'vue';
+import { ref, watch, computed, onMounted, onUnmounted } from 'vue';
 
 const props = defineProps({
-  // 鏍囬
-  title: String,
   dialogVisible: Boolean,
   /**
    * 鍥剧墖鍒嗙被
@@ -82,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);
 // 鍔犺浇鐘舵��
@@ -111,10 +144,12 @@
     loadedImgCount.value
   );
 });
-function onOneImgLoadError(e) {
+function onOneImgLoadError(img) {
+  img.loading = false;
   loadedImgCount.value++;
 }
-function onOneImgLoadSuccess(e) {
+function onOneImgLoadSuccess(img) {
+  img.loading = false;
   loadedImgCount.value++;
 }
 watch(
@@ -151,7 +186,14 @@
     img.isSelect = false;
   }
 }
-
+function handleOpen() {
+  emit('update:dialogVisible', true);
+}
+function handleClose() {
+  selectedImgUrlList.value.forEach((item) => (item.isSelect = false));
+  selectedImgUrlList.value = [];
+  emit('update:dialogVisible', false);
+}
 function handleSubmit() {
   emit('submit', selectedImgUrlList.value);
   emit('update:dialogVisible', false);
@@ -160,6 +202,14 @@
 function handleCancel() {
   emit('cancel');
   emit('update:dialogVisible', false);
+}
+
+// 鍥剧墖鍙抽敭鐐瑰嚮浜嬩欢
+function showContextMenu(event, index) {
+  if (props.onContextMenu && useContextMenu.value) {
+    event.preventDefault();
+    props.onContextMenu(event, activeId.value, index);
+  }
 }
 
 watch(
@@ -171,29 +221,12 @@
   },
   { 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);
-        }
-      });
-    });
-  },
-  { deep: true, immediate: true }
-);
 </script>
 <style scoped>
+.scrollbar-flex-content {
+  display: flex;
+  width: 100%;
+}
 .center {
   display: flex;
   flex-direction: column;
@@ -204,15 +237,13 @@
 }
 
 .main {
-  margin: 0 auto; /* 浣跨埗鍏冪礌灞呬腑 */
-  height: 72vh;
-  width: 100%;
+  /* 浣跨埗鍏冪礌灞呬腑 */
+  /* margin: 0 auto;  */
+  /* width: 100%; */
 }
 
 .imgs {
-  height: 60vh;
   width: 100%;
-  min-height: 100px !important;
   /* border-style:solid;
     border-radius: 1px; */
   /* height: 100%; */
@@ -226,16 +257,9 @@
 
 .image {
   margin: 5px;
-  height: 210px;
-  width: 200px;
+  height: 250px;
+  width: 240px;
   border-radius: 4px;
-}
-
-.active {
-  padding: 5px;
-  width: 20%;
-  height: 200px;
-  border: 0.5rem outset rgb(52, 155, 4);
 }
 
 .selected {

--
Gitblit v1.9.3