From 4b1304917b0b16b09dd50191fab59d96933c0cf3 Mon Sep 17 00:00:00 2001
From: 曹睿 <360930172@qq.com>
Date: 星期二, 17 六月 2025 17:31:11 +0800
Subject: [PATCH] feat: 6月15日任务完90%

---
 src/components/ImageUpload/index.vue |  168 ++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 109 insertions(+), 59 deletions(-)

diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue
index adc0428..9670c72 100644
--- a/src/components/ImageUpload/index.vue
+++ b/src/components/ImageUpload/index.vue
@@ -6,11 +6,12 @@
       list-type="picture-card"
       :on-success="handleUploadSuccess"
       :before-upload="handleBeforeUpload"
+      :data="data"
       :limit="limit"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
-      name="file"
-      :on-remove="handleRemove"
+      ref="imageUpload"
+      :before-remove="handleDelete"
       :show-file-list="true"
       :headers="headers"
       :file-list="fileList"
@@ -47,9 +48,20 @@
 
 <script setup>
 import { getToken } from "@/utils/auth";
+import { isExternal } from "@/utils/validate";
+import Sortable from "sortablejs";
 
 const props = defineProps({
   modelValue: [String, Object, Array],
+  // 涓婁紶鎺ュ彛鍦板潃
+  action: {
+    type: String,
+    default: "/common/upload",
+  },
+  // 涓婁紶鎼哄甫鐨勫弬鏁�
+  data: {
+    type: Object,
+  },
   // 鍥剧墖鏁伴噺闄愬埗
   limit: {
     type: Number,
@@ -68,7 +80,12 @@
   // 鏄惁鏄剧ず鎻愮ず
   isShowTip: {
     type: Boolean,
-    default: true
+    default: true,
+  },
+  // 鎷栧姩鎺掑簭
+  drag: {
+    type: Boolean,
+    default: true,
   },
 });
 
@@ -79,54 +96,37 @@
 const dialogImageUrl = ref("");
 const dialogVisible = ref(false);
 const baseUrl = import.meta.env.VITE_APP_BASE_API;
-const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + props.action); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
 const headers = ref({ Authorization: "Bearer " + getToken() });
 const fileList = ref([]);
 const showTip = computed(
   () => props.isShowTip && (props.fileType || props.fileSize)
 );
 
-watch(() => props.modelValue, val => {
-  if (val) {
-    // 棣栧厛灏嗗�艰浆涓烘暟缁�
-    const list = Array.isArray(val) ? val : props.modelValue.split(",");
-    // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
-    fileList.value = list.map(item => {
-      if (typeof item === "string") {
-        if (item.indexOf(baseUrl) === -1) {
-          item = { name: baseUrl + item, url: baseUrl + item };
-        } else {
-          item = { name: item, url: item };
+watch(
+  () => props.modelValue,
+  (val) => {
+    if (val) {
+      // 棣栧厛灏嗗�艰浆涓烘暟缁�
+      const list = Array.isArray(val) ? val : props.modelValue.split(",");
+      // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁�
+      fileList.value = list.map((item) => {
+        if (typeof item === "string") {
+          if (item.indexOf(baseUrl) === -1 && !isExternal(item)) {
+            item = { name: baseUrl + item, url: baseUrl + item };
+          } else {
+            item = { name: item, url: item };
+          }
         }
-      }
-      return item;
-    });
-  } else {
-    fileList.value = [];
-    return [];
-  }
-});
-
-// 鍒犻櫎鍥剧墖
-function handleRemove(file, files) {
-  const findex = fileList.value.map(f => f.name).indexOf(file.name);
-  if (findex > -1) {
-    fileList.value.splice(findex, 1);
-    emit("update:modelValue", listToString(fileList.value));
-  }
-}
-
-// 涓婁紶鎴愬姛鍥炶皟
-function handleUploadSuccess(res) {
-  uploadList.value.push({ name: res.fileName, url: res.fileName });
-  if (uploadList.value.length === number.value) {
-    fileList.value = fileList.value.concat(uploadList.value);
-    uploadList.value = [];
-    number.value = 0;
-    emit("update:modelValue", listToString(fileList.value));
-    proxy.$modal.closeLoading();
-  }
-}
+        return item;
+      });
+    } else {
+      fileList.value = [];
+      return [];
+    }
+  },
+  { deep: true, immediate: true }
+);
 
 // 涓婁紶鍓峫oading鍔犺浇
 function handleBeforeUpload(file) {
@@ -136,7 +136,7 @@
     if (file.name.lastIndexOf(".") > -1) {
       fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
     }
-    isImg = props.fileType.some(type => {
+    isImg = props.fileType.some((type) => {
       if (file.type.indexOf(type) > -1) return true;
       if (fileExtension && fileExtension.indexOf(type) > -1) return true;
       return false;
@@ -146,8 +146,12 @@
   }
   if (!isImg) {
     proxy.$modal.msgError(
-      `鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${props.fileType.join("/")}鍥剧墖鏍煎紡鏂囦欢!`
+      `鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�${props.fileType.join("/")}鍥剧墖鏍煎紡鏂囦欢!`
     );
+    return false;
+  }
+  if (file.name.includes(",")) {
+    proxy.$modal.msgError("鏂囦欢鍚嶄笉姝g‘锛屼笉鑳藉寘鍚嫳鏂囬�楀彿!");
     return false;
   }
   if (props.fileSize) {
@@ -157,7 +161,7 @@
       return false;
     }
   }
-  proxy.$modal.loading("涓婁紶涓�");
+  proxy.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��...");
   number.value++;
 }
 
@@ -166,9 +170,46 @@
   proxy.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${props.limit} 涓�!`);
 }
 
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file) {
+  if (res.code === 200) {
+    uploadList.value.push({ name: res.fileName, url: res.fileName });
+    uploadedSuccessfully();
+  } else {
+    number.value--;
+    proxy.$modal.closeLoading();
+    proxy.$modal.msgError(res.msg);
+    proxy.$refs.imageUpload.handleRemove(file);
+    uploadedSuccessfully();
+  }
+}
+
+// 鍒犻櫎鍥剧墖
+function handleDelete(file) {
+  const findex = fileList.value.map((f) => f.name).indexOf(file.name);
+  if (findex > -1 && uploadList.value.length === number.value) {
+    fileList.value.splice(findex, 1);
+    emit("update:modelValue", listToString(fileList.value));
+    return false;
+  }
+}
+
+// 涓婁紶缁撴潫澶勭悊
+function uploadedSuccessfully() {
+  if (number.value > 0 && uploadList.value.length === number.value) {
+    fileList.value = fileList.value
+      .filter((f) => f.url !== undefined)
+      .concat(uploadList.value);
+    uploadList.value = [];
+    number.value = 0;
+    emit("update:modelValue", listToString(fileList.value));
+    proxy.$modal.closeLoading();
+  }
+}
+
 // 涓婁紶澶辫触
 function handleUploadError() {
-  proxy.$modal.msgError("涓婁紶澶辫触");
+  proxy.$modal.msgError("涓婁紶鍥剧墖澶辫触");
   proxy.$modal.closeLoading();
 }
 
@@ -183,10 +224,28 @@
   let strs = "";
   separator = separator || ",";
   for (let i in list) {
-    strs += list[i].url.replace(baseUrl, "") + separator;
+    if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {
+      strs += list[i].url.replace(baseUrl, "") + separator;
+    }
   }
   return strs != "" ? strs.substr(0, strs.length - 1) : "";
 }
+
+// 鍒濆鍖栨嫋鎷芥帓搴�
+onMounted(() => {
+  if (props.drag) {
+    nextTick(() => {
+      const element = document.querySelector(".el-upload-list");
+      Sortable.create(element, {
+        onEnd: (evt) => {
+          const movedItem = fileList.value.splice(evt.oldIndex, 1)[0];
+          fileList.value.splice(evt.newIndex, 0, movedItem);
+          emit("update:modelValue", listToString(fileList.value));
+        },
+      });
+    });
+  }
+});
 </script>
 
 <style scoped lang="scss">
@@ -194,13 +253,4 @@
 :deep(.hide .el-upload--picture-card) {
   display: none;
 }
-// 鍘绘帀鍔ㄧ敾鏁堟灉
-:deep(.el-list-enter-active),
-:deep(.el-list-leave-active) {
-  transition: all 0s;
-}
-:deep(.el-list-enter, .el-list-leave-active) {
-  opacity: 0;
-  transform: translateY(0);
-}
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.9.3