// @ts-ignore import JSZipUtils from 'jszip-utils' import docxtemplater from 'docxtemplater' // @ts-ignore import { saveAs } from 'file-saver' import PizZip from 'pizzip' export const getBase64Sync = (imgUrl: string) => { return new Promise(function (resolve, reject) { // 一定要设置为let,不然图片不显示 let image = new Image() image.crossOrigin = 'anonymous' image.src = imgUrl image.onload = function () { let canvas = document.createElement('canvas') canvas.width = image.width canvas.height = image.height let context = canvas.getContext('2d') context?.drawImage(image, 0, 0, image.width, image.height) //图片后缀名 let ext = image.src.substring(image.src.lastIndexOf('.') + 1).toLowerCase() let quality = 0.8 let dataurl = canvas.toDataURL('image/' + ext, quality) resolve(dataurl) } image.onerror = function (err) { reject(err) } }) } export const base64DataURLToArrayBuffer = (dataURL: string) => { const base64Regex = /^data:image\/(png|jpg|jpeg|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 = Buffer.from(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 } export const exportWordDocx = async ( url: string, docxData: Record, fileName: string ) => { const ImageModule = require('docxtemplater-image-module-free') JSZipUtils.getBinaryContent(url, async function (error: unknown, content: any) { if (error) { throw error } // 创建一个PizZip实例,内容为模板的内容 let zip = new PizZip(content) // 创建并加载docxtemplater实例对象 let doc = new docxtemplater().loadZip(zip) doc.attachModule( new ImageModule({ getImage: (base64: string) => base64DataURLToArrayBuffer(base64), getSize: (buffer: string, base64: string, key: string) => { if (docxData.imagePages) { for (const row of docxData.imagePages) { for (const col of row) { for (const img of col) { if (img.img === base64) { return [img.width, img.height] } } } } } return [70, 70] } }) ) // 去除未定义值所显示的undefined doc.setOptions({ nullGetter: function () { return '' } }) // 设置角度解析器Could not find a declaration file for module 'jszip-utils'. doc.setData({ ...docxData }) try { // 用模板变量的值替换所有模板变量 doc.render() } catch (error: any) { let e = { message: error.message, name: error.name, stack: error.stack, properties: error.properties } console.log(JSON.stringify({ error: e })) throw error } // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示) let out = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }) // 将目标文件对象保存为目标类型的文件,并命名 saveAs(out, fileName) }) }