@guandata/guanvis 0.1.34 → 0.1.35
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 +8 -0
- package/README.md +8 -3
- 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 +1 -1
- package/skills/guanvis/SKILL.md +117 -341
- package/skills/guanvis/references/api-reference.md +1 -0
- package/skills/guanvis/references/builder-reference.md +37 -85
- package/skills/guanvis/references/chart-properties.md +1051 -0
- package/skills/guanvis/references/checkout-editing.md +51 -0
- package/skills/guanvis/references/complex-report-pro-patterns.md +43 -0
- package/skills/guanvis/references/metric-chart-reference.md +13 -3
- package/skills/guanvis/references/publish-and-constraints.md +2 -2
package/skills/guanvis/SKILL.md
CHANGED
|
@@ -6,88 +6,72 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
|
|
|
6
6
|
|
|
7
7
|
# guanvis
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
执行型 skill:通过 AI 编写的 JS 脚本创建/修改 BI Card 和 Page 资源。
|
|
10
10
|
|
|
11
|
-
- AI 生成 `card_*.js`
|
|
12
|
-
-
|
|
13
|
-
- 框架内置验证规则,在 pack/publish 时检查字段数量、zone 兼容性、必填字段等。
|
|
14
|
-
- 认证通过 `guancli` 共享配置自动获取。
|
|
11
|
+
- AI 生成 `card_*.js` 定义 Card;`page.js` 组装仪表板。`schema.js` 由 `init`/`checkout` 生成(不允许 AI 修改,checkout 生成是 best-effort);指标卡片用 `metric-init` 生成 `metrics.js`。
|
|
12
|
+
- 框架在 preview/pack/publish 时内置验证(字段数量、zone 兼容性、必填字段等);认证复用 `guancli` 共享配置。
|
|
15
13
|
|
|
16
14
|
## Harness 化工作法
|
|
17
15
|
|
|
18
16
|
把可视化生成当作源文件驱动的构建流程:本地 JS DSL 是可编辑事实源,payload、ZIP、线上 Card/Page 都是从源文件生成的派生产物。
|
|
19
17
|
|
|
20
18
|
- `schema.js` 是由 `init` / `checkout` 生成的数据集事实快照,不手改;数据集字段变化时重新运行对应命令。`metrics.js` 是由 `metric-init` 生成的指标事实快照,不手改;指标口径、适用维度或格式变化时重新运行 `metric-init`。
|
|
21
|
-
-
|
|
19
|
+
- `theme-colors.js` 是项目级图表主题色事实快照,不手改。准备在脚本中使用 `setThemeColor()` 前,先检查项目根目录;不存在时先运行 `guanvis theme-color sync -d <project>`。调用 `setThemeColor()` 切换主题时必须从快照选择真实 `tcId`,不得猜测或编造。已有文件直接复用,主题色列表变化或切换 BI 环境时用 `theme-color sync` 刷新;快照会记录实际选中的 profile、服务地址和 domain,通过环境变量或默认 profile 切换环境后,构建都会拒绝复用旧快照。`preview`/`diff`/`pack`/`publish` 对缺失快照的自动生成只作兜底。
|
|
20
|
+
- 全局参数先用 `guanvis parameter` 创建或复用,再通过 `dynamic-parameters.js` 按 `dpId` 引用;`pack`/`publish` 不会隐式写入参数。创建前必须按名称查询;发现同名有效参数时立即停止,让用户明确选择"更新已有参数"或"换名创建",不得自动复用或修改。
|
|
22
21
|
- `card_*.js`、`selector_*.js`、`page.js` 是可编辑源文件;`*_package.zip`、`.preview.json`(preview 落盘的全量 payload)、publish 后线上资源都是派生产物,不要手工编辑。
|
|
23
|
-
- **Page
|
|
24
|
-
- 已有线上仪表板用 `guanvis checkout <pgId> -d <dir>`
|
|
25
|
-
- **Checkout
|
|
26
|
-
- **Checkout JSON 红线**:`.guanvis/raw/**`、`.guanvis/base/**`、`.guanvis/manifest.json`
|
|
22
|
+
- **Page 归属红线**:包含 Card/Selector 的资源包必须同时包含 Page,且每个 Card/Selector 都必须被至少一个 Page 引用;否则后端会产生 `pg_id` 为空、无法访问且可能阻塞后续发布的孤儿卡片。校验失败时在 `page.js` 中放置对应资源后同包发布。
|
|
23
|
+
- 已有线上仪表板用 `guanvis checkout <pgId> -d <dir>` 拉成可编辑工程(attachCard 基线、自定义图表 `charts/` 反编译、Pro 模板 `templates/`、Page 布局脚本)。checkout 工程只用于修改指定 Page,不用于复制新 Page;只支持普通仪表板(pgType=PAGE),DSL 不能安全表达的结构会直接失败而不是清结构。**checkout 工程动手前先读 `references/checkout-editing.md`**。
|
|
24
|
+
- **Checkout 账号红线**:checkout 读到的是"当前账号视角",publish 整体回写。必须用对涉及数据集有**完整列权限、无脱敏限制**的账号(推荐 owner 或管理员)执行 checkout/publish,否则被裁剪的字段会在回写后从线上卡片永久丢失;多语言租户操作账号语言须与卡片原始语言一致。
|
|
25
|
+
- **Checkout JSON 红线**:`.guanvis/raw/**`、`.guanvis/base/**`、`.guanvis/manifest.json` 是只读快照。Agent 不得修改这些 JSON,也不得复制 checkout JSON 改副本创建新资源;现有卡片修改必须通过 `attachCard(...)` 的 DSL 操作表达(优先 `update*/patch*/add*/remove*/move*`,整 zone 重建的 `set*/clear*` 会触发 warning),新增卡片必须用 `createCard()` / `createSelector()` 工厂函数;操作清单见 `references/checkout-editing.md` §3。
|
|
27
26
|
- Card/Page 描述也是 JS 源文件的一部分:新建看板或改版时,在 `card_*.js` / `page.js` 中写 `.setDescription(...)`,再通过 `preview`/`pack`/`publish` 从 JS 源文件生成并发布资源。
|
|
28
27
|
- 写脚本前先形成 dashboard contract:目标用户、业务问题、使用的数据集、核心指标、维度拆解、筛选器、页面结构和验证方式。
|
|
29
28
|
- 每次生成都针对明确目录或明确子目录;不要把 unrelated 示例、旧包或临时 ZIP 混入同一个发布目标。
|
|
30
|
-
- Card/Page/Selector 的 `.setId(...)`
|
|
31
|
-
- 先 `preview` 做本地结构验证,再 `publish`(publish 自带构建打包上传,**发布前不需要单独 `pack`**;`pack` 只用于生成离线 ZIP
|
|
32
|
-
- **编辑红线(编辑 ≠
|
|
29
|
+
- Card/Page/Selector 的 `.setId(...)` 用 `guanvis genid` 生成(保证字母开头);数字开头 ID 会触发 BI 前端 CSS selector 语法错误,新建资源校验直接报 error 拦截(checkout/attach 的已有资源保留原 ID 不受限)。
|
|
30
|
+
- 先 `preview` 做本地结构验证,再 `publish`(publish 自带构建打包上传,**发布前不需要单独 `pack`**;`pack` 只用于生成离线 ZIP 走 `upload`)。仅修复描述用 `card/page set-description` 并同步 JS 中的 `.setDescription(...)`;改看板内容按「线上仪表板更新红线」处理。
|
|
31
|
+
- **编辑红线(编辑 ≠ 删除重建)**:修改/改名已发布 Page 或 Card 必须保留原 pgId/cdId 原地覆盖发布。本地源工程还在且线上未被网页端改动 → 直接改本地 JS 同 ID 重新 publish;否则 → `checkout` 后编辑,且**不得**把 `attachCard` 改写成 `createCard()`(绕过 base JSON 会丢线上配置)。**禁止**用"新建 + 删除旧的"模拟编辑——资源 ID 变化会让收藏、分享、订阅、门户引用和页面权限全部失效且无法迁移;"保留旧页面出新版本"用 `guanvis page save-as`。全局参数同理只能 `parameter update <dpId>` 原地更新,禁止 delete 后重建同名参数(dpId 断链)。分流决策见 `references/checkout-editing.md` §4。
|
|
33
32
|
- **资源包安全红线**:Agent 只编辑 DSL 源文件;资源包 ZIP 是 `guanvis pack/publish` 的派生产物,不手工生成、解包修改或重打包。`guanvis upload` 只允许上传 `guanvis pack` 原样生成的 ZIP。若用户要求批量重绑资源、迁移已有页面或复用线上页面结构,先停下来说明风险并确认方案,不要直接改 ZIP。
|
|
34
|
-
- 发布后优先用 `guancli page get/card get`
|
|
33
|
+
- 发布后优先用 `guancli page get/card get` 回读结构与配置;`guanvis screenshot` 仅在明确需要视觉质量判断且模型支持图像理解时使用(额外消耗 token),不作默认闭环步骤。
|
|
35
34
|
|
|
36
35
|
## AI Quick Reference(速查,详细说明见按需参考资料)
|
|
37
36
|
|
|
38
|
-
**Checkout/attachCard 速记**:`attachCard(cardId, jsonPath)`
|
|
37
|
+
**Checkout/attachCard 速记**:`attachCard(cardId, jsonPath)` 是"base JSON + 链式 DSL 操作 = 目标 JSON",不修改 base JSON,重复执行产出相同 payload。zone 修改优先 `update*/patch*/add*/remove*/move*`(整 zone 重建的 `set*/clear*` 会触发 warning);已有 selector 用 `.addLink()/.removeLink()/.clearLinks()` 改联动;自定义图表内容编辑仅限 SDK/ECHARTS_LITE(编辑 `charts/` 下反编译源文件),COMPLEX_REPORT/PLUGIN/PLUGIN_LITE/REPORT_FORM 调内容编辑 API 直接报错。发布前用 `guanvis diff <dir>` 或 preview 的 `changeSummary` 查看影响面;没有 DSL 操作覆盖的需求先扩展 DSL,不改 `.guanvis` JSON。完整操作语义(zone/筛选区/筛选栏画布互移等)见 `references/checkout-editing.md` §3。
|
|
39
38
|
|
|
40
|
-
**字段显示名与 Card 标题**:`createCard()` 第二参数是 Card
|
|
39
|
+
**字段显示名与 Card 标题**:`createCard()` 第二参数是 Card 标题,与字段显示名独立。图例/轴标题/表头/Tooltip/指标标签都用字段显示名,需要与物理字段名或 calcField 内部名分开时设置 `alias`(如 `f("营收", { alias: "本月营收" })`);`SINGLE_VALUE`/`KPI_CARD`/`KPI_TREND` 和仪表盘/进度类尤其明显。
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
**图表属性配置**:设置图表属性时,先读 `references/chart-properties.md`,按其中的方法和参数配置。
|
|
42
|
+
|
|
43
|
+
1. **工厂函数**:数据集图表 `createCard()`;复杂报表 Pro `createComplexReportPro()` + `createReportWorkbook()`;已有线上普通卡片 `attachCard(cardId, jsonPath)`;指标卡片 `createMetricChart()`;筛选器/文本/图片/杜邦/Tab/页面用对应工厂函数,不要 `new XxxBuilder()`。旧版复杂报表拒绝,Pro 父卡不能用泛化 `attachCard()`
|
|
44
|
+
2. **注册函数**:`registerCard` / `registerComplexReportPro` / `registerMetricChart` / `registerSelector` / `registerTextCard` / `registerImageCard` / `registerDuPontChart` / `registerPage`,入参一律 `xxx.build()`
|
|
44
45
|
3. **字段引用**:单数据集用 `f("字段名")`,多数据集用 `field(DS, "字段名")`
|
|
45
46
|
4. **zone maxCount**:`BASIC_COLUMN/BAR/LINE` metric=1;`GROUPED_*/STACKED_*` metric=∞;`KPI_CARD` metric=1;组合图 `*_WITH_LINE` row=1
|
|
46
47
|
5. **column vs colorBy**:column 放维度(按类别分组着色),colorBy 放度量(按值渐变着色)
|
|
47
|
-
6.
|
|
48
|
+
6. **原生聚合优先**:单字段聚合用 `f("字段", { aggrType: AggrType.XXX })`(SUM/AVG/COUNT/COUNT_DISTINCT/MIN/MAX),不要用 `calcField()` 手写 SQL 聚合函数(如 `COUNT_DISTINCT([字段])`)
|
|
48
49
|
7. **calcField 命名**:不能与数据集物理字段同名,否则 BI 默认取数据集字段
|
|
49
50
|
8. **calcField 类型**:`aggregation`(默认)公式必须含聚合函数;纯算术用 `{ calculationType: "normal" }`;窗口函数用 `{ calculationType: "window" }`
|
|
50
|
-
9. **明细/滚动表 calcField**:`DETAIL_TABLE
|
|
51
|
-
10.
|
|
52
|
-
11. **selector
|
|
53
|
-
12.
|
|
54
|
-
13. **placeCard
|
|
55
|
-
14. **publish
|
|
56
|
-
15. **更新线上仪表板**:checkout
|
|
57
|
-
16.
|
|
58
|
-
17.
|
|
59
|
-
18.
|
|
60
|
-
19.
|
|
61
|
-
20.
|
|
62
|
-
21.
|
|
63
|
-
22. **资源包/checkout JSON 禁止手改**:只改 DSL
|
|
64
|
-
23.
|
|
65
|
-
24. **复杂报表 Pro
|
|
66
|
-
- **Pro 不是默认功能,需要单独授权**:只有用户明确说了"复杂报表 / 复杂报表 Pro",或修改的卡片本身已是 Pro(checkout 保持原类型),才选 Pro;用户只说"表格/报表/透视表"一律用原生卡片(DATA_GRID/PIVOT_TABLE 等),版式做不到时告知用户"Pro 可实现但需授权"由用户决定。
|
|
67
|
-
- 只支持 `COMPLEX_REPORT_PRO`;旧版复杂报表拒绝,Pro 父卡不能用泛化 `attachCard()`。从零创建优先 Workbook DSL,拿到现成 xlsx 才用 `.setTemplate()`。
|
|
68
|
-
- 同一数据视图只写 `context`,绝不加同源 `filterBy`(嵌套 LP 后端 500);`filterBy` 仅用于跨数据视图父格映射。
|
|
69
|
-
- 左父格(纵向)允许在其列或左侧的**任意行**(阶梯布局、"汇总在上"总计/小计行挂下方维度均合法);上父格(横向)必须同列上方;各最多一个,双父格写 `A4*B3`。
|
|
70
|
-
- 小计三件套:维度父格 → `setContextText` 标签 → `bindSubtotal`(标签同行左侧);总计 `bindGrandTotal` 禁止 context;小计行公式聚合用 `setDynamicFormula("SUM(D2)", { context: 标签格 })`;不要写老版 `G_SUBTOTAL/G_GRANDTOTAL`。
|
|
71
|
-
- 聚合白名单 `SUM/COUNT/AVERAGE/MAX/MIN/PRODUCT/STDDEV/STDDEVP/VAR/VARP`(`AVG`→`AVERAGE`,`COUNTA` 拒绝);`bindDimension` 字段必须 DIM,数值列不能做维度。
|
|
72
|
-
- 分页:单 Sheet、全模板禁 `filter/filterBy`、唯一 `countPerPage` 放无 context 顶层维度。段落块用 `sheet.beginBlock()`。多源 JOIN 用 `.setDataSourceRelations()`。
|
|
73
|
-
- 模板引用的每个字段都必须进对应子视图查询区;子视图 `.setLimit()` 不限制导出行数。
|
|
74
|
-
- 排序放数据视图 `.addSort()`(决定模板展开顺序);行级链接用 `HYPERLINK()` 动态公式(模板格超链接不随扩展复制);涨跌着色可直接用条件数字格式 `[Red]0"↑";[Green]0"↓"`。
|
|
75
|
-
- **计算 BI 优先**:行级公式→guands 普通计算字段;比率/均值等非可加指标→聚合计算字段(`--calc-type aggregation`,引用时不写 aggrType),其小计/总计=每个粒度一个数据视图(禁用 bindSubtotal,会把比率按明细求和);GcExcel `setDynamicFormula` 只做排版级算术(序号/HYPERLINK/单格换算)。模板 `aggregate: COUNT` 作用于视图行不是明细行,计数放视图 zone 模板用 SUM 透传。
|
|
76
|
-
- 新建 Pro 必须与引用它的 Page 同包发布,ID 用 `guanvis genid` 生成;pack/preview 通过≠语义正确,发布后必须 `guancli card preview <proCardId> -o result.xlsx` 检查无 `{{...}}` 残留。发布失败后重试若持续报"找不到相关卡片",直接 `genid` 换新 ID 重发。
|
|
77
|
-
- 编辑已有 Pro 模板:统一走 `.setWorkbook()`。`report decompile` 全量可表达时输出 `createReportWorkbook()` 从零形态;含图片/数据验证等 lossy 部件时输出 `createReportWorkbook("templates/<cdId>.xlsx").editSheet(...)` 基底编辑形态(增量操作,未触及部件原样保留;覆盖模板格需 `{ overwrite: true }`,删除用 `clearCell`/`unmerge`)。publish 成功后 CLI 自动 bump JS 里的 `.setTemplateVersion()`;若提示未找到该调用,下轮改模板前必须手动 +1,否则命中服务端模板缓存静默不生效。
|
|
51
|
+
9. **明细/滚动表 calcField**:`DETAIL_TABLE`/`SCROLL_TABLE` 只逐行展示,行级计算必须 `{ calculationType: "normal" }` 且禁用聚合/窗口函数;汇总需求改用非明细图表或 ETL 预计算
|
|
52
|
+
10. **联动/下钻**:新建筛选器联动图表必须 `.linkToAll()` 或 `.linkTo(cardIndex)`;已有筛选器用 `attachCard(...).addLink()/.removeLink()/.clearLinks()`;筛选器级联用 `.linkToSelector(selectorId, targetFieldName?)`;卡片联动卡片用 `card.linkTo(layoutCardIndex, { fields: [{ source, target }] })`;固定路径下钻用 `registerDrillPath(parentCardIndex, [child.build()], { position: DrillPathPosition.BOTTOM })`;详细规则见 `references/builder-reference.md`
|
|
53
|
+
11. **selector 类型**:离散值 → `DS_ELEMENTS`(默认);连续数值 → `SelectorType.DS_INTERVAL`;日期 → `CALENDAR`;快捷日期区间(本月/近7天等)→ `.setTimeMacroOptions(options)`
|
|
54
|
+
12. **同环比默认**:未指定输出值时默认增长率;未指定模式时默认 `ComparativeMode.FILTER_BASED`(普通模式需显式 `NORMAL`)。日期字段已是预聚合周期字段(如 `月开始日期`)时必须声明 `{ granularity: Granularity.NONE }`,避免按 DAY 筛选窗口计算为空
|
|
55
|
+
13. **placeCard 入参**:优先用 card/selector ID 字符串(checkout 工程与子目录工程必须用),如 `placeCard("cardId", x, y, w, h)`。数字 index 仅限新建工程,按可布局资源(registerCard/MetricChart/TextCard/ImageCard/CustomChart/DuPontChart)的注册顺序累加,文件按文件名排序加载;**registerSelector 不参与 card index 计数**——selector 进画布/布局组件一律用其 ID 字符串。
|
|
56
|
+
14. **publish 认证**:由底层 CLI 负责——guancli 先 `guancli auth use <profile>`,guancli-lite 用环境变量
|
|
57
|
+
15. **更新线上仪表板**:checkout 工程 = 修改指定线上 Page,保留原资源 ID;CLI 检测到同 ID Page 时必须先向用户说明覆盖影响并取得明确确认,才可加 `--allow-overwrite`(自带覆盖备份兜底)。要"保留原页面出新版本"用 `guanvis page save-as <pgId> --suffix _guanvis`(BI 原生整页另存为,服务端重映射全部卡片间引用),不要复制 checkout JSON 改 ID;细节见 `references/checkout-editing.md` §5
|
|
58
|
+
16. **描述维护**:仅修复已发布资源描述时保留原 ID,用 `guanvis card/page set-description`;本地有 JS 工程时同步更新 `.setDescription(...)`
|
|
59
|
+
17. **主题切换**:用户描述风格 → 工程目录里 `guanvis theme preference --keywords "..." --sync`;不要选租户默认"浅色"/"深色",没有合适主题就保持/清空偏好用内置"简约"兜底;改版未提风格时 `.applied.json` 自动继承上次主题。多子目录工程主题按子目录独立配置和执行;详见 `references/theme.md`
|
|
60
|
+
18. **设计规则**:preview/pack/publish 自动应用内置设计规则;自定义时在工程目录新建 `design-rule.json`,不手改 `themes/<themeId>.json`;详见 `references/theme.md`
|
|
61
|
+
19. **"指标卡片"语义分流**:数据集字段做单值/KPI → `SINGLE_VALUE` / `KPI_CARD`;用指标平台已有指标建卡 → 先 `guanvis metric-init <metricId>` 再 `createMetricChart()` + `metric()`/`metricDim()`;复杂指标卡片参数先读 `references/metric-chart-reference.md`
|
|
62
|
+
20. **杜邦分析图**:用 `createDuPontChart()` 创建 `LAYOUT` 卡片(非普通 ChartType),节点放 `KPI_CARD` 子卡并用 `.setRoot()`/`.addChild()` 组织树;页面只放杜邦父卡片,筛选器 `linkToAll()` 会覆盖杜邦子卡片
|
|
63
|
+
21. **布局组件**:AreaTitle/CardGroup/SelGroup/Tab 只支持放画布根布局、不支持嵌套组合;SelGroup 内只能放 selector;详见 `references/builder-reference.md`
|
|
64
|
+
22. **资源包/checkout JSON 禁止手改**:只改 DSL 源文件,不改 ZIP 内部文件与 `.guanvis/**` JSON;批量重绑、迁移页面等需求先讨论方案,必要时扩展 DSL,不手工改生成物。
|
|
65
|
+
23. **动态字段**:用户明确需要字段切换时用 `.addDynamicRow()` / `.addDynamicMetric()` 等(普通卡动态维度/数值,指标卡动态维度/指标);细节见 `references/builder-reference.md`。
|
|
66
|
+
24. **复杂报表 Pro**:非默认功能,需单独授权——只有用户明确点名"复杂报表 / 复杂报表 Pro"或被修改卡片已是 Pro 才选 Pro;用户只说"表格/报表/透视表"一律用原生卡片(DATA_GRID/PIVOT_TABLE 等),版式做不到时告知"Pro 可实现但需授权"由用户决定。动手前必读 `references/complex-report-pro-patterns.md`(§0 选型、§2 配方、§3 数据视图规则、§4 报错修复、§5 编辑闭环、§6 验证闭环),全部结构红线与修复表以该文件为准;工作流程见下文「复杂报表 Pro 工作方式」
|
|
78
67
|
|
|
79
68
|
## 何时使用
|
|
80
69
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
- 创建或 checkout/edit 复杂报表 Pro——**仅当用户明确点名"复杂报表 / 复杂报表 Pro",或被修改的卡片已是 Pro**(Pro 需单独授权,不是默认功能,泛化的"做个表格/报表"需求用原生卡片);旧版复杂报表则明确拒绝并建议外部迁移后新建 Pro。
|
|
87
|
-
- 创建筛选器并配置联动关系(选择筛选器、日历筛选器等)。
|
|
88
|
-
- 组装多个 Card 和筛选器为一个仪表板/Page,含 grid layout 布局和筛选器面板。
|
|
89
|
-
- 批量生成一组 Card 并上传到 BI 系统。
|
|
90
|
-
- 用户提到 `card.js`、`page.js`、CardPayload、图表类型、chart axes、zone spec、筛选器联动。
|
|
70
|
+
- 新建观远 BI Card(柱形/折线/饼/表格/KPI/散点/漏斗/地图等 30+ 种)、文本卡片、图片卡片。
|
|
71
|
+
- 基于指标平台已有指标创建指标卡片(MetricChart,后端 `cdType=13`)。
|
|
72
|
+
- 创建或 checkout/edit 复杂报表 Pro——**仅当用户明确点名"复杂报表 / 复杂报表 Pro"或被修改卡片已是 Pro**(需单独授权;泛化"做个表格/报表"用原生卡片);旧版复杂报表明确拒绝并建议外部迁移后新建 Pro。
|
|
73
|
+
- 创建筛选器并配置联动;组装 Card 和筛选器为仪表板/Page(grid layout + 筛选器面板)。
|
|
74
|
+
- 用户提到 `card.js`、`page.js`、CardPayload、图表类型、zone spec、筛选器联动。
|
|
91
75
|
|
|
92
76
|
## 固定工作方式
|
|
93
77
|
|
|
@@ -102,49 +86,30 @@ guancli auth status
|
|
|
102
86
|
### 2. 生成 schema.js(只做一次或数据集变更时重新生成)
|
|
103
87
|
|
|
104
88
|
```bash
|
|
105
|
-
# 查找数据集
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
# 生成 schema.js(传入数据集 ID)
|
|
109
|
-
guanvis init <dsId1> <dsId2> -d ./my_dashboard/
|
|
89
|
+
guancli ds search <关键词> # 查找数据集 ID
|
|
90
|
+
guanvis init <dsId1> <dsId2> -d ./my_dashboard/ # 生成 schema.js(多数据集加 --alias 命名全局变量)
|
|
110
91
|
```
|
|
111
92
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
生成的 `schema.js` 示例:
|
|
115
|
-
```javascript
|
|
116
|
-
// Auto-generated — DO NOT EDIT
|
|
117
|
-
defineDataset("s9ded2338f43807b095fbb4f", [
|
|
118
|
-
{ fdId: "jb16f22f6c1c21c3f6e8e293", name: "区域", fdType: "STRING", metaType: "DIM" },
|
|
119
|
-
{ fdId: "lb1c31b4dc86511a27049a98", name: "营收", fdType: "DOUBLE", metaType: "METRIC" },
|
|
120
|
-
// ...
|
|
121
|
-
], { displayType: "EXCEL" });
|
|
122
|
-
```
|
|
93
|
+
用户给的是业务目录名时,先 `guancli ds tree` 定位目录再按真实数据集名搜索,不要把目录名当数据集名反复 `ds search`。生成的 `schema.js` 是 `defineDataset(dsId, [{ fdId, name, fdType, metaType }...])` 形态的事实快照,不可编辑。
|
|
123
94
|
|
|
124
95
|
### 2b. 生成 metrics.js(创建指标平台指标卡片时)
|
|
125
96
|
|
|
126
|
-
|
|
97
|
+
用户给的是指标平台 metric ID/指标名时走这条链路,不要把指标当数据集字段:
|
|
127
98
|
|
|
128
99
|
```bash
|
|
129
|
-
|
|
130
|
-
guancli metric search '<关键词>'
|
|
131
|
-
|
|
132
|
-
# 生成指标事实快照
|
|
100
|
+
guancli metric search '<关键词>' # 用户只给名称时先查 ID
|
|
133
101
|
guanvis metric-init <metricId1> <metricId2> -d ./my_dashboard/
|
|
134
102
|
```
|
|
135
103
|
|
|
136
|
-
生成后在 `card_*.js` 中使用:
|
|
137
|
-
|
|
138
104
|
```javascript
|
|
139
105
|
var card = createMetricChart(ChartType.PIVOT_TABLE, "销售指标分析")
|
|
140
106
|
.setId("cardId24chars")
|
|
141
107
|
.addRow(metricDim("销售额", "区域"))
|
|
142
108
|
.addMetric(metric("销售额"));
|
|
143
|
-
|
|
144
109
|
registerMetricChart(card.build());
|
|
145
110
|
```
|
|
146
111
|
|
|
147
|
-
`metrics.js` 和 `
|
|
112
|
+
`metrics.js`、`dynamic-parameters.js` 和 `theme-colors.js` 必须在 `card_*.js` 前加载;目录模式会自动按 `schema.js` → `metrics.js` → `dynamic-parameters.js` → `theme-colors.js` → `card_*.js` → `selector_*.js` → `page.js` 的顺序执行。
|
|
148
113
|
|
|
149
114
|
### 3. 设置仪表板主题(按需)
|
|
150
115
|
|
|
@@ -152,75 +117,28 @@ registerMetricChart(card.build());
|
|
|
152
117
|
|
|
153
118
|
```bash
|
|
154
119
|
cd ./my_dashboard
|
|
155
|
-
|
|
156
|
-
# (
|
|
157
|
-
guanvis theme
|
|
158
|
-
|
|
159
|
-
# (b) 用户给出明确 themeId
|
|
160
|
-
guanvis theme preference --theme-id custom_blue --sync
|
|
161
|
-
|
|
162
|
-
# (c) 想先看看候选名字
|
|
163
|
-
guanvis theme sync # 拉列表
|
|
164
|
-
guanvis theme list # 看候选 themeId / themeName / themeType
|
|
120
|
+
guanvis theme preference --keywords "深色 科技" --sync # (a) 用户描述了风格关键词
|
|
121
|
+
guanvis theme preference --theme-id custom_blue --sync # (b) 用户给出明确 themeId
|
|
122
|
+
guanvis theme sync && guanvis theme list # (c) 先看候选名字再决定
|
|
165
123
|
```
|
|
166
124
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
命令产出的目录形态(与 `schema.js` 同级):
|
|
170
|
-
|
|
171
|
-
```
|
|
172
|
-
my_dashboard/
|
|
173
|
-
├── schema.js
|
|
174
|
-
├── themes/
|
|
175
|
-
│ ├── .preference.json # theme preference 写入的偏好(themeId / keywords)
|
|
176
|
-
│ ├── .index.json # theme sync 拉到的候选主题索引
|
|
177
|
-
│ ├── .sync-meta.json # syncedAt / count
|
|
178
|
-
│ ├── default_7.json # theme sync 落盘的主题快照(每个 themeId 一份)
|
|
179
|
-
│ └── custom_blue.json
|
|
180
|
-
└── ... (card_*.js / page.js 后面再加)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
`.applied.json` 会在第一次 `pack`/`publish` 实际使用了线上主题时自动写入;这之前不存在很正常。回退到 skill 自带 `simple.json` 时**故意不写** `.applied.json`,避免污染下次解析。
|
|
184
|
-
|
|
185
|
-
何时跳过这一步:
|
|
186
|
-
|
|
187
|
-
- **改版已有看板**(工程下已存在 `themes/.applied.json`)→ 跳过,`pack`/`publish` 会自动继承上次主题。
|
|
188
|
-
- **新看板但用户没描述风格** → 跳过,自动落到 skill 自带的 `simple.json`(与原行为一致;离线/弱网都不会失败)。
|
|
189
|
-
- **候选主题只剩默认“浅色”/“深色”或都不贴合需求** → 不要为了命中而随便选,清空/不写偏好并使用内置“简约”兜底。
|
|
190
|
-
- 后续用户改主意要换风格 → 再跑一次 `theme preference` 就行,不需要重做 schema 或 card。
|
|
191
|
-
|
|
192
|
-
完整决策规则、`themes/` 目录结构、离线 vs 联网约定见 `references/theme.md`。
|
|
125
|
+
何时跳过:改版已有看板(`.applied.json` 自动继承上次主题)、新看板但用户没描述风格(自动落到内置 `simple.json`)、候选只剩默认"浅色"/"深色"或都不贴合(不要随便选,清空/不写偏好用内置"简约"兜底)。多子目录工程的主题各子目录独立配置和执行。完整决策规则、`themes/` 目录文件说明、离线 vs 联网约定、排错见 `references/theme.md`。
|
|
193
126
|
|
|
194
127
|
### 4. 编写 card 脚本
|
|
195
128
|
|
|
196
|
-
card
|
|
129
|
+
card 脚本用 `field(DS, "字段")` 或单数据集简写 `f("字段")` 从 schema 引用字段(无需记忆 fdId):
|
|
197
130
|
|
|
198
131
|
```javascript
|
|
199
|
-
// card_01_revenue.js
|
|
132
|
+
// card_01_revenue.js
|
|
200
133
|
var card = createCard(ChartType.GROUPED_COLUMN, "营收分析")
|
|
201
134
|
.bindDataset(DS)
|
|
202
|
-
.setDescription("
|
|
203
|
-
.addRow(field(DS, "区域"))
|
|
204
|
-
.addMetric(field(DS, "营收", {
|
|
205
|
-
aggrType: AggrType.SUM,
|
|
206
|
-
numberFormat: NumberFormat.currency("¥", 0)
|
|
207
|
-
}))
|
|
208
|
-
.addColumn(field(DS, "产品"))
|
|
209
|
-
.setShowLegend(true, "right")
|
|
210
|
-
.setDataLabel({ show: true, showNumber: true });
|
|
211
|
-
|
|
212
|
-
registerCard(card.build());
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
```javascript
|
|
216
|
-
// card_02_pivot.js — 使用 f() 简写(单数据集场景)
|
|
217
|
-
var card = createCard(ChartType.PIVOT_TABLE, "区域产品交叉分析")
|
|
218
|
-
.bindDataset(DS)
|
|
135
|
+
.setDescription("业务故事:回答各区域营收规模与产品结构差异,面向经营管理层。营收按 SUM 聚合。")
|
|
219
136
|
.addRow(f("区域"))
|
|
220
137
|
.addColumn(f("产品"))
|
|
221
|
-
.addMetric(f("营收", { aggrType: AggrType.SUM }))
|
|
138
|
+
.addMetric(f("营收", { aggrType: AggrType.SUM, numberFormat: NumberFormat.currency("¥", 0) }))
|
|
222
139
|
.addSort(f("营收", { aggrType: AggrType.SUM, sortType: SortOrder.DESC }))
|
|
223
|
-
.
|
|
140
|
+
.setShowLegend(true, "right")
|
|
141
|
+
.setDataLabel({ show: true, showNumber: true });
|
|
224
142
|
|
|
225
143
|
registerCard(card.build());
|
|
226
144
|
```
|
|
@@ -240,238 +158,95 @@ var page = createPage("销售仪表板")
|
|
|
240
158
|
registerPage(page.build());
|
|
241
159
|
```
|
|
242
160
|
|
|
243
|
-
|
|
161
|
+
**仪表板主题**:没配 `themes/` 时 `preview`/`pack`/`publish` 自动使用内置简约主题(不依赖租户线上主题列表);普通图表与指标平台 MetricChart 都会自动应用主题视觉配置(只写 `settings` 与 `meta.chartMain.props`,不改 `zoneData` 等查询字段)。**JS DSL 不提供主题接口**——`setDashboardTheme(...)` / `page.setTheme(...)` 会因函数未定义而报错,主题一律走 `guanvis theme preference`(见 `references/theme.md`)。
|
|
244
162
|
|
|
245
|
-
|
|
163
|
+
**单张图表主题色**:用 `.setThemeColor(tcId, colors?, options?)` 切换主题色、修改颜色覆盖或选择分类/顺序色板,`options.useSequentialPalette` 用于显式选择色板模式。只修改当前主题时 `tcId` 传 `null`;编写配置前必须检查项目根目录的 `theme-colors.js`,不存在时先运行 `guanvis theme-color sync -d <project>`,非空 `tcId` 必须取自快照。多页面和多子目录共用这一份快照,构建阶段的自动生成只作兜底。完整语义见 `references/chart-properties.md`。
|
|
246
164
|
|
|
247
|
-
|
|
165
|
+
**多页面支持**:同一项目可多次 `registerPage`。两种组织方式:
|
|
248
166
|
|
|
249
167
|
1. **单目录**:所有 card 和 page 在同一目录,page 通过 card index(注册顺序)引用
|
|
250
|
-
2.
|
|
168
|
+
2. **子目录**(推荐):每个子目录是独立看板工程,有自己的 `schema.js`、`card_*.js`、`page.js`、`themes/`、`charts/`;page 布局必须用 card ID 字符串而非 index,如 `addFullWidthCard("cardId24chars", 8)`
|
|
251
169
|
|
|
252
|
-
|
|
253
|
-
```
|
|
254
|
-
project/
|
|
255
|
-
├── overview/
|
|
256
|
-
│ ├── schema.js
|
|
257
|
-
│ ├── dynamic-parameters.js ← 全局参数快照(按需)
|
|
258
|
-
│ ├── themes/ ← 主题偏好与缓存(按需,仅当跑过 theme preference / sync)
|
|
259
|
-
│ │ ├── .preference.json
|
|
260
|
-
│ │ ├── .applied.json
|
|
261
|
-
│ │ ├── .index.json
|
|
262
|
-
│ │ ├── .sync-meta.json
|
|
263
|
-
│ │ └── <themeId>.json
|
|
264
|
-
│ ├── card_01_kpi.js
|
|
265
|
-
│ ├── card_02_chart.js
|
|
266
|
-
│ ├── page.js ← addFullWidthCard("card_id_string", 6)
|
|
267
|
-
│ └── charts/ ← 自定义图表内容
|
|
268
|
-
├── detail/
|
|
269
|
-
│ ├── schema.js
|
|
270
|
-
│ ├── themes/ ← 每个子目录是独立工程,主题各自维护
|
|
271
|
-
│ │ └── ...
|
|
272
|
-
│ ├── card_01_table.js
|
|
273
|
-
│ └── page.js
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
> 子目录模式下每个子目录是独立的看板工程,`themes/` 与 `schema.js` 同级、各自隔离;preview/pack/publish/`theme *` 命令必须 `cd` 进对应子目录单独执行。**在父级根目录直接 `guanvis pack/preview/publish .` 时,若任一子目录里出现了 `themes/`,命令会直接报错并提示需要进入子目录单独执行**——这避免了根目录运行时各子目录主题被静默忽略、全部退回内置 `simple.json` 的隐蔽问题。如果整个工程不需要主题(所有子目录都没有 `themes/`),在根目录一次性 `pack` 也照常工作,行为不变。
|
|
277
|
-
|
|
278
|
-
子目录模式下,page 布局必须使用 card ID 字符串而非 index:
|
|
279
|
-
```javascript
|
|
280
|
-
var p = createPage("Detail Page")
|
|
281
|
-
.setId("pgId24chars")
|
|
282
|
-
.addFullWidthCard("cardId24chars", 8); // 用 card ID 而非 index
|
|
283
|
-
registerPage(p.build());
|
|
284
|
-
```
|
|
170
|
+
子目录模式下 preview/pack/publish/`theme *` 必须 `cd` 进对应子目录单独执行;**根目录直接运行时,若任一子目录有 `themes/`,命令会直接报错并提示 cd**(避免子目录主题被静默忽略)。整个工程都没配 `themes/` 时根目录一次性 `pack` 照常工作。
|
|
285
171
|
|
|
286
172
|
### 6. 执行命令
|
|
287
173
|
|
|
288
174
|
```bash
|
|
289
|
-
# 生成资源 ID(用于 .setId()
|
|
290
|
-
guanvis genid
|
|
291
|
-
guanvis
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
# 生成布局组件 ID
|
|
295
|
-
guanvis gen-layout-id tab # 生成 1 个 tab_ + 默认 6 位字母
|
|
296
|
-
guanvis gen-layout-id panel 3 --length 8 # 生成 3 个 panel_ + 8 位字母;length 只计算下划线后的随机字母,超出 6~10 时自动收敛
|
|
297
|
-
guanvis gen-layout-id areaTitle # 生成 1 个 areaTitle_ + 默认 6 位字母
|
|
298
|
-
guanvis gen-layout-id cardGroup # 生成 1 个 cardGroup_ + 默认 6 位字母
|
|
299
|
-
guanvis gen-layout-id selGroup # 生成 1 个 selGroup_ + 默认 6 位字母
|
|
300
|
-
|
|
301
|
-
# 拉取已有线上仪表板为可编辑工程(只读 BI,不发布;尽量生成 schema.js)
|
|
175
|
+
# 生成资源 ID(用于 .setId();genid 保证字母开头,手写数字开头 ID 会被新建校验报错拦截)
|
|
176
|
+
guanvis genid 5
|
|
177
|
+
guanvis gen-layout-id <tab|panel|areaTitle|cardGroup|selGroup> [数量] [--length N] # 布局组件 ID,如 tab_AbCdEf
|
|
178
|
+
|
|
179
|
+
# 拉取已有线上仪表板为可编辑工程(只读 BI;细节与红线见 references/checkout-editing.md)
|
|
302
180
|
guanvis checkout <pageId> -d ./existing_dashboard
|
|
303
|
-
#
|
|
304
|
-
#
|
|
305
|
-
# 若 schema.js 未生成或缺字段,后续可手动 guanvis init <dsId> -d ./existing_dashboard --force 补齐
|
|
306
|
-
# checkout --overwrite 会清理输出目录下所有根级 .js 和旧 .guanvis,避免 schema/selector/metrics/other.js 残留混入运行
|
|
181
|
+
# schema.js 未生成或缺字段时:guanvis init <dsId> -d ./existing_dashboard --force 补齐
|
|
182
|
+
# checkout --overwrite 会清理输出目录下所有根级 .js 和旧 .guanvis,避免残留混入运行
|
|
307
183
|
|
|
308
|
-
#
|
|
309
|
-
# 全量 payload 写入工程目录 .preview.json,需要时用 read_file 按需查看,或加 --full 全量输出)
|
|
184
|
+
# 预览(默认摘要 JSON:卡片/页面清单 + changeSummary + 验证状态;全量 payload 落盘 .preview.json,--full 全量输出)
|
|
310
185
|
guanvis preview ./my_dashboard/
|
|
311
|
-
# checkout/attach
|
|
312
|
-
guanvis diff ./existing_dashboard/
|
|
313
|
-
|
|
314
|
-
# 打包为 ZIP 资源包
|
|
315
|
-
guanvis pack ./my_dashboard/
|
|
316
|
-
guanvis pack -o output.zip ./my_dashboard/
|
|
317
|
-
|
|
318
|
-
# 一步到位:构建并上传到 BI(在线同步)
|
|
319
|
-
guanvis publish ./my_dashboard/
|
|
320
|
-
guanvis publish ./my_dashboard/ --page-parent-dir <dir_id> # 指定页面目录
|
|
321
|
-
|
|
322
|
-
# 上传已有 ZIP 资源包;只允许上传 guanvis pack 原样生成的 ZIP
|
|
323
|
-
guanvis upload output.zip
|
|
324
|
-
|
|
325
|
-
# 修复已发布资源描述(保留原 Card/Page ID)
|
|
326
|
-
# 如果本地维护对应 JS 工程,也同步更新 card_*.js / page.js 里的 .setDescription(...)。
|
|
327
|
-
guanvis card set-description <cd_id> --description "这张卡用于回答..."
|
|
328
|
-
guanvis card set-description <cd_id> --file ./card_story.md
|
|
329
|
-
guanvis page set-description <pg_id> --description "这张页面用于回答..."
|
|
330
|
-
guanvis page set-description <pg_id> --file ./page_story.md --visible=false
|
|
331
|
-
|
|
332
|
-
# 页面视觉验证(可选,PNG,通过 BI 后端服务端截图,不依赖浏览器)
|
|
333
|
-
# 仅在明确需要视觉质量判断且当前大模型支持图像理解时使用;图像分析会额外消耗 token/费用。
|
|
334
|
-
guanvis screenshot <pageId> # 截图页面 PNG 到 <pageId>.png
|
|
335
|
-
guanvis screenshot <pageId> -o /tmp/dashboard.png # 指定输出路径
|
|
336
|
-
guanvis screenshot <pageId> --orientation horizontal # 横向截图
|
|
337
|
-
|
|
338
|
-
# 数据集/指标切换后的检查(仅梳理)
|
|
339
|
-
guanvis check-dataset-usage . --ds <dsId> # 盘点某个 dsId 在工程中的引用
|
|
340
|
-
guanvis check-dataset-switch . --from <oldDs> --to <newDs> --mode full # 整页/整包数据集切换后检查
|
|
341
|
-
guanvis check-dataset-switch . --from <oldDs> --to <newDs> --mode linked --changed-cards <cdId> # 局部切数据集后检查一跳关联资源
|
|
342
|
-
guanvis check-metric-switch . --from <oldMetric> --to <newMetric> --mode linked --changed-cards <cdId> # 局部切指标后检查一跳关联资源
|
|
343
|
-
|
|
344
|
-
# 仪表板主题(详见 `references/theme.md`,[dir] 缺省为当前目录)
|
|
345
|
-
guanvis theme preference --keywords "深色 科技" --sync # 在当前目录写入偏好并同步主题列表
|
|
346
|
-
guanvis theme preference ./my_dashboard --theme-id custom_blue # 显式指定工程目录
|
|
347
|
-
guanvis theme preference --clear # 清空当前目录的偏好与 applied 快照(彻底回到内置 simple.json)
|
|
348
|
-
guanvis theme list # 列出已落盘的候选主题
|
|
349
|
-
guanvis theme show # 打印当前主题决策(不联网)
|
|
350
|
-
guanvis theme sync # 强制刷新主题列表
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
**多子目录工程的执行方式**:每个子目录是独立工程,preview/pack/publish 必须在每个子目录里分别执行,每次产出独立的 ZIP 资源包;想要每个子目录用不同主题,就在每个子目录里分别 `theme preference`。在根目录直接运行 preview/pack/publish 时,若任一子目录里有 `themes/`,命令会拒绝执行并打印 `cd <subdir> && guanvis <preview|pack|publish> .` 提示。
|
|
354
|
-
|
|
355
|
-
```bash
|
|
356
|
-
# 多子目录工程 + 各子目录主题不同 → 在每个子目录分别执行
|
|
357
|
-
for sub in overview detail kpi; do
|
|
358
|
-
cd "./project/$sub"
|
|
359
|
-
guanvis theme preference --keywords "..." --sync
|
|
360
|
-
guanvis publish .
|
|
361
|
-
cd -
|
|
362
|
-
done
|
|
363
|
-
|
|
364
|
-
# 多子目录工程 + 整个工程不需要主题(无任一子目录配 themes/)→ 根目录一次性 pack 仍然可用(与原行为一致)
|
|
365
|
-
guanvis pack ./project
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
`publish` 和 `upload` 使用 BI 的 **transfer API**(`/api/manual/template/transfer`),特点:
|
|
369
|
-
- `needIdMapping=false`:保持资源 ID 不变,重复导入会覆盖同 ID 资源
|
|
370
|
-
- 发布前强制校验 Page 归属:资源包包含 Card/Selector 时必须同时包含 Page,且每个 Card/Selector 都必须被至少一个 Page 引用;Card-only 和孤儿 Card/Selector 包会在上传前被拒绝,并提示在 `page.js` 中放置资源后同包发布
|
|
371
|
-
- 在线覆盖检查只探测 Page ID,不探测 Card/Selector ID,避免部分 BI 版本在导入前缓存"找不到相关卡片"
|
|
372
|
-
- 认证方式:随底层 `guancli fetch` 使用 `Cookie: uIdToken=...`
|
|
373
|
-
- 需要 `raw-backend-response: TRUE` header 绕过前端代理层
|
|
374
|
-
- 不需要目标系统开启"一键迁移"开关,所有环境通用
|
|
375
|
-
|
|
376
|
-
**资源包安全约束**:`upload` 只是上传器,不是制作自定义资源包的入口。除非用户明确批准,否则不得上传手工生成、解包修改、重打包或批量替换内部内容后的 ZIP。需要批量重绑数据集、字段、卡片或页面 ID 时,先讨论方案,不要直接改 ZIP。
|
|
377
|
-
|
|
378
|
-
**线上仪表板更新策略**:新建工程发布的是新 Page;checkout 工程发布的是对 checkout 指定 Page 的覆盖式修改,不承担“复制新版本”职责。需要保留原页面并生成新版本时,不要在 guanvis CLI 内手工复制 JSON 或改 ID map;用 `guanvis page save-as <pgId> --suffix _guanvis`(或 `--name <新名>`,可加 `--parent-dir <dirId>`)做 BI 原生整页另存为,服务端会重映射全部卡片间引用并由命令自动 release 发布副本,然后 checkout 副本 Page 继续编辑。命令会回读副本核对卡片数(无指标平台 license 时指标卡会被服务端过滤)并扫描是否残留源页卡片 ID 引用,出现 ⚠ 警告时先排查再继续。对 checkout 工程同 ID 发布时,命令必须显式加 `--allow-overwrite` 允许同 ID Page 覆盖;发布前可用 `--dry-run` 查看会覆盖哪些线上 Page。Card/Selector ID 不做在线覆盖检查。**Agent 禁止在未确认的情况下自行加 `--allow-overwrite`**:当 CLI 提示将覆盖线上 Page 时,必须先停止发布,向用户说明将覆盖的 Page ID、名称和覆盖后可能替换原页面布局,等用户明确确认“覆盖”后才可以重跑并加 `--allow-overwrite`。使用 `--allow-overwrite` 时,CLI 会先为冲突 Page 发起资源包导出备份并等待导出成功;备份包含 Page 及其组成资源,但不会沿血缘额外导出数据集、数据账户等上游资源,避免普通用户因缺少上游资源所有者权限而无法备份。备份未成功则中止覆盖。CLI 只记录备份导出记录和 packageId,不自动下载资源包;需要回滚时,到 BI 资源迁移导出记录中手动下载该资源包后再导入覆盖回去。
|
|
379
|
-
|
|
380
|
-
## 复杂报表 Pro 工作方式
|
|
381
|
-
|
|
382
|
-
**进入本节的前提**:用户明确点名了"复杂报表 / 复杂报表 Pro",或 checkout 的目标卡片已是 Pro。Pro 是需要单独授权的非默认功能——未点名的表格/报表需求回到「固定工作方式」用原生卡片实现。
|
|
186
|
+
guanvis diff ./existing_dashboard/ # checkout/attach 工程的路径级变更摘要
|
|
383
187
|
|
|
384
|
-
|
|
188
|
+
# 发布(publish 自带构建打包上传;pack 只用于生成离线 ZIP 走 upload)
|
|
189
|
+
guanvis publish ./my_dashboard/ [--page-parent-dir <dir_id>]
|
|
190
|
+
guanvis pack [-o output.zip] ./my_dashboard/
|
|
191
|
+
guanvis upload output.zip # 只允许上传 guanvis pack 原样生成的 ZIP
|
|
385
192
|
|
|
386
|
-
|
|
193
|
+
# 修复已发布资源描述(保留原 ID;本地有 JS 工程时同步更新 .setDescription(...))
|
|
194
|
+
guanvis card set-description <cd_id> --description "..." # 或 --file ./story.md
|
|
195
|
+
guanvis page set-description <pg_id> --description "..." # 支持 --visible=false
|
|
387
196
|
|
|
388
|
-
|
|
389
|
-
guanvis
|
|
390
|
-
guanvis init <ds1> <ds2> -d ./x/ --alias ORDERS,SALES # 多数据集必须用 --alias 命名全局变量
|
|
391
|
-
cd ./pro_report && guanvis genid 3 # 父卡 + 每个数据视图 + page 各一个 ID
|
|
392
|
-
```
|
|
197
|
+
# 页面视觉验证(可选 PNG,服务端截图不依赖浏览器;仅在需要视觉判断且模型支持图像理解时用,消耗额外 token)
|
|
198
|
+
guanvis screenshot <pageId> [-o out.png] [--orientation horizontal]
|
|
393
199
|
|
|
394
|
-
|
|
200
|
+
# 数据集/指标切换后的检查(仅梳理):check-dataset-usage / check-dataset-switch / check-metric-switch
|
|
201
|
+
guanvis check-dataset-switch . --from <oldDs> --to <newDs> --mode full # 详见 --help;--mode linked 查一跳关联
|
|
395
202
|
|
|
396
|
-
|
|
203
|
+
# 仪表板主题(详见 references/theme.md)
|
|
204
|
+
guanvis theme preference --keywords "..." --sync # 另有 --theme-id / --clear;theme list/show/sync
|
|
397
205
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
.setId("<genid>")
|
|
402
|
-
.bindDataset(DS)
|
|
403
|
-
.addRow(f("区域"))
|
|
404
|
-
.addMetric(f("金额", { aggrType: AggrType.SUM }));
|
|
405
|
-
|
|
406
|
-
var workbook = createReportWorkbook().addSheet("月报", function (sheet) {
|
|
407
|
-
sheet.merge("A1:B1")
|
|
408
|
-
.setValue("A1", "销售月报", { fontSize: 16, bold: true, horizontalAlignment: "center", verticalAlignment: "center" })
|
|
409
|
-
.setRowHeight(1, 34)
|
|
410
|
-
.setValue("A2", "区域", { bold: true }).setValue("B2", "金额", { bold: true })
|
|
411
|
-
.bindDimension("A3", reportField("orders", "区域"))
|
|
412
|
-
.bindMetric("B3", reportField("orders", "金额"), { aggregate: "SUM", context: "A3", numberFormat: "#,##0.00" })
|
|
413
|
-
.setContextText("A4", "小计", { context: "A3" })
|
|
414
|
-
.bindSubtotal("B4", reportField("orders", "金额"), { aggregate: "SUM", context: "A4" })
|
|
415
|
-
.bindGrandTotal("B5", reportField("orders", "金额"), { aggregate: "SUM" });
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
registerComplexReportPro(createComplexReportPro("销售月报")
|
|
419
|
-
.setId("<genid>")
|
|
420
|
-
.setWorkbook(workbook)
|
|
421
|
-
.addDataView("orders", orders)
|
|
422
|
-
.setColumnWidthStretch(true)
|
|
423
|
-
.build());
|
|
206
|
+
# 单张图表主题色
|
|
207
|
+
guanvis theme-color list
|
|
208
|
+
guanvis theme-color sync -d ./my_dashboard
|
|
424
209
|
```
|
|
425
210
|
|
|
426
|
-
|
|
211
|
+
**多子目录工程**:每个子目录是独立工程,preview/pack/publish/`theme *` 必须 `cd` 进各子目录分别执行、各出各的资源包;根目录直接运行时若任一子目录有 `themes/` 会拒绝执行并打印 cd 提示。
|
|
427
212
|
|
|
428
|
-
|
|
213
|
+
**发布机制**:`publish`/`upload` 走 BI transfer API,`needIdMapping=false` 同 ID 覆盖、发布前强制校验 Page 归属(Card-only 与孤儿 Card/Selector 包直接拒绝)、覆盖检查只探测 Page ID;接口/认证/header 细节见 `references/publish-and-constraints.md`。
|
|
429
214
|
|
|
430
|
-
|
|
431
|
-
guanvis checkout <pageId> -d ./work # 模板下载到 templates/,templateVersion 自增
|
|
432
|
-
guanvis report inspect ./work/templates/<cdId>.xlsx # 不开 Excel 看模板格/父格链/环检测
|
|
433
|
-
guanvis report decompile ./work/templates/<cdId>.xlsx -o wb.js # 反编译为 Workbook DSL 或 patch 脚手架
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
创建与编辑共用**一套 Workbook DSL**:`createReportWorkbook()` 从零构建(`addSheet`),`createReportWorkbook("templates/<cdId>.xlsx")` 以已有模板为基底做增量编辑(`editSheet`),挂载入口统一是 `.setWorkbook(workbook)`。decompile 有两种产物:模板完全可表达时输出从零构建形态(冻结窗格/条件格式/序号列/阶梯布局都能还原);含 DSL 无法表达部件(内嵌图片、数据验证等)时自动输出基底编辑脚手架 `createReportWorkbook(path).editSheet(...)`——只写要改的操作,未触及部件原样保留,现有模板格以注释列在脚手架里供参考。`editSheet` 内方法与 `addSheet` 完全同名,另有仅编辑模式可用的原语:`clearCell`/`unmerge` 删除,`insertRows`/`removeRows`/`insertCols`/`removeCols` 结构编辑(自动重写模板表达式引用与父格,删除被引用模板格会拒绝;插入后坐标按移位后位置书写),`setCellStyle(cellOrRange, style)` 合并式改样式(只覆盖给出的属性);落点已有模板表达式时须在 options 加 `{ overwrite: true }`。改完 `guanvis diff` 看影响面(基底编辑的指令流会逐条出现在 changeSummary),发布走覆盖确认流程(`--allow-overwrite` 前必须征得用户确认)。
|
|
215
|
+
**线上仪表板更新红线**:checkout 工程发布 = 覆盖式修改指定 Page。CLI 检测到同 ID Page 时,**Agent 禁止未经用户确认自行加 `--allow-overwrite`**——必须先说明将覆盖的 Page ID/名称与影响,用户明确确认后才可重跑加该参数(CLI 会先做覆盖备份,备份失败则中止;`--dry-run` 可预查覆盖对象)。要"保留原页面出新版本"用 `guanvis page save-as`,不要复制 JSON 改 ID。备份/回滚/save-as 细节见 `references/checkout-editing.md` §5。
|
|
437
216
|
|
|
438
|
-
|
|
217
|
+
## 复杂报表 Pro 工作方式
|
|
439
218
|
|
|
440
|
-
|
|
219
|
+
**进入前提**:用户明确点名"复杂报表 / 复杂报表 Pro",或 checkout 的目标卡片已是 Pro(未点名的表格/报表需求回「固定工作方式」用原生卡片)。只支持 `COMPLEX_REPORT_PRO`,旧版复杂报表拒绝并建议外部迁移后新建 Pro。
|
|
441
220
|
|
|
442
|
-
|
|
221
|
+
与「固定工作方式」同体系(auth → init → 写脚本 → preview/pack → publish),差异只在脚本形态和验证闭环。**动手前先读 `references/complex-report-pro-patterns.md`**:
|
|
443
222
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
guancli card preview <proCardId> -o result.xlsx
|
|
448
|
-
# 2. 检查 result.xlsx:无 {{...}} 残留、行数/分组符合预期、抽查小计值
|
|
449
|
-
guancli card preview <proCardId> --filter "字段 EQ 值" -o f.xlsx # 3. 有筛选联动时验证 childFilters
|
|
450
|
-
```
|
|
223
|
+
- **新建**:§0 选型门槛 → §2.0 最小工程骨架(init/`--alias`/genid + 数据视图/workbook/注册三段式)→ §2 结构配方 → §3 数据视图规则。Pro 卡必须与引用它的 Page 同包发布。
|
|
224
|
+
- **编辑已有 Pro**:checkout 后统一走 `.setWorkbook()`;decompile 产物形态、`editSheet` 原语、templateVersion 生命周期、stale-base 防护全在 §5。
|
|
225
|
+
- **报错修复**:对照 §4 修复表。
|
|
226
|
+
- **验证闭环(发布后必做)**:`pack`/`preview` 只验证结构,发布后必须 `guancli card preview <proCardId> -o result.xlsx` 检查无 `{{...}}` 残留,详见 §6。
|
|
451
227
|
|
|
452
228
|
## 文件结构约定
|
|
453
229
|
|
|
454
230
|
目录模式下文件加载顺序:
|
|
455
|
-
1. `schema.js` — 数据集定义(init
|
|
231
|
+
1. `schema.js` — 数据集定义(init/checkout 生成,不可修改)
|
|
456
232
|
2. `metrics.js` — 指标定义(仅指标卡片需要,自动生成,不可修改)
|
|
457
233
|
3. `dynamic-parameters.js` — 项目全局参数快照(按需,由 parameter 命令或 checkout 生成)
|
|
458
|
-
4. `
|
|
459
|
-
5. `
|
|
460
|
-
6. `
|
|
461
|
-
|
|
462
|
-
自定义图表时,图表内容文件(如 ECharts 脚本)放在 **子目录**(如 `charts/`),避免被当作 card 脚本执行。
|
|
234
|
+
4. `theme-colors.js` — 项目级图表主题色快照(配置主题色前由 `theme-color sync` 生成或刷新,不可修改;多页面/多子目录共用;构建阶段缺失时会兜底生成)
|
|
235
|
+
5. `card_01_xxx.js` ~ `card_NN_xxx.js` — Card 定义(按文件名排序)
|
|
236
|
+
6. `selector_01_xxx.js` ~ `selector_NN_xxx.js` — 筛选器定义(在 card 之后执行,因为联动需要引用 card 索引)
|
|
237
|
+
7. `page.js` — Page/仪表板组装
|
|
463
238
|
|
|
464
|
-
|
|
239
|
+
自定义图表内容文件(如 ECharts 脚本)放子目录(如 `charts/`),避免被当作 card 脚本执行;`themes/` 由 `theme *` 命令维护、全部文件不手改(见 `references/theme.md`)。
|
|
465
240
|
|
|
466
241
|
## 参考示例
|
|
467
242
|
|
|
468
243
|
| 示例 | 路径 | 说明 |
|
|
469
244
|
|------|------|------|
|
|
470
|
-
| 基础仪表板 | `evals/sales_dashboard/` |
|
|
471
|
-
| 拆分图 | `evals/split_charts/` |
|
|
472
|
-
| 自定义图表 | `evals/custom_chart_echarts/` | ECharts Lite
|
|
473
|
-
| 复杂报表 Pro | `evals/complex_report_pro/` | 最小 Workbook DSL
|
|
474
|
-
| Tab 布局 | `evals/tab_layout/` |
|
|
245
|
+
| 基础仪表板 | `evals/sales_dashboard/` | 普通卡片 + 筛选器 + 页面布局 |
|
|
246
|
+
| 拆分图 | `evals/split_charts/` | 图表按字段拆分 |
|
|
247
|
+
| 自定义图表 | `evals/custom_chart_echarts/` | ECharts Lite,`loadContent()` 文件模式 |
|
|
248
|
+
| 复杂报表 Pro | `evals/complex_report_pro/` | 最小 Workbook DSL 工程(结构配方以 patterns.md §2 为准) |
|
|
249
|
+
| Tab 布局 | `evals/tab_layout/` | 根布局指标卡 + panel 内卡片 + 筛选器 |
|
|
475
250
|
|
|
476
251
|
生成脚本前先查阅对应示例中的文件结构和写法。
|
|
477
252
|
|
|
@@ -479,14 +254,15 @@ guancli card preview <proCardId> --filter "字段 EQ 值" -o f.xlsx # 3. 有
|
|
|
479
254
|
|
|
480
255
|
| 场景 | 路径 | 读取时机 |
|
|
481
256
|
|------|------|----------|
|
|
482
|
-
| 字段、计算字段、NumberFormat
|
|
483
|
-
|
|
|
484
|
-
|
|
|
485
|
-
|
|
|
486
|
-
|
|
|
487
|
-
|
|
|
488
|
-
|
|
|
489
|
-
|
|
|
257
|
+
| 字段、计算字段、NumberFormat、高级计算、卡片筛选器 API | `references/api-reference.md` | 写字段/指标/公式/筛选条件时 |
|
|
258
|
+
| 各类 Builder API 与枚举(含 ComplexReportProBuilder 权威定义) | `references/builder-reference.md` | 写或改 JS DSL builder 调用时 |
|
|
259
|
+
| 图表属性配置 | `references/chart-properties.md` | 创建或修改图表属性时 |
|
|
260
|
+
| checkout 编辑闭环:生成物、attachCard 操作语义、覆盖发布与备份 | `references/checkout-editing.md` | checkout 工程动手前、改线上仪表板时 |
|
|
261
|
+
| 复杂报表 Pro 选型/骨架/配方/报错/编辑/验证 | `references/complex-report-pro-patterns.md` | 创建或修改 Pro 前必读 |
|
|
262
|
+
| zone 校验、图表选型、地图/拆分图、字段对象细节 | `references/validation-and-chart-patterns.md` | pack 报错、选型不确定时 |
|
|
263
|
+
| 仪表板主题机制与 theme 排错 | `references/theme.md` | 指定视觉风格、主题异常时 |
|
|
264
|
+
| 在线同步、认证、ID 管理和硬约束 | `references/publish-and-constraints.md` | publish/upload、确认生成边界时 |
|
|
265
|
+
| Tableau 迁移清单 | `references/tableau-migration.md` | Tableau 工作簿迁移时 |
|
|
490
266
|
| 常见错误与修复 | `references/troubleshooting.md` | 命令失败或校验报错时 |
|
|
491
267
|
|
|
492
268
|
## 最后怎么向用户汇报
|