UNPKG

element-react-codish

Version:
261 lines (234 loc) 6.24 kB
/* @flow */ import React from 'react'; import { Component, PropTypes } from '../../libs'; import UploadList from './UploadList'; import iFrameUpload from './iFrameUpload'; import AjaxUpload from './AjaxUpload'; import type { UploadState, RawFile, _File, _ProgressEvent } from './Types'; export default class Upload extends Component { state: UploadState; static defaultProps = { headers: {}, name: 'file', type: 'select', listType: 'text', fileList: [], showFileList: true, autoUpload: true, onRemove() {}, onPreview() {}, onProgress() {}, onSuccess() {}, onError() {}, onChange() {} }; constructor(props: Object) { super(props); this.state = { fileList: [], tempIndex: 1 }; } componentWillMount(): void { this.init(this.props); } init(props: Object): void { let { tempIndex } = this.state; const { fileList } = props; const uploadFiles = fileList.map(file => { file.uid = file.uid || Date.now() + tempIndex++; file.status = 'success'; return file; }); this.setState({ fileList: uploadFiles }); } getChildContext() { return { onPreview: this.handlePreview.bind(this), onRemove: this.handleRemove.bind(this) }; } getFile(file: RawFile): ?_File { if (file) { return this.state.fileList.find(item => item.uid === file.uid); } return null; } handleStart(file: RawFile): void { let { tempIndex, fileList } = this.state; file.uid = Date.now() + tempIndex++; let _file: _File = { status: 'ready', name: file.name, size: file.size, percentage: 0, uid: file.uid, raw: file }; try { _file.url = URL.createObjectURL(file); } catch (err) { return; } fileList.push(_file); this.setState({ fileList, tempIndex }); } handleProgress(e: _ProgressEvent, file: RawFile): void { const { fileList } = this.state; let _file = this.getFile(file); if (_file) { _file.percentage = e.percent || 0; _file.status = 'uploading'; this.props.onProgress(e, _file, fileList); this.setState({ fileList }); } } handleSuccess(res: Object, file: RawFile): void { const { fileList } = this.state; let _file = this.getFile(file); if (_file) { _file.status = 'success'; _file.response = res; setTimeout( () => { this.setState({ fileList }, () => { this.props.onSuccess(res, _file, fileList); this.props.onChange(_file, fileList); }); }, 1000 ); } } handleError(err: Error, file: RawFile): void { const { fileList } = this.state; let _file = this.getFile(file); if (_file) { _file.status = 'fail'; fileList.splice(fileList.indexOf(_file), 1); this.setState({ fileList }, () => { this.props.onError(err, _file, fileList); this.props.onChange(_file, fileList); }); } } handleRemove(file: RawFile): void { const { fileList } = this.state; let _file = this.getFile(file); if (_file) { fileList.splice(fileList.indexOf(_file), 1); this.setState({ fileList }, () => this.props.onRemove(file, fileList)); } } handlePreview(file: _File): void { if (file.status === 'success') { this.props.onPreview(file); } } clearFiles(): void { this.setState({ fileList: [] }); } submit(): void { this.state.fileList .filter(file => file.status === 'ready') .forEach(file => { this.refs['upload-inner'].upload(file.raw, file); }); } showCover(): boolean { const { fileList } = this.state; const file = fileList[fileList.length - 1]; return file && file.status !== 'fail'; } render(): React.Element<any> { const { fileList } = this.state; const { showFileList, autoUpload, drag, tip, action, multiple, beforeUpload, withCredentials, headers, name, data, accept, listType, className } = this.props; let uploadList; if (showFileList && fileList.length) { uploadList = <UploadList listType={listType} fileList={fileList} />; } const restProps = { autoUpload, drag, action, multiple, beforeUpload, withCredentials, headers, name, data, accept, listType, onStart: this.handleStart.bind(this), onProgress: this.handleProgress.bind(this), onSuccess: this.handleSuccess.bind(this), onError: this.handleError.bind(this), onPreview: this.handlePreview.bind(this), onRemove: this.handleRemove.bind(this), showCover: this.showCover(), ref: 'upload-inner' }; const trigger = this.props.trigger || this.props.children; const uploadComponent = typeof FormData !== 'undefined' ? <AjaxUpload key="AjaxUpload" {...restProps}>{trigger}</AjaxUpload> : <iFrameUpload key="iFrameUpload" {...restProps}>{trigger}</iFrameUpload>; return ( <div className={className}> {listType === 'picture-card' ? uploadList : ''} {this.props.trigger ? [uploadComponent, this.props.children] : uploadComponent} {tip} {listType !== 'picture-card' ? uploadList : ''} </div> ); } } Upload.childContextTypes = { onPreview: PropTypes.func, onRemove: PropTypes.func }; Upload.propTypes = { action: PropTypes.string.isRequired, headers: PropTypes.object, data: PropTypes.object, multiple: PropTypes.bool, name: PropTypes.string, withCredentials: PropTypes.bool, showFileList: PropTypes.bool, fileList: PropTypes.array, autoUpload: PropTypes.bool, accept: PropTypes.string, drag: PropTypes.bool, listType: PropTypes.oneOf(['text', 'picture', 'picture-card']), tip: PropTypes.node, trigger: PropTypes.node, beforeUpload: PropTypes.func, onRemove: PropTypes.func, onPreview: PropTypes.func, onProgress: PropTypes.func, onSuccess: PropTypes.func, onError: PropTypes.func, onChange: PropTypes.func, className: PropTypes.string };