@guandata/guanvis 0.1.34 → 0.1.36
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 +15 -0
- package/README.md +16 -4
- 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 +243 -94
- package/skills/guanvis/references/chart-properties.md +1177 -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 +15 -4
- package/skills/guanvis/references/publish-and-constraints.md +6 -4
- package/skills/guanvis/references/theme.md +11 -5
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 编辑已有线上仪表板(checkout 工作流)
|
|
2
|
+
|
|
3
|
+
SKILL.md 正文只保留 checkout 编辑的红线速记;本文件是 `checkout → 编辑 → diff → publish` 闭环的完整参考:生成物形态、attachCard 编辑模型、DSL 操作语义、覆盖发布与备份机制。
|
|
4
|
+
|
|
5
|
+
## 1. Checkout 生成物形态
|
|
6
|
+
|
|
7
|
+
`guanvis checkout <pgId> -d <dir>` 把线上 Page 拉成可编辑工程:
|
|
8
|
+
|
|
9
|
+
- **schema.js**:best-effort 生成——数据集无权限/已删除/跨环境残留时只 warning 并继续生成可编辑工程;后续可手动 `guanvis init <dsId> -d <dir> --force` 补齐。
|
|
10
|
+
- **普通 Card**:生成 `attachCard(cdId, ".guanvis/base/cards/<cdId>.json")`,接受线上 JSON 作为基线。
|
|
11
|
+
- **自定义图表(SDK/ECHARTS_LITE)**:脚本/HTML/CSS 反编译到 `charts/<cdId>.js|.html|.css`;超长内联资源(GeoJSON、base64 图片)抽取到 `charts/<cdId>_assets/` + `__asset_text/__asset_base64` 占位符(逐字节往返验证,未编辑时 diff 恒为空)。card JS 用 `attachCard(...).loadContent("charts/<cdId>")` 引用,直接编辑内容文件即可改图表。
|
|
12
|
+
- **复杂报表 Pro**:额外下载可编辑 xlsx 到 `templates/`,生成 `createComplexReportPro()` 父卡和嵌套的 attached data view,并使用下一模板版本;旧版复杂报表 checkout 直接拒绝。编辑闭环见 `complex-report-pro-patterns.md` §5。
|
|
13
|
+
- **Page**:生成 `createPage(...).setBasePath(...).placeCard("cdId", ...)` 脚本,尽量反编译根布局里的 Tab/CardGroup/AreaTitle/SelGroup 和快捷筛选组,并保留 parentDirId。checkout 生成的 page 布局默认用 card/selector ID 字符串。
|
|
14
|
+
- **适用范围**:checkout 工程只用于修改指定 Page,不用于复制新 Page;遇到嵌套布局组件等当前 DSL 不能安全表达的结构,checkout 会直接失败,不生成会清结构的工程。只支持普通仪表板(pgType=PAGE),自助取数/数据大屏/清单页等特殊页面会在 checkout 入口直接报错。
|
|
15
|
+
- `checkout --overwrite` 会清理输出目录下所有根级 `.js` 和旧 `.guanvis`,避免 schema/selector/metrics/other.js 残留混入运行。
|
|
16
|
+
|
|
17
|
+
## 2. 账号与语言要求
|
|
18
|
+
|
|
19
|
+
checkout 读到的是"当前账号视角"的卡片定义,publish 会把它整体回写。必须用对页面涉及数据集拥有**完整列权限、无脱敏限制**的账号(推荐资源 owner 或管理员)执行 checkout/publish,否则读接口会按该账号权限裁剪 zone 字段/脱敏字段,回写后这些字段会从线上卡片中**永久丢失**。租户启用多语言时,操作账号语言应与卡片原始语言一致,避免把翻译后的字段显示名固化回卡片。
|
|
20
|
+
|
|
21
|
+
## 3. attachCard 编辑模型与 DSL 操作语义
|
|
22
|
+
|
|
23
|
+
`attachCard(cardId, jsonPath)` 是"base JSON + 链式 DSL 操作 = 目标 JSON"。它不会修改 base JSON,重复执行同一组 JS 操作应产出相同 payload。`attachCard` 只能引用 manifest 记录的原始 base-card,且 `cardId` 必须与该 JSON 的资源 ID 一致。
|
|
24
|
+
|
|
25
|
+
- **通用操作**:已有卡片可继续串接常用 `createCard` 后续操作,包括标题/描述(`setName`/`setDescription`)、`setRawSettings`、图例/标签/坐标轴/表格/拆分等视觉设置。
|
|
26
|
+
- **Zone 操作按链式顺序真实执行**:`addRow/addMetric/...` 追加字段;`insertMetric(index, field)` 插入;`removeMetric(selector)` 删除字段并保守清理其它 zone 中同字段引用;`moveMetric(selector, index)` 调整顺序;`updateMetric(selector, patch)` / `patchMetric(...)` 修改已有字段属性并保留未设置字段配置。`setRows/setMetrics/...` 和 `clearRows/clearMetrics/...` 是整 zone 重建,不会继承被替换字段的格式,并会在验证时提示 warning——默认优先用 `update*/patch*/add*/remove*/move*`。
|
|
27
|
+
- **自定义图表内容编辑**:仅限 subType 为 **SDK / ECHARTS_LITE**。checkout 自动反编译出 `charts/<cdId>.js`(含内嵌资源抽取),card JS 里 `attachCard(...).loadContent("charts/<cdId>")`;也可用 `.setScript()/.setHtml()/.setCss()/.setLibs()/.addLib()` 内联修改。COMPLEX_REPORT(走 Pro 流程)、PLUGIN/PLUGIN_LITE(事实源是插件市场资源)、REPORT_FORM(填报模板配置)调用这些内容编辑 API 会直接报错,不要对它们生成此类修改;详见 `builder-reference.md` 自定义图表章节。
|
|
28
|
+
- **已有 selector 联动**:用 `.addLink(cardIdOrIndex, targetFieldName?)` / `.removeLink(cardIdOrIndex)` / `.clearLinks()` 叠加修改现有 `settings.asFilter`,不要反向改 JSON。
|
|
29
|
+
- **Page 快捷筛选区**:按有序操作执行——`setFilterLayout` 整体设置,`clearFilterLayout` 清空,`addFilterLayoutItem` 追加去重,`insert/remove/moveFilterSelector` 局部调整;筛选栏布局、名称/控件/按钮字体、控件风格、按钮色、背景色和背景图用 `setFilterPanelLayout()`。省略字段保留 base,显式 `null` 删除对应覆盖并恢复产品/主题默认。
|
|
30
|
+
- **筛选器在筛选栏和画布间移动**:优先用动作级 API:`moveFilterSelectorToCanvas(selectorId, x, y, w, h)` / `moveCanvasSelectorToFilter(selectorId, index?)`;筛选器组用 `moveSelectorGroupToCanvas(group, x, y, w, h)` / `moveCanvasSelectorGroupToFilter(group, index?)`。
|
|
31
|
+
- **新增卡片**必须使用 `createCard()` / `createSelector()` 等工厂函数(新建资源 ID 用 `guanvis genid` 生成)。
|
|
32
|
+
- **影响面检查**:发布前用 `guanvis diff <dir>` 或 `preview` 输出里的 `changeSummary` 查看 base JSON 到最终 payload 的路径级影响面。
|
|
33
|
+
- 没有 DSL 操作覆盖的需求,先扩展 DSL,不要改 `.guanvis` JSON。
|
|
34
|
+
|
|
35
|
+
## 4. 编辑红线的完整依据(编辑 ≠ 删除重建)
|
|
36
|
+
|
|
37
|
+
用户要求修改/改名已发布 Page 或 Card 时,必须保留原 pgId/cdId 原地覆盖发布,先按工程来源分流:
|
|
38
|
+
|
|
39
|
+
- **本地有源工程**(该 Page 就是当前 guanvis 工程创建并发布的,`card_*.js` / `page.js` 还在,且线上没有在发布后被网页端改动过):直接修改本地 JS 源文件(改名即改 `createCard(...)` / `createPage(...)` 标题)重新 publish 同 ID 覆盖。
|
|
40
|
+
- **线上在发布后被网页端修改过、本地没有原始 JS 工程、或不确定线上是否已被改动**:用 `checkout` 拉取线上版本编辑——Page 改 checkout 生成的 `createPage(...)` 标题,已 checkout 的 Card 用 `attachCard(...).setName(...)`。**不得**把 `attachCard` 改写成 `createCard()`:那会绕过 base JSON,未被 DSL 表达的线上配置会在覆盖发布时丢失(`createCard()` 只用于新增卡片)。
|
|
41
|
+
- **禁止**用"新建一个新 Page/Card + 删除或废弃旧的"来模拟编辑——资源 ID 变化会让收藏、分享链接、订阅推送、门户菜单引用和页面权限配置全部失效,这些状态 guanvis 无法迁移。
|
|
42
|
+
- **全局参数同理**:只能 `parameter update <dpId>` 原地更新,禁止 delete 后重建同名参数(dpId 变化会让所有引用它的卡片/筛选器断链);`parameter delete` 只用于用户明确要求删除参数本身。
|
|
43
|
+
- **描述修复**:仅修复已发布 Card/Page 的描述时保留原资源 ID,用 `guanvis card/page set-description` 更新线上描述;本地有对应 JS 工程时同步更新 `.setDescription(...)`。
|
|
44
|
+
|
|
45
|
+
## 5. 发布:覆盖确认、备份与"另存新版本"
|
|
46
|
+
|
|
47
|
+
checkout 工程发布的是对 checkout 指定 Page 的**覆盖式修改**,不承担"复制新版本"职责。
|
|
48
|
+
|
|
49
|
+
- **覆盖确认(Agent 红线)**:对 checkout 工程同 ID 发布时,CLI 检测到同 ID Page 必须显式加 `--allow-overwrite` 才会覆盖。**Agent 禁止在未确认的情况下自行加 `--allow-overwrite`**:CLI 提示将覆盖线上 Page 时,必须先停止发布,向用户说明将覆盖的 Page ID、名称和覆盖后可能替换原页面布局,等用户明确确认"覆盖"后才可以重跑并加该参数。发布前可用 `--dry-run` 查看会覆盖哪些线上 Page。Card/Selector ID 不做在线覆盖检查。
|
|
50
|
+
- **覆盖备份机制**:使用 `--allow-overwrite` 时,CLI 会先为冲突 Page 发起资源包导出备份并等待导出成功;备份包含 Page 及其组成资源,但不会沿血缘额外导出数据集、数据账户等上游资源(避免普通用户因缺少上游资源所有者权限而无法备份)。备份未成功则中止覆盖。CLI 只记录备份导出记录和 packageId,不自动下载资源包;需要回滚时,到 BI 资源迁移导出记录中手动下载该资源包后再导入覆盖回去。
|
|
51
|
+
- **保留原页面、出一个新版本**:不要把 checkout JSON 复制后改 ID 做"新版本",也不要在 guanvis CLI 里手写复杂 ID map 或用浏览器手工复制页面。用 `guanvis page save-as <pgId> --suffix _guanvis`(或 `--name <新名>`,可加 `--parent-dir <dirId>`)做 BI 原生整页另存为:服务端事务复制全部卡片并重映射联动/下钻/父子/指标关系等 ID,命令自动 release 发布副本(7.2.0 之前无草稿态会自动跳过),然后基于副本页面 checkout/edit。命令会回读副本核对卡片数(无指标平台 license 时指标卡会被服务端过滤)并扫描是否残留源页卡片 ID 引用,出现 ⚠ 警告时先排查再继续。
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
从零创建优先 **Workbook DSL**(`.setWorkbook()`,可文本审阅、pack 全量校验);只有拿到现成 xlsx 模板文件时才用 `.setTemplate()`。
|
|
28
28
|
|
|
29
|
+
只支持 `COMPLEX_REPORT_PRO`:旧版复杂报表(COMPLEX_REPORT)不支持创建或编辑,一律拒绝并建议外部迁移后新建 Pro;Pro 父卡也不能用泛化 `attachCard()` 修改——checkout 会生成 `createComplexReportPro()` 工程,编辑走 §5。
|
|
30
|
+
|
|
29
31
|
## 1. 模板心智模型(读懂再写)
|
|
30
32
|
|
|
31
33
|
Pro 模板 = Excel 网格上放"模板格"。每个模板格要么绑定数据(`bindDimension/bindMetric/...`),要么是随分组重复的标签(`setContextText`),要么是随扩展复制的公式(`setDynamicFormula`)。**父格(`context`)决定重复结构**:
|
|
@@ -52,6 +54,47 @@ Pro 模板 = Excel 网格上放"模板格"。每个模板格要么绑定数据
|
|
|
52
54
|
|
|
53
55
|
每个配方给最小正确形态;完整可运行工程见 `evals/complex_report_pro/`(最小 Workbook DSL 工程)。
|
|
54
56
|
|
|
57
|
+
### 2.0 最小工程骨架(从零创建)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
guanvis init <dsId> -d ./pro_report/ # 单数据集
|
|
61
|
+
guanvis init <ds1> <ds2> -d ./x/ --alias ORDERS,SALES # 多数据集必须用 --alias 命名全局变量
|
|
62
|
+
cd ./pro_report && guanvis genid 3 # 父卡 + 每个数据视图 + page 各一个 ID
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
多数据集时**不要**手写 `var X = defineDataset(...)`(schema.js 的顶层 var 不会进入其他脚本的作用域),一律用 `--alias`;单数据集裸引用可用 `f("字段")`,多数据集用 `field(SALES, "字段")` 指明归属(`f()` 永远取第一个数据集)。
|
|
66
|
+
|
|
67
|
+
`card_01_xxx.js` 三段式:数据视图 + workbook + 注册(下例为分组小计形态,其他结构套本节配方):
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
var orders = createCard(ChartType.DATA_GRID, "orders") // 数据视图:模板引用的字段都必须进 row/metric
|
|
71
|
+
.setId("<genid>")
|
|
72
|
+
.bindDataset(DS)
|
|
73
|
+
.addRow(f("区域"))
|
|
74
|
+
.addMetric(f("金额", { aggrType: AggrType.SUM }));
|
|
75
|
+
|
|
76
|
+
var workbook = createReportWorkbook().addSheet("月报", function (sheet) {
|
|
77
|
+
sheet.merge("A1:B1")
|
|
78
|
+
.setValue("A1", "销售月报", { fontSize: 16, bold: true, horizontalAlignment: "center", verticalAlignment: "center" })
|
|
79
|
+
.setRowHeight(1, 34)
|
|
80
|
+
.setValue("A2", "区域", { bold: true }).setValue("B2", "金额", { bold: true })
|
|
81
|
+
.bindDimension("A3", reportField("orders", "区域"))
|
|
82
|
+
.bindMetric("B3", reportField("orders", "金额"), { aggregate: "SUM", context: "A3", numberFormat: "#,##0.00" })
|
|
83
|
+
.setContextText("A4", "小计", { context: "A3" })
|
|
84
|
+
.bindSubtotal("B4", reportField("orders", "金额"), { aggregate: "SUM", context: "A4" })
|
|
85
|
+
.bindGrandTotal("B5", reportField("orders", "金额"), { aggregate: "SUM" });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
registerComplexReportPro(createComplexReportPro("销售月报")
|
|
89
|
+
.setId("<genid>")
|
|
90
|
+
.setWorkbook(workbook)
|
|
91
|
+
.addDataView("orders", orders)
|
|
92
|
+
.setColumnWidthStretch(true)
|
|
93
|
+
.build());
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`page.js` 正常 `registerPage`(Pro 卡按注册顺序参与 card index,或用 ID 字符串);**Pro 卡必须与引用它的 Page 同包 pack/publish**。之后与普通流程一致:`preview` → `pack`/`publish`。
|
|
97
|
+
|
|
55
98
|
### 2.1 层级分组(区域→客户 两级)
|
|
56
99
|
|
|
57
100
|
```javascript
|
|
@@ -172,11 +172,22 @@ registerMetricChart(card.build());
|
|
|
172
172
|
| `.addSize(metric(...))` | 添加大小指标 |
|
|
173
173
|
| `.addTooltip(metric(...))` | 添加 tooltip 指标 |
|
|
174
174
|
| `.addSplit(metricDim(...))` | 添加拆分维度 |
|
|
175
|
-
| `.setProps(obj)`
|
|
175
|
+
| `.setProps(obj)` | 设置 `chartMain.props` |
|
|
176
176
|
| `.setConfig(obj)` / `.setRawConfig(key, value)` | 设置 `chartMain.config` |
|
|
177
|
-
| `.setSummary(
|
|
177
|
+
| `.setSummary(metric(...), options?)` | 设置 `meta.summary`;`options` 支持 `label`、`position`,旧的原始对象签名继续兼容 |
|
|
178
|
+
| `.setSummaryStyle(config)` | 设置汇总指标名称与数值样式 |
|
|
179
|
+
| `.setSpecialValue(config)` | 设置特殊值显示;仅支持前端开放该属性的图表类型 |
|
|
180
|
+
| `.setShowTitle(show)` / `.setCardTitleStyle(config)` | 设置卡片标题显隐与样式 |
|
|
178
181
|
| `.setColumns(columns)` | 设置 `content.columns` 与 dsInfo.columns |
|
|
179
|
-
| `.setTableSetting(obj)` |
|
|
182
|
+
| `.setTableSetting(obj)` | 设置表格行为与视觉样式;详细字段见 `chart-properties.md` |
|
|
183
|
+
| `.setTableCellMerge(obj)` | 设置透视表单元格合并 |
|
|
184
|
+
| `.setPieSetting(obj)` / `.setPieCenterText(obj)` | 设置饼图属性 |
|
|
185
|
+
| `.setSplitSetting(obj)` | 设置拆分图属性 |
|
|
186
|
+
| `.setBarSetting(obj)` | 设置柱形图/条形图的柱体宽度、间距和圆角;详细字段见 `chart-properties.md` |
|
|
187
|
+
| `.setShapeColorType(type)` | 设置图形填充 |
|
|
188
|
+
| `.setLineSetting(obj)` | 设置折线显示 |
|
|
189
|
+
| `.setAuxiliaryLine(obj)` | 设置辅助线 |
|
|
190
|
+
| `.setGrandTotal(obj)` | 设置透视表/分组表行列总计及样式;字段小计通过 `metricDim()` / `metric()` overrides 配置 |
|
|
180
191
|
| `.setFreeDrill(enabled, position)` | 设置 `config.freeDrillConfig` |
|
|
181
192
|
| `.setRowThreshold(thresholds)` | 设置 `config.rowThreshold` |
|
|
182
193
|
|
|
@@ -230,7 +241,7 @@ var card = createMetricChart(ChartType.PIVOT_TABLE, "复杂指标透视表")
|
|
|
230
241
|
fieldFormat: { numberFormat: NumberFormat.currency("¥", 0) }
|
|
231
242
|
}))
|
|
232
243
|
.addSort(metric("销售额", { sortType: SortOrder.DESC }))
|
|
233
|
-
.setTableSetting({ fixedHeaderInfo: { X: false }
|
|
244
|
+
.setTableSetting({ fixedHeaderInfo: { X: false } })
|
|
234
245
|
.setConfig({ rowThreshold: [] });
|
|
235
246
|
|
|
236
247
|
registerMetricChart(card.build());
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
`publish` 和 `upload` 命令通过 BI 的 transfer API 直接将资源包上传到目标系统:
|
|
4
4
|
|
|
5
5
|
- **接口**:`POST /api/manual/template/transfer`(标准 multipart/form-data,表单字段名 `new-file`)
|
|
6
|
-
- **认证**:随底层
|
|
6
|
+
- **认证**:随底层 BI 请求通道使用 `Cookie: uIdToken=...`
|
|
7
7
|
- **关键 header**:`raw-backend-response: TRUE`(绕过前端代理层,直达后端)
|
|
8
|
-
- **ID 策略**:`needIdMapping=false`,保持资源 ID 不变。同 ID 资源会被覆盖更新。为避免部分 BI 版本在导入前探测 Card 时缓存"找不到相关卡片",`guanvis publish/upload` 的在线覆盖检查只探测目标环境已有 Page ID;检测到同 ID Page 时默认拒绝上传,只有明确加 `--allow-overwrite` 才允许覆盖。加 `--allow-overwrite` 后,CLI 会先调用资源包导出为冲突 Page
|
|
8
|
+
- **ID 策略**:`needIdMapping=false`,保持资源 ID 不变。同 ID 资源会被覆盖更新。为避免部分 BI 版本在导入前探测 Card 时缓存"找不到相关卡片",`guanvis publish/upload` 的在线覆盖检查只探测目标环境已有 Page ID;检测到同 ID Page 时默认拒绝上传,只有明确加 `--allow-overwrite` 才允许覆盖。加 `--allow-overwrite` 后,CLI 会先调用资源包导出为冲突 Page 生成备份记录,并等待导出成功;`/api/task/{taskId}` 是备份成功或失败的权威终态,资源包列表只在任务成功但结果未直接返回 packageId 时用于补齐 packageId,不用列表状态覆盖任务结论。目标 BI 不支持通过该 taskId 查询任务或响应缺少任务状态时,兼容回退到资源包列表判定。备份失败或超时则中止上传。Card/Selector ID 不做在线探测。checkout 工程表示修改指定 Page,不在 CLI 内复制新版本或手写 ID 映射。
|
|
9
9
|
- **Page 归属校验**:资源包只要包含 Card/Selector,就必须同时包含 Page,且每个 Card/Selector 的 ID 必须出现在至少一个 Page 的 `cdIds` 中。只有 Card/Selector、没有 Page,或包内存在未被任何 Page 引用的 Card/Selector 时,`preview/pack/publish/upload` 会提示在 `page.js` 中放置对应资源并将 Page 与 Card/Selector 同包发布。该约束用于避免导入端生成 `pg_id` 为空、无法访问且会与页面草稿 `origin_cd_id` 冲突的孤儿卡片。
|
|
10
10
|
- **通用性**:不需要目标系统开启"一键迁移"开关,所有客户环境可用
|
|
11
11
|
- **异步执行**:上传成功后返回 `taskId`,后端异步完成导入
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
若用户要求批量重绑资源、迁移已有页面或复用线上页面结构,先说明风险并确认方案;不要直接修改 ZIP 内部文件后上传。
|
|
16
16
|
|
|
17
|
-
checkout 工程表示“基于线上快照修改指定 Page”,不会新建 Page,也不要通过复制 checkout JSON、改 ID 或自建 ID map
|
|
17
|
+
checkout 工程表示“基于线上快照修改指定 Page”,不会新建 Page,也不要通过复制 checkout JSON、改 ID 或自建 ID map 来生成新版本。若用户要求保留原页面并另存新版本,用 `guanvis page save-as <pgId> --suffix _guanvis`(或 `--name <新名>`)做 BI 原生整页另存为,由服务端处理资源 ID 映射,再对副本 Page 执行 checkout/edit(细节见 `checkout-editing.md` §5)。用户可能已经在 BI 上手工改过页面布局、卡片配置、筛选器或说明文本;如果按旧 checkout 工程同 ID `publish`,线上改动会被覆盖。发布前应使用 `--dry-run` 检查覆盖对象,只有用户明确要求覆盖原资源时,才允许加 `--allow-overwrite` 同 ID 发布。
|
|
18
18
|
|
|
19
19
|
## 认证与 CLI 集成
|
|
20
20
|
|
|
@@ -50,7 +50,9 @@ checkout 工程表示“基于线上快照修改指定 Page”,不会新建 Pa
|
|
|
50
50
|
|
|
51
51
|
所有 Card、Selector 和 Page **必须**调用 `.setId(id)` 设置显式 ID。未设置 ID 会在 JS 校验和 Go 校验两层报错,阻止生成。
|
|
52
52
|
|
|
53
|
-
-
|
|
53
|
+
- **新建资源 ID** 应使用 `guanvis genid` 生成;`genid` 输出格式为 `^[a-z][0-9a-f]{23}$`。新建校验接受字母开头的 24 位小写字母数字 ID(`^[a-z][a-z0-9]{23}$`),因此已有的固定小写测试 ID 仍可使用,但混合大小写和数字开头 ID 会被拦截。
|
|
54
|
+
- **已有资源兼容**:checkout/attach 把线上 ID 视为不透明标识并原样保留,不校验格式;只检查非空、唯一和引用关系,避免已有资源因历史或未来 ID 形态变化而无法原地编辑。
|
|
55
|
+
- 存量本地源码工程若包含已发布的非规范 ID,不要按新建校验提示替换 ID;应 checkout/attach 后继续使用线上原 ID,避免收藏、订阅、权限和外部引用断链。
|
|
54
56
|
- **生成 ID**:先运行 `guanvis genid <数量>` 生成足够的 ID,在编写脚本时直接填入每个 card/selector/page 的 `.setId()` 调用中。
|
|
55
57
|
- **布局组件 ID 例外**:Tab、Panel、AreaTitle、CardGroup、SelGroup 使用 `guanvis gen-layout-id <prefix>` 生成,形如 `tab_AbCdEf`、`panel_AbCdEf`、`areaTitle_AbCdEf`、`cardGroup_AbCdEf`、`selGroup_AbCdEf`,不适用 24 位 `genid` 规则。
|
|
56
58
|
- **线上更新默认策略**:新建工程发布新 Page;checkout 工程只修改 checkout 指定的 Page,不负责复制新版本。
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
## 仪表板主题
|
|
2
2
|
|
|
3
|
-
`preview` / `pack` / `publish`
|
|
3
|
+
`preview` / `pack` / `publish` 会自动给新建页面与卡片注入主题,决策顺序如下:
|
|
4
4
|
|
|
5
5
|
1. **`<dir>/themes/.preference.json`** — 用户/AI 主动写入的意图(`themeId` 优先,缺失再用 `keywords` 在 `.index.json` 上匹配;命中后 `themeId` 会被回写到 `.preference.json`)
|
|
6
|
-
2. **`<dir>/themes/.applied.json`** — 上一次成功 `pack`/`publish`
|
|
6
|
+
2. **`<dir>/themes/.applied.json`** — 上一次成功 `pack`/`publish` 明确选用的项目级线上主题(用于改版自动继承;本次回退到 skill 自带 `simple.json` 时**不写**该文件)
|
|
7
7
|
3. **skill 自带 `simple.json`** — 兜底(embed 在二进制里,**不联网、不会失败**)
|
|
8
8
|
|
|
9
|
+
`guanvis checkout` 是例外:线上 Page 的完整 `meta.theme` 只保存在
|
|
10
|
+
`.guanvis/base/page.json`,不会写成项目级 `.applied.json`。未明确切换主题时,每个
|
|
11
|
+
checkout Page 独立恢复自己的线上主题,新卡片继承所属 Page 的主题;旧页面没有
|
|
12
|
+
`meta.theme`(缺失、`null` 或空对象)也是有效状态,新卡片不会被注入内置简约主题。
|
|
13
|
+
项目里已有的 `.preference.json` 仍代表用户明确切换主题,优先级高于 checkout base。
|
|
14
|
+
|
|
9
15
|
AI 选择主题时不要把租户主题列表里的默认“浅色”/“深色”当作候选:这两套主题没有特殊样式。若除了“浅色”/“深色”外没有合适主题,不写主题偏好或执行 `theme preference --clear`,让解析落到 skill 内置“简约”(`simple.json`),不要为了命中而从列表里随便挑一个。
|
|
10
16
|
|
|
11
17
|
兜底覆盖的失败场景(任意一种发生都会平滑退到 simple.json,命令不会因主题问题中断):
|
|
12
|
-
-
|
|
18
|
+
- 新建工程目录下没有 `themes/`、或 `.preference.json` 缺失(checkout 工程会优先保留 base 页面原状)
|
|
13
19
|
- `.preference.json` 里的 `themeId` 在租户线上 list 中不存在 / `Sync` 失败 / 当前命令本来就不联网
|
|
14
20
|
- `keywords` 在 `.index.json` 上没有任何命中
|
|
15
21
|
- `.applied.json` 引用的 `themeId` 本地快照已被删除(applied 步骤**只读本地、不再发起 sync**)
|
|
@@ -39,10 +45,10 @@ AI 选择主题时不要把租户主题列表里的默认“浅色”/“深色
|
|
|
39
45
|
|
|
40
46
|
themeId 需为单个「安全文件名」片段:`[A-Za-z0-9_-]`、长度 ≤32,且不能含 `/`、`\`、子串 `..`;否则 CLI 会拒绝,sync 也会跳过并打 stderr 警告。
|
|
41
47
|
|
|
42
|
-
-
|
|
48
|
+
- **改版(不重提风格)**:普通工程由 `.applied.json` 沿用上次项目主题;checkout 工程按 Page base 保留各自线上主题。
|
|
43
49
|
- **换风格**:再跑一次 `theme preference` 即可;下一次 `pack`/`publish` 实际使用新主题时 `.applied.json` 会自动覆盖。
|
|
44
50
|
- **没有合适主题**:不要选择默认“浅色”/“深色”,也不要从列表里随便挑;保持无偏好或执行 `theme preference --clear`,使用内置“简约”兜底。
|
|
45
|
-
-
|
|
51
|
+
- **回到默认状态**:`guanvis theme preference --clear` 会**同时**删除 `.preference.json` 和 `.applied.json`。新建工程下次运行会使用内置 `simple.json`;checkout 工程会优先恢复 `.guanvis/base/page.json` 记录的线上主题或“无主题”状态,避免清除偏好反而改坏已有页面。
|
|
46
52
|
|
|
47
53
|
### 离线 vs 联网
|
|
48
54
|
|