Skip to content

refactor(Upload): refactor Upload #249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions packages/devui-vue/devui/upload/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import type { App } from 'vue'
import Upload from './src/upload'
import fileDropDirective from './src/file-drop-directive'
import type { App } from 'vue';
import Upload from './src/upload';
import fileDropDirective from './src/file-drop-directive';
export * from './src/upload-types';

Upload.install = function (app: App) {
app.directive('file-drop', fileDropDirective)
app.component(Upload.name, Upload)
}

export { Upload }
export { Upload };

export default {
title: 'Upload 上传',
category: '数据录入',
status: '100%',
install(app: App): void {
app.use(Upload as any)
}
}
app.directive('file-drop', fileDropDirective);
app.component(Upload.name, Upload);
},
};
109 changes: 109 additions & 0 deletions packages/devui-vue/devui/upload/src/composables/use-select-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { ref } from 'vue';
import { IFileOptions } from '../upload-types';
import { getNotAllowedFileTypeMsg, getBeyondMaximalFileSizeMsg, getAllFilesBeyondMaximalFileSizeMsg } from '../i18n-upload';

export const useSelectFiles = () => {
const BEYOND_MAXIMAL_FILE_SIZE_MSG = ref('');
const simulateClickEvent = (input) => {
const evt = document.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
input.dispatchEvent(evt);
};
const selectFiles = ({ multiple, accept, webkitdirectory }: IFileOptions): Promise<File[]> => {
return new Promise((resolve) => {
const tempNode = document.getElementById('d-upload-temp');
if (tempNode) {
document.body.removeChild(tempNode);
}
const input = document.createElement('input');

input.style.position = 'fixed';
input.style.left = '-2000px';
input.style.top = '-2000px';

input.setAttribute('id', 'd-upload-temp');
input.setAttribute('type', 'file');
if (multiple) {
input.setAttribute('multiple', '');
}
if (accept) {
input.setAttribute('accept', accept);
}

if (webkitdirectory) {
input.setAttribute('webkitdirectory', '');
}

input.addEventListener('change', (event) => {
resolve(Array.prototype.slice.call((event.target as HTMLInputElement).files));
});
document.body.appendChild(input); // Fix compatibility issue with Internet Explorer 11
simulateClickEvent(input);
});
};

const isAllowedFileType = (accept: string, file: File) => {
if (accept) {
const acceptArr = accept.split(',');
const baseMimeType = file.type.replace(/\/.*$/, '');
return acceptArr.some((type: string) => {
const validType = type.trim();
// suffix name (e.g. '.png,.xlsx')
if (validType.startsWith('.')) {
return (
file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.toLowerCase().length - validType.toLowerCase().length) > -1
);
// mime type like 'image/*'
} else if (/\/\*$/.test(validType)) {
return baseMimeType === validType.replace(/\/.*$/, '');
}
// mime type like 'text/plain,application/json'
return file.type === validType;
});
}
return true;
};

const beyondMaximalSize = (fileSize, maximumSize) => {
if (maximumSize) {
return fileSize > 1024 * 1024 * maximumSize;
}
return false;
};

const _validateFiles = (file, accept, uploadOptions) => {
if (!isAllowedFileType(accept, <File>file)) {
return {
checkError: true,
errorMsg: getNotAllowedFileTypeMsg((<File>file).name, accept),
};
}
if (uploadOptions && beyondMaximalSize((<File>file).size, uploadOptions.maximumSize)) {
return {
checkError: true,
errorMsg: getBeyondMaximalFileSizeMsg((<File>file).name, uploadOptions.maximumSize),
};
}
return { checkError: false, errorMsg: undefined };
};

const triggerSelectFiles = (fileOptions: IFileOptions) => {
const { multiple, accept, webkitdirectory } = fileOptions;
return selectFiles({ multiple, accept, webkitdirectory });
};
const triggerDropFiles = (files: File[]) => {
return Promise.resolve(files);
};
const checkAllFilesSize = (fileSize, maximumSize) => {
if (beyondMaximalSize(fileSize, maximumSize)) {
BEYOND_MAXIMAL_FILE_SIZE_MSG.value = getAllFilesBeyondMaximalFileSizeMsg(maximumSize);
return { checkError: true, errorMsg: BEYOND_MAXIMAL_FILE_SIZE_MSG.value };
}
};
return {
triggerSelectFiles,
_validateFiles,
triggerDropFiles,
checkAllFilesSize,
};
};
134 changes: 134 additions & 0 deletions packages/devui-vue/devui/upload/src/composables/use-upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { ref } from 'vue';
import { FileUploader } from '../file-uploader';
import { UploadStatus } from '../upload-types';

export const useUpload = () => {
const fileUploaders = ref<Array<FileUploader>>([]);
const filesWithSameName = ref([]);

const checkFileSame = (fileName) => {
let checkRel = true;

for (let i = 0; i < fileUploaders.value.length; i++) {
if (fileName === fileUploaders.value[i].file.name) {
checkRel = false;
if (filesWithSameName.value.indexOf(fileName) === -1) {
filesWithSameName.value.push(fileName);
}
break;
}
}
return checkRel;
};

const addFile = (file, options) => {
if (options && options.checkSameName) {
if (checkFileSame(file.name)) {
fileUploaders.value.push(new FileUploader(file, options));
}
} else {
fileUploaders.value.push(new FileUploader(file, options));
}
};

const getFiles = () => {
return fileUploaders.value.map((fileUploader) => {
return fileUploader.file;
});
};

const getFullFiles = () => {
return fileUploaders.value.map((fileUploader) => {
return fileUploader;
});
};

const dealOneTimeUploadFiles = async (uploads) => {
if (!uploads || !uploads.length) {
return Promise.reject('no files');
}
// 触发文件上传
let finalUploads = [];
await uploads[0].send(uploads).finally(
() =>
// 根据uploads[0]的上传状态为其他file设置状态
(finalUploads = uploads.map((file) => {
file.status = uploads[0].status;
file.percentage = uploads[0].percentage;
return { file: file.file, response: uploads[0].response };
}))
);

return finalUploads;
};

const upload = async (
oneFile?
): Promise<
| never
| {
file: File;
response: any;
}[]
> => {
let uploads: any[] = [];
if (oneFile) {
oneFile.percentage = 0;
const uploadedFile = await oneFile.send();
uploads.push(uploadedFile);
} else {
const preFiles = fileUploaders.value.filter((fileUploader) => fileUploader.status === UploadStatus.preLoad);
const failedFiles = fileUploaders.value.filter((fileUploader) => fileUploader.status === UploadStatus.failed);
const uploadFiles = preFiles.length > 0 ? preFiles : failedFiles;
uploads = await Promise.all(
uploadFiles.map(async (fileUploader) => {
fileUploader.percentage = 0;
const uploadedFile = await fileUploader.send();
return uploadedFile;
})
);
}
if (uploads.length > 0) {
return Promise.resolve(uploads);
}

return Promise.reject('no files');
};

const _oneTimeUpload = () => {
const uploads = fileUploaders.value.filter((fileUploader) => fileUploader.status !== UploadStatus.uploaded);
return dealOneTimeUploadFiles(uploads);
};

const deleteFile = (file) => {
const deleteUploadFile = fileUploaders.value.find((fileUploader) => fileUploader.file === file);
deleteUploadFile.cancel();
fileUploaders.value = fileUploaders.value.filter((fileUploader) => {
return file !== fileUploader.file;
});
};

const removeFiles = () => {
fileUploaders.value = [];
filesWithSameName.value = [];
};
const getSameNameFiles = () => {
return filesWithSameName.value.join();
};
const resetSameNameFiles = () => {
filesWithSameName.value = [];
};

return {
fileUploaders,
getFiles,
addFile,
getFullFiles,
deleteFile,
upload,
removeFiles,
getSameNameFiles,
resetSameNameFiles,
_oneTimeUpload,
};
};
Loading