mirror of https://github.com/ElemeFE/element
update upload
parent
2ceff8709e
commit
0aaf2df436
|
@ -7,33 +7,6 @@
|
||||||
.demo-box {
|
.demo-box {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
.el-draggeer__uploaded-image__btns {
|
|
||||||
margin-top: 45px;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
& .btn {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
& span {
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .15s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-left: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover span {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& i {
|
|
||||||
display: block;
|
|
||||||
font-size: 26px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
@ -43,6 +16,16 @@
|
||||||
},
|
},
|
||||||
handleRemove(file, fileList) {
|
handleRemove(file, fileList) {
|
||||||
console.log(file, fileList);
|
console.log(file, fileList);
|
||||||
|
},
|
||||||
|
beforeUpload(file) {
|
||||||
|
if (file.size > 40000000) {
|
||||||
|
console.warn(file.name + ' is too large!');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
console.log(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,31 +34,66 @@
|
||||||
## 基础使用
|
## 基础使用
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" @filechange="handleChange" @fileremove="handleRemove">
|
<el-upload action="http://element.alpha.elenet.me/upload" :on-preview="handlePreview" :on-remove="handleRemove">
|
||||||
<el-button size="small" type="primary">点击上传</el-button>
|
<el-button size="small" type="primary">点击上传</el-button>
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" @filechange="handleChange" @fileremove="handleRemove">
|
<el-upload action="http://element.alpha.elenet.me/upload" :on-preview="handlePreview" :on-remove="handleRemove">
|
||||||
<el-button size="small" type="primary">点击上传</el-button>
|
<el-button size="small" type="primary">点击上传</el-button>
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleRemove(file, fileList) {
|
||||||
|
console.log(file, fileList);
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
console.log(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## 拖拽文件上传
|
## 拖拽文件上传
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" type="drag" :multiple="true">
|
<el-upload
|
||||||
|
action="http://element.alpha.elenet.me/upload"
|
||||||
|
type="drag"
|
||||||
|
:multiple="true"
|
||||||
|
:on-preview="handlePreview"
|
||||||
|
:on-remove="handleRemove">
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" type="drag" :multiple="true">
|
<el-upload
|
||||||
|
action="http://element.alpha.elenet.me/upload"
|
||||||
|
type="drag"
|
||||||
|
:multiple="true"
|
||||||
|
:on-preview="handlePreview"
|
||||||
|
:on-remove="handleRemove">
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleRemove(file, fileList) {
|
||||||
|
console.log(file, fileList);
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
console.log(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## 图片缩略图模式
|
## 图片缩略图模式
|
||||||
|
@ -83,23 +101,39 @@
|
||||||
上传文件类型限制为只能上传图片,并可展示本地缩略图,该模式暂不支持多选
|
上传文件类型限制为只能上传图片,并可展示本地缩略图,该模式暂不支持多选
|
||||||
|
|
||||||
<div class="demo-box">
|
<div class="demo-box">
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" type="drag" mode="image">
|
<el-upload
|
||||||
<div class="el-draggeer__uploaded-image__btns" slot="interact">
|
action="http://element.alpha.elenet.me/upload"
|
||||||
<span class="btn"><i class="el-icon-share"></i><span>分享图片</span></span>
|
type="drag"
|
||||||
<span class="btn"><i class="el-icon-delete"></i><span>删除</span></span>
|
:thumbnail-mode="true"
|
||||||
</div>
|
:on-preview="handlePreview"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
>
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<el-upload action="http://127.0.0.1:9000/upload" type="drag" mode="image">
|
<el-upload
|
||||||
<div class="el-draggeer__uploaded-image__btns" slot="interact">
|
action="http://element.alpha.elenet.me/upload"
|
||||||
<span class="btn"><i class="el-icon-share"></i><span>分享图片</span></span>
|
type="drag"
|
||||||
<span class="btn"><i class="el-icon-delete"></i><span>删除</span></span>
|
:thumbnail-mode="true"
|
||||||
</div>
|
:on-preview="handlePreview"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
>
|
||||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleRemove(file, fileList) {
|
||||||
|
console.log(file, fileList);
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
console.log(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
@ -113,6 +147,8 @@
|
||||||
| showUploadList | 是否显示已上传文件列表 | boolean | | true |
|
| showUploadList | 是否显示已上传文件列表 | boolean | | true |
|
||||||
| type | 上传控件类型 | string | select,drag | select |
|
| type | 上传控件类型 | string | select,drag | select |
|
||||||
| accept | 可选参数, 接受上传的[文件类型](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-accept), 拖拽文件上传时不受此参数影响 | string | | |
|
| accept | 可选参数, 接受上传的[文件类型](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-accept), 拖拽文件上传时不受此参数影响 | string | | |
|
||||||
| filechange | 可选参数, 上传文件改变时的回调 | function(file, fileList, event) | | |
|
| onPreview | 可选参数, 点击已上传的文件链接时的钩子 | function(file) | | |
|
||||||
| fileremove | 可选参数, 文件列表移除文件时的回调 | function(file, fileList) | | |
|
| onRemove | 可选参数, 文件列表移除文件时的钩子 | function(file, fileList) | | |
|
||||||
|
| beforeUpload | 可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。 | function(file) | | |
|
||||||
|
| thumbnailMode | 是否设置为图片模式,该模式下会显示图片缩略图 | boolean | | false |
|
||||||
| type | 上传控件类型 | string | select,drag | select |
|
| type | 上传控件类型 | string | select,drag | select |
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
@import './var.css';
|
@import './var.css';
|
||||||
|
|
||||||
.fade-in-transition {
|
.fade-in-linear-enter-active,
|
||||||
opacity: 1;
|
.fade-in-linear-leave-active {
|
||||||
transition: var(--fade-transition);
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-linear-enter-active {
|
|
||||||
opacity: 1;
|
|
||||||
transition: var(--fade-linear-transition);
|
transition: var(--fade-linear-transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fade-in-linear-enter,
|
||||||
|
.fade-in-linear-leave,
|
||||||
.fade-in-linear-leave-active {
|
.fade-in-linear-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: var(--fade-linear-transition);
|
}
|
||||||
|
|
||||||
|
.fade-in-enter-active,
|
||||||
|
.fade-in-leave-active {
|
||||||
|
transition: all .3s cubic-bezier(.55,0,.1,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-in-enter,
|
.fade-in-enter,
|
||||||
.fade-in-leave,
|
.fade-in-leave-active {
|
||||||
.fade-in-linear-enter,
|
|
||||||
.fade-in-linear-leave {
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,28 +95,19 @@
|
||||||
transition: opacity .3s cubic-bezier(.645,.045,.355,1);
|
transition: opacity .3s cubic-bezier(.645,.045,.355,1);
|
||||||
}
|
}
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave,
|
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-in-bottom-enter {
|
.list-move, .list-enter-active, .list-leave-active {
|
||||||
animation: slideInBottomEnter .3s;
|
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||||
}
|
}
|
||||||
.slide-in-bottom-leave {
|
.list-enter, .list-leave-active {
|
||||||
animation: slideInBottomLeave .3s;
|
opacity: 0;
|
||||||
}
|
transform: translate(0, -30px);
|
||||||
|
|
||||||
@keyframes slideInBottomEnter {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translate3d(0,50%,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideInBottomLeave {
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translate3d(0,50%,0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/*.list-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0.01) translate(30px, 0);
|
||||||
|
}*/
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
--color-black: #000;
|
--color-black: #000;
|
||||||
--color-grey: #C0CCDA;
|
--color-grey: #C0CCDA;
|
||||||
|
|
||||||
|
/* Link
|
||||||
|
-------------------------- */
|
||||||
|
--link-color: #475669;
|
||||||
|
--link-hover-color: var(--color-primary);
|
||||||
|
|
||||||
/* Border
|
/* Border
|
||||||
-------------------------- */
|
-------------------------- */
|
||||||
--border-width-base: 1px;
|
--border-width-base: 1px;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@e file {
|
@e file {
|
||||||
|
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #475669;
|
color: #475669;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
@ -33,21 +34,16 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #475669;
|
||||||
|
transition: color .3s;
|
||||||
|
}
|
||||||
[class^="el-icon"] {
|
[class^="el-icon"] {
|
||||||
color: #99a9bf;
|
color: #99a9bf;
|
||||||
margin-right: 7px;
|
margin-right: 7px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #eff2f7;
|
|
||||||
|
|
||||||
.el-upload__btn-delete {
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& .el-progress {
|
& .el-progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -61,6 +57,21 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: #eff2f7;
|
||||||
|
}
|
||||||
|
@when finished {
|
||||||
|
& a:hover {
|
||||||
|
color: var(--link-hover-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.el-upload__btn-delete {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@e tip {
|
@e tip {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -125,6 +136,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
& img {
|
& img {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -140,6 +152,45 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(#000, .72);
|
background-color: rgba(#000, .72);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
& .btn {
|
||||||
|
display: inline-block;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: var(--md-fade-transition);
|
||||||
|
margin-top: 60px;
|
||||||
|
|
||||||
|
& i {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
& span {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity .15s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-13px);
|
||||||
|
|
||||||
|
& span {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& i {
|
||||||
|
color: #fff;
|
||||||
|
display: block;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: inherit;
|
||||||
|
margin: 0 auto 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@e title {
|
@e title {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const Upload = require('./src/upload');
|
const Upload = require('./src/index');
|
||||||
|
|
||||||
Upload.install = function(Vue) {
|
Upload.install = function(Vue) {
|
||||||
Vue.component(Upload.name, Upload);
|
Vue.component(Upload.name, Upload);
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
<script>
|
||||||
|
import UploadList from './upload-list';
|
||||||
|
import Upload from './upload';
|
||||||
|
import ElProgress from 'packages/progress/index.js';
|
||||||
|
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'el-upload',
|
||||||
|
|
||||||
|
// extends: typeof FormData !== 'undefined' ? ajaxUpload : iframeUpload,
|
||||||
|
// extends: iframeUpload,
|
||||||
|
|
||||||
|
components: {
|
||||||
|
ElProgress,
|
||||||
|
UploadList,
|
||||||
|
Upload
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
// 'Access-Control-Request-Methods': 'GET, PUT, POST, DELETE, OPTIONS',
|
||||||
|
// 'Access-Control-Request-Headers': 'Content-Type, Content-Range, Content-Disposition, Content-Description'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: 'file'
|
||||||
|
},
|
||||||
|
withCredentials: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
thumbnailMode: Boolean,
|
||||||
|
showUploadList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
accept: String,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'select'
|
||||||
|
},
|
||||||
|
beforeUpload: Function,
|
||||||
|
onRemove: {
|
||||||
|
type: Function,
|
||||||
|
default: noop
|
||||||
|
},
|
||||||
|
onChange: {
|
||||||
|
type: Function,
|
||||||
|
default: noop
|
||||||
|
},
|
||||||
|
onPreview: {
|
||||||
|
type: Function,
|
||||||
|
default: noop
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadedFiles: [],
|
||||||
|
dragOver: false,
|
||||||
|
draging: false,
|
||||||
|
tempIndex: 1
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onStart(file) {
|
||||||
|
file.uid = Date.now() + this.tempIndex++;
|
||||||
|
let _file = {
|
||||||
|
status: 'uploading',
|
||||||
|
name: file.name,
|
||||||
|
size: file.size,
|
||||||
|
percentage: 0,
|
||||||
|
uid: file.uid,
|
||||||
|
showProgress: true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.thumbnailMode) {
|
||||||
|
try {
|
||||||
|
_file.url = URL.createObjectURL(file);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.uploadedFiles.push(_file);
|
||||||
|
},
|
||||||
|
onProgress(ev, file) {
|
||||||
|
var _file = this.getFile(file);
|
||||||
|
_file.percentage = ev.percent;
|
||||||
|
},
|
||||||
|
onSuccess(res, file) {
|
||||||
|
var _file = this.getFile(file);
|
||||||
|
|
||||||
|
_file.status = 'finished';
|
||||||
|
_file.response = res;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
_file.showProgress = false;
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
onError(err, file) {
|
||||||
|
var _file = this.getFile(file);
|
||||||
|
var fileList = this.uploadedFiles;
|
||||||
|
|
||||||
|
_file.status = 'fail';
|
||||||
|
|
||||||
|
fileList.splice(fileList.indexOf(_file), 1);
|
||||||
|
this.$emit('error', _file, fileList, err);
|
||||||
|
},
|
||||||
|
handleRemove(file) {
|
||||||
|
var fileList = this.uploadedFiles;
|
||||||
|
fileList.splice(fileList.indexOf(file), 1);
|
||||||
|
this.onRemove(file, fileList);
|
||||||
|
},
|
||||||
|
getFile(file) {
|
||||||
|
var fileList = this.uploadedFiles;
|
||||||
|
var target;
|
||||||
|
fileList.every(item => {
|
||||||
|
target = file.uid === item.uid ? item : null;
|
||||||
|
return !target;
|
||||||
|
});
|
||||||
|
return target;
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
if (file.status === 'finished') {
|
||||||
|
this.onPreview(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
var uploadList;
|
||||||
|
if (this.showUploadList && !this.thumbnailMode) {
|
||||||
|
uploadList = (
|
||||||
|
<UploadList
|
||||||
|
files={this.uploadedFiles}
|
||||||
|
on-remove={this.handleRemove}
|
||||||
|
on-preview={this.handlePreview}>
|
||||||
|
</UploadList>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var props = {
|
||||||
|
props: {
|
||||||
|
action: this.action,
|
||||||
|
multiple: this.multiple,
|
||||||
|
'before-upload': this.beforeUpload,
|
||||||
|
'with-credentials': this.withCredentials,
|
||||||
|
name: this.name,
|
||||||
|
accept: this.thumbnailMode ? 'image/*' : this.accept,
|
||||||
|
'on-start': this.onStart,
|
||||||
|
'on-progress': this.onProgress,
|
||||||
|
'on-success': this.onSuccess,
|
||||||
|
'on-error': this.onError,
|
||||||
|
'on-preview': this.handlePreview,
|
||||||
|
'on-remove': this.handleRemove
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.type === 'select') {
|
||||||
|
return (
|
||||||
|
<div class="el-upload">
|
||||||
|
{uploadList}
|
||||||
|
<upload {...props}>
|
||||||
|
{this.$slots.default}
|
||||||
|
</upload>
|
||||||
|
{this.$slots.tip}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.type === 'drag') {
|
||||||
|
props.props.type = 'drag';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="el-upload">
|
||||||
|
<upload {...props}>
|
||||||
|
{this.$slots.default}
|
||||||
|
</upload>
|
||||||
|
{this.$slots.tip}
|
||||||
|
{uploadList}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<transition-group tag="ul" class="el-upload__files" name="list">
|
||||||
|
<li
|
||||||
|
v-for="file in files"
|
||||||
|
class="el-upload__file"
|
||||||
|
:class="{
|
||||||
|
'is-finished': file.status === 'finished'
|
||||||
|
}"
|
||||||
|
:key="file"
|
||||||
|
@click="$emit('clickFile', file)"
|
||||||
|
>
|
||||||
|
<a class="el-upload__file__name" @click="$emit('preview', file)">
|
||||||
|
<i class="el-icon-document"></i>{{file.name}}
|
||||||
|
</a>
|
||||||
|
<i class="el-icon-check" v-if="file.status === 'finished' && file.showProgress"></i>
|
||||||
|
<span class="el-upload__btn-delete" @click="$emit('remove', file)" v-show="file.status === 'finished'">删除</span>
|
||||||
|
<el-progress
|
||||||
|
v-if="file.showProgress"
|
||||||
|
size="small"
|
||||||
|
:percentage="file.percentage"
|
||||||
|
:type="file.status === 'finished' ? 'green' : 'blue'">
|
||||||
|
</el-progress>
|
||||||
|
</li>
|
||||||
|
</transition-group>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,187 +1,103 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="el-upload">
|
<div class="el-upload__inner"
|
||||||
<!-- 选择类型 -->
|
:class="{
|
||||||
<template v-if="type === 'select'">
|
'el-dragger': type === 'drag',
|
||||||
<ul class="el-upload__files" v-show="showUploadList && uploadedFiles.length > 0" transition="slide-in-bottom">
|
'is-dragOver': dragOver,
|
||||||
<li class="el-upload__file" v-for="file in uploadedFiles" transition="slide-in-bottom">
|
'is-hover': mouseover,
|
||||||
<i class="el-icon-document"></i>{{file.name}}
|
'is-showImage': showThumbnail
|
||||||
<i class="el-icon-check" v-show="file.status === 'success'"></i>
|
}"
|
||||||
<span class="el-upload__btn-delete" @click="removeFile(file)" v-show="file.status === 'finished'">删除</span>
|
@click="$refs.input.click()"
|
||||||
<el-progress
|
@drop.prevent="onDrop"
|
||||||
v-if="file.status === 'success' || file.status === 'uploading'"
|
@dragover.prevent="dragOver = true"
|
||||||
size="small"
|
@dragleave.prevent="dragOver = false"
|
||||||
:percentage="file.percentage"
|
@mouseenter="mouseover = true"
|
||||||
:type="file.status === 'success' ? 'green' : 'blue'">
|
@mouseleave="mouseover = false"
|
||||||
</el-progress>
|
>
|
||||||
</li>
|
<slot></slot>
|
||||||
</ul>
|
<template v-if="type === 'drag' && !showThumbnail">
|
||||||
<component :is="uploadComponent"
|
<i class="el-icon-upload"></i>
|
||||||
:action="action",
|
<div class="el-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
:multiple="multiple",
|
|
||||||
:with-credentials="withCredentials",
|
|
||||||
:name="name",
|
|
||||||
:accept="accept",
|
|
||||||
:on-start="onStart",
|
|
||||||
:on-progress="onProgress",
|
|
||||||
:on-success="onSuccess",
|
|
||||||
:on-error="onError"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</component>
|
|
||||||
<slot name="tip"></slot>
|
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="thumbnailMode">
|
||||||
<!-- 拖拽类型 -->
|
<transition name="fade-in">
|
||||||
<template v-if="type === 'drag'">
|
|
||||||
<div class="el-dragger"
|
|
||||||
:class="{
|
|
||||||
'is-dragOver': dragOver,
|
|
||||||
'is-draging': draging,
|
|
||||||
'is-hover': mouseover,
|
|
||||||
'is-showImage': showImageBlock
|
|
||||||
}"
|
|
||||||
@drop.prevent="dragOver = false"
|
|
||||||
@dragOver.prevent="dragOver = true"
|
|
||||||
@dragLeave.prevent="dragOver = false"
|
|
||||||
@mouseenter="mouseover = true"
|
|
||||||
@mouseleave="mouseover = false"
|
|
||||||
>
|
|
||||||
<el-progress
|
<el-progress
|
||||||
class="el-dragger__progress"
|
class="el-dragger__progress"
|
||||||
v-if="mode === 'image' && (image.status === 'success' || image.status === 'uploading')"
|
v-if="lastestFile.showProgress"
|
||||||
size="large"
|
size="large"
|
||||||
:percentage="image.percentage"
|
:percentage="lastestFile.percentage"
|
||||||
:type="image.status === 'success' ? 'green' : 'blue'">
|
:type="lastestFile.status === 'finished' ? 'green' : 'blue'">
|
||||||
</el-progress>
|
</el-progress>
|
||||||
<div class="el-dragger__uploaded-image"
|
</transition>
|
||||||
v-if="mode === 'image' && image.status === 'finished'"
|
<div class="el-dragger__uploaded-image" v-if="lastestFile.status === 'finished'" @click.stop>
|
||||||
transition="slide-in-bottom"
|
<img :src="lastestFile.url">
|
||||||
>
|
<transition name="fade-in">
|
||||||
<img :src="image.url">
|
<div v-show="mouseover" class="el-dragger__uploaded-image__interact">
|
||||||
<div v-show="mouseover" class="el-dragger__uploaded-image__interact" transition="fade-in">
|
<div class="el-draggeer__uploaded-image__btns">
|
||||||
<slot name="interact"></slot>
|
<span class="btn" @click="$refs.input.click()"><i class="el-icon-upload"></i><span>继续上传</span></span>
|
||||||
|
<span class="btn" @click="onPreview(lastestFile)"><i class="el-icon-search"></i><span>查看图片</span></span>
|
||||||
|
<span class="btn" @click="onRemove(lastestFile)"><i class="el-icon-delete"></i><span>删除</span></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h4 v-show="mouseover" class="el-dragger__uploaded-image__title" transition="slide-in-bottom">{{image.name}}</h4>
|
</transition>
|
||||||
</div>
|
<transition name="md-fade-top">
|
||||||
<component :is="uploadComponent"
|
<h4 v-show="mouseover" class="el-dragger__uploaded-image__title">{{lastestFile.name}}</h4>
|
||||||
:action="action",
|
</transition>
|
||||||
:multiple="multiple",
|
|
||||||
:with-credentials="withCredentials",
|
|
||||||
:name="name",
|
|
||||||
:accept="accept",
|
|
||||||
:on-start="onStart",
|
|
||||||
:on-progress="onProgress",
|
|
||||||
:on-success="onSuccess",
|
|
||||||
:on-error="onError"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</component>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot name="tip" class="el-dragger__tip"></slot>
|
|
||||||
|
|
||||||
<ul class="el-upload__files"
|
|
||||||
v-if="mode !== 'image' && showUploadList"
|
|
||||||
v-show="uploadedFiles.length > 0"
|
|
||||||
transition="slide-in-bottom"
|
|
||||||
>
|
|
||||||
<li class="el-upload__file" v-for="file in uploadedFiles" transition="slide-in-bottom">
|
|
||||||
<i class="el-icon-document"></i>{{file.name}}
|
|
||||||
<i class="el-icon-check" v-show="file.status === 'success'"></i>
|
|
||||||
<span class="el-upload__btn-delete" @click="removeFile(file)" v-show="file.status === 'finished'">删除</span>
|
|
||||||
<el-progress
|
|
||||||
v-if="file.status === 'success' || file.status === 'uploading'"
|
|
||||||
size="small"
|
|
||||||
:percentage="file.percentage"
|
|
||||||
:type="file.status === 'success' ? 'green' : 'blue'">
|
|
||||||
</el-progress>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
</template>
|
||||||
|
<input class="el-upload__input" type="file" ref="input" @change="handleChange" :multiple="multiple" :accept="accept">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AjaxUpload from './ajax-upload';
|
import ajax from './ajax';
|
||||||
import IframeUpload from './iframe-upload';
|
|
||||||
import ElProgress from 'packages/progress/index.js';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'el-upload',
|
|
||||||
|
|
||||||
// extends: typeof FormData !== 'undefined' ? ajaxUpload : iframeUpload,
|
|
||||||
// extends: iframeUpload,
|
|
||||||
|
|
||||||
components: {
|
|
||||||
ElProgress,
|
|
||||||
AjaxUpload,
|
|
||||||
IframeUpload
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
type: String,
|
||||||
action: {
|
action: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
headers: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {
|
|
||||||
// 'Access-Control-Request-Methods': 'GET, PUT, POST, DELETE, OPTIONS',
|
|
||||||
// 'Access-Control-Request-Headers': 'Content-Type, Content-Range, Content-Disposition, Content-Description'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
multiple: false,
|
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'file'
|
default: 'file'
|
||||||
},
|
},
|
||||||
withCredentials: {
|
withCredentials: Boolean,
|
||||||
type: Boolean,
|
multiple: Boolean,
|
||||||
default: false
|
|
||||||
},
|
|
||||||
showUploadList: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
accept: String,
|
accept: String,
|
||||||
type: {
|
onStart: Function,
|
||||||
type: String,
|
onProgress: Function,
|
||||||
default: 'select'
|
onSuccess: Function,
|
||||||
|
onError: Function,
|
||||||
|
beforeUpload: Function,
|
||||||
|
onPreview: {
|
||||||
|
type: Function,
|
||||||
|
default: function() {}
|
||||||
},
|
},
|
||||||
mode: String
|
onRemove: {
|
||||||
|
type: Function,
|
||||||
|
default: function() {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
uploading: false,
|
|
||||||
percentage: 0,
|
|
||||||
uploadedFiles: [],
|
|
||||||
filename: '',
|
|
||||||
success: false,
|
|
||||||
dragOver: false,
|
dragOver: false,
|
||||||
draging: false,
|
mouseover: false
|
||||||
mouseover: false,
|
|
||||||
tempIndex: 1
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
uploadComponent() {
|
lastestFile() {
|
||||||
return typeof FormData !== 'undefined' ? 'AjaxUpload' : 'IframeUpload';
|
var uploadedFiles = this.$parent.uploadedFiles;
|
||||||
|
return uploadedFiles.length > 0 ? uploadedFiles[uploadedFiles.length - 1] : {};
|
||||||
},
|
},
|
||||||
image() {
|
showThumbnail() {
|
||||||
return this.uploadedFiles.length > 0 ? this.uploadedFiles[this.uploadedFiles.length - 1] : {};
|
var file = this.lastestFile;
|
||||||
|
return this.thumbnailMode && file.status && file.status !== 'fail';
|
||||||
},
|
},
|
||||||
showImageBlock() {
|
thumbnailMode() {
|
||||||
return this.mode === 'image' && this.image.status && this.image.status !== 'fail';
|
return this.$parent.thumbnailMode;
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ready() {
|
|
||||||
if (this.mode === 'image') {
|
|
||||||
this.accept = 'image/*';
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -189,59 +105,76 @@ export default {
|
||||||
isImage(str) {
|
isImage(str) {
|
||||||
return str.indexOf('image') !== -1;
|
return str.indexOf('image') !== -1;
|
||||||
},
|
},
|
||||||
removeFile(file) {
|
handleChange(ev) {
|
||||||
this.uploadedFiles.$remove(file);
|
const files = ev.target.files;
|
||||||
this.$dispatch('fileremove', file, this.uploadedFiles);
|
|
||||||
|
if (!files) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.uploadFiles(files);
|
||||||
},
|
},
|
||||||
onStart(files) {
|
uploadFiles(files) {
|
||||||
files.forEach(file => {
|
let postFiles = Array.prototype.slice.call(files);
|
||||||
|
if (!this.multiple) { postFiles = postFiles.slice(0, 1); }
|
||||||
|
|
||||||
|
if (postFiles.length === 0) { return; }
|
||||||
|
|
||||||
|
postFiles.forEach(file => {
|
||||||
let isImage = this.isImage(file.type);
|
let isImage = this.isImage(file.type);
|
||||||
let uid = Date.now() + this.tempIndex++;
|
|
||||||
let _file = {
|
if (this.thumbnailMode && !isImage) {
|
||||||
status: 'uploading',
|
return;
|
||||||
name: file.name,
|
} else {
|
||||||
size: file.size,
|
this.upload(file);
|
||||||
percentage: 0,
|
|
||||||
uid: uid
|
|
||||||
};
|
|
||||||
if (this.mode === 'image') {
|
|
||||||
if (!isImage) {
|
|
||||||
this.tempIndex--;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
_file.url = URL.createObjectURL(file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.uploadedFiles.push(_file);
|
|
||||||
|
|
||||||
file.index = this.uploadedFiles.length - 1;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onProgress(ev, file) {
|
upload(file) {
|
||||||
this.uploadedFiles[file.index].percentage = ev.percent;
|
if (!this.beforeUpload) {
|
||||||
},
|
return this.post(file);
|
||||||
onSuccess(res, file) {
|
}
|
||||||
var _file = this.uploadedFiles[file.index];
|
|
||||||
|
|
||||||
_file.status = 'success';
|
const before = this.beforeUpload(file);
|
||||||
setTimeout(() => {
|
if (before && before.then) {
|
||||||
_file.status = 'finished';
|
before.then(processedFile => {
|
||||||
this.reset();
|
if (Object.prototype.toString.call(processedFile) === '[object File]') {
|
||||||
}, 1000);
|
this.post(processedFile);
|
||||||
|
} else {
|
||||||
|
this.post(file);
|
||||||
|
}
|
||||||
|
}, () => {
|
||||||
|
// this.$emit('cancel', file);
|
||||||
|
});
|
||||||
|
} else if (before !== false) {
|
||||||
|
this.post(file);
|
||||||
|
} else {
|
||||||
|
// this.$emit('cancel', file);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError(err, file) {
|
post(file) {
|
||||||
var _file = this.uploadedFiles[file.index];
|
this.onStart(file);
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append(this.name, file);
|
||||||
|
|
||||||
_file.status = 'finished';
|
ajax(this.action, {
|
||||||
this.uploadedFiles.$remove(_file);
|
headers: this.headers,
|
||||||
this.reset();
|
withCredentials: this.withCredentials,
|
||||||
console.log(err);
|
file: file,
|
||||||
|
filename: this.name,
|
||||||
|
onProgress: e => {
|
||||||
|
this.onProgress(e, file);
|
||||||
|
},
|
||||||
|
onSuccess: res => {
|
||||||
|
this.onSuccess(res, file);
|
||||||
|
},
|
||||||
|
onError: err => {
|
||||||
|
this.onError(err, file);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
reset() {
|
onDrop(e) {
|
||||||
this.uploading = false;
|
this.dragOver = false;
|
||||||
this.percent = 0;
|
this.uploadFiles(e.dataTransfer.files);
|
||||||
this.filename = '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue