jc-biz-components
Version:
jc component library based on Antd
246 lines (234 loc) • 7.29 kB
JavaScript
import React from 'react'
import Animate from 'rc-animate'
import { Tooltip, Progress, Icon } from 'antd'
import classNames from 'classnames'
// import styles from './index.less'
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
const previewFile = (file, callback) => {
const reader = new FileReader()
reader.onloadend = () => callback(reader.result)
reader.readAsDataURL(file)
}
export default class UploadList extends React.Component {
static defaultProps = {
listType: 'text', // or picture
progressAttr: {
strokeWidth: 2,
showInfo: false,
},
prefixCls: 'ant-upload',
showRemoveIcon: true,
showPreviewIcon: true,
prefixCls2: 'jc-upload'
}
handleClose = (file) => {
const { onRemove } = this.props
if (onRemove) {
onRemove(file)
}
}
handlePreview = (file, e) => {
const { onPreview } = this.props
if (!onPreview) {
return
}
e.preventDefault()
return onPreview(file)
}
componentDidUpdate() {
if (this.props.listType !== 'picture' && this.props.listType !== 'picture-card') {
return
}
(this.props.items || []).forEach(file => {
if (typeof document === 'undefined' ||
typeof window === 'undefined' ||
!(window).FileReader || !(window).File ||
!(file.originFileObj instanceof File) ||
file.thumbUrl !== undefined) {
return
}
/*eslint-disable */
file.thumbUrl = ''
/*eslint-enable */
previewFile(file.originFileObj, (previewDataUrl) => {
/*eslint-disable */
file.thumbUrl = previewDataUrl
/*eslint-enable */
this.forceUpdate()
})
})
}
render() {
const { prefixCls, prefixCls2, items = [], listType, showPreviewIcon, showRemoveIcon, locale, needOrder, reUploadRender } = this.props
const list = items.map((file, index) => {
let progress = null
let icon = <Icon type={file.status === 'uploading' ? 'loading' : 'paper-clip'} />
if (listType === 'picture' || listType === 'picture-card') {
if (file.status === 'uploading' || (!file.thumbUrl && !file.url)) {
if (listType === 'picture-card') {
icon = <div className={`${prefixCls}-list-item-uploading-text`}>{locale.uploading}</div>
} else {
icon = (<Icon
className={`${prefixCls}-list-item-thumbnail`}
type='picture'
/>)
}
} else {
icon = (
<a
className={`${prefixCls}-list-item-thumbnail`}
onClick={e => this.handlePreview(file, e)}
href={file.url || file.thumbUrl}
target='_blank'
rel='noopener noreferrer'
>
<img
src={file.thumbUrl || file.url}
alt={file.name}
/>
</a>
)
}
}
if (file.status === 'uploading') {
// show loading icon if upload progress listener is disabled
const loadingProgress = ('percent' in file) ? (
<Progress
type='line'
{...this.props.progressAttr}
percent={file.percent}
/>
) : null
progress = (
<div
className={`${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
href={file.url}
target='_blank'
rel='noopener noreferrer'
className={`${prefixCls}-list-item-name`}
onClick={e => this.handlePreview(file, e)}
title={file.name}
>
{file.name}
</a>
) : (
<span
className={`${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 removeIcon = showRemoveIcon ? (
<Icon
type='delete'
title={locale.removeFile}
onClick={() => this.handleClose(file)}
/>
) : null
const removeIconCross = showRemoveIcon ? (
<Icon
type='cross'
title={locale.removeFile}
onClick={() => this.handleClose(file)}
/>
) : null
const actions = (listType === 'picture-card' && file.status !== 'uploading')
? <span className={`${prefixCls}-list-item-actions`}>{previewIcon}{reUploadRender(index)}{removeIcon}</span>
: removeIconCross
let message = null
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 isNeedOrder = needOrder && file.status === 'done'
const isNeedOrder = needOrder
return (
<div
key={file.uid}
style={{ float: 'left' }}
>
<div className={infoUploadingClass}>
<div className={`${prefixCls}-list-item-info`}>
{iconAndPreview}
</div>
{actions}
<Animate
transitionName='fade'
component=''
>
{progress}
</Animate>
</div>
{isNeedOrder && (
<span className={`${prefixCls2}-iconContainer`}>
<Icon
className={`${prefixCls2}-icon`}
style={{ paddingRight: 8 }}
type='left'
onClick={() => this.props.orderChange(file, 0)}
/>
<Icon
className={`${prefixCls2}-icon`}
style={{ paddingLeft: 8 }}
type='right'
onClick={() => this.props.orderChange(file, 1)}
/>
</span>
)}
</div>
)
})
// <Input size='small' onChange={e => {
// this.props.orderChange(file, e.target.value)
// }} />
const listClassNames = classNames({
[`${prefixCls}-list`]: true,
[`${prefixCls}-list-${listType}`]: true,
})
const animationDirection =
listType === 'picture-card' ? 'animate-inline' : 'animate'
return (
<Animate
transitionName={`${prefixCls}-${animationDirection}`}
component='div'
className={listClassNames}
>
{list}
</Animate>
)
}
}