| 
					
				 | 
			
			
				@@ -0,0 +1,244 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  <BasicModal 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    v-bind="$attrs" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @register="register" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @ok="handleOk" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :closeFunc="handleCloseFunc" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :maskClosable="false" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    width="800px" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    title="上传组件" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    wrapClassName="upload-modal" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :okButtonProps="{ disabled: isUploadingRef }" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    :cancelButtonProps="{ disabled: isUploadingRef }" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <template #centerdFooter> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <a-button @click="handleStartUpload" color="success" :loading="isUploadingRef"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        {{ isUploadingRef ? '上传中' : '开始上传' }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </a-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <Upload :accept="getStringAccept" :multiple="multiple" :before-upload="beforeUpload"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <a-button type="primary"> 选择文件 </a-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <span class="px-2">{{ getHelpText }}</span> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </Upload> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <BasicTable @register="registerTable" :dataSource="fileListRef" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  </BasicModal> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<script lang="ts"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { defineComponent, reactive, ref, toRef, unref } from 'vue'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { Upload } from 'ant-design-vue'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { BasicModal, useModalInner } from '/@/components/Modal'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { BasicTable, useTable } from '/@/components/Table'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // hooks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { useUploadType } from './useUpload'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { useMessage } from '/@/hooks/web/useMessage'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   types 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { FileItem, UploadResultStatus } from './types'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { basicProps } from './props'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { createTableColumns, createActionColumn } from './data'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // utils 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { checkFileType, checkImgType, getBase64WithFile } from './utils'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { buildUUID } from '/@/utils/uuid'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { createImgPreview } from '/@/components/Preview/index'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  import { uploadApi } from '/@/api/demo/upload'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  export default defineComponent({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    components: { BasicModal, Upload, BasicTable }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    props: basicProps, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    setup(props, { emit }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const [register, { closeModal }] = useModalInner(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const { getAccept, getStringAccept, getHelpText } = useUploadType({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        acceptRef: toRef(props, 'accept'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        helpTextRef: toRef(props, 'helpText'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        maxNumberRef: toRef(props, 'maxNumber'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        maxSizeRef: toRef(props, 'maxSize'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const fileListRef = ref<FileItem[]>([]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const state = reactive<{ fileList: FileItem[] }>({ fileList: [] }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const { createMessage } = useMessage(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 上传前校验 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      function beforeUpload(file: File) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const { size, name } = file; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const { maxSize } = props; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const accept = unref(getAccept); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 设置最大值,则判断 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (maxSize && file.size / 1024 / 1024 >= maxSize) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          createMessage.error(`只能上传不超过${maxSize}MB的文件!`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 设置类型,则判断 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (accept.length > 0 && !checkFileType(file, accept)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          createMessage.error!(`只能上传${accept.join(',')}格式文件`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 生成图片缩略图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (checkImgType(file)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // beforeUpload,如果异步会调用自带上传方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // file.thumbUrl = await getBase64(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          getBase64WithFile(file).then(({ result: thumbUrl }) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            fileListRef.value = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ...unref(fileListRef), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                uuid: buildUUID(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                file, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                thumbUrl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                percent: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                type: name.split('.').pop(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          fileListRef.value = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ...unref(fileListRef), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              uuid: buildUUID(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              file, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              percent: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              type: name.split('.').pop(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 删除 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      function handleRemove(record: FileItem) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        index !== -1 && fileListRef.value.splice(index, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 预览 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      function handlePreview(record: FileItem) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const { thumbUrl = '' } = record; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        createImgPreview({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          imageList: [thumbUrl], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const [registerTable] = useTable({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        columns: createTableColumns(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        actionColumn: createActionColumn(handleRemove, handlePreview), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pagination: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //   是否正在上传 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const isUploadingRef = ref(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      async function uploadApiByItem(item: FileItem) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.status = UploadResultStatus.UPLOADING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const { data } = await uploadApi( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              file: item.file, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            function onUploadProgress(progressEvent: ProgressEvent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              const complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              item.percent = complete; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.status = UploadResultStatus.SUCCESS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.responseData = data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            success: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            error: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          console.log(e); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          item.status = UploadResultStatus.ERROR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            success: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            error: e, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 点击开始上传 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      async function handleStartUpload() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          isUploadingRef.value = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const data = await Promise.all( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            unref(fileListRef).map((item) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              return uploadApiByItem(item); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          isUploadingRef.value = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // 生产环境:抛出错误 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const errorList = data.filter((item) => !item.success); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (errorList.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw errorList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          isUploadingRef.value = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          throw e; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //   点击保存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      function handleOk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // TODO: 没起作用:okButtonProps={{ disabled: state.isUploading }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isUploadingRef.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          createMessage.warning('请等待文件上传后,保存'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const fileList: string[] = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (const item of fileListRef.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const { status, responseData } = item; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (status === UploadResultStatus.SUCCESS && responseData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            fileList.push(responseData.url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 存在一个上传成功的即可保存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (fileList.length <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          createMessage.warning('没有上传成功的文件,无法保存'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        console.log(fileList); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        emit('change', fileList); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        fileListRef.value = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        closeModal(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 点击关闭:则所有操作不保存,包括上传的 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      function handleCloseFunc() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!isUploadingRef.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          fileListRef.value = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          createMessage.warning('请等待文件上传结束后操作'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        register, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        closeModal, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        getHelpText, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        getStringAccept, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        beforeUpload, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        registerTable, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        fileListRef, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        state, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        isUploadingRef, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handleStartUpload, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handleOk, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handleCloseFunc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<style lang="less"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   /deep/ .ant-upload-list { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //     display: none; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  .upload-modal { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    .ant-upload-list { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      display: none; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    .ant-table-wrapper .ant-spin-nested-loading { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      padding: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</style> 
			 |