@guandata/guanvis 0.1.16
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/CHANGELOG.md +44 -0
- package/README.md +85 -0
- package/bin/run.js +87 -0
- package/binaries/guanvis-darwin-arm64 +0 -0
- package/binaries/guanvis-darwin-x64 +0 -0
- package/binaries/guanvis-linux-arm64 +0 -0
- package/binaries/guanvis-linux-x64 +0 -0
- package/binaries/guanvis-win32-x64.exe +0 -0
- package/package.json +41 -0
- package/skills/guanvis/SKILL.md +334 -0
- package/skills/guanvis/evals/china_map/card_01_basic_map.js +13 -0
- package/skills/guanvis/evals/china_map/card_02_world_map.js +10 -0
- package/skills/guanvis/evals/china_map/card_03_point_map.js +12 -0
- package/skills/guanvis/evals/china_map/page.js +10 -0
- package/skills/guanvis/evals/china_map/schema.js +10 -0
- package/skills/guanvis/evals/comparative_mvp_roundtrip/README.md +30 -0
- package/skills/guanvis/evals/comparative_mvp_roundtrip/card_01_comparative_mvp.js +72 -0
- package/skills/guanvis/evals/comparative_mvp_roundtrip/page.js +6 -0
- package/skills/guanvis/evals/comparative_mvp_roundtrip/schema.js +22 -0
- package/skills/guanvis/evals/comparative_mvp_roundtrip/verify_default_roundtrip.sh +92 -0
- package/skills/guanvis/evals/custom_chart_echarts/card_01_bar.js +13 -0
- package/skills/guanvis/evals/custom_chart_echarts/card_02_pie.js +13 -0
- package/skills/guanvis/evals/custom_chart_echarts/charts/bar.js +11 -0
- package/skills/guanvis/evals/custom_chart_echarts/charts/pie.js +15 -0
- package/skills/guanvis/evals/custom_chart_echarts/page.js +5 -0
- package/skills/guanvis/evals/custom_chart_echarts/schema.js +9 -0
- package/skills/guanvis/evals/percentage_advcalc_roundtrip/README.md +26 -0
- package/skills/guanvis/evals/percentage_advcalc_roundtrip/card_01_percentage_advcalc.js +44 -0
- package/skills/guanvis/evals/percentage_advcalc_roundtrip/card_02_scroll_percentage.js +12 -0
- package/skills/guanvis/evals/percentage_advcalc_roundtrip/page.js +6 -0
- package/skills/guanvis/evals/percentage_advcalc_roundtrip/schema.js +22 -0
- package/skills/guanvis/evals/rank_advcalc_roundtrip/README.md +28 -0
- package/skills/guanvis/evals/rank_advcalc_roundtrip/card_01_rank_advcalc.js +59 -0
- package/skills/guanvis/evals/rank_advcalc_roundtrip/page.js +6 -0
- package/skills/guanvis/evals/rank_advcalc_roundtrip/schema.js +22 -0
- package/skills/guanvis/evals/rank_advcalc_roundtrip/verify_default_roundtrip.sh +135 -0
- package/skills/guanvis/evals/running_total_advcalc_roundtrip/README.md +15 -0
- package/skills/guanvis/evals/running_total_advcalc_roundtrip/card_01_running_total_advcalc.js +74 -0
- package/skills/guanvis/evals/running_total_advcalc_roundtrip/page.js +6 -0
- package/skills/guanvis/evals/running_total_advcalc_roundtrip/schema.js +22 -0
- package/skills/guanvis/evals/sales_dashboard/card_01_revenue_column.js +10 -0
- package/skills/guanvis/evals/sales_dashboard/card_02_trend_line.js +9 -0
- package/skills/guanvis/evals/sales_dashboard/card_03_kpi.js +6 -0
- package/skills/guanvis/evals/sales_dashboard/card_04_pie.js +9 -0
- package/skills/guanvis/evals/sales_dashboard/card_05_calc_field_test.js +12 -0
- package/skills/guanvis/evals/sales_dashboard/page.js +11 -0
- package/skills/guanvis/evals/sales_dashboard/schema.js +14 -0
- package/skills/guanvis/evals/sales_dashboard/selector_01_region.js +10 -0
- package/skills/guanvis/references/api-reference.md +408 -0
- package/skills/guanvis/references/builder-reference.md +690 -0
- package/skills/guanvis/references/publish-and-constraints.md +46 -0
- package/skills/guanvis/references/tableau-migration.md +73 -0
- package/skills/guanvis/references/theme.md +115 -0
- package/skills/guanvis/references/troubleshooting.md +20 -0
- package/skills/guanvis/references/validation-and-chart-patterns.md +205 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
## Builder API 参考
|
|
2
|
+
|
|
3
|
+
### CardBuilder
|
|
4
|
+
|
|
5
|
+
| 方法 | 说明 |
|
|
6
|
+
|------|------|
|
|
7
|
+
| `createCard(chartType, name)` | 创建 Card(chartType 必须使用 `ChartType.XXX` 枚举) |
|
|
8
|
+
| `.setId(cardId)` | **必填**。设置资源 ID(严格 24 位字母数字,格式与后端 RandUtil.uuid 一致),支持多次上传覆盖更新。通过 `guanvis genid` 生成 |
|
|
9
|
+
| `.bindDataset(dsId)` | 绑定数据集(必填,dsId 必须在 defineDataset 中注册) |
|
|
10
|
+
| `.addRow(field)` | 添加行维度(X 轴) |
|
|
11
|
+
| `.addColumn(field)` | 添加列维度(按维度分组着色,如按地区/类别分色)。仅 `STACKED_COLUMN`、`GROUPED_COLUMN`、`GROUPED_BAR` 等多指标图表支持 |
|
|
12
|
+
| `.addMetric(field)` | 添加度量(Y 轴,主轴) |
|
|
13
|
+
| `.addMetricAdditional(field)` | 添加副轴度量(仅组合图 `*_WITH_LINE`/`*_WITH_SYMBOL`),默认绑定副 Y 轴(`plotOn: secondary`) |
|
|
14
|
+
| `.addColorBy(field)` | 按指标值渐变着色(接受度量字段,不是维度)|
|
|
15
|
+
| `.addTooltip(field)` / `.addFilter(field)` | 提示/筛选 |
|
|
16
|
+
| `.addSort(field)` / `.addSplit(field)` / `.addSize(field)` | 排序/拆分/大小 |
|
|
17
|
+
| `.addLocation(field)` / `.addTarget(field)` / `.addCompare(field)` | 位置/目标/对比 |
|
|
18
|
+
| `.setSplitSetting({ rows, columns })` | 拆分行列数(默认各 3),需配合 `.addSplit(field)` |
|
|
19
|
+
| `.setColorByColors(preset_or_config)` | colorBy 渐变色。传 `ColorByPreset.RedGreen` 等预设名称,或 `{ startColor, endColor, middleColor?, steps? }` 自定义 hex 颜色 |
|
|
20
|
+
| `.setShowLegend(show, position)` | 图例 |
|
|
21
|
+
| `.setDataLabel(config)` | 数据标签 |
|
|
22
|
+
| `.setAxis(config)` | 轴配置(见下方 Axis Config 详解) |
|
|
23
|
+
| `.setTableSetting(config)` / `.setPieSetting(config)` | 特殊图表设置 |
|
|
24
|
+
| `.setThemeColor(tcId, colors)` | 主题颜色 |
|
|
25
|
+
| `.setLimit(count)` | 数据行数限制 |
|
|
26
|
+
| `.setConditionalFormat(config)` / `.setAuxiliaryLine(config)` | 条件格式/辅助线 |
|
|
27
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
28
|
+
| `.build()` | 构建(触发验证) |
|
|
29
|
+
|
|
30
|
+
#### 图表选型
|
|
31
|
+
|
|
32
|
+
- `SINGLE_VALUE`:只展示一个指标值,例如总销售额、订单数、门店数、平均客单价。
|
|
33
|
+
- `KPI_CARD`:展示主指标 + 对比指标,例如同比、环比、目标差异;使用时应同时配置 `.addMetric(...)` 和 `.addCompare(...)`。
|
|
34
|
+
- 没有对比指标时优先用 `SINGLE_VALUE`,即使卡片放在看板顶部 KPI 区。
|
|
35
|
+
|
|
36
|
+
#### Axis Config(`.setAxis(config)`)
|
|
37
|
+
|
|
38
|
+
`config` 对象可包含 `categoryAxis`(X 类目轴)、`mainAxis`(Y 主轴)、`secondaryAxis`(Y 副轴):
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
.setAxis({
|
|
42
|
+
categoryAxis: {
|
|
43
|
+
visible: true,
|
|
44
|
+
showTitle: true, title: "月份",
|
|
45
|
+
autoRotate: 45,
|
|
46
|
+
labelFontSize: 12,
|
|
47
|
+
showAxisLine: true
|
|
48
|
+
},
|
|
49
|
+
mainAxis: {
|
|
50
|
+
visible: true,
|
|
51
|
+
showTitle: true, title: "销售额",
|
|
52
|
+
min: 0, max: 100000,
|
|
53
|
+
autoExtremes: false,
|
|
54
|
+
showGridLine: true,
|
|
55
|
+
labelFontSize: 11
|
|
56
|
+
},
|
|
57
|
+
secondaryAxis: {
|
|
58
|
+
visible: true,
|
|
59
|
+
showTitle: true, title: "利润率",
|
|
60
|
+
labelFontSize: 11
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| 属性 | 适用轴 | 说明 |
|
|
66
|
+
|------|--------|------|
|
|
67
|
+
| `visible` | 所有 | 是否显示轴(`false` 隐藏轴) |
|
|
68
|
+
| `showTitle` | 所有 | 是否显示轴标题 |
|
|
69
|
+
| `title` | 所有 | 轴标题文字 |
|
|
70
|
+
| `titleFontSize` / `titleColor` / `titleBold` | 所有 | 标题字体样式 |
|
|
71
|
+
| `unit` | mainAxis/secondaryAxis | 单位(如"万元"),显示在标题旁 |
|
|
72
|
+
| `min` / `max` | mainAxis/secondaryAxis | 固定轴范围(需 `autoExtremes: false`) |
|
|
73
|
+
| `autoExtremes` | mainAxis/secondaryAxis | `true`(默认)自动计算范围 |
|
|
74
|
+
| `showGridLine` | mainAxis/secondaryAxis | 是否显示网格线 |
|
|
75
|
+
| `reverseValue` | mainAxis/secondaryAxis | 反转轴方向 |
|
|
76
|
+
| `labelFontSize` / `labelColor` | 所有 | 刻度标签字体 |
|
|
77
|
+
| `autoRotate` | categoryAxis | 标签旋转角度(0/45/90) |
|
|
78
|
+
| `textLength` | categoryAxis | 标签截断字符长度 |
|
|
79
|
+
| `step` | categoryAxis | 标签间隔(每 N 个显示一个) |
|
|
80
|
+
| `showAxisLine` | categoryAxis | 是否显示轴线 |
|
|
81
|
+
|
|
82
|
+
#### Auxiliary Line Config(`.setAuxiliaryLine(config)`)
|
|
83
|
+
|
|
84
|
+
辅助线/参考线配置。`config` 对象按轴分组:
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
.setAuxiliaryLine({
|
|
88
|
+
mainAxis: [
|
|
89
|
+
{ name: "目标线", color: "#FF0000", valueType: "FIXED", fixedValue: "50000" },
|
|
90
|
+
{ name: "平均值", color: "#0088FF", valueType: "CALCULATED", calculatedValue: "AVG" }
|
|
91
|
+
],
|
|
92
|
+
secondaryAxis: [
|
|
93
|
+
{ name: "基准线", color: "#00AA00", valueType: "FIXED", fixedValue: "0.3" }
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
每条辅助线的属性:
|
|
99
|
+
|
|
100
|
+
| 属性 | 说明 |
|
|
101
|
+
|------|------|
|
|
102
|
+
| `name` | 辅助线名称(显示在图例中) |
|
|
103
|
+
| `color` | 颜色(hex 字符串如 `"#FF0000"`) |
|
|
104
|
+
| `valueType` | `"FIXED"`(固定值)或 `"CALCULATED"`(聚合计算) |
|
|
105
|
+
| `fixedValue` | 当 `valueType="FIXED"` 时的固定数值(字符串格式) |
|
|
106
|
+
| `calculatedValue` | 当 `valueType="CALCULATED"` 时的聚合类型:`"AVG"`(平均值)、`"MAX"`、`"MIN"`、`"MEDIAN"`、`"SUM"` |
|
|
107
|
+
|
|
108
|
+
#### Conditional Format Config(`.setConditionalFormat(config)`)
|
|
109
|
+
|
|
110
|
+
条件格式用于按值区间设置颜色。通过 `setRawSettings("conditionalFormat", config)` 设置(因为结构较复杂,建议直接用 `setRawSettings`)。
|
|
111
|
+
|
|
112
|
+
> **迁移建议**:Tableau 的 Reference Line 对应 `setAuxiliaryLine`,Reference Band 暂无直接等价,可用辅助线近似。条件格式主要用于表格类图表的单元格着色。
|
|
113
|
+
|
|
114
|
+
### PageBuilder
|
|
115
|
+
|
|
116
|
+
**布局单位**:
|
|
117
|
+
1. 默认横向使用 12 列栅格;开启精细模式后使用 60 列栅格。
|
|
118
|
+
2. 推荐通过 `.setFineMode(true)` 设置为精细模式,且必须在任何 `addRow()` / `placeCard()` 等放置卡片的工具方法之前调用。
|
|
119
|
+
3. `addRow()` 及其快捷方法的 `height` 省略或为 0 时使用默认行高(普通 6,精细 18)。
|
|
120
|
+
|
|
121
|
+
| 方法 | 说明 |
|
|
122
|
+
|------|------|
|
|
123
|
+
| `createPage(name)` | 创建 Page |
|
|
124
|
+
| `.setId(pgId)` | 设置 Page ID |
|
|
125
|
+
| `.setParentDir(dirId)` | 设置页面所在目录 ID(不设置则在根目录),目录 ID 可通过 `guancli page tree` 获取 |
|
|
126
|
+
| `.addRow(specs, height?)` | **推荐**:灵活行布局,specs = `[{ card: index, w: colSpan }, ...]`;不传 w 时自动等分当前栅格 |
|
|
127
|
+
| `.addFullWidthCard(cardIndex, height?)` | 全宽行,等价于 `addRow([{ card }], height)` |
|
|
128
|
+
| `.addHalfWidthCards(ci1, ci2, height?)` | 左右各半 |
|
|
129
|
+
| `.addThirdWidthCards(ci1, ci2, ci3, height?)` | 三等分 |
|
|
130
|
+
| `.addQuarterWidthCards(ci1, ci2, ci3, ci4, height?)` | 四等分 |
|
|
131
|
+
| `.placeCard(cardIndex, x, y, w, h)` | 精确放置 Card,`w/h` 必须大于 0, `x/y/w/h` 必须显式填写 |
|
|
132
|
+
| `.setBackgroundColor(color)` | 页面背景色 |
|
|
133
|
+
| `.setCardMargin(margin)` | 卡片间距 |
|
|
134
|
+
| `.setFineMode(enabled)` | 开启/关闭精细模式 |
|
|
135
|
+
| `.setDashboardTitle(enabled, options?: { title?: string })` | 开启/关闭仪表板标题;未传 `title` 时默认使用 Page 名称 |
|
|
136
|
+
| `.setLayoutSetting(config)` | 原始 layout 配置 |
|
|
137
|
+
| `.build()` | 构建 |
|
|
138
|
+
|
|
139
|
+
#### 页面密度尺寸建议
|
|
140
|
+
|
|
141
|
+
以下尺寸建议以非精细模式的 12 列布局单位为基准,用于生成页面时选择页面卡片间距和常见卡片高度。精细模式目前只定义横向 60 列栅格与显式 `x/y/w/h` 放置规则,暂不提供独立的密度尺寸换算规则。
|
|
142
|
+
|
|
143
|
+
密度选择建议:默认使用 `comfortable`;当页面用于汇报展示、希望更强留白感,或卡片数量较少时,使用 `relaxed`。同一页面建议只选择一个主密度基准。
|
|
144
|
+
|
|
145
|
+
| 项目 | `comfortable` | `relaxed` |
|
|
146
|
+
|------|------|------|
|
|
147
|
+
| 页面卡片间距 | `20` | `30` |
|
|
148
|
+
| 单指标卡高度(`SINGLE_VALUE`) | `2` | `3` |
|
|
149
|
+
| 对比指标卡高度(`KPI_CARD`) | `2` | `3` |
|
|
150
|
+
| 图表高度 | `6` | `7` |
|
|
151
|
+
| 表格高度 | `5` | `6` |
|
|
152
|
+
|
|
153
|
+
同一行卡片默认使用同一高度,避免页面节奏不齐。若需要压缩页面,可在不影响可读性的前提下降低局部卡片高度。
|
|
154
|
+
|
|
155
|
+
注意:这里的高度建议是非精细模式下的页面生成建议,不覆盖 `addRow()` 在精细模式下省略高度时使用默认行高 `18` 的 API 行为。
|
|
156
|
+
|
|
157
|
+
### SelectorBuilder(筛选器)
|
|
158
|
+
|
|
159
|
+
筛选器是特殊的卡片(`cdType=6`),放在页面顶部的筛选器面板中,可联动影响其他图表卡片。
|
|
160
|
+
|
|
161
|
+
| 方法 | 说明 |
|
|
162
|
+
|------|------|
|
|
163
|
+
| `createSelector(name)` | 创建筛选器 |
|
|
164
|
+
| `.setId(cardId)` | 设置固定资源 ID(同 CardBuilder) |
|
|
165
|
+
| `.setSelectorType(type)` | 筛选器类型:`SelectorType.DS_ELEMENTS`(列表选择,默认)、`DS_INTERVAL`(数值范围)、`CALENDAR`(日期)、`TIME_MACRO`(快捷日期区间) |
|
|
166
|
+
| `.setFilterType(type)` | 筛选条件:`DS_INTERVAL` 默认 `"BT"`(区间),`DS_ELEMENTS` 默认 `"IN"`。可用值参见 `FilterType` 枚举 |
|
|
167
|
+
| `.bindDataset(dsId)` | 绑定数据集(可选,单数据集场景自动绑定) |
|
|
168
|
+
| `.bindField(field)` | 绑定筛选字段(`DS_ELEMENTS`/`DS_INTERVAL`/`CALENDAR` 必填,`TIME_MACRO` 不需要),使用 `f("字段名")` 引用 |
|
|
169
|
+
| `.setGranularity(granularity)` | 设置 `CALENDAR` 日期筛选器粒度,等价于只允许一个粒度。可用值:`Granularity.YEAR`、`QUARTER`、`MONTH`、`WEEK`、`DAY` |
|
|
170
|
+
| `.setGranularityOptions(options, defaultGranularity?)` | 设置 `CALENDAR` 可选日期粒度列表和默认粒度,例如 `[Granularity.MONTH, Granularity.QUARTER]`。未显式设置时会从目标卡片日期字段粒度自动推断 |
|
|
171
|
+
| `.setTimeMacroOptions(options, defaultMacroName?)` | 设置快捷日期选项(自动设置 `selectorType` 为 `TIME_MACRO`)。`options`: `[{ name, expr }]`,`expr` 使用内置宏名(见示例)。`defaultMacroName` 默认选中的宏名,传 `null` 则不选(页面打开时无默认值),不传则取第一项。不需要 `bindField` 和 `bindDataset` |
|
|
172
|
+
| `.setMultiSelect(bool)` | 是否多选(默认 false) |
|
|
173
|
+
| `.setDefaultType(type)` | 默认值类型:`SelectorDefaultType.FIRST_PICK`(默认)、`FIXED_VALUE` 或 `ALL` |
|
|
174
|
+
| `.setDefaultAll()` | 设置默认"全部"(不筛选),等价于 `setDefaultType(SelectorDefaultType.ALL)` |
|
|
175
|
+
| `.setDefaultValue(values, displayValues?)` | 设置固定默认值,自动切换为 FIXED_VALUE 类型 |
|
|
176
|
+
| `.setFirstPickLink(bool)` | FIRST_PICK 模式下是否联动刷新(默认 false) |
|
|
177
|
+
| `.setDisplayType(type)` | 展示类型(仅 `DS_ELEMENTS` 使用):`SelectorDisplay.SEARCH_LIST`(单选下拉)、`SEARCH_BOX`(多选下拉)、`CHECKBOX`(复选框)、`RADIO`(单选框)、`BUTTON_GROUP`(按钮组)。不设置时根据 multiSelect 自动选择。`DS_INTERVAL` 类型不需要此设置 |
|
|
178
|
+
| `.setShowSelectAll(bool)` | 是否显示"全选"(默认 true) |
|
|
179
|
+
| `.setCanClear(bool)` | 是否可清空(默认 true) |
|
|
180
|
+
| `.linkTo(cardIndex, targetFieldName?)` | 联动指定卡片(cardIndex 为注册顺序),可指定目标字段名(默认同名匹配) |
|
|
181
|
+
| `.linkToAll()` | 自动联动所有图表卡片(按同名字段匹配) |
|
|
182
|
+
| `.build()` | 构建(触发验证) |
|
|
183
|
+
|
|
184
|
+
**使用示例**:
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
// selector_01_region.js — 列表选择(DS_ELEMENTS,默认)
|
|
188
|
+
var sel = createSelector("区域筛选")
|
|
189
|
+
.setId("s184352b7a76776db5f534df")
|
|
190
|
+
.bindField(f("区域"))
|
|
191
|
+
.setMultiSelect(true)
|
|
192
|
+
.linkToAll()
|
|
193
|
+
.build();
|
|
194
|
+
registerSelector(sel);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
// selector_02_profit_rate.js — 数值范围(DS_INTERVAL)
|
|
199
|
+
var sel = createSelector("利润率筛选")
|
|
200
|
+
.setId("h61d8bf256952ef3fcf961c5")
|
|
201
|
+
.setSelectorType(SelectorType.DS_INTERVAL) // 范围筛选器
|
|
202
|
+
.bindField(f("利润率"))
|
|
203
|
+
.linkToAll()
|
|
204
|
+
.build();
|
|
205
|
+
registerSelector(sel);
|
|
206
|
+
// DS_INTERVAL 默认 filterType="BT"(区间),展示两个输入框(起始值-结束值)
|
|
207
|
+
// 也可设置 .setFilterType("EQ") 单值等于,或 "GT"/"LT" 等比较
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
// selector_03_timemacro.js — 快捷日期(TIME_MACRO)
|
|
212
|
+
var sel = createSelector("快捷日期")
|
|
213
|
+
.setId("gf7a7ed51ec7c9477fcd1d81")
|
|
214
|
+
.setTimeMacroOptions([
|
|
215
|
+
{ name: "今天", expr: ["TODAY"] },
|
|
216
|
+
{ name: "昨天", expr: ["YESTERDAY"] },
|
|
217
|
+
{ name: "最近7天", expr: ["LAST_7_DAY"] },
|
|
218
|
+
{ name: "最近30天", expr: ["LAST_30_DAY"] },
|
|
219
|
+
{ name: "本月", expr: ["MONTH_TO_DAY"] },
|
|
220
|
+
{ name: "上月", expr: ["LAST_MONTH"] },
|
|
221
|
+
{ name: "本年", expr: ["YEAR_TO_DAY"] }
|
|
222
|
+
], "最近7天")
|
|
223
|
+
.linkToAll()
|
|
224
|
+
.build();
|
|
225
|
+
registerSelector(sel);
|
|
226
|
+
// TIME_MACRO 不需要 bindField/bindDataset,自动匹配目标卡片中的日期字段联动
|
|
227
|
+
// 内置宏名(expr数组只需一个元素):TODAY, YESTERDAY, LAST_7_DAY, LAST_14_DAY,
|
|
228
|
+
// LAST_30_DAY, LAST_90_DAY, LAST_1_YEAR, LAST_WEEK, LAST_MONTH,
|
|
229
|
+
// WEEK_TO_DAY, MONTH_TO_DAY, YEAR_TO_DAY, DAY_BEFORE_YESTERDAY,
|
|
230
|
+
// WEEK_TO_YESTERDAY, MONTH_TO_YESTERDAY, YEAR_TO_YESTERDAY,
|
|
231
|
+
// QUARTER_TO_DAY, QUARTER_TO_YESTERDAY, YEAR_TO_LAST_MONTH, YEAR_TO_LAST_QUARTER
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**筛选器类型选择指南**:
|
|
235
|
+
- **离散值**(区域、类别、客户名等文本字段)→ `DS_ELEMENTS`(默认),配合 `setDisplayType` 选择展示样式
|
|
236
|
+
- **连续数值范围**(利润率、金额区间等)→ `SelectorType.DS_INTERVAL`,默认区间输入(起始值-结束值)
|
|
237
|
+
- **日期选择**(精确日期范围)→ `SelectorType.CALENDAR`,需要 `bindField` 绑定日期字段。默认会从联动目标卡片推断日期粒度;如需固定月/季度等粒度,可用 `.setGranularity(Granularity.MONTH)` 或 `.setGranularityOptions([...], default)`
|
|
238
|
+
- **快捷日期区间**(本月/上月/近7天等预设区间)→ `.setTimeMacroOptions(options, default)`,不需要 `bindField`,自动匹配目标卡片日期字段联动。`default` 传 `null` 表示无默认值
|
|
239
|
+
|
|
240
|
+
**联动机制**:筛选器通过 `settings.asFilter` 配置联动关系。`linkTo(cardIndex)` 会自动构建 `columnMappings`,将筛选器字段映射到目标卡片的同名字段。`linkToAll()` 会自动匹配所有图表卡片中的同名字段。
|
|
241
|
+
|
|
242
|
+
**文件命名**:筛选器脚本建议命名为 `selector_NN_xxx.js`,会在 `card_*.js` 之后、`page.js` 之前执行。
|
|
243
|
+
|
|
244
|
+
### TextCardBuilder(文本卡片)
|
|
245
|
+
|
|
246
|
+
文本卡片(`cdType=1`)用于在仪表板中展示富文本内容,支持内嵌 SINGLE_VALUE 指标引用(在文本中内联展示实时指标值)。
|
|
247
|
+
|
|
248
|
+
| 方法 | 说明 |
|
|
249
|
+
|------|------|
|
|
250
|
+
| `createTextCard(name)` | 创建文本卡片 |
|
|
251
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
252
|
+
| `.addText(text)` | 添加一段普通文本 |
|
|
253
|
+
| `.addHeader(text, level?)` | 添加标题(level 1-6,默认 2) |
|
|
254
|
+
| `.addMarkdown(markdownText)` | **推荐**。用 Markdown 语法批量定义富文本内容(见下方 Markdown 语法说明) |
|
|
255
|
+
| `.embedCard(cardRefId, placeholder?)` | 在当前文本块末尾嵌入一个 SINGLE_VALUE 指标引用。`cardRefId` 是被引用卡片的 ID,`placeholder` 是占位文本(默认空格) |
|
|
256
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
257
|
+
| `.build()` | 构建(触发验证) |
|
|
258
|
+
|
|
259
|
+
**使用示例**:
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// card_00_kpi.js — 先创建被引用的 SINGLE_VALUE 卡片
|
|
263
|
+
var kpi = createCard(ChartType.SINGLE_VALUE, "总营收指标")
|
|
264
|
+
.setId("a184352b7a76776db5f534df")
|
|
265
|
+
.bindDataset(DS)
|
|
266
|
+
.addMetric(f("营收", { aggrType: AggrType.SUM }));
|
|
267
|
+
registerCard(kpi.build());
|
|
268
|
+
|
|
269
|
+
// card_01_text.js — 文本卡片引用上面的指标
|
|
270
|
+
var text = createTextCard("业绩概览")
|
|
271
|
+
.setId("b284352b7a76776db5f534df")
|
|
272
|
+
.addHeader("本月业绩报告")
|
|
273
|
+
.addText("本月总营收为 ")
|
|
274
|
+
.embedCard("a184352b7a76776db5f534df", "[总营收]")
|
|
275
|
+
.addText(",较上月有所增长。");
|
|
276
|
+
registerTextCard(text.build());
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**嵌入机制**:文本卡片使用 Draft.js 格式存储内容。`embedCard()` 通过 `entityMap` 中的 `Macro` 类型实体引用其他 SINGLE_VALUE 卡片的 ID,BI 系统在渲染时会将占位文本替换为实时指标值。被引用的卡片**必须是 SINGLE_VALUE 类型**。
|
|
280
|
+
|
|
281
|
+
**Markdown 模式**(推荐用于复杂文本):
|
|
282
|
+
|
|
283
|
+
`addMarkdown()` 支持以下 Markdown 语法,自动转换为 BI 富文本格式:
|
|
284
|
+
|
|
285
|
+
| 语法 | 效果 |
|
|
286
|
+
|------|------|
|
|
287
|
+
| `# ~ ######` | 一至六级标题 |
|
|
288
|
+
| `**text**` | **加粗** |
|
|
289
|
+
| `*text*` | *斜体* |
|
|
290
|
+
| `~~text~~` | ~~删除线~~ |
|
|
291
|
+
| `` `code` `` | 行内代码 |
|
|
292
|
+
| `- item` / `* item` | 无序列表(支持缩进嵌套) |
|
|
293
|
+
| `1. item` | 有序列表 |
|
|
294
|
+
| `> quote` | 引用块 |
|
|
295
|
+
| `---` | 分隔线 |
|
|
296
|
+
| `{{cardId:占位文本}}` | 内嵌 SINGLE_VALUE 指标引用 |
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
// 使用 addMarkdown 一次性定义复杂富文本(ID 通过 guanvis genid 预生成)
|
|
300
|
+
var kpiId = "c384352b7a76776db5f534df";
|
|
301
|
+
var kpi = createCard(ChartType.SINGLE_VALUE, "总营收")
|
|
302
|
+
.setId(kpiId)
|
|
303
|
+
.bindDataset(DS)
|
|
304
|
+
.addMetric(f("营收", { aggrType: AggrType.SUM }));
|
|
305
|
+
registerCard(kpi.build());
|
|
306
|
+
|
|
307
|
+
var text = createTextCard("数据报告")
|
|
308
|
+
.setId("d484352b7a76776db5f534df")
|
|
309
|
+
.addMarkdown(
|
|
310
|
+
"## 月度业绩报告\n\n" +
|
|
311
|
+
"本月总营收为 {{" + kpiId + ":总营收}},**表现优异**。\n\n" +
|
|
312
|
+
"### 关键发现\n" +
|
|
313
|
+
"1. 华东区域贡献最大\n" +
|
|
314
|
+
"2. 新品类增长 *显著*\n\n" +
|
|
315
|
+
"> 数据截至本月最后一个工作日"
|
|
316
|
+
);
|
|
317
|
+
registerTextCard(text.build());
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### createTextCardWithData(带数据的文本卡片)
|
|
321
|
+
|
|
322
|
+
高层便捷方法,一次调用自动完成:创建多个 SINGLE_VALUE 指标卡片 → 创建包含 Markdown 富文本的文本卡片 → 自动注册所有卡片。省去手动创建 KPI 卡片、拼接 `{{cardId:placeholder}}` 占位符、依次注册的繁琐步骤。
|
|
323
|
+
|
|
324
|
+
```javascript
|
|
325
|
+
createTextCardWithData(config)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**config 参数**:
|
|
329
|
+
|
|
330
|
+
| 字段 | 必填 | 说明 |
|
|
331
|
+
|------|------|------|
|
|
332
|
+
| `textCardId` | 是 | 文本卡片的资源 ID |
|
|
333
|
+
| `textCardName` | 否 | 文本卡片名称(默认"数据报告") |
|
|
334
|
+
| `textCardDescription` | 否 | 文本卡片描述 |
|
|
335
|
+
| `dsId` | 否 | 数据集 ID(默认使用 `DS`,即第一个 `defineDataset` 的数据集) |
|
|
336
|
+
| `metrics` | 是 | 指标配置数组(见下表) |
|
|
337
|
+
| `markdown` | 是 | Markdown 模板,用 `{{字段名或label}}` 引用指标 |
|
|
338
|
+
|
|
339
|
+
**metrics 数组元素**:
|
|
340
|
+
|
|
341
|
+
| 字段 | 必填 | 说明 |
|
|
342
|
+
|------|------|------|
|
|
343
|
+
| `id` | 是 | 该 SINGLE_VALUE 卡片的资源 ID |
|
|
344
|
+
| `fieldName` | 是 | 数据集中的字段名 |
|
|
345
|
+
| `label` | 否 | 指标别名(用于 Markdown 中引用和卡片命名,默认取 fieldName) |
|
|
346
|
+
| `aggrType` | 否 | 聚合类型(默认 `AggrType.SUM`) |
|
|
347
|
+
| `numberFormat` | 否 | 数值格式 |
|
|
348
|
+
|
|
349
|
+
**Markdown 中的引用语法**:使用 `{{label}}` 或 `{{fieldName}}` 引用指标,函数自动替换为对应 SINGLE_VALUE 卡片的 Macro 引用。
|
|
350
|
+
|
|
351
|
+
**使用示例**:
|
|
352
|
+
|
|
353
|
+
```javascript
|
|
354
|
+
createTextCardWithData({
|
|
355
|
+
textCardId: "t184352b7a76776db5f534df",
|
|
356
|
+
textCardName: "月度业绩报告",
|
|
357
|
+
metrics: [
|
|
358
|
+
{ id: "m184352b7a76776db5f534df", fieldName: "营收", label: "总营收",
|
|
359
|
+
aggrType: AggrType.SUM, numberFormat: NumberFormat.currency("¥", 0) },
|
|
360
|
+
{ id: "m284352b7a76776db5f534df", fieldName: "利润", aggrType: AggrType.SUM },
|
|
361
|
+
{ id: "m384352b7a76776db5f534df", fieldName: "订单数", label: "总订单",
|
|
362
|
+
aggrType: AggrType.COUNT }
|
|
363
|
+
],
|
|
364
|
+
markdown: [
|
|
365
|
+
"## 月度业绩报告",
|
|
366
|
+
"",
|
|
367
|
+
"本月总营收为 {{总营收}},利润 {{利润}}。",
|
|
368
|
+
"",
|
|
369
|
+
"### 关键指标",
|
|
370
|
+
"- 总订单数:{{总订单}}",
|
|
371
|
+
"- 利润率表现**优异**",
|
|
372
|
+
"",
|
|
373
|
+
"> 数据截至本月最后一个工作日"
|
|
374
|
+
].join("\n")
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// 布局:第一行 3 个 KPI 指标卡(cardIndex 0~2),第二行全宽文本报告(cardIndex 3)
|
|
378
|
+
var page = createPage("业绩仪表板")
|
|
379
|
+
.setId("p184352b7a76776db5f534df")
|
|
380
|
+
.addRow([{ card: 0, w: 4 }, { card: 1, w: 4 }, { card: 2, w: 4 }], 3)
|
|
381
|
+
.addFullWidthCard(3, 6);
|
|
382
|
+
registerPage(page.build());
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**注册顺序**:`createTextCardWithData` 会按 `metrics` 数组顺序先注册 SINGLE_VALUE 卡片(cardIndex 从 0 开始),最后注册文本卡片。在 page 布局中,前 N 个 cardIndex 对应 N 个指标卡,第 N 个 cardIndex 对应文本卡片。
|
|
386
|
+
|
|
387
|
+
### ImageCardBuilder(图片卡片)
|
|
388
|
+
|
|
389
|
+
图片卡片(`cdType=4`)用于在仪表板中展示图片,支持外链 URL 和本地图片文件。
|
|
390
|
+
|
|
391
|
+
**支持的图片格式**:本地上传仅支持 `jpg/jpeg/png/gif` 格式。**不支持 SVG**——如需使用 SVG 图片,必须先转换为 PNG 等支持的格式后再上传。
|
|
392
|
+
|
|
393
|
+
**SVG 转 PNG 推荐方式**(按优先级排列):
|
|
394
|
+
1. `npx sharp-cli -i input.svg -o output.png -f png` — 基于 sharp(最流行的 Node.js 图像处理库),无需提前安装
|
|
395
|
+
2. `npx sharp-cli -i input.svg -o output.png -f png resize 1200` — 指定宽度缩放
|
|
396
|
+
3. **agent-browser** — 通过浏览器打开 SVG 文件再截图,适合需要精确 CSS/字体渲染的场景
|
|
397
|
+
|
|
398
|
+
不要使用 `ffmpeg`(不支持 SVG)或 `cairosvg`(Python 依赖复杂易出错)。
|
|
399
|
+
|
|
400
|
+
| 方法 | 说明 |
|
|
401
|
+
|------|------|
|
|
402
|
+
| `createImageCard(name)` | 创建图片卡片 |
|
|
403
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
404
|
+
| `.setUrl(url)` | 设置外链图片 URL(sourceType=1) |
|
|
405
|
+
| `.setLocalImage(filePath)` | 设置本地图片文件路径(sourceType=2),打包时图片会作为附件写入 ZIP |
|
|
406
|
+
| `.setRenderType(type)` | 设置图片渲染模式:`ImageRenderType.RATIO`(原比例,默认)、`ImageRenderType.STRETCH`(拉伸填满)、`ImageRenderType.FIT_TO_CONTENT`(自适应内容) |
|
|
407
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
408
|
+
| `.build()` | 构建(触发验证) |
|
|
409
|
+
|
|
410
|
+
**使用示例**:
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// 外链图片
|
|
414
|
+
var img1 = createImageCard("Logo")
|
|
415
|
+
.setId("c384352b7a76776db5f534df")
|
|
416
|
+
.setUrl("https://example.com/logo.png");
|
|
417
|
+
registerImageCard(img1.build());
|
|
418
|
+
|
|
419
|
+
// 本地图片 + 拉伸填满模式(适合 Banner)
|
|
420
|
+
var img2 = createImageCard("Banner")
|
|
421
|
+
.setId("d484352b7a76776db5f534df")
|
|
422
|
+
.setLocalImage("./assets/banner.png")
|
|
423
|
+
.setRenderType(ImageRenderType.STRETCH);
|
|
424
|
+
registerImageCard(img2.build());
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**本地图片机制**:`setLocalImage()` 指定本地文件路径,`pack`/`publish` 时工具会将图片文件读取并作为 Appendix 附件打包进 ZIP 资源包。导入 BI 系统时,后端会将图片存储到内部文件存储并建立引用关系。仅支持 jpg/jpeg/png/gif 格式;SVG 需先转为 PNG。
|
|
428
|
+
|
|
429
|
+
### CustomChartBuilder(自定义图表)
|
|
430
|
+
|
|
431
|
+
自定义图表(`cdType=10`)允许使用自定义 HTML/CSS/JavaScript 代码渲染图表,适用于内置图表类型无法满足的场景。支持三种子类型:
|
|
432
|
+
|
|
433
|
+
| 子类型 | 说明 |
|
|
434
|
+
|--------|------|
|
|
435
|
+
| `CustomChartSubType.SDK` | 标准自定义图表,在 iframe 中运行。支持任意前端库(Vega-Lite/D3/ECharts 等)。**Tableau 迁移场景首选** |
|
|
436
|
+
| `CustomChartSubType.ECHARTS_LITE` | 原生 ECharts 模式,无 iframe。只需写 JS 脚本设置 `option`。仅适用于 ECharts 能满足的简单场景 |
|
|
437
|
+
|
|
438
|
+
**子类型选择指南**:
|
|
439
|
+
- 自定义图表优先使用 **SDK** 模式 + Vega-Lite,模板和文档支持最完整
|
|
440
|
+
- 纯 ECharts 且脚本极简的场景 → 可用 **ECHARTS_LITE**(无 iframe 开销,但也可以用 SDK 模式)
|
|
441
|
+
- SDK 模式运行在 iframe 中,需要通过 `__asset_text__`/`__asset_base64__` 内嵌外部资源
|
|
442
|
+
|
|
443
|
+
| 方法 | 说明 |
|
|
444
|
+
|------|------|
|
|
445
|
+
| `createCustomChart(name)` | 创建自定义图表卡片 |
|
|
446
|
+
| `.setId(cardId)` | **必填**。设置资源 ID |
|
|
447
|
+
| `.setSubType(subType)` | 设置子类型,默认 `SDK`。用 `CustomChartSubType.XXX` |
|
|
448
|
+
| `.loadContent(baseName)` | **推荐**。从文件加载 HTML/CSS/JS。工具自动读取 `baseName.html`、`baseName.css`、`baseName.js`(`.js` 必须存在,`.html` 和 `.css` 可选) |
|
|
449
|
+
| `.setContent(html, css, script)` | 内联设置 HTML/CSS/JS(仅在内容极简时使用)|
|
|
450
|
+
| `.addLib(url)` | 添加外部 JS 库 URL |
|
|
451
|
+
| `.setProps(props)` | 设置自定义属性 |
|
|
452
|
+
| `.addDataView(cardBuilder)` | 添加数据视图(子卡片),子卡片使用普通 `CardBuilder` 创建(任意 ChartType 均可,系统自动转换为 DATA_GRID)。用 `.addRow()` 放维度、`.addMetric()` 放度量 |
|
|
453
|
+
| `.setRawSettings(key, value)` | 原始设置 |
|
|
454
|
+
| `.build()` | 构建(触发验证) |
|
|
455
|
+
|
|
456
|
+
**数据流**:BI 前端查询子卡片(data view)的数据 → 将结果按列组织为 `data` → 传给自定义图表的 `renderChart(data, clickFunc, config)` 函数(SDK)或直接可用 `data` 变量(ECHARTS_LITE)。
|
|
457
|
+
|
|
458
|
+
`data` 格式(二维数组,外层每个元素对应一个数据视图,内层每个元素对应一个字段列):
|
|
459
|
+
```javascript
|
|
460
|
+
// data[viewIndex][columnIndex] = { name: "字段名", data: [...值], numberFormat: ... }
|
|
461
|
+
data[0][0].name // → "类别"
|
|
462
|
+
data[0][0].data // → ["办公用品", "技术", "家具"]
|
|
463
|
+
data[0][1].name // → "销售额"
|
|
464
|
+
data[0][1].data // → [4916842, 3157709.5, 3037943.5]
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
`config` 包含 `{ theme: "LIGHT"|"DARK", colors: string[], customOptions: object, language: string }`。
|
|
468
|
+
|
|
469
|
+
**推荐的工作方式**(文件模式):
|
|
470
|
+
|
|
471
|
+
1. AI 将自定义图表的 HTML/CSS/JS 分别写入独立文件(如 `my_chart.html`、`my_chart.css`、`my_chart.js`)
|
|
472
|
+
2. 在 card 脚本中使用 `.loadContent("my_chart")` 引用
|
|
473
|
+
|
|
474
|
+
文件结构示例(**内容文件必须放在子目录中**,避免被 pack 当作 card 脚本执行):
|
|
475
|
+
```
|
|
476
|
+
project/
|
|
477
|
+
├── schema.js
|
|
478
|
+
├── card_01_custom.js ← card 脚本(loadContent("charts/my_chart"))
|
|
479
|
+
├── page.js
|
|
480
|
+
└── charts/ ← 子目录:自定义图表内容文件
|
|
481
|
+
├── my_chart.html ← HTML(可选)
|
|
482
|
+
├── my_chart.css ← CSS(可选)
|
|
483
|
+
├── my_chart.js ← JavaScript(必须)
|
|
484
|
+
└── us-10m.json ← 资源文件(可选,通过 asset 占位符引用)
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**资源内嵌**(`__asset_text__` / `__asset_base64__`):
|
|
488
|
+
|
|
489
|
+
自定义图表运行在 iframe 沙箱中,不能从外部 URL 加载资源(CORS/sandbox 限制)。需要将 GeoJSON、图片等资源内嵌到 JS/HTML 中。使用 asset 占位符让 `pack`/`publish` 自动替换:
|
|
490
|
+
|
|
491
|
+
```javascript
|
|
492
|
+
// 在 .js 文件中引用本地文件为 JSON 字符串(自动 escape)
|
|
493
|
+
var geoData = JSON.parse(__asset_text("./us-10m.json")__);
|
|
494
|
+
|
|
495
|
+
// 引用本地文件为 base64 编码字符串
|
|
496
|
+
var logoBase64 = __asset_base64("./logo.png")__;
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
- `__asset_text("path")__` — 读取文件内容,做 JSON string escape 后替换(结果带双引号,是一个合法的 JSON 字符串字面量)
|
|
500
|
+
- `__asset_base64("path")__` — 读取文件内容,做 base64 编码后替换(结果带双引号)
|
|
501
|
+
- 路径相对于内容文件所在目录(即 `.loadContent()` 指向的目录)
|
|
502
|
+
- 路径不允许向上跳出内容目录(安全限制)
|
|
503
|
+
- 占位符仅在 `pack`/`publish` 构建时处理,不影响 AI 脚本的可读性
|
|
504
|
+
|
|
505
|
+
**内嵌第三方 JS 库**(如 Vega-Lite、D3 等):
|
|
506
|
+
|
|
507
|
+
SDK 模式的 iframe 沙箱**阻止从外部 CDN 加载脚本**(sandbox/CSP 限制)。`addLib()` 添加的 CDN URL 在安全模式下不生效。正确做法是:
|
|
508
|
+
|
|
509
|
+
1. 将第三方库的 `.min.js` 文件下载到 `charts/` 目录
|
|
510
|
+
2. 在渲染 JS 文件中用 `__asset_text__` 内嵌并通过 `new Function()` 执行
|
|
511
|
+
|
|
512
|
+
```javascript
|
|
513
|
+
// 内嵌 Vega-Lite 库(下载到 charts/ 目录后引用)
|
|
514
|
+
var _vegaSrc = __asset_text("./vega.min.js")__;
|
|
515
|
+
var _vegaLiteSrc = __asset_text("./vega-lite.min.js")__;
|
|
516
|
+
var _vegaEmbedSrc = __asset_text("./vega-embed.min.js")__;
|
|
517
|
+
(new Function(_vegaSrc))();
|
|
518
|
+
(new Function(_vegaLiteSrc))();
|
|
519
|
+
(new Function(_vegaEmbedSrc))();
|
|
520
|
+
|
|
521
|
+
// 之后即可使用 vegaEmbed(...)
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**注意**:内嵌大型库会增加资源包体积(Vega-Lite 全套约 800KB),但确保在所有环境下都能正常运行。`addLib()` 仅在未开启安全模式的环境中有效,不推荐用于生产。
|
|
525
|
+
|
|
526
|
+
**Vega-Lite 地图(geoshape)的坑**:Vega-Lite 的 `geoshape` mark 在使用 inline GeoJSON 数据时,projection 的自动 fit 行为不可靠,常导致地图渲染为空白。推荐的替代方案:
|
|
527
|
+
|
|
528
|
+
- **方案 A(推荐)**:只内嵌 `vega.min.js`,手动实现 Mercator 投影 + SVG 渲染。`vega.min.js` 中不直接暴露 `geoMercator` 等 d3-geo API,需自行实现投影公式:
|
|
529
|
+
```javascript
|
|
530
|
+
function toRad(deg) { return deg * Math.PI / 180; }
|
|
531
|
+
function mercX(lon) { return toRad(lon); }
|
|
532
|
+
function mercY(lat) { return Math.log(Math.tan(Math.PI / 4 + toRad(lat) / 2)); }
|
|
533
|
+
// 计算 projected bounding box 后用 fitSize 逻辑缩放到容器
|
|
534
|
+
```
|
|
535
|
+
关键:x 和 y 都必须转换到同一单位空间(弧度),否则宽高比会错误。
|
|
536
|
+
- **方案 B**:使用 `ECHARTS_LITE` 子类型代替 SDK,ECharts 的 `registerMap` + `visualMap` 对 inline GeoJSON 支持更好。
|
|
537
|
+
- **方案 C**:如果必须用 Vega-Lite,`data.values` 必须是完整的 FeatureCollection 对象(不是 features 数组),`format` 设为 `{"type": "json", "property": "features"}`。参考 [vega-lite#3432](https://github.com/vega/vega-lite/issues/3432)。
|
|
538
|
+
- 只有完整格式 `__asset_text("path")__` 才会被替换,注释或字符串中的 `__asset_text__` 文字不受影响
|
|
539
|
+
- **来源标注**:对于从网上下载的资源文件(如 GeoJSON),在占位符上方用注释标注来源 URL,便于后续维护和溯源:
|
|
540
|
+
|
|
541
|
+
```javascript
|
|
542
|
+
// source: https://cdn.jsdelivr.net/npm/vega-datasets@2/data/us-10m.json
|
|
543
|
+
var geoData = JSON.parse(__asset_text("./us-10m.json")__);
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
**SDK 子类型示例**(iframe 模式,使用 `gd-plugin.js`):
|
|
547
|
+
|
|
548
|
+
`card_01_custom.js`(card 脚本):
|
|
549
|
+
```javascript
|
|
550
|
+
var dataView = createCard(ChartType.DATA_GRID, "数据视图")
|
|
551
|
+
.setId("a484352b7a76776db5f534df")
|
|
552
|
+
.bindDataset(DS)
|
|
553
|
+
.addRow(f("类别"))
|
|
554
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
555
|
+
|
|
556
|
+
var chart = createCustomChart("自定义柱状图")
|
|
557
|
+
.setId("b484352b7a76776db5f534df")
|
|
558
|
+
.setSubType(CustomChartSubType.SDK)
|
|
559
|
+
.loadContent("charts/my_chart")
|
|
560
|
+
.addDataView(dataView);
|
|
561
|
+
|
|
562
|
+
registerCustomChart(chart.build());
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
`charts/my_chart.html`:
|
|
566
|
+
```html
|
|
567
|
+
<div id="container"></div>
|
|
568
|
+
<script>loadBuiltinResourceByName('echarts')</script>
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
`charts/my_chart.css`:
|
|
572
|
+
```css
|
|
573
|
+
#container { width: 100%; height: 100%; }
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
`charts/my_chart.js`(运行在 BI iframe 中的渲染代码):
|
|
577
|
+
```javascript
|
|
578
|
+
var myChart = echarts.init(document.getElementById('container'));
|
|
579
|
+
function renderChart(data, clickFunc, config) {
|
|
580
|
+
// data[0] = 第一个数据视图的列数据: [{name:"类别", data:[...]}, {name:"销售额", data:[...]}]
|
|
581
|
+
var cols = data[0] || [];
|
|
582
|
+
myChart.setOption({
|
|
583
|
+
xAxis: { type: 'category', data: (cols[0] || {}).data || [] },
|
|
584
|
+
yAxis: { type: 'value' },
|
|
585
|
+
series: [{ type: 'bar', data: (cols[1] || {}).data || [] }],
|
|
586
|
+
color: config.colors
|
|
587
|
+
});
|
|
588
|
+
myChart.resize();
|
|
589
|
+
}
|
|
590
|
+
new GDPlugin().init(renderChart);
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**ECHARTS_LITE 子类型示例**(无 iframe,直接操作 ECharts,仅适用于纯 ECharts 场景):
|
|
594
|
+
|
|
595
|
+
`card_01_echarts.js`(card 脚本):
|
|
596
|
+
```javascript
|
|
597
|
+
var dataView = createCard(ChartType.DATA_GRID, "数据视图")
|
|
598
|
+
.setId("c484352b7a76776db5f534df")
|
|
599
|
+
.bindDataset(DS)
|
|
600
|
+
.addRow(f("类别"))
|
|
601
|
+
.addMetric(f("销售额", { aggrType: AggrType.SUM }));
|
|
602
|
+
|
|
603
|
+
var chart = createCustomChart("ECharts 柱状图")
|
|
604
|
+
.setId("d484352b7a76776db5f534df")
|
|
605
|
+
.setSubType(CustomChartSubType.ECHARTS_LITE)
|
|
606
|
+
.loadContent("charts/echarts_bar")
|
|
607
|
+
.addDataView(dataView);
|
|
608
|
+
|
|
609
|
+
registerCustomChart(chart.build());
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
`charts/echarts_bar.js`(ECharts 渲染代码,HTML 和 CSS 文件可省略):
|
|
613
|
+
```javascript
|
|
614
|
+
// data[0] = [{name:"类别", data:[...]}, {name:"销售额", data:[...]}]
|
|
615
|
+
var cols = data[0] || [];
|
|
616
|
+
var categories = (cols[0] || {}).data || [];
|
|
617
|
+
var values = (cols[1] || {}).data || [];
|
|
618
|
+
option = {
|
|
619
|
+
xAxis: { type: "category", data: categories },
|
|
620
|
+
yAxis: { type: "value" },
|
|
621
|
+
series: [{ type: "bar", data: values }]
|
|
622
|
+
};
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
> **注意**:ECHARTS_LITE 模式下,脚本中的 `data`、`config`、`clickFunc`、`utils` 是预定义变量。将 ECharts option 赋值给 `option` 变量即可渲染。**不要使用 `new GDPlugin().init()`**,那是 SDK(iframe)模式的 API。
|
|
626
|
+
|
|
627
|
+
**ECHARTS_LITE 自定义地图示例**(使用 `__asset_text__` 内嵌 GeoJSON):
|
|
628
|
+
|
|
629
|
+
`card_01_map.js`(card 脚本):
|
|
630
|
+
```javascript
|
|
631
|
+
var dataView = createCard(ChartType.DATA_GRID, "地图数据视图")
|
|
632
|
+
.setId("c584352b7a76776db5f534df")
|
|
633
|
+
.bindDataset(DS)
|
|
634
|
+
.addRow(f("省/自治区"))
|
|
635
|
+
.addMetric(calcField("利润率", "SUM([利润])/SUM([销售额])"));
|
|
636
|
+
|
|
637
|
+
var chart = createCustomChart("各省利润率(ECharts)")
|
|
638
|
+
.setId("d584352b7a76776db5f534df")
|
|
639
|
+
.setSubType(CustomChartSubType.ECHARTS_LITE)
|
|
640
|
+
.loadContent("charts/profit_map")
|
|
641
|
+
.addDataView(dataView);
|
|
642
|
+
|
|
643
|
+
registerCustomChart(chart.build());
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
`charts/profit_map.js`(ECharts 地图渲染,需配套 `china.json`):
|
|
647
|
+
```javascript
|
|
648
|
+
// source: guandata-web 内置地图或 https://geo.datav.aliyun.com/...
|
|
649
|
+
var chinaGeoJSON = JSON.parse(__asset_text("./china.json")__);
|
|
650
|
+
|
|
651
|
+
var cols = data[0] || [];
|
|
652
|
+
var names = (cols[0] || {}).data || [];
|
|
653
|
+
var values = (cols[1] || {}).data || [];
|
|
654
|
+
|
|
655
|
+
var mapData = [];
|
|
656
|
+
for (var i = 0; i < names.length; i++) {
|
|
657
|
+
mapData.push({ name: names[i], value: +(values[i]) || 0 });
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
echarts.registerMap("china", chinaGeoJSON);
|
|
661
|
+
|
|
662
|
+
option = {
|
|
663
|
+
tooltip: { trigger: "item" },
|
|
664
|
+
visualMap: { min: -0.3, max: 0.3, calculable: true,
|
|
665
|
+
inRange: { color: ["#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"] } },
|
|
666
|
+
series: [{ type: "map", map: "china", label: { show: true, fontSize: 10 }, data: mapData }]
|
|
667
|
+
};
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
> **适用场景**:ECHARTS_LITE 自定义地图仅适用于不需要其他 JS 库的简单场景。Tableau 迁移场景应使用 **SDK 模式**(支持 Vega-Lite 等更灵活的库)。中国地图优先使用 `BASIC_MAP` 内置图表。
|
|
671
|
+
|
|
672
|
+
### 枚举常量
|
|
673
|
+
|
|
674
|
+
| 枚举 | 常用值 | 说明 |
|
|
675
|
+
|------|--------|------|
|
|
676
|
+
| `ChartType` | `BASIC_COLUMN`, `BASIC_BAR`, `BASIC_LINE`, `PIE`, `PIVOT_TABLE`, `DETAIL_TABLE`, `KPI_CARD`, `BASIC_MAP`, `WORLD_MAP`, `POINT_MAP`, `BUBBLE_MAP` 等 74 种 | 图表类型(与后端 ChartType.scala 一一对应)。地图类型使用 `addRow()` 放地理维度 |
|
|
677
|
+
| `AggrType` | `SUM`, `AVG`, `COUNT`(=CNT), `COUNT_DISTINCT`(=CNT_DISTINCT), `MIN`, `MAX` | 聚合类型 |
|
|
678
|
+
| `FieldType` | `STRING`, `INT`, `LONG`, `DOUBLE`, `FLOAT`, `DATE`, `BOOL`, `DECIMAL` | 字段数据类型 |
|
|
679
|
+
| `SortOrder` | `ASC`, `DESC` | 排序方向 |
|
|
680
|
+
| `Granularity` | `NONE`, `YEAR`, `QUARTER`, `MONTH`, `WEEK`, `DAYOFWEEK`, `DAY`, `HOUR`, `MINUTE`, `SECOND` | 日期粒度 |
|
|
681
|
+
| `FilterType` | `IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `ENDSWITH`, `IS_NULL`, `NOT_NULL` | 筛选条件类型 |
|
|
682
|
+
| `FilterLevel` | `DETAIL`(明细), `AGGREGATION`(聚合), `RESULT`(结果) | 筛选级别 |
|
|
683
|
+
| `NumberFormat` | `.number()`, `.currency()`, `.percentage()`, `.auto()`, `.custom()` | 数值格式化工厂 |
|
|
684
|
+
| `SelectorType` | `DS_ELEMENTS`(默认), `DS_INTERVAL`, `CALENDAR`, `TIME_MACRO` | 筛选器类型 |
|
|
685
|
+
| `SelectorDisplay` | `SEARCH_LIST`(单选下拉), `SEARCH_BOX`(多选下拉), `CHECKBOX`(复选框), `RADIO`(单选框), `BUTTON_GROUP`(按钮组) | 筛选器展示类型,不设置时根据 multiSelect 自动推断 |
|
|
686
|
+
| `SelectorDefaultType` | `FIRST_PICK`(默认), `FIXED_VALUE`, `ALL`(全部/不筛选) | 筛选器默认值类型 |
|
|
687
|
+
| `CardType` | `CHART`(0), `TEXT`(1), `IFRAME`(2), `PICTURE`(4), `SELECTOR`(6) | 卡片类型(内部使用,通常不需要直接引用) |
|
|
688
|
+
| `ImageSourceType` | `OUTSIDE_LINK`(1), `LOCAL_IMAGE`(2) | 图片来源类型 |
|
|
689
|
+
| `ImageRenderType` | `RATIO`(1,原比例), `STRETCH`(2,拉伸填满), `FIT_TO_CONTENT`(3,自适应内容) | 图片渲染模式 |
|
|
690
|
+
| `CustomChartSubType` | `SDK`(iframe,首选), `ECHARTS_LITE`(原生 ECharts) | 自定义图表子类型 |
|