有 preview 图片,不再加载原始图片预览

This commit is contained in:
liaoxuezhi 2019-12-23 16:13:02 +08:00
parent a8f61f0c92
commit 08de256dcf
5 changed files with 62 additions and 45 deletions

View File

@ -73,7 +73,7 @@
padding: px2rem(5px); padding: px2rem(5px);
display: inline-block; display: inline-block;
margin-right: px2rem(15px); margin-right: px2rem(15px);
margin-right: px2rem(15px); margin-bottom: px2rem(15px);
position: relative; position: relative;
} }

View File

@ -57,6 +57,9 @@ import BackIcon from '../icons/back.svg';
// @ts-ignore // @ts-ignore
import MoveIcon from '../icons/move.svg'; import MoveIcon from '../icons/move.svg';
// @ts-ignore
import InfoIcon from '../icons/info.svg';
// 兼容原来的用法,后续不直接试用。 // 兼容原来的用法,后续不直接试用。
// @ts-ignore // @ts-ignore
export const closeIcon = <CloseIcon />; export const closeIcon = <CloseIcon />;
@ -115,6 +118,7 @@ registerIcon('fail', FailIcon);
registerIcon('search', SearchIcon); registerIcon('search', SearchIcon);
registerIcon('back', BackIcon); registerIcon('back', BackIcon);
registerIcon('move', MoveIcon); registerIcon('move', MoveIcon);
registerIcon('info', InfoIcon);
export function Icon({ export function Icon({
icon, icon,

8
src/icons/info.svg Normal file
View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" version="1.1" p-id="1463">
<g id="Group-9">
<circle id="Oval-7" stroke="currentColor" fill="transparent" cx="8" cy="8" r="7.5"></circle>
<rect id="Rectangle-26" fill="currentColor" x="7" y="3" width="2" height="2"></rect>
<rect id="Rectangle-26-Copy" fill="currentColor" x="7" y="6" width="2" height="7"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 463 B

View File

@ -91,7 +91,7 @@ function gennerateId() {
let preventEvent = (e: any) => e.stopPropagation(); let preventEvent = (e: any) => e.stopPropagation();
function getNameFromUrl(url: string) { export function getNameFromUrl(url: string) {
if (/(?:\/|^)([^\/]+?)$/.test(url)) { if (/(?:\/|^)([^\/]+?)$/.test(url)) {
return decodeURIComponent(RegExp.$1); return decodeURIComponent(RegExp.$1);
} }

View File

@ -8,16 +8,13 @@ import find = require('lodash/find');
import qs from 'qs'; import qs from 'qs';
import {Payload} from '../../types'; import {Payload} from '../../types';
import {buildApi} from '../../utils/api'; import {buildApi} from '../../utils/api';
import {createObject, qsstringify} from '../../utils/helper'; import {createObject, qsstringify, guid} from '../../utils/helper';
import {Icon} from '../../components/icons'; import {Icon} from '../../components/icons';
import Button from '../../components/Button'; import Button from '../../components/Button';
// @ts-ignore // @ts-ignore
import accepts from 'attr-accept'; import accepts from 'attr-accept';
import {getNameFromUrl} from './File';
let id = 1;
function gennerateId() {
return id++;
}
let preventEvent = (e: any) => e.stopPropagation(); let preventEvent = (e: any) => e.stopPropagation();
export interface ImageProps extends FormControlProps { export interface ImageProps extends FormControlProps {
@ -122,7 +119,7 @@ export default class ImageControl extends React.Component<
? { ? {
value, value,
url: value, url: value,
id: gennerateId() id: guid()
} }
: value), : value),
state: 'init' state: 'init'
@ -146,6 +143,7 @@ export default class ImageControl extends React.Component<
files: [] files: []
}; };
files: Array<FileValue | FileX> = [];
cropper = React.createRef<Cropper>(); cropper = React.createRef<Cropper>();
dropzone = React.createRef<any>(); dropzone = React.createRef<any>();
current: FileValue | FileX | null = null; current: FileValue | FileX | null = null;
@ -222,7 +220,7 @@ export default class ImageControl extends React.Component<
if ( if (
obj && obj &&
(org = find( (org = find(
this.state.files, this.files,
item => (item as FileValue).value === obj.value item => (item as FileValue).value === obj.value
)) ))
) { ) {
@ -239,7 +237,7 @@ export default class ImageControl extends React.Component<
} }
this.setState({ this.setState({
files files: this.files = files
}); });
} }
@ -288,15 +286,15 @@ export default class ImageControl extends React.Component<
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
})); }));
this.setState({ this.setState({
files: multiple files: this.files = multiple
? this.state.files.concat(files) ? this.files.concat(files)
: this.state.files.length : this.files.length
? this.state.files ? this.files
: files.slice(0, 1) : files.slice(0, 1)
}); });
@ -316,7 +314,7 @@ export default class ImageControl extends React.Component<
{ {
uploading: true, uploading: true,
locked: true, locked: true,
files: this.state.files.map(file => { files: this.files = this.files.map(file => {
if (file.state === 'error') { if (file.state === 'error') {
file.state = 'pending'; file.state = 'pending';
} }
@ -347,23 +345,20 @@ export default class ImageControl extends React.Component<
return; return;
} }
const file = find( const file = find(this.files, item => item.state === 'pending') as FileX;
this.state.files,
item => item.state === 'pending'
) as FileX;
if (file) { if (file) {
this.current = file; this.current = file;
file.state = 'uploading'; file.state = 'uploading';
this.setState( this.setState(
{ {
files: this.state.files.concat() files: this.files = this.files.concat()
}, },
() => () =>
this.sendFile( this.sendFile(
file as FileX, file as FileX,
(error, file, obj) => { (error, file, obj) => {
const files = this.state.files.concat(); const files = this.files.concat();
const idx = files.indexOf(file); const idx = files.indexOf(file);
if (!~idx) { if (!~idx) {
@ -383,26 +378,29 @@ export default class ImageControl extends React.Component<
return this.setState( return this.setState(
{ {
files: files, files: this.files = files,
error: error error: error
}, },
this.tick this.tick
); );
} }
} else { } else {
newFile = obj as FileValue; newFile = {
...obj,
preview: file.preview
} as FileValue;
} }
files.splice(idx, 1, newFile); files.splice(idx, 1, newFile);
this.current = null; this.current = null;
this.setState( this.setState(
{ {
files: files files: this.files = files
}, },
this.tick this.tick
); );
}, },
progress => { progress => {
const files = this.state.files.concat(); const files = this.files.concat();
const idx = files.indexOf(file); const idx = files.indexOf(file);
if (!~idx) { if (!~idx) {
@ -412,7 +410,7 @@ export default class ImageControl extends React.Component<
// file 是个非 File 对象先不copy了直接改。 // file 是个非 File 对象先不copy了直接改。
file.progress = progress; file.progress = progress;
this.setState({ this.setState({
files files: this.files = files
}); });
} }
) )
@ -428,7 +426,7 @@ export default class ImageControl extends React.Component<
if (this.resolve) { if (this.resolve) {
this.resolve( this.resolve(
this.state.files.some(file => file.state === 'error') this.files.some(file => file.state === 'error')
? '文件上传失败请重试' ? '文件上传失败请重试'
: null : null
); );
@ -440,13 +438,13 @@ export default class ImageControl extends React.Component<
} }
removeFile(file: FileValue, index: number) { removeFile(file: FileValue, index: number) {
const files = this.state.files.concat(); const files = this.files.concat();
files.splice(index, 1); files.splice(index, 1);
this.setState( this.setState(
{ {
files: files files: this.files = files
}, },
this.onChange this.onChange
); );
@ -455,7 +453,7 @@ export default class ImageControl extends React.Component<
editImage(index: number) { editImage(index: number) {
const {multiple} = this.props; const {multiple} = this.props;
const files = this.state.files; const files = this.files;
this.setState({ this.setState({
cropFile: { cropFile: {
@ -475,7 +473,7 @@ export default class ImageControl extends React.Component<
valueField valueField
} = this.props; } = this.props;
const files = this.state.files.filter( const files = this.files.filter(
file => file.state == 'uploaded' || file.state == 'init' file => file.state == 'uploaded' || file.state == 'init'
); );
@ -542,7 +540,7 @@ export default class ImageControl extends React.Component<
return; return;
} }
blob.id = gennerateId(); blob.id = guid();
files.push(blob); files.push(blob);
}); });
@ -577,7 +575,7 @@ export default class ImageControl extends React.Component<
} }
const {multiple, maxLength, maxSize, accept} = this.props; const {multiple, maxLength, maxSize, accept} = this.props;
let currentFiles = this.state.files; let currentFiles = this.files;
if (!multiple && currentFiles.length) { if (!multiple && currentFiles.length) {
currentFiles = []; currentFiles = [];
@ -604,9 +602,9 @@ export default class ImageControl extends React.Component<
} }
file.state = 'pending'; file.state = 'pending';
file.id = gennerateId(); file.id = guid();
if (!file.preview || !file.url) { if (!file.preview || !file.url) {
file.preview = window.URL.createObjectURL(file); file.preview = URL.createObjectURL(file);
} }
inputFiles.push(file); inputFiles.push(file);
}); });
@ -618,7 +616,7 @@ export default class ImageControl extends React.Component<
this.setState( this.setState(
{ {
error: undefined, error: undefined,
files: currentFiles.concat(inputFiles), files: this.files = currentFiles.concat(inputFiles),
locked: true locked: true
}, },
() => { () => {
@ -769,7 +767,7 @@ export default class ImageControl extends React.Component<
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
delete img.onload; delete img.onload;
const files = this.state.files.concat(); const files = this.files.concat();
const file = files[index]; const file = files[index];
if (!file) { if (!file) {
@ -789,7 +787,7 @@ export default class ImageControl extends React.Component<
this.setState( this.setState(
{ {
files: files files: this.files = files
}, },
!needUploading ? this.onChange : undefined !needUploading ? this.onChange : undefined
); );
@ -802,13 +800,13 @@ export default class ImageControl extends React.Component<
return this.state.lockedReason; return this.state.lockedReason;
} else if ( } else if (
this.state.uploading || this.state.uploading ||
this.state.files.some(item => item.state === 'pending') this.files.some(item => item.state === 'pending')
) { ) {
return new Promise(resolve => { return new Promise(resolve => {
this.resolve = resolve; this.resolve = resolve;
this.startUpload(); this.startUpload();
}); });
} else if (this.state.files.some(item => item.state === 'error')) { } else if (this.files.some(item => item.state === 'error')) {
return '文件上传失败请重试'; return '文件上传失败请重试';
} }
} }
@ -890,7 +888,7 @@ export default class ImageControl extends React.Component<
'is-reject': isDragReject 'is-reject': isDragReject
})} })}
> >
</div> </div>
) : ( ) : (
<> <>
@ -962,7 +960,7 @@ export default class ImageControl extends React.Component<
this, this,
key key
)} )}
src={file.url || file.preview} src={file.preview || file.url}
alt={file.name} alt={file.name}
/> />
</div> </div>
@ -973,11 +971,11 @@ export default class ImageControl extends React.Component<
> >
{file.info ? ( {file.info ? (
[ [
<div key="1"> <div key="info">
{file.info.width} x {file.info.height} {file.info.width} x {file.info.height}
</div>, </div>,
file.info.len ? ( file.info.len ? (
<div key="2"> <div key="size">
{ImageControl.formatFileSize( {ImageControl.formatFileSize(
file.info.len file.info.len
)} )}
@ -1020,6 +1018,13 @@ export default class ImageControl extends React.Component<
<Icon icon="remove" className="icon" /> <Icon icon="remove" className="icon" />
</a> </a>
) : null} ) : null}
<a
data-tooltip={getNameFromUrl(file.value)}
data-position="bottom"
target="_blank"
>
<Icon icon="info" className="icon" />
</a>
</div> </div>
</> </>
)} )}