文件上传优化

This commit is contained in:
2betop 2019-12-23 18:31:41 +08:00
parent f6d329f9ac
commit cacb6e5626
3 changed files with 47 additions and 20 deletions

View File

@ -144,4 +144,12 @@
line-height: 120px; line-height: 120px;
text-align: center; text-align: center;
} }
&-sum {
font-size: $fontSizeSm;
> a {
cursor: pointer;
}
}
} }

View File

@ -9,7 +9,7 @@ import ImageControl from './Image';
import {Payload, ApiObject, ApiString} from '../../types'; import {Payload, ApiObject, ApiString} from '../../types';
import {filter} from '../../utils/tpl'; import {filter} from '../../utils/tpl';
import Alert from '../../components/Alert2'; import Alert from '../../components/Alert2';
import {qsstringify, createObject} from '../../utils/helper'; import {qsstringify, createObject, guid} from '../../utils/helper';
import {buildApi} from '../../utils/api'; import {buildApi} from '../../utils/api';
import Button from '../../components/Button'; import Button from '../../components/Button';
import {Icon} from '../../components/icons'; import {Icon} from '../../components/icons';
@ -83,12 +83,6 @@ export interface FileState {
files: Array<FileX | FileValue>; files: Array<FileX | FileValue>;
error?: string | null; error?: string | null;
} }
let id = 1;
function gennerateId() {
return id++;
}
let preventEvent = (e: any) => e.stopPropagation(); let preventEvent = (e: any) => e.stopPropagation();
export function getNameFromUrl(url: string) { export function getNameFromUrl(url: string) {
@ -134,6 +128,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
state: FileState; state: FileState;
current: FileValue | FileX | null; current: FileValue | FileX | null;
resolve?: (value?: any) => void; resolve?: (value?: any) => void;
emitValue: any;
static valueToFile( static valueToFile(
value: string | FileValue, value: string | FileValue,
@ -151,17 +146,19 @@ export default class FileControl extends React.Component<FileProps, FileState> {
value: value, value: value,
name: value.name, name: value.name,
url: '', url: '',
id: gennerateId() id: guid()
} }
: { : {
...(typeof value === 'string' ...(typeof value === 'string'
? { ? {
state: file && file.state ? file.state : 'init', state: file && file.state ? file.state : 'init',
value, value,
name: /^data:/.test(value) name:
? (file && file.name) || 'base64数据' (file && file.name) ||
: getNameFromUrl(value), (/^data:/.test(value)
id: gennerateId(), ? 'base64数据'
: getNameFromUrl(value)),
id: guid(),
url: url:
typeof props.downloadUrl === 'string' && typeof props.downloadUrl === 'string' &&
value && value &&
@ -209,6 +206,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
this.handleDropRejected = this.handleDropRejected.bind(this); this.handleDropRejected = this.handleDropRejected.bind(this);
this.startUpload = this.startUpload.bind(this); this.startUpload = this.startUpload.bind(this);
this.stopUpload = this.stopUpload.bind(this); this.stopUpload = this.stopUpload.bind(this);
this.retry = this.retry.bind(this);
this.toggleUpload = this.toggleUpload.bind(this); this.toggleUpload = this.toggleUpload.bind(this);
this.tick = this.tick.bind(this); this.tick = this.tick.bind(this);
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
@ -220,7 +218,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
componentWillReceiveProps(nextProps: FileProps) { componentWillReceiveProps(nextProps: FileProps) {
const props = this.props; const props = this.props;
if (props.value !== nextProps.value) { if (props.value !== nextProps.value && this.emitValue !== nextProps.value) {
const value: string | Array<string | FileValue> | FileValue = const value: string | Array<string | FileValue> | FileValue =
nextProps.value; nextProps.value;
const multiple = nextProps.multiple; const multiple = nextProps.multiple;
@ -295,7 +293,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
file.state = 'pending'; file.state = 'pending';
} }
file.id = gennerateId(); file.id = guid();
inputFiles.push(file); inputFiles.push(file);
}); });
@ -327,7 +325,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
const files = rejectedFiles.map((file: any) => ({ const files = rejectedFiles.map((file: any) => ({
...file, ...file,
state: 'invalid', state: 'invalid',
id: gennerateId(), id: guid(),
name: file.name name: file.name
})); }));
@ -350,7 +348,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
this.dropzone.current && this.dropzone.current.open(); this.dropzone.current && this.dropzone.current.open();
} }
startUpload() { startUpload(retry: boolean = false) {
if (this.state.uploading) { if (this.state.uploading) {
return; return;
} }
@ -359,8 +357,9 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{ {
uploading: true, uploading: true,
files: this.state.files.map(file => { files: this.state.files.map(file => {
if (file.state === 'error') { if (retry && file.state === 'error') {
file.state = 'pending'; file.state = 'pending';
file.progress = 0;
} }
return file; return file;
@ -385,6 +384,10 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}); });
} }
retry() {
this.startUpload(true);
}
tick() { tick() {
if (this.current || !this.state.uploading) { if (this.current || !this.state.uploading) {
return; return;
@ -617,7 +620,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
value = typeof resetValue === 'undefined' ? '' : resetValue; value = typeof resetValue === 'undefined' ? '' : resetValue;
} }
onChange(value); onChange((this.emitValue = value));
} }
uploadFile( uploadFile(
@ -880,6 +883,18 @@ export default class FileControl extends React.Component<FileProps, FileState> {
const hasPending = files.some(file => file.state == 'pending'); const hasPending = files.some(file => file.state == 'pending');
let uploaded = 0;
let failed = 0;
this.state.uploading ||
this.state.files.forEach(item => {
if (item.state === 'error') {
failed++;
} else if (item.state === 'uploaded') {
uploaded++;
}
});
return ( return (
<div className={cx('FileControl', className)}> <div className={cx('FileControl', className)}>
<DropZone <DropZone
@ -1006,8 +1021,11 @@ export default class FileControl extends React.Component<FileProps, FileState> {
)} )}
</DropZone> </DropZone>
{error ? ( {failed ? (
<div className={cx('FileControl-errorMsg')}>{error}</div> <div className={cx('FileControl-sum')}>
{uploaded}{failed}
<a onClick={this.retry}></a>
</div>
) : null} ) : null}
{!autoUpload && !hideUploadButton && files.length ? ( {!autoUpload && !hideUploadButton && files.length ? (

View File

@ -318,6 +318,7 @@ export default class ImageControl extends React.Component<
files: this.files = this.files.map(file => { files: this.files = this.files.map(file => {
if (retry && file.state === 'error') { if (retry && file.state === 'error') {
file.state = 'pending'; file.state = 'pending';
file.progress = 0;
} }
return file; return file;