import BaseMixin from '../_util/BaseMixin'; import { getOptionProps, initDefaultProps } from '../_util/props-util'; import getTransitionProps from '../_util/getTransitionProps'; import { ConfigConsumerProps } from '../config-provider'; import Icon from '../icon'; import Tooltip from '../tooltip'; import Progress from '../progress'; import classNames from 'classnames'; import { UploadListProps } from './interface'; const imageTypes = ['image', 'webp', 'png', 'svg', 'gif', 'jpg', 'jpeg', 'bmp', 'dpg', 'ico']; // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL const previewFile = (file, callback) => { if (file.type && !imageTypes.includes(file.type)) { callback(''); } const reader = new window.FileReader(); reader.onloadend = () => callback(reader.result); reader.readAsDataURL(file); }; const extname = url => { if (!url) { return ''; } const temp = url.split('/'); const filename = temp[temp.length - 1]; const filenameWithoutSuffix = filename.split(/#|\?/)[0]; return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0]; }; const isImageUrl = file => { if (imageTypes.includes(file.type)) { return true; } const url = file.thumbUrl || file.url; const extension = extname(url); if (/^data:image\//.test(url) || /(webp|svg|png|gif|jpg|jpeg|bmp|dpg|ico)$/i.test(extension)) { return true; } else if (/^data:/.test(url)) { // other file types of base64 return false; } else if (extension) { // other file types which have extension return false; } return true; }; export default { name: 'AUploadList', mixins: [BaseMixin], props: initDefaultProps(UploadListProps, { listType: 'text', // or picture progressAttr: { strokeWidth: 2, showInfo: false, }, showRemoveIcon: true, showPreviewIcon: true, }), inject: { configProvider: { default: () => ({}) }, }, updated() { this.$nextTick(() => { if (this.listType !== 'picture' && this.listType !== 'picture-card') { return; } (this.items || []).forEach(file => { if ( typeof document === 'undefined' || typeof window === 'undefined' || !window.FileReader || !window.File || !(file.originFileObj instanceof window.File) || file.thumbUrl !== undefined ) { return; } /*eslint-disable */ file.thumbUrl = ''; /*eslint -enable */ previewFile(file.originFileObj, previewDataUrl => { /*eslint-disable */ file.thumbUrl = previewDataUrl; /*eslint -enable todo */ // this.forceUpdate() }); }); }); }, methods: { handleClose(file) { this.$emit('remove', file); }, handlePreview(file, e) { const { preview } = this.$listeners; if (!preview) { return; } e.preventDefault(); return this.$emit('preview', file); }, }, render() { const { prefixCls: customizePrefixCls, items = [], listType, showPreviewIcon, showRemoveIcon, locale, } = getOptionProps(this); const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls; const prefixCls = getPrefixCls('upload', customizePrefixCls); const list = items.map(file => { let progress; let icon = ; if (listType === 'picture' || listType === 'picture-card') { if (listType === 'picture-card' && file.status === 'uploading') { icon =
{locale.uploading}
; } else if (!file.thumbUrl && !file.url) { icon = ; } else { const thumbnail = isImageUrl(file) ? ( {file.name} ) : ( ); icon = ( this.handlePreview(file, e)} href={file.url || file.thumbUrl} target="_blank" rel="noopener noreferrer" > {thumbnail} ); } } if (file.status === 'uploading') { const progressProps = { props: { ...this.progressAttr, type: 'line', percent: file.percent, }, }; // show loading icon if upload progress listener is disabled const loadingProgress = 'percent' in file ? : null; progress = (
{loadingProgress}
); } const infoUploadingClass = classNames({ [`${prefixCls}-list-item`]: true, [`${prefixCls}-list-item-${file.status}`]: true, }); const linkProps = typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps; const preview = file.url ? ( this.handlePreview(file, e)} > {file.name} ) : ( this.handlePreview(file, e)} title={file.name} > {file.name} ); const style = file.url || file.thumbUrl ? undefined : { pointerEvents: 'none', opacity: 0.5, }; const previewIcon = showPreviewIcon ? ( this.handlePreview(file, e)} title={locale.previewFile} > ) : null; const iconProps = { props: { type: 'delete', title: locale.removeFile, }, on: { click: () => { this.handleClose(file); }, }, }; const iconProps1 = { ...iconProps, ...{ props: { type: 'close' } } }; const removeIcon = showRemoveIcon ? : null; const removeIconClose = showRemoveIcon ? : null; const actions = listType === 'picture-card' && file.status !== 'uploading' ? ( {previewIcon} {removeIcon} ) : ( removeIconClose ); let message; if (file.response && typeof file.response === 'string') { message = file.response; } else { message = (file.error && file.error.statusText) || locale.uploadError; } const iconAndPreview = file.status === 'error' ? ( {icon} {preview} ) : ( {icon} {preview} ); const transitionProps = getTransitionProps('fade'); return (
{iconAndPreview}
{actions} {progress}
); }); const listClassNames = classNames({ [`${prefixCls}-list`]: true, [`${prefixCls}-list-${listType}`]: true, }); const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate'; const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`); return ( {list} ); }, };