Просмотр исходного кода

feat: 添加上传前文件重名检查功能,支持用户确认继续上传

xieyong 16 часов назад
Родитель
Сommit
f3e636e5bc

+ 83 - 35
src/components/upload/fileUpload1.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="upload-file">
     <el-upload
+      ref="upload"
       class="upload-demo"
       action="#"
       :disabled="disabled || loading"
@@ -39,10 +40,7 @@
         class="progress-item"
       >
         <div class="file-name">{{ fileNameMap[fileId] }}</div>
-        <el-progress
-          :percentage="progress"
-          :stroke-width="6"
-        ></el-progress>
+        <el-progress :percentage="progress" :stroke-width="6"></el-progress>
       </div>
     </div>
   </div>
@@ -89,6 +87,11 @@
       disabled: {
         default: false,
         type: Boolean
+      },
+      // 上传前拦截钩子:返回 false 取消上传;返回 Promise<boolean> 异步判断(resolve(false) 取消)
+      beforeUploadFile: {
+        type: Function,
+        default: null
       }
     },
     data() {
@@ -221,46 +224,91 @@
 
         if (this.limit > 0 && this.fileList.length === this.limit) {
           this.$message.error(`最多上传 ${this.limit}个文件`);
+          this._removeCanceledFile(file);
           return false;
         }
+        // 父组件可在上传前异步拦截(如查重)
+        if (this.beforeUploadFile) {
+          const result = this.beforeUploadFile(file);
+          if (result === false) {
+            this._removeCanceledFile(file);
+            return false;
+          }
+          if (result && typeof result.then === 'function') {
+            return result.then((allowed) => {
+              if (allowed === false) {
+                this._removeCanceledFile(file);
+                return false;
+              }
+              return this._doUpload(file);
+            });
+          }
+        }
+        return this._doUpload(file);
+      },
+      // 取消上传时清理进度条;file-list 由 el-upload 自己从内部 uploadFiles 移除
+      _removeCanceledFile(file) {
+        const fileId = file.uid;
+        if (
+          fileId !== undefined &&
+          this.fileProgressMap[fileId] !== undefined
+        ) {
+          this.$delete(this.fileProgressMap, fileId);
+          this.$delete(this.fileNameMap, fileId);
+          if (Object.keys(this.fileProgressMap).length === 0) {
+            this.loading = false;
+          }
+        }
+        // el-upload 的 handleStart 在 beforeUpload 之前就把文件塞进 uploadFiles,
+        // 即便 beforeUpload 返回 false 也不会自动清掉;这里手动清掉,否则 display 还会显示
+        const upload = this.$refs.upload;
+        if (upload && Array.isArray(upload.uploadFiles)) {
+          const idx = upload.uploadFiles.findIndex((f) => f.uid === fileId);
+          if (idx !== -1) {
+            upload.uploadFiles.splice(idx, 1);
+          }
+        }
+      },
+      async _doUpload(file) {
         const fileId = file.uid || Date.now();
         this.loading = true;
         this.$set(this.fileProgressMap, fileId, 0);
         this.$set(this.fileNameMap, fileId, file.name);
-        return uploadFileNew(
-          {
-            module: this.module,
-            multiPartFile: file
-          },
-          {
-            onUploadProgress: (progressEvent) => {
-              if (progressEvent.total) {
-                this.$set(
-                  this.fileProgressMap,
-                  fileId,
-                  Math.round((progressEvent.loaded * 100) / progressEvent.total)
-                );
+        try {
+          const res = await uploadFileNew(
+            {
+              module: this.module,
+              multiPartFile: file
+            },
+            {
+              onUploadProgress: (progressEvent) => {
+                if (progressEvent.total) {
+                  this.$set(
+                    this.fileProgressMap,
+                    fileId,
+                    Math.round(
+                      (progressEvent.loaded * 100) / progressEvent.total
+                    )
+                  );
+                }
               }
             }
+          );
+          if (res.data) {
+            this.$emit('input', [
+              ...(this.value || []),
+              { ...file, url: res.data.storePath, ...res.data }
+            ]);
           }
-        )
-          .then((res) => {
-            if (res.data) {
-              this.$emit('input', [
-                ...(this.value || []),
-                { ...file, url: res.data.storePath, ...res.data }
-              ]);
-            }
-            this.$emit('fileChange', res.data);
-            return res.data;
-          })
-          .finally(() => {
-            this.$delete(this.fileProgressMap, fileId);
-            this.$delete(this.fileNameMap, fileId);
-            if (Object.keys(this.fileProgressMap).length === 0) {
-              this.loading = false;
-            }
-          });
+          this.$emit('fileChange', res.data);
+          return res.data;
+        } finally {
+          this.$delete(this.fileProgressMap, fileId);
+          this.$delete(this.fileNameMap, fileId);
+          if (Object.keys(this.fileProgressMap).length === 0) {
+            this.loading = false;
+          }
+        }
       },
       handlRequest() {
         return Promise.resolve();

+ 31 - 1
src/views/doc/components/file-edit.vue

@@ -47,6 +47,7 @@
                 v-model="form.storagePath"
                 module="main"
                 :limit="1"
+                :beforeUploadFile="checkNameBeforeUpload"
                 @fileChange="fileChange"
               >
                 <template slot="templateBtn">
@@ -148,7 +149,8 @@
     fileUpdateAPI,
     fileGetByIdAPI,
     fileVersion,
-    listCode
+    listCode,
+    checkNameExistsAPI
   } from '@/api/doc-manage';
   import FileUpload from '@/components/upload/fileUpload1.vue';
   import { setFolderList } from '../util.js';
@@ -252,6 +254,34 @@
         console.log(file, 'file');
         this.form.name = file.name.replace(/\.[^/.]+$/, '');
       },
+      // 上传前查重:返回 false 取消上传;返回 Promise<boolean> 异步判断
+      async checkNameBeforeUpload(file) {
+        try {
+          const nameWithoutExt = file.name.replace(/\.[^/.]+$/, '');
+          const duplicates = await checkNameExistsAPI([nameWithoutExt]);
+          console.log(duplicates, 'duplicates1');
+          if (!duplicates || duplicates.length === 0) {
+            return true;
+          }
+          try {
+            await this.$confirm(
+              `以下文件名称已存在:${duplicates.join('、')},是否继续上传?`,
+              '重名提示',
+              {
+                type: 'warning',
+                confirmButtonText: '继续上传',
+                cancelButtonText: '取消上传'
+              }
+            );
+            return true;
+          } catch {
+            return false;
+          }
+        } catch (e) {
+          // 查重接口异常 → 放行
+          return true;
+        }
+      },
       cascaderChange() {
         this.getCode();
       },

+ 30 - 1
src/views/doc/components/file-editAll.vue

@@ -61,6 +61,7 @@
                 module="main"
                 :limit="100"
                 :multiple="true"
+                :beforeUploadFile="checkNameBeforeUpload"
                 @fileChange="fileChange"
               >
                 <!-- <template slot="templateBtn">
@@ -132,7 +133,7 @@
 </template>
 
 <script>
-  import { fileSaveAPI, listCode } from '@/api/doc-manage';
+  import { fileSaveAPI, listCode, checkNameExistsAPI } from '@/api/doc-manage';
   import FileUpload from '@/components/upload/fileUpload1.vue';
   import { setFolderList } from '../util.js';
   // import getCode from './getCode.vue';
@@ -258,6 +259,34 @@
         console.log(file, 'file');
         this.form.name = file.name.replace(/\.[^/.]+$/, '');
       },
+      // 上传前查重:返回 false 取消上传;返回 Promise<boolean> 异步判断
+      async checkNameBeforeUpload(file) {
+        try {
+          const nameWithoutExt = file.name.replace(/\.[^/.]+$/, '');
+          const duplicates = await checkNameExistsAPI([nameWithoutExt]);
+          console.log(duplicates, 'duplicates2');
+          if (!duplicates || duplicates.length === 0) {
+            return true; // 不重名,放行
+          }
+          try {
+            await this.$confirm(
+              `以下文件名称已存在:${duplicates.join('、')},是否继续上传?`,
+              '重名提示',
+              {
+                type: 'warning',
+                confirmButtonText: '继续上传',
+                cancelButtonText: '取消上传'
+              }
+            );
+            return true; // 用户确认,放行
+          } catch {
+            return false; // 用户取消,不上传
+          }
+        } catch (e) {
+          // 查重接口异常 → 放行,由后续 save 兜底
+          return true;
+        }
+      },
       // success(code) {
       //   this.code = code;
       //   this.$nextTick(() => {