{fileUploaders[0]?.status === UploadStatus.uploading && (
-
)}
{fileUploaders[0]?.status === UploadStatus.uploaded && (
-
-
-
- {i18nText.uploadSuccess}
-
+
+
+ {i18nText.uploadSuccess}
)}
{fileUploaders[0]?.status === UploadStatus.failed && (
-
-
-
- {i18nText.uploadFailed}
+
@@ -331,16 +304,16 @@ export default defineComponent({
{this.$slots.preloadFiles?.({
fileUploaders,
- deleteFile: onDeleteFile,
+ deleteFile: onDeleteFile
})}
{this.$slots.uploadedFiles?.({
uploadedFiles,
- deleteFile: deleteUploadedFile,
+ deleteFile: deleteUploadedFile
})}
)
- },
+ }
})
diff --git a/packages/devui-vue/devui/upload/src/upload-types.ts b/packages/devui-vue/devui/upload/src/upload-types.ts
index 1567766aa35c53c34003545ebc17f4299dac26e8..d9e564926da0cbbe0b40b0336de28d5215a19531 100644
--- a/packages/devui-vue/devui/upload/src/upload-types.ts
+++ b/packages/devui-vue/devui/upload/src/upload-types.ts
@@ -1,4 +1,5 @@
import type { PropType, ExtractPropTypes } from 'vue'
+import { FileUploader } from './file-uploader'
export class IUploadOptions {
// 上传接口地址
uri: string
@@ -30,7 +31,7 @@ export class IUploadOptions {
export class IFileOptions {
accept?: string
- multiple: boolean
+ multiple?: boolean
webkitdirectory: boolean
}
@@ -38,165 +39,95 @@ export enum UploadStatus {
preLoad = 0,
uploading,
uploaded,
- failed,
+ failed
}
type DynamicUploadOptionsFn = (files, uploadOptions) => IUploadOptions
type ChangeFn = (_: any) => void
-type BeforeUploadFn = (file: File) => boolean | Promise
+type BeforeUploadFn = (file: FileUploader) => boolean | Promise
export const uploadProps = {
+ // 规定能够通过文件上传进行提交的文件类型,例如 accept: '.xls,.xlsx,.pages,.mp3,.png'
+ accept: {
+ type: String
+ },
+ // 是否允许用户选择文件目录,而不是文件
+ webkitdirectory: {
+ type: Boolean,
+ default: false
+ },
uploadOptions: {
type: Object as PropType,
- required: true,
+ required: true
},
- fileOptions: {
- type: Object as PropType,
- required: true,
+ multiple: {
+ type: Boolean,
+ default: false
},
autoUpload: {
type: Boolean,
- default: false,
+ default: false
},
placeholderText: {
type: String,
- default: '选择文件',
+ default: '选择文件'
},
uploadText: {
type: String,
- default: '上传',
+ default: '上传'
},
uploadedFiles: {
type: Array as PropType,
- default: () => [],
+ default: () => []
},
withoutBtn: {
type: Boolean,
- default: false,
+ default: false
},
enableDrop: {
type: Boolean,
- default: false,
+ default: false
},
beforeUpload: {
- type: Function as PropType,
+ type: Function as PropType
},
+ /** @deprecated */
dynamicUploadOptionsFn: {
- type: Function as PropType,
+ type: Function as PropType
},
disabled: {
type: Boolean,
- default: false,
- },
- showTip: {
- type: Boolean,
- default: false,
+ default: false
},
onChange: {
- type: Function as PropType,
+ type: Function as PropType
},
fileDrop: {
type: Function as PropType<(v: any) => void>,
- default: undefined,
+ default: undefined
},
fileOver: {
type: Function as PropType<(v: boolean) => void>,
- default: undefined,
+ default: undefined
},
fileSelect: {
type: Function as PropType<(v: File) => void>,
- default: undefined,
- },
- errorEvent: {
- type: Function as PropType<(v: { file: File; response: any; }) => void>,
- default: undefined,
+ default: undefined
},
- successEvent: {
- type: Function as PropType<(v: { file: File; response: any; }[]) => void>,
- default: undefined,
- },
- deleteUploadedFileEvent: {
+ deleteUploadedFile: {
type: Function as PropType<(v: string) => void>,
- default: undefined,
- },
-} as const
-export type UploadProps = ExtractPropTypes
-
-export const multiUploadProps = {
- uploadOptions: {
- type: Object as PropType,
- required: true,
+ default: undefined
},
- fileOptions: {
- type: Object as PropType,
- required: true,
- },
- autoUpload: {
- type: Boolean,
- default: false,
- },
- withoutBtn: {
- type: Boolean,
- default: false,
- },
- showTip: {
- type: Boolean,
- default: false,
- },
- uploadedFiles: {
- type: Array as PropType,
- default: () => [],
- },
- enableDrop: {
- type: Boolean,
- default: false,
- },
- placeholderText: {
- type: String,
- default: '选择文件',
- },
- uploadText: {
- type: String,
- default: '上传',
- },
- oneTimeUpload: {
- type: Boolean,
- default: false,
- },
- disabled: {
- type: Boolean,
- default: false,
- },
- beforeUpload: {
- type: Function as PropType<(files: any) => boolean | Promise>,
- },
- fileDrop: {
- type: Function as PropType<(v: any) => void>,
- default: undefined,
- },
- fileOver: {
- type: Function as PropType<(v: boolean) => void>,
- default: undefined,
- },
- fileSelect: {
- type: Function as PropType<(v: File) => void>,
- default: undefined,
- },
- errorEvent: {
+ 'on-error': {
type: Function as PropType<(v: { file: File; response: any; }) => void>,
- default: undefined,
+ default: undefined
},
- successEvent: {
+ 'on-success': {
type: Function as PropType<(v: { file: File; response: any; }[]) => void>,
- default: undefined,
- },
- deleteUploadedFileEvent: {
- type: Function as PropType<(v: string) => void>,
- default: undefined,
+ default: undefined
},
- setCustomUploadOptions: {
- type: Function as PropType<
- (files: File[], uploadOptions: IUploadOptions) => IUploadOptions
- >,
- default: undefined,
- },
-}
+ oneTimeUpload: {
+ type: Boolean,
+ default: false
+ }
+} as const
+export type UploadProps = ExtractPropTypes
diff --git a/packages/devui-vue/devui/upload/src/multiple-upload.tsx b/packages/devui-vue/devui/upload/src/upload.tsx
similarity index 76%
rename from packages/devui-vue/devui/upload/src/multiple-upload.tsx
rename to packages/devui-vue/devui/upload/src/upload.tsx
index 0928fe4106b23878bb278236f0a9062e1de07173..8678147cf3bcfc23fd646598cca65756904adf7d 100644
--- a/packages/devui-vue/devui/upload/src/multiple-upload.tsx
+++ b/packages/devui-vue/devui/upload/src/upload.tsx
@@ -1,34 +1,24 @@
import { defineComponent, toRefs, ref } from 'vue'
import { ToastService } from '../../toast'
-import { UploadStatus, multiUploadProps } from './upload-types'
+import { UploadStatus, UploadProps, uploadProps } from './upload-types'
import { useSelectFiles } from './use-select-files'
import { useUpload } from './use-upload'
import {
getFailedFilesCount,
getSelectedFilesCount,
getUploadingFilesCount,
- i18nText,
- getExistSameNameFilesMsg,
+ getExistSameNameFilesMsg
} from './i18n-upload'
import { FileUploader } from './file-uploader'
import './upload.scss'
export default defineComponent({
- name: 'DMultipleUpload',
- props: multiUploadProps,
- emits: [
- 'fileDrop',
- 'fileOver',
- 'fileSelect',
- 'successEvent',
- 'errorEvent',
- 'deleteUploadedFileEvent',
- 'update:uploadedFiles',
- ],
- setup(props, ctx) {
+ name: 'DUpload',
+ props: uploadProps,
+ emits: ['fileDrop', 'fileOver', 'fileSelect', 'deleteUploadedFile', 'update:uploadedFiles'],
+ setup(props: UploadProps, ctx) {
const {
uploadOptions,
- fileOptions,
placeholderText,
autoUpload,
withoutBtn,
@@ -37,17 +27,14 @@ export default defineComponent({
beforeUpload,
enableDrop,
oneTimeUpload,
- showTip,
uploadedFiles,
+ multiple,
+ accept,
+ webkitdirectory
} = toRefs(props)
+ const { triggerSelectFiles, _validateFiles, triggerDropFiles, checkAllFilesSize } =
+ useSelectFiles()
const {
- triggerSelectFiles,
- _validateFiles,
- triggerDropFiles,
- checkAllFilesSize,
- } = useSelectFiles()
- const {
- getFiles,
fileUploaders,
addFile,
getFullFiles,
@@ -56,13 +43,13 @@ export default defineComponent({
resetSameNameFiles,
removeFiles,
_oneTimeUpload,
- getSameNameFiles,
+ getSameNameFiles
} = useUpload()
const isDropOVer = ref(false)
const uploadTips = ref('')
const alertMsg = (errorMsg: string) => {
ToastService.open({
- value: [{ severity: 'warn', content: errorMsg }],
+ value: [{ severity: 'warn', content: errorMsg }]
})
}
const checkValid = () => {
@@ -73,7 +60,7 @@ export default defineComponent({
const checkResult = _validateFiles(
fileUploader.file,
- fileOptions.value.accept,
+ accept.value,
fileUploader.uploadOptions
)
if (checkResult && checkResult.checkError) {
@@ -84,10 +71,7 @@ export default defineComponent({
})
if (oneTimeUpload.value) {
- const checkResult = checkAllFilesSize(
- totalFileSize,
- uploadOptions.value.maximumSize
- )
+ const checkResult = checkAllFilesSize(totalFileSize, uploadOptions.value.maximumSize)
if (checkResult && checkResult.checkError) {
removeFiles()
alertMsg(checkResult.errorMsg)
@@ -100,6 +84,10 @@ export default defineComponent({
promise
.then((files) => {
files.forEach((file) => {
+ // 单文件上传前先清空数组
+ if (!multiple.value) {
+ removeFiles()
+ }
addFile(file, uploadOptions.value)
// debounceTime(100)
})
@@ -109,13 +97,11 @@ export default defineComponent({
alertMsg(getExistSameNameFilesMsg(sameNameFiles))
}
const selectedFiles = fileUploaders.value
- .filter(
- (fileUploader) => fileUploader.status === UploadStatus.preLoad
- )
+ .filter((fileUploader) => fileUploader.status === UploadStatus.preLoad)
.map((fileUploader) => fileUploader.file)
ctx.emit('fileSelect', selectedFiles)
if (autoUpload.value) {
- upload()
+ fileUpload()
}
})
.catch((error: Error) => {
@@ -127,7 +113,13 @@ export default defineComponent({
if (disabled.value) {
return
}
- _dealFiles(triggerSelectFiles(fileOptions.value))
+ _dealFiles(
+ triggerSelectFiles({
+ accept: accept.value,
+ multiple: multiple.value,
+ webkitdirectory: webkitdirectory.value
+ })
+ )
}
const onFileDrop = (files: File[]) => {
@@ -139,18 +131,21 @@ export default defineComponent({
isDropOVer.value = event
ctx.emit('fileOver', event)
}
- const onDeleteFile = (event: Event, file: File) => {
- event.stopPropagation()
- deleteFile(file)
- }
// 删除已上传文件
const deleteUploadedFile = (file: File) => {
const newUploadedFiles = uploadedFiles.value.filter((uploadedFile) => {
return uploadedFile.name !== file.name
})
- ctx.emit('deleteUploadedFileEvent', file)
+ ctx.emit('deleteUploadedFile', file)
ctx.emit('update:uploadedFiles', newUploadedFiles)
}
+ const onDeleteFile = (event: Event, file: File, status: UploadStatus) => {
+ event.stopPropagation()
+ if (status === UploadStatus.uploaded) {
+ deleteUploadedFile(file)
+ }
+ deleteFile(file)
+ }
const canUpload = () => {
let uploadResult = Promise.resolve(true)
if (beforeUpload.value) {
@@ -174,19 +169,17 @@ export default defineComponent({
removeFiles()
return
}
- const uploadObservable = oneTimeUpload.value
- ? _oneTimeUpload()
- : upload(fileUploader)
+ const uploadObservable = oneTimeUpload.value ? _oneTimeUpload() : upload(fileUploader)
uploadObservable
.then((results: Array<{ file: File; response: any; }>) => {
- ctx.emit('successEvent', results)
+ props['on-success'] && props['on-success'](results)
const newFiles = results.map((result) => result.file)
const newUploadedFiles = [...newFiles, ...uploadedFiles.value]
ctx.emit('update:uploadedFiles', newUploadedFiles)
})
.catch((error) => {
- ctx.emit('errorEvent', error)
+ props['on-error'] && props['on-error'](error)
})
})
}
@@ -236,7 +229,6 @@ export default defineComponent({
return {
uploadOptions,
- fileOptions,
placeholderText,
autoUpload,
withoutBtn,
@@ -251,11 +243,11 @@ export default defineComponent({
fileUploaders,
onDeleteFile,
fileUpload,
- showTip,
getStatus,
uploadTips,
cancelUpload,
deleteUploadedFile,
+ multiple
}
},
render() {
@@ -265,7 +257,6 @@ export default defineComponent({
withoutBtn,
uploadText,
disabled,
- beforeUpload,
enableDrop,
isDropOVer,
onFileDrop,
@@ -274,52 +265,43 @@ export default defineComponent({
fileUploaders,
onDeleteFile,
fileUpload,
- showTip,
- getStatus,
- uploadTips,
- cancelUpload,
uploadedFiles,
deleteUploadedFile,
+ multiple
} = this
+
return (
- <>
+
{this.$slots.default?.() ? (
{this.$slots.default()}
) : (
-