旁观拍手笑疏狂。疏又何妨,狂又何妨
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
在ToB的业务中,报表是绕不过,也是比较难解决的一个需求,各个客户业务流程不同,业务节点不同,关注点不同,报表维度和内容也不尽相同,传统的表格难以满足诸如 合并表头 、 分组小计 、 多级小计 、加权平均 等等复杂的计算与展现需求,于是商业化的报表工具应运而生
商业化报表
- 帆软报表 帆软报表是国内比较有名的报表解决方案服务商,商业化报表经验在十年以上,积累了大量的业务代码和产品需求,最新的帆软报表已经支持数据建仓与维度建模,支持报表转图表,技术也更新了基于现代化前端框架的版本
- 锐浪报表 需要安装grid++ 插件,设计器是CS模式,打印也是CS模式,与帆软功能类似
- smartBi 类EXCEL报表,也是现代化框架的商业报表,功能也比较全,费用较高,按项目授权
- 葡萄城/活字格 类EXCEL报表,有开源版本,功能比smartBi要少
- 金蝶精斗云/用友财务云 集报表与财务管理于一体的sass服务,提供了专业化的财务报表
优势与局限
有句话说得好,“一分价钱一分货”,商业化报表功能大而全,收费也基本是项目授权的方式,早以前的买断制已经不在各大商业报表厂商的营销策略内,一个报表动辄十几万,几十万甚至上百万,而且功能扩展难,与自身产品风格难以有效融合,接入商业化报表带来的竞争力远远小于竞标成本的提升【ps: 假如你们做的都是上千万的项目,那可以当我没说】,假如不想每个项目都被钝刀子放血,自身构建一个报表设计和解析工具就势在必行。
前期调研
首先当然是需要了解市面上各大报表设计软件或各大sass系统的设计逻辑以及所实现的具体功能,分步实现报表设计和解析自有化。 首先通过cs进行设计的锐浪 Grid++被最先排除。。因为cs架构难以进行调试和代码定位。
通过对各大报表的使用和分析,总结得出了如下设计模型:
- 报表由资源表字段构建、统计依据、统计内容、查询配置 四部分构成
- 资源表字段构建:通过监听数据库的方式,将各个关联表的数据抽取到动态生成的宽表中,也就是基础的数据建仓
- 统计依据 就是要通过哪些字段来作为groupBy的条件【当然,分组是由前端解析完成的】
- 统计内容 数值项的列,指定那些列要参与小计、合计、以及小计的方式是求和,求平均,还是加权平均
- 查询配置 配置报表查询条件,只支持and连接,支持各类查询操作符如
EQLIKEINNOT_IN等
实现思路
- 资源表字段构建 采用
FLINK等框架做数据库监听及抽取即可,前端界面提供数据库表的选择以及进行表关联,为形成宽表提供条件即可 - 多级表头 多级表头需要在配置时维护数据列之间的tree关系即可
<vxe-grid v-bind="gridOptions"></vxe-grid>
gridOptions: {
border: true,
stripe: true,
resizable: true,
height: 500,
// 分组列头,通过 children 定义子列
columns: [
{ type: 'seq', width: 50 },
{
title: '基本信息',
children: [
{ field: 'name', title: 'Name' },
{
title: '其他信息',
children: [
{ field: 'nickname', title: 'Nickname' },
{ field: 'age', title: 'Age', sortable: true }
]
},
{ field: 'sex', title: 'Sex' }
]
},
{ field: 'address', title: 'Address', sortable: true, showOverflow: true }
],
}
- 分组及小计
分组及小计需要通过合并行列的方式去实现,其中为了支撑大数据量的展现,小计的计算需要通过webworker的方式另外开线程去做计算
核心实现略
- 查询条件配置
其实就是字段-查询操作符-字段类型的有机组合
<vxe-table-column field="compareType" title="比较符类型" width="180" >
<template #default="{ row }">
<a-select style="width: 140px;" allowClear v-model="row.compareType" @change="updateStatus('searchCondition', row)">
<a-select-option :value="option.value" v-for="option in compareOption" :key="option.value">
{{option.label}}
</a-select-option>
</a-select>
</template>
</vxe-table-column>
<vxe-table-column field="fieldType" title="字段类型" width="180" >
<template #default="{ row }">
<a-select style="width: 140px;" allowClear v-model="row.fieldType" @change="updateStatus('searchCondition', row)">
<a-select-option :value="option.value" v-for="option in fieldTypeOption" :key="option.value">
{{option.label}}
</a-select-option>
</a-select>
</template>
</vxe-table-column>
结语
基于vxe-table@3 进行封装的这个报表查询插件开启虚拟滚动后可以支持50W+数据的正常浏览,导出时间在3min内,小计采用NCPU开新开webworker进行计算,避免阻塞渲染进程导致浏览器崩溃。基本实现了客户的常用报表需求