- 数据分析
- 数据可视化
- 前端
【免费下载链接】evidence
Business intelligence as code: build fast, interactive data visualizations in SQL and markdown
这篇技术指南以仓库中的 cli/test-environment/pages/order-analysis.md 示例页面为主线,完整讲解如何使用 Evidence(Business intelligence as code:用 SQL 与 Markdown 构建交互式数据可视化)编写一份覆盖渠道、支付方式与产品品类的零售订单分析报表。读者读完可以掌握 dropdown / button_group 过滤器搭建、big_value 核心指标卡、line_chart 趋势图与 table 多维表格(含 pivot、delta 对比)的完整写法,并学会在本地 CLI 开发环境中直接运行与调试这份报表。
一、示例页面在仓库中的定位
order-analysis.md位于 CLI 的本地开发测试工程 cli/test-environment/ 的pages目录下。该目录是 Evidence CLI 开发时用来跑命令的"测试项目",入口页 cli/test-environment/pages/home.md 将其注册为Order Analysis页面(零售订单分析,涵盖渠道与产品维度)。
从文件组织看,这份报表完全由 Evidence 的 markdown + 组件语法写成,不包含任何自定义 JavaScript。所有数据源均指向两张 demo 表:
demo.order_headers:订单头表,含sales_channel、payment_method、date、hour等字段,用于渠道、支付方式、时段维度;demo.order_details:订单明细表,含category、item_name、quantity、unit_price、date等字段,用于产品与品类维度。
这也决定了整份报表的两条主线:订单头数据回答"谁在哪买、怎么买",订单明细数据回答"卖什么、赚多少"。
二、在本地运行这份报表
order-analysis.md是 cli/test-environment/ 工程的一部分,可以按该目录 README 提供的方式在 monorepo 根目录直接启动:
# 启动开发服务器(vite dev,无需先构建二进制) pnpm evd dev # 用 CLI 直接执行一条查询,验证数据源连通 pnpm evd query --sql "select 1"两条命令都通过--project cli/test-environment(默认值)把工程目录传给 CLI,而不依赖cd切换工作目录。启动后在浏览器打开/order-analysis即可看到报表;修改pages下的 Markdown 会触发热更新,控制台会输出查询执行日志(详见 cli/test-environment/README.md)。
三、页面结构与"过滤器 → 组件消费"数据流
整份报表遵循 Evidence 的典型布局:顶部定义过滤器 → 各业务小节用filters=[...]引用过滤器 ID。页面共 9 个小节,对应 9 个分析主题:
| 小节 | 核心组件 | 数据表 | 消费的过滤器 |
|---|---|---|---|
| Filters | dropdown × 2、button_group | demo.order_headers | — |
| Executive Summary | big_value × 3(含 sparkline) | 两张表 | channel_filter、payment_filter |
| Sales Channel Performance | line_chart、table | demo.order_headers | payment_filter / channel_filter |
| Payment Method Analysis | line_chart、table(含 pivot) | demo.order_headers | channel_filter |
| Product Performance | table | demo.order_details | channel_filter |
| Category Revenue Analysis | line_chart、table(含计算列) | demo.order_details | channel_filter |
| Time-of-Day Analysis | line_chart、table | demo.order_headers | channel_filter、payment_filter |
| Top Selling Products | table | demo.order_details | channel_filter |
| Year-over-Year Performance | table(date_range + comparison) | demo.order_details | channel_filter |
可以看到filters属性是页面联动的心脏:过滤器通过id注册,组件通过filters=[...]数组声明自己消费哪些过滤器,从而在选值变化时自动重查。这正对应 docs/components/dropdown.mdx 中对filters属性的定义——"Array of filter IDs to apply when querying"。
四、过滤器搭建:dropdown 与 button_group
4.1 两个下拉筛选器
页面开头定义了两个 dropdown,分别筛选销售渠道与支付方式:
{% dropdown id="channel_filter" data="demo.order_headers" value_column="sales_channel" title="Sales Channel" initial_value="All" /%} {% dropdown id="payment_filter" data="demo.order_headers" value_column="payment_method" title="Payment Method" initial_value="All" /%}参数含义(依据 docs/components/dropdown.mdx):
id(必填):过滤器的唯一标识,供其它组件的filters属性引用;data+value_column:指定从哪张表、哪个列取值作为下拉选项(此处从订单头表动态读取渠道/支付方式的去重值);title:显示在下拉框上方的标题;initial_value:初始选中值,这里设为"All"。
dropdown 还支持label_column、multiple(多选)、select_first、default_top_n、search、clear、order、where、date_range等高级属性,以及级联用法——在 dropdown 的filters中引用另一个 dropdown 的id,即可实现"选了品类后,产品下拉只出现该品类下的商品"(参见 docs/components/dropdown.mdx 的 Cascading Dropdowns 示例)。
4.2 按钮组时间粒度切换
{% button_group id="time_grain" title="Time Period" %} {% option value="month" label="Monthly" /%} {% option value="quarter" label="Quarterly" /%} {% option value="year" label="Yearly" /%} {% /button_group %}与 dropdown 不同,button_group 没有绑定data和value_column,而是用子组件option显式声明选项(依据 docs/components/option.mdx,option允许的父组件是 dropdown / button_group / input_tabs)。option支持value(必填)、label、fmt(如fmt="usd"用于联动度量格式)。
注意time_grain的消费方式与 dropdown 不同:图表中用date_grain={{time_grain}}把按钮组的选中值作为"时间粒度"注入,而非放进filters数组——这是 button_group 作为"控制值"而非"筛选条件"的典型用法。
4.3 过滤器变量的取值语义
在 SQL 或组件属性中可通过{{filter_id}}引用过滤器值。以 dropdown 为例,依据 docs/components/dropdown.mdx:
| 上下文 | 默认属性 | 未选中 | 单选 | 多选 |
|---|---|---|---|---|
内联 SQL /where属性 | .selected | '' | 'Electronics' | ('Sports', 'Home') |
| 文本 / Markdown | .literal | — | Electronics | Sports, Home |
更细粒度可用{{filter_id.filter}}(返回完整 WHERE 表达式,未选中时为true)、{{filter_id.selected}}(带引号的 SQL 比较值)、{{filter_id.literal}}(原始值)、{{filter_id.label}}(展示标签)、{{filter_id.fmt}}(选项关联的格式串)。order-analysis.md正是通过date_grain={{time_grain}}这种引用方式把按钮组值与图表属性打通。
五、Executive Summary:big_value 核心指标卡
第一屏用三个big_value展示订单总量、总营收与销售件数:
{% row %} {% big_value data="demo.order_headers" value="count(*)" title="Total Orders" fmt="num0" filters=["channel_filter", "payment_filter"] sparkline={ type="bar" x="date" } /%} {% big_value data="demo.order_details" value="sum(quantity * unit_price)" title="Total Revenue" fmt="usd1m" filters=["channel_filter"] sparkline={ type="area" x="date" } /%} {% big_value data="demo.order_details" value="sum(quantity)" title="Items Sold" fmt="num0" filters=["channel_filter"] /%} {% /row %}要点(依据 docs/components/big_value.mdx):
value传入 SQL 聚合表达式:count(*)、sum(quantity * unit_price)、sum(quantity);fmt控制展示格式:num0(整数千分位)、usd1m(美元、1 位小数、百万量级缩写,渲染为如$412.1m);filters声明指标卡响应的过滤器——注意三个卡片的过滤器组合刻意不同:Total Orders 同时响应渠道与支付方式,Total Revenue 与 Items Sold 只响应渠道,实现不同 KPI 的差异化联动;sparkline对象为指标卡附加迷你趋势:type支持line/area/bar,x指定时间列;文档中还支持color、y_fmt、x_fmt、fit_to_data、date_grain、date_range等子属性。
big_value还支持comparison(与上期/上年/目标/基准对比)、text_size(sm到5xl)、metric(引用语义化指标而非data+value)等能力,可参见 docs/components/big_value.mdx。
六、Sales Channel Performance:渠道表现
6.1 渠道订单趋势折线图
{% row %} {% line_chart data="demo.order_headers" x="date" y="count(*)" series="sales_channel" date_grain={{time_grain}} y_fmt="num0" title="Orders by Sales Channel Over Time" filters=["payment_filter"] /%} {% /row %}这是"过滤器 + 控制值"组合消费的典范:date_grain={{time_grain}}让折线图随按钮组在 月/季/年 粒度间切换,series="sales_channel"按渠道拆分多系列折线,filters=["payment_filter"]让支付方式筛选作用于本图(依据 docs/components/line_chart.mdx)。line_chart还支持subtitle、chart_options.series_colors自定义系列颜色、date_grain="day of week"/"month of year"等季节性子粒度(周年循环分析)。
6.2 渠道明细表:三种可视化度量
{% table data="demo.order_headers" filters=["payment_filter"] %} {% dimension value="sales_channel" title="Channel" /%} {% measure value="count(*)" title="Total Orders" fmt="num0" viz="bar" bar_options={ bar_color="#3b82f6" } /%} {% measure value="count(distinct date)" title="Active Days" fmt="num0" /%} {% measure value="count(*)" title="Order Trend" viz="sparkline" sparkline_options={ x="date" type="area" } /%} {% /table %}这里示范了measure的三种viz形态(依据 docs/components/measure.mdx):
- 默认数值列:
count(distinct date)统计活跃天数,注意它用的是去重聚合而非count(*); viz="bar":列内条形,配合bar_options.bar_color自定义条色(此处为蓝色#3b82f6);viz="sparkline":行内迷你趋势图,sparkline_options指定x="date"与type="area"。
dimension定义行分组列,title可覆盖列标题(见 docs/components/dimension.mdx)。
七、Payment Method Analysis:支付方式分析(含透视)
支付方式小节示范了 Evidence 表格的**透视(pivot)**能力:
{% table data="demo.order_headers" filters=["channel_filter"] %} {% dimension value="payment_method" title="Payment Method" /%} {% pivot value="sales_channel" /%} {% measure value="count(*)" title="Orders" fmt="num0" viz="color" /%} {% /table %}结构为"行维度(支付方式)× 列维度(销售渠道)× 度量(订单数)",等价于 Excel 透视表。关键点:
pivot把sales_channel变成列方向维度;pivot还支持date_grain(把日期列按 月/季/年 分桶为列)、sort(asc/desc),见 docs/components/pivot.mdx;viz="color"对订单数做连续色阶着色,快速识别高低分布;measure的viz="color"支持color_options.color_scale自定义三段色(见 docs/components/measure.mdx)。
八、Product Performance 与 Category Revenue Analysis:产品维度分析
8.1 产品表现表
{% table data="demo.order_details" filters=["channel_filter"] %} {% dimension value="category" /%} {% dimension value="item_name" title="Product" /%} {% measure value="max(unit_price)" title="Price" fmt="usd2" viz="bar" bar_options={ bar_color="#10b981" } /%} {% measure value="sum(quantity)" title="Units Sold" fmt="num0" /%} {% measure value="sum(quantity * unit_price)" title="Revenue" fmt="usd1m" viz="color" /%} {% /table %}两层维度(品类 → 产品)先粗后细,max(unit_price)取最高单价作为"Price",usd2保留两位小数,Revenue 用色阶突出量级。
8.2 品类营收趋势与计算列
{% line_chart data="demo.order_details" x="date" y="sum(quantity * unit_price)" series="category" date_grain={{time_grain}} y_fmt="usd" title="Revenue by Category Over Time" filters=["channel_filter"] /%}{% measure value="sum(quantity * unit_price) / sum(quantity) as avg_price" title="Avg Price" fmt="usd2" /%}这里的value="sum(quantity * unit_price) / sum(quantity) as avg_price"是Evidence 计算列的写法:直接用 SQL 表达式生成新列并as命名(依据 docs/components/measure.mdx 的 Calculated Measures 示例,如sum(total_sales) / sum(transactions) as avg_price)。Avg Price 正是"加权平均单价"。
九、Time-of-Day Analysis 与 Top Selling Products:细粒度洞察
时段分析按小时观察下单分布,同时消费两个过滤器:
{% line_chart data="demo.order_headers" x="hour" y="count(*)" series="sales_channel" y_fmt="num0" title="Orders by Hour of Day" filters=["channel_filter", "payment_filter"] /%}注意此处的x="hour"是普通数值维度而非日期,因此没有date_grain;line_chart的x并不强制要求时间列。紧随其后的表格按hour分组统计订单数,并用橙色#f59e0b条形展示。
Top Selling Products 汇总销量与营收:
{% measure value="sum(quantity * unit_price) / sum(quantity) as avg_price" title="Avg Price" fmt="usd2" /%} {% measure value="sum(quantity)" title="Sales Trend" viz="sparkline" sparkline_options={ x="date" type="bar" } /%}与前面章节复用同一套dimension/measure模式,并再次组合"计算列 + 行内 sparkline(柱状)",说明这些构件可以像积木一样跨页面复用。
十、Year-over-Year Performance:同比(YoY)分析
报表以同比分析收尾,示范measure的date_range+comparison组合(依据 docs/components/measure.mdx 的 Prior Year Comparison 示例):
{% measure value="sum(quantity * unit_price)" title="Revenue (L12M)" fmt="usd1m" date_range={ range="last 12 months" date="date" } comparison={ compare_vs="prior year" } viz="delta" /%} {% measure value="sum(quantity)" title="Units Sold (L12M)" fmt="num0" date_range={ range="last 12 months" date="date" } comparison={ compare_vs="prior year" } viz="delta" /%}解读:
date_range是对象而非字符串:range="last 12 months"限定近 12 个月,date="date"指明日期列(表含多个日期列时必填)。range支持预置值(last 7 days、month to date、year to date、all time等)、动态模式(Last 90 days)、自定义窗口(2020-01-01 to 2023-03-01)与部分区间(from 2020-01-01/until 2023-03-01);comparison.compare_vs="prior year"与上年同期对比,另有prior period(同长上期)、target(目标值)、benchmark(组内平均/聚合基准);comparison还支持display_type(pct/abs/compared_value)、down_is_good、neutral_range等;viz="delta"把对比渲染为涨跌指示,配合fmt="usd1m"/fmt="num0"显示本期值。
big_value同样支持date_range+comparison组合做 KPI 级同比(见 docs/components/big_value.mdx),可将同一套逻辑下沉到核心指标卡。
十一、总结:一份可复用的订单分析报表模板
回看 cli/test-environment/pages/order-analysis.md 全页,它几乎覆盖了 Evidence 构建业务报表所需的全部基础组件:
- 过滤器层:
dropdown(数据驱动选项)+button_group(手工选项)+option子组件,构成页面交互入口; - KPI 层:
big_value+sparkline+filters组合,提供可联动的一屏总览; - 趋势层:
line_chart+series+date_grain(支持被按钮组动态控制),覆盖"随时间变化"的各类主题; - 明细层:
table+dimension/measure/pivot,配合viz="bar"/viz="color"/viz="sparkline"与bar_options/sparkline_options做表内可视化; - 进阶分析:SQL 计算列(
as别名)、date_range时间窗口、comparison同比对比、viz="delta"涨跌渲染。
整套报表只依赖两张 demo 表、纯 Markdown 编写、零自定义代码,充分体现了 Evidence "Business intelligence as code" 的核心工作方式:分析即文档,文档即查询。仓库内的组件参考文档位于 docs/components/,格式化说明见 docs/core-concepts/value-formatting.mdx,可直接将本页中的fmt值替换为其它货币(CNY/EUR/JPY 等)、量级(k/m/b/t)或数字精度格式,按需定制自己的订单分析看板。
- 数据分析
- 数据可视化
- 前端
【免费下载链接】evidence
Business intelligence as code: build fast, interactive data visualizations in SQL and markdown
相关推荐
Apache RocketMQ 消息过滤实战:从 Tag 订阅到 SQL92 表达式过滤完整指南
Apache RocketMQ 消息过滤实战:从 Tag 订阅到 SQL92 表达式过滤完整指南 本篇指南聚焦 Apache RocketMQ 的 消息过滤(M
消息队列流处理后端Comp AI CRM 列表构建路线图:从字段、过滤器到可复用 BDR 名单的完整规划
Comp AI CRM 列表构建路线图:从字段、过滤器到可复用 BDR 名单的完整规划 导读 本文基于 docs/list building roadmap.m
后端前端CRM人工智能AI AgentEvidence 交互式销售分析仪表板实战:用 SQL + Markdown 构建可过滤的数据可视化
Evidence 交互式销售分析仪表板实战:用 SQL + Markdown 构建可过滤的数据可视化 本文以 Evidence 仓库内的 cli/test en
数据分析数据可视化前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考