跳到正文

这是开发版文档,跟随主分支更新,可能包含尚未发布的功能。

数据透视 ​

@dou-ui/pivot 把一组明细记录按字段分组汇总成交叉表。选好哪些字段放在行上、哪些放在列上、汇总哪些数值,表格会算出每个组合的结果,以及各级小计和总计。

透视表只读取传入的记录,不会修改它们。10 万条记录的分组汇总在几十毫秒内完成,只调整排序、展开或折叠时不会重新汇总。完整页面的写法见区块中的销售分析和工单统计。

安装 ​

数据透视是单独的包,需要和 dou-ui 一起使用:

sh
bun add dou-ui @dou-ui/pivot

引入样式,再注册组件:

ts
import 'dou-ui/style.css'
import '@dou-ui/pivot/style.css'
import { DouPivot, DouPivotFields } from '@dou-ui/pivot'

app.use(DouPivot)
app.use(DouPivotFields)

基础用法 ​

data 是一组记录,fields 说明每个字段的名称和显示方式,config 决定字段放在哪里:

  • rows:放在行上的字段,从外到内逐级分组;
  • columns:放在列上的字段;
  • values:要汇总的数值。
季度
销售额
Q1
Q2
Q3
Q4
总计
华东
¥5,767
¥7,177
¥7,169
¥7,287
¥27,399
杭州
¥1,592
¥1,918
¥1,494
¥2,087
¥7,091
南京
¥1,215
¥1,754
¥2,169
¥1,662
¥6,800
上海
¥1,313
¥1,572
¥1,934
¥1,832
¥6,651
苏州
¥1,647
¥1,933
¥1,572
¥1,705
¥6,857
华南
¥6,635
¥6,794
¥7,384
¥7,154
¥27,968
广州
¥1,766
¥1,989
¥3,088
¥2,588
¥9,431
厦门
¥2,651
¥2,101
¥2,582
¥2,220
¥9,554
深圳
¥2,218
¥2,704
¥1,714
¥2,346
¥8,983
华北
¥7,200
¥6,160
¥6,969
¥6,858
¥27,186
北京
¥1,571
¥2,031
¥2,424
¥2,145
¥8,172
青岛
¥2,777
¥2,437
¥2,170
¥2,558
¥9,942
天津
¥2,852
¥1,691
¥2,375
¥2,155
¥9,072
西南
¥6,322
¥6,537
¥5,891
¥5,950
¥24,700
成都
¥2,222
¥2,099
¥1,683
¥1,948
¥7,952
重庆
¥2,279
¥2,038
¥2,254
¥2,171
¥8,742
昆明
¥1,821
¥2,400
¥1,954
¥1,831
¥8,006
总计
¥25,923
¥26,668
¥27,413
¥27,249
¥107,253

行上的多个字段显示成一棵树,组所在的行显示这一组的小计。列上的多个字段显示成多级表头,展开的组后面有一列“合计”。最下方的总计行在滚动时始终可见,最右侧是总计列。

config 支持 v-model:config,在表格里排序时会更新它。它是普通的数据,可以直接保存下来,下次打开时恢复同样的视图。

字段 ​

fields 是一个数组,每一项描述一个字段:

ts
import type { PivotConfig, PivotField } from '@dou-ui/pivot'
import { ref } from 'vue'

interface Order {
  region: string
  month: number
  amount: number
  cost: number
}

const fields: PivotField<Order>[] = [
  { name: 'region', label: '大区', order: ['华东', '华南', '华北', '西南'] },
  { name: 'month', label: '月份', format: (m) => `${m} 月` },
  {
    name: 'amount',
    label: '销售额',
    type: 'number',
    format: { style: 'currency', currency: 'CNY' },
  },
  { name: 'profit', label: '毛利', value: (row) => row.amount - row.cost },
]

const config = ref<PivotConfig>({ rows: ['region'], columns: ['month'], values: ['amount'] })
  • 给 PivotField 传入记录的类型,value 收到的 row 就带有类型。config 用 PivotConfig 标注,后面各页的片段只写出其中的字段。
  • name 是记录上的键,config 里用它指代字段;label 是表头上显示的名字。
  • type 不写时根据前 100 条记录推断。
  • format 决定组名或数值怎么显示:数字字段传 Intl.NumberFormat 的选项,日期字段传 Intl.DateTimeFormat 的选项,或者传一个函数。
  • order 指定组的顺序,没有列出的组排在后面。
  • value 从记录算出字段的值,用来定义记录上没有的字段。

不传 fields 时,字段从记录的键推断,表头显示键名。

空值(null、undefined、空字符串、NaN)归为一组,显示为“(空)”,总是排在最后。

尺寸 ​

size 设置行高,sm、md、lg 分别是 28、32、40px。maxHeight 是表格的最大高度,内容更少时表格随内容变矮;宽度总是占满容器。

rowHeaderWidth 是行头的宽度,窄屏上会自动收窄;columnWidth 是每个数值列的最小宽度,表格较宽时会适当加宽。

语言 ​

表格和字段面板里的文字(“总计”“(空)”、汇总方式的名称、菜单和对话框等)跟随 ConfigProvider 的语言,内置简体中文、繁体中文和英文。

messages 可以改写其中几条:

template
<DouPivot :data="orders" :config="config" :messages="{ total: '全部', empty: '未填写' }" />
  • messages.aggregates 里可以给自定义汇总方式起名字,键是它的 name。
  • pivotLocales 是内置的三份文案,按语言名称(如 'zh-CN')索引。要支持其他语言时,往里面加一份完整的 PivotMessages。
  • usePivotMessages(override?) 返回当前语言的文案,自己的界面里需要相同的文字时使用。

API ​

Pivot Props ​

名称说明类型默认值
data记录:对象数组,或按列给出的数组object[] | PivotColumns—
fields字段的说明PivotField[]从记录的键推断
config字段放在哪里,支持 v-model:configPivotConfig{}
collapsed折叠的组,支持 v-model:collapsed,见展开与折叠PivotCollapsed{}
maxHeight最大高度,数字按 px 计算;内容更少时随内容变矮number | string480
size行高:28、32、40px'sm' | 'md' | 'lg''md'
rowHeaderWidth行头的宽度(px),窄屏上会自动收窄number200
columnWidth每个数值列的最小宽度(px),表格较宽时会适当加宽number120
layout紧凑式或表格式布局'compact' | 'tabular''compact'
resizable能否拖动调整列宽booleantrue
worker是否在 worker 中汇总;'auto' 超过 10 万条时使用boolean | 'auto''auto'
engine在别处汇总:自己的 worker 或服务端PivotEngine—
aggregators自定义的汇总方式PivotAggregator[]—
highlight标出一个行组和一个列组,路径同 cellClick 给出的 row、column{ row?: PivotPath; column?: PivotPath }—
ariaLabel读屏读出的名称string'数据透视表'
messages替换语言包里的文字PivotMessagesOverride—

Pivot Events ​

名称说明参数
update:config在表格里排序时PivotConfig
update:collapsed展开或折叠组时PivotCollapsed
cellClick点击数字,或选中后按 Enter,见查看明细PivotCellEvent

Pivot Exposes ​

名称说明类型
result当前的汇总结果,见汇总内核PivotResult
expandAll({ axis? })展开所有组(options?) => void
collapseAll({ axis?, depth? })折叠从第 depth 级开始的所有组(options?) => void
toggle(axis, path, open?)展开或折叠一个组(axis, path, open?) => void
selectAll()选中全部格子() => void
copy({ all? })复制选中的格子,all 复制整张表(options?) => Promise<void>
toCSV(options?)导出 CSV,见复制与导出(options?) => string
toSheet({ name? })导出给 DouSheet 的工作簿(options?) => PivotSheetWorkbook
toChartRows({ valueIndex? })导出给图表的行数据和系列,见透视图(options?) => PivotChartRows
toGrid()每个格子的文字、数值和类型() => PivotGrid
print({ title?, orientation? })打印整张表(options?) => void

PivotField ​

名称说明类型默认值
name记录上的键,config 里用它指代字段string—
label表头和字段面板上显示的名字stringname
type字段的类型,决定怎么分组、排序和显示'string' | 'number' | 'date' | 'boolean'按前 100 条推断
format组名或数值的写法Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | (value) => string—
order排在前面的组,按列出的顺序unknown[]—
value从记录算出字段的值(row, index) => unknown读 row[name]

PivotConfig ​

名称说明类型默认值
rows行上的字段,对象写法见分组(string | PivotDimension)[][]
columns列上的字段(string | PivotDimension)[][]
values要汇总的值,对象写法见汇总方式(string | PivotValue)[]计数
filters按字段筛选Record<string, PivotFilter>—
valuesOn多个值放在哪个方向'columns' | 'rows''columns'
sort按某一列的数值给行组排序PivotValueSort | null—
totals总计行和总计列,见总计{ rows?: boolean, columns?: boolean }都显示

CSS 变量 ​

变量说明
--dou-pivot-line格子之间的线
--dou-pivot-line-strong表头、行头的分隔线
--dou-pivot-head-bg表头和总计行的背景
--dou-pivot-total-bg合计列和总计列的背景
--dou-pivot-ring键盘选中格子的边框颜色
--dou-pivot-selected选中范围的底色
--dou-pivot-scale-strength色阶最深时语气色的比例,默认 28%
--dou-pivot-bar-strength数据条语气色的比例,默认 12%
--dou-pivot-bar-strength-dark深色主题下数据条语气色的比例,默认 24%