[关闭]
@Bios 2021-04-08T08:57:43.000000Z 字数 1520 阅读 458

中台大文件导出方案

前端


背景

现在中台系统有两种导出方式,前端导出后端导出

前端导出采取的是一次获取10000条数据,然后生成excel,缺点就是容易遗漏数据。
后端导出是后台生成excel返回下载链接,缺点就是请求时间长,用户体验不好。

技术调研

  1. 后端导出

    • 大量数据生成excel时间长,接口返回很慢
    • 无法获取实时进度 - (websocket)
    • sdk那边不支持后端导出(转发)
  2. 前端导出

    • 采用分页查询,可控制每页数量,单个接口请求时间短
    • 可以适用于sdk导出
    • 可以获取实时进度
    • 用户不用一直等待下载完成,可以继续从事其他工作,在适当的时间查看下载任务,如果完成就可以下载了

方案实现

在现有的中台基础框架下,采用前端导出,分页获取的方式最佳。

  1. this.$store.dispatch('setTask', {
  2. api: 'getBanLog',
  3. page: 'Page',
  4. pageSize: 'PageSize',
  5. params: {
  6. GameId: this.queryParam.GameId,
  7. StartTime: this.queryParam.StartTime,
  8. EndTime: this.queryParam.EndTime
  9. },
  10. data: 'data',
  11. excel: {
  12. title: '封禁记录',
  13. header: ['ID', '类型', '区服', '角色名称', '提交时间', '封禁时长(分钟)', 'Vip', '等级', '原因', '邮件内容', '封禁人'],
  14. field: ['Id', 'TypeName', 'ServerName', 'role', 'CreatedAt', 'DoMinute', 'VipLevel', 'Level', 'Reason', 'MailContent', 'CreatedName']
  15. }
  16. }).then(res => {
  17. this.$store.dispatch('setShowTask', true);
  18. });

要实现多个任务的同步进行,那么每一个Task必须是独立,并且每个下载任务完成后,在不刷新页面的情况是缓存的,为什么刷新页面就没了?而不做缓存? 没有这个必要性,作为用户使用下载任务,是及时的,下载完了这个功能就结束了。

  1. ├── DownloadTasks
  2. ├── api.js
  3. ├── index.vue
  4. └── task.vue

重点:
- 请求的api,需要提前导入(一个系统中提供下载的地方并不多)
- 请求参数
- 返回数据的读取路径(我们系统接的多方接口,并没有统一的规范)
- 导出表格的名称、表头、对应字段

根据数据的读取路径获取数据的算法:

  1. getValue (path, obj) {
  2. path = path.split('.');
  3. return path.reduce((prev, next) => {
  4. return prev[next];
  5. }, obj);
  6. },

进度条是根据返回的数据总数来处理的:

  1. this.percent = Number((100 / Math.ceil(total / 1000)) * page).toFixed(2) - 0;

针对USDK的接口,无法返回真实的数据总数:

如果这页数据小于pageSize,则表明请求完了 this.percent = 100

  1. if (data.length >= 1000 && !this.cancel && !this.clear) {
  2. this.getData(this.page++);
  3. } else {
  4. this.percent = 100;
  5. this.isComplete = true;
  6. }

局限性:
- 如果分页量达到了成百上千,这会到浏览器和服务器造成很大的压力
- 导出数据的字段需要提前转译(后端 例:date,status,type),这个功能不能放到组件内来做,这是实际业务的场景具有无逻辑性,无规则性。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注