import JSZipUtils from 'jszip-utils'
|
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'
|
|
/**
|
* 等比例缩放图片
|
* 根据图片的长宽比进行不同方式的缩放
|
* 如果宽度大于高度(横拍图片),则按照设定高度等比缩放;
|
* 如果宽度小于高度(竖拍图片),则按照设定宽度等比缩放;
|
* @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()
|
// 解析数据
|
if (data) {
|
doc.resolveData(data).then(() => {
|
resolve(doc)
|
})
|
} else {
|
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:A4;margin: -1cm 0cm 0cm 0cm;}`, //去除页眉页脚
|
css: css || null, //css url
|
})
|
}
|
export { exportDocx, prepareDocxBlob, preparePdf, previewDocx, downloadDocx, print }
|