feat: update upload

pull/309/head
wangxueliang 2018-12-05 18:31:58 +08:00
parent e51a6e9691
commit 44d55b329d
9 changed files with 77 additions and 12 deletions

View File

@ -48,10 +48,15 @@ export default {
}, },
methods: { methods: {
onStart (file) { onStart (file) {
const nextFileList = this.sFileList.concat()
const targetItem = fileToObject(file) const targetItem = fileToObject(file)
targetItem.status = 'uploading' targetItem.status = 'uploading'
nextFileList.push(targetItem) const nextFileList = this.sFileList.concat()
const fileIndex = nextFileList.findIndex(({ uid }) => uid === targetItem.uid)
if (fileIndex === -1) {
nextFileList.push(targetItem)
} else {
nextFileList[fileIndex] = targetItem
}
this.onChange({ this.onChange({
file: targetItem, file: targetItem,
fileList: nextFileList, fileList: nextFileList,

View File

@ -7,8 +7,12 @@ import Progress from '../progress'
import classNames from 'classnames' import classNames from 'classnames'
import { UploadListProps } from './interface' import { UploadListProps } from './interface'
const imageTypes = ['image', 'webp', 'png', 'svg', 'gif', 'jpg', 'jpeg', 'bmp']
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
const previewFile = (file, callback) => { const previewFile = (file, callback) => {
if (file.type && !imageTypes.includes(file.type)) {
callback('')
}
const reader = new window.FileReader() const reader = new window.FileReader()
reader.onloadend = () => callback(reader.result) reader.onloadend = () => callback(reader.result)
reader.readAsDataURL(file) reader.readAsDataURL(file)
@ -23,7 +27,7 @@ const extname = (url) => {
const filenameWithoutSuffix = filename.split(/#|\?/)[0] const filenameWithoutSuffix = filename.split(/#|\?/)[0]
return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0] return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0]
} }
const imageTypes = ['image', 'webp', 'png', 'svg', 'gif', 'jpg', 'jpeg', 'bmp']
const isImageUrl = (file) => { const isImageUrl = (file) => {
if (imageTypes.includes(file.type)) { if (imageTypes.includes(file.type)) {
return true return true
@ -148,15 +152,17 @@ export default {
[`${prefixCls}-list-item`]: true, [`${prefixCls}-list-item`]: true,
[`${prefixCls}-list-item-${file.status}`]: true, [`${prefixCls}-list-item-${file.status}`]: true,
}) })
const linkProps = typeof file.linkProps === 'string'
? JSON.parse(file.linkProps) : file.linkProps
const preview = file.url ? ( const preview = file.url ? (
<a <a
{...file.linkProps}
href={file.url}
target='_blank' target='_blank'
rel='noopener noreferrer' rel='noopener noreferrer'
class={`${prefixCls}-list-item-name`} class={`${prefixCls}-list-item-name`}
onClick={e => this.handlePreview(file, e)}
title={file.name} title={file.name}
{...linkProps}
href={file.url}
onClick={e => this.handlePreview(file, e)}
> >
{file.name} {file.name}
</a> </a>
@ -196,16 +202,16 @@ export default {
} }
}, },
} }
const iconProps1 = {...iconProps, ...{props: {type: 'cross'}}} const iconProps1 = {...iconProps, ...{props: {type: 'close'}}}
const removeIcon = showRemoveIcon ? ( const removeIcon = showRemoveIcon ? (
<Icon {...iconProps} /> <Icon {...iconProps} />
) : null ) : null
const removeIconCross = showRemoveIcon ? ( const removeIconClose = showRemoveIcon ? (
<Icon {...iconProps1}/> <Icon {...iconProps1}/>
) : null ) : null
const actions = (listType === 'picture-card' && file.status !== 'uploading') const actions = (listType === 'picture-card' && file.status !== 'uploading')
? <span class={`${prefixCls}-list-item-actions`}>{previewIcon}{removeIcon}</span> ? <span class={`${prefixCls}-list-item-actions`}>{previewIcon}{removeIcon}</span>
: removeIconCross : removeIconClose
let message let message
if (file.response && typeof file.response === 'string') { if (file.response && typeof file.response === 'string') {
message = file.response message = file.response

View File

@ -176,4 +176,55 @@ describe('Upload', () => {
}) })
}) })
}) })
it('should support linkProps as object', () => {
const fileList = [{
uid: '-1',
name: 'foo.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
linkProps: {
download: 'image',
rel: 'noopener',
},
}]
const props = {
propsData: {
fileList,
},
sync: false,
}
const wrapper = mount(Upload, props)
setTimeout(() => {
const linkNode = wrapper.find('a.ant-upload-list-item-name')
expect(linkNode.props().download).toBe('image')
expect(linkNode.props().rel).toBe('noopener')
}, 0)
})
it('should support linkProps as json stringify', () => {
const linkPropsString = JSON.stringify({
download: 'image',
rel: 'noopener',
})
const fileList = [{
uid: '-1',
name: 'foo.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png',
linkProps: linkPropsString,
}]
const props = {
propsData: {
fileList,
},
sync: false,
}
const wrapper = mount(Upload, props)
setTimeout(() => {
const linkNode = wrapper.find('a.ant-upload-list-item-name')
expect(linkNode.props().download).toBe('image')
expect(linkNode.props().rel).toBe('noopener')
}, 0)
})
}) })

View File

@ -76,7 +76,7 @@ describe('Upload List', () => {
const wrapper = mount(Upload, props) const wrapper = mount(Upload, props)
setTimeout(async () => { setTimeout(async () => {
expect(wrapper.findAll('.ant-upload-list-item').length).toBe(2) expect(wrapper.findAll('.ant-upload-list-item').length).toBe(2)
wrapper.findAll('.ant-upload-list-item').at(0).find('.anticon-cross').trigger('click') wrapper.findAll('.ant-upload-list-item').at(0).find('.anticon-close').trigger('click')
await delay(400) await delay(400)
// wrapper.update(); // wrapper.update();
expect(wrapper.findAll('.ant-upload-list-item').length).toBe(1) expect(wrapper.findAll('.ant-upload-list-item').length).toBe(1)

View File

@ -1,7 +1,7 @@
<cn> <cn>
#### 用户头像 #### 用户头像
点击上传用户头像,并使用 `beforeUpload` 限制用户上传的图片格式和大小。 点击上传用户头像,并使用 `beforeUpload` 限制用户上传的图片格式和大小。
`beforeUpload` 的返回值可以是一个 Promise 以支持也支持异步检查 `beforeUpload` 的返回值可以是一个 Promise 以支持异步处理,如服务端校验等
</cn> </cn>
<us> <us>

View File

@ -20,6 +20,7 @@
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon` and `showRemoveIcon` individually | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true | | showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon` and `showRemoveIcon` individually | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true |
| supportServerRender | Need to be turned on while the server side is rendering. | boolean | false | | supportServerRender | Need to be turned on while the server side is rendering. | boolean | false |
| withCredentials | ajax upload with cookie sent | boolean | false | | withCredentials | ajax upload with cookie sent | boolean | false |
| openFileDialogOnClick | click open file dialog | boolean | true |
| remove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is `false` or a Promise which resolve(false) or reject. | Function(file): `boolean | Promise` | - | | remove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is `false` or a Promise which resolve(false) or reject. | Function(file): `boolean | Promise` | - |
### events ### events

View File

@ -20,6 +20,7 @@
| showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true | | showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true |
| supportServerRender | 服务端渲染时需要打开这个 | boolean | false | | supportServerRender | 服务端渲染时需要打开这个 | boolean | false |
| withCredentials | 上传请求时是否携带 cookie | boolean | false | | withCredentials | 上传请求时是否携带 cookie | boolean | false |
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true |
| remove   | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象Promise 对象 resolve(false) 或 reject 时不移除。               | Function(file): `boolean | Promise` | 无   | | remove   | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象Promise 对象 resolve(false) 或 reject 时不移除。               | Function(file): `boolean | Promise` | 无   |
### 事件 ### 事件

View File

@ -76,6 +76,7 @@ export const UploadProps = {
prefixCls: PropsTypes.string, prefixCls: PropsTypes.string,
customRequest: PropsTypes.func, customRequest: PropsTypes.func,
withCredentials: PropsTypes.bool, withCredentials: PropsTypes.bool,
openFileDialogOnClick: PropsTypes.bool,
locale: UploadLocale, locale: UploadLocale,
height: PropsTypes.number, height: PropsTypes.number,
} }

View File

@ -11,7 +11,7 @@ import Api from './components/api'
import './components' import './components'
import demoBox from './components/demoBox' import demoBox from './components/demoBox'
import demoContainer from './components/demoContainer' import demoContainer from './components/demoContainer'
import Test from '../components/avatar/demo/index' import Test from '../components/test/index.vue'
import zhCN from './theme/zh-CN' import zhCN from './theme/zh-CN'
import enUS from './theme/en-US' import enUS from './theme/en-US'
Vue.use(VueClipboard) Vue.use(VueClipboard)