qm-bus
Version:
千米公有云业务组件库
259 lines (242 loc) • 8.18 kB
JavaScript
import React, { Component } from 'react'
import { Form, Upload, Button, Icon, Input, message, Modal } from 'antd'
import { QMImg } from 'qm-ui'
import { QMConst, QMValidator } from 'qm-ux'
const FormItem = Form.Item
import { checkUrl } from '../webapi'
import assign from 'object-assign'
export default class Uploader extends Component {
static defaultProps = {
limit: 10, // 图片数量限制
rule: {
limit: 10, // 文件数量限制
size: 2, // 文件大小限制
filetype: 'jpeg,jpg,gif,png', // 支持的文件类型
msg: ({ limit, size, filetype }) =>
`图片格式仅支持:${filetype},且一次最多上传 ${limit}张,每张不能超过 ${size}MB!`,
},
}
constructor(props) {
super(props)
this.errorSet = new Set()
this.errorMsg = {
limit: ({ limit }) => `图片文件最多只能上传 ${limit}张!`,
type: ({ filetype }) => `图片文件格式仅支持:${filetype}!`,
size: ({ size }) => `图片文件大小不得超过 ${size}MB!`,
}
this.state = {
loading: false,
preview: false,
previewImage: '',
files: [],
linkAddress: '',
netImages: [],
videos: [],
}
}
_onPull = () => {
var _this = this
this.setState({ loading: true })
let url = this.state.linkAddress
if (url) {
if (QMValidator.protocolHead(url)) {
// 这里只校验协议头,防止有使用短连接的情况
checkUrl(encodeURIComponent(url)).then(
res => {
setTimeout(() => {
if (res.err) {
message.error(res.err.message)
_this.setState({ loading: false })
} else {
this.setState({
linkAddress: '',
loading: false,
netImages: this.state.netImages.concat([res.data]),
})
this.props.setNetImg(res.data)
}
}, 500)
},
res => {
_this.setState({ loading: false })
}
)
} else {
_this.setState({ loading: false })
message.error('请输入正确的图片地址')
}
} else {
_this.setState({ loading: false })
message.error('请输入图片地址')
}
}
_onNetImageDel = v => {
this.state.netImages.splice(v, 1)
this.setState({ netImages: this.state.netImages })
}
_onImageDel = file => {
this.state.files.splice(this.state.files.indexOf(file), 1)
this.setState({ files: this.state.files })
}
_onPreview = file => {
if (file.response) {
this.setState({ preview: true, previewImage: file.response.data[0].url })
} else {
this.setState({ preview: true, previewImage: file.url })
}
}
_onPreviewCancel = () => {
this.setState({ preview: false })
}
_onChange = ({ file, fileList }) => {
if (file.response && file.response.success && file.status == 'done') {
let url = file.response.data[0].url
if (fileList.filter(i => i.hash == url && i.response).length > 0) {
message.warning('图片已经上传过了.')
fileList.splice(fileList.indexOf(file), 1)
} else {
file.hash = url
file.url = url + '@100w_100h'
file.thumbUrl = url + '@100w_100h'
}
} else if (file.response && file.status == 'done') {
let _index = fileList.findIndex(f => f.uid == file.uid)
fileList.splice(_index, 1)
if (file.response.message) {
message.error(file.response.message)
} else {
message.error('图片上传失败.')
}
}
this.setState({ files: fileList })
this.props.setImg(this.state.files)
}
/**
* 上传前校验
*/
onValidBeforeUpload = (file, files) => {
let { limit, rule } = this.props
let { size, filetype, limit: pic_limit } = rule
limit = pic_limit || limit
let index = files.indexOf(file)
let name = file.name.toLowerCase()
try {
// 1.数量校验
if (this.state.files.length + index > limit - 1) {
this.errorSet.add('limit')
throw new Error(limit)
}
// 2.文件类型校验
if (!(new RegExp(filetype.split(',').join('|')).test(name) || /^image/gi.test(file.type))) {
this.errorSet.add('type')
throw new Error(limit)
}
// 3.文件大小校验
if (file.size > 1024 * 1024 * size) {
this.errorSet.add('size')
throw new Error(limit)
}
return true
} catch (e) {
return false
} finally {
if (index === files.length - 1) {
let i = 0
for (let s of this.errorSet) {
message.config({
top: 20 + 40 * i++,
duration: 5,
})
message.error(this.errorMsg[s]({ limit, filetype, size }))
}
this.errorSet.clear()
}
}
}
_onLinkAddressChange = e => this.setState({ linkAddress: e.target.value })
render() {
let { formLayout, headers, limit, rule } = this.props
let { msg, filetype, size, limit: pic_limit } = rule
limit = pic_limit || limit
if (msg && typeof msg === 'function') {
msg = msg({ limit, filetype, size })
}
return (
<Form>
<FormItem {...formLayout} label="网络图片">
<Input
ref="picture-link"
type="text"
value={this.state.linkAddress}
placeholder="请输入图片链接地址"
disabled={this.state.netImages.length >= 5}
onChange={this._onLinkAddressChange}
/>
<Button
className="pushl"
size="large"
loading={!!this.state.loading}
disabled={this.state.netImages.size >= 5}
onClick={this._onPull}>
提取
</Button>
<div className="network-img-preview">
<div className="ant-upload-list ant-upload-list-picture-card">
{this.state.netImages.map((i, v) => (
<div
className="ant-upload-list-item ant-upload-list-item-done"
key={v + '_' + i.url}>
<div className="ant-upload-list-item-info">
<a
className="ant-upload-list-item-thumbnail"
href={QMImg.src({ src: i.url })}
target="_blank">
<img src={QMImg.src({ src: i.url })} alt={i.name} title={i.name} />
</a>
<span>
<Icon type="eye-o" onClick={this._onPreview.bind(this, i)} />
<Icon
title="Remove file"
type="delete"
onClick={this._onNetImageDel.bind(this, v)}
/>
</span>
</div>
</div>
))}
</div>
</div>
</FormItem>
<FormItem
{...formLayout}
label="本地图片"
help={<span dangerouslySetInnerHTML={{ __html: msg }}></span>}>
<div className="local-img-preview clearfix">
<Upload
action={QMConst.HOST['v_upload_api'] + '/api/upload/image'}
headers={headers}
multiple
onPreview={this._onPreview}
fileList={this.state.files.map(i =>
assign({}, i, { url: QMImg.src({ src: i.url }) })
)}
onChange={this._onChange}
listType="picture-card"
beforeUpload={this.onValidBeforeUpload}
withCredentials={true}
onRemove={this._onImageDel}>
{this.state.files.length < limit ? (
<div>
<Icon type="plus" />
</div>
) : null}
</Upload>
</div>
<Modal visible={this.state.preview} footer={null} onCancel={this._onPreviewCancel}>
<QMImg alt="example" style={{ width: '100%' }} src={this.state.previewImage} />
</Modal>
</FormItem>
</Form>
)
}
}