UNPKG

@forchange/aui

Version:

ai-boss 业务 ui 组件库

335 lines (278 loc) 8.14 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import * as React from 'react'; import 'antd/lib/upload/style/css'; import defaultRequest from './utils/request'; import getUid from './utils/uid'; import { Upload } from 'antd'; import 'antd/lib/modal/style/css'; // 不引入modal样式preview图片时会出错 import { fileToObject, genPercentAdd, getFileItem } from './utils/utils'; class UploadPlus extends React.Component { constructor(props) { super(props); _defineProperty(this, "reqs", {}); _defineProperty(this, "progressTimer", void 0); _defineProperty(this, "onFilePaste", e => { // ant design 若开启上传文件夹模式,单个文件不能上传。 // 粘贴上传的图片都是单个文件的,所以若开启上传文件夹模式不能上传粘贴的文件。 if (!this.props.pasteUpload || this.props.directory || this.props.limit && this.state.fileList.length >= this.props.limit) { return; } const items = e.clipboardData.items; let file = {}; for (const item of items) { if (item.kind === 'file') { file = item.getAsFile(); } } const uid = getUid(); const rcFile = Object.assign(file, { uid }); const postFiles = [rcFile]; this.upload(rcFile, postFiles); }); _defineProperty(this, "onError", (error, response, file) => { this.clearProgressTimer(); const { fileList } = this.state; const targetItem = getFileItem(file, fileList); // removed if (!targetItem) { return; } targetItem.error = error; targetItem.response = response; targetItem.status = 'error'; this.onChange({ file: { ...targetItem }, fileList }); }); _defineProperty(this, "onStart", file => { const { fileList } = this.state; const targetItem = fileToObject(file); targetItem.status = 'uploading'; targetItem.percent = 0; const nextFileList = fileList.concat(); const fileIndex = nextFileList.findIndex( // nextFileList, ({ uid }) => uid === targetItem.uid); if (fileIndex === -1) { nextFileList.push(targetItem); } else { nextFileList[fileIndex] = targetItem; } this.onChange({ file: targetItem, fileList: nextFileList }); // fix ie progress if (!window.FormData) { this.autoUpdateProgress(0, targetItem); } }); _defineProperty(this, "onProgress", (e, file) => { const { fileList } = this.state; const targetItem = getFileItem(file, fileList); // removed if (!targetItem) { return; } targetItem.percent = e.percent; this.onChange({ event: e, file: { ...targetItem }, fileList }); }); _defineProperty(this, "onSuccess", (response, file) => { this.clearProgressTimer(); try { if (typeof response === 'string') { response = JSON.parse(response); } } catch (e) { /* do nothing */ } const { fileList } = this.state; const targetItem = getFileItem(file, fileList); // removed if (!targetItem) { return; } targetItem.status = 'done'; targetItem.response = response; this.onChange({ file: { ...targetItem }, fileList }); }); _defineProperty(this, "onChange", info => { if (!('fileList' in this.props)) { this.setState({ fileList: info.fileList }); } const { onChange } = this.props; if (onChange) { onChange(info); } }); this.state = { isMounted: false, fileList: props.fileList || props.defaultFileList || [] }; } componentDidMount() { this.setState({ isMounted: true }); } componentWillUnmount() { this.setState({ isMounted: false }); this.abort(); } // 监听父组件 fileList 的变化 componentWillReceiveProps(nextProps) { if (this.props.fileList !== nextProps.fileList) { this.setState({ fileList: nextProps.fileList }); } } upload(file, fileList) { const { props } = this; if (!props.beforeUpload) { // always async in case use react state to keep fileList return setTimeout(() => this.post(file), 0); } const before = props.beforeUpload(file, fileList); if (before && before.then) { before.then(processedFile => { const processedFileType = Object.prototype.toString.call(processedFile); if (processedFileType === '[object File]' || processedFileType === '[object Blob]') { return this.post(processedFile); } return this.post(file); }).catch(e => { console.log(e); // eslint-disable-line }); } else if (before !== false) { setTimeout(() => this.post(file), 0); } } post(file) { if (!this.state.isMounted) { return; } const { transformFile = originFile => originFile } = this.props; let { data } = this.props; if (typeof data === 'function') { data = data(file); } new Promise(resolve => { const { action } = this.props; if (typeof action === 'function') { return resolve(action(file)); } resolve(action); }).then(action => { const { uid } = file; const request = this.props.customRequest || defaultRequest; const transform = Promise.resolve(transformFile(file)); transform.then(transformedFile => { const requestOption = { action, filename: this.props.name, data, file: transformedFile, headers: this.props.headers, withCredentials: this.props.withCredentials, onProgress: e => { this.onProgress(e, file); }, onSuccess: ret => { delete this.reqs[uid]; this.onSuccess(ret, file); }, onError: (err, ret) => { delete this.reqs[uid]; this.onError(err, ret, file); } }; this.reqs[uid] = request(requestOption); this.onStart(file); }); }); } clearProgressTimer() { clearInterval(this.progressTimer); } autoUpdateProgress(_, file) { const getPercent = genPercentAdd(); let curPercent = 0; this.clearProgressTimer(); this.progressTimer = setInterval(() => { curPercent = getPercent(curPercent); this.onProgress({ percent: curPercent * 100 }, file); }, 200); } abort(file) { const { reqs } = this; if (file) { let uid = file; if (file && file.uid) { uid = file.uid; } if (reqs[uid] && reqs[uid].abort) { reqs[uid].abort(); } delete reqs[uid]; } else { Object.keys(reqs).forEach(uid => { if (reqs[uid] && reqs[uid].abort) { reqs[uid].abort(); } delete reqs[uid]; }); } } render() { return React.createElement("div", { onPaste: this.onFilePaste }, React.createElement(Upload, _extends({}, this.props, { onChange: this.onChange, fileList: this.state.fileList }), this.props.children), React.createElement("span", null, " \xA0")); } } _defineProperty(UploadPlus, "defaultProps", { pasteUpload: true, limit: 0 }); export default UploadPlus;