@forchange/aui
Version:
ai-boss 业务 ui 组件库
335 lines (278 loc) • 8.14 kB
JavaScript
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;