databricks-aibi-dashboards
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAI/BI Dashboard Skill
AI/BI仪表盘技能
Create Databricks AI/BI dashboards (formerly Lakeview dashboards).
A dashboard should be showing something relevant for a human, typically some KPI on the top, and based on the story, some graph (often temporal), and we see "something happens".
Follow these guidelines strictly.
When a custom app fits better: A managed AI/BI dashboard is the right tool for read-only KPIs, charts, and filters over governed tables. If the user instead needs a custom-code interactive app — write-back / data entry, bespoke UI or interactions beyond the dashboard grid, embedded or auth-gated workflows, or a conversational Genie/chat assistant as the primary surface — build a Databricks App instead with theskill (which brings indatabricks-appsfor the data-screen UX). Linking an "Ask Genie" space to this dashboard stays here (see Linking a Genie Space below).databricks-app-design
创建Databricks AI/BI仪表盘(原Lakeview仪表盘)。
仪表盘应展示对用户有价值的内容,通常顶部为关键绩效指标(KPI),并根据业务场景搭配图表(多为时间趋势图),呈现数据中的关键变化。
请严格遵循以下准则。
何时更适合使用自定义应用: 托管式AI/BI仪表盘适用于受管控表格的只读KPI、图表和筛选场景。如果用户需要的是自定义代码交互式应用——支持数据回写/录入、超出仪表盘网格的定制UI或交互、嵌入式或权限管控工作流,或是以对话式Genie/聊天助手为核心界面——则应使用技能构建Databricks应用(该技能包含用于数据界面UX的databricks-apps)。将“Ask Genie”空间链接至本仪表盘的操作仍遵循本指南(见下方“链接Genie空间”部分)。databricks-app-design
Quick Reference
快速参考
| Task | Command |
|---|---|
| List warehouses | |
| List tables | |
| Get schema | |
| Test query | |
| Create dashboard | |
| Update dashboard | |
| Publish | |
| Delete | |
flag: if--warehousefails withdatabricks experimental aitools tools query --warehouse WH "..."on your CLI version, setunknown flag: --warehousein the environment instead and drop the flag — the command auto-picks it from there.DATABRICKS_WAREHOUSE_ID=WH
| 任务 | 命令 |
|---|---|
| 列出计算仓库 | |
| 列出表格 | |
| 获取表结构 | |
| 测试查询 | |
| 创建仪表盘 | |
| 更新仪表盘 | |
| 发布仪表盘 | |
| 删除仪表盘 | |
参数说明: 若你的CLI版本执行--warehouse时提示databricks experimental aitools tools query --warehouse WH "...",可在环境变量中设置unknown flag: --warehouse,并移除该参数——命令会自动从环境变量中读取。DATABRICKS_WAREHOUSE_ID=WH
Widget Index (Version + Where Documented)
组件索引(版本及文档位置)
Wrong version = broken widget! This is the #1 cause of dashboard errors.
| Widget Type | Version | Documented in |
|---|---|---|
| text (markdown, no spec block) | N/A | 1-widget-specifications.md#text-headersdescriptions |
| 2 | 1-widget-specifications.md#counter-kpi |
| 2 | 1-widget-specifications.md#table |
| 3 | 1-widget-specifications.md#line--bar-charts |
| 3 | 1-widget-specifications.md#pie-chart |
| 2 | 1-widget-specifications.md#symbol-map-bubble-map |
| 3 | 2-advanced-widget-specifications.md#area-chart |
| 3 | 2-advanced-widget-specifications.md#scatter-plot--bubble-chart |
| 1 | 2-advanced-widget-specifications.md#combo-chart-bar--line |
| 1 | 2-advanced-widget-specifications.md#choropleth-map |
| 1 | 2-advanced-widget-specifications.md#forecast-line-with-ai_forecast |
| 3 | 2-advanced-widget-specifications.md#pivot |
| 3 | 2-advanced-widget-specifications.md#histogram |
| 1 | 2-advanced-widget-specifications.md#sankey |
| 3 | 2-advanced-widget-specifications.md#heatmap |
| 1 | 2-advanced-widget-specifications.md#funnel |
| 1 | 2-advanced-widget-specifications.md#box |
| 1 | 2-advanced-widget-specifications.md#waterfall |
| 2 | 3-filters.md#filter-widget-structure |
| 2 | 3-filters.md#range-slider-numeric-range-filter |
| 1 | 6-custom-visualizations.md#custom-vega-viz |
Cohort retention charts are built as awith a color-scale cell style — there is nopivotwidget type. See pivot in 2-advanced-widget-specifications.md.cohort
版本错误会导致组件失效! 这是仪表盘报错的首要原因。
| 组件类型 | 版本 | 文档位置 |
|---|---|---|
| 文本(markdown,无规范块) | N/A | 1-widget-specifications.md#text-headersdescriptions |
| 2 | 1-widget-specifications.md#counter-kpi |
| 2 | 1-widget-specifications.md#table |
| 3 | 1-widget-specifications.md#line--bar-charts |
| 3 | 1-widget-specifications.md#pie-chart |
| 2 | 1-widget-specifications.md#symbol-map-bubble-map |
| 3 | 2-advanced-widget-specifications.md#area-chart |
| 3 | 2-advanced-widget-specifications.md#scatter-plot--bubble-chart |
| 1 | 2-advanced-widget-specifications.md#combo-chart-bar--line |
| 1 | 2-advanced-widget-specifications.md#choropleth-map |
| 1 | 2-advanced-widget-specifications.md#forecast-line-with-ai_forecast |
| 3 | 2-advanced-widget-specifications.md#pivot |
| 3 | 2-advanced-widget-specifications.md#histogram |
| 1 | 2-advanced-widget-specifications.md#sankey |
| 3 | 2-advanced-widget-specifications.md#heatmap |
| 1 | 2-advanced-widget-specifications.md#funnel |
| 1 | 2-advanced-widget-specifications.md#box |
| 1 | 2-advanced-widget-specifications.md#waterfall |
| 2 | 3-filters.md#filter-widget-structure |
| 2 | 3-filters.md#range-slider-numeric-range-filter |
| 1 | 6-custom-visualizations.md#custom-vega-viz |
同期群留存图表需通过组件搭配颜色刻度单元格样式构建——没有专门的pivot组件类型。详情见2-advanced-widget-specifications.md中的pivot部分。cohort
NEW DASHBOARD CREATION WORKFLOW
新仪表盘创建流程
You MUST test ALL SQL queries via CLI BEFORE deploying. Follow the overall logic in these steps for new dashboard - Skipping validation causes broken dashboards.
部署前必须通过CLI测试所有SQL查询。 新仪表盘创建请严格遵循以下步骤逻辑——跳过验证会导致仪表盘失效。
Step 1: Get Warehouse ID if not already known
步骤1:获取计算仓库ID(若未知)
bash
undefinedbash
undefinedList warehouses to find one for SQL execution
列出计算仓库以选择用于SQL执行的仓库
databricks warehouses list
undefineddatabricks warehouses list
undefinedStep 2: Discover Table Schemas and existing data pattern
步骤2:探索表结构及现有数据模式
A good dashboard comes from knowing the data first. Spend time here — the exploration drives design decisions in Step 4 (which widgets, which filters, which groupings).
Use as the default — one call returns columns, types, sample rows, null counts, and row count. If you only know the schema, list tables first with .
discover-schemaquery "SHOW TABLES IN ..."databricks experimental aitools tools discover-schema catalog.schema.orders catalog.schema.customersSample rows alone don't tell you what to build. you can write aggregate SQL through to probe typically:
databricks experimental aitools tools query --warehouse <WH> "..."- Cardinality of candidate grouping columns → decides chart color-group vs. table (≤8 distinct values for charts, see Cardinality & Readability below).
- Top categorical values → populates filter options and chart legends meaningfully.
- Numeric distribution (min/max/avg/percentiles) → decides KPI with delta vs. trend chart (flat metrics shouldn't be line charts, see Data Variance Considerations below).
- Trend viability at daily/weekly/monthly grain → picks the right trend granularity.
- Story confirmation — run the aggregations you plan to put in the dashboard and check they're not flat, empty, or uninteresting. Fix the query or adjust the story before moving on.
Fan out independent probes in one call — pass several positional SQLs (and/or repeated ) and they run in parallel (default ):
--file--concurrency 8bash
DATABRICKS_WAREHOUSE_ID=<WH> databricks experimental aitools tools query --output json \
"SELECT COUNT(*) FROM catalog.schema.orders" \
"SELECT region, COUNT(*) FROM catalog.schema.orders GROUP BY region ORDER BY 2 DESC LIMIT 10" \
"SELECT MIN(ts), MAX(ts) FROM catalog.schema.orders"- is mandatory in multi-query mode. Returns one object per statement:
--output json; failures are per-statement ({sql, state, rows, error}), others still succeed.state: "FAILED" - ⚠️ Don't trust the exit code (a failed statement can still exit ) — gate on each object's
0.state != "SUCCEEDED"
Dashboard queries are different — inside the dashboard JSON, theclause must reference ONLY the table name, with no catalog or schema prefix:FROM
- ✅ Correct:
FROM trips- ❌ Wrong:
FROM nyctaxi.trips- ❌ Wrong:
FROM samples.nyctaxi.tripsThe catalog and schema are supplied separately via theand--dataset-catalogflags when you run--dataset-schema. These flags do NOT rewrite the query — they only fill in the catalog/schema when the query omits them. If you hardcode a catalog or schema in thedatabricks lakeview createclause, the flags are ignored for that query and the dashboard won't be portable across environments.FROM
优秀的仪表盘始于对数据的充分了解。请在此步骤投入时间——探索结果将决定步骤4中的设计决策(使用哪些组件、哪些筛选器、哪些分组方式)。
默认使用命令——一次调用即可返回列名、类型、样本行、空值计数及总行数。若仅知道schema,可先通过列出表格。
discover-schemaquery "SHOW TABLES IN ..."databricks experimental aitools tools discover-schema catalog.schema.orders catalog.schema.customers仅样本行无法指导仪表盘构建。你可以通过编写聚合SQL,重点探查以下内容:
databricks experimental aitools tools query --warehouse <WH> "..."- 候选分组列的基数 → 决定图表颜色分组还是表格展示(图表建议≤8个不同值,见下方“基数与可读性”)。
- 顶级分类值 → 为筛选选项和图表图例提供有意义的内容。
- 数值分布(最小值/最大值/平均值/百分位数) → 决定使用带差值的KPI还是趋势图(平稳指标不应使用折线图,见下方“数据方差考量”)。
- 按日/周/月粒度的趋势可行性 → 选择合适的趋势粒度。
- 业务场景验证 ——运行计划放入仪表盘的聚合查询,确认结果非平稳、非空且有业务价值。在进入下一步前修复查询或调整业务场景。
可一次执行多个独立探查——传入多个位置参数SQL(和/或重复),它们会并行运行(默认):
--file--concurrency 8bash
DATABRICKS_WAREHOUSE_ID=<WH> databricks experimental aitools tools query --output json \
"SELECT COUNT(*) FROM catalog.schema.orders" \
"SELECT region, COUNT(*) FROM catalog.schema.orders GROUP BY region ORDER BY 2 DESC LIMIT 10" \
"SELECT MIN(ts), MAX(ts) FROM catalog.schema.orders"- 多查询模式下必须使用。每个语句返回一个对象:
--output json;失败为单语句级({sql, state, rows, error}),其他语句仍可成功。state: "FAILED" - ⚠️ 不要信任退出码(单个语句失败仍可能返回)——需检查每个对象的
0。state != "SUCCEEDED"
仪表盘查询注意事项 —— 在仪表盘JSON中,子句必须仅引用表名,不能包含catalog或schema前缀:FROM
- ✅ 正确:
FROM trips- ❌ 错误:
FROM nyctaxi.trips- ❌ 错误:
FROM samples.nyctaxi.tripscatalog和schema通过执行时的databricks lakeview create和--dataset-catalog参数传入。这些参数不会重写查询——仅在查询省略时自动补充。若在--dataset-schema子句中硬编码catalog或schema,参数将对该查询失效,导致仪表盘无法跨环境移植。FROM
Step 3: Verify Data Matches Story
步骤3:验证数据匹配业务场景
The datasets.querylines in the dashboard json (see example below) must be tested to ensure
Before finalizing, run the SQL Queries you intend to add in each dataset to confirm that they run properly and that the result are valid.
This is crucial, as the widget defined in the json will use the query field output to render the visualization. The value should also make sense at a business level.
Remember that for the filter to work, the query should have the field available (so typically group by the filter field)
If values don't match expectations, ensure the query is correct, fix the data if you can, or adjust the story before creating the dashboard.
仪表盘JSON中的datasets.querylines(见下方示例)必须经过测试,确保:
最终确定前,运行计划添加到每个数据集的SQL查询,确认查询可正常执行且结果有效。
这至关重要,因为JSON中定义的组件会使用查询输出来渲染可视化内容,结果在业务层面也应具备意义。
请记住,要使筛选器生效,查询中必须包含筛选字段(通常需按筛选字段分组)。
若结果不符合预期,请确认查询正确,尽可能修复数据,或在创建仪表盘前调整业务场景。
Step 4: Plan Dashboard Structure
步骤4:规划仪表盘结构
Before writing JSON, plan your dashboard:
- You must know the expected specific JSON structure. For this, Read reference files: 1-widget-specifications.md, 3-filters.md.
Always make sure you read an entire example to understand the structure, like 4-examples.md.
-
Think: What widgets? Map each visualization to a dataset:
Widget Type Dataset Has filter field? Revenue KPI counter ds_sales ✓ date, region Trend Chart line ds_sales ✓ date, region Top Products table ds_products ✗ no date ... -
What filters? For each filter, verify ALL datasets you want filtered contain the filter field.Filters only affect datasets that have the filter field. A pre-aggregated table without dates WON'T be date-filtered.
-
Build the dashboard JSON as a local working file (intermediate step, not the deliverable).
编写JSON前,请先规划仪表盘:
- 必须了解预期的JSON结构规范。为此,请阅读参考文档:1-widget-specifications.md、3-filters.md。
请务必完整阅读示例以理解结构,例如4-examples.md。
-
思考:使用哪些组件? 将每个可视化内容映射到对应数据集:
组件 类型 数据集 是否包含筛选字段? 收入KPI counter ds_sales ✓ 日期、区域 趋势图表 line ds_sales ✓ 日期、区域 热门产品 table ds_products ✗ 无日期 ... -
使用哪些筛选器? 对每个筛选器,验证所有需要被筛选的数据集都包含该筛选字段。筛选器仅影响包含该筛选字段的数据集。无日期字段的预聚合表格不会被日期筛选。
-
构建仪表盘JSON作为本地工作文件(中间步骤,非交付物)。
Step 5: Deploy
步骤5:部署
Now deploy the JSON to the workspace. Run (below). Your task is not complete until this command succeeds and returns a dashboard ID — the JSON file alone is an intermediate working artifact.
databricks lakeview createAfter deploying, the same subcommands manage the dashboard's lifecycle (list, get, update, publish, trash).
lakeviewbash
undefined现在将JSON部署到工作区。 执行(如下)。直到该命令成功并返回仪表盘ID,任务才算完成——JSON文件仅为中间工作产物。
databricks lakeview create部署后,可使用相同的子命令管理仪表盘生命周期(列出、详情、更新、发布、删除)。
lakeviewbash
undefinedDeploy: creates the dashboard in the workspace and returns a dashboard ID.
部署:在工作区创建仪表盘并返回仪表盘ID。
Canonical form — MIX flags + --json. Each field has exactly ONE valid place:
标准格式 —— 混合参数 + --json。每个字段仅有一种有效传入方式:
--dataset-catalog / --dataset-schema : FLAG-ONLY (REQUIRED — no JSON field).
--dataset-catalog / --dataset-schema : 仅支持参数形式(必填——无对应JSON字段)。
The CLI silently warns "unknown field" and drops them if put in --json,
若放入--json中,CLI会静默提示"unknown field"并忽略,导致所有数据集查询无法解析catalog.schema。
leaving every dataset query unable to resolve its catalog.schema.
parent_path : 仅支持JSON形式(无对应参数)。若省略,仪表盘将位于
parent_path : JSON-ONLY (no flag). Without it, dashboard lands at
/Users/<you>/<display-name>。
/Users/<you>/<display-name>.
display_name / warehouse_id / serialized_dashboard : 两种形式均可;
display_name / warehouse_id / serialized_dashboard : either form works;
优先使用参数形式以提升可读性。
prefer flags for readability.
dashboard.json中的查询必须使用裸表名("FROM trips",绝不能是
Queries inside dashboard.json MUST use bare table names ("FROM trips", never
"FROM schema.trips"或"FROM catalog.schema.trips")——--dataset-catalog和
"FROM schema.trips" or "FROM catalog.schema.trips") — --dataset-catalog and
--dataset-schema仅补充缺失部分,不会重写硬编码的前缀。
--dataset-schema only fill in missing parts, they do NOT rewrite hardcoded
—
prefixes.
—
databricks lakeview create
--display-name "My Dashboard"
--warehouse-id "abc123def456"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--json '{"parent_path": "/Workspace/Users/me@co.com/dashboards"}'
--display-name "My Dashboard"
--warehouse-id "abc123def456"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--json '{"parent_path": "/Workspace/Users/me@co.com/dashboards"}'
databricks lakeview create
--display-name "My Dashboard"
--warehouse-id "abc123def456"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--json '{"parent_path": "/Workspace/Users/me@co.com/dashboards"}'
--display-name "My Dashboard"
--warehouse-id "abc123def456"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--json '{"parent_path": "/Workspace/Users/me@co.com/dashboards"}'
List all dashboards
列出所有仪表盘
databricks lakeview list
databricks lakeview list
Get dashboard details
获取仪表盘详情
databricks lakeview get DASHBOARD_ID
databricks lakeview get DASHBOARD_ID
Update a dashboard
更新仪表盘
ALWAYS re-pass --dataset-catalog / --dataset-schema: update replaces the
必须重新传入--dataset-catalog / --dataset-schema:更新会替换序列化仪表盘内容,
serialized dashboard, so omitting them nulls the defaults and breaks queries.
若省略这些参数会清空默认配置,导致查询失效。
databricks lakeview update DASHBOARD_ID
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
databricks lakeview update DASHBOARD_ID
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
--dataset-catalog "my_catalog"
--dataset-schema "my_schema"
--serialized-dashboard "$(cat dashboard.json)"
Publish a dashboard
发布仪表盘
databricks lakeview publish DASHBOARD_ID --warehouse-id WAREHOUSE_ID
databricks lakeview publish DASHBOARD_ID --warehouse-id WAREHOUSE_ID
Unpublish a dashboard
取消发布仪表盘
databricks lakeview unpublish DASHBOARD_ID
databricks lakeview unpublish DASHBOARD_ID
Delete (trash) a dashboard
删除(移入回收站)仪表盘
databricks lakeview trash DASHBOARD_ID
databricks lakeview trash DASHBOARD_ID
By default, after creation, tag dashboards to track resources created with this skill
默认情况下,创建后需为仪表盘添加标签,以追踪使用本技能创建的资源
databricks workspace-entity-tag-assignments create-tag-assignment
dashboards DASHBOARD_ID aidevkit_project --tag-value ai-dev-kit
dashboards DASHBOARD_ID aidevkit_project --tag-value ai-dev-kit
---databricks workspace-entity-tag-assignments create-tag-assignment
dashboards DASHBOARD_ID aidevkit_project --tag-value ai-dev-kit
dashboards DASHBOARD_ID aidevkit_project --tag-value ai-dev-kit
---UPDATING AN EXISTING DASHBOARD
更新现有仪表盘
To change a dashboard that already exists, build the updated JSON with the creation workflow above, then deploy it with + on the same — never re-run /import.
updatepublishDASHBOARD_IDcreate- Don't /import to update. That mints a new dashboard id + URL and breaks any link you've already shared;
createis for brand-new dashboards only.create - changes only the draft. The
updatelink viewers see stays on the last snapshot until you/publishedagain — so alwayspublishafterpublish.update
- 不要使用/导入来更新。这会生成新的仪表盘ID和URL,导致已分享的链接失效;
create仅适用于全新仪表盘。create - 仅修改草稿版本。查看者访问的
update链接会保留最后一次快照,直到再次执行/published——因此更新后务必执行publish。publish
JSON Structure (Required Skeleton)
JSON结构(必填框架)
Every dashboard's content must follow this exact structure:
serialized_dashboardImportant: ALWAYS add a space or at the end of each value as they are concatenated to create the dataset.
\nqueryLinesjson
{
"datasets": [
{
"name": "ds_x",
"displayName": "Dataset X",
"queryLines": ["SELECT col1, col2 ", "FROM my_table"]
}
],
"pages": [
{
"name": "main",
"displayName": "Main",
"pageType": "PAGE_TYPE_CANVAS",
"layout": [
{"widget": {/* INLINE widget definition */}, "position": {"x":0,"y":0,"width":2,"height":3}}
]
}
]
}Structural rules (violations cause "failed to parse serialized dashboard"):
- : Array of strings, NOT
queryLines. Elements are joined verbatim with no separator — end each line with"query": "string"or(or strip\n). A line ending in-- commentswith no newline swallows the next line.-- comment - Widgets: INLINE in , NOT a separate
layout[].widgetarray"widgets" - : Required on every page (
pageTypeorPAGE_TYPE_CANVAS)PAGE_TYPE_GLOBAL_FILTERS - Query binding: must exactly match
query.fields[].nameencodings.*.fieldName
每个仪表盘的内容必须严格遵循以下结构:
serialized_dashboard重要提示:每个值末尾必须添加空格或,因为它们会被拼接成完整的数据集查询。
queryLines\njson
{
"datasets": [
{
"name": "ds_x",
"displayName": "Dataset X",
"queryLines": ["SELECT col1, col2 ", "FROM my_table"]
}
],
"pages": [
{
"name": "main",
"displayName": "Main",
"pageType": "PAGE_TYPE_CANVAS",
"layout": [
{"widget": {/* 内联组件定义 */}, "position": {"x":0,"y":0,"width":2,"height":3}}
]
}
]
}结构规则(违反会导致"failed to parse serialized dashboard"错误):
- :字符串数组,而非
queryLines。元素会原样拼接,无分隔符——每行末尾需添加"query": "string"或(或移除\n)。若一行以-- comments结尾且无换行,会吞掉下一行内容。-- comment - 组件:必须内联在中,不能放在单独的
layout[].widget数组中"widgets" - :每个页面必填(
pageType或PAGE_TYPE_CANVAS)PAGE_TYPE_GLOBAL_FILTERS - 查询绑定:必须与
query.fields[].name完全匹配encodings.*.fieldName
Theme & Color (always set this — it makes or breaks the dashboard)
主题与颜色(必须设置——直接影响仪表盘效果)
Top-level controls colors, fonts, and widget chrome across every widget on the dashboard. Without it, the dashboard inherits the workspace default and looks generic. Set the full block on every dashboard you create — a coherent palette is the single highest-impact polish item.
uiSettings.themeMental model — 60/30/10 rule mapped to theme keys: 60% neutral = canvas/widget/border backgrounds (set to hide borders); 30% secondary = + (the content weight); 10% accent = for filters / tabs / active selections — pick something distinct from text and palette; a safe-blue around matches the hyperlink convention and works as a default.
widgetBorderColor = widgetBackgroundColorfontColorvisualizationColorsselectionColor#2272B4json
{
"datasets": [...],
"pages": [...],
"uiSettings": {
"theme": {
"canvasBackgroundColor": {"light": "#FCFCFC", "dark": "#1F272D"},
"widgetBackgroundColor": {"light": "#FFFFFF", "dark": "#11171C"},
"fontColor": {"light": "#11171C", "dark": "#E8ECF0"},
"selectionColor": {"light": "#2272B4", "dark": "#8ACAFF"},
"visualizationColors": [
"#FFA600", "#FF7054", "#DE5582", "#995495",
"#4E5185", "#1D425C", "#99DDB4"
],
"widgetHeaderAlignment": "LEFT"
}
}
}Theme keys (mechanics):
- : ordered palette every chart series and category mapping cycles through. Positions are 0-indexed:
visualizationColors= first color (position: 0above),#FFA600= seventh (position: 6). Length 5–8 is typical.#99DDB4 - Background / font / selection colors take +
lightpairs; the dashboard auto-selects based on viewer mode.dark - :
widgetHeaderAlignment(default),"LEFT", or"CENTER". Optional top-level:"RIGHT"(e.g.fontFamily,"Space Grotesk"— sans-serif keeps dense data readable; don't override per widget) and"Inter"(integer px, e.g.widgetCornerRadiusfor rounded corners;12or omit = square).0 - Per-widget color references: (0-indexed) to pin to a palette slot, or
{"themeColorType": "visualizationColors", "position": N}for an exact color outside the palette.{"hex": "#FF0000"}
Palette-design rules (this is what separates a polished dashboard from a noisy one):
- One coherent color family per dashboard, distinct across the suite. Walk across hues (e.g., amber → coral → pink → purple → navy), not one color faded toward white — a single-hue lightness ramp reads as one color and the viewer can't tell categories apart. Adjacent stops must be visually distinct: if you squint and two blur into one, push them further apart. Single-hue ramps are for quantitative widgets only (), never for
colorRamp.mode: "custom-sequential".visualizationColors - Pin semantic colors as literal hex, outside the palette. "Bad" = a warm coral (e.g. ), "good" = a calm teal/green. Use
#FF7E5Cwith a bare hex string —color.scale.mappings— not{"value": "Critical", "color": "#FF7E5C"}or{"hex": "..."}(both are silently dropped on chart widgets). Reuse the good-teal that's already in the palette so it never clashes.themeColorType: position - Color non-categorical widgets explicitly so they join the family. Maps & heatmaps: with
colorRamp.mode: "custom-sequential"from the family (if directional:{start, end}= bad color,start= good color). Forecast / multi-series: pin per-series viaendkeyed oncolor.scale.mappings(actual = solid family color, forecast = contrast/alert, threshold = muted tone). Sparkline counters: setdisplayNameto a family color, not grey.value.color - "Lighter / more pastel" tweak: nudge all stops up in lightness together; don't recolor individual ones. Re-sync the pinned semantic hex values; keep enough contrast on the alert color that it still reads as a warning.
Starter palettes (pick one and adapt — extend to 7-8 stops if needed; semantic red/green stay as literal hex per rule 2):
#094074 #3C6997 #5ADBFF #FFDD4A #FE9000
#003F5C #594E90 #BC4C96 #FF5F66 #FFA600
#4A8CC7 #F59770 #FFD84A #F0E09E #6DD980
#440154 #3B528B #21918C #5EC962 #FDE725
#4E79A7 #F28E2C #E15759 #76B7B2 #59A14F
#0072B2 #E69F00 #009E73 #CC79A7 #D55E00
#0D0887 #7E03A8 #CC4778 #F89441 #F0F921
#6929C4 #1192E8 #005D5D #9F1853 #FA4D56~4-5% of viewers have color blindness (mostly red/green). Rows 4 and 6 above (viridis, Okabe-Ito) are CB-safe by design; verify customized palettes via simulator (Adobe Color, ). Don't put red and green adjacent, and rely on lightness contrast — not hue alone — between adjacent stops.
colorbrewer2.org顶层控制仪表盘所有组件的颜色、字体和组件边框样式。若不设置,仪表盘将继承工作区默认样式,显得通用平淡。创建的每个仪表盘都必须设置完整的主题配置——协调的配色是提升仪表盘质感的关键。
uiSettings.theme设计思路——将60/30/10规则映射到主题键:60%中性色 = 画布/组件/边框背景色(设置可隐藏边框);30%次要色 = + (内容主体颜色);10%强调色 = (用于筛选器/标签页/选中状态)——选择与文本和配色区分明显的颜色;默认使用左右的安全蓝色,符合超链接惯例。
widgetBorderColor = widgetBackgroundColorfontColorvisualizationColorsselectionColor#2272B4json
{
"datasets": [...],
"pages": [...],
"uiSettings": {
"theme": {
"canvasBackgroundColor": {"light": "#FCFCFC", "dark": "#1F272D"},
"widgetBackgroundColor": {"light": "#FFFFFF", "dark": "#11171C"},
"fontColor": {"light": "#11171C", "dark": "#E8ECF0"},
"selectionColor": {"light": "#2272B4", "dark": "#8ACAFF"},
"visualizationColors": [
"#FFA600", "#FF7054", "#DE5582", "#995495",
"#4E5185", "#1D425C", "#99DDB4"
],
"widgetHeaderAlignment": "LEFT"
}
}
}主题键说明(机制):
- :有序配色板,所有图表系列和分类映射会循环使用。索引从0开始:
visualizationColors= 第一个颜色(上方的position: 0),#FFA600= 第七个颜色(position: 6)。长度通常为5–8。#99DDB4 - 背景/字体/强调色需设置+
light配对值;仪表盘会根据查看者的模式自动选择。dark - :可选值为
widgetHeaderAlignment(默认)、"LEFT"或"CENTER"。可选顶层配置:"RIGHT"(例如fontFamily、"Space Grotesk"——无衬线字体更适合展示密集数据;不要在单个组件中覆盖)和"Inter"(整数像素,例如widgetCornerRadius表示圆角;12或省略表示直角)。0 - 组件级颜色引用:(索引从0开始)可绑定到配色板中的指定位置,或使用
{"themeColorType": "visualizationColors", "position": N}设置配色板外的精确颜色。{"hex": "#FF0000"}
配色板设计规则(区分精致仪表盘与杂乱仪表盘的关键):
- 每个仪表盘使用一套协调的色系,且在整个套件中保持独特性。 选择不同色相(例如琥珀色→珊瑚色→粉色→紫色→深蓝色),而非单一颜色的浅色调——单一色相的亮度渐变会被视为同一种颜色,查看者无法区分分类。相邻颜色必须视觉上明显区分:若眯眼后两种颜色模糊成一种,需进一步拉开差距。单一色相渐变仅适用于定量组件(),绝不能用于
colorRamp.mode: "custom-sequential"。visualizationColors - 将语义颜色固定为十六进制值,放在配色板外。 “不良”=暖珊瑚色(例如),“良好”=柔和蓝绿色。在
#FF7E5C中使用裸十六进制字符串——color.scale.mappings——不要使用{"value": "Critical", "color": "#FF7E5C"}或{"hex": "..."}(这两种方式在图表组件中会被静默忽略)。复用配色板中已有的蓝绿色,避免冲突。themeColorType: position - 为非分类组件显式设置颜色,使其融入整体色系。 地图和热力图:并使用色系中的
colorRamp.mode: "custom-sequential"值(若为方向性:{start, end}=不良颜色,start=良好颜色)。预测/多系列图表:通过end按color.scale.mappings绑定系列颜色(实际值=纯色,预测值=对比/警示色,阈值=柔和色调)。迷你趋势图计数器:将displayName设置为色系中的颜色,而非灰色。value.color - “更浅/更柔和”调整技巧:将所有颜色的亮度统一调高;不要单独修改个别颜色。同步更新固定的语义十六进制值;确保警示色仍有足够对比度,保持警示作用。
入门配色板(选择一套并调整——若需要可扩展至7-8个颜色;语义红/绿按规则2保留为十六进制值):
#094074 #3C6997 #5ADBFF #FFDD4A #FE9000
#003F5C #594E90 #BC4C96 #FF5F66 #FFA600
#4A8CC7 #F59770 #FFD84A #F0E09E #6DD980
#440154 #3B528B #21918C #5EC962 #FDE725
#4E79A7 #F28E2C #E15759 #76B7B2 #59A14F
#0072B2 #E69F00 #009E73 #CC79A7 #D55E00
#0D0887 #7E03A8 #CC4778 #F89441 #F0F921
#6929C4 #1192E8 #005D5D #9F1853 #FA4D56约4-5%的查看者有色盲(主要为红绿色盲)。上方第4行和第6行(viridis、Okabe-Ito)为色盲友好配色;自定义配色板需通过模拟器验证(Adobe Color、)。不要将红色和绿色放在相邻位置,且依赖亮度对比——而非仅依赖色相——区分相邻颜色。
colorbrewer2.orgLinking a Genie Space (Optional)
链接Genie空间(可选)
To add an "Ask Genie" button to the dashboard, or to link a genie space/room with an ID, add to the JSON (alongside if you have one):
uiSettings.genieSpacethemejson
"uiSettings": {
"theme": { /* ... */ },
"genieSpace": {
"isEnabled": true,
"overrideId": "your-genie-space-id-here",
"enablementMode": "ENABLED"
}
}Genie is NOT a widget. Link viaonly. There is nouiSettings.genieSpace."widgetType": "assistant"
要为仪表盘添加“Ask Genie”按钮,或链接指定ID的Genie空间/房间,可在JSON中添加(与同级,若已设置主题):
uiSettings.genieSpacethemejson
"uiSettings": {
"theme": { /* ... */ },
"genieSpace": {
"isEnabled": true,
"overrideId": "your-genie-space-id-here",
"enablementMode": "ENABLED"
}
}Genie不是组件。仅能通过进行链接。不存在uiSettings.genieSpace类型。"widgetType": "assistant"
Design Best Practices
设计最佳实践
Apply unless user specifies otherwise:
- Global date filter: When data has temporal columns, add a date range filter. Most dashboards need time-based filtering.
- KPI time bounds: Use time-bounded metrics that enable period comparison (MoM, YoY). Unbounded "all-time" totals are less actionable.
- Value formatting: Format values based on their meaning — currency with symbol, percentages with %, large numbers compacted (K/M/B).
- Chart selection: Match cardinality to chart type. Few distinct values → bar with color grouping (or pie if you really want a snapshot); many values → table.
除非用户另有指定,否则请遵循以下规则:
- 全局日期筛选器:当数据包含时间列时,添加日期范围筛选器。大多数仪表盘需要基于时间的筛选。
- KPI时间范围:使用可进行周期对比(月环比、年同比)的时间限定指标。无限制的“全时段”总计实用性较低。
- 值格式化:根据数据含义格式化值——货币添加符号,百分比添加%,大数使用K/M/B简化显示。
- 图表选择:根据基数匹配图表类型。不同值较少→带颜色分组的柱状图(或饼图,若仅需快照);不同值较多→表格。
Reference Files
参考文档
Before generating any dashboard JSON, read 4-examples.md first. It's a complete reference dashboard exercising every construct (dataset measures +, sparkline counters, forecast-line with annotations, pivot with conditional cells, symbol-map, histogram, range-slider filter, theme). Use it to learn the JSON shape; then adapt to the user's data and demo story — keep the structure, swap the tables, metrics, palette, and narrative for the case you're building.MEASURE()
| What are you building? | Reference |
|---|---|
| Start here — full working dashboard template | 4-examples.md |
| Any widget (text, counter, table, chart) | 1-widget-specifications.md |
| Advanced charts (area, scatter/Bubble, combo (Line+Bar), Choropleth map) | 2-advanced-widget-specifications.md |
| Dashboard with filters (global or page-level) | 3-filters.md |
| A chart type that isn't built in (matrix/grid, radar, gauge, sunburst, network) — custom Vega-Lite viz | 6-custom-visualizations.md |
| Debugging a broken dashboard | 5-troubleshooting.md |
生成任何仪表盘JSON前,请先阅读4-examples.md。这是一个完整的参考仪表盘,涵盖所有结构(数据集度量 +、迷你趋势图计数器、带注释的预测折线图、带条件单元格的透视表、符号地图、直方图、范围滑块筛选器、主题)。请通过它学习JSON结构;然后根据用户的数据和演示场景调整——保留结构,替换表格、指标、配色板和叙事内容。MEASURE()
| 你要构建什么? | 参考文档 |
|---|---|
| 从这里开始 —— 完整的可运行仪表盘模板 | 4-examples.md |
| 任何组件(文本、计数器、表格、图表) | 1-widget-specifications.md |
| 高级图表(面积图、散点/气泡图、组合图(折线+柱状)、区域地图) | 2-advanced-widget-specifications.md |
| 带筛选器的仪表盘(全局或页面级) | 3-filters.md |
| 无内置组件的图表类型(矩阵/网格、雷达、仪表盘、旭日图、网络图)——自定义Vega-Lite可视化 | 6-custom-visualizations.md |
| 调试失效的仪表盘 | 5-troubleshooting.md |
Implementation Guidelines
实施准则
1) DATASET ARCHITECTURE
1) 数据集架构
- Fewer datasets is better — aim for one dataset that backs as many widgets as possible. Clicking a value on a chart (e.g., a bar, a slice) acts as a filter on that dataset, and every other widget sharing the same dataset re-renders with the click applied. Splitting widgets across many narrow datasets breaks this cross-filtering and forces users to set explicit filter widgets for what should "just work". Prefer one wide dataset per domain (orders, cases, customers); only split when a widget genuinely needs different grain, pre-aggregation, or a parameter the others can't tolerate.
- Two ways to define a dataset:
- SQL query: — full control, can include
{"name": "ds_x", "displayName": "...", "queryLines": ["SELECT ...", "FROM table"]}/WITH/JOIN/ etc.AI_FORECAST - UC asset shorthand: — no SQL needed. Works for tables, views, and metric views. You can still stack
{"name": "ds_x", "asset_name": "catalog.schema.table_or_view"}(measures + derived dimensions) on top:columnsamount_usd`)"}]}{"name": "ds_x", "asset_name": "...", "columns": [{"displayName": "Total Revenue", "expression": "SUM(\MEASURE()` pattern.— same
- SQL query:
- Exactly ONE valid SQL query per dataset when using (no multiple queries separated by
queryLines); - Queries must use bare table names only — no catalog, no schema prefix. Example: , never
FROM ordersorFROM gold.orders. The catalog and schema come from theFROM main.gold.ordersand--dataset-catalogflags at creation time. These flags only fill in missing parts — they do NOT override any catalog/schema written in the query.--dataset-schema - SELECT must include all dimensions needed by widgets and all derived columns via aliases
AS - Put ALL business logic (CASE/WHEN, COALESCE, ratios) into the dataset SELECT with explicit aliases
- Contract rule: Every widget must exactly match a dataset column or alias
fieldName - Add ORDER BY when visualization depends on data order:
- Time series: for chronological display
ORDER BY date - Rankings/Top-N: for "Top 10" charts
ORDER BY metric DESC LIMIT 10 - Categorical charts: to show largest values first
ORDER BY metric DESC
- Time series:
- 数据集越少越好——尽量使用一个数据集支撑多个组件。点击图表中的值(例如柱状图、饼图切片)会作为筛选器应用于该数据集,所有共享同一数据集的其他组件会重新渲染以应用该筛选。将组件分散到多个窄数据集会破坏这种交叉筛选功能,迫使用户为原本“应自动生效”的场景设置显式筛选器。每个业务域(订单、案例、客户)优先使用一个宽数据集;仅当组件确实需要不同粒度、预聚合或其他组件无法兼容的参数时才拆分。
- 两种数据集定义方式:
- SQL查询:——完全可控,可包含
{"name": "ds_x", "displayName": "...", "queryLines": ["SELECT ...", "FROM table"]}/WITH/JOIN/ 等语法。AI_FORECAST - UC资源简写:——无需SQL。适用于表格、视图和度量视图。仍可在其上叠加
{"name": "ds_x", "asset_name": "catalog.schema.table_or_view"}(度量 + 派生维度):columnsamount_usd`)"}]}{"name": "ds_x", "asset_name": "...", "columns": [{"displayName": "Total Revenue", "expression": "SUM(\MEASURE()`模式相同。——与
- SQL查询:
- 使用时,每个数据集仅能包含一个有效的SQL查询(不能用
queryLines分隔多个查询); - 查询必须仅使用裸表名 ——不能包含catalog或schema前缀。示例:,绝不能是
FROM orders或FROM gold.orders。catalog和schema在创建时通过FROM main.gold.orders和--dataset-catalog参数传入。这些参数仅补充缺失部分——不会覆盖查询中硬编码的catalog/schema。--dataset-schema - SELECT语句必须包含组件所需的所有维度,且所有派生列需通过设置别名
AS - 将所有业务逻辑(CASE/WHEN、COALESCE、比率)放入数据集SELECT语句,并设置明确的别名
- 契约规则:每个组件的必须与数据集列名或别名完全匹配
fieldName - 添加ORDER BY:当可视化依赖数据顺序时:
- 时间序列:以按时间顺序展示
ORDER BY date - 排名/Top-N:以展示“Top 10”图表
ORDER BY metric DESC LIMIT 10 - 分类图表:以优先展示最大值
ORDER BY metric DESC
- 时间序列:
Dataset-level measures + MEASURE()
MEASURE()数据集级度量 + MEASURE()
MEASURE()Widget expressions are usually inline aggregations (x`)"}`). But you can also declare reusable measures on the dataset itself and reference them by name — every widget that consumes the dataset can use the same metric without redefining it.
{"name": "sum(x)", "expression": "SUM(\Two ways to define measures:
-
Dashboard-level(works on any dataset — SQL query or
columns):asset_namejson{ "name": "ds_support", "queryLines": ["SELECT * FROM support_cases"], "columns": [ {"displayName": "Total Cases", "description": "Count of cases", "expression": "COUNT(`case_id`)"}, {"displayName": "Reopen Rate %", "description": "% of reopened cases", "expression": "SUM(CASE WHEN `reopened_flag` THEN 1 ELSE 0 END) * 100.0 / COUNT(`case_id`)"}, {"displayName": "Priority Level", "description": "Sorted priority label", "expression": "CASE WHEN `priority`='Critical' THEN '1-Critical' ELSE '4-Low' END"} ] } -
Metric-view source — if the dataset's(or
asset_nameclause) is a UC metric view, its YAML-defined measures are already queryable. Do not redeclare them inFROM. See databricks-metric-views.columns
Either way, widgets reference the measure by name:
json
"fields": [{"name": "measure(Total Cases)", "expression": "MEASURE(`Total Cases`)"}],
"encodings": {"value": {"fieldName": "measure(Total Cases)", "displayName": "Total Cases"}}MEASURE(\组件表达式通常为内联聚合(x`)"}`)。但你也可以在数据集上声明可复用的度量,并通过名称引用——所有使用该数据集的组件都可使用同一度量,无需重新定义。
{"name": "sum(x)", "expression": "SUM(\两种度量定义方式:
-
仪表盘级(适用于任何数据集——SQL查询或
columns):asset_namejson{ "name": "ds_support", "queryLines": ["SELECT * FROM support_cases"], "columns": [ {"displayName": "Total Cases", "description": "案例总数", "expression": "COUNT(`case_id`)"}, {"displayName": "Reopen Rate %", "description": "案例重开率", "expression": "SUM(CASE WHEN `reopened_flag` THEN 1 ELSE 0 END) * 100.0 / COUNT(`case_id`)"}, {"displayName": "Priority Level", "description": "排序后的优先级标签", "expression": "CASE WHEN `priority`='Critical' THEN '1-Critical' ELSE '4-Low' END"} ] } -
度量视图源 —— 若数据集的(或
asset_name子句)是UC度量视图,其YAML中定义的度量已可查询。不要在FROM中重新声明。详情见databricks-metric-views。columns
无论哪种方式,组件都通过名称引用度量:
json
"fields": [{"name": "measure(Total Cases)", "expression": "MEASURE(`Total Cases`)"}],
"encodings": {"value": {"fieldName": "measure(Total Cases)", "displayName": "Total Cases"}}MEASURE(\2) WIDGET FIELD EXPRESSIONS
2) 组件字段表达式
CRITICAL: Field Name Matching Rule TheinnameMUST exactly match thequery.fieldsinfieldName. If they don't match, the widget shows "no selected fields to visualize" error!encodings
Correct pattern for aggregations:
json
// In query.fields:
{"name": "sum(spend)", "expression": "SUM(`spend`)"}
// In encodings (must match!):
{"fieldName": "sum(spend)", "displayName": "Total Spend"}WRONG - names don't match:
json
// In query.fields:
{"name": "spend", "expression": "SUM(`spend`)"} // name is "spend"
// In encodings:
{"fieldName": "sum(spend)", ...} // ERROR: "sum(spend)" ≠ "spend"Allowed expressions in widget queries (you CANNOT use CAST or other SQL in expressions):
json
{"name": "(sum|avg|count|countdistinct|min|max)(col)", "expression": "(SUM|AVG|COUNT|COUNT(DISTINCT)|MIN|MAX)(`col`)"}
{"name": "(daily|weekly|monthly)(date)", "expression": "DATE_TRUNC(\"(DAY|WEEK|MONTH)\", `date`)"}
{"name": "field", "expression": "`field`"}If you need conditional logic or multi-field formulas, compute a derived column in the dataset SQL first.
重要提示:字段名匹配规则中的query.fields必须与name中的encodings完全匹配。 若不匹配,组件会显示"no selected fields to visualize"错误!fieldName
聚合的正确模式:
json
// 在query.fields中:
{"name": "sum(spend)", "expression": "SUM(`spend`)"}
// 在encodings中(必须匹配!):
{"fieldName": "sum(spend)", "displayName": "Total Spend"}错误示例 - 名称不匹配:
json
// 在query.fields中:
{"name": "spend", "expression": "SUM(`spend`)"} // 名称为"spend"
// 在encodings中:
{"fieldName": "sum(spend)", ...} // 错误:"sum(spend)" ≠ "spend"组件查询中允许的表达式(不能在表达式中使用CAST或其他SQL语法):
json
{"name": "(sum|avg|count|countdistinct|min|max)(col)", "expression": "(SUM|AVG|COUNT|COUNT(DISTINCT)|MIN|MAX)(`col`)"}
{"name": "(daily|weekly|monthly)(date)", "expression": "DATE_TRUNC(\"(DAY|WEEK|MONTH)\", `date`)"}
{"name": "field", "expression": "`field`"}若需要条件逻辑或多字段公式,请先在数据集SQL中计算派生列。
3) SPARK SQL PATTERNS
3) Spark SQL模式
- Date math: for days,
date_sub(current_date(), N)for monthsadd_months(current_date(), -N) - Date truncation:
DATE_TRUNC('DAY'|'WEEK'|'MONTH'|'QUARTER'|'YEAR', column) - AVOID syntax - use functions instead
INTERVAL
- 日期计算:用于天数,
date_sub(current_date(), N)用于月数add_months(current_date(), -N) - 日期截断:
DATE_TRUNC('DAY'|'WEEK'|'MONTH'|'QUARTER'|'YEAR', column) - 避免使用语法 - 使用函数替代
INTERVAL
4) LAYOUT (12-Column Grid, NO GAPS)
4) 布局(12列网格,无间隙)
Every page must include alongside .
"layoutVersion": "GRID_V1"pageTypejson
{
"name": "overview",
"displayName": "Overview",
"pageType": "PAGE_TYPE_CANVAS",
"layoutVersion": "GRID_V1",
"layout": [...]
}Each widget has a position:
{"x": 0, "y": 0, "width": 4, "height": 4}Pick the subdivision based on the audience. The 12-column grid divides cleanly into 3, 4, or 6 columns: a 3-column layout (each widget ) reduces cognitive load and fits an executive overview; a 4-column () is the all-rounder; a 6-column () packs the most density for technical / operations dashboards where the reader is hunting through many metrics at once.
width: 4width: 3width: 2Default rule: each row should fill width=12 exactly — no gaps. Once you're confident with the grid, you can stagger heights across columns (a tall widget on the left paired with several shorter ones on the right) so the two halves don't share row boundaries — see 4-examples.md for the pattern. Start with strict rows; relax only when the stagger reads better visually.
CORRECT: WRONG:
y=0: [w=12] y=0: [w=8]____ ← gap!
y=1: [w=4][w=4][w=4] ← fills 12 y=1: [w=2][w=2][w=2][w=2]__ ← gap!
y=4: [w=6][w=6] ← fills 12Recommended widget sizes:
| Widget Type | Width | Height | Notes |
|---|---|---|---|
| Text header | 12 | 1 | Full width; use SEPARATE widgets for title and subtitle |
| Counter/KPI | 4 | 3-4 | NEVER height=2 - too cramped! |
| Line/Bar/Area chart | 6 | 5-6 | Pair side-by-side to fill row |
| Pie chart | 6 | 5-6 | Needs space for legend |
| Full-width chart | 12 | 5-7 | For detailed time series |
| Table | 12 | 5-8 | Full width for readability |
Standard dashboard structure:
text
y=0: Title (w=12, h=1) - Dashboard title (use separate widget!)
y=1: Subtitle (w=12, h=1) - Description (use separate widget!)
y=2: KPIs (w=4 each, h=3) - 3 key metrics side-by-side
y=5: Section header (w=12, h=1) - "Trends" or similar
y=6: Charts (w=6 each, h=5) - Two charts side-by-side
y=11: Section header (w=12, h=1) - "Details"
y=12: Table (w=12, h=6) - Detailed data每个页面必须包含,与同级。
"layoutVersion": "GRID_V1"pageTypejson
{
"name": "overview",
"displayName": "Overview",
"pageType": "PAGE_TYPE_CANVAS",
"layoutVersion": "GRID_V1",
"layout": [...]
}每个组件有位置属性:
{"x": 0, "y": 0, "width": 4, "height": 4}根据受众选择布局细分方式。12列网格可清晰划分为3、4或6列:3列布局(每个组件)可降低认知负荷,适合高管概览;4列布局()为通用布局;6列布局()密度最高,适合技术/运营仪表盘,方便查看者快速浏览大量指标。
width: 4width: 3width: 2默认规则:每行宽度总和必须恰好为12——无间隙。熟悉网格布局后,可在列间交错组件高度(左侧高组件搭配右侧多个矮组件),使两侧不共享行边界——见4-examples.md中的示例模式。先从严格的行布局开始;仅当交错布局视觉效果更好时再调整。
正确示例: 错误示例:
y=0: [w=12] y=0: [w=8]____ ← 间隙!
y=1: [w=4][w=4][w=4] ← 总和12 y=1: [w=2][w=2][w=2][w=2]__ ← 间隙!
y=4: [w=6][w=6] ← 总和12推荐组件尺寸:
| 组件类型 | 宽度 | 高度 | 说明 |
|---|---|---|---|
| 文本标题 | 12 | 1 | 全屏宽度;标题和副标题使用单独的组件 |
| 计数器/KPI | 4 | 3-4 | 绝不要设置height=2 - 过于拥挤! |
| 折线/柱状/面积图 | 6 | 5-6 | 并排摆放以填满整行 |
| 饼图 | 6 | 5-6 | 需要足够空间展示图例 |
| 全屏宽度图表 | 12 | 5-7 | 用于详细时间序列 |
| 表格 | 12 | 5-8 | 全屏宽度以提升可读性 |
标准仪表盘结构:
text
y=0: 标题(w=12, h=1) - 仪表盘标题(使用单独组件!)
y=1: 副标题(w=12, h=1) - 描述(使用单独组件!)
y=2: KPIs(w=4 each, h=3) - 3个关键指标并排展示
y=5: 章节标题(w=12, h=1) - "趋势"或类似标题
y=6: 图表(w=6 each, h=5) - 两个图表并排展示
y=11: 章节标题(w=12, h=1) - "详情"
y=12: 表格(w=12, h=6) - 详细数据5) CARDINALITY & READABILITY (CRITICAL)
5) 基数与可读性(重要)
Dashboard readability depends on limiting distinct values:
| Dimension Type | Max Values | Examples |
|---|---|---|
| Chart color/groups | 3-8 | 4 regions, 5 product lines, 3 tiers |
| Filters | 4-15 | 8 countries, 5 channels |
| High cardinality | Table only | customer_id, order_id, SKU |
Before creating any chart with color/grouping:
- Check column cardinality via discover-schema or a COUNT DISTINCT query
- If >10 distinct values, aggregate to higher level OR use TOP-N + "Other" bucket
- For high-cardinality dimensions, use a table widget instead of a chart
仪表盘可读性取决于限制不同值的数量:
| 维度类型 | 最大值 | 示例 |
|---|---|---|
| 图表颜色/分组 | 3-8 | 4个区域、5个产品线、3个层级 |
| 筛选器 | 4-15 | 8个国家、5个渠道 |
| 高基数 | 仅表格 | customer_id、order_id、SKU |
创建带颜色/分组的图表前:
- 通过discover-schema或COUNT DISTINCT查询检查列基数
- 若不同值>10,聚合到更高层级或使用TOP-N + "其他"分组
- 高基数维度使用表格组件而非图表
6) QUALITY CHECKLIST
6) 质量检查清单
Before deploying, verify:
- All widget names use only alphanumeric + hyphens + underscores
- Every page has
"layoutVersion": "GRID_V1" - All rows sum to width=12 with no gaps
- KPIs use height 3-4, charts use height 5-6
- Chart dimensions have reasonable cardinality (≤8 for colors/groups)
- All widget fieldNames match dataset columns exactly
- Field in query.fields matches
namein encodings exactly (e.g., bothfieldName)"sum(spend)" - Counter datasets: use for 1-row datasets,
disaggregated: truewith aggregation for multi-rowdisaggregated: false - Percent values must be 0-1 for format (0.865 displays as "86.5%", don't forget to set the format). If data is 0-100, either divide by 100 in SQL or use
number-percentformat instead.number - SQL uses Spark syntax (date_sub, not INTERVAL)
- All SQL queries tested via CLI and return expected data
- Every dataset you want filtered MUST contain the filter field — filters only affect datasets with that column in their query
部署前,请验证:
- 所有组件名称仅使用字母数字+连字符+下划线
- 每个页面都包含
"layoutVersion": "GRID_V1" - 所有行宽度总和为12,无间隙
- KPI使用高度3-4,图表使用高度5-6
- 图表维度基数合理(颜色/分组≤8)
- 所有组件fieldName与数据集列名完全匹配
- query.fields中的字段与encodings中的
name完全匹配(例如均为fieldName)"sum(spend)" - 计数器数据集:单行数据集使用,多行聚合数据集使用
disaggregated: truedisaggregated: false - 百分比值必须为0-1以使用格式(0.865显示为"86.5%",不要忘记设置格式)。若数据为0-100,需在SQL中除以100或使用
number-percent格式。number - SQL使用Spark语法(date_sub,而非INTERVAL)
- 所有SQL查询已通过CLI测试并返回预期数据
- 所有需要被筛选的数据集必须包含筛选字段 —— 筛选器仅影响查询中包含该列的数据集
Data Variance Considerations
数据方差考量
Before creating trend charts, check if the metric has enough variance to visualize meaningfully:
sql
SELECT MIN(metric), MAX(metric), MAX(metric) - MIN(metric) as range FROM datasetIf the range is very small relative to the scale (e.g., 83-89% on a 0-100 scale), the chart will appear nearly flat. Consider:
- Showing as KPI with delta/comparison instead of chart
- Using a table to display exact values
- Adjusting the visualization to focus on the variance
创建趋势图前,请检查指标是否有足够的方差以实现有意义的可视化:
sql
SELECT MIN(metric), MAX(metric), MAX(metric) - MIN(metric) as range FROM dataset若范围相对于整体比例非常小(例如0-100刻度上的83-89%),图表会显得几乎平坦。可考虑:
- 改为展示带差值/对比的KPI而非图表
- 使用表格展示精确值
- 调整可视化方式以聚焦方差部分
Related Skills
相关技能
- databricks-apps - when the user needs a custom-code interactive app (write-back, bespoke UI, in-app chat / Genie) instead of a managed dashboard
- databricks-unity-catalog - for querying the underlying data and system tables
- databricks-pipelines - for building the data pipelines that feed dashboards
- databricks-jobs - for scheduling dashboard data refreshes
- databricks-apps - 当用户需要自定义代码交互式应用(数据回写、定制UI、应用内聊天/Genie)而非托管式仪表盘时使用
- databricks-unity-catalog - 用于查询底层数据和系统表
- databricks-pipelines - 用于构建为仪表盘提供数据的数据流
- databricks-jobs - 用于调度仪表盘数据刷新任务