[new feature] Uploader: support preview non-image file (#3604)

This commit is contained in:
neverland 2019-06-22 15:39:49 +08:00 committed by GitHub
parent a27df2c25f
commit dea0d28361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 17 deletions

View File

@ -18,6 +18,7 @@
top: 0; top: 0;
left: 0; left: 0;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: @image-placeholder-text-color; color: @image-placeholder-text-color;

View File

@ -6,6 +6,10 @@ import ImagePreview from '../image-preview';
const [sfc, bem] = use('uploader'); const [sfc, bem] = use('uploader');
function isImageDataUrl(dataUrl) {
return dataUrl.indexOf('data:image') === 0;
}
export default sfc({ export default sfc({
inheritAttrs: false, inheritAttrs: false,
@ -136,10 +140,14 @@ export default sfc({
} }
}, },
onPreviewImage(startPosition) { onPreviewImage(item) {
const imageFiles = this.fileList
.map(item => item.content)
.filter(content => isImageDataUrl(content));
ImagePreview({ ImagePreview({
images: this.fileList.map(file => file.content), images: imageFiles,
startPosition startPosition: imageFiles.indexOf(item.content)
}); });
}, },
@ -148,23 +156,33 @@ export default sfc({
return; return;
} }
return this.fileList.map((file, index) => ( return this.fileList.map((item, index) => (
<div class={bem('preview')}> <div class={bem('preview')}>
<Image <Image
fit="cover" fit="cover"
src={file.content} src={item.content}
class={bem('preview-image')} class={bem('preview-image')}
width={this.previewSize} width={this.previewSize}
height={this.previewSize} height={this.previewSize}
scopedSlots={{
error() {
return [
<Icon class={bem('file-icon')} name="description" />,
<div class={[bem('file-name'), 'van-ellipsis']}>{item.file.name}</div>
];
}
}}
onClick={() => { onClick={() => {
this.onPreviewImage(index); if (isImageDataUrl(item.content)) {
this.onPreviewImage(item);
}
}} }}
/> />
<Icon <Icon
name="delete" name="delete"
class={bem('preview-delete')} class={bem('preview-delete')}
onClick={() => { onClick={() => {
this.onDelete(file, index); this.onDelete(item, index);
}} }}
/> />
</div> </div>

View File

@ -68,4 +68,19 @@
background-color: @uploader-delete-background-color; background-color: @uploader-delete-background-color;
} }
} }
&__file-icon {
color: @gray-darker;
font-size: 20px;
}
&__file-name {
box-sizing: border-box;
width: 100%;
margin-top: 5px;
padding: 0 5px;
color: @gray-darker;
font-size: 12px;
text-align: center;
}
} }

View File

@ -22,7 +22,7 @@ exports[`max-count prop 1`] = `
<div class="van-uploader"> <div class="van-uploader">
<div class="van-uploader__wrapper"> <div class="van-uploader__wrapper">
<div class="van-uploader__preview"> <div class="van-uploader__preview">
<div class="van-image van-uploader__preview-image"><img src="test" class="van-image__img" style="object-fit: cover;"> <div class="van-image van-uploader__preview-image"><img src="data:image/test" class="van-image__img" style="object-fit: cover;">
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;"> <div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;">
<!----></i></div> <!----></i></div>
</div><i class="van-icon van-icon-delete van-uploader__preview-delete"> </div><i class="van-icon van-icon-delete van-uploader__preview-delete">
@ -32,11 +32,29 @@ exports[`max-count prop 1`] = `
</div> </div>
`; `;
exports[`preview not image file 1`] = `
<div class="van-uploader">
<div class="van-uploader__wrapper">
<div class="van-uploader__preview">
<div class="van-image van-uploader__preview-image">
<div class="van-image__error"><i class="van-icon van-icon-description van-uploader__file-icon" style="">
<!----></i>
<div class="van-uploader__file-name van-ellipsis">test.md</div>
</div>
</div><i class="van-icon van-icon-delete van-uploader__preview-delete">
<!----></i>
</div>
<div class="van-uploader__upload"><i class="van-icon van-icon-plus van-uploader__upload-icon">
<!----></i><input type="file" accept="image/*" class="van-uploader__input"></div>
</div>
</div>
`;
exports[`preview-size prop 1`] = ` exports[`preview-size prop 1`] = `
<div class="van-uploader"> <div class="van-uploader">
<div class="van-uploader__wrapper"> <div class="van-uploader__wrapper">
<div class="van-uploader__preview" style=""> <div class="van-uploader__preview" style="">
<div class="van-image van-uploader__preview-image" style="width: 30px; height: 30px;"><img src="test" class="van-image__img" style="object-fit: cover;"> <div class="van-image van-uploader__preview-image" style="width: 30px; height: 30px;"><img src="data:image/test" class="van-image__img" style="object-fit: cover;">
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;"> <div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;">
<!----></i></div> <!----></i></div>
</div><i class="van-icon van-icon-delete van-uploader__preview-delete"> </div><i class="van-icon van-icon-delete van-uploader__preview-delete">
@ -52,7 +70,7 @@ exports[`render preview image 1`] = `
<div class="van-uploader"> <div class="van-uploader">
<div class="van-uploader__wrapper"> <div class="van-uploader__wrapper">
<div class="van-uploader__preview"> <div class="van-uploader__preview">
<div class="van-image van-uploader__preview-image"><img src="test" class="van-image__img" style="object-fit: cover;"> <div class="van-image van-uploader__preview-image"><img src="data:image/test" class="van-image__img" style="object-fit: cover;">
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;"> <div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;">
<!----></i></div> <!----></i></div>
</div><i class="van-icon van-icon-delete van-uploader__preview-delete"> </div><i class="van-icon van-icon-delete van-uploader__preview-delete">

View File

@ -5,22 +5,23 @@ window.File = function () {
this.size = 10000; this.size = 10000;
}; };
const mockFileDataUrl = 'data:image/test';
const mockFile = new File([], '/Users');
const file = { target: { files: [mockFile] } };
const multiFile = { target: { files: [mockFile, mockFile] } };
window.FileReader = function () { window.FileReader = function () {
this.readAsText = function () { this.readAsText = function () {
this.onload && this.onload &&
this.onload({ this.onload({
target: { target: {
result: 'test' result: mockFileDataUrl
} }
}); });
}; };
this.readAsDataURL = this.readAsText; this.readAsDataURL = this.readAsText;
}; };
const mockFile = new File([], '/Users');
const file = { target: { files: [mockFile] } };
const multiFile = { target: { files: [mockFile, mockFile] } };
test('disabled', () => { test('disabled', () => {
const afterRead = jest.fn(); const afterRead = jest.fn();
const wrapper = mount(Uploader, { const wrapper = mount(Uploader, {
@ -39,7 +40,7 @@ it('read text', done => {
propsData: { propsData: {
resultType: 'text', resultType: 'text',
afterRead: readFile => { afterRead: readFile => {
expect(readFile.content).toEqual('test'); expect(readFile.content).toEqual(mockFileDataUrl);
done(); done();
} }
} }
@ -276,5 +277,26 @@ it('click to preview image', async () => {
wrapper.find('.van-image').trigger('click'); wrapper.find('.van-image').trigger('click');
expect(document.querySelector('.van-image-preview')).toBeTruthy(); const imagePreviewNode = document.querySelector('.van-image-preview');
expect(imagePreviewNode).toBeTruthy();
imagePreviewNode.remove();
});
it('preview not image file', async () => {
const wrapper = mount(Uploader, {
propsData: {
fileList: [{
content: 'data:application',
file: {
name: 'test.md'
}
}]
}
});
wrapper.find('img').trigger('error');
wrapper.find('.van-image').trigger('click');
expect(document.querySelector('.van-image-preview')).toBeFalsy();
expect(wrapper).toMatchSnapshot();
}); });