看板与卡片
主体写成看板 dashboard 时,报表是一张网格,上面排着图表、指标与表格卡片。每张卡片各自取数、各自计算,可以来自不同的数据集。
网格与布局
grid.columns 是列数,grid.rowHeight 是每行的高度(px);列宽随看板的宽度均分。每张卡片的 layout 写左上角所在的格(x、y,从 0 起)和占多少格(w、h):
const body: DashboardView = {
type: 'dashboard',
grid: { columns: 12, rowHeight: 40 },
cards: [sales, orders, quantity, trend, regions, top],
}- 卡片互相重叠、或超出列数时,校验报
layout-overlap、layout-out-of-bounds。 - 视口窄于 768px 时,查看器把看板退成单列,按卡片的位置自上而下排,每张卡片保持原来的高度。
取数与刷新
看板上的卡片各自生成取数请求;同一轮里请求相同的卡片只取一次。取回后每张卡片单独计算、单独绘制,取数中显示「正在加载…」,出错的卡片显示「数据加载失败」并派发 load-error,不影响其它卡片。
refresh() 重新取数,refresh({ cards: ['trend'] }) 只刷新列出的卡片。刷新与联动时卡片原地更新:同种图表复用元素、只换数据,不重放入场动效,键盘焦点也留在原处,适合定时刷新。
查询
图表与指标卡片用一份聚合查询 query 取数:按 dimensions 分组,每组算出 measures。
- 维度写数据集字段
field,日期字段可以写粒度bucket(year、quarter、month、week、day、hour),sort按键或按某个度量排成员。 - 度量写聚合方式
aggregate与字段:sum、avg、count、min、max、distinctCount,count不写字段就是数行数。度量也可以写公式formula,以同一查询的其它度量与$参数名为变量,在分组算好之后求值。 filter是查询自己的筛选,sort按维度或度量 id 排结果行,limit在排序之后截取,不影响总计。
维度与度量的 id 是结果行里的键,图表与指标的配置都引用这些 id,而不是字段名。
图表卡片
图表卡片 kind: 'chart' 带一份查询和一份图表配置 chart。图表用 XiHan.UI 的图表元素绘出,颜色只取图表的语义色。
const trend: ChartCard = {
id: 'trend',
kind: 'chart',
title: '月度销售额',
layout: { x: 0, y: 4, w: 8, h: 7 },
dataset: 'sales',
query: { dimensions: [month, { id: 'category', field: 'category', title: '品类' }], measures: [amount] },
chart: {
type: 'cartesian',
splitBy: 'category',
series: [{ id: 'amount', mark: 'bar', x: 'month', y: 'amount', stack: 'total' }],
},
}| 图表 | type | 绑定 |
|---|---|---|
| 柱线图 | cartesian | 每条系列 series 写标记(bar、line、scatter)、横坐标维度 x 与数值度量 y;splitBy 按一个维度的每个成员各展开一条,stack 相同的系列堆叠;横向、坐标轴、标注、缩放与刷选另有配置 |
| 饼图 | pie | 名称维度 nameField 与数值度量 valueField;variant: 'donut' 是环形图,还可以写成玫瑰图、半圆 |
| 漏斗图 | funnel | 阶段维度与数值度量;可以显示相对上一阶段或第一阶段的转化率 |
| 雷达图 | radar | 实体维度 nameField,每个指标 indicators 是一根轴 |
| 桑基图 | sankey | 源维度、目标维度与数值度量 |
| 热力图 | heatmap | 日历(calendar、month)按日期维度着色;矩阵(matrix)按行列两个维度着色 |
| 层级图 | hierarchy | 各层维度 levels 由上到下,数值度量 valueField;布局可选矩形树图、旭日图、冰柱图与圆堆图 |
每种图表的全部属性见属性 · 图表。
指标卡片
指标卡片 kind: 'metric' 显示查询总计里的一个值:
const sales: MetricCard = {
id: 'sales',
kind: 'metric',
layout: { x: 0, y: 0, w: 4, h: 4 },
dataset: 'sales',
query: {
dimensions: [month],
measures: [amount, { id: 'target', title: '目标', formula: '200000' }],
},
metric: { value: 'amount', baseline: 'target', prefix: '¥', sparkline: { x: 'month', y: 'amount' } },
}value是显示的度量;baseline是对比基准,卡片按两者比出涨跌与变化率。上面的目标是一个只写常数的公式度量。prefix、suffix、format决定值怎么写,size与tone是尺寸与语气。sparkline画一条迷你走势,横坐标是查询的一个维度、数值是一个度量,所以查询按月分组时迷你图就按月走。
表格卡片
表格卡片 kind: 'table' 带一个视图 view:明细表、分组报表或交叉表,写法与报表主体一样,有自己的数据集与筛选。
const top: TableCard = {
id: 'top',
kind: 'table',
title: '金额最高的订单',
layout: { x: 0, y: 11, w: 12, h: 6 },
view: {
type: 'table',
dataset: 'sales',
columns: [
{ id: 'orderId', field: 'orderId', width: 150 },
{ id: 'date', field: 'date' },
{ id: 'region', field: 'region' },
{ id: 'category', field: 'category' },
{ id: 'amount', field: 'amount', align: 'end', format: money },
],
sort: [{ field: 'amount', direction: 'desc' }],
limit: 8,
},
}扩展卡片
扩展可以登记新的卡片种类,种类名带点,如 gantt.timeline。没装登记它的扩展时,校验报 unknown-kind:查看器不取数,显示「报表定义有问题」;设计器里卡片原样保留,画出种类名占位。
