方法一:参考链接:Vue + Element 实现导入导出Excel_程序猿小白的博客-CSDN博客_vue 导出excel
方法二 封装代码:下载数据封装(cus-upload.vue)
<template>
<Upload action="//jsonplaceholder.typicode.com/posts/"
:before-upload="onBeforeUpload"
:show-upload-list="false"
:maxSize="maxSize"
:accept="accept">
<slot></slot>
</Upload>
</template>
<script>
export default {
name: 'cus-upload',
props: {
autoUpload: {
type: Boolean,
default: false
},
accept: {
type: String,
// excel -> application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel
// zip -> application/zip
default: ''
},
maxSize: {
type: Number,
default: 12048
},
uploadFnc: {
type: Function,
default: () => {
}
},
fileName: {
type: String,
default: 'file'
},
cusParams: {
type: Object,
default: () => {
return {}
}
}
},
mounted () {
this.onBeforeUpload()
},
methods: {
onBeforeUpload (file) {
if (file && this.autoUpload) {
this.$cu.showLoading()
let params = new FormData()
params.append(this.fileName, file)
this.uploadFnc(params).then(res => {
if ( res.code === 200 ) {
console.log(res)
this.$cu.hideLoading()
this.$Message.success('文件上传成功')
this.$emit('onOk')
} else this.$cu.hideLoading(1.5)
}).catch(() => this.$cu.hideLoading(1.5))
}
else if (file) this.$emit('onBeforeUpload', file)
return false
}
}
}
</script>
<style scoped>
</style>
导入文件封装()
<template>
<div>
<cus-modal ref="modal" title="导入数据" @on-visible-change="onVisibleChange"
width="520">
<div class="draw-section">
<Card class="draw-section-item" @click.native="downloadTemp">
<div class="draw-section-item-logo flex">
<svg t="1628043668627" class="icon" viewBox="0 0 1417 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="19836" width="128" height="128">
<path
d="M708.923077 356.273231c29.617231 0 54.035692 22.528 56.950154 51.436307l0.315077 5.828924v343.04l81.289846-81.211077a57.265231 57.265231 0 0 1 76.327384-4.17477l4.726154 4.17477a57.265231 57.265231 0 0 1 4.096 76.327384l-4.174769 4.726154-179.042461 178.963692a57.265231 57.265231 0 0 1-76.406154 4.17477l-4.568616-4.17477-179.042461-179.042461a57.265231 57.265231 0 0 1 76.406154-85.149539l4.568615 4.17477 81.289846 81.211077V413.538462c0-26.939077 18.589538-49.624615 43.716923-55.611077l7.719385-1.339077L708.923077 356.273231zM708.923077 17.092923c203.303385 0 376.359385 143.123692 408.969846 336.344615l-2.048-10.712615 13.627077 3.308308c126.660923 33.870769 218.112 143.202462 224.964923 271.753846l0.393846 15.596308c0 164.706462-137.688615 298.062769-307.278769 298.062769h-24.260923a56.792615 56.792615 0 0 1-57.501539-56.162462c0-31.113846 25.836308-56.162462 57.501539-56.162461h24.260923c106.338462 0 192.354462-83.259077 192.354462-185.737846 0-97.516308-78.296615-178.648615-178.884924-185.344a56.871385 56.871385 0 0 1-53.484307-51.672616C995.643077 246.075077 865.516308 129.339077 708.923077 129.339077s-286.72 116.736-298.692923 267.027692a56.871385 56.871385 0 0 1-53.405539 51.672616c-100.588308 6.695385-178.806154 87.827692-178.806153 185.344 0 102.4 85.937231 185.737846 192.275692 185.737846h24.260923c31.586462 0 57.501538 25.048615 57.501538 56.162461a56.792615 56.792615 0 0 1-57.501538 56.162462H370.215385C200.704 931.446154 63.015385 798.089846 63.015385 633.383385c0-143.675077 105.550769-266.24 249.540923-292.864l-10.633846 2.284307 1.339076-6.774154C341.858462 157.459692 501.366154 25.521231 690.491077 17.486769z"
p-id="19837"></path>
</svg>
</div>
<div class="draw-section-item-title">下载模板</div>
<div class="draw-section-item-label">下载模板文件</div>
</Card>
<Card class="draw-section-item">
<cus-upload :uploadFnc="uploadFnc" :autoUpload="true" :accept="accept" @onOk="onOk" :cus-params="cusParams"
:fileName="fileName">
<div class="draw-section-item-logo flex">
<svg t="1628043694436" class="icon" viewBox="0 0 1157 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="24667" width="118" height="118">
<path
d="M0.09216 582.528c0-124.37504 82.23744-233.71264 192.1536-266.112C253.07648 156.0832 403.70688 40.96 579.93216 40.96c177.64352 0 324.18304 115.07712 384.96768 275.456 113.4336 33.152 192.19968 141.06624 192.19968 266.112 0 153.96864-119.57248 279.14752-270.91968 279.14752-28.34432 0-53.92896-26.60864-53.92896-56.06912 0-33.8176 25.58464-56.1152 53.92896-56.1152 91.22816 0 163.80928-74.09664 163.80928-166.87616 0-49.61792-21.44768-95.67744-56.64768-125.1328l-9.66144-9.43616a48.96256 48.96256 0 0 0-12.46208-10.05568c-2.75968-3.60448-9.03168-3.60448-12.46208-6.49728h-3.42528c-2.75968-3.5584-6.23104-3.5584-9.0368-6.4512h-3.47136c-2.75968 0-6.23104-3.5584-9.65632-3.5584-2.75968 0-6.23104 0-6.23104-2.8928h-9.0368c-3.47136 0-6.23104 0-9.7024-3.60448h-25.4976c-2.75968-10.81344-6.23104-18.688-6.23104-29.50144-2.75968 0-2.75968-3.5584-2.75968-6.4512-3.42528-6.49728-3.42528-12.90752-6.23104-19.44576 0-3.5584-3.42528-3.5584-3.42528-7.16288-2.75968-6.49728-6.23104-12.90752-9.65632-19.4048v-6.49728c-2.80576-6.4512-9.07776-12.90752-12.46208-19.44576-53.18144-92.11392-151.38816-154.63936-261.97504-154.63936-113.34144 0-211.46624 62.5664-264.68864 154.63936l-9.0368 19.44576c0 2.18112-1.42336 2.18112-2.08896 4.31616l-1.3824 2.18112-9.7024 19.4048v7.16288l-8.94464 19.44576v6.4512c-3.47136 10.77248-6.94272 18.688-6.94272 29.46048h-28.30336c-2.75968 3.60448-6.23104 3.60448-8.94464 3.60448h-6.23104c-2.75968 2.18112-4.14208 2.8928-4.89472 2.8928a1.24928 1.24928 0 0 1-2.048 0c-2.75968 0-6.23104 3.5584-9.03168 3.5584h-6.23104c-3.42528 2.93376-6.23104 2.93376-9.65632 6.49728h-3.42528c-2.75968 2.8928-6.23104 2.8928-9.07776 6.49728h-3.42528c-2.75968 3.5584-6.23104 6.4512-9.7024 10.05568-6.23104 2.84672-8.94464 6.49728-12.416 9.39008-35.24608 29.50656-53.2224 75.56096-53.2224 125.17888 0 92.77952 72.58112 166.87616 160.37888 166.87616 32.4864 0 56.69376 22.29248 56.69376 56.06912 0 29.50656-24.20736 56.07424-56.69376 56.07424-147.82976 0.04096-270.8736-125.13792-270.8736-279.01952v-0.09216z"
p-id="24668"></path>
<path
d="M362.94656 566.72768c0-16.54784 6.23104-28.78976 12.46208-39.56224l163.7632-186.90048c10.41408-10.81344 24.91904-16.55296 40.8064-16.55296 15.92832 0 28.34432 5.7856 41.47712 16.512l160.37888 186.98752c21.5296 22.19008 21.00224 57.63072-1.18784 79.16544a56.00256 56.00256 0 0 1-39.57248 15.80032c-15.92832 0-27.67872-8.6784-38.04672-19.45088l-69.10976-78.40768v281.9584c0 33.8176-24.21248 55.3984-53.93408 55.3984-31.104 0-53.2224-21.5808-53.2224-55.3984v-281.91232L457.69728 602.7264c-10.368 10.81344-25.54368 19.45088-41.43104 19.45088-28.3904 0-53.31456-25.90208-53.31456-55.40352v-0.04608z"
p-id="24669"></path>
</svg>
</div>
<div class="draw-section-item-title">导入excel</div>
<div class="draw-section-item-label">导入excel文件 <br/> 可拖拽上传</div>
</cus-upload>
</Card>
</div>
<div slot="footer">
<div class="modal-footer">
<cus-button size="small" class="mr_2" @onClick="onCancel">关闭</cus-button>
</div>
</div>
</cus-modal>
</div>
</template>
<script>
/**
* @tempSrc 模板导出地址
* @uploadFnc 文件上传方法
* @accept 上传文件类型
* @fileName 文件名,默认file
* @cusParams 自定义额外参数
*
* @onClear 导入文件
*/
const form = {
id: '',
name: '',
age: '',
phonenumber: '',
userId: '',
// index: [],
// phone: '',
// administration: '',
// descr: ''
}
export default {
name: 'addSupplier',
data() {
return {
form: form
}
},
props: {
tempSrc: {
type: String,
default: ''
},
uploadFnc: {
type: Function,
default: () => {
}
},
accept: {
type: String,
// excel -> application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel
default: ''
},
fileName: {
type: String,
default: 'file'
},
cusParams: {
type: Object,
default: () => {
return {}
}
}
},
mounted() {
this.form = this.$cu.deepClone(form)
},
methods: {
onVisibleChange(v) {
if (!v) this.form = this.$cu.deepClone(form)
},
onCancel() {
this.$refs['modal'].show = false
},
onOk() {
this.$refs['modal'].show = false
this.$emit('onOk')
console.log('保存成功')
},
show() {
this.$refs['modal'].show = true
},
downloadTemp() {
window.location.href = this.tempSrc
}
}
}
</script>
<style scoped lang="less">
.draw {
&-section {
display: flex;
align-items: center;
justify-content: space-around;
&-item {
background: white;
display: flex;
flex-direction: column;
align-items: center;
height: 220px;
cursor: pointer;
width: 170px;
&-title {
text-align: center;
margin-top: 10px;
color: rgba(51, 51, 51, 1);
}
&-label {
text-align: center;
color: rgba(153, 153, 153, 1);
}
}
}
}
</style>
cus-model(卡片)
<template>
<Modal v-model="show" :styles="styles" :class-name="className"
:closable="closable"
:mask-closable="maskClosable"
@on-visible-change="onVisibleChange">
<div slot="header" class="modal-header">
<span class="ml_10">{{ title }}</span>
<div class="modal-header-fullscreen" v-if="showFullscreen">
<Icon type="ios-expand" color="#999" size="17" v-if="!fullscreen" @click="fullscreen = !fullscreen"/>
<Icon type="ios-contract" color="#999" size="17" v-if="fullscreen" @click="fullscreen = !fullscreen"/>
</div>
</div>
<slot></slot>
<div slot="footer">
<slot name="footer">
<div class="modal-footer">
<cus-button size="small" class="mr_2" @onClick="onCancel">取消</cus-button>
<cus-button type="primary" size="small" @onClick="onOk">确认</cus-button>
</div>
</slot>
</div>
</Modal>
</template>
<script>
export default {
name: 'cus-modal',
data () {
return {
fullscreen: false,
show: false,
}
},
props: {
title: {
type: String,
default: '添加'
},
width: {
type: [String, Number],
default: 700
},
showFullscreen: {
type: Boolean,
default: false
},
closable: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: true
}
},
computed: {
styles () {
let style = {}
if (!this.fullscreen) {
/*if (style.width.indexOf('px') !== -1 || style.width.indexOf('%') !== -1 || style.width.indexOf('vw') !== -1 || style.width.indexOf('vh') !== -1 || style.width.indexOf('rem') !== -1) {
style.width = `${this.width}`;
} else style.width = `${this.width}px`;*/
style.width = `${this.width}px`
} else {
style.width = '100%'
style.top = 0
}
return style
},
className () {
if (this.fullscreen) {
return 'fullscreen-modal'
} else {
return ''
}
}
},
methods: {
onOk () {
this.$emit('onOk')
},
onCancel () {
this.show = false;
},
onVisibleChange (v) {
this.$emit('on-visible-change', v)
}
}
}
</script>
<style lang="less">
.modal-header {
display: flex;
/*justify-content: center;*/
align-items: center;
position: relative;
height: 20px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
&-fullscreen {
position: absolute;
right: 30px;
cursor: pointer;
i:hover {
color: black !important;
}
}
}
.modal-footer {
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>
cus-button
<template>
<Button :style="[btnStyle]" :disabled="disabled" :type="type" @click="onClick" :ghost="ghost">
<slot></slot>
</Button>
</template>
<script>
export default {
name: "cus-button",
props: {
type: {
type: String,
default: null
},
size: {
type: String,
default: 'default'
},
ghost: {
type: Boolean,
default: false,
},
shape: {
type: String,
default: 'default'
},
cusStyle: {
type: Object,
default: () => {
return {}
}
},
disabled: {
type: Boolean,
default: false
}
},
computed: {
btnStyle() {
let style = {
transition: 'all .1s',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '16px',
padding: '0 16px',
fontFamily: "PingFangSC-Regular, PingFang SC",
// borderRadius: '2px',
cursor: 'pointer',
};
if (this.shape == 'circle') style.borderRadius = '34px';
style = Object.assign(style,this.cusStyle);
if (this.size == 'default') {
style.height = '40px';
} else if (this.size == 'small') {
style.height = '32px';
style.fontSize = '12px';
}
return style;
}
},
methods: {
onClick() {
this.$emit('onClick');
}
}
}
</script>
<style scoped lang="less">
</style>
接口导入
// Excel导入用户信息
export const getUserImportData = (params = {}) => { // 文件上传
return http.post(`${baseURL}/user/importData`, params, { headers: { 'Content-Type': 'multipart/form-data' }
}).then(res => res.data)
}