import JSZipUtils from 'jszip-utils';
|
import JSZip from 'jszip';
|
import docxtemplater from 'docxtemplater';
|
import ImageModule from 'docxtemplater-image-module-free';
|
import Pizzip from 'pizzip';
|
import FileSaver from 'file-saver';
|
import { renderAsync } from 'docx-preview';
|
import printJS from 'print-js';
|
import pdfMake from 'pdfmake/build/pdfmake';
|
import vfs from 'pdfmake/build/vfs_fonts.js';
|
import { jsPDF } from 'jspdf';
|
|
/**
|
* 等比例缩放图片
|
* 根据图片的长宽比进行不同方式的缩放
|
* 如果宽度大于高度(横拍图片),则按照设定高度等比缩放;
|
* 如果宽度小于高度(竖拍图片),则按照设定宽度等比缩放;
|
* @param {Number} horizontalHeight 设定高度
|
* @param {Number} verticalWidth 设定宽度
|
* @param {*} img
|
* @param {*} tagValue
|
* @param {*} tagName
|
* @returns
|
*/
|
function getSizeProportional(
|
horizontalHeight,
|
verticalWidth,
|
img,
|
tagValue,
|
tagName
|
) {
|
return new Promise(function (resolve, reject) {
|
const image = new Image();
|
image.src = tagValue;
|
image.onload = function () {
|
let width = image.width;
|
let height = image.height;
|
// console.log('width height', width, height);
|
|
if (width > height && horizontalHeight && height > horizontalHeight) {
|
const scale = image.height / horizontalHeight;
|
height = horizontalHeight;
|
width = image.width / scale;
|
} else if (width <= height && verticalWidth && width > verticalWidth) {
|
const scale = image.width / verticalWidth;
|
width = verticalWidth;
|
height = image.height / scale;
|
}
|
// console.log('scale', width, height);
|
|
resolve([width, height]);
|
};
|
image.onerror = function (e) {
|
console.log('img, tagValue, tagName : ', img, tagValue, tagName);
|
alert('An error occured while loading ' + tagValue);
|
reject(e);
|
};
|
});
|
}
|
|
/**
|
* 固定大小缩放图片
|
* 根据图片的长宽比进行不同方式的缩放
|
* 如果宽度大于高度(横拍图片),则按照设定高度和宽高比缩放;
|
* 如果宽度小于高度(竖拍图片),则按照设定宽度和宽高比缩放;
|
* @param {*} horizontalHeight 设定高度
|
* @param {*} verticalWidth 设定宽度
|
* @param {*} scale 缩放比例,长边除短边的比例系数
|
* @param {*} img
|
* @param {*} tagValue
|
* @param {*} tagName
|
* @returns
|
*/
|
function getSizeFixed(
|
horizontalHeight,
|
verticalWidth,
|
scale,
|
img,
|
tagValue,
|
tagName
|
) {
|
return new Promise(function (resolve, reject) {
|
const image = new Image();
|
image.src = tagValue;
|
image.onload = function () {
|
let width = image.width;
|
let height = image.height;
|
|
if (
|
width > height &&
|
horizontalHeight &&
|
height > horizontalHeight &&
|
scale
|
) {
|
height = horizontalHeight;
|
width = horizontalHeight * scale;
|
} else if (
|
width <= height &&
|
verticalWidth &&
|
width > verticalWidth &&
|
scale
|
) {
|
width = verticalWidth;
|
height = verticalWidth * scale;
|
}
|
resolve([width, height]);
|
};
|
image.onerror = function (e) {
|
console.log('img, tagValue, tagName : ', img, tagValue, tagName);
|
alert('An error occured while loading ' + tagValue);
|
reject(e);
|
};
|
});
|
}
|
|
/**
|
* 获取图片配置信息
|
* @param {Number} horizontalHeight 图片宽度大于高度时,限制其高度
|
* @param {Number} verticalWidth 图片宽度小于高度时,限制其宽度
|
* @returns
|
*/
|
function getImageOptions(options) {
|
const horizontalHeight = options ? options.horizontalHeight : undefined;
|
const verticalWidth = options ? options.verticalWidth : undefined;
|
return {
|
centered: false,
|
fileType: 'docx',
|
getImage(tagValue) {
|
// In this case tagValue will be a URL tagValue = "https://docxtemplater.com/puffin.png"
|
return new Promise(function (resolve, reject) {
|
JSZipUtils.getBinaryContent(tagValue, function (error, content) {
|
if (error) {
|
return reject(error);
|
}
|
return resolve(content);
|
});
|
});
|
},
|
|
getSize(img, tagValue, tagName) {
|
// return getSizeProportional(horizontalHeight, verticalWidth, img, tagValue, tagName)
|
return getSizeFixed(
|
horizontalHeight,
|
verticalWidth,
|
options.scale,
|
img,
|
tagValue,
|
tagName
|
);
|
}
|
};
|
}
|
|
function prepareDocxtemplater(tempDocpath, data, imageSize) {
|
return new Promise((resolve, reject) => {
|
JSZipUtils.getBinaryContent(tempDocpath, (error, content) => {
|
if (error) {
|
reject(error);
|
throw error;
|
}
|
const zip = new Pizzip(content);
|
let doc = new docxtemplater()
|
.setOptions({ paragraphLoop: true })
|
.loadZip(zip);
|
|
if (imageSize) {
|
const imageOptions = getImageOptions(imageSize);
|
doc.attachModule(new ImageModule(imageOptions));
|
}
|
doc.compile();
|
doc.resolveData(data).then(() => {
|
resolve(doc);
|
});
|
});
|
});
|
}
|
|
/**
|
* 准备docx文档,返回blob对象
|
* @param {*} tempDocpath 模板docx文件路径
|
* @param {*} data 数据对象
|
* @param {*} zipName 压缩包名称
|
* @param {*} imageSize 图片大小配置对象
|
* @returns
|
*/
|
function prepareDocxBlob(tempDocpath, data, imageSize) {
|
return prepareDocxtemplater(tempDocpath, data, imageSize).then((doc) => {
|
try {
|
doc.render();
|
} catch (error) {
|
console.log(error);
|
throw error;
|
}
|
const out = doc.getZip().generate({
|
type: 'blob',
|
mimeType:
|
'application/vnd.openxmlformats-officedocumnet.wordprocessingml.document'
|
});
|
return out;
|
});
|
}
|
|
function prepareDocxStr(tempDocpath, data, imageSize) {
|
return prepareDocxtemplater(tempDocpath, data, imageSize).then((doc) => {
|
try {
|
return doc.render();
|
} catch (error) {
|
console.log(error);
|
throw error;
|
}
|
});
|
}
|
|
async function preparePdf(tempDocpath, data, imageSize) {
|
// return prepareDocxStr(tempDocpath, data, imageSize).then((res) => {
|
// // 将 Word 文档转换为 PDF 格式并保存到文件
|
// console.log(pdfMake);
|
// console.log('res', res);
|
|
// // const printer = new PdfPrinter(vfs);
|
// const docDefinition = {
|
// content: [
|
// {
|
// text: res.getZip().generate({
|
// type: 'blob',
|
// mimeType:
|
// 'application/vnd.openxmlformats-officedocumnet.wordprocessingml.document'
|
// })
|
// // text: res.toString('utf8')
|
// }
|
// ]
|
// };
|
// const pdfDoc = pdfMake.createPdf(docDefinition);
|
// // const pdfBuffer = await pdfDoc.getBuffer();
|
// // return new Blob([pdfBuffer], { type: 'application/pdf' });
|
// console.log(pdfDoc);
|
// return pdfDoc;
|
|
// // console.log('res', res.toString('utf8'));
|
|
// // const doc = new jsPDF();
|
// // doc.text(res.toString('utf8'), 10, 10);
|
|
// // return doc;
|
// });
|
|
try {
|
// 第一步:使用docxtemplater处理docx模板
|
const doc = await prepareDocxStr(tempDocpath, data, imageSize);
|
|
// 第二步:获取渲染后的docx内容
|
const docxBlob = doc.getZip().generate({
|
type: 'blob',
|
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
});
|
|
return docxBlob
|
|
// 第三步:读取docx内容(注意:这一步需要额外的库来解析docx内容)
|
// 由于pdfmake不能直接处理docx格式,我们需要先解析docx内容
|
// 这里提供两种方案:
|
|
// 方案1:使用docx-preview库先渲染为HTML,再用pdfmake创建PDF
|
// const container = document.createElement('div');
|
// await renderAsync(docxBlob, container);
|
|
// // 提取HTML内容并转换为pdfmake可用的格式
|
// const textContent = extractTextFromHtml(container.innerHTML);
|
|
// // 第四步:使用pdfmake创建PDF
|
// const docDefinition = {
|
// content: [
|
// {
|
// text: textContent,
|
// style: 'body'
|
// }
|
// ],
|
// };
|
|
// const pdfDoc = pdfMake.createPdf(docDefinition);
|
// return pdfDoc;
|
|
} catch (error) {
|
console.error('转换docx到pdf失败:', error);
|
throw error;
|
}
|
}
|
|
/**
|
* 从HTML中提取文本内容
|
* @param {string} html HTML字符串
|
* @returns {string} 提取的文本内容
|
*/
|
function extractTextFromHtml(html) {
|
const tempDiv = document.createElement('div');
|
tempDiv.innerHTML = html;
|
return tempDiv.textContent || tempDiv.innerText || '';
|
}
|
|
function exportDocx(tempDocpath, data, zipName, imageSize) {
|
return prepareDocxBlob(tempDocpath, data, zipName, imageSize).then((blob) => {
|
FileSaver.saveAs(blob, zipName);
|
});
|
}
|
|
function previewDocx(blob, ref) {
|
return renderAsync(blob, ref);
|
}
|
|
function downloadDocx(blob, zipName) {
|
FileSaver.saveAs(blob, zipName);
|
}
|
|
function print(
|
ref,
|
title,
|
style,
|
type,
|
jsonData,
|
borderHeadStyle,
|
gridStyle,
|
css
|
) {
|
printJS({
|
printable: ref,
|
header: title || null,
|
type: type || 'html',
|
// headerStyle:
|
// 'font-size:6px;font-weight:600;text-align:center;padding:15px 0 10px 0;', //标题设置
|
properties: jsonData || [], //json数据元
|
gridHeaderStyle:
|
borderHeadStyle ||
|
'font-size:6px;font-weight:400;height:40px;line-height:40px;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json格式表头样式
|
gridStyle:
|
gridStyle ||
|
'font-size:1px;font-weight:200;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', //json各式表哥央视
|
scanStyles: false, //不适用默认样式
|
repeatTableHeader: false, //打印json表头只显示在第一页
|
style: style || `@page{size:auto;margin: 0cm 1cm 0cm 1cm;}`, //去除页眉页脚
|
css: css || null //css url
|
});
|
}
|
export {
|
exportDocx,
|
prepareDocxBlob,
|
preparePdf,
|
previewDocx,
|
downloadDocx,
|
print
|
};
|