elementui封装下载模板和上传组件
封装代码如下
<template>
<div>
<el-dialog
:title="exportStatus? '导入结果' : '一键导入数据'"
:visible.sync="dialogVisible"
width="905px"
:before-close="handleClose"
class="export-standard-speech"
>
<div class="standard-export" v-if="!exportStatus">
<div class="export-title">1、下载导入模板</div>
<div class="export-warning">根据提示完善表格内容</div>
<div class="export-download-btn">
<img
src="@/assets/img/download-demo-icon.png"
width="12px"
style="
vertical-align: baseline;
margin-right: 3px;
margin-top:2px;
display: inline-block;
"
/>
<a
class="a-line"
:href="downloadDemoUrl" rel="external nofollow"
download="项目导入模板.xlsx"
title="下载空的表格模板"
>下载空的表格模板</a>
</div>
<div class="export-title">2、上传完善后的表格</div>
<el-upload
class="upload-demo-xls"
drag
ref="speechDemoUpload"
action=""
:file-list="fileList"
:auto-upload="false"
:show-file-list="false"
accept=".xls,.xlsx,.csv"
:on-change="handleChange"
>
<div class="el-upload__text" v-if="!uploadStatus">将文件拖到此处,或点击<em>上传</em></div>
<div class="el-upload__text" v-else>
<span class="file-name">{{ this.file && this.file.name }}</span>
<span class="file-size">({{bytesToSize(this.file.size)}})</span>
<span class="file-select">重新选择</span>
</div>
</el-upload>
<div class="h32 flex-center-center" style="margin-top:38px">
<Button text="取消" background="#fff" border="#4646E6" color="#4646E6" class="ml10" @click.native="cancelExport" ></Button>
<Button text="导入" background="#4646E6" color="#fff" class="ml10" @click.native="xlsDemoExport" :setGray="isFile"></Button>
</div>
</div>
<div v-if="exportStatus && failNum > 0">
<div class="fail-num">
<img src="@/assets/img/export-fail-img.png" alt="" class="mr10">
导入失败
<span>{{failNum}}条</span>
数据
</div>
<div class="export-fail-table">
<div class="export-fail-text">以下为导入失败的项目,您可修改后重新导入</div>
<el-table
:data="tableData"
height="220"
>
<el-table-column
prop="lineNum"
label="Execel行数"
width="220"
align="left"
>
</el-table-column>
<el-table-column
prop="projectCode"
label="项目编号"
width="220"
align="center"
>
</el-table-column>
<el-table-column
prop="failReason"
label="失败原因"
width="220"
align="right"
>
</el-table-column>
</el-table>
</div>
<div class="h32 flex-center-center" style="margin-top:23px">
<Button text="关闭" background="#fff" border="#4646E6" color="#4646E6" @click.native="cancelExport" ></Button>
</div>
</div>
<div v-if="exportStatus && failNum == 0">
<div class="success-img">
<img src="@/assets/img/export-success-img.png" alt="" class="mr10">
</div>
<div class="success-text">
成功导入
<span>{{ successNum }}条</span>
数据
</div>
<div class="h32 flex-center-center" style="margin-top:23px">
<Button text="完成" background="#4646E6" color="#fff" class="" @click.native="cancelExport"></Button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import Button from "@/components/Button";
import { upload, service } from '@/utils/request-brand'
import { bytesToSize } from '@/utils'
export default {
name: 'ImportData',
components: {
Button
},
props: {
showDialogVisible: {
type: Boolean,
default: false,
required: true
},
downloadDemoUrl:{
type: String,
required: true
},
uploadFileUrl:{
type: String,
required: true
},
// 考虑上传时其他参数的情况
otherUploadData:{
type: Object,
default:() => {
return {}
}
}
},
computed: {
userAccountID() {
return this.$store.state.user.userAccountID;
},
isFile(){
if(this.file){
return false
} else {
return true
}
}
},
watch: {
showDialogVisible(newVal) {
// console.log(newVal);
this.dialogVisible = newVal
}
},
data () {
return {
dialogVisible: false,
fileList: [],
file: null,
// 上传文件的状态切换
uploadStatus: false,
successNum: 0,
failNum: 0,
tableData: [],
// 导入的状态
exportStatus: false,
};
},
methods: {
bytesToSize,
handleClose(done) {
this.dialogVisible = false
this.$emit('dialogVisible', false)
},
// 取消或者清空上传的文件和数据
cancelExport(){
// this.$refs.speechDemoUpload.clearFiles()
this.fileList = []
this.file = null
this.successNum = 0
this.failNum = 0
this.tableData = []
this.uploadStatus = false
this.exportStatus = false
this.$emit('dialogVisible', false)
},
// 上传的文件改变时(覆盖原来的文件)
handleChange(file, fileList){
// console.log(file);
let extension = file.raw.name.substring(file.raw.name.lastIndexOf(".") + 1);
let size = file.size / 1024 / 1024;
// let size = file.size / 1024;
// console.log(extension, extension.toLowerCase() !== "xlsx");
if (!['xlsx','xls','csv'].includes(extension.toLowerCase())) {
this.$message.warning("文件格式不正确,请上传xls / xlsx / csv格式");
return false;
}
if (size > 10) {
this.$message.warning("文件过大,请进行拆分后分多次上传");
return false
}
// console.log(file.raw, fileList);
if (fileList.length > 0) {
this.fileList = [fileList[fileList.length - 1]] // 这一步,是展示最后一次选择的csv文件
this.file = this.fileList[0].raw
}
// console.log(this.file);
this.uploadStatus = true
},
async xlsDemoExport(){
if (!this.file) {
// return this.$message.error('请上传文件')
return false
}
const formData = new FormData()
formData.append('file', this.file)
// 添加其他参数
if(Object.values(this.otherUploadData).length > 0){
for (let key in this.otherUploadData) {
formData.append(key, this.otherUploadData[key])
}
}
// 调用上传接口...
this.$loading.show()
// `${process.env.VUE_APP_BASE_BRAND_API}/v1/inspectionSpeechArt/importExcel
upload.uploadFile(this.uploadFileUrl, formData).then(res => {
if(res.code == 0){
this.exportStatus = true
this.tableData = res.item.failList.map(item => {
let obj = {}
obj.lineNum = item.lineNum
obj.failReason = item .failReason
obj.projectCode = item. projectCode
return obj
})
this.failNum = res.item.failNum
this.successNum = res.item.successNum
} else {
this.$message.error(res.message)
}
this.$loading.hide()
}).catch((error) => {
console.log(error);
this.$message.error('上传失败,请稍后再试或联系IT解决')
this.$loading.hide()
})
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog{
width: 25%;
border-radius: 12px;
margin-top:-8vh !important;
top: 50%;
transform: translateY(-50%);
}
::v-deep .el-dialog__header {
border-bottom: 1px solid #efeff6;
padding-left: 50px;
.el-dialog__title,
.el-dialog__headerbtn i {
color: #36395c !important;
font-size: 18px !important;
font-weight: 600;
}
}
</style>
<style lang="scss">
.export-standard-speech {
.el-list-enter-active,
.el-list-leave-active {
transition: none;
}
.el-list-enter,
.el-list-leave-active {
opacity: 0;
}
.el-upload-list {
height: 40px;
}
// 表格body
.el-dialog__body{
padding: 30px 100px;
}
// 导入
.standard-export{
.upload-demo-xls{
width: 100%;
margin-top: 20px;
}
.el-upload.el-upload--text{
width: 100%;
}
.el-upload-dragger{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #EFEFF6;
height: 120px;
.el-upload__text{
font-weight: 600;
color: #36395C;
.file-name{
color: #4646E6;
}
.file-size{
color: #CCCDD8;
}
.file-select{
color: #4646E6;
text-decoration: underline;
}
}
}
.export-title{
font-size: 14px;
color: #36395C;
font-weight: 600;
line-height: 20px;
}
.export-warning{
font-size: 14px;
color: #CCCDD8;
line-height: 20px;
}
.export-download-btn{
width: 165px;
height: 36px;
border: 1px solid #4646E6;
color: #4646E6;
opacity: 1;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0 30px;
}
}
// 导入失败的表格数据
.fail-num{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 24px;
font-size: 16px;
color: #36395C;
font-weight: 600;
span{
color: #EF6E49;
margin: 0 3px;
}
}
.export-fail-table{
width: 100%;
height: 280px;
border: 1px solid #EFEFF6;
border-radius: 6px;
padding: 0 20px;
.export-fail-text{
font-size: 14px;
line-height: 20px;
color: #36395C;
font-weight: 600;
margin-bottom: 20px;
margin-top: 20px;
}
.el-table__row {
height: 60px;
td {
padding: 0 30px;
}
}
.has-gutter tr {
height: 60px;
}
.has-gutter tr th {
font-size: 14px;
color: #333333;
font-family: Arial;
padding: 0 20px;
}
thead th {
font-size: 14px;
color: #333333;
font-weight: 600;
height: 40px;
background: #F5F6FB;
}
// 滚动条的宽度
.el-table__body-wrapper::-webkit-scrollbar {
width: 6px; // 横向滚动条
height: 6px; // 纵向滚动条
}
// 滚动条的滑块
.el-table__body-wrapper::-webkit-scrollbar-thumb {
background-color: #E2E2E2;
border-radius: 3px;
}
}
.success-img{
display: flex;
justify-content: center;
align-items: center;
margin-top: 103px;
}
.success-text{
display: flex;
justify-content: center;
align-items: center;
margin-top: 30px;
margin-bottom: 50px;
font-size: 16px;
color: #36395C;
font-weight: 600;
span{
color: #4646E6;
margin: 0 3px;
}
}
}
</style>
页面使用
只上传文件的形式
<template>
<div class="upload">
<Button text="批量导入" background="#36395C" color="#fff" :icon="true" @click.native="handleExportBtn" />
// ...
<ImportData
:showDialogVisible="exportVisible"
:downloadDemoUrl="downloadStandardSpeech"
:uploadFileUrl="uploadFileUrl"
@dialogVisible="closeVisible"
/>
</div>
</template>
<script>
import ImportData from '@/views/components/ImportData.vue'
export default {
name: "index",
components: {
ImportData,
},
data() {
return {
// 导入弹框显示和隐藏
exportVisible: false,
downloadStandardSpeech: `${process.env.VUE_APP_EXPORTDEOM_API}/fileResources/templates_standardSpeech.xlsx`, // 模板下载文件地址,
uploadFileUrl: 'http://10.0.0.10:3000/v1/inspectionSpeechArt/importExcel' // 可以写在配置文件中
};
},
computed: {
userAccountID() {
return this.$store.state.user.userAccountID;
},
},
// created() {
// this.getDataList();
// this.getCheckType();
// },
activated() {
this.getDataList();
this.getCheckType();
},
watch:{},
methods: {
// 导入
handleExportBtn(){
this.exportVisible = true
},
// 关闭导入
closeVisible(){
this.exportVisible = false
// 刷新列表等操作
},
},
};
</script>
<style lang="scss" scoped>
</style>
上传文件和其他必传参数的形式
<template>
<div class="upload">
<Button text="批量导入" background="#36395C" color="#fff" :icon="true" @click.native="handleExportBtn" />
// ...
<ImportData
:showDialogVisible="exportVisible"
:downloadDemoUrl="downloadStandardSpeech"
:uploadFileUrl="uploadFileUrl"
:otherUploadData="otherUploadData"
@dialogVisible="closeVisible"
/>
</div>
</template>
<script>
import ImportData from '@/views/components/ImportData.vue'
export default {
name: "index",
components: {
ImportData,
},
data() {
return {
// 导入弹框显示和隐藏
exportVisible: false,
downloadStandardSpeech: `${process.env.VUE_APP_EXPORTDEOM_API}/fileResources/templates_standardSpeech.xlsx`, // 模板下载文件地址,
uploadFileUrl: 'http://10.0.0.10:3000/v1/inspectionSpeechArt/importExcel',
otherUploadData: {},
};
},
computed: {
userAccountID() {
return this.$store.state.user.userAccountID;
},
},
// created() {
// this.getDataList();
// this.getCheckType();
// this.otherUploadData = { key : 'value' };
// },
activated() {
this.getDataList();
this.getCheckType();
this.otherUploadData = { key : 'value' };
},
watch:{},
methods: {
// 导入
handleExportBtn(){
this.exportVisible = true
},
// 关闭导入
closeVisible(){
this.exportVisible = false
// 刷新列表等操作
},
},
};
</script>
<style lang="scss" scoped>
</style>
效果如下
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。