前言
网上查了很多jquery.wordexport的文章都是只支持单独导出word,不符合业务需求。因此修改了jquery.wordexport、利用jszip、file-saver批量导出word。
前提准备
包的版本分别为jszip@3.10.1、file-saver@2.0.5。jquery版本随意,本文使用的为@3.2.1
npm i jszip@3.10.1 -D
npm i file-saver@2.0.5 -D
正文
html部分
注意:导出word文档识别不了css中的样式,只能将样式写为行内样式或者添加在wordExport()方法的第二个参数中。jquery.wordexport无法使用flex布局,position等
<div class="wordForm-box">
<div class="wordForm"
v-for="(item,index) in exportWordList"
:key="index"
:id="'word'+index">
<p align="center"
style="font-size:32px;line-height: 40px;font-weight: 900;">{{ item.formTitle }}</p>
<table style="margin-top:20px">
<thead>
<th>操作时间</th>
<th>操作人员</th>
<th>操作节点</th>
<th>操作类型</th>
<th>操作结果</th>
<th>反馈详情</th>
</thead>
<tbody>
<tr v-for="(record) in item.records"
:key="record.id">
<td>{{ record.create_time | dateFormat}}</td>
<td>{{ record.operator.nickname}}</td>
<td>{{ record.level_from | formatAuditNode}}</td>
<td>{{ record.type | formatState}}</td>
<td>{{ record | formatResult}}</td>
<td>{{ record.remark}}</td>
</tr>
</tbody>
</table>
</div>
</div>
script部分
jquery的引用应放在wordexport前
注意:批量压缩时 同名文件将只会存在一个,请注意命名
<script>
import JSZip from 'jszip';
import FileSaver from 'file-saver';
import $ from '../../../libs/jquery-3.2.1/jquery.min.js';
import '../../../libs/jquery.wordexport';
export default {
data() {
return {
exportWordList: [],//需导出word表格列表
}
}
methods: {
async handleWordExport() {
this.exportWordList = [];//初始化
//...数据处理
// 导出
//本文数据处理有异步操作,nextTick处理保证页面已更新
this.$nextTick(() => {
let wordFiles = [];
let wordList = []; // 由于批量压缩时 同名文件将只会存在一个 这里我们采用[[],[]]包裹同名文件
this.exportWordList.forEach(async (wordItem, index) => {
let tmpIndex = wordList.findIndex((tmpWordItem) => {
return tmpWordItem[0].formTitle == wordItem.formTitle;
});
if (tmpIndex == -1) {
wordList.push([wordItem]);
} else {
wordList[tmpIndex].push(wordItem);
// wordList[tmpIndex][wordList[tmpIndex].length - 1].formTitle += '' + (wordList[tmpIndex].length - 1);
wordItem.formTitle += '(' + (wordList[tmpIndex].length - 1) + ')';
}
let rules =
'table{' +
' border-collapse:collapse;' +
' margin:0 auto;' +
' text-align:center;' +
' width: 100%;' +
'}' +
'table td,table th{' +
' text-align:center;' +
' border:1px solid #000000;' +
' height:25pt;' +
' width:15%;' +
'}' +
'table thead th{' +
' width:15%' +
'}' +
'table tr{' +
' background:#fff;' +
'}';
//可以通过修改wordExport()方法的第二个参数,添加样式
let wordFile = await $('#word' + index).wordExport(wordItem.formTitle, rules);
wordFiles.push(wordFile);
if (wordFiles.length == this.exportWordList.length) {
this.zipWordExport(wordFiles);
}
});
}
},
//导出zip
zipWordExport(promises) {
const zip = new JSZip();
const _this = this;
promises.forEach(async (item, index) => {
//word为blob数据
const { word, fileName } = item;
if (promises.length === 1) {
FileSaver.saveAs(word, `${fileName}.doc`);
} else {
await zip.file(`${fileName}.doc`, word);
}
if (promises.length > 1 && promises.length - 1 == index) {
_this.$message.warning('正在压缩请稍后');
zip.generateAsync({ type: 'blob' }).then((content) => {
FileSaver.saveAs(content, '表单记录合集' + '.zip');
});
}
});
},
}
}
</script>
jquery.wordexport代码
注意:jquery.wordexport中导入的jquery文件应与正文代码为同一文件
// 导入js文件
import $ from './jquery-3.2.1/jquery.min.js';
let jQuery = $;
if (typeof jQuery !== 'undefined') {
(function () {
$.fn.wordExport = function (fileName, rules) {
return new Promise((resolve, reject) => {
setTimeout(() => {
fileName = typeof fileName !== 'undefined' ? fileName : 'jQuery-Word-Export';
var static_ = {
mhtml: {
top: 'Mime-Version: 1.0\nContent-Base: ' + location.href + '\nContent-Type: Multipart/related; boundary="NEXT.ITEM-BOUNDARY";type="text/html"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset="utf-8"\nContent-Location: ' + location.href + '\n\n<!DOCTYPE html>\n<html>\n_html_</html>',
head: '<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<style>\n_styles_\n</style>\n</head>\n',
body: '<body>_body_</body>'
}
};
var options = {
maxWidth: 624
};
// Clone selected element before manipulating it
var markup = $(this).clone();
// Remove hidden elements from the output
markup.each(function () {
var self = $(this);
if (self.is(':hidden')) {
self.remove();
}
});
// Embed all images using Data URLs
var images = Array();
var img = markup.find('img');
for (var i = 0; i < img.length; i++) {
// 如果导出的word文件里面包含线上的图片
// Calculate dimensions of output image
var width = Math.min(img[i].width, options.maxWidth);
var height = img[i].height * (width / img[i].width);
// Create canvas for converting image to data URL
// 这是添加的代码--------------------------------------------
var img_id = '#' + img[i].id;
$('<canvas>').attr('id', 'test_word_img_' + i).width(width).height(height).insertAfter(img_id);
// 如果导出的word文件里面包含本地图片用这一段,如果都包含,要另外研究一下
// Calculate dimensions of output image
var w = Math.min(img[i].width, options.maxWidth);
var h = img[i].height * (w / img[i].width);
// Create canvas for converting image to data URL
var canvas = document.createElement('CANVAS');
canvas.width = w;
canvas.height = h;
// Draw image to canvas
var context = canvas.getContext('2d');
context.drawImage(img[i], 0, 0, w, h);
// Get data URL encoding of image
var uri = canvas.toDataURL('image/png');
$(img[i]).attr('src', img[i].src);
img[i].width = w;
img[i].height = h;
// Save encoded image to array
images[i] = {
type: uri.substring(uri.indexOf(':') + 1, uri.indexOf(';')),
encoding: uri.substring(uri.indexOf(';') + 1, uri.indexOf(',')),
location: $(img[i]).attr('src'),
data: uri.substring(uri.indexOf(',') + 1)
};
}
// Prepare bottom of mhtml file with image data
var mhtmlBottom = '\n';
for (var i = 0; i < images.length; i++) {
mhtmlBottom += '--NEXT.ITEM-BOUNDARY\n';
mhtmlBottom += 'Content-Location: ' + images[i].location + '\n';
mhtmlBottom += 'Content-Type: ' + images[i].type + '\n';
mhtmlBottom += 'Content-Transfer-Encoding: ' + images[i].encoding + '\n\n';
mhtmlBottom += images[i].data + '\n\n';
}
mhtmlBottom += '--NEXT.ITEM-BOUNDARY--';
// TODO: load css from included stylesheet
var styles = rules;
// Aggregate parts of the file together
var fileContent = static_.mhtml.top.replace('_html_', static_.mhtml.head.replace('_styles_', styles) + static_.mhtml.body.replace('_body_', markup.html())) + mhtmlBottom;
// Create a Blob with the file contents
var blob = new Blob([fileContent], {
type: 'application/msword;charset=utf-8'
});
resolve({ word: blob, fileName: fileName });
}, 10);
});
};
})(jQuery);
} else {
if (typeof jQuery === 'undefined') {
console.error('jQuery Word Export: missing dependency (jQuery)');
}
}