vue中将有echarts图表的组件下载为图片,有表格的组件下载为可编辑的表格

文章目录

  • 前言
  • 一、实现步骤
    • 1.组件部分,需要给每个组件添加一个id
    • 2.js部分
  • 总结


前言

最近在项目中遇到一个报告下载的需求,后端需要前端将每个组件转为html,下载为word文档,识别不出echarts,需要将echarts组件转为图片,表格为可编辑状态,过程中遇到一点小问题,记录一下。


一、实现步骤

1.组件部分,需要给每个组件添加一个id

代码如下(示例):

<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>

2.js部分

代码如下(示例):

<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,这里不再赘述,我的这个方法也可以转换,如果有更好的实现方式,希望有大佬可以在评论区批评指正。

你可能感兴趣的:(vue.js,echarts,前端)