@wubaoqi/guancopilot 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +17 -0
- package/README.md +146 -2
- package/assets/coreutils.wasm +0 -0
- package/assets/find.wasm +0 -0
- package/assets/guanbi.wasm +4 -0
- package/assets/guancli.wasm +0 -0
- package/assets/guanhelm.wasm +0 -0
- package/assets/jq.wasm +0 -0
- package/assets/openskills.wasm +0 -0
- package/assets/rg.wasm +0 -0
- package/assets/sed.wasm +0 -0
- package/bin/guancopilot +0 -0
- package/bin/guanvm +0 -0
- package/bin/platforms.cjs +6 -0
- package/bin/run.cjs +39 -0
- package/bin/runtime.cjs +44 -0
- package/licenses/Go-LICENSE +27 -0
- package/licenses/browser-_speed-highlight_core-LICENSE +121 -0
- package/licenses/browser-_speed-highlight_core-package.json +14 -0
- package/licenses/browser-dompurify-LICENSE +202 -0
- package/licenses/browser-dompurify-LICENSE-MPL +373 -0
- package/licenses/browser-dompurify-package.json +10 -0
- package/licenses/browser-marked-LICENSE +44 -0
- package/licenses/browser-marked-package.json +10 -0
- package/licenses/coreutils-LICENSE +18 -0
- package/licenses/findutils-LICENSE +18 -0
- package/licenses/github.com_BurntSushi_toml_v1.6.0-COPYING +21 -0
- package/licenses/github.com_dustin_go-humanize_v1.0.1-LICENSE +21 -0
- package/licenses/github.com_google_jsonschema-go_v0.4.3-LICENSE +21 -0
- package/licenses/github.com_google_uuid_v1.6.0-LICENSE +27 -0
- package/licenses/github.com_jackc_pgpassfile_v1.0.0-LICENSE +22 -0
- package/licenses/github.com_jackc_pgservicefile_v0.0.0-20240606120523-5a60cdf6a761-LICENSE +22 -0
- package/licenses/github.com_jackc_pgx_v5_v5.11.0-LICENSE +22 -0
- package/licenses/github.com_jackc_puddle_v2_v2.2.2-LICENSE +22 -0
- package/licenses/github.com_mattn_go-isatty_v0.0.20-LICENSE +9 -0
- package/licenses/github.com_modelcontextprotocol_go-sdk_v1.8.0-LICENSE +216 -0
- package/licenses/github.com_ncruces_go-strftime_v1.0.0-LICENSE +21 -0
- package/licenses/github.com_remyoudompheng_bigfft_v0.0.0-20230129092748-24d4a6f8daec-LICENSE +27 -0
- package/licenses/github.com_santhosh-tekuri_jsonschema_v6_v6.0.3-LICENSE +175 -0
- package/licenses/github.com_segmentio_asm_v1.1.3-LICENSE +21 -0
- package/licenses/github.com_segmentio_encoding_v0.5.4-LICENSE +21 -0
- package/licenses/github.com_tetratelabs_wazero_v1.12.0-LICENSE +201 -0
- package/licenses/github.com_tetratelabs_wazero_v1.12.0-NOTICE +2 -0
- package/licenses/github.com_yosida95_uritemplate_v3_v3.0.2-LICENSE +25 -0
- package/licenses/golang.org_x_image_v0.44.0-LICENSE +27 -0
- package/licenses/golang.org_x_net_v0.58.0-LICENSE +27 -0
- package/licenses/golang.org_x_oauth2_v0.36.0-LICENSE +27 -0
- package/licenses/golang.org_x_sync_v0.22.0-LICENSE +27 -0
- package/licenses/golang.org_x_sys_v0.47.0-LICENSE +27 -0
- package/licenses/golang.org_x_text_v0.41.0-LICENSE +27 -0
- package/licenses/golang.org_x_time_v0.15.0-LICENSE +27 -0
- package/licenses/guanbi-skills-LICENSE +133 -0
- package/licenses/guanbi-skills-LICENSE.README.md +28 -0
- package/licenses/guanbi-skills-LICENSE.zh-CN +82 -0
- package/licenses/jq-COPYING +176 -0
- package/licenses/modernc.org_libc_v1.73.4-LICENSE +27 -0
- package/licenses/modernc.org_libc_v1.73.4-LICENSE-3RD-PARTY.md +305 -0
- package/licenses/modernc.org_mathutil_v1.7.1-LICENSE +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-GO +27 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-LOGO +1 -0
- package/licenses/modernc.org_memory_v1.11.0-LICENSE-MMAP-GO +25 -0
- package/licenses/modernc.org_sqlite_v1.53.0-LICENSE +26 -0
- package/licenses/mvdan.cc_sh_v3_v3.13.1-LICENSE +27 -0
- package/licenses/ripgrep-COPYING +3 -0
- package/licenses/ripgrep-LICENSE-MIT +21 -0
- package/licenses/sed-LICENSE +21 -0
- package/manifest.json +972 -0
- package/package.json +30 -4
- package/plugin/guancopilot.js +193 -0
- package/skills-bundle/.guanvm-skills-bundle +0 -0
- package/skills-bundle/_recipes/dashboard/gates/page_check.js +16 -0
- package/skills-bundle/_recipes/dashboard/gates/report_check.js +4 -0
- package/skills-bundle/_recipes/dashboard/knowledge/01.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/02.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/03.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/04.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/05.md +1 -0
- package/skills-bundle/_recipes/dashboard/knowledge/06.md +1 -0
- package/skills-bundle/_recipes/dashboard/template.json +41 -0
- package/skills-bundle/_recipes/etl/gates/etl_live_check.js +10 -0
- package/skills-bundle/_recipes/etl/gates/etl_report_check.js +3 -0
- package/skills-bundle/_recipes/etl/knowledge/01.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/02.md +9 -0
- package/skills-bundle/_recipes/etl/knowledge/03.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/04.md +1 -0
- package/skills-bundle/_recipes/etl/knowledge/05.md +1 -0
- package/skills-bundle/_recipes/etl/template.json +39 -0
- package/skills-bundle/_recipes/hints.json +46 -0
- package/skills-bundle/guancli/.commandface.json +155 -0
- package/skills-bundle/guancli/SKILL.md +342 -0
- package/skills-bundle/guancli/evals/evals.json +156 -0
- package/skills-bundle/guancli/evals/fixtures/metric-candidate-empty-search.json +13 -0
- package/skills-bundle/guancli/evals/fixtures/metric-candidate-prior-request.json +13 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-columns.json +46 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-metadata.json +36 -0
- package/skills-bundle/guancli/evals/fixtures/metric-consumption-query.json +18 -0
- package/skills-bundle/guancli/references/analysis-primitives.md +95 -0
- package/skills-bundle/guancli/references/auth-and-config.md +131 -0
- package/skills-bundle/guancli/references/examples/metric-date-in.json +7 -0
- package/skills-bundle/guancli/references/examples/metric-query-rows.py +83 -0
- package/skills-bundle/guancli/references/examples/metric-query.sh +6 -0
- package/skills-bundle/guancli/references/form-chatbi.md +199 -0
- package/skills-bundle/guancli/references/gateway.md +148 -0
- package/skills-bundle/guancli/references/metric-batch-query.md +82 -0
- package/skills-bundle/guancli/references/metric-commands.md +562 -0
- package/skills-bundle/guancli/references/metric-generic-query.md +215 -0
- package/skills-bundle/guancli/references/metric-json-migration.md +18 -0
- package/skills-bundle/guancli/references/metric-query-recipes.md +358 -0
- package/skills-bundle/guancli/references/preview-and-output.md +192 -0
- package/skills-bundle/guancli/references/resource-query.md +101 -0
- package/skills-bundle/guands/SKILL.md +281 -0
- package/skills-bundle/guands/references/calc-fields-boundaries-and-pitfalls.md +160 -0
- package/skills-bundle/guands/references/command-reference.md +267 -0
- package/skills-bundle/guands/references/incremental-and-schedule.md +157 -0
- package/skills-bundle/guands/references/workflows.md +256 -0
- package/skills-bundle/guanetl/SKILL.md +391 -0
- package/skills-bundle/guanetl/evals/evals.json +41 -0
- package/skills-bundle/guanetl/references/ETL_AI_DEVELOP.md +456 -0
- package/skills-bundle/guanmetric/SKILL.md +144 -0
- package/skills-bundle/guanmetric/evals/evals.json +117 -0
- package/skills-bundle/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
- package/skills-bundle/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
- package/skills-bundle/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
- package/skills-bundle/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
- package/skills-bundle/guanmetric/references/metric-api-contract-examples.json +690 -0
- package/skills-bundle/guanmetric/references/metric-api-contract.schema.json +349 -0
- package/skills-bundle/guanmetric/references/metric-api-contracts.md +436 -0
- package/skills-bundle/guanmetric/references/metric-atomic-mutation.md +238 -0
- package/skills-bundle/guanmetric/references/metric-batch-status.md +71 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
- package/skills-bundle/guanmetric/references/metric-business-dictionary.md +76 -0
- package/skills-bundle/guanmetric/references/metric-common-fields.md +246 -0
- package/skills-bundle/guanmetric/references/metric-composite-mutation.md +165 -0
- package/skills-bundle/guanmetric/references/metric-delete-mutation.md +70 -0
- package/skills-bundle/guanmetric/references/metric-derived-mutation.md +453 -0
- package/skills-bundle/guanmetric/references/metric-excel-template.md +365 -0
- package/skills-bundle/guanmetric/references/metric-expression-rules.md +146 -0
- package/skills-bundle/guanmetric/references/metric-flow-generate-example.json +79 -0
- package/skills-bundle/guanmetric/references/metric-flow-generate.schema.json +93 -0
- package/skills-bundle/guanmetric/references/metric-flow.md +218 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
- package/skills-bundle/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
- package/skills-bundle/guanmetric/references/metric-mutation.md +155 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
- package/skills-bundle/guanmetric/references/metric-public-dimension.md +155 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
- package/skills-bundle/guanmetric/references/metric-tree-api-contracts.md +53 -0
- package/skills-bundle/guanmetric/references/metric-tree-mutation.md +500 -0
- package/skills-bundle/guanmetric/references/metric-validation-ownership.md +74 -0
- package/skills-bundle/guanvis/SKILL.md +333 -0
- package/skills-bundle/guanvis/evals/china_map/card_01_basic_map.js +13 -0
- package/skills-bundle/guanvis/evals/china_map/card_02_world_map.js +10 -0
- package/skills-bundle/guanvis/evals/china_map/card_03_point_map.js +12 -0
- package/skills-bundle/guanvis/evals/china_map/page.js +10 -0
- package/skills-bundle/guanvis/evals/china_map/schema.js +10 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/README.md +30 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/card_01_comparative_mvp.js +72 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/verify_default_roundtrip.sh +92 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/card_01_monthly.js +63 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/page.js +6 -0
- package/skills-bundle/guanvis/evals/complex_report_pro/schema.js +6 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/card_01_bar.js +13 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/card_02_pie.js +13 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/bar.js +11 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/pie.js +15 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/page.js +5 -0
- package/skills-bundle/guanvis/evals/custom_chart_echarts/schema.js +9 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/card_01_level_nodes.js +19 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.css +51 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.html +1 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.js +28 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/page.js +5 -0
- package/skills-bundle/guanvis/evals/custom_chart_sdk/schema.js +7 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/card_01_dynamic_dataset.js +20 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/card_02_dynamic_metric_chart.js +16 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/metrics.js +19 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/page.js +9 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/schema.js +7 -0
- package/skills-bundle/guanvis/evals/dynamic_fields/verify_default_roundtrip.sh +137 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/README.md +26 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_01_percentage_advcalc.js +44 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_02_scroll_percentage.js +12 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/README.md +28 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/card_01_rank_advcalc.js +59 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/verify_default_roundtrip.sh +135 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/README.md +15 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/card_01_running_total_advcalc.js +74 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/page.js +6 -0
- package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/schema.js +22 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_01_revenue_column.js +10 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_02_trend_line.js +9 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_03_kpi.js +6 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_04_pie.js +9 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/card_05_calc_field_test.js +12 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/page.js +11 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/schema.js +14 -0
- package/skills-bundle/guanvis/evals/sales_dashboard/selector_01_region.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_01_column_split.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_02_line_split.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/card_03_combo_split.js +11 -0
- package/skills-bundle/guanvis/evals/split_charts/page.js +10 -0
- package/skills-bundle/guanvis/evals/split_charts/schema.js +14 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_00_total_revenue.js +6 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_01_revenue.js +10 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_02_trend.js +9 -0
- package/skills-bundle/guanvis/evals/tab_layout/card_03_story.js +11 -0
- package/skills-bundle/guanvis/evals/tab_layout/page.js +23 -0
- package/skills-bundle/guanvis/evals/tab_layout/schema.js +11 -0
- package/skills-bundle/guanvis/evals/tab_layout/selector_01_region.js +8 -0
- package/skills-bundle/guanvis/references/api-reference.md +476 -0
- package/skills-bundle/guanvis/references/builder-reference.md +1676 -0
- package/skills-bundle/guanvis/references/chart-properties.md +2101 -0
- package/skills-bundle/guanvis/references/checkout-editing.md +53 -0
- package/skills-bundle/guanvis/references/complex-report-pro-patterns.md +398 -0
- package/skills-bundle/guanvis/references/dir-and-page-management.md +48 -0
- package/skills-bundle/guanvis/references/metric-chart-reference.md +258 -0
- package/skills-bundle/guanvis/references/publish-and-constraints.md +60 -0
- package/skills-bundle/guanvis/references/selector-reference.md +431 -0
- package/skills-bundle/guanvis/references/tableau-migration.md +73 -0
- package/skills-bundle/guanvis/references/theme.md +123 -0
- package/skills-bundle/guanvis/references/troubleshooting.md +25 -0
- package/skills-bundle/guanvis/references/validation-and-chart-patterns.md +205 -0
- package/skills-bundle/guanwf/SKILL.md +543 -0
- package/skills-bundle/guanwf/references/ETL_AI_DEVELOP.md +456 -0
- package/skills-bundle/guanwf/references/TASK_NODE_CONTRACTS.md +64 -0
- package/skills-bundle/guanwf/references/WORKFLOW_DSL.md +536 -0
- package/skills-bundle/guanwf/references/WORKFLOW_NODES.md +166 -0
- package/skills-bundle/js/SKILL.md +145 -0
|
@@ -0,0 +1,1676 @@
|
|
|
1
|
+
## Builder API 参考
|
|
2
|
+
|
|
3
|
+
新建 Card/Page 未设置非空业务描述时,payload 描述使用 `[guanvis:created]` 标记创建来源;设置非空业务描述后只保存业务描述,不追加标记。attach/checkout 已有资源不补标记,Page 只有创建标记时不会打开描述展示。
|
|
4
|
+
|
|
5
|
+
### CardBuilder
|
|
6
|
+
|
|
7
|
+
| 方法 | 说明 |
|
|
8
|
+
|------|------|
|
|
9
|
+
| `createCard(chartType, name)` | 创建 Card(chartType 必须使用 `ChartType.XXX` 枚举) |
|
|
10
|
+
| `.setId(cardId)` | **必填**。新建资源 ID 应通过 `guanvis genid` 生成;新建校验格式为 `^[a-z][a-z0-9]{23}$`。支持同 ID 重复上传覆盖更新;checkout/attach 的已有资源 ID 原样保留,不校验格式 |
|
|
11
|
+
| `.bindDataset(dsId)` | 绑定数据集(必填,dsId 必须在 defineDataset 中注册) |
|
|
12
|
+
| `.addRow(field)` | 添加行维度(X 轴) |
|
|
13
|
+
| `.addColumn(field)` | 添加列维度(按维度分组着色,如按地区/类别分色)。仅 `STACKED_COLUMN`、`GROUPED_COLUMN`、`GROUPED_BAR` 等多指标图表支持 |
|
|
14
|
+
| `.addMetric(field)` | 添加度量(Y 轴,主轴) |
|
|
15
|
+
| `.addMetricGroup(group)` | 添加数值组或嵌套数值组;仅支持 `PIVOT_TABLE` / `GROUPED_TABLE` / `LAYER_TREE_TABLE` |
|
|
16
|
+
| `.addMainViceGroup(group)` | 添加主副指标组;仅支持 `PIVOT_TABLE` |
|
|
17
|
+
| `.addMetricAdditional(field)` | 添加副轴度量(仅组合图 `*_WITH_LINE`/`*_WITH_SYMBOL`),默认绑定副 Y 轴(`plotOn: secondary`) |
|
|
18
|
+
| `.addDynamicRow(name, fields, options?)` | 添加动态维度组,候选字段写入 row |
|
|
19
|
+
| `.addDynamicColumn(name, fields, options?)` | 添加动态维度组,候选字段写入 column |
|
|
20
|
+
| `.addDynamicMetric(name, fields, options?)` | 添加动态数值组,候选字段写入 metric |
|
|
21
|
+
| `.addDynamicMetricAdditional(name, fields, options?)` | 添加动态数值组,候选字段写入副轴 |
|
|
22
|
+
| `.addColorBy(field)` | 按指标值渐变着色(接受度量字段,不是维度)|
|
|
23
|
+
| `.addTooltip(field)` / `.addFilter(field)` | 提示/筛选 |
|
|
24
|
+
| `.addSort(field)` / `.addSplit(field)` / `.addSize(field)` | 排序/拆分/大小;排序字段的排序方向用 `sortType: SortOrder.ASC/DESC` |
|
|
25
|
+
| `.addLocation(field)` / `.addTarget(field)` / `.addCompare(field)` | 位置/目标/对比 |
|
|
26
|
+
| `.setSplitSetting(config)` | 拆分图配置 |
|
|
27
|
+
| `.setColorByColors(preset_or_config)` | 渐变色配置 |
|
|
28
|
+
| `.setBarSetting(config)` | 柱形图/条形图的柱体宽度、间距和圆角配置;帕累托图还支持数据点显隐 |
|
|
29
|
+
| `.setStackSplitSetting(config)` | 分组堆积柱形图/条形图的堆积分组模式 |
|
|
30
|
+
| `.setWaterfallSetting(config)` | 瀑布图的正负值颜色和累计值配置 |
|
|
31
|
+
| `.setParetoSetting(config)` | 帕累托图的累计曲线名称和百分比精度配置 |
|
|
32
|
+
| `.setMapSetting(config)` | 地图专属属性配置 |
|
|
33
|
+
| `.setBubbleSetting(config)` | 气泡半径配置 |
|
|
34
|
+
| `.setRadarSetting(config)` | 雷达图显示配置 |
|
|
35
|
+
| `.setBoxPlotSetting(config)` | 箱线图配置 |
|
|
36
|
+
| `.setHeatMapSetting(config)` | 热力图配置 |
|
|
37
|
+
| `.setSingleValueSetting(config)` / `.setKPISetting(config)` | 指标卡、对比指标卡配置 |
|
|
38
|
+
| `.setProgressBarSetting(config)` / `.setProgressPieSetting(config)` | 进度条、进度环配置 |
|
|
39
|
+
| `.setActivityGaugeSetting(config)` / `.setLiquidGaugeSetting(config)` / `.setSolidGaugeSetting(config)` | 活动仪表盘、水波图、实心仪表盘配置 |
|
|
40
|
+
| `.setShapeColorType(type)` | 图形填充配置 |
|
|
41
|
+
| `.setLineSetting(config)` | 折线显示配置 |
|
|
42
|
+
| `.setComboSetting(config)` | 组合图的显示方式、折线或符号样式配置 |
|
|
43
|
+
| `.setCardSetting(config)` | 卡片背景、主题跟随、内边距和内容间距 |
|
|
44
|
+
| `.setShowTitle(show)` / `.setCardTitleStyle(config)` | 卡片标题显隐和样式配置 |
|
|
45
|
+
| `.setShowLegend(show, position?)` / `.setChartLegend(config)` | 图例配置 |
|
|
46
|
+
| `.setDataLabel(config)` / `.setMetricAdditionalDataLabel(config)` | 数据标签配置 |
|
|
47
|
+
| `.setTreemapDataLabel(config)` / `.setFunnelDataLabel(config)` | 矩形树图分层数据标签、漏斗图各类数据标签配置 |
|
|
48
|
+
| `.setAxis(config)` | 坐标轴配置 |
|
|
49
|
+
| `.setTooltip(config)` | 工具提示配置 |
|
|
50
|
+
| `.setTableSetting(config)` / `.setTableCellMerge(config)` | 表格行为、视觉样式与单元格配置 |
|
|
51
|
+
| `.setMiniChart(selector, config)` / `.setMiniChartSetting(selector, config)` | 设置透视表数值字段的迷你图类型、维度及字段 key 对应样式 |
|
|
52
|
+
| `.setPieSetting(config)` / `.setPieCenterText(config)` | 饼图配置 |
|
|
53
|
+
| `.setGrandTotal(config)` | 表格总计与小计配置 |
|
|
54
|
+
| `.setSummary(field, options?)` / `.setSummaryStyle(config)` | 汇总指标及样式配置 |
|
|
55
|
+
| `.setSpecialValue(config)` | 特殊值显示配置 |
|
|
56
|
+
| `.setDynamicParameterDefaultValue(param(dpId), value, options?)` | 卡片级动态参数默认值;数组按逗号连接,默认 `inheritParent: false` |
|
|
57
|
+
| `.setThemeColor(tcId, colors?, options?)` | 主题色、颜色覆盖和分类/顺序色板配置 |
|
|
58
|
+
| `.setLimit(count)` | 数据行数限制 |
|
|
59
|
+
| `.setConditionalFormat(config)` / `.setAuxiliaryLine(config)` | 条件格式和辅助线配置 |
|
|
60
|
+
| `.setMainViceStyle(config)` | 主副指标样式配置 |
|
|
61
|
+
| `.linkTo(target, config)` | 图表卡片点击联动;`target` 可传布局 index 或 cardId,详细规则见本节 Card Linkage |
|
|
62
|
+
| `registerDrillPath(parentCardIndex, drillCards, config?)` | 全局函数,声明固定路径下钻,详细规则见本节 Card Drill |
|
|
63
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
64
|
+
| `.build()` | 构建(触发验证) |
|
|
65
|
+
|
|
66
|
+
动态字段是显式能力,不会根据同一区域多个字段自动推断。只有调用 `.addDynamicRow()` / `.addDynamicColumn()` / `.addDynamicMetric()` / `.addDynamicMetricAdditional()` 时,才会生成 `zoneData.*[].dzId` 和 `meta.chartMain.dynamicZoneInfo`。
|
|
67
|
+
|
|
68
|
+
动态字段 `options`:
|
|
69
|
+
|
|
70
|
+
| 字段 | 默认值 | 说明 |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `defaultValue` | 第一个候选字段 | 推荐传候选数组里的字段对象;字符串只在唯一命中 `name` / `alias` / `fdId` / `id` 时可用 |
|
|
73
|
+
| `multiSelect` | 根据 zone `maxCount` 推断 | `maxCount=1` 时强制单选;维度切换常建议显式写 `false` |
|
|
74
|
+
| `orderType` | `DynamicFieldOrder.PRESET` | `PRESET` 按预置顺序,`CLICK` 按用户点击顺序 |
|
|
75
|
+
| `id` | 自动生成 | 可选,显式指定 `dzId`,用于稳定 diff |
|
|
76
|
+
|
|
77
|
+
`hidden` 和 `selectType` 不开放配置;资源包固定写 `hidden: false`、`selectType: "SEARCHBOX"`。动态字段不写 `stateValue.dzFieldValues`,前端加载卡片时会根据 `dynamicZoneInfo.dzMappings.defaultValue` 初始化默认选中值。
|
|
78
|
+
|
|
79
|
+
#### 数值组与主副指标组
|
|
80
|
+
|
|
81
|
+
数值组使用 `createMetricGroup(title)`,主副指标组使用 `createMainViceGroup(title)`。组 ID 是 5 位大小写字母,通过 `guanvis gen-alpha-id --length 5` 生成;不要使用 Card ID 或布局组件 ID。
|
|
82
|
+
|
|
83
|
+
同一套 group builder 同时适用于普通 `createCard()` 和指标平台 `createMetricChart()`。普通卡组内使用 `f()` / `field()`,指标平台卡组内使用 `metric()`;不要在同一张卡中混用两种字段引用。
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
var revenue = createMetricGroup("收入")
|
|
87
|
+
.setId("AbCdE")
|
|
88
|
+
.setHeaderStyle({
|
|
89
|
+
backgroundColor: "#EAF2FF",
|
|
90
|
+
color: "#245BDB",
|
|
91
|
+
fontSize: 14,
|
|
92
|
+
bold: true
|
|
93
|
+
}, { syncToFields: true })
|
|
94
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
95
|
+
.addMetric(f("利润", { aggrType: AggrType.SUM }));
|
|
96
|
+
|
|
97
|
+
var operation = createMetricGroup("经营指标")
|
|
98
|
+
.setId("FgHiJ")
|
|
99
|
+
.addGroup(revenue);
|
|
100
|
+
|
|
101
|
+
var performance = createMainViceGroup("销售表现")
|
|
102
|
+
.setId("PqRsT")
|
|
103
|
+
.setMainMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
104
|
+
.addViceMetric(f("销售额同比", { aggrType: AggrType.SUM }));
|
|
105
|
+
|
|
106
|
+
var card = createCard(ChartType.PIVOT_TABLE, "经营分析")
|
|
107
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
108
|
+
.bindDataset(DS)
|
|
109
|
+
.addRow(f("区域"))
|
|
110
|
+
.addMetricGroup(operation)
|
|
111
|
+
.addMainViceGroup(performance)
|
|
112
|
+
.setMainViceStyle({
|
|
113
|
+
main: { fontSize: 16, color: "#1F2329", bold: true },
|
|
114
|
+
vice: { fontSize: 12, color: "#646A73", bold: false },
|
|
115
|
+
viceIconStyle: "positiveGreen"
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`MetricGroupBuilder`:
|
|
120
|
+
|
|
121
|
+
| 方法 | 说明 |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `.setId(id)` | 必填,严格 5 位大小写字母,整棵组树内唯一 |
|
|
124
|
+
| `.addMetric(field)` | 添加组内度量 |
|
|
125
|
+
| `.addGroup(metricGroup)` | 添加嵌套数值组;主副指标组不能嵌套 |
|
|
126
|
+
| `.setHeaderStyle(style, options?)` | 设置分组表头;`style` 支持 `backgroundColor`、`color`、`fontSize`(12~20)、`bold`;`options.syncToFields` 默认 `true` |
|
|
127
|
+
|
|
128
|
+
`MainViceGroupBuilder`:
|
|
129
|
+
|
|
130
|
+
| 方法 | 说明 |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `.setId(id)` | 必填,严格 5 位大小写字母 |
|
|
133
|
+
| `.setMainMetric(field)` | 设置唯一的主指标,必填 |
|
|
134
|
+
| `.addViceMetric(field)` | 添加副指标,至少一个 |
|
|
135
|
+
| `.setHeaderStyle(style, options?)` | 与数值组表头配置相同 |
|
|
136
|
+
|
|
137
|
+
`setMainViceStyle()` 中 `main` 和 `vice` 分别支持 `fontSize`(1~72)、`color`、`bold`;`viceIconStyle` 支持 `positiveRed`、`positiveGreen`、`displayNull`。这些配置彼此独立,不共享公共样式对象。
|
|
138
|
+
|
|
139
|
+
组内字段只在 group builder 中声明,不要再对同一个字段调用 `card.addMetric()`。构建时字段按 DSL 声明顺序写入 metric zone,并写入叶子组或当前组的 `subZoneId`。`PIVOT_TABLE` / `GROUPED_TABLE` 有度量时自动保证 row/column 中只有一个 MPH;已有合法位置会保留,否则补到 column。`LAYER_TREE_TABLE` 不添加 MPH。
|
|
140
|
+
|
|
141
|
+
attach 已有卡片时,普通 `updateMetric()`、`moveMetric()` 不会删除 `subZoneId`;`removeMetric()` 删除最后一个组内字段后会清理空组。可使用:
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
attachCard(CARD_ID, BASE_PATH)
|
|
145
|
+
.renameMetricGroup("AbCdE", "收入与利润")
|
|
146
|
+
.setMetricGroupHeaderStyle(
|
|
147
|
+
"AbCdE",
|
|
148
|
+
{ backgroundColor: "#DCE8FF", bold: true },
|
|
149
|
+
{ syncToFields: true }
|
|
150
|
+
)
|
|
151
|
+
.setMainViceStyle({ main: { bold: true } });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
当线上 metric zone 已有 `subZones` 时,`setMetrics()` / `clearMetrics()` 会直接报错,避免静默冲平分组。确实需要取消分组时,必须显式调用 `.clearMetricGroups()`;它只解除组关系并保留 metric 字段,之后才能整体替换 metric zone。attach 中未被上述 API 修改的表头高级字段、主副指标字体字段和其它线上 meta 会原样保留。
|
|
155
|
+
|
|
156
|
+
### MetricChartBuilder(指标平台指标卡片)
|
|
157
|
+
|
|
158
|
+
用于“用指标平台已有指标创建卡片”,生成后端 `CARD_TYPE.METRIC_CHART`(`cdType=13`)。不要用普通 `createCard()` 伪造,也不要把指标 ID 当作数据集字段。
|
|
159
|
+
|
|
160
|
+
前置:先运行 `guanvis metric-init <metricId...> -d <dir>` 生成 `metrics.js`。目录模式会在 `card_*.js` 前自动加载。
|
|
161
|
+
|
|
162
|
+
| 函数/方法 | 说明 |
|
|
163
|
+
|------|------|
|
|
164
|
+
| `defineMetric(metricDef)` | 定义指标事实快照,由 `metric-init` 生成;不要手写/手改 |
|
|
165
|
+
| `metric(metricIdOrName, overrides?)` | 引用指标,传指标 ID 或指标名;用于 `.addMetric(...)` |
|
|
166
|
+
| `metricDim(metricIdOrName, dimName, overrides?)` | 引用某个指标的适用维度;维度名、`fdId` 或 `publicDimensionId` 均可匹配 |
|
|
167
|
+
| `metricDim(dimName, overrides?)` | 在所有已定义指标的适用维度中查找;多指标同名维度时优先用上面的双参数写法 |
|
|
168
|
+
| `createMetricChart(chartType, name)` | 创建指标卡片,`chartType` 使用 `ChartType.XXX`,默认可用 `PIVOT_TABLE` |
|
|
169
|
+
| `.setId(cardId)` | 设置 24 位资源 ID,用于重复导入覆盖 |
|
|
170
|
+
| `.addRow(field)` / `.addColumn(field)` | 添加指标适用维度 |
|
|
171
|
+
| `.addMetric(metric)` | 添加指标平台指标;至少一个 |
|
|
172
|
+
| `.addMetricGroup(group)` | 添加数值组或嵌套数值组;支持 `PIVOT_TABLE` / `GROUPED_TABLE` / `LAYER_TREE_TABLE` |
|
|
173
|
+
| `.addMainViceGroup(group)` | 添加主副指标组;仅支持 `PIVOT_TABLE` |
|
|
174
|
+
| `.setMainViceStyle(config)` | 设置主副指标内容样式,与普通 CardBuilder 一致 |
|
|
175
|
+
| `.addDynamicRow(name, fields, options?)` / `.addDynamicColumn(name, fields, options?)` | 添加指标平台动态维度组 |
|
|
176
|
+
| `.addDynamicMetric(name, fields, options?)` / `.addDynamicMetricAdditional(name, fields, options?)` | 添加指标平台动态指标组 |
|
|
177
|
+
| `.addFilter(field, filterType, filterValue)` / `.addSort(field)` | 添加筛选/排序;排序字段的排序方向用 `sortType: SortOrder.ASC/DESC` |
|
|
178
|
+
| `.setCardSetting()` | 卡片背景、主题跟随、内边距和内容间距 |
|
|
179
|
+
| `.setShowTitle()` / `.setCardTitleStyle()` | 卡片标题显隐和样式配置 |
|
|
180
|
+
| `.setShowLegend()` / `.setChartLegend()` | 图例配置 |
|
|
181
|
+
| `.setDataLabel()` / `.setMetricAdditionalDataLabel()` | 数据标签配置 |
|
|
182
|
+
| `.setTreemapDataLabel()` / `.setFunnelDataLabel()` | 矩形树图分层数据标签、漏斗图各类数据标签配置 |
|
|
183
|
+
| `.setAxis()` / `.setAuxiliaryLine()` / `.setTooltip()` | 坐标轴、辅助线和工具提示配置 |
|
|
184
|
+
| `.setLineSetting()` | 折线显示配置 |
|
|
185
|
+
| `.setComboSetting()` | 组合图的显示方式、折线或符号样式配置 |
|
|
186
|
+
| `.setBarSetting()` | 柱形图/条形图的柱体宽度、间距和圆角配置;帕累托图还支持数据点显隐 |
|
|
187
|
+
| `.setStackSplitSetting()` | 分组堆积柱形图/条形图的堆积分组模式 |
|
|
188
|
+
| `.setWaterfallSetting()` | 瀑布图的正负值颜色和累计值配置 |
|
|
189
|
+
| `.setParetoSetting()` | 帕累托图的累计曲线名称和百分比精度配置 |
|
|
190
|
+
| `.setMapSetting()` | 地图专属属性配置 |
|
|
191
|
+
| `.setBubbleSetting()` | 气泡半径配置 |
|
|
192
|
+
| `.setRadarSetting()` | 雷达图显示配置 |
|
|
193
|
+
| `.setBoxPlotSetting()` | 箱线图配置 |
|
|
194
|
+
| `.setHeatMapSetting()` | 热力图配置 |
|
|
195
|
+
| `.setSingleValueSetting()` / `.setKPISetting()` | 指标卡、对比指标卡配置 |
|
|
196
|
+
| `.setProgressBarSetting()` / `.setProgressPieSetting()` | 进度条、进度环配置 |
|
|
197
|
+
| `.setActivityGaugeSetting()` / `.setLiquidGaugeSetting()` / `.setSolidGaugeSetting()` | 活动仪表盘、水波图、实心仪表盘配置 |
|
|
198
|
+
| `.setPieSetting()` / `.setPieCenterText()` | 饼图配置 |
|
|
199
|
+
| `.setTableSetting()` / `.setTableCellMerge()` / `.setGrandTotal()` | 表格行为、视觉样式与汇总配置 |
|
|
200
|
+
| `.setMiniChart()` / `.setMiniChartSetting()` | 设置透视表数值字段的迷你图和样式;支持已有 MetricChart 增量编辑 |
|
|
201
|
+
| `.setSplitSetting()` / `.setShapeColorType()` | 拆分图和图形填充配置 |
|
|
202
|
+
| `.setRawSettings()` | 原始设置 |
|
|
203
|
+
| `.setProps(obj)` | 设置指标卡片 `meta.chartMain.props` |
|
|
204
|
+
| `.setConfig(obj)` / `.setRawConfig(key, value)` | 设置指标卡片 `meta.chartMain.config` |
|
|
205
|
+
| `.setSummary(metric(...), options?)` | 设置指标卡片 `meta.summary`;旧的原始对象签名继续兼容 |
|
|
206
|
+
| `.setSummaryStyle(config)` / `.setSpecialValue(config)` | 汇总样式和特殊值配置 |
|
|
207
|
+
| `.setColumns(columns)` | 设置指标卡片 `content.columns` / `dsInfo.columns` |
|
|
208
|
+
| `.addMetricAdditional()` / `.addColorBy()` / `.addSize()` / `.addTooltip()` / `.addSplit()` | 添加副轴、颜色、大小、提示、拆分区域字段 |
|
|
209
|
+
| `.build()` | 构建指标卡片 |
|
|
210
|
+
|
|
211
|
+
完整参数表、MPH 占位列、自由钻取、条件格式、迷你图、业务限定、动态字段等见 `references/metric-chart-reference.md`。
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
var card = createMetricChart(ChartType.PIVOT_TABLE, "销售指标分析")
|
|
215
|
+
.setId("card12345678901234567890")
|
|
216
|
+
.addRow(metricDim("销售额", "区域"))
|
|
217
|
+
.addMetric(metric("销售额"))
|
|
218
|
+
.addSort(metric("销售额", { sortType: SortOrder.DESC }));
|
|
219
|
+
|
|
220
|
+
registerMetricChart(card.build());
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Shape Color Type(图形填充方式)
|
|
224
|
+
|
|
225
|
+
`setShapeColorType()` 控制柱子/条形等图形本身的填充方式,和 `.addColorBy()` / `.setColorByColors()` 的“按度量值渐变着色”不同。默认不调用时保持 BI 默认纯色。
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
var card = createCard(ChartType.BASIC_COLUMN, "区域销售额")
|
|
229
|
+
.setId("card12345678901234567890")
|
|
230
|
+
.bindDataset(DS)
|
|
231
|
+
.addRow(f("区域"))
|
|
232
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
233
|
+
.setShapeColorType(ShapeColorType.TransparentGradient);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
支持的图表:`BASIC_COLUMN`、`BULLET_COLUMN`、`BASIC_BAR`、`BULLET_BAR`、`GROUPED_COLUMN`、`GROUPED_BAR`、`GROUPED_COLUMN_WITH_LINE`、`GROUPED_COLUMN_WITH_SYMBOL`。
|
|
237
|
+
|
|
238
|
+
多指标示例:
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
var card = createMetricChart(ChartType.GROUPED_COLUMN, "销售与利润")
|
|
242
|
+
.setId("metriccard12345678901234")
|
|
243
|
+
.addRow(metricDim("销售额", "月份", { granularity: Granularity.MONTH }))
|
|
244
|
+
.addMetric(metric("销售额"))
|
|
245
|
+
.addMetric(metric("利润"));
|
|
246
|
+
|
|
247
|
+
registerMetricChart(card.build());
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### 图表选型
|
|
251
|
+
|
|
252
|
+
- `SINGLE_VALUE`:只展示一个指标值,例如总销售额、订单数、门店数、平均客单价。
|
|
253
|
+
- `KPI_CARD`:展示主指标 + 对比指标,例如同比、环比、目标差异;使用时应同时配置 `.addMetric(...)` 和 `.addCompare(...)`。
|
|
254
|
+
- 没有对比指标时优先用 `SINGLE_VALUE`,即使卡片放在看板顶部 KPI 区。
|
|
255
|
+
|
|
256
|
+
#### 图表属性配置
|
|
257
|
+
|
|
258
|
+
图表属性的字段、枚举、默认值和联动规则见 `references/chart-properties.md`。编写对应 setter 前必须先读该文档。
|
|
259
|
+
|
|
260
|
+
#### Conditional Format Config(`.setConditionalFormat(config)`)
|
|
261
|
+
|
|
262
|
+
条件格式用于按值区间设置颜色。通过 `setRawSettings("conditionalFormat", config)` 设置(因为结构较复杂,建议直接用 `setRawSettings`)。
|
|
263
|
+
|
|
264
|
+
> **迁移建议**:Tableau 的 Reference Line 对应 `setAuxiliaryLine`,Reference Band 暂无直接等价,可用辅助线近似。条件格式主要用于表格类图表的单元格着色。
|
|
265
|
+
|
|
266
|
+
#### Card Linkage(图表卡片点击联动)
|
|
267
|
+
|
|
268
|
+
`CardBuilder.linkTo(target, config)` 用于让一个普通图表卡片、固定路径下钻子卡,或自定义图表的 data view(子卡片),在点击维度值后过滤同一页面内的目标图表卡片。
|
|
269
|
+
通过 `settings.asFilter` 配置联动关系,通过 `settings.interaction`配置默认交互,不是 selector 联动。自定义图表作为联动源时还需在 `renderChart` 里回传 `clickFunc`(见 Custom Chart 章节)。
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
// card_00_region_sales.js
|
|
273
|
+
var card = createCard(ChartType.GROUPED_COLUMN, "区域销售")
|
|
274
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
275
|
+
.bindDataset(DS)
|
|
276
|
+
.addRow(f("区域"))
|
|
277
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
278
|
+
.linkTo(1, {
|
|
279
|
+
fields: [
|
|
280
|
+
{ source: "区域", target: "区域" }
|
|
281
|
+
]
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
registerCard(card.build());
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`target` 为数字时,默认和页面布局中的 `card: n` 含义一致,按 `registerCard` / `registerMetricChart` / `registerTextCard` / `registerImageCard` / `registerCustomChart` / `registerDuPontChart` 等可布局资源的注册顺序解析;`registerSelector` 不参与该 index。CardBuilder 点击联动目前只支持普通图表卡片、下钻子卡和杜邦子卡作为目标,不支持 MetricChart、文本、图片和自定义图表。注意它和 `SelectorBuilder.linkTo(cardIndex)` 不同,selector 的 index 是过滤后的可联动目标序列:普通图表和 MetricChart 按注册/布局顺序进入序列,文本/图片/自定义图表等不可联动资源不占序号,杜邦子图追加在末尾。
|
|
288
|
+
|
|
289
|
+
`target` 也可以是 cardId 字符串,用于引用不在布局 index 中的固定路径下钻子卡;字符串目标也可以指向普通 layout 图表卡。
|
|
290
|
+
|
|
291
|
+
杜邦子卡片不放页面布局,但可参与联动,数字索引追加在可布局资源之后,顺序为杜邦树中的子卡片构建顺序;也可以使用 cardId 字符串目标直接引用。
|
|
292
|
+
|
|
293
|
+
构建阶段会按当前点击动作重算 `interaction`:只有联动一个动作时默认直接联动;如果已有跳转、下钻等其它点击动作,会切换为菜单选择。
|
|
294
|
+
|
|
295
|
+
支持范围:
|
|
296
|
+
|
|
297
|
+
- 普通图表卡片可以联动同页普通图表卡片,或其它下钻路径中的子卡;CardBuilder 点击联动暂不支持 MetricChart 作为 source 或 target。
|
|
298
|
+
- 下钻子卡可以联动同页普通图表卡片。
|
|
299
|
+
- 下钻路径内的父子卡、同路径子卡之间不建立联动;下钻子卡之间也不建立联动。
|
|
300
|
+
- source 卡片不能跨 page 复用,也不能已有 `settings.asFilter`。
|
|
301
|
+
- source 只能用 `.addRow(...)` / `.addColumn(...)` 添加的维度;target 使用目标卡片绑定的数据集字段。
|
|
302
|
+
- 一次 `.linkTo(...)` 声明一组 `{ source, target }`;多个目标多次调用。
|
|
303
|
+
- 日期联动会按 source 日期粒度对齐目标日期字段;source 使用月/季度/年等粒度时,用 `field(..., { granularity })` 表达该粒度。
|
|
304
|
+
- 构建阶段会校验字段、同页关系和联动环。
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
var month = field(DS, "日期", { granularity: Granularity.MONTH });
|
|
308
|
+
|
|
309
|
+
var trend = createCard(ChartType.BASIC_LINE, "月度趋势")
|
|
310
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
311
|
+
.bindDataset(DS)
|
|
312
|
+
.addRow(month)
|
|
313
|
+
.addMetric(f("订单数", { aggrType: AggrType.SUM }));
|
|
314
|
+
|
|
315
|
+
var source = createCard(ChartType.GROUPED_COLUMN, "月度区域销售")
|
|
316
|
+
.setId("cccccccccccccccccccccccc")
|
|
317
|
+
.bindDataset(DS)
|
|
318
|
+
.addRow(month)
|
|
319
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
320
|
+
.linkTo(0, {
|
|
321
|
+
fields: [
|
|
322
|
+
// target 写原始日期字段名时,会按 source 的 MONTH 粒度自动对齐
|
|
323
|
+
{ source: month, target: "日期" }
|
|
324
|
+
]
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
registerCard(trend.build()); // layout card index 0
|
|
328
|
+
registerCard(source.build()); // source linkTo(0) targets trend
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### Card Drill(固定路径下钻)
|
|
332
|
+
|
|
333
|
+
`registerDrillPath(parentCardIndex, drillCards, config?)` 用于声明固定路径下钻。父卡必须是页面 layout 中的普通图表卡;下钻子卡仍用 `createCard(...).build()` 定义,但不要 `registerCard()`,也不要放进页面布局。
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
var province = createCard(ChartType.BASIC_COLUMN, "省份销售额")
|
|
337
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
338
|
+
.bindDataset(DS)
|
|
339
|
+
.addRow(f("省份"))
|
|
340
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
341
|
+
registerCard(province.build());
|
|
342
|
+
|
|
343
|
+
var city = createCard(ChartType.BASIC_BAR, "城市销售额")
|
|
344
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
345
|
+
.bindDataset(DS)
|
|
346
|
+
.addRow(f("城市"))
|
|
347
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
348
|
+
|
|
349
|
+
var store = createCard(ChartType.PIVOT_TABLE, "门店明细")
|
|
350
|
+
.setId("cccccccccccccccccccccccc")
|
|
351
|
+
.bindDataset(DS)
|
|
352
|
+
.addRow(f("门店"))
|
|
353
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
354
|
+
|
|
355
|
+
registerDrillPath(0, [city.build(), store.build()], {
|
|
356
|
+
position: DrillPathPosition.BOTTOM
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
`position` 可传 `DrillPathPosition.TOP` 或 `DrillPathPosition.BOTTOM`,默认在底部展示。下钻链路的点击交互由 guanvis 维护,不要通过 `setRawSettings("interaction", ...)` 手写。
|
|
361
|
+
|
|
362
|
+
`drillWithPageFilters` 只对无维度也支持下钻的指标/进度类父卡生效:`SINGLE_VALUE`、`SOLID_GAUGE`、`PROGRESS_BAR`、`PROGRESS_PIE`、`KPI_CARD`、`LIQUID_GAUGE`。未显式传入时不会写入;传给其他图表类型会输出 warning 并忽略。
|
|
363
|
+
|
|
364
|
+
如果父卡已经通过 `setRawSettings` 写了 `drillPathPosition` 或支持类型上的 `drillWithPageFilters`,建议改为放到 `registerDrillPath` 里统一声明;两边同时写时值必须一致。
|
|
365
|
+
|
|
366
|
+
下钻子卡可以作为联动 source:
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
var city = createCard(ChartType.BASIC_BAR, "城市销售额")
|
|
370
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
371
|
+
.bindDataset(DS)
|
|
372
|
+
.addRow(f("城市"))
|
|
373
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }))
|
|
374
|
+
.linkTo(1, {
|
|
375
|
+
fields: [{ source: "城市", target: "城市" }]
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
普通 layout 卡要联动到下钻子卡时,使用 cardId 字符串:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
overview.linkTo("bbbbbbbbbbbbbbbbbbbbbbbb", {
|
|
383
|
+
fields: [{ source: "区域", target: "城市" }]
|
|
384
|
+
});
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
固定路径下钻支持普通图表卡作为父卡或子卡;不支持自由下钻、指标图表下钻、selector/text/image/custom chart 作为下钻父卡或子卡,也不支持下钻子卡进入页面 layout。
|
|
388
|
+
|
|
389
|
+
### PageBuilder
|
|
390
|
+
|
|
391
|
+
**布局单位**:
|
|
392
|
+
1. 默认横向使用 12 列栅格;开启精细模式后使用 60 列栅格。
|
|
393
|
+
2. 推荐通过 `.setFineMode(true)` 设置为精细模式,且必须在任何 `addRow()` / `placeCard()` / `addTab()` / `addAreaTitle()` / `addCardGroup()` / `addSelectorGroup()` 等布局方法之前调用。
|
|
394
|
+
3. `addRow()` 及其快捷方法的 `height` 省略或为 0 时使用默认行高(普通 6,精细 18)。
|
|
395
|
+
4. 区域小标题用 `createAreaTitle(...).setId(...).build()` 定义,并通过 `page.addAreaTitle(title)` 放在 Page 根布局;不要放进 tab panel。
|
|
396
|
+
5. 卡片组用 `createCardGroup(...).setId(...)` 定义,并通过 `page.addCardGroup(group)` 放在 Page 根布局。
|
|
397
|
+
6. 筛选器组用 `createSelectorGroup(...).setId(...)` 定义;放在画布中的筛选器组通过 `page.addSelectorGroup(group)` 加入 Page 根布局,放在筛选栏中的筛选器组通过 `page.addFilterSelectorGroup(group)` 加入筛选栏。未分组 selector 可通过 `page.addFilterSelector(selectorId)` 显式控制顺序;组内只能放 selector。checkout 后修改已有快捷筛选区时,优先用 `setFilterLayout()` / `clearFilterLayout()` / `addFilterLayoutItem()` / `insertFilterSelector()` / `removeFilterSelector()` / `moveFilterSelector()` 表达增量操作;筛选器或筛选器组需要在快捷筛选区和画布之间移动时,优先用动作级 `moveFilterSelectorToCanvas()` / `moveCanvasSelectorToFilter()` / `moveSelectorGroupToCanvas()` / `moveCanvasSelectorGroupToFilter()`,不要手改 base JSON。
|
|
398
|
+
7. checkout 生成的根布局组件会使用 `page.placeTab()` / `placeAreaTitle()` / `placeCardGroup()` / `placeSelectorGroup()` 保留线上 x/y/w/h;新建工程通常继续用 `addTab()` / `addAreaTitle()` / `addCardGroup()` / `addSelectorGroup()` 自动满宽布局。
|
|
399
|
+
8. 下文布局 API 中的 `cardRef` 表示:推荐使用已注册卡片或 selector 的字符串 ID;数字 index 仍可用于非 selector 卡片,按可布局资源注册顺序计数。`registerSelector()` 不参与数字 index 计数;被布局引用的 selector 不再进入同页筛选器栏。
|
|
400
|
+
|
|
401
|
+
| 方法 | 说明 |
|
|
402
|
+
|------|------|
|
|
403
|
+
| `createPage(name)` | 创建 Page |
|
|
404
|
+
| `.setId(pgId)` | 设置 Page ID |
|
|
405
|
+
| `.setParentDir(dirId)` | 设置页面所在目录 ID(**必填**:新页面没有目录会被 `publish`/`pack` 拒绝,不会落根目录;已发布页面不设置时沿用线上当前目录),目录 ID 可通过 `guancli page tree --type dir` 获取,不存在时用 `guanvis dir create` 创建 |
|
|
406
|
+
| `.addRow(specs, height?)` | **推荐**:灵活行布局,specs = `[{ card: cardRef, w: colSpan }, ...]`;不传 w 时自动等分当前栅格 |
|
|
407
|
+
| `.addFullWidthCard(cardRef, height?)` | 全宽行,等价于 `addRow([{ card }], height)` |
|
|
408
|
+
| `.addHalfWidthCards(a, b, height?)` | 左右各半 |
|
|
409
|
+
| `.addThirdWidthCards(a, b, c, height?)` | 三等分 |
|
|
410
|
+
| `.addQuarterWidthCards(a, b, c, d, height?)` | 四等分 |
|
|
411
|
+
| `.placeCard(cardRef, x, y, w, h)` | 精确放置 Card,`w/h` 必须大于 0, `x/y/w/h` 必须显式填写 |
|
|
412
|
+
| `.addSpareCard(cardId)` | 把已注册的顶层 Card 放进页面的**卡片池**:仍归属本页、可查询,但不上画布、默认不展示。checkout 回写出的 `addSpareCard(...)` 必须保留,不要删掉或改成 `placeCard` |
|
|
413
|
+
| `.addTab(tab, height?)` | 添加一个满宽 tab 容器;不传 height 时按第一个 panel 内容自动推导 |
|
|
414
|
+
| `.addAreaTitle(areaTitle, height?)` | 添加一个满宽区域小标题|
|
|
415
|
+
| `.addCardGroup(group, height?)` | 添加一个满宽卡片组;不传 height 时按标题和组内布局自动推导 |
|
|
416
|
+
| `.addSelectorGroup(group, height?)` | 在画布中添加一个满宽筛选器组;不传 height 时按展示模式、标题和组内布局自动推导 |
|
|
417
|
+
| `.placeTab(tab, x, y, w, h)` | checkout/精确布局用:注册 tab 并按显式坐标放入 Page 根布局 |
|
|
418
|
+
| `.placeAreaTitle(areaTitle, x, y, w, h)` | checkout/精确布局用:注册区域小标题并按显式坐标放入 Page 根布局 |
|
|
419
|
+
| `.placeCardGroup(group, x, y, w, h)` | checkout/精确布局用:注册卡片组并按显式坐标放入 Page 根布局 |
|
|
420
|
+
| `.placeSelectorGroup(group, x, y, w, h)` | checkout/精确布局用:注册筛选器组并按显式坐标放入 Page 根布局 |
|
|
421
|
+
| `.removeLayoutItem(cardRef)` | 从当前 Page 根布局移除已放置的 card/selector/layout component;主要给动作级移动 API 使用 |
|
|
422
|
+
| `.addFilterSelectorGroup(group)` | 在筛选栏中添加一个筛选器组 |
|
|
423
|
+
| `.addFilterSelector(selectorId)` | 显式添加一个未分组的筛选栏 selector,并控制其与筛选器组的顺序 |
|
|
424
|
+
| `.setFilterPanelLayout(config)` | 配置筛选栏布局和视觉样式;见下方“筛选栏布局与视觉” |
|
|
425
|
+
| `.setFilterLayout(items)` | 整体设置快捷筛选区的 selector / filter selectorGroup ID 列表;checkout 场景会覆盖 base `filterLayout` |
|
|
426
|
+
| `.clearFilterLayout()` | 清空快捷筛选区;常用于把已有快捷筛选器改成画布内普通筛选器卡片 |
|
|
427
|
+
| `.addFilterLayoutItem(items)` | 向快捷筛选区追加 selector / filter selectorGroup ID,已存在则跳过 |
|
|
428
|
+
| `.insertFilterLayoutItem(index, items)` / `.insertFilterSelector(index, selectorId)` | 在快捷筛选区指定位置插入 |
|
|
429
|
+
| `.removeFilterLayoutItem(id)` / `.removeFilterSelector(selectorId)` | 从快捷筛选区移除已有 selector / filter selectorGroup ID |
|
|
430
|
+
| `.moveFilterLayoutItem(id, index)` / `.moveFilterSelector(selectorId, index)` | 调整快捷筛选区已有项顺序 |
|
|
431
|
+
| `.moveFilterSelectorToCanvas(selectorId, x, y, w, h)` | 动作级:从快捷筛选区移除 selector,并按坐标放到 Page 画布,联动配置保留在 selector 卡片本身 |
|
|
432
|
+
| `.moveCanvasSelectorToFilter(selectorId, index?)` | 动作级:从 Page 根布局移除 selector,并加入快捷筛选区;传 `index` 时插入指定位置,否则追加 |
|
|
433
|
+
| `.moveSelectorGroupToCanvas(group, x, y, w, h)` / `.moveFilterSelectorGroupToCanvas(group, x, y, w, h)` | 动作级:把筛选栏 SelGroup 转换成画布 SelGroup,并从快捷筛选区移除 |
|
|
434
|
+
| `.moveCanvasSelectorGroupToFilter(group, index?)` | 动作级:把画布 SelGroup 转换成筛选栏 SelGroup,并从 Page 根布局移除;组内布局必须引用 selector ID 字符串 |
|
|
435
|
+
| `.setBackgroundColor(color)` | 页面背景色 |
|
|
436
|
+
| `.setCardMargin(margin)` | 卡片间距 |
|
|
437
|
+
| `.setFineMode(enabled)` | 开启/关闭精细模式 |
|
|
438
|
+
| `.setDashboardTitle(enabled, options?)` | 开启/关闭仪表板标题,并设置标题文字、字体、背景、图标、高度和下边距;未传 `title` 时默认使用 Page 名称 |
|
|
439
|
+
| `.setExportView(enabled, config?)` | 开启/关闭导出视图;`config.mode` 决定使用分页方向还是单页宽度 |
|
|
440
|
+
| `.setWidthAdaptive(enabled, width?)` | 开启/关闭宽度自适应;默认宽度 1280 |
|
|
441
|
+
| `.setLayoutSetting(config)` | 设置 `page.meta.layoutSetting`;布局类型使用 `PageLayoutType` |
|
|
442
|
+
| `.build()` | 构建 |
|
|
443
|
+
|
|
444
|
+
`setDashboardTitle()` 的 `options`:
|
|
445
|
+
|
|
446
|
+
| 字段 | 说明 |
|
|
447
|
+
|------|------|
|
|
448
|
+
| `title` | 标题文字;省略时使用 Page 名称 |
|
|
449
|
+
| `font` | 字体、字形和对齐设置,见下表 |
|
|
450
|
+
| `backgroundColor` | 背景色 |
|
|
451
|
+
| `backgroundImage` | 背景图片,使用通用图片对象 |
|
|
452
|
+
| `icon` | 标题图标,使用通用图片对象 |
|
|
453
|
+
| `contentHeight` | 背景高度,整数 120~400 |
|
|
454
|
+
| `paddingBottom` | 背景下边距,整数 0~100 |
|
|
455
|
+
|
|
456
|
+
`font` 字段:
|
|
457
|
+
|
|
458
|
+
| 字段 | 规则 |
|
|
459
|
+
|------|------|
|
|
460
|
+
| `fontFamily` | 非空字符串 |
|
|
461
|
+
| `fontSize` | 整数 1~72 |
|
|
462
|
+
| `color` | 颜色字符串 |
|
|
463
|
+
| `bold` | 布尔值 |
|
|
464
|
+
| `italic` | 布尔值 |
|
|
465
|
+
| `underline` | 布尔值 |
|
|
466
|
+
| `strikeThrough` | 布尔值 |
|
|
467
|
+
| `textAlign` | `left` / `center` / `right` |
|
|
468
|
+
|
|
469
|
+
通用图片对象:
|
|
470
|
+
|
|
471
|
+
| 字段 | 说明 |
|
|
472
|
+
|------|------|
|
|
473
|
+
| `enabled` | 是否显示图片 |
|
|
474
|
+
| `url` | `http(s)` 外链或已有 `/guandata-store/...` 地址 |
|
|
475
|
+
| `uploadPath` | 本地图片路径;pack/publish 时作为 Page 附件上传 |
|
|
476
|
+
| `sourceType` | `ImageSourceType.OUTSIDE_LINK` / `LOCAL_IMAGE` |
|
|
477
|
+
| `renderType` | `ImageRenderType.RATIO` / `STRETCH` / `FIT_TO_CONTENT` |
|
|
478
|
+
|
|
479
|
+
#### 页面布局类型、导出视图与宽度自适应
|
|
480
|
+
|
|
481
|
+
```javascript
|
|
482
|
+
page.setLayoutSetting({ layoutType: PageLayoutType.WATERFALL });
|
|
483
|
+
page.setLayoutSetting({ layoutType: PageLayoutType.RESPONSIVE });
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
`PageLayoutType` 支持 `WATERFALL`(瀑布流)和 `RESPONSIVE`(自适应);也可以传 `null` 恢复默认布局。
|
|
487
|
+
|
|
488
|
+
```javascript
|
|
489
|
+
// 多页导出:orientation 默认 ExportOrientation.VERTICAL
|
|
490
|
+
page.setExportView(true, {
|
|
491
|
+
mode: ExportViewMode.MULTI_PAGE,
|
|
492
|
+
orientation: ExportOrientation.HORIZONTAL
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
// 单页导出:width 默认 827,可选范围 300 ~ 3000
|
|
496
|
+
page.setExportView(true, {
|
|
497
|
+
mode: ExportViewMode.SINGLE_PAGE,
|
|
498
|
+
width: 1440
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// 宽度自适应:默认 1280,可选范围 800 ~ 4096
|
|
502
|
+
page.setWidthAdaptive(true);
|
|
503
|
+
page.setWidthAdaptive(true, 1600);
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
`setExportView()` 以 `mode` 为唯一判断依据。未传 `mode` 时默认 `ExportViewMode.MULTI_PAGE`;多页模式只读取 `orientation`,缺失或非法时使用 `ExportOrientation.VERTICAL`;单页模式只读取 `width`,缺失或非法时使用 827。传入与当前模式不匹配的 `width` / `orientation` 会被忽略并产生 warning。
|
|
507
|
+
|
|
508
|
+
`setWidthAdaptive(true, width)` 的 `width` 会先静默四舍五入,再校验是否位于 `800 ~ 4096`;缺失或非法时使用 1280。宽度自适应不能与 `PageLayoutType.RESPONSIVE` 同时开启,但可以与导出视图同时开启。
|
|
509
|
+
|
|
510
|
+
#### 页面布局与卡片视觉
|
|
511
|
+
|
|
512
|
+
页面全局视觉配置直接写入 `layoutSetting`,不使用单独的 `setGlobalStyle()`:
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
page.setLayoutSetting({
|
|
516
|
+
compact: true,
|
|
517
|
+
card: {
|
|
518
|
+
border: {
|
|
519
|
+
enabled: true,
|
|
520
|
+
width: 1,
|
|
521
|
+
color: "#D9D9D9",
|
|
522
|
+
radius: 6
|
|
523
|
+
},
|
|
524
|
+
boxShadow: {
|
|
525
|
+
enabled: true
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
page: {
|
|
529
|
+
background: {
|
|
530
|
+
image: {
|
|
531
|
+
enabled: true,
|
|
532
|
+
uploadPath: "./assets/page-background.png",
|
|
533
|
+
renderType: ImageRenderType.STRETCH
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
toolbarSettings: {
|
|
538
|
+
displayState: CardToolbarDisplayState.HIDDEN,
|
|
539
|
+
hiddenState: CardToolbarHiddenState.PARTIAL,
|
|
540
|
+
hiddenMenus: [
|
|
541
|
+
CardToolbarMenu.DATA_EXPLAIN,
|
|
542
|
+
CardToolbarMenu.INTRO
|
|
543
|
+
]
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
`setLayoutSetting()` 按自有属性递归稀疏合并,多次调用只覆盖相同叶子字段。例如先设置 `card.border.enabled`、再单独设置 `card.border.color`,两个值都会保留。未传字段不会被写成默认值:checkout Page 保留 base 中的同级配置,新建 Page 继续由主题和前端运行时补齐。
|
|
549
|
+
|
|
550
|
+
只设置 `card.border.color` 是合法的,但不会自动开启边框;`enabled` 未设置时仍使用现有值或产品默认值 `false`。边框宽度范围为 `1 ~ 10`,圆角范围为 `0 ~ 20`,均接受范围内的有限数字。`card.boxShadow.enabled` 和 `compact` 必须为布尔值。
|
|
551
|
+
|
|
552
|
+
页面背景图片位于 `page.background.image`:
|
|
553
|
+
|
|
554
|
+
- `enabled`:是否显示背景图片;设为 `false` 只关闭显示,不清除已选择的图片。
|
|
555
|
+
- `url`:外链或 BI 已上传图片地址。`http://...` / `https://...` 推断为 `ImageSourceType.OUTSIDE_LINK`;`/guandata-store/...` 是当前 BI 环境中已有的上传资源,推断为 `ImageSourceType.LOCAL_IMAGE`,直接引用而不会再次上传。跨环境迁移时优先使用 `uploadPath`,让图片随 Page 附件一起打包。
|
|
556
|
+
- `uploadPath`:相对项目目录或绝对本地路径。`preview` 会校验文件,`pack` / `publish` 会作为 Page 附件上传并改写为稳定的 `/guandata-store/images/...` 地址。支持 jpg、jpeg、png、gif,并校验扩展名与真实文件类型一致。
|
|
557
|
+
- `renderType`:`ImageRenderType.RATIO`、`STRETCH`、`FIT_TO_CONTENT`;选择新图片而未传时与当前产品一致,默认 `FIT_TO_CONTENT`。
|
|
558
|
+
|
|
559
|
+
`url` 和 `uploadPath` 同时传入时优先使用 `url` 并产生 warning。新建 Page 只公开 `ImageSourceType.OUTSIDE_LINK`(1) 和 `LOCAL_IMAGE`(2);checkout 未修改的历史来源值会原样保留。背景色仍可使用 `.setBackgroundColor()` 或设置 `layoutSetting.pageBackgroundColor`。
|
|
560
|
+
|
|
561
|
+
工具栏配置与产品页面的“卡片工具栏”设置一致:
|
|
562
|
+
|
|
563
|
+
- `displayState`:`CardToolbarDisplayState.DEFAULT` / `HIDDEN`。
|
|
564
|
+
- `hiddenState`:隐藏工具栏时使用 `CardToolbarHiddenState.ALL` / `PARTIAL`;默认展示的新页面可以省略,checkout 从隐藏切回默认时必须显式传 `null`。
|
|
565
|
+
- `hiddenMenus`:使用 `CardToolbarMenu` 中的公开菜单枚举;`ALL` 模式必须传空数组或省略。
|
|
566
|
+
|
|
567
|
+
新建 Page 设置 `hiddenState` 或 `hiddenMenus` 时必须同时设置 `displayState`,设置 `displayState: HIDDEN` 时必须给出 `hiddenState`,避免产生前端无法生效的半完整组合。checkout 改变工具栏状态时按产品的整组更新语义填写关联字段:切回默认使用 `{ displayState: DEFAULT, hiddenState: null, hiddenMenus: [] }`,切换为全部隐藏时同时传 `hiddenMenus: []`。构建会在 base 深度合并后校验最终组合;未修改的历史配置和仅调整菜单的历史值仍可无损回写。
|
|
568
|
+
|
|
569
|
+
#### 筛选栏布局与视觉
|
|
570
|
+
|
|
571
|
+
```javascript
|
|
572
|
+
page.setFilterPanelLayout({
|
|
573
|
+
type: FilterPanelLayoutType.GRID,
|
|
574
|
+
spacing: FilterPanelSpacing.MIDDLE,
|
|
575
|
+
padding: { top: 8, right: 12, bottom: 8, left: 12 },
|
|
576
|
+
labelPosition: "top",
|
|
577
|
+
labelFont: { fontSize: 12, color: "#333333", bold: true },
|
|
578
|
+
controlStyle: FilterPanelControlStyle.OUTLINED,
|
|
579
|
+
controlFont: { fontSize: 12, color: "#222222", bold: false },
|
|
580
|
+
actionOrder: "right",
|
|
581
|
+
buttonColor: "#2E88FF",
|
|
582
|
+
buttonFont: { fontSize: 12, bold: true },
|
|
583
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
584
|
+
backgroundImageEnabled: true,
|
|
585
|
+
backgroundImage: {
|
|
586
|
+
url: "https://example.com/filter-panel.png",
|
|
587
|
+
sourceType: ImageSourceType.OUTSIDE_LINK,
|
|
588
|
+
renderType: ImageRenderType.FIT_TO_CONTENT
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
所有字段均可选,多次调用按字段增量合并;`labelFont`、`controlFont` 和 `buttonFont` 也只覆盖显式传入的字体子字段。省略字段表示保留现值,显式传 `null` 表示删除该覆盖值并恢复产品/主题默认;字体对象的单个子字段也可传 `null`。例如 `{ backgroundColor: null, controlFont: { color: null } }` 会清除背景色和控件文字颜色覆盖。
|
|
594
|
+
|
|
595
|
+
补充规则:
|
|
596
|
+
|
|
597
|
+
| 对象/字段 | 规则 |
|
|
598
|
+
|-----------|------|
|
|
599
|
+
| `padding` | 支持 `top`、`right`、`bottom`、`left`,值为整数 0~32;非法值产生 warning 并丢弃 |
|
|
600
|
+
| `labelFont` | 支持 `fontFamily`、`fontSize`、`color`、`bold`、`italic`、`underline`;字号为整数 9~20 |
|
|
601
|
+
| `controlFont` | 支持 `fontFamily`、`fontSize`、`color`、`bold`、`italic` |
|
|
602
|
+
| `buttonFont` | 支持 `fontFamily`、`fontSize`、`bold`、`italic`、`underline`;文字颜色由产品固定 |
|
|
603
|
+
| `buttonColor` | 按钮强调色 |
|
|
604
|
+
|
|
605
|
+
`backgroundImage`:
|
|
606
|
+
|
|
607
|
+
| 项目 | 规则 |
|
|
608
|
+
|------|------|
|
|
609
|
+
| 完整对象 | 新建 Page 最终必须包含 `url`、`sourceType`、`renderType` |
|
|
610
|
+
| 稀疏更新 | 完整设置后可只修改单个字段;checkout 与 base 合并后的对象必须完整 |
|
|
611
|
+
| `url` | 非空字符串;本地图片使用已有 BI 资源路径 |
|
|
612
|
+
| `sourceType` | `ImageSourceType.OUTSIDE_LINK` / `LOCAL_IMAGE` |
|
|
613
|
+
| `renderType` | `ImageRenderType.RATIO` / `STRETCH` / `FIT_TO_CONTENT` |
|
|
614
|
+
| 关闭显示 | 设置 `backgroundImageEnabled: false` |
|
|
615
|
+
| 恢复默认 | 同时将 `backgroundImageEnabled`、`backgroundImage` 设为 `null` |
|
|
616
|
+
|
|
617
|
+
| 字段 | 可选值 | 写入 `page.meta.filterLayoutSettings` |
|
|
618
|
+
|------|--------|----------------------------------------|
|
|
619
|
+
| `type` | `FilterPanelLayoutType.GRID` / `PARAGRAPH` | `layoutType` |
|
|
620
|
+
| `spacing` | `FilterPanelSpacing.SMALL` / `MIDDLE` / `LARGE` | `selPadding` |
|
|
621
|
+
| `padding` | `{ top?, right?, bottom?, left? }` | `paddingValue` |
|
|
622
|
+
| `labelPosition` | `"top"` / `"left"` | `selName.position` |
|
|
623
|
+
| `labelFont` | 字体对象 | `selName.font` |
|
|
624
|
+
| `controlStyle` | `FilterPanelControlStyle.BORDERLESS` / `OUTLINED` / `FILLED` | `selStyle.variant` |
|
|
625
|
+
| `controlFont` | 字体对象 | `selStyle.font` |
|
|
626
|
+
| `actionOrder` | `"left"` / `"right"` | `opStyle.order` |
|
|
627
|
+
| `buttonColor` | 非空颜色字符串 | `button` |
|
|
628
|
+
| `buttonFont` | 字体对象 | `opStyle.font` |
|
|
629
|
+
| `backgroundColor` | 非空颜色字符串 | `background` |
|
|
630
|
+
| `backgroundImageEnabled` | `true` / `false` | `backgroundImageEnabled` |
|
|
631
|
+
| `backgroundImage` | `{ url, sourceType, renderType }` | `backgroundImage` |
|
|
632
|
+
|
|
633
|
+
该方法只覆盖表中字段。checkout 会把这些布局和视觉字段重新生成到 `page.js`,同时在 `.guanvis/base/page.json` 保留完整线上配置;pack/publish 在基线上稀疏合并显式补丁,未知历史字段不会丢失。新页面未显式设置的视觉字段仍由主题补齐。
|
|
634
|
+
|
|
635
|
+
### AreaTitleBuilder
|
|
636
|
+
|
|
637
|
+
`areaTitle` 是 Page 根布局里的区域小标题,不是 Card,不绑定数据集,也不会生成 page-card relation。ID 必须以 `areaTitle_` 开头,建议用 `guanvis gen-layout-id areaTitle` 生成。
|
|
638
|
+
|
|
639
|
+
| 方法 | 说明 |
|
|
640
|
+
|------|------|
|
|
641
|
+
| `createAreaTitle(name)` | 创建区域小标题,`name` 即为标题的内容,会被写入该组件的 style 中,必须要传 name |
|
|
642
|
+
| `.setId(areaTitleId)` | **必填**。设置区域小标题 ID,必须以 `areaTitle_` 开头 |
|
|
643
|
+
| `.setRawStyle(style)` | checkout 保留线上 style 用;新建工程优先用下列语义化方法 |
|
|
644
|
+
| `.setShowTitle(boolean)` | 是否显示标题 |
|
|
645
|
+
| `.setFontSize(number)` | 字号 |
|
|
646
|
+
| `.setColor(color)` | 字体颜色 |
|
|
647
|
+
| `.setBold(boolean)` | 是否加粗 |
|
|
648
|
+
| `.setTextAlign(alignment)` | 对齐方式, 支持 `left`, `center`, `right` |
|
|
649
|
+
| `.setBackgroundColor(color)` | 背景色 |
|
|
650
|
+
| `.setShowBgImage(boolean)` | 是否显示背景图 |
|
|
651
|
+
| `.setShowIcon(boolean)` | 是否显示图标 |
|
|
652
|
+
| `.setFontStyle(style)` | 稀疏设置字体、字形和对齐方式 |
|
|
653
|
+
| `.setBackgroundImage(image)` | 设置背景图片;支持外链、已有 Store 地址或本地 `uploadPath` |
|
|
654
|
+
| `.setIcon(image)` | 设置图标图片;图片规则同上 |
|
|
655
|
+
| `.build()` | 构建 areaTitle result |
|
|
656
|
+
|
|
657
|
+
```javascript
|
|
658
|
+
var salesTitle = createAreaTitle("销售概览")
|
|
659
|
+
.setId("areaTitle_AbCdEf")
|
|
660
|
+
.setFontSize(20)
|
|
661
|
+
.setBold(true)
|
|
662
|
+
.setTextAlign("left")
|
|
663
|
+
.build();
|
|
664
|
+
|
|
665
|
+
var page = createPage("销售仪表板")
|
|
666
|
+
.setId("p184352b7a76776db5f534df")
|
|
667
|
+
.addAreaTitle(salesTitle)
|
|
668
|
+
.addFullWidthCard(0, 6);
|
|
669
|
+
|
|
670
|
+
registerPage(page.build());
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### CardGroupBuilder
|
|
674
|
+
|
|
675
|
+
`cardGroup` 是一个布局容器,不是 Card,不绑定数据集,也不会生成独立 page-card relation。ID 必须以 `cardGroup_` 开头,建议用 `guanvis gen-layout-id cardGroup` 生成。卡片组目前只能放入根布局,暂不支持放入 tab panel、另一个卡片组或嵌套区域小标题。
|
|
676
|
+
|
|
677
|
+
| 方法 | 说明 |
|
|
678
|
+
|------|------|
|
|
679
|
+
| `createCardGroup(name)` | 创建卡片组,`name` 写入分组标题 |
|
|
680
|
+
| `.setId(cardGroupId)` | **必填**。设置卡片组 ID,必须以 `cardGroup_` 开头 |
|
|
681
|
+
| `.setRawStyle(style)` | checkout 保留线上 style 用;新建工程优先用 `.setShowTitle()` 等语义化方法 |
|
|
682
|
+
| `.setShowTitle(boolean)` | 是否显示标题,默认 `true` |
|
|
683
|
+
| `.setTitleStyle(config)` | 设置标题字体、背景/图标及上下边框 |
|
|
684
|
+
| `.setBackgroundStyle({ color?, image? })` | 设置卡片组自身背景色和背景图 |
|
|
685
|
+
| `.setCardSpacing(type, value?)` | 设置组内卡片间距;type 使用 `LayoutMarginType.NONE/SPACE/DIVIDE` |
|
|
686
|
+
| `.setDividingLineStyle({ color? })` | 设置分割线颜色;分割线模式由 `.setCardSpacing(LayoutMarginType.DIVIDE)` 开启 |
|
|
687
|
+
| `.addRow(specs, height?)` | 在组内按行放置卡片,写法同 `PageBuilder.addRow()` |
|
|
688
|
+
| `.addFullWidthCard(cardRef, height?)` | 在组内放一张满宽卡片 |
|
|
689
|
+
| `.placeCard(cardRef, x, y, w, h)` | 在组内精确放置卡片 |
|
|
690
|
+
|
|
691
|
+
卡片组内布局方法同 `PageBuilder`,使用 `cardRef`。
|
|
692
|
+
|
|
693
|
+
`setTitleStyle()`:
|
|
694
|
+
|
|
695
|
+
| 字段 | 说明 |
|
|
696
|
+
|------|------|
|
|
697
|
+
| `enabled` | 是否显示标题 |
|
|
698
|
+
| `font` | 标题字体、字形和对齐 |
|
|
699
|
+
| `backgroundColor` | 标题背景色 |
|
|
700
|
+
| `backgroundImage` | 标题背景图 |
|
|
701
|
+
| `icon` | 标题图标 |
|
|
702
|
+
| `topStrip` | 顶部边框设置 |
|
|
703
|
+
| `bottomStrip` | 底部边框设置 |
|
|
704
|
+
|
|
705
|
+
`topStrip`、`bottomStrip`:
|
|
706
|
+
|
|
707
|
+
| 字段 | 说明 |
|
|
708
|
+
|------|------|
|
|
709
|
+
| `enabled` | 是否显示边框 |
|
|
710
|
+
| `width` | 2 / 4 / 6 / 8 |
|
|
711
|
+
| `backgroundColor` | 边框颜色 |
|
|
712
|
+
|
|
713
|
+
`setDividingLineStyle()`:
|
|
714
|
+
|
|
715
|
+
| 字段 | 说明 |
|
|
716
|
+
|------|------|
|
|
717
|
+
| `color` | 分割线颜色 |
|
|
718
|
+
|
|
719
|
+
```javascript
|
|
720
|
+
var salesGroup = createCardGroup("销售概览")
|
|
721
|
+
.setId("cardGroup_AbCdEf")
|
|
722
|
+
.addRow([{ card: 0 }, { card: 1 }])
|
|
723
|
+
.addFullWidthCard(2);
|
|
724
|
+
|
|
725
|
+
var page = createPage("销售仪表板")
|
|
726
|
+
.setId("p184352b7a76776db5f534df")
|
|
727
|
+
.addCardGroup(salesGroup);
|
|
728
|
+
|
|
729
|
+
registerPage(page.build());
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### SelectorGroupBuilder
|
|
733
|
+
|
|
734
|
+
`SelGroup` 是原生筛选器组,不是 Card,不绑定数据集,也不会生成独立 page-card relation。ID 必须以 `selGroup_` 开头,使用 `guanvis gen-layout-id selGroup` 生成。位于画布的 SelGroup 只能放入 Page 根布局;位于筛选栏的 SelGroup 只能放入 `filterLayout`;组内只能包含已注册 selector。
|
|
735
|
+
|
|
736
|
+
默认值:`displayMode = "tiled"`、`showTitle = false`、`titleStyle.fontSize = 14`、`titleStyle.bold = true`。筛选栏中的组名始终来自 `name`,不受 `showTitle` 控制。
|
|
737
|
+
|
|
738
|
+
| 方法 | 说明 |
|
|
739
|
+
|------|------|
|
|
740
|
+
| `createSelectorGroup(name)` | 创建筛选器组,`name` 必填 |
|
|
741
|
+
| `.setId(selGroupId)` | **必填**。设置筛选器组 ID,必须以 `selGroup_` 开头 |
|
|
742
|
+
| `.setRawStyle(style)` | checkout 保留线上 style 用;新建工程优先用 `.setDisplayMode()` / `.setShowTitle()` / `.setFpWidth()` |
|
|
743
|
+
| `.setDisplayMode(mode)` | 展示模式:`SelectorGroupDisplayMode.TILED`(默认)或 `SelectorGroupDisplayMode.DROPDOWN` |
|
|
744
|
+
| `.setShowTitle(boolean)` | 是否显示画布中筛选器组的标题;默认 `false` |
|
|
745
|
+
| `.setFpWidth(width)` | 筛选栏非栅格模式宽度,仅用于筛选栏中的筛选器组 |
|
|
746
|
+
| `.setFpGrid(span)` | 筛选栏栅格模式宽度,仅用于筛选栏中的筛选器组 |
|
|
747
|
+
| `.addSelector(selectorId)` / `.addSelectors(selectorIds)` | 添加要放在筛选栏中的 selector;使用后只能传给 `page.addFilterSelectorGroup()` |
|
|
748
|
+
| `.addRow(specs, height?)` | 添加要放在画布中的 selector 布局,写法同 `PageBuilder.addRow()`;height 省略或为 0 时 selector 高度默认普通 1、精细 3;使用后只能传给 `page.addSelectorGroup()` |
|
|
749
|
+
| `.addFullWidthCard(cardRef, height?)` | 在画布中的筛选器组内放一个满宽 selector |
|
|
750
|
+
| `.placeCard(cardRef, x, y, w, h)` | 精确放置画布中筛选器组内的 selector |
|
|
751
|
+
|
|
752
|
+
画布中的下拉筛选器组:
|
|
753
|
+
|
|
754
|
+
```javascript
|
|
755
|
+
var advanced = createSelectorGroup("高级筛选")
|
|
756
|
+
.setId("selGroup_AbCdEf")
|
|
757
|
+
.setDisplayMode(SelectorGroupDisplayMode.DROPDOWN)
|
|
758
|
+
.setShowTitle(true)
|
|
759
|
+
.addRow([
|
|
760
|
+
{ card: "ssssssssssssssssssssssss", w: 6 },
|
|
761
|
+
{ card: "tttttttttttttttttttttttt", w: 6 }
|
|
762
|
+
]);
|
|
763
|
+
|
|
764
|
+
var page = createPage("销售仪表板")
|
|
765
|
+
.setId("p184352b7a76776db5f534df")
|
|
766
|
+
.addSelectorGroup(advanced);
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
筛选栏中的筛选器组与未分组 selector 混排:
|
|
770
|
+
|
|
771
|
+
```javascript
|
|
772
|
+
var globalFilters = createSelectorGroup("全局筛选")
|
|
773
|
+
.setId("selGroup_GhIjKl")
|
|
774
|
+
.addSelector("ssssssssssssssssssssssss")
|
|
775
|
+
.addSelector("tttttttttttttttttttttttt");
|
|
776
|
+
|
|
777
|
+
var page = createPage("销售仪表板")
|
|
778
|
+
.setId("p184352b7a76776db5f534df")
|
|
779
|
+
.addFilterSelectorGroup(globalFilters)
|
|
780
|
+
.addFilterSelector("uuuuuuuuuuuuuuuuuuuuuuuu");
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
#### 页面密度尺寸建议
|
|
784
|
+
|
|
785
|
+
以下尺寸建议以非精细模式的 12 列布局单位为基准,用于生成页面时选择页面卡片间距和常见卡片高度。精细模式目前只定义横向 60 列栅格与显式 `x/y/w/h` 放置规则,暂不提供独立的密度尺寸换算规则。
|
|
786
|
+
|
|
787
|
+
密度选择建议:默认使用 `comfortable`;当页面用于汇报展示、希望更强留白感,或卡片数量较少时,使用 `relaxed`。同一页面建议只选择一个主密度基准。
|
|
788
|
+
|
|
789
|
+
| 项目 | `comfortable` | `relaxed` |
|
|
790
|
+
|------|------|------|
|
|
791
|
+
| 页面卡片间距 | `20` | `30` |
|
|
792
|
+
| 单指标卡高度(`SINGLE_VALUE`) | `2` | `3` |
|
|
793
|
+
| 对比指标卡高度(`KPI_CARD`) | `2` | `3` |
|
|
794
|
+
| 图表高度 | `6` | `7` |
|
|
795
|
+
| 表格高度 | `5` | `6` |
|
|
796
|
+
|
|
797
|
+
同一行卡片默认使用同一高度,避免页面节奏不齐。若需要压缩页面,可在不影响可读性的前提下降低局部卡片高度。
|
|
798
|
+
|
|
799
|
+
注意:这里的高度建议是非精细模式下的页面生成建议,不覆盖 `addRow()` 在精细模式下省略高度时使用默认行高 `18` 的 API 行为。
|
|
800
|
+
|
|
801
|
+
### Tab Builder
|
|
802
|
+
|
|
803
|
+
tab 用于把页面中的卡片分到多个 panel。适合同一主题下多组互斥查看的分析内容;若卡片较少或需要同时对照,优先直接平铺。关键总览指标通常放在 tab 外,tab 内按实际分析主题组织 panel。支持通过 `page.addTab(tab)` 添加满宽 tab,暂不支持半宽 tab 或 tab 嵌套。 示例可以参考 `evals/tab_layout/`。
|
|
804
|
+
|
|
805
|
+
| 方法 | 说明 |
|
|
806
|
+
|------|------|
|
|
807
|
+
| `createTab(name)` | 创建 tab 容器;`name` 用于脚本可读性,页面上显示的是各 panel 的 name |
|
|
808
|
+
| `.setId(tabId)` | **必填**。设置 tab ID,必须以 `tab_` 开头且同一页面内唯一。建议用 `guanvis gen-layout-id tab` 生成 |
|
|
809
|
+
| `.setRawStyle(style)` | checkout 保留线上 tab style 用;新建工程优先用下列语义化方法 |
|
|
810
|
+
| `.setRawPanelStyle(panelStyle)` | checkout 保留线上 panelStyle 用 |
|
|
811
|
+
| `.setRawLayoutItemMap(layoutItemMap)` | checkout 保留线上 tab 内 layoutItemMap 用 |
|
|
812
|
+
| `.addPanel(name, callback)` | 添加 panel;callback 接收 `panel` 配置对象,必须在其中放入至少一张卡片 |
|
|
813
|
+
| `.setLabelStyle(style)` | 设置标签样式:`TabLabelStyle.UNDERLINE`(默认)、`CARD`、`CAPSULE`、`TRAPEZOID` |
|
|
814
|
+
| `.setAlignment(alignment)` | 设置标签对齐:`TabAlignment.LEFT`(默认)、`CENTER`、`RIGHT` |
|
|
815
|
+
| `.setTabSize(size)` | 设置标签宽度:`TabSizeType.MAX_CONTENT`(默认)或 `FLEX` |
|
|
816
|
+
| `.setTitleStyle(config)` | 设置 Tab 总标题及其字体、位置、背景和图标 |
|
|
817
|
+
| `.setSelectedTextStyle(style)` / `.setUnselectedTextStyle(style)` | 设置选中/未选中页签文字样式 |
|
|
818
|
+
| `.setTabColor(color)` | 设置非下划线页签的主体颜色 |
|
|
819
|
+
| `.setBackgroundStyle({ color?, image? })` | 设置页签栏背景色和背景图 |
|
|
820
|
+
| `panel.setId(panelId)` | **必填**。设置 panel ID,必须以 `panel_` 开头且同一页面内唯一。建议用 `guanvis gen-layout-id panel` 生成 |
|
|
821
|
+
| `panel.setPanelStyle(config)` | 设置当前 panel 的背景、卡片间距和分割线颜色 |
|
|
822
|
+
| `panel.addRow(specs, height?)` | 在 panel 内按行放置卡片,写法同 `PageBuilder.addRow()` |
|
|
823
|
+
| `panel.addFullWidthCard(cardRef, height?)` | 在 panel 内放一张满宽卡片 |
|
|
824
|
+
| `panel.placeCard(cardRef, x, y, w, h)` | 在 panel 内精确放置卡片 |
|
|
825
|
+
|
|
826
|
+
Tab 的 `setTitleStyle()`:
|
|
827
|
+
|
|
828
|
+
| 字段 | 说明 |
|
|
829
|
+
|------|------|
|
|
830
|
+
| `enabled` | 是否显示总标题 |
|
|
831
|
+
| `title` | 总标题文字 |
|
|
832
|
+
| `position` | `TabTitlePosition.TOP` / `TabTitlePosition.LEFT` |
|
|
833
|
+
| `font` | 标题字体、字形和对齐 |
|
|
834
|
+
| `backgroundColor` | 标题背景色 |
|
|
835
|
+
| `backgroundImage` | 标题背景图 |
|
|
836
|
+
| `icon` | 标题图标 |
|
|
837
|
+
|
|
838
|
+
`panel.setPanelStyle()`:
|
|
839
|
+
|
|
840
|
+
| 字段 | 说明 |
|
|
841
|
+
|------|------|
|
|
842
|
+
| `backgroundColor` | panel 背景色 |
|
|
843
|
+
| `backgroundImage` | panel 背景图 |
|
|
844
|
+
| `margin` | `{ type, value }`;`type: LayoutMarginType.DIVIDE` 开启分割线模式,`SPACE` 的 value 为整数 1~20 |
|
|
845
|
+
| `dividingLineColor` | 分割线颜色 |
|
|
846
|
+
|
|
847
|
+
**使用示例**:
|
|
848
|
+
|
|
849
|
+
```javascript
|
|
850
|
+
var salesTab = createTab("销售分析")
|
|
851
|
+
.setId("tab_AbCdEf")
|
|
852
|
+
.setLabelStyle(TabLabelStyle.CAPSULE)
|
|
853
|
+
.setAlignment(TabAlignment.CENTER)
|
|
854
|
+
.addPanel("区域分析", function(panel) {
|
|
855
|
+
panel
|
|
856
|
+
.setId("panel_GhIjKl")
|
|
857
|
+
.addRow([{ card: 0, w: 6 }, { card: 1, w: 6 }], 6);
|
|
858
|
+
})
|
|
859
|
+
.addPanel("趋势分析", function(panel) {
|
|
860
|
+
panel
|
|
861
|
+
.setId("panel_MnOpQr")
|
|
862
|
+
.addFullWidthCard(2, 8);
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
var page = createPage("销售仪表板")
|
|
866
|
+
.setId("p184352b7a76776db5f534df")
|
|
867
|
+
.addTab(salesTab);
|
|
868
|
+
|
|
869
|
+
registerPage(page.build());
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
注意:
|
|
873
|
+
|
|
874
|
+
- tab 必须有 panel,panel 必须有卡片;不要创建空 tab 或空 panel。
|
|
875
|
+
- panel 内布局方法同 `PageBuilder`,使用 `cardRef`。
|
|
876
|
+
- panel 布局跟随页面精细模式:`page.setFineMode(true)` 后,panel 也使用 60 列栅格和精细模式默认行高。
|
|
877
|
+
- 不需要手工设置 tab 高度;只有明确要固定高度时才给 `page.addTab(tab, height)` 传第二个参数。
|
|
878
|
+
|
|
879
|
+
### SelectorBuilder(筛选器)
|
|
880
|
+
|
|
881
|
+
这里只保留方法索引。类型选择、配置约束、默认值、参数绑定、联动/级联、checkout 编辑和完整示例统一见 `selector-reference.md`;创建或修改筛选器前必须读取该文档。
|
|
882
|
+
|
|
883
|
+
| 方法 | 说明 |
|
|
884
|
+
|------|------|
|
|
885
|
+
| `createSelector(name)` | 创建筛选器 |
|
|
886
|
+
| `.setId(cardId)` | 设置资源 ID |
|
|
887
|
+
| `.setDescription(desc)` | 设置筛选器描述 |
|
|
888
|
+
| `.setSelectorSetting(config)` | 统一配置新建筛选器或能力矩阵中标记可编辑的已有 selector |
|
|
889
|
+
| `.setSelectorType(type)` / `.setFilterType(type)` | 设置筛选器类型和条件 |
|
|
890
|
+
| `.setFilterLevel(level)` | 设置筛选级别(`FilterLevel.DETAIL` 默认;`PARAMETER` 不支持) |
|
|
891
|
+
| `.bindDataset(dsId)` / `.bindField(field)` | 绑定数据集和字段 |
|
|
892
|
+
| `.bindTreeFields(...fields)` / `.setTreeSetting(config)` | 配置树状筛选器的固定层级字段和专属设置,详见 `selector-reference.md` |
|
|
893
|
+
| `.bindLayerTreeField(field)` / `.setLayerTreeSetting(config)` | 配置层级树状筛选器的单个层级树字段和专属设置;字段必须有 `layerTreeId` |
|
|
894
|
+
| `.bindCombinationFields(...fields)` / `.setCombinationSetting(config)` | 配置组合条件筛选器的候选字段与默认条件,详见 `selector-reference.md` |
|
|
895
|
+
| `.bindParameter(paramRef, options?)` | 绑定全局参数 |
|
|
896
|
+
| `.setGranularity(granularity)` / `.setGranularityOptions(options, defaultGranularity?)` | 设置日期粒度 |
|
|
897
|
+
| `.setTimeMacroOptions(options, defaultMacroName?)` | 设置快捷日期选项 |
|
|
898
|
+
| `.setMultiSelect(bool)` / `.setShowSelectAll(bool)` / `.setCanClear(bool)` | 设置选择行为 |
|
|
899
|
+
| `.setDefaultType(type)` / `.setDefaultAll()` | 设置默认值模式 |
|
|
900
|
+
| `.setDefaultValue(values, displayValues?)` / `.setDefaultDateRange(start, end, displayValues?)` | 设置固定默认值 |
|
|
901
|
+
| `.setFirstPickLink(bool)` | 设置首项联动刷新 |
|
|
902
|
+
| `.setDisplayType(type)` | 设置展示类型 |
|
|
903
|
+
| `.linkTo(cardIndex, targetFieldNameOrMappings?)` / `.linkToAll()` | 联动图表;组合条件可传字段映射对象 |
|
|
904
|
+
| `.linkToSelector(selectorId, targetFieldName?)` | 联动筛选器 |
|
|
905
|
+
| `.build()` | 构建并验证 |
|
|
906
|
+
|
|
907
|
+
### TextCardBuilder(文本卡片)
|
|
908
|
+
|
|
909
|
+
文本卡片(`cdType=1`)用于在仪表板中展示富文本内容,支持内嵌 SINGLE_VALUE 指标引用(在文本中内联展示实时指标值)。
|
|
910
|
+
|
|
911
|
+
| 方法 | 说明 |
|
|
912
|
+
|------|------|
|
|
913
|
+
| `createTextCard(name)` | 创建文本卡片 |
|
|
914
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
915
|
+
| `.addText(text)` | 添加一段普通文本 |
|
|
916
|
+
| `.addHeader(text, level?)` | 添加标题(level 1-6,默认 2) |
|
|
917
|
+
| `.addMarkdown(markdownText)` | **推荐**。用 Markdown 语法批量定义富文本内容(见下方 Markdown 语法说明) |
|
|
918
|
+
| `.embedCard(cardRefId, placeholder?)` | 在当前文本块末尾嵌入一个 SINGLE_VALUE 指标引用。`cardRefId` 是被引用卡片的 ID,`placeholder` 是占位文本(默认空格) |
|
|
919
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
920
|
+
| `.build()` | 构建(触发验证) |
|
|
921
|
+
|
|
922
|
+
**使用示例**:
|
|
923
|
+
|
|
924
|
+
```javascript
|
|
925
|
+
// card_00_kpi.js — 先创建被引用的 SINGLE_VALUE 卡片
|
|
926
|
+
var kpi = createCard(ChartType.SINGLE_VALUE, "总营收指标")
|
|
927
|
+
.setId("a184352b7a76776db5f534df")
|
|
928
|
+
.bindDataset(DS)
|
|
929
|
+
.addMetric(f("营收", { aggrType: AggrType.SUM }));
|
|
930
|
+
registerCard(kpi.build());
|
|
931
|
+
|
|
932
|
+
// card_01_text.js — 文本卡片引用上面的指标
|
|
933
|
+
var text = createTextCard("业绩概览")
|
|
934
|
+
.setId("b284352b7a76776db5f534df")
|
|
935
|
+
.addHeader("本月业绩报告")
|
|
936
|
+
.addText("本月总营收为 ")
|
|
937
|
+
.embedCard("a184352b7a76776db5f534df", "[总营收]")
|
|
938
|
+
.addText(",较上月有所增长。");
|
|
939
|
+
registerTextCard(text.build());
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
**嵌入机制**:文本卡片使用 Draft.js 格式存储内容。`embedCard()` 通过 `entityMap` 中的 `Macro` 类型实体引用其他 SINGLE_VALUE 卡片的 ID,BI 系统在渲染时会将占位文本替换为实时指标值。被引用的卡片**必须是 SINGLE_VALUE 类型**。
|
|
943
|
+
|
|
944
|
+
**Markdown 模式**(推荐用于复杂文本):
|
|
945
|
+
|
|
946
|
+
`addMarkdown()` 支持以下 Markdown 语法,自动转换为 BI 富文本格式:
|
|
947
|
+
|
|
948
|
+
| 语法 | 效果 |
|
|
949
|
+
|------|------|
|
|
950
|
+
| `# ~ ######` | 一至六级标题 |
|
|
951
|
+
| `**text**` | **加粗** |
|
|
952
|
+
| `*text*` | *斜体* |
|
|
953
|
+
| `~~text~~` | ~~删除线~~ |
|
|
954
|
+
| `` `code` `` | 行内代码 |
|
|
955
|
+
| `- item` / `* item` | 无序列表(支持缩进嵌套) |
|
|
956
|
+
| `1. item` | 有序列表 |
|
|
957
|
+
| `> quote` | 引用块 |
|
|
958
|
+
| `---` | 分隔线 |
|
|
959
|
+
| `{{cardId:占位文本}}` | 内嵌 SINGLE_VALUE 指标引用 |
|
|
960
|
+
|
|
961
|
+
```javascript
|
|
962
|
+
// 使用 addMarkdown 一次性定义复杂富文本(ID 通过 guanvis genid 预生成)
|
|
963
|
+
var kpiId = "c384352b7a76776db5f534df";
|
|
964
|
+
var kpi = createCard(ChartType.SINGLE_VALUE, "总营收")
|
|
965
|
+
.setId(kpiId)
|
|
966
|
+
.bindDataset(DS)
|
|
967
|
+
.addMetric(f("营收", { aggrType: AggrType.SUM }));
|
|
968
|
+
registerCard(kpi.build());
|
|
969
|
+
|
|
970
|
+
var text = createTextCard("数据报告")
|
|
971
|
+
.setId("d484352b7a76776db5f534df")
|
|
972
|
+
.addMarkdown(
|
|
973
|
+
"## 月度业绩报告\n\n" +
|
|
974
|
+
"本月总营收为 {{" + kpiId + ":总营收}},**表现优异**。\n\n" +
|
|
975
|
+
"### 关键发现\n" +
|
|
976
|
+
"1. 华东区域贡献最大\n" +
|
|
977
|
+
"2. 新品类增长 *显著*\n\n" +
|
|
978
|
+
"> 数据截至本月最后一个工作日"
|
|
979
|
+
);
|
|
980
|
+
registerTextCard(text.build());
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
### createTextCardWithData(带数据的文本卡片)
|
|
984
|
+
|
|
985
|
+
高层便捷方法,一次调用自动完成:创建多个 SINGLE_VALUE 指标卡片 → 创建包含 Markdown 富文本的文本卡片 → 自动注册所有卡片。省去手动创建 KPI 卡片、拼接 `{{cardId:placeholder}}` 占位符、依次注册的繁琐步骤。
|
|
986
|
+
|
|
987
|
+
```javascript
|
|
988
|
+
createTextCardWithData(config)
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
**config 参数**:
|
|
992
|
+
|
|
993
|
+
| 字段 | 必填 | 说明 |
|
|
994
|
+
|------|------|------|
|
|
995
|
+
| `textCardId` | 是 | 文本卡片的资源 ID |
|
|
996
|
+
| `textCardName` | 否 | 文本卡片名称(默认"数据报告") |
|
|
997
|
+
| `textCardDescription` | 否 | 文本卡片描述 |
|
|
998
|
+
| `dsId` | 否 | 数据集 ID(默认使用 `DS`,即第一个 `defineDataset` 的数据集) |
|
|
999
|
+
| `metrics` | 是 | 指标配置数组(见下表) |
|
|
1000
|
+
| `markdown` | 是 | Markdown 模板,用 `{{字段名或label}}` 引用指标 |
|
|
1001
|
+
|
|
1002
|
+
**metrics 数组元素**:
|
|
1003
|
+
|
|
1004
|
+
| 字段 | 必填 | 说明 |
|
|
1005
|
+
|------|------|------|
|
|
1006
|
+
| `id` | 是 | 该 SINGLE_VALUE 卡片的资源 ID |
|
|
1007
|
+
| `fieldName` | 是 | 数据集中的字段名 |
|
|
1008
|
+
| `label` | 否 | 指标别名(用于 Markdown 中引用和卡片命名,默认取 fieldName) |
|
|
1009
|
+
| `aggrType` | 否 | 聚合类型(默认 `AggrType.SUM`) |
|
|
1010
|
+
| `numberFormat` | 否 | 数值格式 |
|
|
1011
|
+
|
|
1012
|
+
**Markdown 中的引用语法**:使用 `{{label}}` 或 `{{fieldName}}` 引用指标,函数自动替换为对应 SINGLE_VALUE 卡片的 Macro 引用。
|
|
1013
|
+
|
|
1014
|
+
**使用示例**:
|
|
1015
|
+
|
|
1016
|
+
```javascript
|
|
1017
|
+
createTextCardWithData({
|
|
1018
|
+
textCardId: "t184352b7a76776db5f534df",
|
|
1019
|
+
textCardName: "月度业绩报告",
|
|
1020
|
+
metrics: [
|
|
1021
|
+
{ id: "m184352b7a76776db5f534df", fieldName: "营收", label: "总营收",
|
|
1022
|
+
aggrType: AggrType.SUM, numberFormat: NumberFormat.currency("¥", 0) },
|
|
1023
|
+
{ id: "m284352b7a76776db5f534df", fieldName: "利润", aggrType: AggrType.SUM },
|
|
1024
|
+
{ id: "m384352b7a76776db5f534df", fieldName: "订单数", label: "总订单",
|
|
1025
|
+
aggrType: AggrType.COUNT }
|
|
1026
|
+
],
|
|
1027
|
+
markdown: [
|
|
1028
|
+
"## 月度业绩报告",
|
|
1029
|
+
"",
|
|
1030
|
+
"本月总营收为 {{总营收}},利润 {{利润}}。",
|
|
1031
|
+
"",
|
|
1032
|
+
"### 关键指标",
|
|
1033
|
+
"- 总订单数:{{总订单}}",
|
|
1034
|
+
"- 利润率表现**优异**",
|
|
1035
|
+
"",
|
|
1036
|
+
"> 数据截至本月最后一个工作日"
|
|
1037
|
+
].join("\n")
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
// 布局:第一行 3 个 KPI 指标卡(cardIndex 0~2),第二行全宽文本报告(cardIndex 3)
|
|
1041
|
+
var page = createPage("业绩仪表板")
|
|
1042
|
+
.setId("p184352b7a76776db5f534df")
|
|
1043
|
+
.addRow([{ card: 0, w: 4 }, { card: 1, w: 4 }, { card: 2, w: 4 }], 3)
|
|
1044
|
+
.addFullWidthCard(3, 6);
|
|
1045
|
+
registerPage(page.build());
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
**注册顺序**:`createTextCardWithData` 会按 `metrics` 数组顺序先注册 SINGLE_VALUE 卡片(cardIndex 从 0 开始),最后注册文本卡片。在 page 布局中,前 N 个 cardIndex 对应 N 个指标卡,第 N 个 cardIndex 对应文本卡片。
|
|
1049
|
+
|
|
1050
|
+
### ImageCardBuilder(图片卡片)
|
|
1051
|
+
|
|
1052
|
+
图片卡片(`cdType=4`)用于在仪表板中展示图片,支持外链 URL 和本地图片文件。
|
|
1053
|
+
|
|
1054
|
+
**支持的图片格式**:本地上传仅支持 `jpg/jpeg/png/gif` 格式。**不支持 SVG**——如需使用 SVG 图片,必须先转换为 PNG 等支持的格式后再上传。
|
|
1055
|
+
|
|
1056
|
+
**SVG 转 PNG 推荐方式**(按优先级排列):
|
|
1057
|
+
1. `npx sharp-cli -i input.svg -o output.png -f png` — 基于 sharp(最流行的 Node.js 图像处理库),无需提前安装
|
|
1058
|
+
2. `npx sharp-cli -i input.svg -o output.png -f png resize 1200` — 指定宽度缩放
|
|
1059
|
+
3. **agent-browser** — 通过浏览器打开 SVG 文件再截图,适合需要精确 CSS/字体渲染的场景
|
|
1060
|
+
|
|
1061
|
+
不要使用 `ffmpeg`(不支持 SVG)或 `cairosvg`(Python 依赖复杂易出错)。
|
|
1062
|
+
|
|
1063
|
+
| 方法 | 说明 |
|
|
1064
|
+
|------|------|
|
|
1065
|
+
| `createImageCard(name)` | 创建图片卡片 |
|
|
1066
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
1067
|
+
| `.setUrl(url)` | 设置外链图片 URL(sourceType=1) |
|
|
1068
|
+
| `.setLocalImage(filePath)` | 设置本地图片文件路径(sourceType=2),打包时图片会作为附件写入 ZIP |
|
|
1069
|
+
| `.setRenderType(type)` | 设置图片渲染模式:`ImageRenderType.RATIO`(原比例,默认)、`ImageRenderType.STRETCH`(拉伸填满)、`ImageRenderType.FIT_TO_CONTENT`(自适应内容) |
|
|
1070
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
1071
|
+
| `.build()` | 构建(触发验证) |
|
|
1072
|
+
|
|
1073
|
+
**使用示例**:
|
|
1074
|
+
|
|
1075
|
+
```javascript
|
|
1076
|
+
// 外链图片
|
|
1077
|
+
var img1 = createImageCard("Logo")
|
|
1078
|
+
.setId("c384352b7a76776db5f534df")
|
|
1079
|
+
.setUrl("https://example.com/logo.png");
|
|
1080
|
+
registerImageCard(img1.build());
|
|
1081
|
+
|
|
1082
|
+
// 本地图片 + 拉伸填满模式(适合 Banner)
|
|
1083
|
+
var img2 = createImageCard("Banner")
|
|
1084
|
+
.setId("d484352b7a76776db5f534df")
|
|
1085
|
+
.setLocalImage("./assets/banner.png")
|
|
1086
|
+
.setRenderType(ImageRenderType.STRETCH);
|
|
1087
|
+
registerImageCard(img2.build());
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
**本地图片机制**:`setLocalImage()` 指定本地文件路径,`pack`/`publish` 时工具会将图片文件读取并作为 Appendix 附件打包进 ZIP 资源包。导入 BI 系统时,后端会将图片存储到内部文件存储并建立引用关系。仅支持 jpg/jpeg/png/gif 格式;SVG 需先转为 PNG。
|
|
1091
|
+
|
|
1092
|
+
### CustomChartBuilder(自定义图表)
|
|
1093
|
+
|
|
1094
|
+
自定义图表(`cdType=10`)允许使用自定义 HTML/CSS/JavaScript 代码渲染图表,适用于内置图表类型无法满足的场景。支持三种子类型:
|
|
1095
|
+
|
|
1096
|
+
| 子类型 | 说明 |
|
|
1097
|
+
|--------|------|
|
|
1098
|
+
| `CustomChartSubType.SDK` | 标准自定义图表,在 iframe 中运行。支持任意前端库(Vega-Lite/D3/ECharts 等)。**Tableau 迁移场景首选** |
|
|
1099
|
+
| `CustomChartSubType.ECHARTS_LITE` | 原生 ECharts 模式,无 iframe。只需写 JS 脚本设置 `option`。仅适用于 ECharts 能满足的简单场景 |
|
|
1100
|
+
|
|
1101
|
+
**子类型选择指南**:
|
|
1102
|
+
- 自定义图表优先使用 **SDK** 模式 + Vega-Lite,模板和文档支持最完整
|
|
1103
|
+
- 纯 ECharts 且脚本极简的场景 → 可用 **ECHARTS_LITE**(无 iframe 开销,但也可以用 SDK 模式)
|
|
1104
|
+
- SDK 模式运行在 iframe 中,需要通过 `__asset_text__`/`__asset_base64__` 内嵌外部资源
|
|
1105
|
+
|
|
1106
|
+
| 方法 | 说明 |
|
|
1107
|
+
|------|------|
|
|
1108
|
+
| `createCustomChart(name)` | 创建自定义图表卡片 |
|
|
1109
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
1110
|
+
| `.setSubType(subType)` | 设置子类型,默认 `SDK`。用 `CustomChartSubType.XXX` |
|
|
1111
|
+
| `.loadContent(baseName)` | **推荐**。从文件加载 HTML/CSS/JS。工具自动读取 `baseName.html`、`baseName.css`、`baseName.js`(`.js` 必须存在,`.html` 和 `.css` 可选) |
|
|
1112
|
+
| `.setContent(html, css, script)` | 内联设置 HTML/CSS/JS(仅在内容极简时使用)|
|
|
1113
|
+
| `.addLib(url)` | 添加外部 JS 库 URL |
|
|
1114
|
+
| `.setProps(props)` | 设置自定义属性 |
|
|
1115
|
+
| `.addDataView(cardBuilder)` | 添加数据视图(子卡片),子卡片使用普通 `CardBuilder` 创建(任意 ChartType 均可,系统自动转换为 DATA_GRID)。用 `.addRow()` 放维度、`.addMetric()` 放度量 |
|
|
1116
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
1117
|
+
| `.build()` | 构建(触发验证) |
|
|
1118
|
+
|
|
1119
|
+
**数据流**:BI 前端查询子卡片(data view)的数据 → 将结果按列组织为 `data` → 传给自定义图表的 `renderChart(data, clickFunc, config)` 函数(SDK)或直接可用 `data` 变量(ECHARTS_LITE)。
|
|
1120
|
+
|
|
1121
|
+
**点击联动(custom chart 作为联动源)**:在 data view(子卡片 `CardBuilder`)上调用 `.linkTo(target, { fields: [{ source, target }] })`,即可让自定义图表成为同页联动源——图表内部点击某维度时,按映射过滤目标卡片。`target` 仍按布局 index 或 cardId 解析(不能指向自身所在的自定义图表)。校验、字段匹配、同页与联动环检查与普通图表卡片完全一致,结果写为 data view 的 `settings.asFilter` + `interaction=LINK`。SDK 子类型必须在 `renderChart` 里用第二个入参 `clickFunc` 回传点击:`clickFunc({ clickedItems: [{ idx: [viewIndex, columnIndex], colName: '列名', value: ['选中值'] }] })`;`idx[1]` 指向 data view 行字段的列序号。ECHARTS_LITE 也用同样的 `clickFunc`。
|
|
1122
|
+
|
|
1123
|
+
`data` 格式(二维数组,外层每个元素对应一个数据视图,内层每个元素对应一个字段列):
|
|
1124
|
+
```javascript
|
|
1125
|
+
// data[viewIndex][columnIndex] = { name: "字段名", data: [...值], numberFormat: ... }
|
|
1126
|
+
data[0][0].name // → "类别"
|
|
1127
|
+
data[0][0].data // → ["办公用品", "技术", "家具"]
|
|
1128
|
+
data[0][1].name // → "销售额"
|
|
1129
|
+
data[0][1].data // → [4916842, 3157709.5, 3037943.5]
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
`config` 包含 `{ theme: "LIGHT"|"DARK", colors: string[], customOptions: object, language: string }`。
|
|
1133
|
+
|
|
1134
|
+
**推荐的工作方式**(文件模式):
|
|
1135
|
+
|
|
1136
|
+
1. AI 将自定义图表的 HTML/CSS/JS 分别写入独立文件(如 `my_chart.html`、`my_chart.css`、`my_chart.js`)
|
|
1137
|
+
2. 在 card 脚本中使用 `.loadContent("my_chart")` 引用
|
|
1138
|
+
|
|
1139
|
+
文件结构示例(**内容文件必须放在子目录中**,避免被 pack 当作 card 脚本执行):
|
|
1140
|
+
```
|
|
1141
|
+
project/
|
|
1142
|
+
├── schema.js
|
|
1143
|
+
├── card_01_custom.js ← card 脚本(loadContent("charts/my_chart"))
|
|
1144
|
+
├── page.js
|
|
1145
|
+
└── charts/ ← 子目录:自定义图表内容文件
|
|
1146
|
+
├── my_chart.html ← HTML(可选)
|
|
1147
|
+
├── my_chart.css ← CSS(可选)
|
|
1148
|
+
├── my_chart.js ← JavaScript(必须)
|
|
1149
|
+
└── us-10m.json ← 资源文件(可选,通过 asset 占位符引用)
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
**资源内嵌**(`__asset_text__` / `__asset_base64__`):
|
|
1153
|
+
|
|
1154
|
+
自定义图表运行在 iframe 沙箱中,不能从外部 URL 加载资源(CORS/sandbox 限制)。需要将 GeoJSON、图片等资源内嵌到 JS/HTML 中。使用 asset 占位符让 `pack`/`publish` 自动替换:
|
|
1155
|
+
|
|
1156
|
+
```javascript
|
|
1157
|
+
// 在 .js 文件中引用本地文件为 JSON 字符串(自动 escape)
|
|
1158
|
+
var geoData = JSON.parse(__asset_text("./us-10m.json")__);
|
|
1159
|
+
|
|
1160
|
+
// 引用本地文件为 base64 编码字符串
|
|
1161
|
+
var logoBase64 = __asset_base64("./logo.png")__;
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
- `__asset_text("path")__` — 读取文件内容,做 JSON string escape 后替换(结果带双引号,是一个合法的 JSON 字符串字面量)
|
|
1165
|
+
- `__asset_base64("path")__` — 读取文件内容,做 base64 编码后替换(结果带双引号)
|
|
1166
|
+
- 路径相对于内容文件所在目录(即 `.loadContent()` 指向的目录)
|
|
1167
|
+
- 路径不允许向上跳出内容目录(安全限制)
|
|
1168
|
+
- 占位符仅在 `pack`/`publish` 构建时处理,不影响 AI 脚本的可读性
|
|
1169
|
+
|
|
1170
|
+
### ComplexReportProBuilder(复杂报表 Pro)
|
|
1171
|
+
|
|
1172
|
+
复杂报表 Pro 是 `cdType=10 + subType=COMPLEX_REPORT + version=COMPLEX_REPORT_PRO` 的原生报表卡片。**Pro 是需要单独授权的非默认功能**:仅当用户明确点名"复杂报表 / 复杂报表 Pro"、或修改的卡片本身已是 Pro 时使用(选型门槛见 `complex-report-pro-patterns.md` §0)。旧版复杂报表不支持创建、attach 或 checkout/edit;Pro 父卡也不能使用泛化 `attachCard()`,因为它还需要版本化 xlsx 附件和子数据视图协议。
|
|
1173
|
+
|
|
1174
|
+
| 方法 | 说明 |
|
|
1175
|
+
|---|---|
|
|
1176
|
+
| `createComplexReportPro(name)` | 创建 Pro 父卡 |
|
|
1177
|
+
| `.setId(cardId)` | **必填**,24 位父卡 ID |
|
|
1178
|
+
| `.setDescription(desc)` | 描述 |
|
|
1179
|
+
| `.setTemplate(path)` | 使用已有 `.xlsx`;与 `.setWorkbook()` 二选一 |
|
|
1180
|
+
| `.setWorkbook(workbook)` | 使用 `createReportWorkbook()` 结构化生成 xlsx |
|
|
1181
|
+
| `.addDataView(alias, cardBuilder)` | 添加子数据视图;新建用普通 CardBuilder,checkout 可传 attachCard Builder |
|
|
1182
|
+
| `.setTemplateVersion(n)` | 非负整数。新建通常为 0;checkout 默认生成下一版本 |
|
|
1183
|
+
| `.setPagination(bool)` | 写入 Pro 分页配置 |
|
|
1184
|
+
| `.setColumnWidthStretch(bool)` | 写入列宽拉伸配置 |
|
|
1185
|
+
| `.setGCVersion("new" \| "old")` | GcExcel 版本,默认 `new` |
|
|
1186
|
+
| `.setReserveFormulaAndHiddenRCS(bool)` | 是否保留公式与隐藏行列,默认 true |
|
|
1187
|
+
| `.setDataSourceRelations(relations)` | 多数据源关联;pack 阶段做结构校验并把视图别名/字段名翻译成子卡 ID/zone key,详见下文 |
|
|
1188
|
+
| `.setSpecialValue(values)` | 特殊值配置 |
|
|
1189
|
+
| `.setRawSettings(key, value)` | 父卡 settings |
|
|
1190
|
+
| `.build()` | 构建并校验 |
|
|
1191
|
+
|
|
1192
|
+
Workbook API:
|
|
1193
|
+
|
|
1194
|
+
| 方法 | 说明 |
|
|
1195
|
+
|---|---|
|
|
1196
|
+
| `createReportWorkbook().addSheet(name, fn)` | 新建工作簿和 Sheet |
|
|
1197
|
+
| `sheet.setValue(cell, value, style?)` | 常量单元格 |
|
|
1198
|
+
| `sheet.setFormula(cell, formula, style?)` | Excel 公式 |
|
|
1199
|
+
| `sheet.setDynamicFormula(cell, formula, options?, style?)` | 随扩展区域复制的 GcExcel 模板公式 |
|
|
1200
|
+
| `sheet.setContextText(cell, text, { context }, style?)` | 随指定维度父格重复的静态文本,主要用于“小计”标签 |
|
|
1201
|
+
| `sheet.bindDimension(cell, reportField(view, field), options?)` | Pro 维度绑定 |
|
|
1202
|
+
| `sheet.bindMetric(cell, reportField(view, field), options?)` | Pro 度量绑定 |
|
|
1203
|
+
| `sheet.bindImage(cell, reportField(view, urlField), options?)` | 将 URL 字段编译为 Pro 图片单元格 |
|
|
1204
|
+
| `sheet.bindSubtotal(cell, reportField(view, metric), options)` | 分组小计;`context` 必须指向同一行左侧的 `setContextText` |
|
|
1205
|
+
| `sheet.bindGrandTotal(cell, reportField(view, metric), options?)` | 全表总计;自动使用 `E=N,C=None`,禁止传 `context` |
|
|
1206
|
+
| `sheet.merge(range)` | 合并,如 `A1:C1` |
|
|
1207
|
+
| `sheet.setColumnWidth(column, width)` | 列宽 |
|
|
1208
|
+
| `sheet.setRowHeight(row, height)` | 行高 |
|
|
1209
|
+
| `sheet.setRowHidden(row)` / `sheet.setColumnHidden(column)` | 隐藏辅助行/列(数据保留但不显示;column 支持 `"B"` 或 `"B:D"`) |
|
|
1210
|
+
| `sheet.setRowStyle(row, style)` / `sheet.setColumnStyle(column, style)` | 整行/整列默认样式(覆盖空白格与未来扩展格,区别于逐格样式)。会覆盖行/列内已有单元格样式,应在单元格写入**之前**声明 |
|
|
1211
|
+
| `sheet.beginBlock(anchorCell, reportField(view, key), options?)` | 段落明细块:锚点纵向扩展,块内成员整块随记录重复 |
|
|
1212
|
+
|
|
1213
|
+
`beginBlock` 返回块构造器,成员单元格自动挂 `context=锚点`(允许位于锚点下方行,这是普通 `context` 校验禁止的形态):
|
|
1214
|
+
|
|
1215
|
+
| 块方法 | 说明 |
|
|
1216
|
+
|---|---|
|
|
1217
|
+
| `.text(cell, "标签", style?)` | 随块重复的静态标签 |
|
|
1218
|
+
| `.dimension(cell, reportField(...), options?)` | 块内维度值 |
|
|
1219
|
+
| `.metric(cell, reportField(...), options?)` | 块内度量值 |
|
|
1220
|
+
| `.image(cell, reportField(...), options?)` | 块内 URL 图片 |
|
|
1221
|
+
| `.formula(cell, "B2*2", style?)` | 块内动态公式(只能引用单元格) |
|
|
1222
|
+
| `.spacer(cell)` | 空隙行(空 contextText,随块重复留白) |
|
|
1223
|
+
| `.end()` | 返回 sheet 继续链式调用 |
|
|
1224
|
+
|
|
1225
|
+
块校验规则:锚点必须位于块矩形的左上角并纵向扩展;成员只能以锚点为唯一父格;小计/总计绑定不允许放进块内;其他模板单元格不得落入块矩形(GcExcel 会整块重复该区域)。锚点通常是记录 ID,metaType=METRIC 的字段可以直接作锚点(跳过维度类型检查)。语义与 dev29 已验证的手写外部模板版完全一致。
|
|
1226
|
+
|
|
1227
|
+
绑定 `options` 支持 `expansion`、`fillMode`、`context`、`countPerPage`、`filter`、`filterBy`、`numberFormat` 和 `style`;维度额外支持 `group`、`sort`,度量额外支持 `aggregate`。未知 option 会直接校验失败,不再静默忽略。
|
|
1228
|
+
|
|
1229
|
+
`context` 可写单父格 `A3`,也可写横纵双父格 `A4*B3`。父格必须是维度绑定:左父格与当前格同一行且纵向扩展,上父格与当前格同一列且横向扩展,最多各一个。相同数据视图的层级和交叉表只用 `context`;同时生成同源 `filterBy` 会形成嵌套 `LP(...)`,现在会在 pack 阶段拒绝。`filterBy` 仅用于跨数据视图映射,字段的 view 必须是当前绑定 view,引用的 cell 必须是 `context` 里的父格或父格的 `context` 祖先(多级表头可同时给年、月两个列键)。`filter` 与 `filterBy` 不能并用。**同一 Sheet 里 `filterBy` 与 `expansion: "horizontal"` 并存时按格校验**(pack 拒绝,规则与实测见 complex-report-pro-patterns.md §1):带 `filterBy` 的格若挂在横向父格下,`filterBy` 必须包含该横向父格;同 Sheet 其它挂在横向父格下、自身不横向扩展的绑定/动态公式必须也带 `filterBy`,否则改用 `setDataSourceRelations` 虚拟视图 + `context`;`filterBy` 不能写在横向扩展格自身上;第 1 行与 A 列都要有格(标题放 A1),否则渲染器还原横向表头时错位。同一列里下方第二段带的顶层维度要显式 `context: "None"`,否则默认父格推断会把它挂到上一段的同列维度。
|
|
1230
|
+
|
|
1231
|
+
聚合可用 `SUM/COUNT/AVERAGE/MAX/MIN/PRODUCT/STDDEV/STDDEVP/VAR/VARP`。`AVG` 是输入别名,会编译为 `AVERAGE`;`COUNTA` 不是 Pro 聚合函数,会在本地拒绝。`countPerPage` 只接受正整数或 `*`。分页模式最多设置一个 `countPerPage`,且只能放在没有 `context` 的顶层 `bindDimension` 上;放在嵌套子维度上会导致 Pro 分页器只合并部分祖先单元格,因此 `pack` 会直接拒绝。
|
|
1232
|
+
|
|
1233
|
+
小计不要手写老复杂报表的 `G_SUBTOTAL/G_GRANDTOTAL`。Pro 的分组汇总由“维度父格 → `setContextText` 小计标签 → `bindSubtotal` 聚合值”组成;全表汇总使用 `bindGrandTotal`。图片 URL 使用 `bindImage`,编译结果是 Pro 后端识别的 `&=IMAGE(G_TEXT({{view.field(...)}}))`,导出时最多处理 1000 个图片单元格,下载失败时会回退显示 URL。图片表格的模板总宽度小于卡片时,优先对父卡调用 `.setColumnWidthStretch(true)` 横向自动铺满,并通过图片列宽与图片行高控制展示比例。Pro 后端会把图片 shape 设置为整个单元格区域,不提供 `contain/crop` 参数;原图画布自带的白边只能在图片源侧裁切。
|
|
1234
|
+
|
|
1235
|
+
动态扩展行/列中的占比、同比、差值等公式应使用 `setDynamicFormula()`;普通 `setFormula()` 只适合不需要随模板扩展复制的 Excel 公式。动态公式只能引用单元格,options 只支持 `context`;数据字段引用、内部 `LP/LPF`、未配对括号和其他被忽略的 option 会校验失败。
|
|
1236
|
+
|
|
1237
|
+
动态公式的 `context` 还可以指向同行左侧的 `setContextText` 小计标签,实现"分组级公式聚合":`setDynamicFormula("D3", "SUM(D2)", { context: "B3" })` 会随每个分组复制,GcExcel 把引用改写为整组区域(多明细组变成 `SUM(D2,D4,...)`),对数据绑定列和动态公式列都有效(dev29 已实测,独立求和核对一致)。AVERAGE 等其他聚合同样可用。注意小计公式格的数字格式来自它自己的 style,不继承明细列。
|
|
1238
|
+
|
|
1239
|
+
纵向父格允许跨行:父格只需位于子格的左上方位(同行左、同列上、或左上区域均可),不必与子格同行。这覆盖阶梯布局——组标题独占一行(锚点),明细行在下方其他列挂该锚点,小计标签行也跨行挂锚点;GcExcel 会按组正确重复并把跨行小计公式改写为组区域(如 `SUM(C3:C103)`,dev29 已实测)。横向父格仍要求同列上方;`bindSubtotal`/小计行公式的标签仍要求同行左侧。
|
|
1240
|
+
|
|
1241
|
+
`sheet.setFreeze(rows, cols, { topLeftCell? })` 冻结顶部行/左侧列(可选 `topLeftCell` 记录可滚动区的视口锚点格,须位于冻结区之外,默认冻结区后的第一格);`sheet.setConditionalFormat(range, rules)` 写条件格式,rule 支持单元格比较 `{ op: ">", value: "1000", backgroundColor: "#FFC7CE", fontColor: "#9C0006" }`(op 限 `> < >= <= == !=`)或公式条件 `{ formula: "MOD(ROW(),2)=0", backgroundColor: "#EAF3FB" }`(斑马纹);rule 可加 `stopIfTrue: true` 命中后阻止后续规则求值(多档配色)。规则求值顺序 = rules 数组顺序;多个 `setConditionalFormat` 之间按操作声明顺序求值(重叠区域配合 stopIfTrue 时顺序有语义,反编译也按此全局顺序还原)。注意 `value` 是**公式片段**:数字直接写(`"1000"`),文本常量必须带引号(`value: "\"缺货\""`),裸文本会被 Excel 解释为名称引用。dev29 已实测:GcExcel 完整保留模板的冻结窗格与条件格式,且把条件格式区域自动裁剪到扩展后的数据区(写 `B2:B10000` 即可覆盖整列扩展区)。超链接分两种形态(均 dev29 实证):**静态格**用 `setHyperlink(cell, url, { tooltip? })`(GcExcel 渲染保留,适合标题/说明/返回目录格);**扩展区行级链接**用 `setDynamicFormula` + `HYPERLINK("url","文本")`(展开为 shared formula 每行可点)——worksheet 超链条目按固定 ref 定位,不随模板行复制,所以不要给扩展区模板格挂 setHyperlink。颜色必须 `#RRGGBB`。
|
|
1242
|
+
|
|
1243
|
+
打印/静态资产扩展(dev29 已实测 GcExcel 全部保留):`sheet.setImage(cell, path, { scaleX?, scaleY? })` 把**本地** png/jpg/jpeg/gif 嵌入单元格(logo/印章/装饰图;路径相对工程目录且不得逃逸;行级图片列仍用 `bindImage` URL 字段);style 支持 `diagonalDown: true`(斜线表头,`diagonalColor` 可自定义颜色);`sheet.setPrintTitleRows(from, to?)` 让表头行在打印/导出每页重复(xlsx Print_Titles);`sheet.setHeaderFooter({ header?, footer? })` 设置页眉页脚(支持 `&P`/`&N` 页码代码)。序号列用 `setDynamicFormula("ROW()-N", { context: 同行右侧维度格 })`——校验器专门放行"动态公式挂同行右侧父格"的最左序号列形态,GcExcel 逐行展开为 1,2,3…。
|
|
1244
|
+
|
|
1245
|
+
启用 `.setPagination(true)` 时只能包含一个 Sheet,且不能使用 `filter`/`filterBy`;同源层级继续使用 `context`,但分页锚点自身必须是无 `context` 的顶层维度。这些约束对 `.setWorkbook()` 结构化模板和 `.setTemplate()` 外部 xlsx 一视同仁:外部模板会在 pack 阶段扫描 `{{...}}` 块的 `CP/C/F` 属性做同样的拒绝。需要保留更高层标签时,应把分页粒度提升为第一层,或把更高层标签改为固定标题/重复列。新建 Pro 必须和引用它的 Page 一起打包,否则后端虽可能报告导入成功,但卡片查询不可用。
|
|
1246
|
+
|
|
1247
|
+
多数据源用 `.setDataSourceRelations([group, ...])`,每个 group 定义一个 JOIN 出来的虚拟视图:
|
|
1248
|
+
|
|
1249
|
+
```javascript
|
|
1250
|
+
report.setDataSourceRelations([{
|
|
1251
|
+
tableName: "产品供应商", // 模板中通过 产品供应商.字段 引用
|
|
1252
|
+
relations: [
|
|
1253
|
+
{ leftId: "products", rightId: "suppliers",
|
|
1254
|
+
leftColumnKey: "供应商ID", rightColumnKey: "供应商ID", joinType: "INNER" },
|
|
1255
|
+
{ leftId: "products", rightId: "categories",
|
|
1256
|
+
leftColumnKey: "类别ID", rightColumnKey: "类别ID", joinType: "INNER" }
|
|
1257
|
+
],
|
|
1258
|
+
selectedCols: [
|
|
1259
|
+
{ viewId: "suppliers", key: "公司名称", name: "" }, // name 为空输出显示名
|
|
1260
|
+
{ viewId: "categories", key: "类别名称", name: "" },
|
|
1261
|
+
{ viewId: "products", key: "订购量", name: "" }
|
|
1262
|
+
]
|
|
1263
|
+
}]);
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
`leftId/rightId/viewId` 写数据视图别名(也接受 checkout 回读时的子卡 ID),`leftColumnKey/rightColumnKey/key` 写字段显示名(也接受已有 zone key),pack 时统一翻译为后端需要的子卡 ID 和 zone key。`joinType` 仅支持 `INNER/LEFT_OUTER/RIGHT_OUTER/OUTER`(省略默认 `LEFT_OUTER`);同组 relations 必须把所有视图连成一张连通图,断图会在本地直接拒绝(后端同样拒绝)。JOIN 键如果是 metaType=METRIC 的 ID 字段,在子视图里用 `AggrType.MAX` 带出即可。模板引用虚拟视图时字段名必须出现在该组 `selectedCols` 输出中;`tableName` 会自动补进 `viewNames`。虚拟视图输出是行级明细,`bindSubtotal`/`bindGrandTotal` 聚合它们照常可用。dev29 已验证三源 JOIN + 两级小计 + 总计 + 动态公式。
|
|
1267
|
+
|
|
1268
|
+
页面筛选器可以联动 Pro 的数据视图:`createSelector(...).linkTo(index, "字段名")` 的可联动目标序列包含 Pro 子视图(按 `addDataView` 顺序),运行时走与自定义图表相同的 `childFilters` 机制,小计/总计随筛选重算。发布后可用 `guancli card preview <proId> --filter "字段 EQ 值"` 无头验证同一机制。
|
|
1269
|
+
|
|
1270
|
+
“每条记录一个多行块”的段落明细形态优先用 `sheet.beginBlock()` 结构化表达(见上表)。手工维护的外部 xlsx 模板也可以实现同样语义:把纵向锚点 `{{view.主键(S=None)}}` 放在块左上角,块内其余标签写 `文本{{(C=锚点)}}`、值写 `{{view.字段(S=None,C=锚点)}}`(含锚点下方行),空隙行用 `{{(C=锚点)}}`。注意值单元格必须显式写 `C=`:省略时 GcExcel 会按默认父格推断挂到左侧模板格,若左侧标签又显式挂回值单元格会形成父格循环依赖——`pack` 现在会在本地按同样的推断规则做环检测直接拒绝(`guanvis report inspect <xlsx>` 可单独查看模板格、父格链与环检测结果)。数据视图的 `.setLimit(n)` 不会限制 Pro 导出行数。
|
|
1271
|
+
|
|
1272
|
+
checkout 得到的 `templates/<cdId>.xlsx` 可用 `guanvis report decompile <xlsx> [-o workbook.js]` 反编译为等价的 `createReportWorkbook()` JS 源码(段落块还原为 `beginBlock`,小计/总计还原为 `bindSubtotal`/`bindGrandTotal`,冻结窗格还原为 `setFreeze`,单元格比较/公式类条件格式还原为 `setConditionalFormat`,序号列/阶梯布局等所有 pack 校验放行的父格形态都不会被误判成块,`F=` 过滤原样保留为 `filter` option);把 card JS 的 `.setTemplate(...)` 换成 `.setWorkbook(workbook)` 后模板即文本化,可由 AI 直接编辑。反编译结果在替换前务必 `preview`/`pack` 校验一遍。
|
|
1273
|
+
|
|
1274
|
+
**创建与编辑共用一套 Workbook DSL**,`createReportWorkbook(templatePath?)` 的可选参数决定基底:
|
|
1275
|
+
|
|
1276
|
+
| 方法 | 说明 |
|
|
1277
|
+
|---|---|
|
|
1278
|
+
| `createReportWorkbook()` | 空白基底,从零构建(每个 Sheet 都是新建) |
|
|
1279
|
+
| `createReportWorkbook(templatePath)` | 以工程内已有 xlsx 为基底做增量编辑(路径相对工程目录,不得逃逸);未被操作触及的部件(条件格式、图片、冻结、数据验证、样式)原样保留 |
|
|
1280
|
+
| `.addSheet(name, fn)` | 新建 Sheet;基底模式下同名 Sheet 已存在则 pack 失败并提示改用 editSheet |
|
|
1281
|
+
| `.editSheet(name, fn)` | 编辑基底中已存在的 Sheet;仅基底模式可用,Sheet 不存在则 pack 失败并提示改用 addSheet |
|
|
1282
|
+
| `fn(sheet)` 内 | 两种模式方法完全同名(setValue/bind*/setDynamicFormula/setContextText/merge/setColumnWidth/setRowHeight/setFreeze/setConditionalFormat/setImage/...) |
|
|
1283
|
+
| `sheet.clearCell(cell)` | 仅 editSheet 可用:清除单元格内容(样式保留) |
|
|
1284
|
+
| `sheet.unmerge(range)` | 仅 editSheet 可用:拆开合并区(配合重新 `merge`) |
|
|
1285
|
+
| `sheet.insertRows(startRow, count?)` / `removeRows(startRow, count?)` | 仅 editSheet 可用:插入/删除整行。合并区、真实公式等 xlsx 部件由引擎自动调整,**Pro 模板表达式**(动态公式单元格引用、`C=`/`F=` 父格)同步自动重写;删除仍被其他模板格引用的行会以 dangling-reference 报错拒绝 |
|
|
1286
|
+
| `sheet.insertCols(startCol, count?)` / `removeCols(startCol, count?)` | 仅 editSheet 可用:插入/删除整列(列可写字母 `"B"` 或数字),引用重写与行操作相同 |
|
|
1287
|
+
| `sheet.setCellStyle(cellOrRange, style)` | 仅 editSheet 可用:**合并语义**改样式——只覆盖 style 对象里给出的属性,未给的属性(如原有 bold/字号)保留;与各操作自带 style 参数的整体替换语义不同 |
|
|
1288
|
+
| `{ overwrite: true }` | editSheet 中操作落点已有 `{{...}}`/`&=` 模板表达式时必须显式声明,否则 pack 拒绝(防止静默丢绑定)。绑定类/`setDynamicFormula`/`setContextText` 写在 options 里;`setValue`/`setFormula`/`setRow`/`setColumn` 通过第 4 个参数传:`setValue(cell, value, style, { overwrite: true })`。从零 addSheet 中传 overwrite 会被校验拒绝 |
|
|
1289
|
+
|
|
1290
|
+
结构编辑的书写约定:`insertRows`/`insertCols` 之后的操作坐标一律按**移位后的最终位置**书写(操作按链式顺序真实执行)。dev29 实证:财务固定科目表插"口径"列 + 插科目行后,右侧三列 `bindGrandTotal`、下方 `B3-B4` 派生公式与 `IF` 费用率公式全部自动重写且数值正确;标题合并区随插列自动扩展。
|
|
1291
|
+
|
|
1292
|
+
**多轮编辑必须累积操作**:`createReportWorkbook(templatePath)` 的基底是本地 `templates/` 快照,每次发布应用的是「基底 + 当前 editSheet 全部操作」。对同一工程做第二轮修改时,要在原操作序列后**追加**新操作(坐标按前序操作移位后书写),不能只保留新一轮操作——否则上一轮修改会从线上消失(dev29 实测踩过)。想从头写增量时,先重新 `checkout` 刷新本地基底。
|
|
1293
|
+
|
|
1294
|
+
批量写入与页面级设置(对齐 sheet_engine 指令集,addSheet/editSheet 通用):
|
|
1295
|
+
|
|
1296
|
+
| 方法 | 说明 |
|
|
1297
|
+
|---|---|
|
|
1298
|
+
| `sheet.setRow(startCell, values, style?)` | 从 startCell 起横向批量写标量值,数组元素 `null` 跳过该格;style 应用到每个写入格。表头行一行写完 |
|
|
1299
|
+
| `sheet.setColumn(startCell, values, style?)` | 纵向批量写(固定科目列一次写完) |
|
|
1300
|
+
| `sheet.setColumnWidth(col, width)` | col 支持 `"B"` 或范围 `"B:D"`(整段同宽) |
|
|
1301
|
+
| `sheet.setSheetDefaults({ defaultColumnWidth?, defaultRowHeight?, defaultRowHidden?, showGridLines? })` | 未显式设置宽高的行列默认值(编译时自动先于其他操作应用,脚本内位置不影响结果);`defaultRowHidden: true` 使未显式声明的行默认隐藏(OOXML zeroHeight);`showGridLines: false` 隐藏工作表网格线(OOXML sheetView showGridLines="0",无边框单元格之间不再画浅灰线,报表类版式常用;decompile 原样还原) |
|
|
1302
|
+
| `sheet.setHyperlink(cell, url, { tooltip?, display? })` | **静态格**超链接(标题/返回目录等固定格;dev29 实证 GcExcel 渲染保留);`display` 为链接可见文本(格无自身值时用户看到的就是它)。超链不随模板扩展复制——扩展区行级链接用 `setDynamicFormula` + `HYPERLINK("url","文本")`(dev29 实证展开为 shared formula 每行可点) |
|
|
1303
|
+
|
|
1304
|
+
样式对象在原有 `bold/italic/fontSize/fontColor/backgroundColor/horizontalAlignment/verticalAlignment/wrapText/numberFormat/borderColor/diagonalDown` 基础上新增(compile/decompile/setCellStyle 合并三端一致,roundtrip 有测试锁定):
|
|
1305
|
+
|
|
1306
|
+
| 属性 | 说明 |
|
|
1307
|
+
|---|---|
|
|
1308
|
+
| `underline: true \| "single" \| "double"` | 下划线(会计合计线常用 double) |
|
|
1309
|
+
| `strikeout: true` | 删除线 |
|
|
1310
|
+
| `fontFamily: "宋体"` | 指定字体 |
|
|
1311
|
+
| `indent: 1` | 缩进级别(利润表"减:营业成本"科目层级) |
|
|
1312
|
+
| `border: { style, color? }` | 四边统一边框;style 取 `thin/medium/thick/double/dashed/dotted/hair`,color 缺省黑 |
|
|
1313
|
+
| `borderTop/borderRight/borderBottom/borderLeft: { style, color? }` | 按边框(合计行"下双线"用 `borderBottom: { style: "double" }`) |
|
|
1314
|
+
|
|
1315
|
+
`borderColor: "#RRGGBB"` 仍是"四边 thin"的简写。
|
|
1316
|
+
|
|
1317
|
+
挂载入口统一为 `report.setWorkbook(workbook)`,与 `.setTemplate(path)`(引用现成 xlsx 不做任何修改)二选一。基底模式 pack 时先把操作叠加到基底编译出临时 xlsx,再执行与外部模板完全相同的校验(引用进查询区、父格图环检测、分页约束);从零模式则直接做 AST 级校验(错误信息带单元格)。`guanvis diff` 会把基底编辑的每条指令以 `card.template["Sheet"].op[i]` 逐条列出作为模板级变更描述。发布成功后 CLI 自动把工程 JS 的 `.setTemplateVersion(N)` 改写为 N+1,避免下一轮模板编辑命中服务端同版本缓存静默不生效。
|
|
1318
|
+
|
|
1319
|
+
主标题、表头和明细行必须形成明确的高度层级。Excel 默认行高约 15pt,不适合 16px 以上的合并标题;推荐主标题 32–36pt、列头 22–26pt、普通明细 18–22pt,并给标题设置 `verticalAlignment: "center"`:
|
|
1320
|
+
|
|
1321
|
+
```javascript
|
|
1322
|
+
sheet.merge("A1:F1")
|
|
1323
|
+
.setValue("A1", "销售经营月报", {
|
|
1324
|
+
fontSize: 16,
|
|
1325
|
+
bold: true,
|
|
1326
|
+
horizontalAlignment: "center",
|
|
1327
|
+
verticalAlignment: "center"
|
|
1328
|
+
})
|
|
1329
|
+
.setRowHeight(1, 34)
|
|
1330
|
+
.setRowHeight(2, 25);
|
|
1331
|
+
```
|
|
1332
|
+
|
|
1333
|
+
如果标题合并了两行,应按合并后的总高度判断,例如两行各 30pt;不要再额外叠加单行 36pt。
|
|
1334
|
+
|
|
1335
|
+
```javascript
|
|
1336
|
+
var view = createCard(ChartType.DATA_GRID, "sales")
|
|
1337
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
1338
|
+
.bindDataset(DS)
|
|
1339
|
+
.addRow(f("区域"))
|
|
1340
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
1341
|
+
|
|
1342
|
+
var workbook = createReportWorkbook().addSheet("月报", function (sheet) {
|
|
1343
|
+
sheet.merge("A1:B1")
|
|
1344
|
+
.setValue("A1", "销售月报", {
|
|
1345
|
+
fontSize: 16, bold: true,
|
|
1346
|
+
horizontalAlignment: "center", verticalAlignment: "center"
|
|
1347
|
+
})
|
|
1348
|
+
.setRowHeight(1, 34);
|
|
1349
|
+
sheet.bindDimension("A3", reportField("sales", "区域"));
|
|
1350
|
+
sheet.bindMetric("B3", reportField("sales", "销售额"), {
|
|
1351
|
+
aggregate: "SUM", context: "A3", numberFormat: "#,##0.00"
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
registerComplexReportPro(createComplexReportPro("销售月报")
|
|
1356
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
1357
|
+
.setWorkbook(workbook)
|
|
1358
|
+
.addDataView("sales", view)
|
|
1359
|
+
.build());
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
分页与两级小计、总计组合的核心模板结构如下:
|
|
1363
|
+
|
|
1364
|
+
```javascript
|
|
1365
|
+
sheet.bindDimension("A3", reportField("orders", "城市"), {
|
|
1366
|
+
countPerPage: 20
|
|
1367
|
+
});
|
|
1368
|
+
sheet.bindDimension("B3", reportField("orders", "客户"), { context: "A3" });
|
|
1369
|
+
sheet.setContextText("A4", "城市小计", { context: "A3" }, subtotalStyle);
|
|
1370
|
+
sheet.bindSubtotal("D4", reportField("orders", "金额"), {
|
|
1371
|
+
aggregate: "SUM", context: "A4", numberFormat: "#,##0.00"
|
|
1372
|
+
});
|
|
1373
|
+
sheet.bindGrandTotal("D5", reportField("orders", "金额"), {
|
|
1374
|
+
aggregate: "SUM", numberFormat: "#,##0.00"
|
|
1375
|
+
});
|
|
1376
|
+
```
|
|
1377
|
+
|
|
1378
|
+
发布后必须执行 `guancli card preview <proCardId> -o result.xlsx`,并打开结果确认数据已展开、没有残留 `{{...}}` 模板表达式;因为只有 GcExcel 能验证最终模板语义。完整协议、checkout 和线上能力矩阵见 `designs/complex-report-pro.md`。
|
|
1379
|
+
|
|
1380
|
+
### DuPontBuilder(杜邦分析图)
|
|
1381
|
+
|
|
1382
|
+
杜邦分析图不是普通 `ChartType`,而是 BI 的 `LAYOUT` 卡片(`cdType=9`),meta 结构为 `{ layoutType: "DU_PONT", layout: ... }`。guanvis 用 `createDuPontChart()` 创建父卡片,用普通 `CardBuilder` 创建每个节点中的指标卡。
|
|
1383
|
+
|
|
1384
|
+
| 方法 | 说明 |
|
|
1385
|
+
|------|------|
|
|
1386
|
+
| `createDuPontChart(name)` | 创建杜邦分析图父卡片 |
|
|
1387
|
+
| `.setId(cardId)` | **必填**。设置杜邦父卡片 ID |
|
|
1388
|
+
| `.setRoot(cardBuilder, options?)` | 设置根节点。`cardBuilder` 必须是已 `.setId()` 的普通图表卡片,通常为 `KPI_CARD` |
|
|
1389
|
+
| `.addChild(parentCardOrId, childCardBuilder, options?)` | 给指定父节点添加子节点。`parentCardOrId` 可传父节点的 `CardBuilder` 或 cardId |
|
|
1390
|
+
| `.addChildren(parentCardOrId, childCardBuilders, optionsOrOptionsList?)` | 批量添加子节点 |
|
|
1391
|
+
| `.setLayout({})` | 仅用于创建空杜邦图占位;非空 raw layout 不支持,请用 `.setRoot()` / `.addChild()` 自动注册子卡 |
|
|
1392
|
+
| `.setDescription(desc)` | 描述 |
|
|
1393
|
+
| `.setRawSettings(key, value)` | 原始 settings |
|
|
1394
|
+
| `.build()` | 构建(触发验证) |
|
|
1395
|
+
|
|
1396
|
+
`options` 支持:
|
|
1397
|
+
|
|
1398
|
+
| 属性 | 说明 |
|
|
1399
|
+
|------|------|
|
|
1400
|
+
| `operation` | 记录在父节点 `operations` 中的运算符,如 `"*"`, `"/"`, `"+"`, `"-"` |
|
|
1401
|
+
| `bgColor` | 节点背景色 |
|
|
1402
|
+
| `style` | 节点样式覆盖,支持 `titleFont`、`kpiFont`、`bgColor`、`kpiLayout`、`collapse`、`width`、`height` 等 |
|
|
1403
|
+
|
|
1404
|
+
`operation` 使用 `DuPontOperation.ADD` / `SUBTRACT` / `MULTIPLY` / `DIVIDE` / `NONE`;也兼容 `"*"`、`"/"` 并自动转成 BI 前端使用的 `"×"`、`"÷"`。`kpiLayout` 使用 `DuPontKpiLayout.TILE`(平铺式)或 `DuPontKpiLayout.COMPACT`(紧凑式)。
|
|
1405
|
+
|
|
1406
|
+
```javascript
|
|
1407
|
+
var roe = createCard(ChartType.KPI_CARD, "净资产收益率")
|
|
1408
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
1409
|
+
.bindDataset(DS)
|
|
1410
|
+
.addMetric(f("净利润", { aggrType: AggrType.SUM }));
|
|
1411
|
+
|
|
1412
|
+
var margin = createCard(ChartType.KPI_CARD, "销售净利率")
|
|
1413
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
1414
|
+
.bindDataset(DS)
|
|
1415
|
+
.addMetric(f("销售收入", { aggrType: AggrType.SUM }));
|
|
1416
|
+
|
|
1417
|
+
var turnover = createCard(ChartType.KPI_CARD, "资产周转率")
|
|
1418
|
+
.setId("cccccccccccccccccccccccc")
|
|
1419
|
+
.bindDataset(DS)
|
|
1420
|
+
.addMetric(f("资产总额", { aggrType: AggrType.SUM }));
|
|
1421
|
+
|
|
1422
|
+
var dupont = createDuPontChart("杜邦分析")
|
|
1423
|
+
.setId("dddddddddddddddddddddddd")
|
|
1424
|
+
.setRoot(roe, { style: { kpiLayout: DuPontKpiLayout.COMPACT } })
|
|
1425
|
+
.addChild(roe, margin, { operation: "*" })
|
|
1426
|
+
.addChild(roe, turnover, { operation: "*" });
|
|
1427
|
+
|
|
1428
|
+
registerDuPontChart(dupont.build());
|
|
1429
|
+
```
|
|
1430
|
+
|
|
1431
|
+
页面布局中放杜邦父卡片即可,杜邦子卡片会以 `pId=父卡片ID` 打包,不要再单独放进页面布局:
|
|
1432
|
+
|
|
1433
|
+
```javascript
|
|
1434
|
+
var page = createPage("财务分析")
|
|
1435
|
+
.setId("eeeeeeeeeeeeeeeeeeeeeeee")
|
|
1436
|
+
.addFullWidthCard("dddddddddddddddddddddddd", 10);
|
|
1437
|
+
registerPage(page.build());
|
|
1438
|
+
```
|
|
1439
|
+
|
|
1440
|
+
本地校验会检查:
|
|
1441
|
+
- 杜邦父卡片必须是 `LAYOUT` payload,`layoutType` 必须是 `DU_PONT`
|
|
1442
|
+
- layout 节点必须有 `id` / `cardId`
|
|
1443
|
+
- layout 中引用的 `cardId` 必须是当前杜邦父卡片名下的普通子卡片,不能引用无关顶层卡片、selector、其它 layout 或自定义图表 data view
|
|
1444
|
+
- 节点 `id` 不允许重复
|
|
1445
|
+
|
|
1446
|
+
**内嵌第三方 JS 库**(如 Vega-Lite、D3 等):
|
|
1447
|
+
|
|
1448
|
+
SDK 模式的 iframe 沙箱**阻止从外部 CDN 加载脚本**(sandbox/CSP 限制)。`addLib()` 添加的 CDN URL 在安全模式下不生效。正确做法是:
|
|
1449
|
+
|
|
1450
|
+
1. 将第三方库的 `.min.js` 文件下载到 `charts/` 目录
|
|
1451
|
+
2. 在渲染 JS 文件中用 `__asset_text__` 内嵌并通过 `new Function()` 执行
|
|
1452
|
+
|
|
1453
|
+
```javascript
|
|
1454
|
+
// 内嵌 Vega-Lite 库(下载到 charts/ 目录后引用)
|
|
1455
|
+
var _vegaSrc = __asset_text("./vega.min.js")__;
|
|
1456
|
+
var _vegaLiteSrc = __asset_text("./vega-lite.min.js")__;
|
|
1457
|
+
var _vegaEmbedSrc = __asset_text("./vega-embed.min.js")__;
|
|
1458
|
+
(new Function(_vegaSrc))();
|
|
1459
|
+
(new Function(_vegaLiteSrc))();
|
|
1460
|
+
(new Function(_vegaEmbedSrc))();
|
|
1461
|
+
|
|
1462
|
+
// 之后即可使用 vegaEmbed(...)
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1465
|
+
**注意**:内嵌大型库会增加资源包体积(Vega-Lite 全套约 800KB),但确保在所有环境下都能正常运行。`addLib()` 仅在未开启安全模式的环境中有效,不推荐用于生产。
|
|
1466
|
+
|
|
1467
|
+
**Vega-Lite 地图(geoshape)的坑**:Vega-Lite 的 `geoshape` mark 在使用 inline GeoJSON 数据时,projection 的自动 fit 行为不可靠,常导致地图渲染为空白。推荐的替代方案:
|
|
1468
|
+
|
|
1469
|
+
- **方案 A(推荐)**:只内嵌 `vega.min.js`,手动实现 Mercator 投影 + SVG 渲染。`vega.min.js` 中不直接暴露 `geoMercator` 等 d3-geo API,需自行实现投影公式:
|
|
1470
|
+
```javascript
|
|
1471
|
+
function toRad(deg) { return deg * Math.PI / 180; }
|
|
1472
|
+
function mercX(lon) { return toRad(lon); }
|
|
1473
|
+
function mercY(lat) { return Math.log(Math.tan(Math.PI / 4 + toRad(lat) / 2)); }
|
|
1474
|
+
// 计算 projected bounding box 后用 fitSize 逻辑缩放到容器
|
|
1475
|
+
```
|
|
1476
|
+
关键:x 和 y 都必须转换到同一单位空间(弧度),否则宽高比会错误。
|
|
1477
|
+
- **方案 B**:使用 `ECHARTS_LITE` 子类型代替 SDK,ECharts 的 `registerMap` + `visualMap` 对 inline GeoJSON 支持更好。
|
|
1478
|
+
- **方案 C**:如果必须用 Vega-Lite,`data.values` 必须是完整的 FeatureCollection 对象(不是 features 数组),`format` 设为 `{"type": "json", "property": "features"}`。参考 [vega-lite#3432](https://github.com/vega/vega-lite/issues/3432)。
|
|
1479
|
+
- 只有完整格式 `__asset_text("path")__` 才会被替换,注释或字符串中的 `__asset_text__` 文字不受影响
|
|
1480
|
+
- **来源标注**:对于从网上下载的资源文件(如 GeoJSON),在占位符上方用注释标注来源 URL,便于后续维护和溯源:
|
|
1481
|
+
|
|
1482
|
+
```javascript
|
|
1483
|
+
// source: https://cdn.jsdelivr.net/npm/vega-datasets@2/data/us-10m.json
|
|
1484
|
+
var geoData = JSON.parse(__asset_text("./us-10m.json")__);
|
|
1485
|
+
```
|
|
1486
|
+
|
|
1487
|
+
**SDK 子类型示例**(iframe 模式,使用 `gd-plugin.js`):
|
|
1488
|
+
|
|
1489
|
+
`card_01_custom.js`(card 脚本):
|
|
1490
|
+
```javascript
|
|
1491
|
+
var dataView = createCard(ChartType.DATA_GRID, "数据视图")
|
|
1492
|
+
.setId("a484352b7a76776db5f534df")
|
|
1493
|
+
.bindDataset(DS)
|
|
1494
|
+
.addRow(f("类别"))
|
|
1495
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
1496
|
+
|
|
1497
|
+
var chart = createCustomChart("自定义柱状图")
|
|
1498
|
+
.setId("b484352b7a76776db5f534df")
|
|
1499
|
+
.setSubType(CustomChartSubType.SDK)
|
|
1500
|
+
.loadContent("charts/my_chart")
|
|
1501
|
+
.addDataView(dataView);
|
|
1502
|
+
|
|
1503
|
+
registerCustomChart(chart.build());
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
`charts/my_chart.html`:
|
|
1507
|
+
```html
|
|
1508
|
+
<div id="container"></div>
|
|
1509
|
+
<script>loadBuiltinResourceByName('echarts')</script>
|
|
1510
|
+
```
|
|
1511
|
+
|
|
1512
|
+
`charts/my_chart.css`:
|
|
1513
|
+
```css
|
|
1514
|
+
#container { width: 100%; height: 100%; }
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
`charts/my_chart.js`(运行在 BI iframe 中的渲染代码):
|
|
1518
|
+
```javascript
|
|
1519
|
+
var myChart = echarts.init(document.getElementById('container'));
|
|
1520
|
+
function renderChart(data, clickFunc, config) {
|
|
1521
|
+
// data[0] = 第一个数据视图的列数据: [{name:"类别", data:[...]}, {name:"销售额", data:[...]}]
|
|
1522
|
+
var cols = data[0] || [];
|
|
1523
|
+
myChart.setOption({
|
|
1524
|
+
xAxis: { type: 'category', data: (cols[0] || {}).data || [] },
|
|
1525
|
+
yAxis: { type: 'value' },
|
|
1526
|
+
series: [{ type: 'bar', data: (cols[1] || {}).data || [] }],
|
|
1527
|
+
color: config.colors
|
|
1528
|
+
});
|
|
1529
|
+
myChart.resize();
|
|
1530
|
+
}
|
|
1531
|
+
new GDPlugin().init(renderChart);
|
|
1532
|
+
```
|
|
1533
|
+
|
|
1534
|
+
**ECHARTS_LITE 子类型示例**(无 iframe,直接操作 ECharts,仅适用于纯 ECharts 场景):
|
|
1535
|
+
|
|
1536
|
+
`card_01_echarts.js`(card 脚本):
|
|
1537
|
+
```javascript
|
|
1538
|
+
var dataView = createCard(ChartType.DATA_GRID, "数据视图")
|
|
1539
|
+
.setId("c484352b7a76776db5f534df")
|
|
1540
|
+
.bindDataset(DS)
|
|
1541
|
+
.addRow(f("类别"))
|
|
1542
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
1543
|
+
|
|
1544
|
+
var chart = createCustomChart("ECharts 柱状图")
|
|
1545
|
+
.setId("d484352b7a76776db5f534df")
|
|
1546
|
+
.setSubType(CustomChartSubType.ECHARTS_LITE)
|
|
1547
|
+
.loadContent("charts/echarts_bar")
|
|
1548
|
+
.addDataView(dataView);
|
|
1549
|
+
|
|
1550
|
+
registerCustomChart(chart.build());
|
|
1551
|
+
```
|
|
1552
|
+
|
|
1553
|
+
`charts/echarts_bar.js`(ECharts 渲染代码,HTML 和 CSS 文件可省略):
|
|
1554
|
+
```javascript
|
|
1555
|
+
// data[0] = [{name:"类别", data:[...]}, {name:"销售额", data:[...]}]
|
|
1556
|
+
var cols = data[0] || [];
|
|
1557
|
+
var categories = (cols[0] || {}).data || [];
|
|
1558
|
+
var values = (cols[1] || {}).data || [];
|
|
1559
|
+
option = {
|
|
1560
|
+
xAxis: { type: "category", data: categories },
|
|
1561
|
+
yAxis: { type: "value" },
|
|
1562
|
+
series: [{ type: "bar", data: values }]
|
|
1563
|
+
};
|
|
1564
|
+
```
|
|
1565
|
+
|
|
1566
|
+
> **注意**:ECHARTS_LITE 模式下,脚本中的 `data`、`config`、`clickFunc`、`utils` 是预定义变量。将 ECharts option 赋值给 `option` 变量即可渲染。**不要使用 `new GDPlugin().init()`**,那是 SDK(iframe)模式的 API。
|
|
1567
|
+
|
|
1568
|
+
**ECHARTS_LITE 自定义地图示例**(使用 `__asset_text__` 内嵌 GeoJSON):
|
|
1569
|
+
|
|
1570
|
+
`card_01_map.js`(card 脚本):
|
|
1571
|
+
```javascript
|
|
1572
|
+
var dataView = createCard(ChartType.DATA_GRID, "地图数据视图")
|
|
1573
|
+
.setId("c584352b7a76776db5f534df")
|
|
1574
|
+
.bindDataset(DS)
|
|
1575
|
+
.addRow(f("省/自治区"))
|
|
1576
|
+
.addMetric(calcField("利润率", "SUM([利润])/SUM([销售额])"));
|
|
1577
|
+
|
|
1578
|
+
var chart = createCustomChart("各省利润率(ECharts)")
|
|
1579
|
+
.setId("d584352b7a76776db5f534df")
|
|
1580
|
+
.setSubType(CustomChartSubType.ECHARTS_LITE)
|
|
1581
|
+
.loadContent("charts/profit_map")
|
|
1582
|
+
.addDataView(dataView);
|
|
1583
|
+
|
|
1584
|
+
registerCustomChart(chart.build());
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
`charts/profit_map.js`(ECharts 地图渲染,需配套 `china.json`):
|
|
1588
|
+
```javascript
|
|
1589
|
+
// source: guandata-web 内置地图或 https://geo.datav.aliyun.com/...
|
|
1590
|
+
var chinaGeoJSON = JSON.parse(__asset_text("./china.json")__);
|
|
1591
|
+
|
|
1592
|
+
var cols = data[0] || [];
|
|
1593
|
+
var names = (cols[0] || {}).data || [];
|
|
1594
|
+
var values = (cols[1] || {}).data || [];
|
|
1595
|
+
|
|
1596
|
+
var mapData = [];
|
|
1597
|
+
for (var i = 0; i < names.length; i++) {
|
|
1598
|
+
mapData.push({ name: names[i], value: +(values[i]) || 0 });
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
echarts.registerMap("china", chinaGeoJSON);
|
|
1602
|
+
|
|
1603
|
+
option = {
|
|
1604
|
+
tooltip: { trigger: "item" },
|
|
1605
|
+
visualMap: { min: -0.3, max: 0.3, calculable: true,
|
|
1606
|
+
inRange: { color: ["#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"] } },
|
|
1607
|
+
series: [{ type: "map", map: "china", label: { show: true, fontSize: 10 }, data: mapData }]
|
|
1608
|
+
};
|
|
1609
|
+
```
|
|
1610
|
+
|
|
1611
|
+
> **适用场景**:ECHARTS_LITE 自定义地图仅适用于不需要其他 JS 库的简单场景。Tableau 迁移场景应使用 **SDK 模式**(支持 Vega-Lite 等更灵活的库)。中国地图优先使用 `BASIC_MAP` 内置图表。
|
|
1612
|
+
|
|
1613
|
+
#### 编辑已有自定义图表(checkout 反编译 + attachCard 内容编辑)
|
|
1614
|
+
|
|
1615
|
+
`guanvis checkout` 遇到普通自定义图表(cdType=CUSTOM,subType 为 `SDK` 或 `ECHARTS_LITE`,对照后端 CustomCardType 真实枚举)时,会把线上内容**反编译成可编辑源文件**(pack 内联流程的精确逆变换):
|
|
1616
|
+
|
|
1617
|
+
```
|
|
1618
|
+
project/
|
|
1619
|
+
├── card_02_<cdId>.js ← attachCard(...).loadContent("charts/<cdId>")
|
|
1620
|
+
└── charts/
|
|
1621
|
+
├── <cdId>.js ← 图表脚本(必生成;可直接编辑)
|
|
1622
|
+
├── <cdId>.html / <cdId>.css ← 仅线上内容非空时生成
|
|
1623
|
+
└── <cdId>_assets/ ← 从脚本/HTML 抽取的内嵌资源
|
|
1624
|
+
├── asset_01.json ← 原 __asset_text 内联的大 JSON/文本
|
|
1625
|
+
└── asset_02.png ← 原 __asset_base64 内联的图片
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
- **内嵌资源抽取**:脚本中 ≥2KB 的内联字符串字面量(GeoJSON、base64 图片等)会被抽取回独立文件,脚本恢复为 `__asset_text("./<cdId>_assets/asset_01.json")__` / `__asset_base64("./…/asset_02.png")__` 占位符形式。每个抽取都经过「重新内联后与原文逐字节相等」验证,验证不过就放弃抽取仅还原原文——未编辑的 checkout 工程 `guanvis diff` 恒为空。
|
|
1629
|
+
- **编辑方式**:直接改 `charts/<cdId>.js`(或 .html/.css、替换 assets 里的资源文件),pack/publish 时经 `loadContent` 自动回填进 `card.meta`,diff 会显示 `card.meta.script` 的路径级变更。占位符引用的资源文件缺失、越界或不可读时 pack/publish **直接报错**,不会把 `__asset_text(...)__` 残留发布上线。
|
|
1630
|
+
- `.html`/`.css` 文件**不存在时保留线上原值**;要清空内容需写入空文件。重跑 checkout 会重建 `charts/<cdId>.*` 与 `<cdId>_assets/`(本地未发布的脚本修改会被线上版本覆盖;`--refresh-base` 则不触碰 charts/)。
|
|
1631
|
+
- **不做反编译的 CUSTOM 子类型**(checkout 保持普通 attachCard,内容编辑 API 一律报错):`COMPLEX_REPORT` 走 Pro 专属流程;`PLUGIN`/`PLUGIN_LITE` 的内容事实源是 `pluginId` 引用的插件市场资源,本地改副本会与插件脱钩并可能破坏按插件渲染的逻辑,应更新插件本体;`REPORT_FORM` 是表格填报模板配置,不是渲染脚本。
|
|
1632
|
+
|
|
1633
|
+
`AttachedCardBuilder` 的内容编辑 API(仅对 subType 为 `SDK`/`ECHARTS_LITE` 的自定义图表卡有效,其余 cdType/subType 一律报错):
|
|
1634
|
+
|
|
1635
|
+
| 方法 | 说明 |
|
|
1636
|
+
|------|------|
|
|
1637
|
+
| `.loadContent(baseName)` | 从 `<baseName>.js/.html/.css` 加载内容(`.js` 必须存在,`.html`/`.css` 缺失时保留 base 值);checkout 反编译工程默认使用这条链路 |
|
|
1638
|
+
| `.setScript(script)` / `.setHtml(html)` / `.setCss(css)` | 内联覆盖单项内容;与 `loadContent` 同时使用时内联值优先(会有 warning) |
|
|
1639
|
+
| `.setContent(html, css, script)` | 一次性内联设置三项 |
|
|
1640
|
+
| `.setLibs([url, ...])` / `.addLib(url)` | 替换 / 追加外部 JS 库列表 |
|
|
1641
|
+
|
|
1642
|
+
所有通过 `loadContent`/`setScript`/`setHtml`/`setCss` 写入的内容都会走 `__asset_text`/`__asset_base64` 占位符替换(相对内容文件所在目录解析),与 `createCustomChart` 的行为一致。
|
|
1643
|
+
|
|
1644
|
+
### 枚举常量
|
|
1645
|
+
|
|
1646
|
+
| 枚举 | 常用值 | 说明 |
|
|
1647
|
+
|------|--------|------|
|
|
1648
|
+
| `ChartType` | `BASIC_COLUMN`, `BASIC_BAR`, `BASIC_LINE`, `PIE`, `PIVOT_TABLE`, `DETAIL_TABLE`, `KPI_CARD`, `BASIC_MAP`, `WORLD_MAP`, `POINT_MAP`, `BUBBLE_MAP` 等 74 种 | 图表类型(与后端 ChartType.java 对应)。地图类型使用 `addRow()` 放地理维度。后端 `GANTT(74)` 未提供:guandata-web 前端尚无甘特图渲染实现,创建会产出前端不能渲染的卡片;attach 回写已支持透传 GANTT 卡 |
|
|
1649
|
+
| `AggrType` | `SUM`, `AVG`, `COUNT`(=CNT), `COUNT_DISTINCT`(=CNT_DISTINCT), `MIN`, `MAX` | 聚合类型 |
|
|
1650
|
+
| `FieldType` | `STRING`, `INT`, `LONG`, `DOUBLE`, `FLOAT`, `DATE`, `BOOL`, `DECIMAL` | 字段数据类型 |
|
|
1651
|
+
| `SortOrder` | `ASC`, `DESC` | 排序方向 |
|
|
1652
|
+
| `MiniChartType` | `LINE`, `COLUMN`, `PIE`, `PROGRESS` | 透视表字段迷你图类型 |
|
|
1653
|
+
| `MiniChartSort` | `ASC`, `DESC` | 迷你图维度排序方向 |
|
|
1654
|
+
| `MapRegion` | `COUNTRY`, `PROVINCE`, `CITY`, `AUTO` | 中国行政类地图的显示范围 |
|
|
1655
|
+
| `MapSymbol` | `CIRCLE`, `DIAMOND`, `SQUARE`, `TRIANGLE`, `TRIANGLE_DOWN` | 符号行政地图的内置符号 |
|
|
1656
|
+
| `Granularity` | `NONE`, `YEAR`, `QUARTER`, `MONTH`, `WEEK`, `DAYOFWEEK`, `DAY`, `HOUR`, `MINUTE`, `SECOND` | 日期粒度 |
|
|
1657
|
+
| `GrandTotalPosition` | `LEFT`, `RIGHT`, `TOP`, `BOTTOM` | 表格总计位置;行总计用左右,列总计用上下 |
|
|
1658
|
+
| `ContentSpaceSize` | `SMALL`, `MIDDLE`, `LARGE` | 卡片内容间距 |
|
|
1659
|
+
| `DynamicFieldOrder` | `PRESET`, `CLICK` | 动态字段默认顺序;`PRESET` 按候选顺序,`CLICK` 按用户选择顺序 |
|
|
1660
|
+
| `FilterType` | `IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `NOT_STARTSWITH`, `ENDSWITH`, `NOT_ENDSWITH`, `IS_NULL`, `NOT_NULL` | 筛选条件类型 |
|
|
1661
|
+
| `FilterLevel` | `DETAIL`(明细), `AGGREGATION`(聚合), `RESULT`(结果) | 筛选级别 |
|
|
1662
|
+
| `NumberFormat` | `.number()`, `.currency()`, `.percentage()`, `.auto()`, `.custom()` | 数值格式化工厂 |
|
|
1663
|
+
| `SelectorType` | `DS_ELEMENTS`(默认), `TEXT_MATCH`, `DS_INTERVAL`, `CALENDAR`, `TIME_MACRO`, `PARAMETER`, `TREE`, `LAYER_TREE`, `COMBINATION` | 筛选器类型 |
|
|
1664
|
+
| `SelectorDisplay` | `SEARCH_LIST`(单选下拉), `SEARCH_BOX`(多选下拉), `CHECKBOX`(复选框), `RADIO`(单选框), `BUTTON_GROUP`(按钮组) | 筛选器展示类型,不设置时根据 multiSelect 自动推断 |
|
|
1665
|
+
| `TreeSelectorDisplay` | `SEARCH_BOX`, `FLAT` | 树状筛选器的展示类型 |
|
|
1666
|
+
| `CombinationSelectorDisplay` | `DEFAULT`, `STANDARD` | 组合条件筛选器的展示类型 |
|
|
1667
|
+
| `Combination` | `.condition(field, filterType, values, { not }?)`, `.and(...)`, `.or(...)` | 组合条件默认值 AST 构造器 |
|
|
1668
|
+
| `SelectorDefaultType` | `FIRST_PICK`, `FIXED_VALUE`, `ALL`(默认,全部/不筛选) | 筛选器默认值类型 |
|
|
1669
|
+
| `TabTitlePosition` | `TOP`, `LEFT` | Tab 总标题位置 |
|
|
1670
|
+
| `LayoutMarginType` | `NONE`, `SPACE`, `DIVIDE` | Tab panel 与卡片组的卡片间距模式 |
|
|
1671
|
+
| `CardType` | `CHART`(0), `TEXT`(1), `IFRAME`(2), `PICTURE`(4), `SELECTOR`(6), `LAYOUT`(9) | 卡片类型(内部使用,通常不需要直接引用) |
|
|
1672
|
+
| `ImageSourceType` | `OUTSIDE_LINK`(1), `LOCAL_IMAGE`(2) | 图片来源类型 |
|
|
1673
|
+
| `ImageRenderType` | `RATIO`(1,原比例), `STRETCH`(2,拉伸填满), `FIT_TO_CONTENT`(3,自适应内容) | 图片渲染模式 |
|
|
1674
|
+
| `CustomChartSubType` | `SDK`(iframe,首选), `ECHARTS_LITE`(原生 ECharts) | 自定义图表子类型 |
|
|
1675
|
+
| `DuPontKpiLayout` | `TILE`(平铺式), `COMPACT`(紧凑式) | 杜邦节点指标布局 |
|
|
1676
|
+
| `DuPontOperation` | `NONE`, `ADD`, `SUBTRACT`, `MULTIPLY`, `DIVIDE` | 杜邦父节点到各子节点的运算符 |
|