UNPKG

@fesjs/fes-design

Version:
335 lines (331 loc) 8.79 kB
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty'; import { ref, computed, provide, toRefs, watch } from 'vue'; import { isArray, isEqual, isFunction } from 'lodash-es'; import { noop, hasOwn } from '../_util/utils'; import useFormAdaptor from '../_util/use/useFormAdaptor'; import getPrefixCls from '../_util/getPrefixCls'; import { useNormalModel } from '../_util/use/useModel'; import defaultRequest from './ajax'; import { key } from './const'; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } const prefixCls = getPrefixCls('upload'); function genUid(seed) { return Date.now() + seed; } function getFile(rawFile, uploadFiles) { return uploadFiles.find(file => file.uid === rawFile.uid); } var useUpload = (props, emit) => { const isDragger = ref(false); const inputRef = ref(); const requestList = ref({}); let tempIndex = 1; const [uploadFiles, updateUploadFiles] = useNormalModel(props, emit, { prop: 'fileList' }); function initFile(rawFile) { const uid = genUid(tempIndex++); rawFile.uid = uid; const file = { name: rawFile.name, percentage: 0, status: 'ready', size: rawFile.size, raw: rawFile, uid, url: '' }; return file; } function abort(file) { const _requestList = requestList.value; if (file) { const uid = file.uid; if (_requestList[uid]) { _requestList[uid].abort(); } } else { Object.keys(_requestList).forEach(uid => { const _uid = uid; if (_requestList[_uid]) { _requestList[_uid].abort(); } delete _requestList[_uid]; }); } } function onStart(rawFile) { const file = initFile(rawFile); if (props.listType === 'picture-card') { try { file.url = URL.createObjectURL(rawFile); } catch (error) { console.error('[Upload]', error); emit('error', { error, file, fileList: uploadFiles.value }); } } uploadFiles.value.push(file); emit('change', { file, fileList: uploadFiles.value }); } function onExceed(files) { emit('exceed', { files, fileList: uploadFiles.value }); } function onProgress(_ref) { let { event, rawFile } = _ref; const file = getFile(rawFile, uploadFiles.value); if (!file) { return; } file.status = 'uploading'; file.percentage = event.percent || 0; emit('progress', { event, file, fileList: uploadFiles.value }); } function onSuccess(_ref2) { let { response, rawFile } = _ref2; const file = getFile(rawFile, uploadFiles.value); if (!file) { return; } file.status = 'success'; file.response = response; emit('success', { response, file, fileList: uploadFiles.value }); emit('change', { file, fileList: uploadFiles.value }); } function onError(_ref3) { let { error, rawFile } = _ref3; const uploadFilesValue = uploadFiles.value; const file = getFile(rawFile, uploadFilesValue); if (!file) { return; } file.status = 'error'; emit('error', { error, file, fileList: uploadFilesValue }); emit('change', { file, fileList: uploadFilesValue }); } function onRemove(rawFile, file) { const uploadFilesValue = uploadFiles.value; file = file || getFile(rawFile, uploadFilesValue); if (!file) { return; } const doRemove = () => { abort(file); uploadFilesValue.splice(uploadFilesValue.indexOf(file), 1); emit('remove', { file, fileList: uploadFilesValue }); emit('change', { file, fileList: uploadFilesValue }); }; if (!props.beforeRemove) { return doRemove(); } if (isFunction(props.beforeRemove)) { const before = props.beforeRemove(file, uploadFilesValue); if (before instanceof Promise) { before.then(() => { doRemove(); }).catch(noop); } else if (before !== false) { doRemove(); } } } const httpRequest = computed(() => { var _props$httpRequest; return (_props$httpRequest = props.httpRequest) !== null && _props$httpRequest !== void 0 ? _props$httpRequest : defaultRequest; }); const post = rawFile => { if (!props.httpRequest && !props.action) { onRemove(rawFile); console.error('[FUpload] 需配置action地址,才能执行上传'); return; } const { uid } = rawFile; const options = { headers: props.headers, withCredentials: props.withCredentials, data: props.data, file: rawFile, fileName: props.name, action: props.action, timeout: props.timeout, transformResponse: props.transformResponse, onProgress: e => { onProgress({ event: e, rawFile }); }, onSuccess: res => { onSuccess({ response: res, rawFile }); delete requestList.value[uid]; }, onError: err => { onError({ error: err, rawFile }); delete requestList.value[uid]; } }; const req = httpRequest.value(options); requestList.value[uid] = req; if (req instanceof Promise) { req.then(options.onSuccess, options.onError); } }; const upload = async rawFile => { inputRef.value.value = null; if (!props.beforeUpload) { return post(rawFile); } try { let processedFile = await props.beforeUpload(rawFile); if (processedFile === false) { return onRemove(rawFile); } const fileType = Object.prototype.toString.call(processedFile); if (fileType === '[object File]' || fileType === '[object Blob]') { if (fileType === '[object Blob]') { processedFile = new File([processedFile], rawFile.name, { type: rawFile.type }); } Object.keys(rawFile).forEach(p => { if (hasOwn(rawFile, p)) { processedFile[p] = rawFile[p]; } }); post(processedFile); } else { post(rawFile); } } catch (e) { onRemove(rawFile); } }; const onUploadFiles = files => { files = Array.from(files); if (props.multipleLimit && props.fileList.length + files.length > props.multipleLimit) { onExceed(files); return; } let postFiles = files; if (!props.multiple) { postFiles = postFiles.slice(0, 1); } if (postFiles.length === 0) { return; } postFiles.forEach(rawFile => { onStart(rawFile); upload(rawFile); }); }; // 表单组件的总体disabled状态 const { isFormDisabled } = useFormAdaptor(); provide(key, _objectSpread(_objectSpread({}, toRefs(props)), {}, { disabled: computed(() => { return props.disabled || isFormDisabled.value; }), prefixCls, uploadFiles, onRemove, onUploadFiles, inputRef, isDragger })); watch(() => props.fileList, fileList => { if (!isArray(fileList)) { fileList = []; } if (!isEqual(uploadFiles.value, fileList)) { uploadFiles.value = fileList.map(file => { return _objectSpread(_objectSpread({}, file), {}, { uid: file.uid || genUid(tempIndex++), status: file.status || 'success' }); }); } }, { immediate: true, deep: true }); function clearFiles() { updateUploadFiles([]); } function addFile(rawFile) { if (!rawFile) { return; } if (props.multipleLimit && props.fileList.length + 1 > props.multipleLimit) { onExceed([rawFile]); return; } onStart(rawFile); upload(rawFile); } function removeFile(file) { if (!file) { return; } onRemove(null, file); } return { uploadFiles, isDragger, clearFiles, addFile, removeFile }; }; export { useUpload as default };