《vue实现动态生成并导出world功能》
1. 安装需要的插件并引入import PizZip from 'pizzip'
import Docxtemplater from 'docxtemplater'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
import ImageModule from 'docxtemplater-image-module-free'
import { Buffer } from 'buffer'2. 工具utils中新建 exportFile.js 文件,用于将图片转换为base64格式
// getBase64Sync
export function getBase64Sync(imgUrl) {
return new Promise((resolve, reject) => {
const image = new Image();
image.crossOrigin = 'anonymous';
image.onload = () => {
const canvas = document.createElement('canvas');
// 固定画布尺寸为90x90
canvas.width = 90;
canvas.height = 90;
const ctx = canvas.getContext('2d');
// 计算缩放比例后居中绘制
const scale = Math.min(90 / image.width, 90 / image.height);
const scaledWidth = image.width * scale;
const scaledHeight = image.height * scale;
const dx = (90 - scaledWidth) / 2;
const dy = (90 - scaledHeight) / 2;
ctx.drawImage(image, dx, dy, scaledWidth, scaledHeight);
let ext = imgUrl.split('.').pop().toLowerCase();
if (ext === 'jpg') ext = 'jpeg';
const mime = `image/${ext}`;
try {
const dataurl = canvas.toDataURL(mime, 0.8);
resolve(dataurl);
} catch (e) {
reject(e);
}
};
image.onerror = () => reject(new Error('图片加载失败'));
image.src = imgUrl + (imgUrl.includes('?') ? '&' : '?') + 't=' + Date.now();
});
}
// base64DataURLToArrayBuffer
export function base64DataURLToArrayBuffer(dataURL) {
const base64 = dataURL.split(',');
const binaryString = window.atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes = binaryString.charCodeAt(i);
}
return bytes.buffer;
}3.引入 exportFile中的函数
import { getBase64Sync,base64DataURLToArrayBuffer } from '@/utils/exportFile.js'4.设置.docx模板文件,位置放在public文件下
数组使用{#data}{/data}包裹起来
展示的字段使用{item}
图片赋值用到{%img}
模板例如:
5.导出按钮具体功能实现
/** 方案1,不考虑图片直接导出 world */
function submitForm() {
// const htmlContent = document.getElementById('htmlcontent');
// const blob = new Blob(, { type: 'application/msword' });
// const url = window.URL.createObjectURL(blob);
// const a = document.createElement('a');
// a.href = url;
// a.download = '包装码.docx';
// a.click();
// window.URL.revokeObjectURL(url);
}/** 方案2,考虑图片,导出world */
async function exportWord() {
try {
const content = await new Promise((resolve, reject) => {<br> //world模板'/boxCode.docx'
JSZipUtils.getBinaryContent('/boxCode.docx?random=' + Math.random(), (error, data) => {
error ? reject(error) : resolve(data);
});
});
const zip = new PizZip(content);
let doc = new Docxtemplater();
// 注册图片模块
const imageOptions = {
getImage: (tag) => {
const base64Data = tag.split(',');
return Buffer.from(base64Data, 'base64');
},
// 设置Word中图片显示尺寸为90x90
getSize: () =>
};
doc.attachModule(new ImageModule(imageOptions));
doc.loadZip(zip);
const processedData = await Promise.all(
currentData.value.map(async (item) => {
const base64 = await getBase64Sync(item.boxCodeUrl);
const matches = base64.match(/^data:image\/(\w+);base64,/);
const validBase64 = matches ? base64 : `data:image/png;base64,${base64}`; //图片转码
return {
itemCode:item.itemCode?item.itemCode:'',
batchNumber:item.batchNumber?item.batchNumber:'',
itemName:item.itemName?item.itemName:'',
itemModel:item.itemModel?item.itemModel:'',
itemNumber:item.itemNumber?item.itemNumber:'',
projectName:item.projectName?item.projectName:'',
specification:item.specification?item.specification:'',
vendorName:item.vendorName?item.vendorName:'',
boxCodeUrl: validBase64 || ''
};
})
)
doc.setData({ currentData: processedData });//数据赋值
try {
doc.render();
} catch (error) {
console.error('模板渲染错误:', error.properties?.errors);
throw error;
}
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
});
saveAs(out, currentItemName.value + '包装码.docx');
} catch (error) {
console.error('导出失败:', error);
throw error;
}finally{
visible.value = false
}
}6.导出的world页面中若需要分页,在需要分页的光标位置设置分页符
注:因为我用到了标签打印,生成的world打印时纵向横向样式展示没办法解决,所以将生成的world通过接口转为pdf输出进行打印// 生成Word Blob 发送到后端转换服务 const selectedFile = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const formData = new FormData(); formData.append('file', selectedFile); fetch(VITE_APP_BASE_API + VITE_AGENT_API+`/md/purchaseorder/convertWordToPDF`, { method: 'POST', headers: { 'Authorization': `Bearer ${getToken()}` }, body: formData }) .then(response => { if (!response.ok) { throw new Error(`服务器返回错误: ${response.status}`); } return response.blob(); }) .then(blob => { const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `${currentItemName.value}` + '包装码.pdf' ); document.body.appendChild(link); link.click(); document.body.removeChild(link); }) .catch(error => { console.error('导出失败:', error); loadingSubmit.value = false throw error; });
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]