@guandata/guanvis 0.1.44 → 0.1.46
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 +14 -0
- package/bin/platforms.js +34 -0
- package/bin/run.js +76 -44
- package/package.json +14 -4
- package/skills/guanvis/SKILL.md +11 -3
- package/skills/guanvis/references/builder-reference.md +2 -1
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guanvis 0.1.46 - 2026-09-09
|
|
4
|
+
|
|
5
|
+
- 正式发布按系统和架构拆分的原生程序包,安装命令不变,下载量与磁盘占用显著降低。
|
|
6
|
+
- 新建页面前要求指定目标目录并确认落位计划,完成后返回资源链接和存储路径。
|
|
7
|
+
- 页面支持卡片池配置,批量预览会汇总脚本错误并提供合法配置键和候选名称提示。
|
|
8
|
+
- 修复 `DATA_GRID` 错误应用视觉主题的问题。
|
|
9
|
+
|
|
10
|
+
## @guandata/guanvis 0.1.45 - 2026-09-09
|
|
11
|
+
|
|
12
|
+
- 安装时自动选择当前系统和架构的原生程序,减少下载量与磁盘占用,原有安装命令不变;离线安装也支持自动选包。
|
|
13
|
+
- 新建页面前要求指定目标目录并确认落位计划,成功后输出资源链接与存储路径。
|
|
14
|
+
- 新增 `page.addSpareCard()`,支持将卡片放入页面卡片池,`checkout` 后回写保留卡片池配置。
|
|
15
|
+
- `preview` 支持批量汇总脚本错误,提供允许的配置键及候选名称提示,精简错误展示。
|
|
16
|
+
- 修复 `DATA_GRID` 应用视觉主题配置的问题,此类卡片不再应用视觉主题。
|
|
17
|
+
|
|
3
18
|
## @guandata/guanvis 0.1.44 - 2026-09-03
|
|
4
19
|
|
|
5
20
|
- 页面筛选器新增条件匹配、树状、层级树状和组合条件类型,并完善全局参数筛选器的创建与原地更新。
|
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ npm install -g --foreground-scripts @guandata/guanvis
|
|
|
10
10
|
|
|
11
11
|
> 全局安装/升级时会通过 postinstall 自动执行一次 `guanvis install-skill` 刷新 AI skill。`--foreground-scripts` 用于显示明确的成功、失败或跳过结果;失败时按提示手动运行 `guanvis install-skill`。CI 等无需 skill 的环境可设 `GUAN_SKIP_INSTALL_SKILL=1` 跳过。
|
|
12
12
|
|
|
13
|
+
安装包会通过 npm `optionalDependencies` 自动选择当前系统的原生二进制。不要使用 `--omit=optional` 或 `optional=false`;企业 npm 镜像也需要同步对应的 `@guandata/guanvis-<平台>-<架构>` 包。若平台包缺失,CLI 会显示对应包名和重新安装方法。
|
|
14
|
+
|
|
13
15
|
安装后即可在终端使用:
|
|
14
16
|
|
|
15
17
|
```bash
|
|
@@ -55,6 +57,18 @@ guanvis publish ./my_dashboard/ --allow-overwrite
|
|
|
55
57
|
|
|
56
58
|
## 版本更新
|
|
57
59
|
|
|
60
|
+
### @guandata/guanvis 0.1.46
|
|
61
|
+
|
|
62
|
+
- 正式启用按系统和架构拆分的原生程序包,安装命令不变,下载量与磁盘占用显著降低。
|
|
63
|
+
- 新建页面要求指定目标目录并确认落位计划,页面支持卡片池配置。
|
|
64
|
+
- 改进批量预览错误提示,并修复 `DATA_GRID` 主题处理。
|
|
65
|
+
|
|
66
|
+
### @guandata/guanvis 0.1.45
|
|
67
|
+
|
|
68
|
+
- 安装时自动选择当前系统和架构的原生程序,减少下载量与磁盘占用,原有安装命令不变。
|
|
69
|
+
- 支持 macOS arm64/x64、Linux arm64/x64 和 Windows x64;离线安装包也会自动选择匹配的平台。
|
|
70
|
+
- 页面支持卡片池配置,改进批量构建错误提示和页面发布目标目录检查。
|
|
71
|
+
|
|
58
72
|
### @guandata/guanvis 0.1.44
|
|
59
73
|
|
|
60
74
|
- 新增条件匹配、树状、层级树状和组合条件筛选器,并完善全局参数筛选器支持。
|
package/bin/platforms.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const PACKAGE_PREFIX = "@guandata/guanvis";
|
|
4
|
+
|
|
5
|
+
const PLATFORM_TARGETS = [
|
|
6
|
+
{ platform: "darwin", arch: "arm64", suffix: "darwin-arm64", binary: "guanvis" },
|
|
7
|
+
{ platform: "darwin", arch: "x64", suffix: "darwin-x64", binary: "guanvis" },
|
|
8
|
+
{ platform: "linux", arch: "x64", suffix: "linux-x64", binary: "guanvis" },
|
|
9
|
+
{ platform: "linux", arch: "arm64", suffix: "linux-arm64", binary: "guanvis" },
|
|
10
|
+
{ platform: "win32", arch: "x64", suffix: "win32-x64", binary: "guanvis.exe" },
|
|
11
|
+
].map((target) => ({
|
|
12
|
+
...target,
|
|
13
|
+
key: `${target.platform}-${target.arch}`,
|
|
14
|
+
packageName: `${PACKAGE_PREFIX}-${target.suffix}`,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
function targetForRuntime(platform, arch) {
|
|
18
|
+
return PLATFORM_TARGETS.find(
|
|
19
|
+
(target) => target.platform === platform && target.arch === arch
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function optionalDependencies(version) {
|
|
24
|
+
return Object.fromEntries(
|
|
25
|
+
PLATFORM_TARGETS.map((target) => [target.packageName, version])
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
PACKAGE_PREFIX,
|
|
31
|
+
PLATFORM_TARGETS,
|
|
32
|
+
optionalDependencies,
|
|
33
|
+
targetForRuntime,
|
|
34
|
+
};
|
package/bin/run.js
CHANGED
|
@@ -7,34 +7,56 @@ const path = require("path");
|
|
|
7
7
|
const fs = require("fs");
|
|
8
8
|
const os = require("os");
|
|
9
9
|
const { createInstallChildEnv, reexecInstallCommand } = require("./install-env");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
console.error(
|
|
24
|
-
`Unsupported platform: ${key}\nSupported: ${Object.keys(PLATFORM_MAP).join(", ")}`
|
|
10
|
+
const { PLATFORM_TARGETS, targetForRuntime } = require("./platforms");
|
|
11
|
+
|
|
12
|
+
function getBinaryPath(options = {}) {
|
|
13
|
+
const platform = options.platform || process.platform;
|
|
14
|
+
const arch = options.arch || process.arch;
|
|
15
|
+
const resolvePackage = options.resolvePackage || require.resolve;
|
|
16
|
+
const exists = options.exists || fs.existsSync;
|
|
17
|
+
const readJson = options.readJson || ((filename) => JSON.parse(fs.readFileSync(filename, "utf8")));
|
|
18
|
+
const key = `${platform}-${arch}`;
|
|
19
|
+
const target = targetForRuntime(platform, arch);
|
|
20
|
+
if (!target) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Unsupported platform: ${key}\nSupported: ${PLATFORM_TARGETS.map((item) => item.key).join(", ")}`
|
|
25
23
|
);
|
|
26
|
-
process.exit(1);
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
try {
|
|
27
|
+
const packageJson = resolvePackage(`${target.packageName}/package.json`);
|
|
28
|
+
const platformVersion = readJson(packageJson).version;
|
|
29
|
+
const mainVersion = readJson(path.join(__dirname, "..", "package.json")).version;
|
|
30
|
+
if (platformVersion !== mainVersion) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Platform package ${target.packageName} version ${platformVersion} does not match ` +
|
|
33
|
+
`@guandata/guanvis ${mainVersion}. Reinstall @guandata/guanvis.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const binaryPath = path.join(path.dirname(packageJson), "bin", target.binary);
|
|
37
|
+
if (!exists(binaryPath)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Platform package ${target.packageName} is installed but its binary is missing: ${binaryPath}. ` +
|
|
40
|
+
"Reinstall @guandata/guanvis."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return binaryPath;
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err.message && err.message.startsWith("Platform package ")) throw err;
|
|
46
|
+
|
|
47
|
+
// Local development fallback. The generated directory is excluded from
|
|
48
|
+
// the published main package, so installed users always use the optional
|
|
49
|
+
// platform dependency above.
|
|
50
|
+
const localBinary = path.join(__dirname, "..", "platforms", target.suffix, "bin", target.binary);
|
|
51
|
+
if (exists(localBinary)) return localBinary;
|
|
52
|
+
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Missing optional platform package ${target.packageName} for ${key}.\n` +
|
|
55
|
+
"Reinstall without disabling optional dependencies:\n" +
|
|
56
|
+
" npm install -g @guandata/guanvis\n" +
|
|
57
|
+
"If you used --omit=optional or optional=false, remove that setting first."
|
|
33
58
|
);
|
|
34
|
-
process.exit(1);
|
|
35
59
|
}
|
|
36
|
-
|
|
37
|
-
return binaryPath;
|
|
38
60
|
}
|
|
39
61
|
|
|
40
62
|
function copyDirectory(src, dest) {
|
|
@@ -81,7 +103,7 @@ function installBuddySkills(pkgRoot, skill) {
|
|
|
81
103
|
}
|
|
82
104
|
}
|
|
83
105
|
|
|
84
|
-
if (process.argv[2] === "version" && process.argv.length === 3) {
|
|
106
|
+
if (require.main === module && process.argv[2] === "version" && process.argv.length === 3) {
|
|
85
107
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
|
|
86
108
|
console.log(pkg.version);
|
|
87
109
|
process.exit(0);
|
|
@@ -111,7 +133,7 @@ function resolveNpxInvocation() {
|
|
|
111
133
|
return { command: "npx", argsPrefix: [] };
|
|
112
134
|
}
|
|
113
135
|
|
|
114
|
-
if (process.argv[2] === "install-skill") {
|
|
136
|
+
if (require.main === module && process.argv[2] === "install-skill") {
|
|
115
137
|
reexecInstallCommand(__filename, process.argv.slice(2));
|
|
116
138
|
const pkgRoot = path.join(__dirname, "..");
|
|
117
139
|
const extraArgs = process.argv.slice(3);
|
|
@@ -143,28 +165,38 @@ if (process.argv[2] === "install-skill") {
|
|
|
143
165
|
process.exit(status);
|
|
144
166
|
}
|
|
145
167
|
|
|
146
|
-
|
|
168
|
+
if (require.main === module) {
|
|
169
|
+
let binary;
|
|
170
|
+
try {
|
|
171
|
+
binary = getBinaryPath();
|
|
172
|
+
} catch (err) {
|
|
173
|
+
console.error(err.message);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
147
176
|
|
|
148
|
-
try {
|
|
149
|
-
|
|
150
|
-
|
|
177
|
+
try {
|
|
178
|
+
if (process.platform !== "win32") {
|
|
179
|
+
fs.chmodSync(binary, 0o755);
|
|
180
|
+
}
|
|
181
|
+
} catch (_) {
|
|
182
|
+
// chmod may fail in read-only environments
|
|
151
183
|
}
|
|
152
|
-
} catch (_) {
|
|
153
|
-
// chmod may fail in read-only environments
|
|
154
|
-
}
|
|
155
184
|
|
|
156
|
-
if (process.platform === "win32") {
|
|
157
|
-
|
|
158
|
-
}
|
|
185
|
+
if (process.platform === "win32") {
|
|
186
|
+
try { execSync("chcp 65001", { stdio: "ignore" }); } catch (_) {}
|
|
187
|
+
}
|
|
159
188
|
|
|
160
|
-
try {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
} catch (err) {
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
try {
|
|
190
|
+
execFileSync(binary, process.argv.slice(2), {
|
|
191
|
+
stdio: "inherit",
|
|
192
|
+
env: { ...process.env, GUANVIS_PROG_NAME: "guanvis" },
|
|
193
|
+
});
|
|
194
|
+
} catch (err) {
|
|
195
|
+
if (err.status != null) {
|
|
196
|
+
process.exit(err.status);
|
|
197
|
+
}
|
|
198
|
+
throw err;
|
|
168
199
|
}
|
|
169
|
-
throw err;
|
|
170
200
|
}
|
|
201
|
+
|
|
202
|
+
module.exports = { getBinaryPath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guanvis",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.46",
|
|
4
4
|
"description": "观远 BI Card/Page 生成工具 - 通过 JS DSL 创建图表和仪表板",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guanvis": "bin/run.js"
|
|
@@ -8,14 +8,17 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"postinstall": "node bin/postinstall.js",
|
|
10
10
|
"build": "node scripts/build.js && node scripts/sync-skill.js",
|
|
11
|
-
"
|
|
11
|
+
"pack:all": "node scripts/pack-all.js",
|
|
12
|
+
"test:build-script": "node scripts/build.test.js && node scripts/run.test.js",
|
|
13
|
+
"test:package-layout": "node scripts/package-layout.test.js && node scripts/install-smoke.test.js",
|
|
14
|
+
"test:auto-select": "node scripts/auto-select.test.js",
|
|
15
|
+
"verify:platforms": "node scripts/verify-platforms.js",
|
|
12
16
|
"changelog": "node ../../scripts/generate-release-changelog.js .",
|
|
13
17
|
"check-changelog": "node ../../scripts/check-release-changelog.js .",
|
|
14
|
-
"prepublishOnly": "npm run test:build-script && npm run check-changelog && npm run build && node scripts/preflight.js"
|
|
18
|
+
"prepublishOnly": "npm run test:build-script && npm run check-changelog && npm run build && node scripts/preflight.js && npm run test:package-layout && npm run test:auto-select"
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
17
21
|
"bin/",
|
|
18
|
-
"binaries/",
|
|
19
22
|
"skills/",
|
|
20
23
|
"CHANGELOG.md",
|
|
21
24
|
"LICENSE",
|
|
@@ -36,6 +39,13 @@
|
|
|
36
39
|
"linux",
|
|
37
40
|
"win32"
|
|
38
41
|
],
|
|
42
|
+
"optionalDependencies": {
|
|
43
|
+
"@guandata/guanvis-darwin-arm64": "0.1.46",
|
|
44
|
+
"@guandata/guanvis-darwin-x64": "0.1.46",
|
|
45
|
+
"@guandata/guanvis-linux-x64": "0.1.46",
|
|
46
|
+
"@guandata/guanvis-linux-arm64": "0.1.46",
|
|
47
|
+
"@guandata/guanvis-win32-x64": "0.1.46"
|
|
48
|
+
},
|
|
39
49
|
"engines": {
|
|
40
50
|
"node": ">=14"
|
|
41
51
|
},
|
package/skills/guanvis/SKILL.md
CHANGED
|
@@ -18,7 +18,7 @@ AI 生成 `card_*.js` 定义 Card、`page.js` 组装仪表板(`schema.js`/`met
|
|
|
18
18
|
- `theme-colors.js` 是项目级图表主题色事实快照,不手改。准备在脚本中使用 `setThemeColor()` 前,先检查项目根目录;不存在时先运行 `guanvis theme-color sync -d <project>`。调用 `setThemeColor()` 切换主题时必须从快照选择真实 `tcId`,不得猜测或编造。已有文件直接复用,主题色列表变化或切换 BI 环境时用 `theme-color sync` 刷新;快照会记录实际选中的 profile、服务地址和 domain,通过环境变量或默认 profile 切换环境后,构建都会拒绝复用旧快照。`preview`/`diff`/`pack`/`publish` 对缺失快照的自动生成只作兜底。
|
|
19
19
|
- 全局参数先用 `guanvis parameter` 创建或复用,再通过 `dynamic-parameters.js` 按 `dpId` 引用;`pack`/`publish` 不会隐式写入参数。创建前必须按名称查询;发现同名有效参数时立即停止,让用户明确选择"更新已有参数"或"换名创建",不得自动复用或修改。
|
|
20
20
|
- `card_*.js`、`selector_*.js`、`page.js` 是可编辑源文件;`*_package.zip`、`.preview.json`(preview 落盘的全量 payload)、publish 后线上资源都是派生产物,不要手工编辑。
|
|
21
|
-
- **Page 归属红线**:包含 Card/Selector 的资源包必须同时包含 Page,且每个 Card/Selector 都必须被至少一个 Page 引用;否则后端会产生 `pg_id` 为空、无法访问且可能阻塞后续发布的孤儿卡片。校验失败时在 `page.js`
|
|
21
|
+
- **Page 归属红线**:包含 Card/Selector 的资源包必须同时包含 Page,且每个 Card/Selector 都必须被至少一个 Page 引用;否则后端会产生 `pg_id` 为空、无法访问且可能阻塞后续发布的孤儿卡片。校验失败时在 `page.js` 中放置对应资源后同包发布。页面"卡片池"里的卡(checkout 回写为 `page.addSpareCard(cardId)`)归属本页但默认不展示,编辑时原样保留,不要删掉或改成放置。
|
|
22
22
|
- 已有线上仪表板用 `guanvis checkout <pgId> -d <dir>` 拉成可编辑工程(attachCard 基线、自定义图表 `charts/` 反编译、Pro 模板 `templates/`、Page 布局脚本)。checkout 工程只用于修改指定 Page,不用于复制新 Page;只支持普通仪表板(pgType=PAGE),DSL 不能安全表达的结构会直接失败而不是清结构。**checkout 工程动手前先读 `references/checkout-editing.md`**。
|
|
23
23
|
- **Checkout 账号红线**:checkout 读到的是"当前账号视角",publish 整体回写。必须用对涉及数据集有**完整列权限、无脱敏限制**的账号(推荐 owner 或管理员)执行 checkout/publish,否则被裁剪的字段会在回写后从线上卡片永久丢失;多语言租户操作账号语言须与卡片原始语言一致。
|
|
24
24
|
- **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。
|
|
@@ -71,7 +71,7 @@ AI 生成 `card_*.js` 定义 Card、`page.js` 组装仪表板(`schema.js`/`met
|
|
|
71
71
|
21. **布局组件**:AreaTitle/CardGroup/SelGroup/Tab 只支持放画布根布局、不支持嵌套组合;SelGroup 内只能放 selector;详见 `references/builder-reference.md`
|
|
72
72
|
22. **资源包/checkout JSON 禁止手改**:只改 DSL 源文件,不改 ZIP 内部文件与 `.guanvis/**` JSON;批量重绑、迁移页面等需求先讨论方案,必要时扩展 DSL,不手工改生成物。
|
|
73
73
|
23. **动态字段**:用户明确需要字段切换时用 `.addDynamicRow()` / `.addDynamicMetric()` 等(普通卡动态维度/数值,指标卡动态维度/指标);细节见 `references/builder-reference.md`。
|
|
74
|
-
24. **自定义图表(HTML/CSS/JS 自绘)**:内置图表满足不了的可视化才走 `createCustomChart()`。子类型选型:纯 ECharts 配置能画 → `CustomChartSubType.ECHARTS_LITE`(脚本给 `option` 赋值,禁用 `GDPlugin`);需要自定义 DOM/CSS 布局或第三方库(节点图、进度轴、Vega 等)→ `CustomChartSubType.SDK`(`charts/<name>.{html,css,js}` 三件套 + `loadContent("charts/<name>")`,js 里实现 `renderChart(data, clickFunc, config)` 并 `new GDPlugin().init(renderChart)`)。数据用 `.addDataView(createCard(ChartType.DATA_GRID, ...))`
|
|
74
|
+
24. **自定义图表(HTML/CSS/JS 自绘)**:内置图表满足不了的可视化才走 `createCustomChart()`。子类型选型:纯 ECharts 配置能画 → `CustomChartSubType.ECHARTS_LITE`(脚本给 `option` 赋值,禁用 `GDPlugin`);需要自定义 DOM/CSS 布局或第三方库(节点图、进度轴、Vega 等)→ `CustomChartSubType.SDK`(`charts/<name>.{html,css,js}` 三件套 + `loadContent("charts/<name>")`,js 里实现 `renderChart(data, clickFunc, config)` 并 `new GDPlugin().init(renderChart)`)。数据用 `.addDataView(createCard(ChartType.DATA_GRID, ...))` 传入;`DATA_GRID` 只承载数据,不应用页面主题,pack/publish 会删除其 `settings` 中的 `bgSettings`、`backgroundColor`、`showTitle`、`style`、`titleSetting`,checkout 工程回写时也会清理既有值。最小可运行工程直接抄 `evals/custom_chart_sdk/`(SDK)或 `evals/custom_chart_echarts/`(ECHARTS_LITE)。**布局写法**:对齐/等比类要求用结构性保证而非数值手调——固定尺寸容器 + flex 居中让几何天然成立,关键坐标(如贯穿线端点)在渲染 JS 里 `getBoundingClientRect()` 实测反写并挂 resize 重算;手调 top/margin 意味着每发布一次才能验一次。**视觉验收**:preview 只校验结构不渲染 HTML/CSS,本地 file:// 打开也不可靠——正确闭环是发布(可先发到测试目录)后 `guanvis screenshot <pgId>` 读图确认(这是总则"screenshot 不作默认闭环"的例外:自定义图表视觉由手写 HTML/CSS 决定,结构回读覆盖不到);读图判断即可,不要解析 PNG 像素做几何量化,也不要为验收安装图像处理依赖;模型不支持图像理解时,改为把 publish 成功后输出的 `Page URL` 交给用户人工确认。不要浪费时间做本地渲染验证。完整 API 见 `references/builder-reference.md` 的 CustomChartBuilder 章节。
|
|
75
75
|
25. **复杂报表 Pro**:非默认功能,需单独授权——只有用户明确点名"复杂报表 / 复杂报表 Pro"或被修改卡片已是 Pro 才选 Pro;用户只说"表格/报表/透视表"一律用原生卡片(DATA_GRID/PIVOT_TABLE 等),版式做不到时告知"Pro 可实现但需授权"由用户决定。动手前必读 `references/complex-report-pro-patterns.md`(§0 选型、§2 配方、§3 数据视图规则、§4 报错修复、§5 编辑闭环、§6 验证闭环),全部结构红线与修复表以该文件为准;工作流程见下文「复杂报表 Pro 工作方式」
|
|
76
76
|
|
|
77
77
|
## 何时使用
|
|
@@ -197,10 +197,13 @@ guanvis preview ./my_dashboard/
|
|
|
197
197
|
guanvis diff ./existing_dashboard/ # checkout/attach 工程的路径级变更摘要
|
|
198
198
|
|
|
199
199
|
# 发布(publish 自带构建打包上传;pack 只用于生成离线 ZIP 走 upload)
|
|
200
|
+
guanvis publish ./my_dashboard/ --dry-run # 先看"页面落位计划"(目录路径 + dirId),交给用户确认
|
|
200
201
|
guanvis publish ./my_dashboard/ [--page-parent-dir <dir_id>]
|
|
201
|
-
#
|
|
202
|
+
# 每个 Page 都必须有存储目录:page.js 里 .setParentDir("<dirId>") 或 --page-parent-dir;
|
|
203
|
+
# 两者皆无且线上没有同 pgId 页面可沿用时 publish/pack 直接拒绝(不会落根目录,也不会自动建目录)。
|
|
202
204
|
# 目标目录还不存在时先 guanvis dir create --name <名称> --parent <父目录 dirId> 建出来,
|
|
203
205
|
# 用它输出的 dirId 再 publish;查已有目录 ID 用 guancli page tree --type dir
|
|
206
|
+
# 拉不到页面目录树时 publish 会阻断(路径来自目录树,读不到就无法确认落位),先检查账号的页面目录权限
|
|
204
207
|
guanvis pack [-o output.zip] ./my_dashboard/
|
|
205
208
|
guanvis upload output.zip # 只允许上传 guanvis pack 原样生成的 ZIP
|
|
206
209
|
|
|
@@ -301,3 +304,8 @@ guanvis icon list --group default_line -f json
|
|
|
301
304
|
- 是否有 Page,布局方式如何。
|
|
302
305
|
- 是否有验证错误及修复建议。
|
|
303
306
|
- `pack`/`publish`/`upload` 哪些步骤已成功。
|
|
307
|
+
- 每个已发布 Page 的访问链接和存储路径,直接取 `publish` 成功后"页面落位(发布后回读)"段里的 `链接:`(`<BI 地址>/page/<pgId>`)和 `路径:`(页面目录名称链)。回读失败或提示"实际目录与计划目录不一致"时如实转述,不要编造路径。
|
|
308
|
+
|
|
309
|
+
## 发布前必须确认页面存储目录
|
|
310
|
+
|
|
311
|
+
创建/发布仪表板前先明确页面放在哪个文件夹并由用户确认(招行等客户的目录管理规范):先用 `guancli page tree --type dir` 找到目录的路径和 dirId,把"页面 <名称> 将保存到 <路径>"交给用户;目录不存在时用 `guanvis dir create` 显式创建,**不要**让发布流程自动建目录。确认后在 `page.js` 写 `.setParentDir("<dirId>")`(或发布时 `--page-parent-dir`),`publish --dry-run` 会打印"页面落位计划"(目录路径 + dirId + 新建/覆盖),确认无误再真实发布。修改已发布页面(checkout 工程或线上已有同 pgId)时不指定目录会沿用当前目录,落位计划里会标注"沿用"。任何 Page 都不允许没有目录:`publish`/`pack` 会拒绝,不会把页面放到根目录。
|
|
@@ -402,13 +402,14 @@ overview.linkTo("bbbbbbbbbbbbbbbbbbbbbbbb", {
|
|
|
402
402
|
|------|------|
|
|
403
403
|
| `createPage(name)` | 创建 Page |
|
|
404
404
|
| `.setId(pgId)` | 设置 Page ID |
|
|
405
|
-
| `.setParentDir(dirId)` | 设置页面所在目录 ID
|
|
405
|
+
| `.setParentDir(dirId)` | 设置页面所在目录 ID(**必填**:新页面没有目录会被 `publish`/`pack` 拒绝,不会落根目录;已发布页面不设置时沿用线上当前目录),目录 ID 可通过 `guancli page tree --type dir` 获取,不存在时用 `guanvis dir create` 创建 |
|
|
406
406
|
| `.addRow(specs, height?)` | **推荐**:灵活行布局,specs = `[{ card: cardRef, w: colSpan }, ...]`;不传 w 时自动等分当前栅格 |
|
|
407
407
|
| `.addFullWidthCard(cardRef, height?)` | 全宽行,等价于 `addRow([{ card }], height)` |
|
|
408
408
|
| `.addHalfWidthCards(a, b, height?)` | 左右各半 |
|
|
409
409
|
| `.addThirdWidthCards(a, b, c, height?)` | 三等分 |
|
|
410
410
|
| `.addQuarterWidthCards(a, b, c, d, height?)` | 四等分 |
|
|
411
411
|
| `.placeCard(cardRef, x, y, w, h)` | 精确放置 Card,`w/h` 必须大于 0, `x/y/w/h` 必须显式填写 |
|
|
412
|
+
| `.addSpareCard(cardId)` | 把已注册的顶层 Card 放进页面的**卡片池**:仍归属本页、可查询,但不上画布、默认不展示。checkout 回写出的 `addSpareCard(...)` 必须保留,不要删掉或改成 `placeCard` |
|
|
412
413
|
| `.addTab(tab, height?)` | 添加一个满宽 tab 容器;不传 height 时按第一个 panel 内容自动推导 |
|
|
413
414
|
| `.addAreaTitle(areaTitle, height?)` | 添加一个满宽区域小标题|
|
|
414
415
|
| `.addCardGroup(group, height?)` | 添加一个满宽卡片组;不传 height 时按标题和组内布局自动推导 |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|