add listType

This commit is contained in:
baiyaaaaa 2017-02-13 00:44:57 +08:00 committed by 杨奕
parent 2f61998e78
commit 02a1f74022
14 changed files with 558 additions and 507 deletions

View File

@ -46,7 +46,6 @@
"row": "./packages/row/index.js",
"col": "./packages/col/index.js",
"upload": "./packages/upload/index.js",
"upload-dragger": "./packages/upload/index.js",
"progress": "./packages/progress/index.js",
"spinner": "./packages/spinner/index.js",
"message": "./packages/message/index.js",

View File

@ -10,6 +10,32 @@
.upload-demo {
width: 360px;
}
.avatar-uploader {
.el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
&:hover {
border-color: #20a0ff;
}
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: @width;
line-height: @height;
text-align: center;
}
.avatar {
width: 178px;
height: @width;
display: block;
}
}
}
</style>
<script>
@ -24,7 +50,8 @@
name: 'food2.jpeg',
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
status: 'finished'
}]
}],
imageUrl: ''
};
},
methods: {
@ -52,6 +79,21 @@
},
submitUpload() {
this.$refs.upload.submit();
},
handleAvatarScucess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}
}
}
@ -61,13 +103,13 @@
通过点击或者拖拽上传文件
### 点击上传多个文件
### 点击上传
::: demo 通过 slot 你可以传入自定义的上传按钮类型和文字提示。
```html
<el-upload
class="upload-demo"
action="//jsonplaceholder.typicode.com/posts/"
action="http://localhost:9000/upload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList">
@ -94,18 +136,121 @@
```
:::
::: demo 通过 slot 你可以传入自定义的上传按钮类型和文字提示。
### 用户头像上传
使用 beforeUpload 限制用户上传的图片格式和大小。
::: demo
```html
<el-upload
class="avatar-uploader"
action="http://localhost:9000/upload"
:show-file-list="false"
:on-success="handleAvatarScucess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<script>
export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
}
}
}
</script>
```
:::
### 照片墙
使用 listType 属性来设置文件列表的样式。
::: demo
```html
<el-upload
action="http://localhost:9000/upload"
list-type="picture-card"
:on-preview="handlePreview">
<i class="el-icon-plus"></i>
</el-upload>
<script>
export default {
data() {
return {
fileList: []
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
}
}
}
</script>
```
:::
### 图片列表缩略图
::: demo
```html
<el-upload
class="upload-demo"
draggable
action="//jsonplaceholder.typicode.com/posts/"
action="http://localhost:9000/upload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
thumbnail-mode>
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
<script>
export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
}
}
}
</script>
```
:::
### 拖拽上传
::: demo
```html
<el-upload
class="upload-demo"
drag
action="http://localhost:9000/upload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
mutiple>
<i class="el-icon-upload"></i>
<div class="el-upload-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
```
@ -118,7 +263,7 @@
<el-upload
class="upload-demo"
ref="upload"
action="//jsonplaceholder.typicode.com/posts/"
action="http://localhost:9000/upload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
@ -147,84 +292,6 @@
```
:::
<!-- ### 拖拽上传
可将文件拖入指定区域进行上传。
::: demo 将 `type` 属性指定为 'drag' 可以将上传控件变为支持拖拽的形式,并且你可以通过 `multiple` 属性来控制是否支持多选,`on-preview` 和 `on-remove` 是一个钩子函数,分别在点击上传后的文件链接和点击移除上传后的文件后被调用。
```html
<el-upload
action="//jsonplaceholder.typicode.com/posts/"
type="drag"
:multiple="true"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-success="handleSuccess"
:on-error="handleError"
:file-list="fileList"
>
<i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
<script>
export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
}
}
}
</script>
```
:::
### 上传单个图片
专门针对图片类型文件的上传,上传后在原位置显示缩略图。
::: demo `thumbnail-mode` 属性允许你将上传组件强制只允许图片上传,并支持展示上传文件的缩略图。
```html
<el-upload
action="//jsonplaceholder.typicode.com/posts/"
type="drag"
:thumbnail-mode="true"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
>
<i class="el-icon-upload"></i>
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div>
</el-upload>
<script>
export default {
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
}
}
}
</script>
```
::: -->
### Attribute
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
@ -234,7 +301,7 @@
| data | 可选参数, 上传时附带的额外参数 | object | — | — |
| name | 可选参数, 上传的文件字段名 | string | — | file |
| with-credentials | 支持发送 cookie 凭证信息 | boolean | — | false |
| show-upload-list | 是否显示已上传文件列表 | boolean | — | true |
| show-file-list | 是否显示已上传文件列表 | boolean | — | true |
| type | 上传控件类型 | string | select,drag | select |
| accept | 可选参数, 接受上传的[文件类型](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-accept)thumbnail-mode 模式下此参数无效)| string | — | — |
| on-preview | 可选参数, 点击已上传的文件链接时的钩子, 可以通过 file.response 拿到服务端返回数据 | function(file) | — | — |
@ -243,8 +310,9 @@
| on-error | 可选参数, 文件上传失败时的钩子 | function(err, response, file) | — | — |
| on-progress | 可选参数, 文件上传时的钩子 | function(event, file, fileList) | — | — |
| before-upload | 可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。 | function(file) | — | — |
| thumbnail-mode | 是否设置为图片模式,该模式下会显示图片缩略图 | boolean | — | false |
| fileList | 默认已上传的文件列表, 例如: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}] | array | — | [] |
| list-type | 文件列表的类型 | string | text/picture/picture-card | text |
| auto-upload | 是否在选取文件后立即进行上传 | boolean | — | true |
| fileList | 上传的文件列表, 例如: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}] | array | — | [] |
### Methods
| 方法名 | 说明 | 参数 |

View File

@ -57,5 +57,13 @@
}
.collapse-transition {
transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out;
transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-active {
opacity: 0;
transform: translateY(-30px);
}

View File

@ -5,63 +5,110 @@
@component-namespace el {
@b upload {
display: inline-block;
text-align: center;
@e input {
display: none;
}
@e inner {
display: inline-block;
position: relative;
@e tip {
font-size: 12px;
color: var(--color-base-silver);
margin-top: 7px;
}
& iframe {
position: absolute;
z-index: -1;
top: 0;
left: 0;
opacity: 0;
filter: alpha(opacity=0);
}
/* 照片墙模式 */
@m picture-card {
background-color: #fbfdff;
border: 1px dashed #c0ccda;
border-radius: 6px;
box-sizing: border-box;
width: 148px;
height: @width;
cursor: pointer;
line-height: calc(@height - 2);
& iframe {
position: absolute;
z-index: -1;
top: 0;
left: 0;
opacity: 0;
filter: alpha(opacity=0);
i {
font-size: 28px;
color: #8c939d;
}
&:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
}
@e files {
margin: 0;
padding: 0;
list-style: none;
margin-bottom: 10px;
}
@b upload-dragger {
background-color: #fff;
border: 1px dashed #d9d9d9;
border-radius: 6px;
box-sizing: border-box;
width: 360px;
height: 180px;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;
& .el-icon-upload {
font-size: 67px;
color: var(--color-light-silver);
margin: 40px 0 16px;
line-height: 50px;
}
@e file {
& + .el-upload__tip {
text-align: center;
}
& ~ .el-upload__files {
border-top: 1px solid rgba(var(--color-extra-light-silver), .2);
margin-top: 7px;
padding-top: 5px;
}
.el-upload__text {
color: var(--color-light-silver);
font-size: 14px;
text-align: center;
& em {
color: var(--color-primary);
font-style: normal;
}
}
&:hover {
border-color: var(--color-primary);
}
@when dragOver {
background-color: rgba(32, 159, 255, .06);
border: 2px dashed var(--color-primary);
}
}
@b upload-list {
margin: 0;
padding: 0;
list-style: none;
@e item {
transition: all .5s cubic-bezier(.55,0,.1,1);
font-size: 14px;
color: var(--color-extra-light-black);
line-height: 32px;
line-height: 1.8;
margin-top: 5px;
position: relative;
box-sizing: border-box;
border-radius: 4px;
width: 100%;
position: relative;
@e name {
color: var(--color-extra-light-black);
display: block;
margin-right: 40px;
overflow: hidden;
padding-left: 4px;
text-overflow: ellipsis;
transition: color .3s;
white-space: nowrap;
[class^="el-icon"] {
color: var(--color-light-silver);
margin-right: 7px;
height: 100%;
line-height: inherit;
}
}
@e icon {
position: absolute;
right: 0;
top: 0;
line-height: inherit;
}
& .el-progress {
position: absolute;
bottom: -3px;
@ -77,98 +124,206 @@
margin-right: 0;
padding-right: 0;
}
&:first-child {
margin-top: 10px;
}
&:hover {
background-color: var(--color-extra-light-gray);
}
@when success {
.el-upload__file__icon {
color: var(--color-success);
}
.el-upload__file__name:hover {
.el-upload-list__item-name:hover {
color: var(--link-hover-color);
cursor: pointer;
}
.el-icon-close {
display: none;
}
&:hover {
.el-upload__file__icon {
.el-icon-close {
display: inline-block;
cursor: pointer;
opacity: .75;
transform: scale(.7);
color: var(--color-extra-light-black);
&:hover {
opacity: 1;
}
}
.el-icon-circle-check,
.el-icon-check {
display: none;
}
.el-upload__btn-delete {
display: block;
cursor: pointer;
}
}
}
@e item-name {
color: var(--color-extra-light-black);
display: block;
margin-right: 40px;
overflow: hidden;
padding-left: 4px;
text-overflow: ellipsis;
transition: color .3s;
white-space: nowrap;
[class^="el-icon"] {
color: var(--color-light-silver);
margin-right: 7px;
height: 100%;
line-height: inherit;
}
}
@e item-status-label {
position: absolute;
right: 10px;
top: 0;
line-height: inherit;
color: var(--color-success);
}
@e item-delete {
position: absolute;
right: 10px;
top: 0;
font-size: 12px;
color: var(--color-extra-light-black);
display: none;
&: hover {
color: var(--color-primary);
}
}
@m picture-card {
float: left;
margin: 0;
.el-upload-list__item {
overflow: hidden;
background-color: #fff;
border: 1px solid #c0ccda;
border-radius: 6px;
box-sizing: border-box;
width: 148px;
height: @width;
margin: 0 8px 8px 0;
display: inline-block;
&:hover .el-upload-list__item-status-label {
display: none;
}
}
.el-upload-list__item-name {
display: none;
}
.el-upload-list__item-thumbnail {
width: 100%;
height: 100%;
}
.el-upload-list__item-status-label {
position: absolute;
right: -15px;
top: -6px;
width: 40px;
height: 24px;
background: #13ce66;
text-align: center;
transform: rotate(45deg);
box-shadow: 0 0 1pc 1px rgba(0,0,0,0.2);
i {
font-size: 12px;
margin-top: 11px;
transform: rotate(-45deg) scale(0.8);
color: #fff;
}
}
.el-upload-list__item-actions {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s;
@utils-vertical-center;
span {
display: none;
cursor: pointer;
}
span + span {
margin-left: 15px;
}
.el-upload-list__item-delete {
position: static;
font-size: inherit;
color: inherit;
}
&:hover {
opacity: 1;
span {
display: inline-block;
}
}
}
@when fail {
.el-upload__file__icon {
color: var(--color-error);
}
@m picture {
.el-upload-list__item {
overflow: hidden;
background-color: #fff;
border: 1px solid #c0ccda;
border-radius: 6px;
box-sizing: border-box;
margin-top: 10px;
&:hover {
.el-upload-list__item-status-label {
background: transparent;
box-shadow: none;
top: -2px;
right: -12px;
.el-icon-close {
transform: rotate(45deg) scale(.7);
}
}
}
}
}
@e tip {
font-size: 12px;
color: var(--color-base-silver);
margin-top: 7px;
}
@e btn-delete {
position: absolute;
right: 15px;
top: 0;
font-size: 12px;
color: var(--color-primary);
display: none;
}
/* 拖拽模式 */
@m draggable {
background-color: var(--color-dark-white);
border: 1px solid var(--color-extra-light-silver);
box-sizing: border-box;
width: 360px;
height: 180px;
border-radius: 4px;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;
& .el-upload__inner {
display: block;
height: 100%;
.el-upload-list__item-thumbnail {
vertical-align: middle;
display: inline-block;
width: 70px;
height: 70px;
margin: 10px;
}
& .el-icon-upload {
font-size: 67px;
color: var(--color-light-silver);
margin: 40px 0 16px;
line-height: 50px;
.el-upload-list__item-name {
display: inline-block;
vertical-align: middle;
}
& + .el-upload__tip {
.el-upload-list__item-status-label {
position: absolute;
right: -17px;
top: -7px;
width: 46px;
height: 26px;
background: #13ce66;
text-align: center;
}
& ~ .el-upload__files {
margin-top: 7px;
padding-top: 5px;
border-top: 1px solid rgba(var(--color-extra-light-silver), .2);
}
transform: rotate(45deg);
box-shadow: 0 1px 1px #ccc;
@e text {
color: var(--color-light-silver);
font-size: 14px;
text-align: center;
& em {
color: var(--color-primary);
font-style: normal;
i {
font-size: 12px;
margin-top: 12px;
transform: rotate(-45deg) scale(0.8);
color: #fff;
}
}
&:not(.is-showCover):hover {
border-color: var(--color-primary);
}
@when dragOver {
background-color: rgba(32, 159, 255, .06);
border: 2px dashed var(--color-primary);
}
}
}
@b upload-cover {

View File

@ -1,8 +0,0 @@
import UploadDragger from '../upload/src/upload-dragger';
/* istanbul ignore next */
UploadDragger.install = function(Vue) {
Vue.component(UploadDragger.name, UploadDragger);
};
export default UploadDragger;

View File

@ -1,10 +0,0 @@
import Upload from './src';
import UploadDragger from './src/upload-dragger';
/* istanbul ignore next */
Upload.install = function(Vue) {
Vue.component(Upload.name, Upload);
Vue.component(UploadDragger.name, UploadDragger);
};
export default { Upload, UploadDragger };

View File

@ -1,61 +0,0 @@
<template>
<div class="el-upload-cover" @click.stop v-if="image">
<transition name="el-fade-in">
<el-progress
class="el-upload-cover__progress"
v-if="image.status === 'uploading'"
:percentage="image.percentage"
:show-text="false"
>
</el-progress>
</transition>
<div
class="el-upload-cover__content"
v-if="image.status === 'success'"
@mouseenter="mouseover = true"
@mouseleave="mouseover = false"
>
<img :src="image.url">
<label class="el-upload-cover__label"><i class="el-icon-check"></i></label>
<transition name="el-fade-in">
<div v-show="mouseover" class="el-upload-cover__interact">
<div class="el-draggeer__cover__btns">
<span class="btn" @click="$parent.handleClick()"><i class="el-icon-upload2"></i><span>{{ t('el.upload.continue') }}</span></span>
<span class="btn" @click="$emit('preview', image)"><i class="el-icon-view"></i><span>{{ t('el.upload.preview') }}</span></span>
<span class="btn" @click="$emit('remove', image)"><i class="el-icon-delete2"></i><span>{{ t('el.upload.delete') }}</span></span>
</div>
</div>
</transition>
<transition name="el-zoom-in-bottom">
<h4 v-show="mouseover" class="el-upload-cover__title">{{image.name}}</h4>
</transition>
</div>
</div>
</template>
<script>
import Locale from 'element-ui/src/mixins/locale';
import ElProgress from 'element-ui/packages/progress';
export default {
mixins: [Locale],
components: { ElProgress },
props: {
image: {},
onPreview: {
type: Function,
default: function() {}
},
onRemove: {
type: Function,
default: function() {}
}
},
data() {
return {
mouseover: false
};
}
};
</script>

View File

@ -1,30 +0,0 @@
import Cover from './cover';
export default {
components: {
Cover
},
data() {
return {
dragOver: false
};
},
computed: {
lastestFile() {
return this.fileList[this.fileList.length - 1];
},
showCover() {
var file = this.lastestFile;
return this.thumbnailMode && file && file.status !== 'fail';
},
thumbnailMode() {
return this.$parent.thumbnailMode;
}
},
methods: {
onDrop(e) {
this.dragOver = false;
this.uploadFiles(e.dataTransfer.files);
}
}
};

View File

@ -1,9 +1,9 @@
<script>
import Cover from './cover';
import UploadDragger from './upload-dragger.vue';
export default {
components: {
Cover
UploadDragger
},
props: {
type: String,
@ -30,12 +30,13 @@ export default {
onRemove: {
type: Function,
default: function() {}
}
},
drag: Boolean,
listType: String
},
data() {
return {
dragOver: false,
mouseover: false,
domain: '',
file: null,
@ -43,31 +44,22 @@ export default {
};
},
computed: {
lastestFile() {
var fileList = this.$parent.fileList;
return fileList[fileList.length - 1];
},
showCover() {
var file = this.lastestFile;
return this.thumbnailMode && file && file.status !== 'fail';
},
thumbnailMode() {
return this.$parent.thumbnailMode;
}
},
methods: {
isImage(str) {
return str.indexOf('image') !== -1;
},
handleClick() {
if (!this.disabled) {
this.$refs.input.click();
}
this.$refs.input.click();
},
handleChange(ev) {
const file = ev.target.files[0];
const file = ev.target.value;
if (file) {
this.uploadFiles(file);
}
},
uploadFiles(file) {
if (this.disabled) return;
this.disabled = true;
this.file = file;
this.onStart(file);
@ -86,58 +78,49 @@ export default {
dataSpan.innerHTML = inputs.join('');
formNode.submit();
dataSpan.innerHTML = '';
this.disabled = true;
},
getFormNode() {
return this.$refs.form;
},
getFormDataNode() {
return this.$refs.data;
},
onDrop(e) {
e.preventDefault();
this.dragOver = false;
this.uploadFiles(e.dataTransfer.files);
},
handleDragover(e) {
e.preventDefault();
this.onDrop = true;
},
handleDragleave(e) {
e.preventDefault();
this.onDrop = false;
},
onload(e) {
this.disabled = false;
}
},
created() {
this.frameName = 'frame-' + Date.now();
},
mounted() {
const self = this;
!this.$isServer && window.addEventListener('message', (event) => {
var targetOrigin = new URL(this.action).origin;
if (event.origin !== targetOrigin) {
return false;
}
if (!self.file) return;
var targetOrigin = new URL(self.action).origin;
if (event.origin !== targetOrigin) return;
var response = event.data;
if (response.result === 'success') {
this.onSuccess(response, this.file);
self.onSuccess(response, self.file);
} else if (response.result === 'failed') {
this.onSuccess(response, this.file);
self.onError(response, self.file);
}
self.disabled = false;
self.file = null;
}, false);
},
render(h) {
var cover = <cover image={this.lastestFile} onPreview={this.onPreview} onRemove={this.onRemove}></cover>;
var frameName = 'frame-' + Date.now();
const {
drag,
uploadFiles,
listType,
frameName
} = this;
const oClass = { 'el-upload': true };
oClass[`el-upload--${listType}`] = true;
return (
<div
class={{
'el-upload__inner': true,
'el-dragger': this.type === 'drag',
'is-dragOver': this.dragOver,
'is-showCover': this.showCover
}}
class={oClass}
on-click={this.handleClick}
nativeOn-drop={this.onDrop}
nativeOn-dragover={this.handleDragover}
@ -161,7 +144,11 @@ export default {
<input type="hidden" name="documentDomain" value={ this.$isServer ? '' : document.domain } />
<span ref="data"></span>
</form>
{!this.showCover ? this.$slots.default : cover}
{
drag
? <upload-dragger on-file={uploadFiles}>{this.$slots.default}</upload-dragger>
: this.$slots.default
}
</div>
);
}

View File

@ -1,7 +1,6 @@
<script>
import UploadList from './upload-list';
import Upload from './upload';
import UploadDragger from './upload-dragger';
import IframeUpload from './iframe-upload';
import ElProgress from 'element-ui/packages/progress';
@ -14,7 +13,6 @@ export default {
ElProgress,
UploadList,
Upload,
UploadDragger,
IframeUpload
},
@ -35,11 +33,11 @@ export default {
type: String,
default: 'file'
},
draggable: Boolean,
drag: Boolean,
dragger: Boolean,
withCredentials: Boolean,
thumbnailMode: Boolean,
showUploadList: {
showFileList: {
type: Boolean,
default: true
},
@ -58,8 +56,7 @@ export default {
default: noop
},
onPreview: {
type: Function,
default: noop
type: Function
},
onSuccess: {
type: Function,
@ -82,6 +79,10 @@ export default {
autoUpload: {
type: Boolean,
default: true
},
listType: {
type: String,
default: 'text' // text,picture,picture-card
}
},
@ -168,11 +169,6 @@ export default {
});
return target;
},
handlePreview(file) {
if (file.status === 'finished') {
this.onPreview(file);
}
},
clearFiles() {
this.uploadFiles = [];
},
@ -188,12 +184,13 @@ export default {
render(h) {
var uploadList;
if (this.showUploadList && this.uploadFiles.length) {
if (this.showFileList) {
uploadList = (
<UploadList
listType={this.listType}
files={this.uploadFiles}
on-remove={this.handleRemove}
on-preview={this.handlePreview}>
handlePreview={this.onPreview}>
</UploadList>
);
}
@ -201,7 +198,7 @@ export default {
var uploadData = {
props: {
type: this.type,
draggable: this.draggable,
drag: this.drag,
action: this.action,
multiple: this.multiple,
'before-upload': this.beforeUpload,
@ -212,36 +209,31 @@ export default {
accept: this.thumbnailMode ? 'image/gif, image/png, image/jpeg, image/bmp, image/webp' : this.accept,
fileList: this.uploadFiles,
autoUpload: this.autoUpload,
listType: this.listType,
'on-start': this.handleStart,
'on-progress': this.handleProgress,
'on-success': this.handleSuccess,
'on-error': this.handleError,
'on-preview': this.handlePreview,
'on-preview': this.onPreview,
'on-remove': this.handleRemove
},
ref: 'upload-inner'
};
// var uploadComponent = (typeof FormData !== 'undefined' || this.$isServer)
// ? <upload {...props}>{this.$slots.default}</upload>
// : <iframeUpload {...props}>{this.$slots.default}</iframeUpload>;
if (this.draggable) {
return (
<div>
<upload {...uploadData}>{this.$slots.trigger || this.$slots.default}</upload>
{this.$slots.tip}
{uploadList}
</div>
);
}
const trigger = this.$slots.trigger || this.$slots.default;
const uploadComponent = (typeof FormData !== 'undefined' || this.$isServer)
? <upload {...uploadData}>{trigger}</upload>
: <iframeUpload {...uploadData}>{trigger}</iframeUpload>;
return (
<div>
{uploadList}
<upload {...uploadData}>{this.$slots.trigger || this.$slots.default}</upload>
{this.$slots.default}
{
this.$slots.trigger
? [uploadComponent, this.$slots.default]
: uploadComponent
}
{this.$slots.tip}
{uploadList}
</div>
);
}

View File

@ -2,86 +2,29 @@
<div
class="el-upload-dragger"
:class="{
'is-dragOver': dragOver,
'is-showCover': showCover
'is-dragOver': dragOver
}"
@click="handleClick"
@drop.prevent="onDrop"
@dragover.prevent="dragOver = true"
@dragleave.prevent="dragOver = false"
>
<slot v-if="!showCover"></slot>
<cover :image="lastestFile" :on-preview="onPreview" :on-remove="onRemove" v-else></cover>
<input class="el-upload__input" type="file" ref="input" @change="handleChange" :multiple="multiple" :accept="accept">
<slot></slot>
</div>
</template>
<script>
import Upload from './upload';
import IframeUpload from './iframe-upload';
import Cover from './cover';
export default {
name: 'ElUploadDragger',
name: 'ElUploadDrag',
extends: Upload,
components: {
IframeUpload,
Cover
},
data() {
return {
dragOver: false
};
},
props: {
draggable: {
type: Boolean,
default: true
}
},
computed: {
lastestFile() {
var fileList = this.$parent.fileList;
return fileList[fileList.length - 1];
},
showCover() {
var file = this.lastestFile;
return this.thumbnailMode && file && file.status !== 'fail';
},
thumbnailMode() {
return this.$parent.thumbnailMode;
}
},
methods: {
onDrop(e) {
this.dragOver = false;
this.uploadFiles(e.dataTransfer.files);
this.$emit('file', e.dataTransfer.files);
}
}
// render(h) {
// let {
// dragover
// } = this;
// let content = this.showCover
// ? <cover image={this.lastestFile} on-preview={this.onPreview} on-remove={this.onRemove}></cover>
// : this.$slots.default
// return (
// <div
// class={{
// 'el-upload-dragger': true,
// 'is-dragOver': this.dragOver,
// 'is-showCover': this.showCover
// }}
// @drop.prevent="onDrop"
// @dragover.prevent="dragOver = true"
// @dragleave.prevent="dragOver = false"
// >
// {content}
// <input class="el-upload__input" type="file" ref="input" on-change={this.handleChange} multiple={this.multiple} accept={this.accept} />
// </div>
// );
// }
};
</script>

View File

@ -1,20 +1,48 @@
<template>
<transition-group tag="ul" class="el-upload__files" name="list">
<transition-group
tag="ul"
:class="['el-upload-list', 'el-upload-list--' + listType]"
name="list"
>
<li
v-for="file in files"
:class="['el-upload__file', 'is-' + file.status]"
:class="['el-upload-list__item', 'is-' + file.status]"
:key="file"
@click="$emit('clickFile', file)"
>
<a class="el-upload__file__name" @click="$emit('preview', file)">
<img class="el-upload-list__item-thumbnail" v-if="['picture-card', 'picture'].indexOf(listType) > -1" :src="file.url" alt="">
<a class="el-upload-list__item-name" @click="handleClick(file)">
<i class="el-icon-document"></i>{{file.name}}
</a>
<i :class="{
'el-upload__file__icon': true,
'el-icon-circle-check': file.status === 'success',
'el-icon-circle-cross': file.status === 'fail'
}"></i>
<span class="el-upload__btn-delete" @click="$emit('remove', file)" v-show="file.status === 'success'">{{ t('el.upload.delete') }}</span>
<label v-show="file.status === 'success'" class="el-upload-list__item-status-label">
<i :class="{
'el-icon-circle-check': listType === 'text',
'el-icon-check': ['picture-card', 'picture'].indexOf(listType) > -1
}"></i>
<i class="el-icon-close" @click="$emit('remove', file)"></i>
</label>
<span class="el-upload-list__item-actions"
v-if="
listType === 'picture-card' &&
file.status === 'success'
"
>
<span
v-if="
handlePreview &&
listType === 'picture-card'
"
@click="handlePreview(file)"
class="el-upload-list__item-preview"
>
<i class="el-icon-view"></i>
</span>
<span
class="el-upload-list__item-delete"
@click="$emit('remove', file)"
>
<i class="el-icon-delete2"></i>
</span>
</span>
<el-progress
v-if="file.status === 'uploading'"
:stroke-width="2"
@ -38,11 +66,16 @@
default() {
return [];
}
}
},
handlePreview: Function,
listType: String
},
methods: {
parsePercentage(val) {
return parseInt(val, 10);
},
handleClick(file) {
this.handlePreview && this.handlePreview(file);
}
}
};

View File

@ -1,11 +1,11 @@
<script>
import merge from 'element-ui/src/utils/merge';
import ajax from './ajax';
import dragger from './dragger';
import UploadDragger from './upload-dragger.vue';
export default {
mixins: [dragger],
components: {
UploadDragger
},
props: {
type: String,
action: {
@ -26,7 +26,7 @@ export default {
onSuccess: Function,
onError: Function,
beforeUpload: Function,
draggable: Boolean,
drag: Boolean,
onPreview: {
type: Function,
default: function() {}
@ -36,7 +36,8 @@ export default {
default: function() {}
},
fileList: Array,
autoUpload: Boolean
autoUpload: Boolean,
listType: String
},
data() {
@ -118,15 +119,12 @@ export default {
render(h) {
let {
handleClick,
draggable,
onDrop,
showCover,
onPreview,
onRemove,
drag,
handleChange,
multiple,
accept,
lastestFile
listType,
uploadFiles
} = this;
const data = {
class: {
@ -136,32 +134,12 @@ export default {
click: handleClick
}
};
if (draggable) {
merge(data.on, {
dragover: (ev) => {
ev.preventDefault();
this.dragOver = true;
},
dragleave: (ev) => {
ev.preventDefault();
this.dragOver = false;
},
drop: (ev) => {
ev.preventDefault();
onDrop(ev);
}
});
merge(data.class, {
'el-upload--draggable': true,
'is-dragOver': this.dragOver,
'is-showCover': this.showCover
});
}
data.class[`el-upload--${listType}`] = true;
return (
<div {...data}>
{
showCover
? <cover image={lastestFile} on-preview={onPreview} on-remove={onRemove}></cover>
drag
? <upload-dragger on-file={uploadFiles}>{this.$slots.default}</upload-dragger>
: this.$slots.default
}
<input class="el-upload__input" type="file" ref="input" on-change={handleChange} multiple={multiple} accept={accept}></input>

View File

@ -47,7 +47,6 @@ import Icon from '../packages/icon';
import Row from '../packages/row';
import Col from '../packages/col';
import Upload from '../packages/upload';
import UploadDragger from '../packages/upload-dragger';
import Progress from '../packages/progress';
import Spinner from '../packages/spinner';
import Message from '../packages/message';
@ -109,7 +108,6 @@ const components = [
Row,
Col,
Upload,
UploadDragger,
Progress,
Spinner,
Badge,
@ -203,7 +201,6 @@ module.exports = {
Row,
Col,
Upload,
UploadDragger,
Progress,
Spinner,
Message,