/** * 上传图片弹框 */ import * as React from 'react'; import { Component } from 'react'; // use this only as type, @types/sortablejs and sortablejs cannot be used with `esModuleInterop: false` import * as Sortable from 'sortablejs'; import { Button, Input, Icon } from 'zent'; import FileInput from './FileInput'; import uploadLocalImage from './UploadLocal'; import UploadImageItem from './UploadImageItem'; import { initSortable, swapArray } from '../utils/sortable'; import { formatFileSize } from '../utils'; import { UID_KEY } from '../constants'; import Select from '../../select'; // use this as value // const SortableJS: typeof _SortableJS = (_SortableJS as any).default; class UploadPopup extends Component { static defaultProps = { networkImage: {}, networkUploading: false, buttonText: '', options: {}, className: '', }; networkUrl: string; sortable: Sortable; constructor(props) { super(props); this.state = { categoryId: props.options.categoryId, networkImage: props.networkImage, networkUploading: props.networkUploading, localUploading: props.localUploading, buttonText: props.i18n.popup.extract, // hacky localFiles: [], }; this.networkUrl = ''; this.confirmNetworkUrl = this.confirmNetworkUrl.bind(this); this.networkUrlChanged = this.networkUrlChanged.bind(this); this.uploadLocalImages = this.uploadLocalImages.bind(this); this.fileProgressHandler = this.fileProgressHandler.bind(this); this.setCategoryId = this.setCategoryId.bind(this); } render() { const { prefix, options, className } = this.props; const { categoryList } = options; return (
{categoryList.length > 0 && this.renderUploadGroup(this.props)} {!options.localOnly && options.type !== 'voice' && this.renderNetworkRegion(this.props)} {this.renderLocalUploadRegion(this.props)}
{this.renderFooterRegion()}
); } setCategoryId(evt, data) { this.setState({ categoryId: data.id }); } /** * 渲染上传分组 */ renderUploadGroup(props) { const { prefix, i18n, options: { categoryList }, } = props; const { categoryId } = this.state; return (
{i18n.popup.group}:
); } // 上传图片列表 renderLocalImage(item, index) { const { prefix } = this.props; return ( ); } // 上传语音列表 renderLocalVoice(item, index) { const { prefix } = this.props; return (
  • {item.file.name}
    {formatFileSize(item.file.size)}
    × {item.progress ? (
    {`${item.progress.toFixed(1)}%`}
    ) : ( '' )}
  • ); } /** * 本地上传图片、语音 */ renderLocalUploadRegion(props) { const { prefix, accept, options, i18n } = props; const { localFiles } = this.state; // 记录最后一项的索引 let lastIndex = 0; const filesLength = localFiles.length; if (filesLength > 0) { // 保证新添加的都是在旧添加的文件后面 lastIndex = localFiles[filesLength - 1][UID_KEY] + 1; } return (
    {`${ i18n.popup[`title_${options.type}`] }:`}
    {filesLength > 0 && (
      {localFiles.map((item, index) => { return options.type === 'voice' ? this.renderLocalVoice(item, index) : this.renderLocalImage(item, index); })}
    )} {!options.maxAmount || localFiles.length < options.maxAmount ? (
    ) : ( '' )}
    {i18n.popup.type({ types: accept.replace(/image\/?|audio\/?/g, '').split(','), size: formatFileSize(options.maxSize), })}
    ); } renderFooterRegion() { const { localUploading, localFiles } = this.state; const { i18n, prefix } = this.props; return (
    ); } handleMove = (fromIndex, toIndex) => { let { localFiles } = this.state; localFiles = swapArray(localFiles, fromIndex, toIndex); this.setState({ localFiles, }); }; handleDelete = index => { const { localFiles } = this.state; localFiles.splice(index, 1); this.setState({ localFiles, }); }; uploadLocalImages() { const { options, showUploadPopup } = this.props; const { localFiles, categoryId } = this.state; this.setState({ localUploading: true, }); uploadLocalImage(options, { localFiles, categoryId, onProgress: this.fileProgressHandler, }) .then(() => { this.setState({ localUploading: false, }); showUploadPopup(false); }) .catch(() => { this.setState({ localUploading: false, }); }); } networkUrlChanged(evt) { this.networkUrl = evt.target.value; } fileProgressHandler(progress, index) { const { localFiles } = this.state; // 上传过程中删除预览小图 const fileIndex = localFiles.findIndex(file => file[UID_KEY] === index); if (fileIndex >= 0) { localFiles[fileIndex].progress = progress; } this.setState(localFiles); } handleChange = files => { let { localFiles } = this.state; localFiles = localFiles.concat(files); // 根据索引进行排序,防止读取文件导致顺序错乱 localFiles.sort((a, b) => (a[UID_KEY] > b[UID_KEY] ? 1 : -1)); this.setState({ localFiles, }); }; /** * 提取网络图片 */ confirmNetworkUrl() { const { options, showUploadPopup, i18n } = this.props; const { categoryId } = this.state; if (!this.networkUrl) return false; this.setState({ networkUploading: true, buttonText: i18n.popup.extracting, }); return options.onFetch(this.networkUrl, categoryId).then( () => { this.setState({ networkImage: {}, networkUploading: false, buttonText: i18n.popup.extract, }); showUploadPopup(false); }, () => { this.setState({ networkUploading: false, buttonText: i18n.popup.extract, }); } ); } onListRefChange = list => { if (list) { this.sortable = initSortable(list, this.handleMove); } else { this.sortable && this.sortable.destroy(); } }; } export default UploadPopup;