前段时间由于后台的研究僧跑路了,我这个应届小菜鸟肩负起了全栈开发的工作,学得那是一个心累啊。项目没有很大,但麻雀虽小五脏俱全,写几篇文章不枉此行吧。废话不多说,华丽丽的分割线进入正题。
管理后台一个个录入表单太慢了,采用excel来批量添加数据到数据库中。由于是公司的项目,就不截图了。还有项目中所用到的npm依赖安装也不做多余赘述。
前端部分:vue全家桶+elementUI
后台部分:express+formidable+xlsx+mongodb
前端采用饿了么的上传组件,无需使用axios来post提交,只需要配置好action即可。
<el-upload ref="upload" action="/fashion/multiAdd" :show-file-list="false"
class="upload-data" :on-success="multiAddSucc">
<el-button slot="trigger" icon="el-icon-upload" type="success">批量导入</el-button>
</el-upload>
顺带提一句,在开发环境中vue的项目采用npm run dev来调试,而后台是node的开发环境,在进行通信的过程中端口不一致,将会发生跨域。所以前端需要配置代理来访问后台。
// config/index.js
'/fashion/*': {
target: 'http://127.0.0.1:3020',
changeOrigin: true
},
而后台需要配置CORS允许跨域
// app.js
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,POST,DELETE,PUT');
res.header('Access-Control-Allow-Headers', 'Content-Type,Accept');
res.header('Access-Control-Allow-Credentials', 'true');
后台需要先接受前端传过来的excel文件,此处我们采用formidable中间件进行接受
// fashion.js
var express = require('express');
var router = express.Router();
var fs = require('fs');
var XLSX = require('xlsx');
var formidable = require('formidable');
router.post('/multiAdd', function (req, res) {
var form = new formidable.IncomingForm();
var xlsxJson;
form.encoding = 'utf-8'; // 编码方式
form.uploadDir = 'public/tmp'; // 临时上传路径
form.keepExtensions = true; // 保存后缀名
})
之后将上传的excel重命名并移动
// fashion.js
form.parse(req, function (err, fields, files) {
// console.log(files);
// 重命名并修改上传文件的路径
var sourceFileName = files.file.name;
var tempPath = files.file.path;
var targetPath = 'public/upload/' + sourceFileName;
fs.renameSync(tempPath, targetPath);
})
原本到这一步我们已经可以直接使用js-xlsx对excel进行解析成json,然后批量添加进入数据库就好了。但此处发现有一个坑,XLSX将excel转换成json时,无法将excel的日期格式正常转换。如2018/05/03,解析成json变成了一串数字。查了资料后,发现只要将日期单拎出来单独处理就好了。
let date = new Date(1900,0,dateVal-1);
遂在我的项目中有以下代码
// fashion.js
const workbook = XLSX.readFile(targetPath);
const sheetNames = workbook.SheetNames;
const worksheet = workbook.Sheets[sheetNames[0]];
xlsxJson = XLSX.utils.sheet_to_json(worksheet);
var len = xlsxJson.length;
for (let i = 0; i < len; i++) {
let dateVal = xlsxJson[i].pub_time;
let date = new Date(1900, 0, dateVal - 1).format('yyyy-MM-dd');
// console.log(date);
xlsxJson[i].pub_time = date;
}
由于js直接new Date()时会出现时间,项目不需要时间。
注意在for循环中还对new Date进行了一次格式化,格式化的代码来源于网上。(赞一个)
Date.prototype.format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
如上,我们将excel成功转换成了json。接下来的工作是批量添加到mongodb就好了。
// fashions是我写的一个model
fashions.insertMany(xlsxJson, function (err, docs) {
if (err) {
res.json({
status: '0',
msg: '批量导入出错,请检查表格格式',
result: ''
})
} else {
res.json({
status: '1',
msg: '插入成功',
result: ''
})
}
})
前端有个钩子函数处理el-upload组件上传成功的,即on-suceess函数。我们在前端做点上传友好提示吧。
multiAddSucc(res, file) {
if (res.status == '1') {
this.$message({
message: '批量上传成功',
type: 'success'
})
this.getFashionList(1, 1, 5); // 这个函数是用来刷新数据的就不说了
}
else {
this.$message.error(res.msg);
}
}