重要代码已标红
用到的插件组件
npm i element
npm i xlsx
vue3 引入写法有差异 具体自行百度
html:
<div class="crenter">
<div>
<el-card class="box-card">
<el-upload ref="upload" accept=".xls,.xlsx" action="#" :auto-upload="false"
:multiple="false" :file-list="fileList" :before-upload="beforeUpload"
:http-request="uploadHttpRequest" :on-remove="fileRemove" :on-change="fileChange"
drag >
<img class="upImg" src="../../style/img/up.png" alt="" />
<el-button class="buttonUp" type="primary">上传excel</el-button>
<div class="el-upload__text">或者拖放一个文件</div>
</el-upload>
</el-card>
<div class="el-upload__tip">只能上传excel文件,且不超过500kb</div>
</div>
<div>
<el-button style="width: 450px; margin: 20px auto; padding: 15px" type="primary" @click="submitUpload">确认上传</el-button>
</div>
</div>
js:
引入组件
import XLSX from '../../../node_modules/xlsx'
export default {
data() {
return {
options: [
{
value: 1,
label: '整包',
},
{
value: 2,
label: '散包',
},
{
value: 3,
label: '单一来源',
},
],
is_type: '',
action: process.env.VUE_APP_BASE_API + '/business/BizMaterialSum/importData',
// 用户导入参数
fileList: [],
// 读取
defaultIndex: 0, // 默认显示第一个工作表
wb: null, // 工作表对象
formData: {},
}
},
created() {},
methods: {
beforeUpload(file) {
//文件类型
const isType = file.type === 'application/vnd.ms-excel'
const isTypeComputer = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const fileType = isType || isTypeComputer
if (!fileType) {
this.$message.error('上传文件只能是xls/xlsx格式!')
}
// 文件大小限制为10M
const fileLimit = file.size / 1024 / 1024 < 10
if (!fileLimit) {
this.$message.error('上传文件大小不超过10M!')
}
return fileType && fileLimit
},
// 自定义上传方法,param是默认参数,可以取得file文件信息,具体信息如下图
uploadHttpRequest(param) {
// const formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加
// formData.append('file', param.file) //添加文件对象
// formData.append('uploadType', this.is_type) //接口要传的参数
// // 调用接口api
// importData(formData).then((data) => {
// if (data.code == 200) {
// this.msgSuccess('成功')
// param.onSuccess() // 上传成功的文件显示绿色的对勾
// this.fileList = []
// this.is_type = ''
// } else {
// this.msgError(data.msg)
// }
// })
},
// 点击上传:手动上传到服务器,此时会触发组件的http-request
submitUpload() {
if (this.is_type && this.fileList) {
// this.$refs.upload.submit()
// console.log(this.formData)
importData(this.formData).then((data) => {
if (data.code == 200) {
this.msgSuccess('成功')
this.fileList = []//清空上传的文件展示列表
this.is_type = ''
this.$refs.upload.clearFiles()//清空已上传的文件列表(该方法不支持在 before-upload 中调用)
} else {
this.msgError(data.msg)
}
})
} else if (this.is_type && this.fileList.length == 0) {
this.msgError('请选择上传文件')
} else if (!this.is_type && this.fileList.length != 0) {
this.msgError('请选择导入模式')
} else if (!this.is_type && this.fileList.length == 0) {
this.msgError('请选择导入模式和上传文件')
}
},
// 移除选择的文件
fileRemove(file, fileList) {
if (fileList.length < 1) {
this.uploadDisabled = true //未选择文件则禁用上传按钮
}
},
// 取消
closeDialog() {
this.$refs.upload.clearFiles() //清除上传文件对象
this.fileList = [] //清空选择的文件列表
this.$emit('close', false)
},
// 文件发生改变
fileChange(file, fileList) {
// if (fileList.length > 0) {
// this.fileList = [fileList[fileList.length - 1]] // 展示最后一次选择的文件
// }
// console.log(file)
this.formData = {
Name: file.name,
IsType: this.is_type,
}
let files = { 0: file.raw }
this.readExcel(files)
},
// 导入用XLSX读取文档
readExcel(files) {
var that = this
// 如果没有⽂件名
if (files.length <= 0) {
return false
} else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {
this.$Message.error('上传格式不正确,请上传xls或者xlsx格式')
return false
}
const fileReader = new FileReader()
fileReader.onload = (ev) => {
try {
const data = ev.target.result
const workbook = XLSX.read(data, {
type: 'binary',
})
// 取第⼀张表
const wsname = workbook.SheetNames[0] //
// ⽣成
// 表格内容
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname])
console.log(ws, 'ws是表格⾥的数据,且是json格式')
let list = ws.map((item) => {
return {
Coding: (item.物料编码)+'',
Name: (item.物料名称)+'',
Specification: (item.规格型号)+'',
Units: (item.计量单位)+'',
AllName: (item.全名)+'',
ApplyNumber: (item.申请数量),
AdjustNumber: (item.调剂后数量),
Remark: (item.备注)+'',
}
})
this.formData.BizMaterialSon = list
// 重写数据
this.$refs.upload.value = ''
} catch (e) {
return false
}
}
fileReader.readAsBinaryString(files[0])
},
},
}
</script>
css:掺杂了一些其他的代码
<style scoped lang="scss">
.title {
text-align: center;
font-size: 70px;
font-weight: 600;
}
.crenter {
width: 450px;
margin: 20px auto;
}
.select {
position: relative;
}
.selectright {
width: 450px;
margin: 20px auto;
}
.selectLeft {
width: 410px;
position: absolute;
left: 54%;
top: 0;
}
.upload-demo {
width: 100%;
}
.upImg {
width: 150px;
// height: 100px;
margin: 10px auto;
}
</style>
<style scoped>
.upload-demo >>> .el-upload-dragger {
border: none;
height: 250px !important;
width: 100%;
}
.box-card >>> .el-upload-dragger {
border: none;
height: 208px !important;
width: 100%;
}
.el-card.is-always-shadow {
-webkit-box-shadow: 0 2px 12px 0 #f0f0f0;
box-shadow: 0px -6px 20px 0 #f0f0f0;
border: none;
}
.box-card >>> .el-upload {
display: block !important;
}
.buttonUp {
display: block;
width: 140px;
padding: 15px;
border-radius: 5px;
margin: 0px auto;
margin-bottom: 10px;
}
.el-upload__tip {
text-align: center;
color: #a7a3a2;
padding: 20px;
box-shadow: 0px 4px 14px 0px #f0f0f0;
margin-top: 0px;
}
</style>
整合:一整个页面里的代码,可以复制过去自己修改
<template>
<div class="app-container home">
<div style="padding-top: 30px">
<div class="title">上传excel导入物料采购单</div>
<div class="select">
<div class="selectright">
<el-form>
<el-form-item label="导入模式">
<el-select v-model="is_type" placeholder="请输入导入模式">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div class="selectLeft">
<span style="color: red">*</span>
打包为整包、散包、单一来源;为整包时,填写价格时不可填写0,且每个都必填;为散包时,价格可填写为0。
</div>
</div>
<div class="crenter">
<div>
<el-card class="box-card">
<el-upload
ref="upload"
accept=".xls,.xlsx"
action="#"
:auto-upload="false"
:multiple="false"
:file-list="fileList"
:before-upload="beforeUpload"
:http-request="uploadHttpRequest"
:on-remove="fileRemove"
:on-change="fileChange"
drag
>
<img class="upImg" src="../../style/img/up.png" alt="" />
<el-button class="buttonUp" type="primary">上传excel</el-button>
<div class="el-upload__text">或者拖放一个文件</div>
</el-upload>
</el-card>
<div class="el-upload__tip">只能上传excel文件,且不超过500kb</div>
</div>
<div><el-button style="width: 450px; margin: 20px auto; padding: 15px" type="primary" @click="submitUpload">确认上传</el-button></div>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { importData } from '@/api/purchase/purchase'
import XLSX from '../../../node_modules/xlsx'
export default {
data() {
return {
options: [
{
value: 1,
label: '整包',
},
{
value: 2,
label: '散包',
},
{
value: 3,
label: '单一来源',
},
],
is_type: '',
action: process.env.VUE_APP_BASE_API + '/business/BizMaterialSum/importData',
// 用户导入参数
fileList: [],
// 读取
defaultIndex: 0, // 默认显示第一个工作表
wb: null, // 工作表对象
formData: {},
}
},
created() {},
methods: {
beforeUpload(file) {
//文件类型
const isType = file.type === 'application/vnd.ms-excel'
const isTypeComputer = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const fileType = isType || isTypeComputer
if (!fileType) {
this.$message.error('上传文件只能是xls/xlsx格式!')
}
// 文件大小限制为10M
const fileLimit = file.size / 1024 / 1024 < 10
if (!fileLimit) {
this.$message.error('上传文件大小不超过10M!')
}
return fileType && fileLimit
},
// 自定义上传方法,param是默认参数,可以取得file文件信息,具体信息如下图
uploadHttpRequest(param) {
// const formData = new FormData() //FormData对象,添加参数只能通过append('key', value)的形式添加
// formData.append('file', param.file) //添加文件对象
// formData.append('uploadType', this.is_type) //接口要传的参数
// // 调用接口api
// importData(formData).then((data) => {
// if (data.code == 200) {
// this.msgSuccess('成功')
// param.onSuccess() // 上传成功的文件显示绿色的对勾
// this.fileList = []
// this.is_type = ''
// } else {
// this.msgError(data.msg)
// }
// })
},
// 点击上传:手动上传到服务器,此时会触发组件的http-request
submitUpload() {
if (this.is_type && this.fileList) {
// this.$refs.upload.submit()
// console.log(this.formData)
importData(this.formData).then((data) => {
if (data.code == 200) {
this.msgSuccess('成功')
this.fileList = []//清空上传的文件展示列表
this.is_type = ''
this.$refs.upload.clearFiles()//清空已上传的文件列表(该方法不支持在 before-upload 中调用)
} else {
this.msgError(data.msg)
}
})
} else if (this.is_type && this.fileList.length == 0) {
this.msgError('请选择上传文件')
} else if (!this.is_type && this.fileList.length != 0) {
this.msgError('请选择导入模式')
} else if (!this.is_type && this.fileList.length == 0) {
this.msgError('请选择导入模式和上传文件')
}
},
// 移除选择的文件
fileRemove(file, fileList) {
if (fileList.length < 1) {
this.uploadDisabled = true //未选择文件则禁用上传按钮
}
},
// 取消
closeDialog() {
this.$refs.upload.clearFiles() //清除上传文件对象
this.fileList = [] //清空选择的文件列表
this.$emit('close', false)
},
// 文件发生改变
fileChange(file, fileList) {
// if (fileList.length > 0) {
// this.fileList = [fileList[fileList.length - 1]] // 展示最后一次选择的文件
// }
// console.log(file)
this.formData = {
Name: file.name,
IsType: this.is_type,
}
let files = { 0: file.raw }
this.readExcel(files)
},
// 导入用XLSX读取文档
readExcel(files) {
var that = this
// 如果没有⽂件名
if (files.length <= 0) {
return false
} else if (!/\.(xls|xlsx)$/.test(files[0].name.toLowerCase())) {
this.$Message.error('上传格式不正确,请上传xls或者xlsx格式')
return false
}
const fileReader = new FileReader()
fileReader.onload = (ev) => {
try {
const data = ev.target.result
const workbook = XLSX.read(data, {
type: 'binary',
})
// 取第⼀张表
const wsname = workbook.SheetNames[0] //
// ⽣成
// 表格内容
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname])
console.log(ws, 'ws是表格⾥的数据,且是json格式')
let list = ws.map((item) => {
return {
Coding: (item.物料编码)+'',
Name: (item.物料名称)+'',
Specification: (item.规格型号)+'',
Units: (item.计量单位)+'',
AllName: (item.全名)+'',
ApplyNumber: (item.申请数量),
AdjustNumber: (item.调剂后数量),
Remark: (item.备注)+'',
}
})
this.formData.BizMaterialSon = list
// 重写数据
this.$refs.upload.value = ''
} catch (e) {
return false
}
}
fileReader.readAsBinaryString(files[0])
},
},
}
</script>
<style scoped lang="scss">
.title {
text-align: center;
font-size: 70px;
font-weight: 600;
}
.crenter {
width: 450px;
margin: 20px auto;
}
.select {
position: relative;
}
.selectright {
width: 450px;
margin: 20px auto;
}
.selectLeft {
width: 410px;
position: absolute;
left: 54%;
top: 0;
}
.upload-demo {
width: 100%;
}
.upImg {
width: 150px;
// height: 100px;
margin: 10px auto;
}
</style>
<style scoped>
.upload-demo >>> .el-upload-dragger {
border: none;
height: 250px !important;
width: 100%;
}
.box-card >>> .el-upload-dragger {
border: none;
height: 208px !important;
width: 100%;
}
.el-card.is-always-shadow {
-webkit-box-shadow: 0 2px 12px 0 #f0f0f0;
box-shadow: 0px -6px 20px 0 #f0f0f0;
border: none;
}
.box-card >>> .el-upload {
display: block !important;
}
.buttonUp {
display: block;
width: 140px;
padding: 15px;
border-radius: 5px;
margin: 0px auto;
margin-bottom: 10px;
}
.el-upload__tip {
text-align: center;
color: #a7a3a2;
padding: 20px;
box-shadow: 0px 4px 14px 0px #f0f0f0;
margin-top: 0px;
}
</style>
页面图片: