<script setup>
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
import PizZip from 'pizzip'
import Docxtemplater from 'docxtemplater'
import JszipUtils from 'jszip-utils'
import FileSave from 'file-saver'
import ImageModule from 'docxtemplater-image-module-free'
const chartRef = ref(null);
let myChart = null
const initChart = () => {
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
};
myChart = echarts.init(chartRef.value);
myChart.setOption(option);
}
const exportDocx = async () => {
if (!myChart) return
const content = await JszipUtils.getBinaryContent('template.docx')
let opts = {
centered: false,
fileType: 'docx'
}
opts.getImage = function (tagValue) {
if (tagValue.size && tagValue.data) {
return base64DataURLToArrayBuffer(tagValue.data)
}
return base64DataURLToArrayBuffer(tagValue)
}
opts.getSize = function (_, tagValue) {
if (tagValue.size && tagValue.data) {
return tagValue.size
}
return [500, 300] // word里面图片的尺寸
}
// 将文件转为zip文件
let pizZip = new PizZip(content)
let doc = new Docxtemplater()
doc.loadZip(pizZip)
doc.setOptions({
nullGetter: function () {
return ''
}
})
doc.attachModule(new ImageModule(opts))
const docData = {
image: myChart.getDataURL({
// pixelRatio: 5, // 导出的图片分辨率比率,默认是1
// backgroundColor: '#afdfe4', // 图表背景色
// excludeComponents: ['toolbox'], // 忽略组件的列表
// type: 'png' // 图片类型支持png和jpeg
}),
title: '测试',
content: '测试文章内容,哈哈',
list: [
{
url: 'https://www.baidu.com',
},
{
url: 'https://www.baidu.com',
},
{
url: 'https://www.baidu.com',
},
],
checked: true,
}
doc.setData(docData)
try {
doc.render()
} catch (error) {
// 抛出异常
let e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
throw error
}
const out = doc.getZip().generate({
type: 'blob',
mimeType:
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
FileSave.saveAs(out, 'test.docx')
}
/**
* base64转为ArrayBuffer
* 这个我也不知道为什么,我看最后下载打印的时候连接是base64格式的
*/
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
}
/**
* 下载图片什么需要将格式转化为base64
* 图片转base64方法
*/
function urlToBase64(url) {
return new Promise((resolve) => {
const image = new Image()
image.setAttribute('crossOrigin', 'Anonymous')
image.onload = function () {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
canvas.getContext('2d').drawImage(image, 0, 0)
const result = canvas.toDataURL('image/png')
resolve(result)
}
image.src = url
})
}
onMounted(() => {
initChart();
})
</script>
<template>
<div class="container">
<button @click="exportDocx">导出</button>
<div class="chart" ref="chartRef">
</div>
</div>
</template>
<style scoped>
.container {
width: 100%;
height: 100%;
}
.chart {
width: 500px;
height: 300px;
}
button {
margin-top: 20px;
}
</style>
DOCX模板:
导出DOX: