2017-01-19 16:26:31 +08:00
|
|
|
<template>
|
2017-01-22 14:48:38 +08:00
|
|
|
<div :class="[prefixCls]">
|
|
|
|
<div
|
|
|
|
:class="classes"
|
|
|
|
@click="handleClick"
|
|
|
|
@drop.prevent="onDrop"
|
|
|
|
@dragover.prevent="dragOver = true"
|
|
|
|
@dragleave.prevent="dragOver = false">
|
|
|
|
<input
|
|
|
|
v-el:input
|
|
|
|
:class="[prefixCls + '-input']"
|
|
|
|
type="file"
|
|
|
|
@change="handleChange"
|
|
|
|
:multiple="multiple"
|
|
|
|
:accept="accept">
|
|
|
|
<slot></slot>
|
|
|
|
</div>
|
|
|
|
<slot name="tip"></slot>
|
|
|
|
<upload-list
|
|
|
|
v-if="showUploadList"
|
|
|
|
:files="fileList"
|
|
|
|
@on-file-remove="handleRemove"
|
|
|
|
@on-file-preview="handlePreview"></upload-list>
|
2017-01-19 18:16:41 +08:00
|
|
|
</div>
|
2017-01-19 16:26:31 +08:00
|
|
|
</template>
|
|
|
|
<script>
|
2017-01-22 14:48:38 +08:00
|
|
|
import UploadList from './upload-list.vue';
|
2017-01-19 18:16:41 +08:00
|
|
|
import ajax from './ajax';
|
|
|
|
import { oneOf } from '../../utils/assist';
|
|
|
|
|
|
|
|
const prefixCls = 'ivu-upload';
|
|
|
|
|
2017-01-19 16:26:31 +08:00
|
|
|
export default {
|
2017-01-22 14:48:38 +08:00
|
|
|
components: { UploadList },
|
2017-01-19 18:16:41 +08:00
|
|
|
props: {
|
|
|
|
action: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
headers: {
|
|
|
|
type: Object,
|
|
|
|
default () {
|
2017-01-19 18:17:06 +08:00
|
|
|
return {};
|
2017-01-19 18:16:41 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
multiple: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
data: {
|
|
|
|
type: Object
|
|
|
|
},
|
|
|
|
name: {
|
|
|
|
type: String,
|
|
|
|
default: 'file'
|
|
|
|
},
|
|
|
|
withCredentials: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
showUploadList: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
type: {
|
|
|
|
type: String,
|
|
|
|
validator (value) {
|
|
|
|
return oneOf(value, ['select', 'drag']);
|
2017-01-22 14:48:38 +08:00
|
|
|
},
|
|
|
|
default: 'select'
|
2017-01-19 18:16:41 +08:00
|
|
|
},
|
|
|
|
format: {
|
|
|
|
type: Array,
|
|
|
|
default () {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
accept: {
|
|
|
|
type: String
|
|
|
|
},
|
|
|
|
maxSize: {
|
|
|
|
type: Number
|
|
|
|
},
|
|
|
|
beforeUpload: Function,
|
|
|
|
onProgress: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onSuccess: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onError: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onRemove: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onPreview: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onExceededSize: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onFormatError: {
|
|
|
|
type: Function,
|
|
|
|
default () {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
},
|
|
|
|
defaultFileList: {
|
|
|
|
type: Array,
|
|
|
|
default() {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2017-01-19 16:26:31 +08:00
|
|
|
data () {
|
2017-01-19 18:16:41 +08:00
|
|
|
return {
|
|
|
|
prefixCls: prefixCls,
|
|
|
|
dragOver: false,
|
|
|
|
fileList: [],
|
|
|
|
tempIndex: 1
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
classes () {
|
|
|
|
return [
|
|
|
|
`${prefixCls}`,
|
|
|
|
{
|
2017-01-22 14:48:38 +08:00
|
|
|
[`${prefixCls}-select`]: this.type === 'select',
|
2017-01-19 18:16:41 +08:00
|
|
|
[`${prefixCls}-drag`]: this.type === 'drag',
|
2017-01-22 15:25:00 +08:00
|
|
|
[`${prefixCls}-dragOver`]: this.type === 'drag' && this.dragOver
|
2017-01-19 18:16:41 +08:00
|
|
|
}
|
|
|
|
];
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
handleClick () {
|
|
|
|
this.$els.input.click();
|
|
|
|
},
|
|
|
|
handleChange (e) {
|
|
|
|
const files = e.target.files;
|
|
|
|
|
|
|
|
if (!files) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.uploadFiles(files);
|
|
|
|
this.$els.input.value = null;
|
|
|
|
},
|
|
|
|
onDrop (e) {
|
|
|
|
this.dragOver = false;
|
|
|
|
this.uploadFiles(e.dataTransfer.files);
|
|
|
|
},
|
|
|
|
uploadFiles (files) {
|
|
|
|
let postFiles = Array.prototype.slice.call(files);
|
|
|
|
if (!this.multiple) postFiles = postFiles.slice(0, 1);
|
|
|
|
|
|
|
|
if (postFiles.length === 0) return;
|
|
|
|
|
|
|
|
postFiles.forEach(file => {
|
|
|
|
this.upload(file);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
upload (file) {
|
|
|
|
if (!this.beforeUpload) {
|
|
|
|
return this.post(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
const before = this.beforeUpload(file);
|
|
|
|
if (before && before.then) {
|
|
|
|
before.then(processedFile => {
|
|
|
|
if (Object.prototype.toString.call(processedFile) === '[object File]') {
|
|
|
|
this.post(processedFile);
|
|
|
|
} else {
|
|
|
|
this.post(file);
|
|
|
|
}
|
|
|
|
}, () => {
|
|
|
|
// this.$emit('cancel', file);
|
|
|
|
});
|
|
|
|
} else if (before !== false) {
|
|
|
|
this.post(file);
|
|
|
|
} else {
|
|
|
|
// this.$emit('cancel', file);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
post (file) {
|
2017-01-22 17:19:37 +08:00
|
|
|
// check format
|
|
|
|
if (this.format.length) {
|
|
|
|
const _file_format = file.name.split('.').pop().toLocaleLowerCase();
|
|
|
|
const checked = this.format.some(item => item.toLocaleLowerCase() === _file_format);
|
|
|
|
if (!checked) {
|
2017-01-22 18:08:36 +08:00
|
|
|
this.onFormatError(file, this.fileList);
|
2017-01-22 17:19:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check maxSize
|
|
|
|
if (this.maxSize) {
|
|
|
|
if (file.size > this.maxSize * 1024) {
|
2017-01-22 18:08:36 +08:00
|
|
|
this.onExceededSize(file, this.fileList);
|
2017-01-22 17:19:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 18:16:41 +08:00
|
|
|
this.handleStart(file);
|
|
|
|
let formData = new FormData();
|
|
|
|
formData.append(this.name, file);
|
|
|
|
|
|
|
|
ajax({
|
|
|
|
headers: this.headers,
|
|
|
|
withCredentials: this.withCredentials,
|
|
|
|
file: file,
|
|
|
|
data: this.data,
|
|
|
|
filename: this.name,
|
|
|
|
action: this.action,
|
|
|
|
onProgress: e => {
|
|
|
|
this.handleProgress(e, file);
|
|
|
|
},
|
|
|
|
onSuccess: res => {
|
|
|
|
this.handleSuccess(res, file);
|
|
|
|
},
|
|
|
|
onError: (err, response) => {
|
|
|
|
this.handleError(err, response, file);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
handleStart (file) {
|
|
|
|
file.uid = Date.now() + this.tempIndex++;
|
|
|
|
const _file = {
|
|
|
|
status: 'uploading',
|
|
|
|
name: file.name,
|
|
|
|
size: file.size,
|
|
|
|
percentage: 0,
|
|
|
|
uid: file.uid,
|
|
|
|
showProgress: true
|
|
|
|
};
|
|
|
|
|
|
|
|
this.fileList.push(_file);
|
|
|
|
},
|
|
|
|
getFile (file) {
|
|
|
|
const fileList = this.fileList;
|
|
|
|
let target;
|
|
|
|
fileList.every(item => {
|
|
|
|
target = file.uid === item.uid ? item : null;
|
|
|
|
return !target;
|
|
|
|
});
|
|
|
|
return target;
|
|
|
|
},
|
|
|
|
handleProgress (e, file) {
|
|
|
|
const _file = this.getFile(file);
|
|
|
|
this.onProgress(e, _file, this.fileList);
|
|
|
|
_file.percentage = e.percent || 0;
|
|
|
|
},
|
|
|
|
handleSuccess (res, file) {
|
|
|
|
const _file = this.getFile(file);
|
|
|
|
|
|
|
|
if (_file) {
|
|
|
|
_file.status = 'finished';
|
|
|
|
_file.response = res;
|
|
|
|
|
2017-01-22 15:02:06 +08:00
|
|
|
this.$dispatch('on-form-change', _file);
|
2017-01-19 18:16:41 +08:00
|
|
|
this.onSuccess(res, _file, this.fileList);
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
_file.showProgress = false;
|
|
|
|
}, 1000);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
handleError (err, response, file) {
|
|
|
|
const _file = this.getFile(file);
|
|
|
|
const fileList = this.fileList;
|
|
|
|
|
|
|
|
_file.status = 'fail';
|
|
|
|
|
|
|
|
fileList.splice(fileList.indexOf(_file), 1);
|
|
|
|
|
|
|
|
this.onError(err, response, file);
|
|
|
|
},
|
|
|
|
handleRemove(file) {
|
|
|
|
const fileList = this.fileList;
|
|
|
|
fileList.splice(fileList.indexOf(file), 1);
|
|
|
|
this.onRemove(file, fileList);
|
|
|
|
},
|
|
|
|
handlePreview(file) {
|
|
|
|
if (file.status === 'finished') {
|
|
|
|
this.onPreview(file);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
clearFiles() {
|
|
|
|
this.fileList = [];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
defaultFileList: {
|
|
|
|
immediate: true,
|
|
|
|
handler(fileList) {
|
|
|
|
this.fileList = fileList.map(item => {
|
|
|
|
item.status = 'finished';
|
|
|
|
item.percentage = 100;
|
|
|
|
item.uid = Date.now() + this.tempIndex++;
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-01-19 16:26:31 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|