Vue2 实现一个简单的数据报告功能 1

793 阅读6分钟

Vue2 实现一个简单的数据报告功能 1

调研过程就不做细究,方案不止一种,我当时找到了 4 种,各有优缺点,最后还是选择了如下的方式,因为更适合我们的项目。

1. 需求

先说说我们的需求吧,就是有些用户会在每周或者每月做数据统计汇总,我们发现,用户在制作报告的过程中,很多时候就是写好了一个 Word 模板,然后再从我们系统去获取数据填入,不同的用户使用的模板不一样,但是数据基本一致,所以我们想将这个过程简化,让用户能更快速的制作出一个报告。

2. 使用 file-saver + html-docx-js 实现导出 Word

  • 安装:yarn add file-saver html-docx-js
  • 使用(并没有写样式):
<template>
  <div>
    <button @click="exportWord">导出为Word</button>

    <div ref="testDoc">
      <h1>测试标题1</h1>
      <h2>测试标题2</h2>
      <h3>测试标题3</h3>
      <h4>测试标题4</h4>
      <h5>测试标题5</h5>

      <p>测试段落</p>

      <table>
        <thead>
          <th>标题1</th>
          <th>标题2</th>
          <th>标题3</th>
          <th>标题4</th>
        </thead>
        <tbody>
          <tr>
            <td>1111</td>
            <td>2222</td>
            <td>3333</td>
            <td>4444</td>
          </tr>
          <tr>
            <td>1111</td>
            <td>2222</td>
            <td>3333</td>
            <td>4444</td>
          </tr>
          <tr>
            <td>1111</td>
            <td>2222</td>
            <td>3333</td>
            <td>4444</td>
          </tr>
        </tbody>
      </table>

      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>

      <ol>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ol>

      <!-- 图片用线上地址或者base64格式 -->
      <img src="https://img0.baidu.com/it/u=3580555748,3972654988&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500" alt="">
    </div>
  </div>
</template>

<script>
import { asBlob } from 'html-docx-js/dist/html-docx'
import saveAs from 'file-saver'

export default {
  methods: {
    exportWord () {
      // this.$refs.testDoc.$el
      const content = this.$refs.testDoc
      const page = `<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>${content.innerHTML}</body></html>`
      const converted = asBlob(page)
      saveAs(converted, `测试.docx`)
    }
  }
}
</script>

点击导出按钮查看文件,效果如下(图片在第二页,没截取了):

测试Word1.png

可以看到,该有的结构都有,只是还没有写样式,一旦有了样式,那就好看了。所以基于此可以做一些简单的 word 文件的导出需求了。截取一张我们项目中使用到的最终导出的 Word 效果图吧(因为涉及到部分隐私数据,所以打码了):

测试Word3.png

大概说说实现步骤吧,感兴趣的可以自己去研究下。

首要的功能已经实现,就是将 HTML 导出为 Word,接下来就是实现部分样式(样式要用内联那种哟,而且样式也不是百分百的兼容,细节还等待你去发现),将数据填充上去。为什么导出 Word,说白了就是将部分能从系统抓取的数据展示出来,然后用户就可以基于此做一个报告出来,不用在网站上到处找数据去做报告。

3. 一些核心功能的实现

这里就简单的说一些核心功能的实现方式(完全的实现还是比较复杂,如果以后空闲了,我再出一个更详细的,可能还要分几篇来写)。

从我们的需求中可以看到,用户是基于自己的 Word 模板来制作各自的数据报告,所以,我们得实现定制化模板的功能,基于这个模板,一键生成数据报告。那么这个模板具体有些什么?其实很简单,当然是文字 + 图表了 (哈哈哈,开个玩笑)。我们将它细分为如下功能模块。

  • 标题模块
  • 段落模块
  • 表格模块
  • 数据图模块
  • 有序/无序列表模块
  • 样式设置模块

分析到这里,是不是有点儿奇奇怪怪的感觉,感觉这个功能是不是在哪里见过?好吧,这不就是一个富文本编辑器嘛,只不过我们是特殊化定制的富文本编辑器。

模板分析到这里,接下来就是数据了,模板的作用就是后面生成报告的时候,直接将数据填充上去,就是一个报告了,那么如何将数据填充?其实也简单,留个坑位,到时候直接替换即可。我们将数据分为如下几种情况,分别有不同的替换方式。

  • 段落中的数据:例如:本周新增了 20 人,这个 20 就是我们要替换的数据,这种使用的是占位,有点儿像 Vue 的 {{}},为了和 Vue 区分开,最后就变成了这种,本周新增了 {%newPeopleWeek%} 人,在生成报告的时候用正则替换即可。这种适用于标题模块,段落模块,有序/无序列表模块,因为展示的都是一些非结构化的数据。
  • 表格中的数据:表格我们分为两种
    • 用户就想要得一个什么都没有的表格,内容用户自己添加,不涉及到数据。这个比较简单,就是生成一个普通的表格,内容用户自己去编辑,行列也由用户自己去增加删除。
    • 用户想展示数据的表格。这种表格就比较简单了,和后端约定好数据结构,然后通过这个结构去生成对应的表格即可,用户想要生成这种表格,就是在点击生成表格模块的时候选择自己想要展示得一个数据源,到时候生成报告的时候,将这个数据源 ID 给后端,他返回对应的数据即可。一般这就结束了,但是用户不同,我们不知道他们想展示什么数据,只有一个大概的范围,所以给出了数据源这个概念,万一部分用户只想展示这个数据源中部分列数据,怎么办?害,再增加个选择功能即可,每行再增加个删除功能,但是删除了怎么回退?增加个操作列表,记录历史操作,撤销就是,有点儿感觉没得,是不是有点儿像 命令模式 的感觉(后期也是用命令模式来实现的)。最后大概就像下面这样。

导出Word2.png

  • charts 数据:图这种数据和表格类似,也是结构化的数据,我们制作模板的时候依然只是选择数据源,后期生成报告的时候根据数据源 ID 去拿到对应的数据展示成图表即可,因为 Word 还没有强大到兼容我们的交互式图表,所以我们这里在生成图表后直接通过截图保存即可。一般这也就结束了,但是的用户是不同的人,我们不知道他到底想怎么去展示这种数据,有些用户喜欢饼图,有些喜欢折线图,有些喜欢柱状图,怎么办?害,继续加呗,根据这份数据去生成不同的图表,简单。最后大约就是像下面这样(当然还有有些其他的特殊定制化图表,实现步骤都差不多,只是数据结构不一样罢了)。

导出Word3.png

4. 最后

由于篇幅和时间关系,所以就没有更细致的解析,后面如果我空闲了再出一版更为详细的。如果你刚好有这方面的需求,可以按照这个思路来实现一个,有其他疑问再一起讨论即可。