##项目背景#
因公司需要生成word文档,后端导出需要收费下载依赖,so由前端负责生成。
#项目依赖#
"jszip-utils": "^0.1.0",
"pizzip": "^3.1.4",
"file-saver": "^2.0.5",
"angular-expressions": "^1.2.1",
"docxtemplater": "^3.36.1",
#方法封装#
在utils文件夹下面新建createWord.js
import Docxtemplater from 'docxtemplater'
import JSZipUtils from 'jszip-utils'
import PizZip from 'pizzip'
import {saveAs} from 'file-saver'
import expressions from 'angular-expressions'
import merge from "lodash/merge"
/**
* dataURL:base64图片
* */
export function base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpg|svg|svg\+xml);base64,/
if (!base64Regex.test(dataURL)) {
return false
}
const stringBase64 = dataURL.replace(base64Regex, '')
let binaryString
if (typeof window !== 'undefined') {
binaryString = window.atob(stringBase64)
} else {
binaryString = new Buffer(stringBase64, 'base64').toString('binary')
}
const len = binaryString.length
const bytes = new Uint8Array(len)
for (let i = 0; i < len; i++) {
const ascii = binaryString.charCodeAt(i)
bytes[i] = ascii
}
return bytes.buffer
}
/**
* setData:word模板对应的数据
* wordTitle:生成的word标题
* wordPath:word模板对应的路径
* point:Vue
* isUrlArr:是否针对生成的图片特殊化处理
* */
export function downloadprice(setData, wordTitle, wordPath, point,isUrlArr) {
let _this = point;
let ImageModule = require('docxtemplater-image-module-free')
//1
var last = require("lodash/last");
var assign = require("lodash/assign");
var docxtemplater = require('docxtemplater');
JSZipUtils.getBinaryContent(wordPath, function (error, content) {
if (error) {
_this.$msgError('下载word失败,请稍候重试。。。');
throw error;
}
let opts = {}
opts.centered = false
opts.fileType = 'docx'
opts.getImage = function (chartId) {
return base64DataURLToArrayBuffer(chartId)
}
opts.getSize = function (value, item, url) {
if (isUrlArr && typeof isUrlArr === 'object') {
for (const [key, size] of Object.entries(isUrlArr)) {
if (url === key) {
return size;
}
}
}
return [350, 350];
};
//角度筛选器
var angularParser= function(tag){
tag = tag
.replace(/^\.$/, "this")
.replace(/(’|‘)/g, "'")
.replace(/(“|”)/g, '"');
const expr = expressions.compile(tag);
return {
get: function (scope, context) {
let obj = {};
const index = last(context.scopePathItem);
const scopeList = context.scopeList;
const num = context.num;
for (let i = 0, len = num + 1; i < len; i++) {
obj = assign(obj, scopeList[i]);
}
obj = assign(obj, {objIndex : index });
return expr(scope, obj);
},
};
}
let zip = new PizZip(content);
// 创建并加载docxtemplater实例对象
var doc = new docxtemplater()
.loadZip(zip)
.setOptions({parser:angularParser})
.attachModule(new ImageModule(opts))
.compile();
doc.resolveData({...setData}).then(function () {
doc.render();
var out = doc.getZip().generate({
type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
//输出文档
_this.$msgSuccess('下载成功');
saveAs(out, wordTitle+".docx");
})
});
}
注意:此项目是vue2项目,所以导出得文件路径是在public目录下面
#方法使用#
1:我使用得是延迟4s调用此方法
2:方法使用
copyValue就是你包裹的所有数据对象
这几个img都要转为base64格式
举例:availabilityUrl: [{availabilityUrl: ''}]
createDownload() {
this.copyValue = cloneDeep(this.reportObj)
this.copyValue.securityIncidentImg = this.securityChartsUrl
this.copyValue.vulnerabilityRiskImg = this.vulnerabilityRiskChartsUrl
this.copyValue.riskAssetsChartsImg = this.riskAssetsChartsUrl
this.copyValue.assertsContentImg = this.assertsContentUrl
this.copyValue.assetsBarImg = this.assetsBarUrl
this.copyValue.availabilityImg = this.availabilityUrl
downloadprice(
{...this.copyValue},
this.copyValue.wordTitle,
'/wordEyeVersionTwo.docx',
this,
{
securityIncidentUrl: [630, 400],
vulnerabilityRiskUrl: [630, 400],
riskAssetsChartsUrl: [630, 400],
assertsContentUrl: [630, 500],
assetsBarUrl: [630, 400],
availabilityUrl: [630, 400]
}
)
},
3:word模板
最后左右的样式都可以在word上修改,包括颜色、字体大小、间距等等
#写在结尾#
word由前端生成资料很少,部分要实现的效果可能要借助word本身自带的功能,例如,我每一个标题下面会有一个空格,这种是因为我做判断长度的时候这个会占用一行,解决办法就是word的把这个文字隐藏掉就好了,但是这种对后期维护很不友好!还是要看产品怎么决定。最后:祝君上岸!!!