ant-design-vue/components/upload/UploadList.jsx
tangjinzhou ff25efe185
update to antd3.8.3 (#159)
* refactor: align

* feat:  update align to 2.4.3

* feat: update trigger 2.5.4

* feat: update tooltip 3.7.2

* fix: align

* feat: update vc-calendar to 9.6.2

* feat: update vc-checkbox to 2.1.5

* feat: update vc-dialog to 7.1.8

* feat: update vc-from to 2.2.1

* feat: update vc-notification to 3.1.1

* test: update snapshots

* feat: update vc-tree to 1.12.6

* feat: update vc-table to 6.2.8

* feat: update vc-upload to 2.5.1

* feat: update vc-input-number to 4.0.12

* feat: update vc-tabs to 9.2.6

* refactor: vc-menu

* refactor: update vc-menu to 7.0.5

* style: remove unused

* feat: update pagination to 1.16.5

* feat: add vc-progress 2.2.5 tag

* feat: add vc-rate 2.4.0 tag

* feat: update vc-slider to 8.6.1

* fix: tooltip error

* style: delete conosle

* feat: update vc-steps to 3.1.1

* add vc-switch tag 1.6.0

* feat: update upload to 2.5.1

* fix: update vc-menu

* fix: update store

* fix: add ref dir

* fix: trigger mock shouldComponentUpdate

* fix: update vc-select

* revert: trigger lazyrenderbox

* fix: update vc-select

* fix: update vc-select

* fix: update vc-select

* fix: update vc-menu

* fix: update vc-slick ref

* update style to 3.8.2

* test: update snapshots

* update vc-select

* update util & affix

* feat: add drawer

* fix: support title add slot mode

* test: update affix test

* update alert

* update anchor

* update snapshots

* fix: doc and vc-drawer

* update select & auto-complete

* update back-top & grid

* feractor: avatar

* test: add drawer test

* update badge

* update button

* update card

* update divider

* feat: update vc-tabs to 9.3.6 and tabs

* add afterEnter callback

* update form

* fix: update drawer

* test: update snapshots

* update modal & notification

* test: update snapshots

* update message

* update locale-provider

* update dropdown

* update layout popconfirm popover

* update time-picker

* update menu

* update date-picker

* docs: update input docs

* update input

* update snapshots

* update table

* update test snapshots

* feat: update progress

* update checkbox

* feat: update spin

* update radio

* docs: slider steps timeline

* update list

* update transfer

* update collapse

* update cascader

* update upload
2018-09-05 21:28:54 +08:00

249 lines
7.5 KiB
Vue

import BaseMixin from '../_util/BaseMixin'
import { getOptionProps, initDefaultProps } from '../_util/props-util'
import getTransitionProps from '../_util/getTransitionProps'
import Icon from '../icon'
import Tooltip from '../tooltip'
import Progress from '../progress'
import classNames from 'classnames'
import { UploadListProps } from './interface'
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
const previewFile = (file, 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 imageTypes = ['image', 'webp', 'png', 'svg', 'gif', 'jpg', 'jpeg', 'bmp']
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)$/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,
},
prefixCls: 'ant-upload',
showRemoveIcon: true,
showPreviewIcon: true,
}),
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, items = [], listType, showPreviewIcon, showRemoveIcon, locale } = getOptionProps(this)
const list = items.map(file => {
let progress
let icon = <Icon type={file.status === 'uploading' ? 'loading' : 'paper-clip'} />
if (listType === 'picture' || listType === 'picture-card') {
if (listType === 'picture-card' && file.status === 'uploading') {
icon = <div class={`${prefixCls}-list-item-uploading-text`}>{locale.uploading}</div>
} else if (!file.thumbUrl && !file.url) {
icon = <Icon class={`${prefixCls}-list-item-thumbnail`} type='picture' />
} else {
const thumbnail = isImageUrl(file) ? (
<img src={file.thumbUrl || file.url} alt={file.name} />
) : (
<Icon
type='file'
style={{ fontSize: '48px', color: 'rgba(0,0,0,0.5)' }}
/>
)
icon = (
<a
class={`${prefixCls}-list-item-thumbnail`}
onClick={e => this.handlePreview(file, e)}
href={file.url || file.thumbUrl}
target='_blank'
rel='noopener noreferrer'
>
{thumbnail}
</a>
)
}
}
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) ? (
<Progress {...progressProps} />
) : null
progress = (
<div class={`${prefixCls}-list-item-progress`} key='progress'>
{loadingProgress}
</div>
)
}
const infoUploadingClass = classNames({
[`${prefixCls}-list-item`]: true,
[`${prefixCls}-list-item-${file.status}`]: true,
})
const preview = file.url ? (
<a
{...file.linkProps}
href={file.url}
target='_blank'
rel='noopener noreferrer'
class={`${prefixCls}-list-item-name`}
onClick={e => this.handlePreview(file, e)}
title={file.name}
>
{file.name}
</a>
) : (
<span
class={`${prefixCls}-list-item-name`}
onClick={e => this.handlePreview(file, e)}
title={file.name}
>
{file.name}
</span>
)
const style = (file.url || file.thumbUrl) ? undefined : {
pointerEvents: 'none',
opacity: 0.5,
}
const previewIcon = showPreviewIcon ? (
<a
href={file.url || file.thumbUrl}
target='_blank'
rel='noopener noreferrer'
style={style}
onClick={e => this.handlePreview(file, e)}
title={locale.previewFile}
>
<Icon type='eye-o' />
</a>
) : null
const iconProps = {
props: {
type: 'delete',
title: locale.removeFile,
},
on: {
click: () => {
this.handleClose(file)
}
},
}
const iconProps1 = {...iconProps, ...{props: {type: 'cross'}}}
const removeIcon = showRemoveIcon ? (
<Icon {...iconProps} />
) : null
const removeIconCross = showRemoveIcon ? (
<Icon {...iconProps1}/>
) : null
const actions = (listType === 'picture-card' && file.status !== 'uploading')
? <span class={`${prefixCls}-list-item-actions`}>{previewIcon}{removeIcon}</span>
: removeIconCross
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')
? <Tooltip title={message}>{icon}{preview}</Tooltip>
: <span>{icon}{preview}</span>
const transitionProps = getTransitionProps('fade')
return (
<div class={infoUploadingClass} key={file.uid}>
<div class={`${prefixCls}-list-item-info`}>
{iconAndPreview}
</div>
{actions}
<transition {...transitionProps}>
{progress}
</transition>
</div>
)
})
const listClassNames = classNames({
[`${prefixCls}-list`]: true,
[`${prefixCls}-list-${listType}`]: true,
})
const animationDirection =
listType === 'picture-card' ? 'animate-inline' : 'animate'
const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`)
return (
<transition-group
{...transitionGroupProps}
tag='div'
class={listClassNames}
>
{list}
</transition-group>
)
},
}