diff --git a/components/upload/Upload.jsx b/components/upload/Upload.jsx index bc154b126..9bbba11c3 100644 --- a/components/upload/Upload.jsx +++ b/components/upload/Upload.jsx @@ -48,10 +48,15 @@ export default { }, methods: { onStart (file) { - const nextFileList = this.sFileList.concat() const targetItem = fileToObject(file) 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({ file: targetItem, fileList: nextFileList, diff --git a/components/upload/UploadList.jsx b/components/upload/UploadList.jsx index 2d73dcbbd..ce566651b 100644 --- a/components/upload/UploadList.jsx +++ b/components/upload/UploadList.jsx @@ -7,8 +7,12 @@ import Progress from '../progress' import classNames from 'classnames' 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 const previewFile = (file, callback) => { + if (file.type && !imageTypes.includes(file.type)) { + callback('') + } const reader = new window.FileReader() reader.onloadend = () => callback(reader.result) reader.readAsDataURL(file) @@ -23,7 +27,7 @@ const extname = (url) => { 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 @@ -148,15 +152,17 @@ export default { [`${prefixCls}-list-item`]: true, [`${prefixCls}-list-item-${file.status}`]: true, }) + const linkProps = typeof file.linkProps === 'string' + ? JSON.parse(file.linkProps) : file.linkProps const preview = file.url ? ( this.handlePreview(file, e)} title={file.name} + {...linkProps} + href={file.url} + onClick={e => this.handlePreview(file, e)} > {file.name} @@ -196,16 +202,16 @@ export default { } }, } - const iconProps1 = {...iconProps, ...{props: {type: 'cross'}}} + const iconProps1 = {...iconProps, ...{props: {type: 'close'}}} const removeIcon = showRemoveIcon ? ( ) : null - const removeIconCross = showRemoveIcon ? ( + const removeIconClose = showRemoveIcon ? ( ) : null const actions = (listType === 'picture-card' && file.status !== 'uploading') ? {previewIcon}{removeIcon} - : removeIconCross + : removeIconClose let message if (file.response && typeof file.response === 'string') { message = file.response diff --git a/components/upload/__tests__/upload.test.js b/components/upload/__tests__/upload.test.js index 0f9cf3d80..b74c0db93 100644 --- a/components/upload/__tests__/upload.test.js +++ b/components/upload/__tests__/upload.test.js @@ -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) + }) }) diff --git a/components/upload/__tests__/uploadlist.test.js b/components/upload/__tests__/uploadlist.test.js index 2d8b784db..3624df8a1 100644 --- a/components/upload/__tests__/uploadlist.test.js +++ b/components/upload/__tests__/uploadlist.test.js @@ -76,7 +76,7 @@ describe('Upload List', () => { const wrapper = mount(Upload, props) setTimeout(async () => { 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) // wrapper.update(); expect(wrapper.findAll('.ant-upload-list-item').length).toBe(1) diff --git a/components/upload/demo/avatar.md b/components/upload/demo/avatar.md index 6097971ca..38ce83eb0 100644 --- a/components/upload/demo/avatar.md +++ b/components/upload/demo/avatar.md @@ -1,7 +1,7 @@ #### 用户头像 点击上传用户头像,并使用 `beforeUpload` 限制用户上传的图片格式和大小。 -`beforeUpload` 的返回值可以是一个 Promise 以支持也支持异步检查 +`beforeUpload` 的返回值可以是一个 Promise 以支持异步处理,如服务端校验等 diff --git a/components/upload/index.en-US.md b/components/upload/index.en-US.md index af6752cec..949a35bec 100644 --- a/components/upload/index.en-US.md +++ b/components/upload/index.en-US.md @@ -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 | | supportServerRender | Need to be turned on while the server side is rendering. | 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` | - | ### events diff --git a/components/upload/index.zh-CN.md b/components/upload/index.zh-CN.md index f10efc625..3e18f2b60 100644 --- a/components/upload/index.zh-CN.md +++ b/components/upload/index.zh-CN.md @@ -20,6 +20,7 @@ | showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true | | supportServerRender | 服务端渲染时需要打开这个 | boolean | false | | withCredentials | 上传请求时是否携带 cookie | boolean | false | +| openFileDialogOnClick | 点击打开文件对话框 | boolean | true | | remove   | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除。               | Function(file): `boolean | Promise` | 无   | ### 事件 diff --git a/components/upload/interface.jsx b/components/upload/interface.jsx index 179e3ad9f..8643ce484 100755 --- a/components/upload/interface.jsx +++ b/components/upload/interface.jsx @@ -76,6 +76,7 @@ export const UploadProps = { prefixCls: PropsTypes.string, customRequest: PropsTypes.func, withCredentials: PropsTypes.bool, + openFileDialogOnClick: PropsTypes.bool, locale: UploadLocale, height: PropsTypes.number, } diff --git a/site/dev.js b/site/dev.js index 290aada55..42db1aa8a 100644 --- a/site/dev.js +++ b/site/dev.js @@ -11,7 +11,7 @@ import Api from './components/api' import './components' import demoBox from './components/demoBox' 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 enUS from './theme/en-US' Vue.use(VueClipboard)