背景:需要前端实现上传excel文件,展示到页面上。实现效果如下:
因为项目是后台管理系统(vue+element),通过引入xlsx插件来实现。
页面展示部分
<el-form-item label="导入订单:" prop="itemslist">
<el-button icon="el-icon-plus" @click="importOrder" :loading="loading">导入订单</el-button>
<input type="file" style="display: none;" id="file" ref="files" accept=".xls,.xlsx" @change="changeFile" />
</el-form-item>
<!-- 生成表单 -->
<div v-if="form.itemslist.length" class="tables">
<el-table :data="form.itemslist" border style="width: 100%">
<el-table-column :label="item" min-width="180" v-for="(item,index) in Object.keys(form.itemslist[0])" :key="index">
<template #default="scope">
{{Object.values(form.itemslist[scope.$index])[index]}}
</template>
</el-table-column>
</el-table>
</div>
import XLSX from "xlsx";
/**
* excel导出时间格式 2021/12/16 10:14:30=>44546.42673611111 ,需要做转换
* @param numb 是传过来的整数数字
* @param format 是之间间隔的符号
* */
const formatDate = (numb, format) => {
const time = new Date((numb - 1) * 24 * 3600000 + 1);
time.setFullYear(time.getFullYear() - 70);
time.setHours(time.getHours() - 8);
const year = time.getFullYear() + '';
const month = time.getMonth() + 1 + '';
const date = time.getDate() - 1 + '';
const hours = time.getHours().toLocaleString();
const minutes = time.getMinutes();
const second = time.getSeconds();
if (format && format.length === 1) {
return year + format + month + format + date + ' ' + (+hours < 10 ? '0' + hours : hours) + ':' + (+minutes < 10 ? '0' + minutes : minutes) + ':' + (+second < 10 ? '0' + second : second);
}
return year + (+month < 10 ? '0' + month : month) + (+date < 10 ? '0' + date : date) + (+second < 10) ? '0' + second: second;
;
/**
* 文件上传
* 这里需要把中文字符转换为需要上传对应的字符
*/
const changeFile = () => {
const Reg = /\.(xls|xlsx)$/g;
const fils = files.value.files[0];
const render = new FileReader();
if (fils != undefined) {
loading.value = true; // 开启loading
if (!Reg.test(fils.name)){
GL.$message.error('上传的不是excel文件');
return false;
};
render.readAsBinaryString(fils);
render.onload = (e) => {
const data = e.target?.result;
const excel = XLSX.read(data,{type: "binary"});
form.value.itemslist = XLSX.utils.sheet_to_json(excel.Sheets[excel.SheetNames[0]],{defval: ''}); // 获取excel表的数据
elForm.value.validate((valid: boolean) => {
if (!valid) {return false;}
}); // 开启校验
if ( form.value.itemslist) {
loading.value = false;
}
let isfag = false; // 数据是否缺少
let isFormat = false; //检测表头
// 转换数组
const newList: any = [];
const oldKeys = ['姓名', '手机号','订单号', '订单时间'];
const newKeys = ['real_name', 'mobile', 'out_trade_no', 'pay_time'];
// 校验表头
if (form.value.itemslist.length === 0){
GL.$message.error('导入订单数据未填写完整,请再次导入');
delFile();
return false;
}
oldKeys.forEach((item,id) => {
if (Object.keys(form.value.itemslist[0])[id] !== item){
isFormat = true;
return false;
}
});
if(isFormat){
GL.$message.error('导入订单数据的表头错误,请再次导入');
delFile();
isFormat = false;
return false;
}
// 原始表格时间转换
form.value.itemslist.forEach(element => {
if(element['订单时间']){ element['订单时间'] = formatDate(element['订单时间'],'-'); }
});
// 检验表内容
form.value.itemslist.map((item,index)=>{
const newKey = {};
newKeys.forEach((element,id) => {
newKey[element] = Object.values(item)[id];
});
newList[index] = newKey;
});
form.value.items = newList;
form.value.items.forEach((element,index) => {
newKeys.forEach(item => {
element[item] ? form.value[`items[${index}][${item}]`] = element[item] : isfag = true;
});
});
if (isfag) {
GL.$message.error('导入订单数据未填写完整,请再次导入');
delFile();
isfag = false;
return false;
}
files.value.value = '';
};
}
};