| ... | ... | @@ -7,18 +7,21 @@ | 
| 7 | 7 | import { Upload, Spin } from 'ant-design-vue'; | 
| 8 | 8 | import { InboxOutlined } from '@ant-design/icons-vue'; | 
| 9 | 9 | import { useMessage } from '/@/hooks/web/useMessage'; | 
| 10 |  | -  import { isBoolean, isFunction } from '/@/utils/is'; | 
| 11 |  | -  import { computed, ref, unref } from 'vue'; | 
|  | 10 | +  import { computed, ref, unref, useAttrs } from 'vue'; | 
| 12 | 11 | import { cloneDeep } from 'lodash-es'; | 
| 13 |  | -  interface FileItem { | 
|  | 12 | +  import { isFunction, isObject } from '/@/utils/is'; | 
|  | 13 | + | 
|  | 14 | +  export interface FileItem { | 
| 14 | 15 | uid: string; | 
| 15 |  | -    name?: string; | 
|  | 16 | +    name: string; | 
| 16 | 17 | status?: string; | 
| 17 | 18 | response?: string; | 
| 18 | 19 | url?: string; | 
| 19 | 20 | } | 
| 20 | 21 |  | 
| 21 |  | -  const emit = defineEmits(['update:fileList']); | 
|  | 22 | +  const emit = defineEmits(['update:fileList', 'preview', 'download']); | 
|  | 23 | + | 
|  | 24 | +  const attrs = useAttrs(); | 
| 22 | 25 |  | 
| 23 | 26 | const { createMessage } = useMessage(); | 
| 24 | 27 |  | 
| ... | ... | @@ -26,8 +29,9 @@ | 
| 26 | 29 |  | 
| 27 | 30 | const componentDisabled = ref(false); | 
| 28 | 31 |  | 
| 29 |  | -  const setLoading = (spin: boolean) => { | 
| 30 |  | -    loading.value = spin; | 
|  | 32 | +  const setUploadStatus = (status: boolean) => { | 
|  | 33 | +    loading.value = status; | 
|  | 34 | +    componentDisabled.value = status; | 
| 31 | 35 | }; | 
| 32 | 36 |  | 
| 33 | 37 | const props = withDefaults( | 
| ... | ... | @@ -60,28 +64,28 @@ | 
| 60 | 64 |  | 
| 61 | 65 | const getDisabled = computed(() => { | 
| 62 | 66 | const { disabled } = props; | 
| 63 |  | -    if (isBoolean(disabled)) { | 
| 64 |  | -      return disabled ? componentDisabled.value : disabled; | 
| 65 |  | -    } | 
| 66 |  | -    return componentDisabled.value; | 
|  | 67 | +    return disabled ? disabled : unref(componentDisabled); | 
| 67 | 68 | }); | 
| 68 | 69 |  | 
| 69 | 70 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { | 
| 70 | 71 | try { | 
| 71 |  | -      setLoading(true); | 
| 72 |  | -      componentDisabled.value = true; | 
| 73 |  | -      console.log({ componentDisabled: unref(componentDisabled), getDisabled: unref(getDisabled) }); | 
|  | 72 | +      setUploadStatus(true); | 
| 74 | 73 | const { transformFile, api } = props; | 
| 75 | 74 | if (transformFile && isFunction(transformFile)) file = await transformFile(file as File); | 
| 76 | 75 | if (api && isFunction(api)) { | 
| 77 | 76 | const data = await api(file); | 
| 78 |  | -        emit('update:fileList', cloneDeep([...props.fileList, data])); | 
|  | 77 | +        if (isObject(data) && Reflect.has(data, 'uid') && Reflect.has(data, 'name')) { | 
|  | 78 | +          emit('update:fileList', cloneDeep([...props.fileList, data])); | 
|  | 79 | +          return; | 
|  | 80 | +        } | 
|  | 81 | +        window.console.error( | 
|  | 82 | +          `The ApiUpload component's api properties need to return an object, that object requires a uid field and a name field` | 
|  | 83 | +        ); | 
| 79 | 84 | } | 
| 80 | 85 | } catch (error) { | 
| 81 | 86 | window.console.error(error); | 
| 82 | 87 | } finally { | 
| 83 |  | -      setLoading(false); | 
| 84 |  | -      componentDisabled.value = false; | 
|  | 88 | +      setUploadStatus(false); | 
| 85 | 89 | } | 
| 86 | 90 | }; | 
| 87 | 91 |  | 
| ... | ... | @@ -92,17 +96,34 @@ | 
| 92 | 96 | emit('update:fileList', _fileList); | 
| 93 | 97 | }; | 
| 94 | 98 |  | 
|  | 99 | +  const defaultPreview = (file: FileItem) => { | 
|  | 100 | +    console.log('default preview', file); | 
|  | 101 | +  }; | 
|  | 102 | + | 
|  | 103 | +  const defaultDownload = (file: FileItem) => { | 
|  | 104 | +    console.log('default download', file); | 
|  | 105 | +  }; | 
|  | 106 | + | 
| 95 | 107 | const handlePreview = (file: FileItem) => { | 
| 96 |  | -    console.log('preview', file); | 
|  | 108 | +    if (Reflect.has(attrs, 'preview')) { | 
|  | 109 | +      emit('preview', file); | 
|  | 110 | +      return; | 
|  | 111 | +    } | 
|  | 112 | +    defaultPreview(file); | 
| 97 | 113 | }; | 
| 98 | 114 |  | 
| 99 | 115 | const handleDownload = (file: FileItem) => { | 
| 100 |  | -    console.log('download', file); | 
|  | 116 | +    if (Reflect.has(attrs, 'download')) { | 
|  | 117 | +      emit('download', file); | 
|  | 118 | +      return; | 
|  | 119 | +    } | 
|  | 120 | +    defaultDownload(file); | 
| 101 | 121 | }; | 
| 102 | 122 | </script> | 
| 103 | 123 |  | 
| 104 | 124 | <template> | 
| 105 | 125 | <Upload.Dragger | 
|  | 126 | +    class="block" | 
| 106 | 127 | :file-list="props.fileList" | 
| 107 | 128 | :disabled="getDisabled" | 
| 108 | 129 | :before-upload="handleBeforeUpload" | 
| ... | ... | @@ -111,7 +132,6 @@ | 
| 111 | 132 | :remove="handleRemove" | 
| 112 | 133 | > | 
| 113 | 134 | <Spin :spinning="loading"> | 
| 114 |  | -      {{ getDisabled }} | 
| 115 | 135 | <div class="w-full h-full flex flex-col justify-center content-center"> | 
| 116 | 136 | <InboxOutlined class="text-[3rem] !text-blue-500" /> | 
| 117 | 137 | <div class="m-2 text-gray-400">点击上传或拖拽上传</div> | 
| ... | ... | @@ -119,3 +139,5 @@ | 
| 119 | 139 | </Spin> | 
| 120 | 140 | </Upload.Dragger> | 
| 121 | 141 | </template> | 
|  | 142 | + | 
|  | 143 | +<style></style> | 
... | ... |  |