最近在项目中遇到一个报告下载的需求,后端需要前端将每个组件转为html,下载为word文档,识别不出echarts,需要将echarts组件转为图片,表格为可编辑状态,过程中遇到一点小问题,记录一下。
代码如下(示例):
<template>
<div class="objectview_wrap">
<el-button @click="handleSave">下载</el-button>
<div id="export-chart">
<template item = "zcxx">
<div
id="scopesupervision"
class="report_form_flag"
>
<scope-supervision />
</div>
</template>
<template item = "ryfw">
<div
id="applicationaccess"
class="report_form_flag">
<applicationaccess />
</div>
</template>
<template item="wlhl">
<div
id="utilitysystemstatus"
class="report_form_flag">
<utilitysystemstatus />
</div>
</template>
<template item="ywqk">
<div
id="ops"
class="report_form_flag">
<ops />
</div>
</template>
<template item="wjcs">
<div
id="files"
class="report_form_flag">
<files />
</div>
</template>
<cooperate ref="child" />
<approve ref="child1" />
<template item="sjfs">
<div
id="happen"
class="report_form_flag">
<happen />
</div>
</template>
<template item="ajbs">
<div
id="submission"
class="report_form_flag">
<submission />
</div>
</template>
<template item = "fxsjcy">
<div
id="causeanalysis"
class="report_form_flag">
<causeanalysis />
</div>
</template>
<template item="gjjy">
<div
id="advice"
class="report_form_flag">
<advice />
</div>
</template>
代码如下(示例):
<script>
import domtoimage from 'dom-to-image'
import { exportWord } from '../../../../apiNew/businessManage'
import ops from './components/ops.vue'
import applicationaccess from './components/applicationaccess.vue'
import ScopeSupervision from './components/ScopeSupervision.vue'
import utilitysystemstatus from './components/utilitysystemstatus.vue'
import files from './components/files.vue'
import cooperate from './components/cooperate.vue'
import approve from './components/approve.vue'
import happen from './components/happen.vue'
import submission from './components/submission.vue'
import causeanalysis from './components/causeanalysis.vue'
import advice from './components/advice.vue'
/* import formDetails from './components/formDetails.vue' */
export default {
components: {ScopeSupervision,
applicationaccess,
utilitysystemstatus,
ops,
files,
cooperate,
approve,
happen,
submission,
causeanalysis,
advice},
data () {
return {
ruleForm: {
template_name: 'xxxx报告',
format_list: 'wps',
type_list: 'moon',
check_list: [],
check_chart_list: []
}
}
},
methods: {
async handleSave () {
this.loading = true
// 创建临时目标dom
let temptReportDom = document.createElement('div')
// 获取页面相关dom
let pageDom = document.getElementById('export-chart')
let getBoxList = pageDom.getElementsByClassName('report_form_flag')
// dom 元素循环(不能使用es6的方法)
for (let index = 0; index < getBoxList.length; index++) {
const element = getBoxList[index]
let elId = element.id
if (
!(
elId === 'event-ranking-top-form' ||
elId === 'export-chart-title'
)
) {
// 将chart图表转换成图片
let base64url = await this.handleDomToImg(element)
let img = new Image()
img.src = base64url
let targetDom = document.createElement('div')
targetDom.id = elId
targetDom.appendChild(img)
// 存入目标dom
temptReportDom.appendChild(targetDom)
targetDom = null
} else {
let targetDom = document.createElement('div')
targetDom.id = elId
// 存入目标dom
targetDom.innerHTML = element.innerHTML
temptReportDom.appendChild(targetDom)
targetDom = null
}
}
this.handleExportReport(temptReportDom)
// 删除不再使用的dom
temptReportDom = null
},
handleDomToImg (dom) {
return domtoimage.toPng(dom)
},
handleMapCheckDom (value) {
let domId = ''
switch (value) {
case 'zcxx':
domId = 'scopesupervision'
break
case 'ryfw':
domId = 'applicationaccess'
break
case 'wlhl':
domId = 'utilitysystemstatus'
break
case 'ywqk':
domId = 'ops'
break
case 'wjcs':
domId = 'files'
break
case 'xcxb':
domId = 'cooperate'
break
case 'sxsp':
domId = 'approve'
break
case 'sjfs':
domId = 'happen'
break
case 'ajbs':
domId = 'submission'
break
case 'fxsjcy':
domId = 'causeanalysis'
break
case 'gjjy':
domId = 'advice'
break
default:
break
}
return domId
},
// 调用后端接口
handleExportReport (dom) {
let params = {
title: this.ruleForm.template_name,
exportFormat: this.ruleForm.format_list,
// 由于需要给文档添加一个标题,在传参数时拼接上去即可
htmlBody: '<h2 style="text-align:center">xxxx 报告 </h2>' + dom.innerHTML + this.$refs.child.$el.innerHTML + this.$refs.child1.$el.innerHTML
}
// 二进制流
exportWord(params)
.then((file) => {
if (file) {
let typeRes =
this.ruleForm.format_list === 'wps'
? 'application/msword'
: 'application/pdf'
let fileName = `${this.ruleForm.template_name}.${this.ruleForm.format_list === 'wps' ? 'doc' : 'pdf'}`
if (window.navigator.msSaveBlob) {
try {
const blob = new Blob([file], { type: typeRes })
window.navigator.msSaveBlob(blob, fileName)
} catch (e) { }
} else {
const blob = new Blob([file], { type: typeRes })
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
}
this.handleCancel()
}
})
.finally((_) => {
this.loading = false
})
},
handleCancel () {
this.$emit('cancel')
}
}
}
</script>
当然,如果是单纯将echarts转换为图片的话,echarts官网中有个 getDataURL方法 可以返回一个base64的URL,这里不再赘述,我的这个方法也可以转换,如果有更好的实现方式,希望有大佬可以在评论区批评指正。