文件上传
根据正常配置,element ui 的upLoad
组件无法使用。配置和一般人的用法一致。但是用原生form表单又可以使用。
目前初步估计是由于后端的配置问题。但是由于后端知识有限,暂不能知道是什么问题。
目前的暂行办法是: 用原生form + iframe实现该功能,但是拖拽是暂时不能实现了。
具体实现
iframe模拟ajax
文件上传的关键是input的类型设置为file
,并且将from设置属性为enctype="multipart/form -data"
(具体作用未深入)。
但是,这样实现的样式提交的时候会导致浏览器的默认刷新事件,解决办法是通过ajax模拟表单,或者通过iframe。在这里选择用iframe。
若要form和iframe之间产生关联,需要在form标签上增加属性target="nm_iframe"
,并且在iframe上添加属性name="nm_iframe"
。
<form class="cf" enctype="multipart/form-data" method="post" :action="baseUrl + '/check/uploadFile'" target="nm_iframe">
<input style="display: none" type="file" name="files" id="fileInput" @change="handlerUpload" accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label for="fileInput" class="el-button el-button--primary el-button--small">选择文件</label>
</form>
<iframe id="id_iframe" name="nm_iframe"></iframe>
通过这样的设置,在请求返回成功之后,iframe会重新渲染,触发onload事件,会把返回值渲染到iframe中。
根据这个钩子,我们可以做很多事情。
iframeUploadSuccessHandler() {
const uploadIframe = document.querySelector('#id_iframe');
uploadIframe.onload = () => {
let res = JSON.parse(uploadIframe.contentWindow.document.querySelector('body pre').innerHTML)
const head = res.head;
if (head.code == 100) {
this.$message.success(head.message);
this.allFileList = this.allFileList.concat(this.fileList);
this.clearWaitFileList()
return
}
this.$message.error(head.message);
}
}
文件上传的控制
通过input[type=”file”]的change
事件可以控制文件的增删。
setTimeout(() => { // 放在队列后面,等待页面加载完毕
this.fileInput = document.querySelector('#fileInput')
});
handlerUpload(e) {
let fileArray = e.target.files;
this.fileList = Array.from(fileArray); // 将fileLIst转为数组
this.successUpload = false;
},
deleteFile() {
this.clearWaitFileList()
},
// 清空待上传文件列表
clearWaitFileList() {
this.fileInput.value = '';
this.fileList = [];
}
最终代码:
<template>
<el-dialog title="对账" v-model="dialogCheck" size="tiny" :close-on-click-modal="false" @close="closeDialog" custom-class="dialog-w-400">
<div>
<p class="bold">选择对账类型</p>
<el-checkbox-group v-model="dataType">
<el-checkbox v-for="(d, k) in dataTypeOpts" :key="k" :label="d.value">{{d.label}}</el-checkbox>
</el-checkbox-group>
</div>
<div>
<p class="bold">选择对账日期</p>
<el-date-picker
v-model="checkDateRange"
type="daterange"
:picker-options="finishDateOpts"
placeholder="选择时间范围">
</el-date-picker>
</div>
<div class="cf">
<p class="bold">增加数据对账
<i class="iconfont cursor font-20 mgr10 inline-block" title="展开" @click="showMore = true" v-show="!showMore"></i>
<i class="iconfont cursor font-20 mgr10 inline-block" title="收起" @click="showMore = false" v-show="showMore"></i>
</p>
<form class="cf" enctype="multipart/form-data" method="post" :action="baseUrl + '/check/uploadFile'" v-show="showMore" target="nm_iframe">
<input style="display: none" type="file" name="files" id="fileInput" @change="handlerUpload" accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label for="fileInput" class="el-button el-button--primary el-button--small">选择文件</label>
<input type="hidden" name="checkId" :value="UUID">
<input type="submit" class="el-button el-button--success el-button--small mgl10" :class="{'not-allowed': !fileList.length}" name="提交" value="上传到服务器" :disabled="!fileList.length">
<div class="color-gray font-12">(只能上传excel文件,且不超过10M)</div>
<div class="font-12 mt10" style="list-style: none">
<li class="fong-12 cf" v-for="(d, k) in allFileList" :key="k">
<i class="el-icon-document"></i>
{{d.name}}
<i class="el-icon-upload-success el-icon-circle-check color-success fr" style="margin-top: 3px" ></i>
</li>
<li class="fong-12 cf" v-for="(d, k) in fileList" :key="k">
<i class="el-icon-document"></i>
{{d.name}}
<i class="iconfont cursor font-13 fr" style="margin: 3px -5px 0 0" @click="deleteFile(k)"></i>
</li>
</div>
</form>
<iframe id="id_iframe" name="nm_iframe" style="display:none;></iframe>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="check">开始对账</el-button>
</span>
</el-dialog>
</template>
<script>
export default{
created() {
this.init();
},
mounted() {
},
props:{
dialogCheck: {
type: Boolean,
default: false
}
},
data() {
return {
dataType: [],
dataTypeOpts: [
{
value: 1,
label: '放款'
},
{
value: 2,
label: '实收'
}
],
checkDateRange: null,
pickerOpts: {},
showMore: false,
fileList: [],
allFileList: [],
UUID: null,
successUpload: false,
fileInput: {},
}
},
computed: {
},
methods: {
init() {
this.finishDateOpts = {
disabledDate(time) {
let thisTime = time.getTime();
// 禁用今天及以后
return (thisTime > (new Date().setHours(0, 0, 0, 0)) - 1);
}
}
},
closeDialog() {
this.dataType = [];
this.checkDateRange = null;
this.showMore = false;
this.successUpload = false;
this.fileList = [];
this.allFileList = [];
this.$emit('close')
},
check() {
let dataType = this.dataType;
if(!dataType.length) {
this.$message.error('至少选择一个对账类型')
return
}
if (!this.checkDateRange || !this.checkDateRange[0] || !this.checkDateRange[1]) {
this.$message.error('请选择对账日期')
return
}
const config = {
checkTypes: this.dataType.join(','),
checkId: this.UUID,
startDate: this.checkDateRange[0].format('yyyy-MM-dd'),
endDate: this.checkDateRange[1].format('yyyy-MM-dd'),
};
if (dataType.length === 1) {
config.dataType = this.dataType[0]
}
const loadingInstance = this.$loading({
fullscreen: true,
text: '对账中'
})
this.$http.post('/check/manualCheck', config).then(res => {
loadingInstance.close();
this.closeDialog();
let head = res.data.head || {};
if(head.code == '100') {
this.$message.success(head.message||'对账完毕')
this.$emit('update')
return;
}
this.$message.error(head.message||'对账失败')
})
},
iframeUploadSuccessHandler() {
const uploadIframe = document.querySelector('#id_iframe');
uploadIframe.onload = () => {
let res = JSON.parse(uploadIframe.contentWindow.document.querySelector('body pre').innerHTML)
const head = res.head;
if (head.code == 100) {
this.$message.success(head.message);
this.allFileList = this.allFileList.concat(this.fileList);
this.clearWaitFileList()
return
}
this.$message.error(head.message);
}
},
handlerUpload(e) {
let fileArray = e.target.files;
this.fileList = Array.from(fileArray); // 将fileLIst转为数组
this.successUpload = false;
},
deleteFile() {
this.clearWaitFileList()
},
// 清空待上传文件列表
clearWaitFileList() {
this.fileInput.value = '';
this.fileList = [];
}
},
watch: {
dialogCheck(value) {
if (value) {
this.UUID = Vue.com.generateUUID();
setTimeout(() => { // 放在队列后面,等待页面加载完毕
this.fileInput = document.querySelector('#fileInput')
});
}
},
showMore(value) {
if (value) {
this.iframeUploadSuccessHandler();
} else {
this.clearWaitFileList()
}
}
}
}
</script>
<style lang="less" scoped>
#fileInput {
border: 0;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #c4c4c4;
color: #1f2d3d;
margin: 0;
padding: 2px 15px;
border-radius: 4px;
-webkit-appearance: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
outline: 0;
text-align: center;
}
</style>
最终效果:
拖拽上传
MDN
有很好的教程。
参考: