@guandata/guanvis 0.1.43 → 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 +22 -0
- package/README.md +20 -0
- package/bin/platforms.js +34 -0
- package/bin/run.js +76 -44
- package/package.json +16 -5
- package/skills/guanvis/SKILL.md +15 -6
- package/skills/guanvis/references/api-reference.md +1 -1
- package/skills/guanvis/references/builder-reference.md +43 -188
- package/skills/guanvis/references/chart-properties.md +19 -6
- package/skills/guanvis/references/checkout-editing.md +2 -2
- package/skills/guanvis/references/selector-reference.md +431 -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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
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
|
+
|
|
18
|
+
## @guandata/guanvis 0.1.44 - 2026-09-03
|
|
19
|
+
|
|
20
|
+
- 页面筛选器新增条件匹配、树状、层级树状和组合条件类型,并完善全局参数筛选器的创建与原地更新。
|
|
21
|
+
- 支持统一筛选配置、固定默认值、日期粒度、快捷日期、展示样式、卡片联动、筛选器级联及环路校验。
|
|
22
|
+
- checkout/publish 会保留并可安全编辑已支持筛选器的专属配置,无法无损处理的自定义类型会明确拒绝模拟修改。
|
|
23
|
+
- 改进 Windows npm 全局安装环境下的 CLI 执行器定位。
|
|
24
|
+
|
|
3
25
|
## @guandata/guanvis 0.1.43 - 2026-09-01
|
|
4
26
|
|
|
5
27
|
- 同步底层运行时兼容性与稳定性更新。
|
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,24 @@ 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
|
+
|
|
72
|
+
### @guandata/guanvis 0.1.44
|
|
73
|
+
|
|
74
|
+
- 新增条件匹配、树状、层级树状和组合条件筛选器,并完善全局参数筛选器支持。
|
|
75
|
+
- 支持统一配置默认值、日期粒度、展示样式、卡片联动和筛选器级联,构建时检查无效映射与级联环路。
|
|
76
|
+
- checkout/publish 可保留并安全编辑已支持筛选器配置,同时改善 Windows npm 安装兼容性。
|
|
77
|
+
|
|
58
78
|
### @guandata/guanvis 0.1.43
|
|
59
79
|
|
|
60
80
|
- 同步底层运行时兼容性与稳定性更新。
|
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,10 +39,18 @@
|
|
|
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
|
},
|
|
42
52
|
"publishConfig": {
|
|
43
|
-
"registry": "https://registry.npmjs.org/"
|
|
53
|
+
"registry": "https://registry.npmjs.org/",
|
|
54
|
+
"access": "public"
|
|
44
55
|
}
|
|
45
56
|
}
|
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。
|
|
@@ -42,7 +42,7 @@ AI 生成 `card_*.js` 定义 Card、`page.js` 组装仪表板(`schema.js`/`met
|
|
|
42
42
|
|
|
43
43
|
## AI Quick Reference(速查,详细说明见按需参考资料)
|
|
44
44
|
|
|
45
|
-
**Checkout/attachCard 速记**:`attachCard(cardId, jsonPath)` 是"base JSON + 链式 DSL 操作 = 目标 JSON",不修改 base JSON,重复执行产出相同 payload。zone 修改优先 `update*/patch*/add*/remove*/move*`(整 zone 重建的 `set*/clear*` 会触发 warning
|
|
45
|
+
**Checkout/attachCard 速记**:`attachCard(cardId, jsonPath)` 是"base JSON + 链式 DSL 操作 = 目标 JSON",不修改 base JSON,重复执行产出相同 payload。zone 修改优先 `update*/patch*/add*/remove*/move*`(整 zone 重建的 `set*/clear*` 会触发 warning);已有且在能力矩阵中标记为可编辑的 selector 用 `.setSelectorSetting()` 修改配置,树状筛选器用专属 `.setTreeSetting()` 修改层级字段配置,层级树状筛选器用 `.setLayerTreeSetting()` 修改多选、清空与默认路径,组合条件筛选器用 `.setCombinationSetting()` 修改清空、展示和默认条件(不重新绑定候选字段),`cdType=SELECTOR` 的筛选器用 `.addLink()/.removeLink()/.clearLinks()` 修改联动,禁止借配置入口改变 selector 类型或重新绑定字段;已有 `PARAMETER` selector 例外,允许用 `.bindParameter()` 原地更新参数配置。自定义筛选器等未提供专用 DSL 的类型只能保留已有专属配置。自定义图表内容编辑仅限 SDK/ECHARTS_LITE(编辑 `charts/` 下反编译源文件),COMPLEX_REPORT/PLUGIN/PLUGIN_LITE/REPORT_FORM 调内容编辑 API 直接报错。发布前用 `guanvis diff <dir>` 或 preview 的 `changeSummary` 查看影响面;没有 DSL 操作覆盖的需求应报告暂不支持,不改 `.guanvis` JSON。完整操作语义(zone/筛选区/筛选栏画布互移等)见 `references/checkout-editing.md` §3。
|
|
46
46
|
|
|
47
47
|
**字段显示名与 Card 标题**:`createCard()` 第二参数是 Card 标题,与字段显示名独立。图例/轴标题/表头/Tooltip/指标标签都用字段显示名,需要与物理字段名或 calcField 内部名分开时设置 `alias`(如 `f("营收", { alias: "本月营收" })`);`SINGLE_VALUE`/`KPI_CARD`/`KPI_TREND` 和仪表盘/进度类尤其明显。
|
|
48
48
|
|
|
@@ -57,8 +57,8 @@ AI 生成 `card_*.js` 定义 Card、`page.js` 组装仪表板(`schema.js`/`met
|
|
|
57
57
|
7. **calcField 命名**:不能与数据集物理字段同名,否则 BI 默认取数据集字段
|
|
58
58
|
8. **calcField 类型**:`aggregation`(默认)公式必须含聚合函数;纯算术用 `{ calculationType: "normal" }`;窗口函数用 `{ calculationType: "window" }`
|
|
59
59
|
9. **明细/滚动表 calcField**:`DETAIL_TABLE`/`SCROLL_TABLE` 只逐行展示,行级计算必须 `{ calculationType: "normal" }` 且禁用聚合/窗口函数;汇总需求改用非明细图表或 ETL 预计算
|
|
60
|
-
10.
|
|
61
|
-
11. **selector 类型**:离散值 → `DS_ELEMENTS
|
|
60
|
+
10. **筛选器/联动/下钻**:新建筛选器和能力矩阵中标记可编辑的已有 selector 优先用 `.setSelectorSetting()` 配置;新建筛选器联动图表必须 `.linkToAll()` 或 `.linkTo(cardIndex)`,已有 `cdType=SELECTOR` 筛选器用 `attachCard(...).addLink()/.removeLink()/.clearLinks()` 修改联动;筛选器级联用 `.linkToSelector(selectorId, targetFieldName?)`;完整能力边界和配置规则见 `references/selector-reference.md`。卡片联动卡片用 `card.linkTo(layoutCardIndex, { fields: [{ source, target }] })`;固定路径下钻用 `registerDrillPath(parentCardIndex, [child.build()], { position: DrillPathPosition.BOTTOM })`
|
|
61
|
+
11. **selector 类型**:离散值 → `DS_ELEMENTS`(默认);文本条件 → `TEXT_MATCH`(默认操作符 `CONTAINS`);连续数值 → `SelectorType.DS_INTERVAL`;日期 → `CALENDAR`;快捷日期区间(本月/近7天等)→ `.setSelectorSetting({ type: SelectorType.TIME_MACRO, timeMacro: { options, defaultName } })`(旧 `.setTimeMacroOptions()` 仅保留兼容);树状筛选器 → `SelectorType.TREE` + `.bindTreeFields(...)` + `.setTreeSetting(...)`;层级树状筛选器 → `SelectorType.LAYER_TREE` + `.bindLayerTreeField(...)` + `.setLayerTreeSetting(...)`(字段必须有 `layerTreeId`);组合条件 → `SelectorType.COMBINATION` + `.bindCombinationFields(...)` + `.setCombinationSetting(...)`;全局参数 → `.bindParameter(...)`(自动设置为 `PARAMETER`)
|
|
62
62
|
12. **同环比默认**:未指定输出值时默认增长率;未指定模式时默认 `ComparativeMode.FILTER_BASED`(普通模式需显式 `NORMAL`)。日期字段已是预聚合周期字段(如 `月开始日期`)时必须声明 `{ granularity: Granularity.NONE }`,避免按 DAY 筛选窗口计算为空
|
|
63
63
|
13. **placeCard 入参**:优先用 card/selector ID 字符串(checkout 工程与子目录工程必须用),如 `placeCard("cardId", x, y, w, h)`。数字 index 仅限新建工程,按可布局资源(registerCard/MetricChart/TextCard/ImageCard/CustomChart/DuPontChart)的注册顺序累加,文件按文件名排序加载;**registerSelector 不参与 card index 计数**——selector 进画布/布局组件一律用其 ID 字符串。
|
|
64
64
|
14. **publish 认证**:由底层 CLI 负责——普通 guancli profile 先 `guancli auth use <profile>`;上游托管 OIDC Token 时在当前进程同时设置 `GUANCLI_OIDC_BASE_URL`/`GUANCLI_OIDC_ACCESS_TOKEN`,无需本地 profile;guancli-lite 使用 `GUANCLI_BASE_URL`/`GUANCLI_TOKEN`
|
|
@@ -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
|
|
|
@@ -281,6 +284,7 @@ guanvis icon list --group default_line -f json
|
|
|
281
284
|
|------|------|----------|
|
|
282
285
|
| 字段、计算字段、NumberFormat、高级计算、卡片筛选器 API | `references/api-reference.md` | 写字段/指标/公式/筛选条件时 |
|
|
283
286
|
| 各类 Builder API 与枚举(含 ComplexReportProBuilder 权威定义) | `references/builder-reference.md` | 写或改 JS DSL builder 调用时 |
|
|
287
|
+
| 页面筛选器:类型、配置、默认值、联动、级联、参数和 checkout 编辑 | `references/selector-reference.md` | 创建或修改 selector 前必读 |
|
|
284
288
|
| 图表属性配置 | `references/chart-properties.md` | 创建或修改图表属性时 |
|
|
285
289
|
| checkout 编辑闭环:生成物、attachCard 操作语义、覆盖发布与备份 | `references/checkout-editing.md` | checkout 工程动手前、改线上仪表板时 |
|
|
286
290
|
| 页面目录与页面壳管理完整硬约束 | `references/dir-and-page-management.md` | `guanvis dir` / `page rename/move/delete` 动手前 |
|
|
@@ -300,3 +304,8 @@ guanvis icon list --group default_line -f json
|
|
|
300
304
|
- 是否有 Page,布局方式如何。
|
|
301
305
|
- 是否有验证错误及修复建议。
|
|
302
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` 会拒绝,不会把页面放到根目录。
|
|
@@ -471,6 +471,6 @@ createCard(ChartType.PIVOT_TABLE, "品牌同比分析")
|
|
|
471
471
|
|
|
472
472
|
`filterField(dsId, fieldName, filterType, filterValue?, opts?)` — 与 `field()` 和 `calcField()` 模式一致。
|
|
473
473
|
|
|
474
|
-
枚举 `FilterType`:`IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `ENDSWITH`, `IS_NULL`, `NOT_NULL`
|
|
474
|
+
枚举 `FilterType`:`IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `NOT_STARTSWITH`, `ENDSWITH`, `NOT_ENDSWITH`, `IS_NULL`, `NOT_NULL`
|
|
475
475
|
|
|
476
476
|
枚举 `FilterLevel`:`DETAIL`(明细筛选,默认), `AGGREGATION`(聚合筛选), `RESULT`(结果筛选)
|
|
@@ -394,7 +394,7 @@ overview.linkTo("bbbbbbbbbbbbbbbbbbbbbbbb", {
|
|
|
394
394
|
3. `addRow()` 及其快捷方法的 `height` 省略或为 0 时使用默认行高(普通 6,精细 18)。
|
|
395
395
|
4. 区域小标题用 `createAreaTitle(...).setId(...).build()` 定义,并通过 `page.addAreaTitle(title)` 放在 Page 根布局;不要放进 tab panel。
|
|
396
396
|
5. 卡片组用 `createCardGroup(...).setId(...)` 定义,并通过 `page.addCardGroup(group)` 放在 Page 根布局。
|
|
397
|
-
6. 筛选器组用 `createSelectorGroup(...).setId(...)`
|
|
397
|
+
6. 筛选器组用 `createSelectorGroup(...).setId(...)` 定义;放在画布中的筛选器组通过 `page.addSelectorGroup(group)` 加入 Page 根布局,放在筛选栏中的筛选器组通过 `page.addFilterSelectorGroup(group)` 加入筛选栏。未分组 selector 可通过 `page.addFilterSelector(selectorId)` 显式控制顺序;组内只能放 selector。checkout 后修改已有快捷筛选区时,优先用 `setFilterLayout()` / `clearFilterLayout()` / `addFilterLayoutItem()` / `insertFilterSelector()` / `removeFilterSelector()` / `moveFilterSelector()` 表达增量操作;筛选器或筛选器组需要在快捷筛选区和画布之间移动时,优先用动作级 `moveFilterSelectorToCanvas()` / `moveCanvasSelectorToFilter()` / `moveSelectorGroupToCanvas()` / `moveCanvasSelectorGroupToFilter()`,不要手改 base JSON。
|
|
398
398
|
7. checkout 生成的根布局组件会使用 `page.placeTab()` / `placeAreaTitle()` / `placeCardGroup()` / `placeSelectorGroup()` 保留线上 x/y/w/h;新建工程通常继续用 `addTab()` / `addAreaTitle()` / `addCardGroup()` / `addSelectorGroup()` 自动满宽布局。
|
|
399
399
|
8. 下文布局 API 中的 `cardRef` 表示:推荐使用已注册卡片或 selector 的字符串 ID;数字 index 仍可用于非 selector 卡片,按可布局资源注册顺序计数。`registerSelector()` 不参与数字 index 计数;被布局引用的 selector 不再进入同页筛选器栏。
|
|
400
400
|
|
|
@@ -402,23 +402,24 @@ 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 时按标题和组内布局自动推导 |
|
|
415
|
-
| `.addSelectorGroup(group, height?)` |
|
|
416
|
+
| `.addSelectorGroup(group, height?)` | 在画布中添加一个满宽筛选器组;不传 height 时按展示模式、标题和组内布局自动推导 |
|
|
416
417
|
| `.placeTab(tab, x, y, w, h)` | checkout/精确布局用:注册 tab 并按显式坐标放入 Page 根布局 |
|
|
417
418
|
| `.placeAreaTitle(areaTitle, x, y, w, h)` | checkout/精确布局用:注册区域小标题并按显式坐标放入 Page 根布局 |
|
|
418
419
|
| `.placeCardGroup(group, x, y, w, h)` | checkout/精确布局用:注册卡片组并按显式坐标放入 Page 根布局 |
|
|
419
|
-
| `.placeSelectorGroup(group, x, y, w, h)` | checkout
|
|
420
|
+
| `.placeSelectorGroup(group, x, y, w, h)` | checkout/精确布局用:注册筛选器组并按显式坐标放入 Page 根布局 |
|
|
420
421
|
| `.removeLayoutItem(cardRef)` | 从当前 Page 根布局移除已放置的 card/selector/layout component;主要给动作级移动 API 使用 |
|
|
421
|
-
| `.addFilterSelectorGroup(group)` |
|
|
422
|
+
| `.addFilterSelectorGroup(group)` | 在筛选栏中添加一个筛选器组 |
|
|
422
423
|
| `.addFilterSelector(selectorId)` | 显式添加一个未分组的筛选栏 selector,并控制其与筛选器组的顺序 |
|
|
423
424
|
| `.setFilterPanelLayout(config)` | 配置筛选栏布局和视觉样式;见下方“筛选栏布局与视觉” |
|
|
424
425
|
| `.setFilterLayout(items)` | 整体设置快捷筛选区的 selector / filter selectorGroup ID 列表;checkout 场景会覆盖 base `filterLayout` |
|
|
@@ -730,9 +731,9 @@ registerPage(page.build());
|
|
|
730
731
|
|
|
731
732
|
### SelectorGroupBuilder
|
|
732
733
|
|
|
733
|
-
`SelGroup` 是原生筛选器组,不是 Card,不绑定数据集,也不会生成独立 page-card relation。ID 必须以 `selGroup_` 开头,使用 `guanvis gen-layout-id selGroup`
|
|
734
|
+
`SelGroup` 是原生筛选器组,不是 Card,不绑定数据集,也不会生成独立 page-card relation。ID 必须以 `selGroup_` 开头,使用 `guanvis gen-layout-id selGroup` 生成。位于画布的 SelGroup 只能放入 Page 根布局;位于筛选栏的 SelGroup 只能放入 `filterLayout`;组内只能包含已注册 selector。
|
|
734
735
|
|
|
735
|
-
默认值:`displayMode = "tiled"`、`showTitle = false`、`titleStyle.fontSize = 14`、`titleStyle.bold = true
|
|
736
|
+
默认值:`displayMode = "tiled"`、`showTitle = false`、`titleStyle.fontSize = 14`、`titleStyle.bold = true`。筛选栏中的组名始终来自 `name`,不受 `showTitle` 控制。
|
|
736
737
|
|
|
737
738
|
| 方法 | 说明 |
|
|
738
739
|
|------|------|
|
|
@@ -740,15 +741,15 @@ registerPage(page.build());
|
|
|
740
741
|
| `.setId(selGroupId)` | **必填**。设置筛选器组 ID,必须以 `selGroup_` 开头 |
|
|
741
742
|
| `.setRawStyle(style)` | checkout 保留线上 style 用;新建工程优先用 `.setDisplayMode()` / `.setShowTitle()` / `.setFpWidth()` |
|
|
742
743
|
| `.setDisplayMode(mode)` | 展示模式:`SelectorGroupDisplayMode.TILED`(默认)或 `SelectorGroupDisplayMode.DROPDOWN` |
|
|
743
|
-
| `.setShowTitle(boolean)` |
|
|
744
|
-
| `.setFpWidth(width)` |
|
|
745
|
-
| `.setFpGrid(span)` |
|
|
746
|
-
| `.addSelector(selectorId)` / `.addSelectors(selectorIds)` |
|
|
747
|
-
| `.addRow(specs, height?)` |
|
|
748
|
-
| `.addFullWidthCard(cardRef, height?)` |
|
|
749
|
-
| `.placeCard(cardRef, x, y, w, h)` |
|
|
744
|
+
| `.setShowTitle(boolean)` | 是否显示画布中筛选器组的标题;默认 `false` |
|
|
745
|
+
| `.setFpWidth(width)` | 筛选栏非栅格模式宽度,仅用于筛选栏中的筛选器组 |
|
|
746
|
+
| `.setFpGrid(span)` | 筛选栏栅格模式宽度,仅用于筛选栏中的筛选器组 |
|
|
747
|
+
| `.addSelector(selectorId)` / `.addSelectors(selectorIds)` | 添加要放在筛选栏中的 selector;使用后只能传给 `page.addFilterSelectorGroup()` |
|
|
748
|
+
| `.addRow(specs, height?)` | 添加要放在画布中的 selector 布局,写法同 `PageBuilder.addRow()`;height 省略或为 0 时 selector 高度默认普通 1、精细 3;使用后只能传给 `page.addSelectorGroup()` |
|
|
749
|
+
| `.addFullWidthCard(cardRef, height?)` | 在画布中的筛选器组内放一个满宽 selector |
|
|
750
|
+
| `.placeCard(cardRef, x, y, w, h)` | 精确放置画布中筛选器组内的 selector |
|
|
750
751
|
|
|
751
|
-
|
|
752
|
+
画布中的下拉筛选器组:
|
|
752
753
|
|
|
753
754
|
```javascript
|
|
754
755
|
var advanced = createSelectorGroup("高级筛选")
|
|
@@ -765,7 +766,7 @@ var page = createPage("销售仪表板")
|
|
|
765
766
|
.addSelectorGroup(advanced);
|
|
766
767
|
```
|
|
767
768
|
|
|
768
|
-
|
|
769
|
+
筛选栏中的筛选器组与未分组 selector 混排:
|
|
769
770
|
|
|
770
771
|
```javascript
|
|
771
772
|
var globalFilters = createSelectorGroup("全局筛选")
|
|
@@ -877,180 +878,31 @@ registerPage(page.build());
|
|
|
877
878
|
|
|
878
879
|
### SelectorBuilder(筛选器)
|
|
879
880
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
**布局归属**:
|
|
883
|
-
- 全局筛选器可进入页面筛选器栏,并按需使用 `.linkToAll()`。
|
|
884
|
-
- 凡是作为画布内容或隶属于某个分区、Tab、CardGroup 的筛选器,必须跟随所属布局放置,不进入筛选栏。局部筛选器使用 `.linkTo(...)` 明确联动所属分区内图表,不默认 `.linkToAll()`。
|
|
881
|
+
这里只保留方法索引。类型选择、配置约束、默认值、参数绑定、联动/级联、checkout 编辑和完整示例统一见 `selector-reference.md`;创建或修改筛选器前必须读取该文档。
|
|
885
882
|
|
|
886
883
|
| 方法 | 说明 |
|
|
887
884
|
|------|------|
|
|
888
885
|
| `createSelector(name)` | 创建筛选器 |
|
|
889
|
-
| `.setId(cardId)` |
|
|
890
|
-
| `.
|
|
891
|
-
| `.
|
|
892
|
-
| `.
|
|
893
|
-
| `.
|
|
894
|
-
| `.
|
|
895
|
-
| `.
|
|
896
|
-
| `.
|
|
897
|
-
| `.
|
|
898
|
-
| `.
|
|
899
|
-
| `.
|
|
900
|
-
| `.
|
|
901
|
-
| `.
|
|
902
|
-
| `.
|
|
903
|
-
| `.setDefaultDateRange(start, end, displayValues?)` |
|
|
904
|
-
| `.setFirstPickLink(bool)` |
|
|
905
|
-
| `.setDisplayType(type)` |
|
|
906
|
-
| `.
|
|
907
|
-
| `.
|
|
908
|
-
| `.
|
|
909
|
-
| `.linkToSelector(selectorId, targetFieldName?)` | 联动指定筛选器(用于省→市→区等级联)。`selectorId` 为目标筛选器 ID;`targetFieldName` 默认按源字段名匹配目标筛选器数据集字段。目标筛选器为 `ALL`/空默认值时会自动启用 `FIRST_PICK + firstPickLink`,固定默认值会保留 |
|
|
910
|
-
| `.linkToAll()` | 自动联动所有普通图表卡片、MetricChart 和杜邦子卡片(按同名字段匹配) |
|
|
911
|
-
| `.build()` | 构建(触发验证) |
|
|
912
|
-
|
|
913
|
-
推荐优先使用统一配置入口,旧的 `.setSelectorType()`、`.setMultiSelect()`、`.setDefaultValue()` 等方法继续兼容。资源身份、数据绑定和联动具有独立生命周期,仍分别使用 `.setId()`、`.bindField()` / `.bindParameter()` 和 `.linkTo*()`;已有筛选器联动使用 `attachCard().addLink()/removeLink()/clearLinks()`。
|
|
914
|
-
|
|
915
|
-
`setSelectorSetting(config)` 的结构如下。所有字段都可选;`false`、`0` 和允许的空数组都会按显式值处理,未传字段在 `attachCard()` 模式下保持线上原值:
|
|
916
|
-
|
|
917
|
-
```javascript
|
|
918
|
-
{
|
|
919
|
-
type: SelectorType.DS_ELEMENTS,
|
|
920
|
-
filterType: FilterType.IN,
|
|
921
|
-
selection: {
|
|
922
|
-
multiple: true,
|
|
923
|
-
showSelectAll: true,
|
|
924
|
-
canClear: false,
|
|
925
|
-
firstPickLink: false
|
|
926
|
-
},
|
|
927
|
-
display: {
|
|
928
|
-
type: SelectorDisplay.SEARCH_BOX,
|
|
929
|
-
showColumnName: true
|
|
930
|
-
},
|
|
931
|
-
defaultValue: {
|
|
932
|
-
type: SelectorDefaultType.FIXED_VALUE,
|
|
933
|
-
values: ["华东"],
|
|
934
|
-
displayValues: ["华东地区"]
|
|
935
|
-
},
|
|
936
|
-
calendar: {
|
|
937
|
-
granularities: [Granularity.MONTH, Granularity.QUARTER],
|
|
938
|
-
defaultGranularity: Granularity.MONTH
|
|
939
|
-
},
|
|
940
|
-
timeMacro: {
|
|
941
|
-
options: [{ name: "最近7天", expr: ["LAST_7_DAY"] }],
|
|
942
|
-
defaultName: "最近7天"
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
```
|
|
946
|
-
|
|
947
|
-
适用规则:`selection.multiple/showSelectAll` 和 `display.type` 仅用于 `DS_ELEMENTS`;`calendar` 仅用于 `CALENDAR`;`timeMacro` 仅用于 `TIME_MACRO`。`defaultValue.values` 会切换为 `FIXED_VALUE`。已有筛选器传入的 `type` 是类型断言,不能借此把筛选器改成另一种类型,也不会重新绑定字段或参数。
|
|
948
|
-
|
|
949
|
-
**使用示例**:
|
|
950
|
-
|
|
951
|
-
```javascript
|
|
952
|
-
// selector_01_region.js — 列表选择(DS_ELEMENTS,默认)
|
|
953
|
-
var sel = createSelector("区域筛选")
|
|
954
|
-
.setId("s184352b7a76776db5f534df")
|
|
955
|
-
.bindField(f("区域"))
|
|
956
|
-
.setSelectorSetting({
|
|
957
|
-
selection: { multiple: true, showSelectAll: true, canClear: false },
|
|
958
|
-
display: { type: SelectorDisplay.SEARCH_BOX }
|
|
959
|
-
})
|
|
960
|
-
.linkToAll()
|
|
961
|
-
.build();
|
|
962
|
-
registerSelector(sel);
|
|
963
|
-
```
|
|
964
|
-
|
|
965
|
-
```javascript
|
|
966
|
-
// selector_02_profit_rate.js — 数值范围(DS_INTERVAL)
|
|
967
|
-
var sel = createSelector("利润率筛选")
|
|
968
|
-
.setId("h61d8bf256952ef3fcf961c5")
|
|
969
|
-
.setSelectorType(SelectorType.DS_INTERVAL) // 范围筛选器
|
|
970
|
-
.bindField(f("利润率"))
|
|
971
|
-
.linkToAll()
|
|
972
|
-
.build();
|
|
973
|
-
registerSelector(sel);
|
|
974
|
-
// DS_INTERVAL 默认 filterType="BT"(区间),展示两个输入框(起始值-结束值)
|
|
975
|
-
// 也可设置 .setFilterType("EQ") 单值等于,或 "GT"/"LT" 等比较
|
|
976
|
-
```
|
|
977
|
-
|
|
978
|
-
```javascript
|
|
979
|
-
// selector_03_date.js — 日期范围(CALENDAR)
|
|
980
|
-
var sel = createSelector("日期筛选")
|
|
981
|
-
.setId("abc123def456abc123def456")
|
|
982
|
-
.setSelectorType(SelectorType.CALENDAR)
|
|
983
|
-
.bindField(f("订单日期"))
|
|
984
|
-
.setDefaultDateRange("2026-01-01", "2026-01-31")
|
|
985
|
-
.linkToAll()
|
|
986
|
-
.build();
|
|
987
|
-
registerSelector(sel);
|
|
988
|
-
// CALENDAR 默认 filterType="BT"(区间),固定默认值必须是 2 个日期值。
|
|
989
|
-
// 支持 "2026-01-15"、"2026-01"、"2026-Q1"、"2026-W03"、"2026" 等格式。
|
|
990
|
-
// 同一个默认值数组必须使用同一粒度;未显式 setGranularity 时会从默认值格式推断粒度。
|
|
991
|
-
```
|
|
992
|
-
|
|
993
|
-
```javascript
|
|
994
|
-
// selector_03_timemacro.js — 快捷日期(TIME_MACRO)
|
|
995
|
-
var sel = createSelector("快捷日期")
|
|
996
|
-
.setId("gf7a7ed51ec7c9477fcd1d81")
|
|
997
|
-
.setSelectorSetting({
|
|
998
|
-
type: SelectorType.TIME_MACRO,
|
|
999
|
-
timeMacro: {
|
|
1000
|
-
options: [
|
|
1001
|
-
{ name: "今天", expr: ["TODAY"] },
|
|
1002
|
-
{ name: "昨天", expr: ["YESTERDAY"] },
|
|
1003
|
-
{ name: "最近7天", expr: ["LAST_7_DAY"] },
|
|
1004
|
-
{ name: "最近30天", expr: ["LAST_30_DAY"] },
|
|
1005
|
-
{ name: "本月", expr: ["MONTH_TO_DAY"] },
|
|
1006
|
-
{ name: "上月", expr: ["LAST_MONTH"] },
|
|
1007
|
-
{ name: "本年", expr: ["YEAR_TO_DAY"] }
|
|
1008
|
-
],
|
|
1009
|
-
defaultName: "最近7天"
|
|
1010
|
-
}
|
|
1011
|
-
})
|
|
1012
|
-
.linkToAll()
|
|
1013
|
-
.build();
|
|
1014
|
-
registerSelector(sel);
|
|
1015
|
-
// TIME_MACRO 不需要 bindField/bindDataset,自动匹配目标卡片中的日期字段联动
|
|
1016
|
-
// 内置宏名(expr数组只需一个元素):TODAY, YESTERDAY, LAST_7_DAY, LAST_14_DAY,
|
|
1017
|
-
// LAST_30_DAY, LAST_90_DAY, LAST_1_YEAR, LAST_WEEK, LAST_MONTH,
|
|
1018
|
-
// WEEK_TO_DAY, MONTH_TO_DAY, YEAR_TO_DAY, DAY_BEFORE_YESTERDAY,
|
|
1019
|
-
// WEEK_TO_YESTERDAY, MONTH_TO_YESTERDAY, YEAR_TO_YESTERDAY,
|
|
1020
|
-
// QUARTER_TO_DAY, QUARTER_TO_YESTERDAY, YEAR_TO_LAST_MONTH, YEAR_TO_LAST_QUARTER
|
|
1021
|
-
```
|
|
1022
|
-
|
|
1023
|
-
```javascript
|
|
1024
|
-
// selector_04_cascade.js — 筛选器级联(省 -> 市)
|
|
1025
|
-
var city = createSelector("市")
|
|
1026
|
-
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
1027
|
-
.bindField(f("市"))
|
|
1028
|
-
.build();
|
|
1029
|
-
registerSelector(city);
|
|
1030
|
-
|
|
1031
|
-
var province = createSelector("省")
|
|
1032
|
-
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
1033
|
-
.bindField(f("省"))
|
|
1034
|
-
.linkToSelector("bbbbbbbbbbbbbbbbbbbbbbbb") // 默认用“省”过滤“市”筛选器的数据集
|
|
1035
|
-
.linkToAll()
|
|
1036
|
-
.build();
|
|
1037
|
-
registerSelector(province);
|
|
1038
|
-
// 若目标筛选器“市”是 ALL/空默认值(包括显式 setDefaultAll()),
|
|
1039
|
-
// 会自动启用 FIRST_PICK + firstPickLink,省变化后自动重选第一项并继续向下游联动。
|
|
1040
|
-
// 若目标筛选器已显式 setDefaultValue([...]) 固定默认值,则保持用户设置。
|
|
1041
|
-
// 如果目标筛选器数据集中的上游字段不是同名字段,可传第二个参数:
|
|
1042
|
-
// .linkToSelector("bbbbbbbbbbbbbbbbbbbbbbbb", "所属省份")
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
**筛选器类型选择指南**:
|
|
1046
|
-
- **离散值**(区域、类别、客户名等文本字段)→ `DS_ELEMENTS`(默认),配合 `setDisplayType` 选择展示样式
|
|
1047
|
-
- **连续数值范围**(利润率、金额区间等)→ `SelectorType.DS_INTERVAL`,默认区间输入(起始值-结束值)
|
|
1048
|
-
- **日期选择**(精确日期范围)→ `SelectorType.CALENDAR`,需要 `bindField` 绑定日期字段。默认会从联动目标卡片推断日期粒度;如需固定月/季度等粒度,可用 `.setGranularity(Granularity.MONTH)` 或 `.setGranularityOptions([...], default)`
|
|
1049
|
-
- **快捷日期区间**(本月/上月/近7天等预设区间)→ `.setSelectorSetting({ type: SelectorType.TIME_MACRO, timeMacro: { options, defaultName } })`,不需要 `bindField`,自动匹配目标卡片日期字段联动。`defaultName` 传 `null` 表示无默认值;旧 `.setTimeMacroOptions()` 仅保留兼容
|
|
1050
|
-
|
|
1051
|
-
**联动机制**:筛选器通过 `settings.asFilter` 配置联动关系。`linkTo(cardIndex)` 会自动构建 `columnMappings`,将筛选器字段映射到目标卡片的同名字段;cardIndex 只统计普通图表、MetricChart 和杜邦子卡片,文本/图片等不可联动资源不占序号。`linkToSelector(selectorId, targetFieldName?)` 用于筛选器联动筛选器,目标必须是已注册的 DS_ELEMENTS/TREE 筛选器,构建时会检查 selector 级联成环;目标为 ALL/空默认值时会自动改为 `FIRST_PICK + firstPickLink`,目标已有固定默认值时保留用户设置。`linkToAll()` 会自动匹配所有普通图表卡片、MetricChart 和杜邦子卡片中的同名字段,不自动包含筛选器。若同一个筛选器同时写了 `linkTo(index, "自定义字段")` 和 `linkToAll()`,显式 `linkTo` 的目标字段映射优先。
|
|
1052
|
-
|
|
1053
|
-
**文件命名**:筛选器脚本建议命名为 `selector_NN_xxx.js`,会在 `card_*.js` 之后、`page.js` 之前执行。
|
|
886
|
+
| `.setId(cardId)` | 设置资源 ID |
|
|
887
|
+
| `.setDescription(desc)` | 设置筛选器描述 |
|
|
888
|
+
| `.setSelectorSetting(config)` | 统一配置新建筛选器或能力矩阵中标记可编辑的已有 selector |
|
|
889
|
+
| `.setSelectorType(type)` / `.setFilterType(type)` | 设置筛选器类型和条件 |
|
|
890
|
+
| `.setFilterLevel(level)` | 设置筛选级别(`FilterLevel.DETAIL` 默认;`PARAMETER` 不支持) |
|
|
891
|
+
| `.bindDataset(dsId)` / `.bindField(field)` | 绑定数据集和字段 |
|
|
892
|
+
| `.bindTreeFields(...fields)` / `.setTreeSetting(config)` | 配置树状筛选器的固定层级字段和专属设置,详见 `selector-reference.md` |
|
|
893
|
+
| `.bindLayerTreeField(field)` / `.setLayerTreeSetting(config)` | 配置层级树状筛选器的单个层级树字段和专属设置;字段必须有 `layerTreeId` |
|
|
894
|
+
| `.bindCombinationFields(...fields)` / `.setCombinationSetting(config)` | 配置组合条件筛选器的候选字段与默认条件,详见 `selector-reference.md` |
|
|
895
|
+
| `.bindParameter(paramRef, options?)` | 绑定全局参数 |
|
|
896
|
+
| `.setGranularity(granularity)` / `.setGranularityOptions(options, defaultGranularity?)` | 设置日期粒度 |
|
|
897
|
+
| `.setTimeMacroOptions(options, defaultMacroName?)` | 设置快捷日期选项 |
|
|
898
|
+
| `.setMultiSelect(bool)` / `.setShowSelectAll(bool)` / `.setCanClear(bool)` | 设置选择行为 |
|
|
899
|
+
| `.setDefaultType(type)` / `.setDefaultAll()` | 设置默认值模式 |
|
|
900
|
+
| `.setDefaultValue(values, displayValues?)` / `.setDefaultDateRange(start, end, displayValues?)` | 设置固定默认值 |
|
|
901
|
+
| `.setFirstPickLink(bool)` | 设置首项联动刷新 |
|
|
902
|
+
| `.setDisplayType(type)` | 设置展示类型 |
|
|
903
|
+
| `.linkTo(cardIndex, targetFieldNameOrMappings?)` / `.linkToAll()` | 联动图表;组合条件可传字段映射对象 |
|
|
904
|
+
| `.linkToSelector(selectorId, targetFieldName?)` | 联动筛选器 |
|
|
905
|
+
| `.build()` | 构建并验证 |
|
|
1054
906
|
|
|
1055
907
|
### TextCardBuilder(文本卡片)
|
|
1056
908
|
|
|
@@ -1805,11 +1657,14 @@ project/
|
|
|
1805
1657
|
| `GrandTotalPosition` | `LEFT`, `RIGHT`, `TOP`, `BOTTOM` | 表格总计位置;行总计用左右,列总计用上下 |
|
|
1806
1658
|
| `ContentSpaceSize` | `SMALL`, `MIDDLE`, `LARGE` | 卡片内容间距 |
|
|
1807
1659
|
| `DynamicFieldOrder` | `PRESET`, `CLICK` | 动态字段默认顺序;`PRESET` 按候选顺序,`CLICK` 按用户选择顺序 |
|
|
1808
|
-
| `FilterType` | `IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `ENDSWITH`, `IS_NULL`, `NOT_NULL` | 筛选条件类型 |
|
|
1660
|
+
| `FilterType` | `IN`, `NOT_IN`, `GT`, `GE`, `LT`, `LE`, `EQ`, `NE`, `BT`(区间), `CONTAINS`, `NOT_CONTAINS`, `STARTSWITH`, `NOT_STARTSWITH`, `ENDSWITH`, `NOT_ENDSWITH`, `IS_NULL`, `NOT_NULL` | 筛选条件类型 |
|
|
1809
1661
|
| `FilterLevel` | `DETAIL`(明细), `AGGREGATION`(聚合), `RESULT`(结果) | 筛选级别 |
|
|
1810
1662
|
| `NumberFormat` | `.number()`, `.currency()`, `.percentage()`, `.auto()`, `.custom()` | 数值格式化工厂 |
|
|
1811
|
-
| `SelectorType` | `DS_ELEMENTS`(默认), `DS_INTERVAL`, `CALENDAR`, `TIME_MACRO` | 筛选器类型 |
|
|
1663
|
+
| `SelectorType` | `DS_ELEMENTS`(默认), `TEXT_MATCH`, `DS_INTERVAL`, `CALENDAR`, `TIME_MACRO`, `PARAMETER`, `TREE`, `LAYER_TREE`, `COMBINATION` | 筛选器类型 |
|
|
1812
1664
|
| `SelectorDisplay` | `SEARCH_LIST`(单选下拉), `SEARCH_BOX`(多选下拉), `CHECKBOX`(复选框), `RADIO`(单选框), `BUTTON_GROUP`(按钮组) | 筛选器展示类型,不设置时根据 multiSelect 自动推断 |
|
|
1665
|
+
| `TreeSelectorDisplay` | `SEARCH_BOX`, `FLAT` | 树状筛选器的展示类型 |
|
|
1666
|
+
| `CombinationSelectorDisplay` | `DEFAULT`, `STANDARD` | 组合条件筛选器的展示类型 |
|
|
1667
|
+
| `Combination` | `.condition(field, filterType, values, { not }?)`, `.and(...)`, `.or(...)` | 组合条件默认值 AST 构造器 |
|
|
1813
1668
|
| `SelectorDefaultType` | `FIRST_PICK`, `FIXED_VALUE`, `ALL`(默认,全部/不筛选) | 筛选器默认值类型 |
|
|
1814
1669
|
| `TabTitlePosition` | `TOP`, `LEFT` | Tab 总标题位置 |
|
|
1815
1670
|
| `LayoutMarginType` | `NONE`, `SPACE`, `DIVIDE` | Tab panel 与卡片组的卡片间距模式 |
|
|
@@ -83,12 +83,14 @@
|
|
|
83
83
|
titleSetting: {
|
|
84
84
|
backgroundColor: "#FFFFFF",
|
|
85
85
|
height: 40,
|
|
86
|
-
showBgImage:
|
|
86
|
+
showBgImage: true,
|
|
87
|
+
bgImage: {
|
|
88
|
+
uploadPath: "./assets/title-background.png",
|
|
89
|
+
renderType: ImageRenderType.STRETCH
|
|
90
|
+
},
|
|
87
91
|
showIcon: true,
|
|
88
92
|
icon: {
|
|
89
|
-
|
|
90
|
-
sourceType: 3,
|
|
91
|
-
renderType: 3
|
|
93
|
+
uploadPath: "./assets/title-icon.png"
|
|
92
94
|
},
|
|
93
95
|
topStrip: {
|
|
94
96
|
enabled: true,
|
|
@@ -123,10 +125,21 @@
|
|
|
123
125
|
| `backgroundColor` | string / `null` | 标题区域背景色 |
|
|
124
126
|
| `height` | 0–100 的整数 | 标题区域高度,单位 px |
|
|
125
127
|
| `showBgImage` / `showIcon` | boolean | 是否显示背景图/图标 |
|
|
126
|
-
| `bgImage` / `icon` | image object / `null` |
|
|
128
|
+
| `bgImage` / `icon` | image object / `null` | 图片配置;`null` 清除对应图片 |
|
|
127
129
|
| `topStrip` / `bottomStrip` | strip object / `null` | 顶部/底部边框 |
|
|
128
130
|
|
|
129
|
-
|
|
131
|
+
图片对象支持:
|
|
132
|
+
|
|
133
|
+
| 字段 | 类型/取值 | 说明 |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `url` | string | 外链、当前环境已有的上传图片地址或素材地址 |
|
|
136
|
+
| `uploadPath` | string | 本地图片路径;没有 `url` 时生效,`pack`/`publish` 时作为 Card 附件上传 |
|
|
137
|
+
| `sourceType` | `1` / `2` / `3` | 链接、上传或素材;使用 `uploadPath` 时固定为 `2`,不必传入 |
|
|
138
|
+
| `renderType` | `1` / `2` / `3` | 原比例、铺满或自适应;本地图片省略时默认自适应 |
|
|
139
|
+
|
|
140
|
+
本地标题背景图和 icon 支持 `jpg/jpeg/png/gif`,相对路径以 guanvis 工程目录为基准;`url` 和
|
|
141
|
+
`uploadPath` 同时设置时优先使用 `url`,并产生 warning。边框对象包含 `enabled`、`backgroundColor`
|
|
142
|
+
和 `width`,其中 `width` 可用 `2`、`4`、`6`、`8`。
|
|
130
143
|
|
|
131
144
|
`attachCard()` 只增量合并显式传入的字段。例如只修改字号和底部边框开关时,不会覆盖线上标题颜色、背景和其它边框字段。
|
|
132
145
|
|
|
@@ -25,8 +25,8 @@ checkout 读到的是"当前账号视角"的卡片定义,publish 会把它整
|
|
|
25
25
|
- **通用操作**:已有卡片可继续串接常用 `createCard` 后续操作,包括标题/描述(`setName`/`setDescription`)、`setRawSettings`、图例/标签/坐标轴/表格/拆分等视觉设置。
|
|
26
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
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
|
|
29
|
-
- **已有 selector
|
|
28
|
+
- **已有 selector 配置**:仅能力矩阵中标记可编辑的类型可用 `.setSelectorSetting()` 修改配置;禁止原地改变 selector 类型或重新绑定字段。已有 `PARAMETER` selector 可用 `.bindParameter()` 原地更新参数绑定;已有 `TEXT_MATCH` selector 可更新文本操作符、筛选级别、默认文本、`canClear` 和列名显示;树状筛选器、层级树状筛选器和组合条件筛选器分别使用 `.setTreeSetting()`、`.setLayerTreeSetting()` 和 `.setCombinationSetting()` 修改专属配置。自定义等未提供专用 DSL 的类型只能保留已有专属配置。完整能力边界、配置结构和适用规则见 `selector-reference.md`。
|
|
29
|
+
- **已有 selector 联动**:`cdType=SELECTOR` 的筛选器可用 `.addLink(cardIdOrIndex, targetFieldName?)` / `.removeLink(cardIdOrIndex)` / `.clearLinks()` 叠加修改现有 `settings.asFilter`。这些方法不支持 `TREE_SELECTOR`、`CUSTOM_SELECTOR` 等其他 selector 类型;不要把有顺序的联动增删混进 `.setSelectorSetting()`,也不要反向改 JSON。
|
|
30
30
|
- **Page 快捷筛选区**:按有序操作执行——`setFilterLayout` 整体设置,`clearFilterLayout` 清空,`addFilterLayoutItem` 追加去重,`insert/remove/moveFilterSelector` 局部调整;筛选栏布局、名称/控件/按钮字体、控件风格、按钮色、背景色和背景图用 `setFilterPanelLayout()`。省略字段保留 base,显式 `null` 删除对应覆盖并恢复产品/主题默认。
|
|
31
31
|
- **筛选器在筛选栏和画布间移动**:优先用动作级 API:`moveFilterSelectorToCanvas(selectorId, x, y, w, h)` / `moveCanvasSelectorToFilter(selectorId, index?)`;筛选器组用 `moveSelectorGroupToCanvas(group, x, y, w, h)` / `moveCanvasSelectorGroupToFilter(group, index?)`。
|
|
32
32
|
- **新增卡片**必须使用 `createCard()` / `createSelector()` 等工厂函数(新建资源 ID 用 `guanvis genid` 生成)。
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
## 筛选器参考
|
|
2
|
+
|
|
3
|
+
本文是 GuanVis 页面筛选器的语义事实源,覆盖筛选器类型、创建与编辑、默认值、展示配置、联动、级联和页面放置。通用 Builder 方法索引仍见 `builder-reference.md`;checkout 工程的整体编辑与覆盖发布红线见 `checkout-editing.md`。
|
|
4
|
+
|
|
5
|
+
这里的“页面筛选器”指作为独立资源进入页面筛选栏或画布的 selector;新建资源使用 `createSelector()` / `registerSelector()`,已有资源由 checkout 生成 `attachCard()` 脚本,具体可编辑范围见下文能力矩阵。它不是普通 Card 的 filters zone;卡片级筛选条件仍见 `api-reference.md` 的“卡片级筛选器 (Filters Zone)”。
|
|
6
|
+
|
|
7
|
+
### 能力边界
|
|
8
|
+
|
|
9
|
+
前端存在某类筛选器,不代表 GuanVis 已提供对应的新建或语义化编辑 DSL;按下表选择当前支持的操作。
|
|
10
|
+
|
|
11
|
+
| 类型 | BI 标识 | GuanVis 当前能力 | 说明 |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| 离散值 | `DS_ELEMENTS` | 支持新建和 `attachCard()` 配置编辑 | 单选、多选、默认值和多种展示样式 |
|
|
14
|
+
| 连续范围 | `DS_INTERVAL` | 支持新建和 `attachCard()` 配置编辑 | 默认使用 `BT` 区间条件 |
|
|
15
|
+
| 日期 | `CALENDAR` | 支持新建和 `attachCard()` 配置编辑 | 支持日期粒度和固定日期区间 |
|
|
16
|
+
| 快捷日期区间 | `TIME_MACRO` | 支持新建和 `attachCard()` 配置编辑 | 不绑定字段或数据集 |
|
|
17
|
+
| 全局参数 | `PARAMETER` | 支持新建;已有同类型 selector 可更新参数绑定和通用配置 | 使用 `bindParameter(param(dpId), options)`,不走卡片联动 |
|
|
18
|
+
| 条件筛选器 | `TEXT_MATCH` | 支持新建和 `attachCard()` 配置编辑 | 绑定单个字段,支持 8 种文本匹配操作符 |
|
|
19
|
+
| 树状筛选器 | `TREE` | 支持新建和 `attachCard()` 专属配置编辑 | 固定层级,至少绑定同一数据集的两个有序字段;路径默认值使用二维数组 |
|
|
20
|
+
| 层级树状筛选器 | `LAYER_TREE` | 支持新建和 `attachCard()` 专属配置编辑 | 绑定单个带 `layerTreeId` 的字段;`cdType=TREE_SELECTOR` |
|
|
21
|
+
| 组合条件 | `COMBINATION` | 支持新建和 `attachCard()` 专属配置编辑 | 同一数据集绑定多个候选字段;默认条件可为空或只覆盖其中一部分 |
|
|
22
|
+
| 自定义筛选器 | `CUSTOM_SELECTOR` | checkout 后可保留已有配置,暂不支持通用专属内容创建/编辑 | 依赖目标环境插件和不透明 `customConfig` |
|
|
23
|
+
|
|
24
|
+
`TREE_SELECTOR`、`MERGE_SELECTOR` 和 `CUSTOM_SELECTOR` 等已有资源在 checkout/publish 时会保留原 `cdType` 和未修改配置。树状筛选器使用专属 `.setTreeSetting()` 编辑,层级树状筛选器使用 `.setLayerTreeSetting()` 编辑,组合条件筛选器使用 `.setCombinationSetting()` 编辑;其他类型不能调用普通 `setSelectorSetting()` 修改专属内容。需要修改暂未支持的专属内容时应报告暂不支持,禁止修改 `.guanvis/base/**` 或 `.guanvis/raw/**` JSON。
|
|
25
|
+
|
|
26
|
+
### 类型选择
|
|
27
|
+
|
|
28
|
+
- 离散文本或分类值(区域、类别、客户名等)使用 `DS_ELEMENTS`。
|
|
29
|
+
- 连续数值(利润率、金额区间等)使用 `DS_INTERVAL`,默认展示起止输入框。
|
|
30
|
+
- 精确日期或日期范围使用 `CALENDAR`,需要绑定日期字段。
|
|
31
|
+
- 本月、上月、近 7 天等预设区间使用 `TIME_MACRO`,不绑定字段或数据集。
|
|
32
|
+
- 控制计算字段或卡片参数表达式时使用 `PARAMETER`,先创建/同步全局参数,再按稳定 `dpId` 绑定。
|
|
33
|
+
- 单字段需要等于、不等于、包含、开头或结尾等匹配条件时使用 `TEXT_MATCH`;默认操作符为 `CONTAINS`。
|
|
34
|
+
- 固定字段层级(如区域 → 城市)使用树状筛选器,必须按父到子的顺序绑定至少两个字段。
|
|
35
|
+
- 数据集字段已配置层级树时使用层级树状筛选器,绑定该单个字段;`schema.js` 中该字段必须带 `layerTreeId`,否则构建明确报错。
|
|
36
|
+
- 多个同一数据集字段允许用户自由组合条件时使用组合条件筛选器;用 `.bindCombinationFields(...)` 声明可选字段,用 `.setCombinationSetting(...)` 设置展示和初始条件。
|
|
37
|
+
- 用户要求自定义筛选器时,先对照上面的能力边界;当前没有对应创建/编辑 DSL 时明确报告暂不支持,不用其他筛选器类型模拟。
|
|
38
|
+
|
|
39
|
+
### 文件、注册与页面归属
|
|
40
|
+
|
|
41
|
+
筛选器脚本建议命名为 `selector_NN_xxx.js`。目录模式按 `schema.js` → `metrics.js` → `dynamic-parameters.js` → `theme-colors.js` → `card_*.js` → `selector_*.js` → `page.js` 执行,因此 selector 可以按联动目标序列引用先注册的 Card。
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
var sel = createSelector("区域筛选")
|
|
45
|
+
.setId("s184352b7a76776db5f534df")
|
|
46
|
+
.bindField(f("区域"))
|
|
47
|
+
.linkToAll()
|
|
48
|
+
.build();
|
|
49
|
+
|
|
50
|
+
registerSelector(sel);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
每个 selector 必须设置由 `guanvis genid` 生成的 ID,并调用 `registerSelector(selector.build())` 或先 `.build()` 后注册。包含 selector 的资源包必须同时包含引用它的 Page:
|
|
54
|
+
|
|
55
|
+
- 未被页面布局引用的 selector 默认进入页面筛选栏;也可用 `page.addFilterSelector(selectorId)` 显式控制顺序。
|
|
56
|
+
- 作为画布内容或隶属于 Tab、CardGroup、SelGroup 的 selector 必须跟随对应布局放置,不再进入筛选栏。
|
|
57
|
+
- 画布中的局部 selector 用 `.linkTo(...)` 明确联动所属区域,不默认 `.linkToAll()`。
|
|
58
|
+
- selector 进入画布、布局组件或 SelGroup 时使用字符串 ID;`registerSelector()` 不参与普通 card 数字 index 计数。
|
|
59
|
+
|
|
60
|
+
### SelectorBuilder 方法
|
|
61
|
+
|
|
62
|
+
| 方法 | 说明 |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `createSelector(name)` | 创建筛选器 |
|
|
65
|
+
| `.setId(cardId)` | 设置固定资源 ID;新建 ID 用 `guanvis genid` 生成 |
|
|
66
|
+
| `.setDescription(desc)` | 设置筛选器描述 |
|
|
67
|
+
| `.setSelectorSetting(config)` | 统一配置入口,支持新建和能力矩阵中标记可编辑的 `attachCard()` selector |
|
|
68
|
+
| `.setTreeSetting(config)` | 树状筛选器专属配置;新建和已有树状筛选器均可用 |
|
|
69
|
+
| `.setLayerTreeSetting(config)` | 层级树状筛选器专属配置;新建和已有层级树状筛选器均可用 |
|
|
70
|
+
| `.setCombinationSetting(config)` | 组合条件筛选器专属配置;可修改清空、展示与默认条件 |
|
|
71
|
+
| `.setSelectorType(type)` | 设置类型;可新建 `DS_ELEMENTS`、`TEXT_MATCH`、`DS_INTERVAL`、`CALENDAR`、`TIME_MACRO`、`TREE`、`LAYER_TREE`、`COMBINATION`,`PARAMETER` 由 `bindParameter()` 自动设置 |
|
|
72
|
+
| `.setFilterType(type)` | 设置筛选条件;`DS_ELEMENTS` 默认 `IN`,`DS_INTERVAL`/`CALENDAR` 默认 `BT` |
|
|
73
|
+
| `.setFilterLevel(level)` | 设置筛选级别;默认 `FilterLevel.DETAIL`,`PARAMETER` 不支持 |
|
|
74
|
+
| `.bindDataset(dsId)` | 显式绑定数据集;单数据集工程通常由字段自动确定 |
|
|
75
|
+
| `.bindField(field)` | 绑定筛选字段;`DS_ELEMENTS`、`DS_INTERVAL`、`CALENDAR` 必填 |
|
|
76
|
+
| `.bindTreeFields(...fields)` | 按父到子顺序绑定树状筛选器的至少两个字段 |
|
|
77
|
+
| `.bindLayerTreeField(field)` | 绑定层级树状筛选器的单个字段;字段必须带 `layerTreeId` |
|
|
78
|
+
| `.bindCombinationFields(...fields)` | 绑定组合条件筛选器的候选字段;必须属于同一数据集且不能是聚合或窗口计算 |
|
|
79
|
+
| `.bindParameter(paramRef, options?)` | 绑定全局参数;已有 `PARAMETER` selector 可原地更新绑定、继承方式和本地默认值 |
|
|
80
|
+
| `.setGranularity(granularity)` | 设置 `CALENDAR` 的唯一日期粒度 |
|
|
81
|
+
| `.setGranularityOptions(options, defaultGranularity?)` | 设置 `CALENDAR` 可选粒度和默认粒度 |
|
|
82
|
+
| `.setTimeMacroOptions(options, defaultMacroName?)` | 兼容入口;设置快捷日期选项并自动切为 `TIME_MACRO` |
|
|
83
|
+
| `.setMultiSelect(bool)` | 设置 `DS_ELEMENTS` 是否多选 |
|
|
84
|
+
| `.setDefaultType(type)` | 设置 `FIRST_PICK`、`FIXED_VALUE` 或 `ALL` |
|
|
85
|
+
| `.setDefaultAll()` | 设置默认全部,即不筛选 |
|
|
86
|
+
| `.setDefaultValue(values, displayValues?)` | 设置固定默认值,并切换为 `FIXED_VALUE` |
|
|
87
|
+
| `.setDefaultDateRange(start, end, displayValues?)` | 设置 `CALENDAR` 固定日期区间 |
|
|
88
|
+
| `.setFirstPickLink(bool)` | `FIRST_PICK` 模式下是否联动刷新 |
|
|
89
|
+
| `.setDisplayType(type)` | 设置 `DS_ELEMENTS` 展示样式 |
|
|
90
|
+
| `.setShowSelectAll(bool)` | 设置 `DS_ELEMENTS` 是否显示全选 |
|
|
91
|
+
| `.setCanClear(bool)` | 设置是否允许清空 |
|
|
92
|
+
| `.linkTo(cardIndex, targetFieldNameOrMappings?)` | 联动指定图表;组合条件和带路径树状筛选器可传 `{源字段: 目标字段}` 完整映射 |
|
|
93
|
+
| `.linkToSelector(selectorId, targetFieldName?)` | 联动指定 selector,构建时校验目标类型和级联环 |
|
|
94
|
+
| `.linkToAll()` | 按同名字段联动所有可联动图表、MetricChart 和杜邦子卡片 |
|
|
95
|
+
| `.build()` | 构建并触发验证 |
|
|
96
|
+
|
|
97
|
+
推荐优先使用 `.setSelectorSetting()`。旧的 `.setSelectorType()`、`.setMultiSelect()`、`.setDefaultValue()` 等方法继续兼容。资源身份、字段/参数绑定和联动具有独立生命周期,仍分别使用 `.setId()`、`.bindField()` / `.bindParameter()` 和 `.linkTo*()`。
|
|
98
|
+
|
|
99
|
+
### 统一配置 `setSelectorSetting()`
|
|
100
|
+
|
|
101
|
+
所有字段都可选;`false`、`0` 和允许的空数组按显式值处理。新建 selector 未设置的字段采用 GuanVis 默认值;能力矩阵中标记可编辑的 `attachCard()` selector 只修改显式字段,未传字段保持线上原值。
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
{
|
|
105
|
+
type: SelectorType.DS_ELEMENTS,
|
|
106
|
+
filterType: FilterType.IN,
|
|
107
|
+
filterLevel: FilterLevel.DETAIL,
|
|
108
|
+
selection: {
|
|
109
|
+
multiple: true,
|
|
110
|
+
showSelectAll: true,
|
|
111
|
+
canClear: false,
|
|
112
|
+
firstPickLink: false
|
|
113
|
+
},
|
|
114
|
+
display: {
|
|
115
|
+
type: SelectorDisplay.SEARCH_BOX,
|
|
116
|
+
showColumnName: true
|
|
117
|
+
},
|
|
118
|
+
defaultValue: {
|
|
119
|
+
type: SelectorDefaultType.FIXED_VALUE,
|
|
120
|
+
values: ["华东"],
|
|
121
|
+
displayValues: ["华东地区"]
|
|
122
|
+
},
|
|
123
|
+
calendar: {
|
|
124
|
+
granularities: [Granularity.MONTH, Granularity.QUARTER],
|
|
125
|
+
defaultGranularity: Granularity.MONTH
|
|
126
|
+
},
|
|
127
|
+
timeMacro: {
|
|
128
|
+
options: [{ name: "最近7天", expr: ["LAST_7_DAY"] }],
|
|
129
|
+
defaultName: "最近7天"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
适用规则:
|
|
135
|
+
|
|
136
|
+
- `selection.multiple`、`selection.showSelectAll` 和 `display.type` 仅用于 `DS_ELEMENTS`。
|
|
137
|
+
- `TEXT_MATCH` 的 `filterType` 仅支持 `EQ`、`NE`、`CONTAINS`、`NOT_CONTAINS`、`STARTSWITH`、`NOT_STARTSWITH`、`ENDSWITH` 和 `NOT_ENDSWITH`;其默认值仅使用字符串 `values`,不使用 `type` 或 `displayValues`。
|
|
138
|
+
- `calendar` 仅用于 `CALENDAR`;`timeMacro` 仅用于 `TIME_MACRO`。
|
|
139
|
+
- `defaultValue.values` 会切换为 `FIXED_VALUE`;`displayValues` 必须与 `values` 同次传入。
|
|
140
|
+
- `TIME_MACRO` 和 `PARAMETER` 不接受通用 `filterType`、`defaultValue` 或 `firstPickLink` 配置。
|
|
141
|
+
- 已有 selector 传入的 `type` 是类型断言,不能借此改变 selector 类型,也不会重新绑定字段。
|
|
142
|
+
- `display.showColumnName` 对应 BI 内容中的 `display.showColName`;`selection.canClear` 对应 `props.canClear`。
|
|
143
|
+
|
|
144
|
+
### 已支持类型示例
|
|
145
|
+
|
|
146
|
+
#### 离散值 `DS_ELEMENTS`
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
var sel = createSelector("区域筛选")
|
|
150
|
+
.setId("s184352b7a76776db5f534df")
|
|
151
|
+
.bindField(f("区域"))
|
|
152
|
+
.setSelectorSetting({
|
|
153
|
+
selection: { multiple: true, showSelectAll: true, canClear: false },
|
|
154
|
+
display: { type: SelectorDisplay.SEARCH_BOX, showColumnName: true },
|
|
155
|
+
defaultValue: {
|
|
156
|
+
type: SelectorDefaultType.FIXED_VALUE,
|
|
157
|
+
values: ["华东"]
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
.linkToAll()
|
|
161
|
+
.build();
|
|
162
|
+
|
|
163
|
+
registerSelector(sel);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`SelectorDisplay` 可用值:`SEARCH_LIST`、`SEARCH_BOX`、`CHECKBOX`、`RADIO`、`BUTTON_GROUP`。不设置时根据 `multiple` 自动选择。
|
|
167
|
+
|
|
168
|
+
#### 条件筛选器 `TEXT_MATCH`
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
var sel = createSelector("客户关键字")
|
|
172
|
+
.setId("a184352b7a76776db5f534df")
|
|
173
|
+
.bindField(f("客户名称"))
|
|
174
|
+
.setSelectorSetting({
|
|
175
|
+
type: SelectorType.TEXT_MATCH,
|
|
176
|
+
filterType: FilterType.CONTAINS,
|
|
177
|
+
filterLevel: FilterLevel.DETAIL,
|
|
178
|
+
selection: { canClear: false },
|
|
179
|
+
display: { showColumnName: true },
|
|
180
|
+
defaultValue: { values: ["观远"] }
|
|
181
|
+
})
|
|
182
|
+
.linkToAll()
|
|
183
|
+
.build();
|
|
184
|
+
|
|
185
|
+
registerSelector(sel);
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`TEXT_MATCH` 默认操作符为 `CONTAINS`,默认值是字符串数组;传空数组表示页面打开时没有预填文本。它不支持多选、全选、展示样式、首项默认值或默认显示值。
|
|
189
|
+
|
|
190
|
+
#### 组合条件 `COMBINATION`
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
var condition = createSelector("经营条件")
|
|
194
|
+
.setId("d184352b7a76776db5f534df")
|
|
195
|
+
.setSelectorType(SelectorType.COMBINATION)
|
|
196
|
+
.bindCombinationFields(f("区域"), f("城市"), f("销售额"))
|
|
197
|
+
.setCombinationSetting({
|
|
198
|
+
selection: { canClear: false },
|
|
199
|
+
display: {
|
|
200
|
+
type: CombinationSelectorDisplay.STANDARD,
|
|
201
|
+
showColumnName: true
|
|
202
|
+
},
|
|
203
|
+
defaultValue: {
|
|
204
|
+
conditions: [
|
|
205
|
+
Combination.and(
|
|
206
|
+
Combination.condition(f("区域"), FilterType.IN, ["华东"]),
|
|
207
|
+
Combination.or(
|
|
208
|
+
Combination.condition(f("城市"), FilterType.EQ, ["上海"]),
|
|
209
|
+
Combination.condition(f("销售额"), FilterType.GE, [100000])
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
.linkTo(0, {
|
|
216
|
+
"区域": "销售区域",
|
|
217
|
+
"城市": "销售城市",
|
|
218
|
+
"销售额": "含税销售额"
|
|
219
|
+
})
|
|
220
|
+
.build();
|
|
221
|
+
registerSelector(condition);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`bindCombinationFields(...)` 是页面上允许用户选择的候选字段集合,默认 `conditions` 可以是 `[]`,也可以只使用其中一部分;不会强制每个候选字段都出现在默认条件中。`Combination.condition(field, filterType, filterValue, { not: true }?)` 创建叶子条件,其中 `not` 省略时为 `false`,传入时必须为布尔值;`Combination.and(...)` / `Combination.or(...)` 创建嵌套分组,最多 5 层、共 200 个叶子条件。候选字段必须来自同一数据集,且不能是动态参数、聚合计算或窗口计算。
|
|
225
|
+
|
|
226
|
+
筛选器联动则必须为每个候选字段提供可用映射,否则用户在运行时选到未映射字段会使目标卡片无法正确过滤。`.linkTo(index, mappings)` 中 `mappings` 的键可使用源字段名或 `fdId`,值可使用目标字段名或 `fdId`;显式映射必须覆盖全部候选字段。`.linkToAll()` 只连接能按同名字段完整映射的图表,自动跳过缺少任一候选字段的目标。组合条件筛选器不支持 `linkToSelector()` 级联。
|
|
227
|
+
|
|
228
|
+
#### 树状筛选器
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
var tree = createSelector("区域城市")
|
|
232
|
+
.setId("b184352b7a76776db5f534df")
|
|
233
|
+
.setSelectorType(SelectorType.TREE)
|
|
234
|
+
.bindTreeFields(f("区域"), f("城市"))
|
|
235
|
+
.setTreeSetting({
|
|
236
|
+
selection: { multiple: true, canClear: false },
|
|
237
|
+
display: { type: TreeSelectorDisplay.FLAT, showExclude: true, showConfirm: true },
|
|
238
|
+
defaultValue: {
|
|
239
|
+
paths: [["华东", "上海"]],
|
|
240
|
+
displayPaths: [["东区", "上海市"]]
|
|
241
|
+
},
|
|
242
|
+
path: { withPath: true, autoMergePath: true }
|
|
243
|
+
})
|
|
244
|
+
.build();
|
|
245
|
+
|
|
246
|
+
registerSelector(tree);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
树状筛选器会生成独立的 `cdType=TREE_SELECTOR`,不是普通 `SELECTOR`。`defaultValue.paths` / `displayPaths` 都是路径二维数组;默认值模式只支持 `FIXED_VALUE` 与 `FIRST_PICK`。`TreeSelectorDisplay` 可用 `SEARCH_BOX` 和 `FLAT`;`showConfirm`、`showExclude` 仅多选可用(平铺时可显式切换确认按钮)。路径配置为 `path.withPath`、`anyPathEnabled`、`excludeNullValue`、`autoMergePath`;其中任意层选择只适用于带路径单选,末级空值缩略只适用于不带路径,多选路径合并只适用于带路径多选。`filterLevel` 仅可用于不带路径模式。
|
|
250
|
+
|
|
251
|
+
不带路径的树状筛选器可以使用 `.linkTo()` / `.linkToAll()` 按末级字段联动图表。带路径树状筛选器的选择值包含完整路径,需用 `.linkTo(cardIndex, { 源层级字段: 目标字段, ... })` 为每一级提供映射;映射的键和值均可写字段名或 `fdId`,且必须覆盖全部绑定层级。`.linkToAll()` 只会联动同时拥有全部同名层级字段的图表;不会降级成仅按末级字段联动。带路径树状筛选器暂不支持 `.linkToSelector()`。
|
|
252
|
+
|
|
253
|
+
#### 层级树状筛选器
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
var layerTree = createSelector("组织层级")
|
|
257
|
+
.setId("c184352b7a76776db5f534df")
|
|
258
|
+
.setSelectorType(SelectorType.LAYER_TREE)
|
|
259
|
+
.bindLayerTreeField(f("组织"))
|
|
260
|
+
.setLayerTreeSetting({
|
|
261
|
+
selection: { multiple: true, canClear: false },
|
|
262
|
+
defaultValue: {
|
|
263
|
+
paths: [["100", "200"]],
|
|
264
|
+
displayPaths: [["事业群", "运营部"]]
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
.linkToAll()
|
|
268
|
+
.build();
|
|
269
|
+
registerSelector(layerTree);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
层级树状筛选器同样生成 `cdType=TREE_SELECTOR`,但与树状筛选器不同:`source` 只有 `field`,没有 `fieldSeq`;绑定字段的 `layerTreeId` 由 `guanvis init` 写入可选字段元数据。数据集没有这个字段,或所绑字段没有 `layerTreeId` 时,构建会报错,不能用普通树状筛选器替代。`defaultValue.paths` 是节点 ID 的二维路径数组;GuanVis 自动补齐前端需要的层级标记,`displayPaths` 可选,未传时由节点 ID 生成显示值。它只支持多选、清空与默认路径配置,不支持树状筛选器的展示、路径模式或 `filterLevel` 配置。可按该字段使用 `.linkTo()` / `.linkToAll()` 联动图表。
|
|
273
|
+
|
|
274
|
+
#### 连续范围 `DS_INTERVAL`
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
var sel = createSelector("利润率筛选")
|
|
278
|
+
.setId("h61d8bf256952ef3fcf961c5")
|
|
279
|
+
.setSelectorType(SelectorType.DS_INTERVAL)
|
|
280
|
+
.bindField(f("利润率"))
|
|
281
|
+
.linkToAll()
|
|
282
|
+
.build();
|
|
283
|
+
|
|
284
|
+
registerSelector(sel);
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`DS_INTERVAL` 默认 `filterType="BT"`,展示起止输入框。需要单值或比较条件时可显式设置支持的 `FilterType`,不要用 `DS_ELEMENTS` 枚举连续数值。
|
|
288
|
+
|
|
289
|
+
#### 日期 `CALENDAR`
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
var sel = createSelector("日期筛选")
|
|
293
|
+
.setId("abc123def456abc123def456")
|
|
294
|
+
.setSelectorType(SelectorType.CALENDAR)
|
|
295
|
+
.bindField(f("订单日期"))
|
|
296
|
+
.setDefaultDateRange("2026-01-01", "2026-01-31")
|
|
297
|
+
.linkToAll()
|
|
298
|
+
.build();
|
|
299
|
+
|
|
300
|
+
registerSelector(sel);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
固定默认值必须有两个日期端点,支持 `2026-01-15`、`2026-01`、`2026-Q1`、`2026-W03`、`2026` 等格式。同一默认值数组必须使用相同粒度;未显式配置粒度时会从默认值或联动目标字段推断。
|
|
304
|
+
|
|
305
|
+
#### 快捷日期区间 `TIME_MACRO`
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
var sel = createSelector("快捷日期")
|
|
309
|
+
.setId("gf7a7ed51ec7c9477fcd1d81")
|
|
310
|
+
.setSelectorSetting({
|
|
311
|
+
type: SelectorType.TIME_MACRO,
|
|
312
|
+
timeMacro: {
|
|
313
|
+
options: [
|
|
314
|
+
{ name: "今天", expr: ["TODAY"] },
|
|
315
|
+
{ name: "昨天", expr: ["YESTERDAY"] },
|
|
316
|
+
{ name: "最近7天", expr: ["LAST_7_DAY"] },
|
|
317
|
+
{ name: "最近30天", expr: ["LAST_30_DAY"] },
|
|
318
|
+
{ name: "本月", expr: ["MONTH_TO_DAY"] },
|
|
319
|
+
{ name: "上月", expr: ["LAST_MONTH"] },
|
|
320
|
+
{ name: "本年", expr: ["YEAR_TO_DAY"] }
|
|
321
|
+
],
|
|
322
|
+
defaultName: "最近7天"
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
.linkToAll()
|
|
326
|
+
.build();
|
|
327
|
+
|
|
328
|
+
registerSelector(sel);
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
`TIME_MACRO` 不绑定字段或数据集,通过目标卡片中的日期字段自动匹配。省略 `defaultName` 时默认选中第一项;显式传入 `defaultName: null` 时页面打开不选择默认项。内置宏还包括 `LAST_14_DAY`、`LAST_90_DAY`、`LAST_1_YEAR`、`LAST_WEEK`、`WEEK_TO_DAY`、`YEAR_TO_DAY`、`DAY_BEFORE_YESTERDAY`、`WEEK_TO_YESTERDAY`、`MONTH_TO_YESTERDAY`、`YEAR_TO_YESTERDAY`、`QUARTER_TO_DAY`、`QUARTER_TO_YESTERDAY`、`YEAR_TO_LAST_MONTH` 和 `YEAR_TO_LAST_QUARTER`。
|
|
332
|
+
|
|
333
|
+
#### 全局参数 `PARAMETER`
|
|
334
|
+
|
|
335
|
+
参数先通过 `guanvis parameter` 创建或更新,并生成/刷新 `dynamic-parameters.js`;脚本按稳定 `dpId` 引用,不按名称猜测。
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
var sel = createSelector("区域参数")
|
|
339
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
340
|
+
.bindParameter(param("aaaaaaaaaaaaaaaaaaaaaaaa"), {
|
|
341
|
+
inheritParent: true
|
|
342
|
+
})
|
|
343
|
+
.setCanClear(false)
|
|
344
|
+
.build();
|
|
345
|
+
|
|
346
|
+
registerSelector(sel);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
参数筛选器不绑定数据集或字段,也不调用 `linkTo()` / `linkToAll()`;参数值通过 `dpId` 影响引用该全局参数的计算与卡片。需要覆盖参数本地默认值时显式关闭继承:
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
.bindParameter(param("aaaaaaaaaaaaaaaaaaaaaaaa"), {
|
|
353
|
+
inheritParent: false,
|
|
354
|
+
defaultValue: ["华东", "华南"]
|
|
355
|
+
})
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 联动与级联
|
|
359
|
+
|
|
360
|
+
筛选器通过 `settings.asFilter` 联动图表:
|
|
361
|
+
|
|
362
|
+
- `.linkTo(index, targetFieldName?)` 中 index 是过滤后的可联动目标序列:普通图表和 MetricChart 按注册/布局顺序进入,文本、图片和自定义图表等不可联动资源不占序号,杜邦子卡片追加在末尾。
|
|
363
|
+
- `.linkToAll()` 按同名字段联动所有普通图表、MetricChart 和杜邦子卡片,不自动包含其他 selector。
|
|
364
|
+
- 同一 selector 同时使用显式 `.linkTo(index, "目标字段")` 和 `.linkToAll()` 时,显式目标字段映射优先。
|
|
365
|
+
- checkout 后的普通 `cdType=SELECTOR` 筛选器使用 `attachCard().addLink()`、`.removeLink()`、`.clearLinks()` 增量修改联动,不把有顺序的联动增删混进 `.setSelectorSetting()`;这些联动方法不支持 `TREE_SELECTOR`、`CUSTOM_SELECTOR` 等其他 selector 类型。
|
|
366
|
+
|
|
367
|
+
筛选器级联使用 `.linkToSelector(selectorId, targetFieldName?)`:
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
var city = createSelector("市")
|
|
371
|
+
.setId("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
372
|
+
.bindField(f("市"))
|
|
373
|
+
.build();
|
|
374
|
+
registerSelector(city);
|
|
375
|
+
|
|
376
|
+
var province = createSelector("省")
|
|
377
|
+
.setId("aaaaaaaaaaaaaaaaaaaaaaaa")
|
|
378
|
+
.bindField(f("省"))
|
|
379
|
+
.linkToSelector("bbbbbbbbbbbbbbbbbbbbbbbb")
|
|
380
|
+
.linkToAll()
|
|
381
|
+
.build();
|
|
382
|
+
registerSelector(province);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
当前级联目标只支持离散值筛选器和树状筛选器;构建时会校验目标存在、目标字段映射和 selector 级联成环。目标为 `ALL` 或空默认值时会自动启用 `FIRST_PICK + firstPickLink`,目标已有固定默认值时保留。上游字段与目标数据集字段不同名时,给 `.linkToSelector()` 传第二个参数。
|
|
386
|
+
|
|
387
|
+
### Checkout 与 `attachCard()` 编辑
|
|
388
|
+
|
|
389
|
+
能力矩阵中标记可编辑的已有 selector 使用 checkout 生成的 `attachCard(cardId, jsonPath)` 原地编辑:
|
|
390
|
+
|
|
391
|
+
```javascript
|
|
392
|
+
registerCard(
|
|
393
|
+
attachCard("bbbbbbbbbbbbbbbbbbbbbbbb", "selector.json")
|
|
394
|
+
.setSelectorSetting({
|
|
395
|
+
selection: { canClear: false },
|
|
396
|
+
display: { showColumnName: true }
|
|
397
|
+
})
|
|
398
|
+
.addLink("cccccccccccccccccccccccc")
|
|
399
|
+
.build()
|
|
400
|
+
);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
`attachCard().build()` 返回的是 attached-card 结果,因此使用 `registerCard()` 注册;只有 `createSelector().build()` 的结果使用 `registerSelector()`。
|
|
404
|
+
|
|
405
|
+
编辑规则:
|
|
406
|
+
|
|
407
|
+
- `.setSelectorSetting()` 只修改显式配置,保留未修改内容及未知扩展字段。
|
|
408
|
+
- `selection.canClear` 和 `display.showColumnName` 是可编辑的 selector 配置;未知字段的保留是 checkout 往返兼容原则,不表示 GuanVis 声明支持其产品语义。
|
|
409
|
+
- 已有 selector 的 `type` 只能用于断言,禁止原地改变类型或借配置入口重新绑定字段。
|
|
410
|
+
- 已有 `PARAMETER` selector 是绑定规则的例外:可用 `.bindParameter()` 原地更新参数、`inheritParent` 和本地默认值;不能把其他类型转换成参数 selector。
|
|
411
|
+
- `setSelectorSetting()` 仅用于新建 selector 和能力矩阵中标记可编辑的已有类型。`TEXT_MATCH` 可原地修改文本操作符、筛选级别、默认文本、`canClear` 和列名显示;树状筛选器使用 `.setTreeSetting()` 原地修改多选、清空、树展示、默认路径和路径选项;层级树状筛选器使用 `.setLayerTreeSetting()` 原地修改多选、清空与默认路径;组合条件筛选器使用 `.setCombinationSetting()` 原地修改 `canClear`、展示和默认条件,但保留 `source.fieldSeq`、`dsInfo` 及未知扩展字段,不重新绑定候选字段。自定义筛选器等其他类型仍只能保留原配置。
|
|
412
|
+
- 任何已有 selector 都必须保留原 cdId 原地发布,禁止删除后重建同名资源。
|
|
413
|
+
|
|
414
|
+
### 页面放置与筛选器组
|
|
415
|
+
|
|
416
|
+
selector 可以作为字符串 ID 放入页面画布、Tab、CardGroup 或 SelectorGroup。SelectorGroup 本身是 Page 布局组件,不是 selector 资源;其创建、样式、画布/筛选栏归属、移动操作和完整示例统一见 `builder-reference.md` 的 `PageBuilder` 与 `SelectorGroupBuilder` 章节。
|
|
417
|
+
|
|
418
|
+
### 验证与常见错误
|
|
419
|
+
|
|
420
|
+
| 问题 | 处理 |
|
|
421
|
+
|---|---|
|
|
422
|
+
| selector 未设置 ID | 用 `guanvis genid` 生成并调用 `.setId()` |
|
|
423
|
+
| selector 未联动任何图表 | 全局筛选器调用 `.linkToAll()`;局部筛选器调用 `.linkTo(index)` |
|
|
424
|
+
| 连续数值生成了大量离散选项 | 改用 `DS_INTERVAL` |
|
|
425
|
+
| `TIME_MACRO` 绑定了字段或数据集 | 删除字段/数据集绑定,只保留时间宏配置和联动 |
|
|
426
|
+
| `PARAMETER` 调用了图表联动 | 删除 `linkTo*`,确认目标卡片通过同一 `dpId` 使用参数 |
|
|
427
|
+
| `display.type` 用在非 `DS_ELEMENTS` | 删除该配置;其他类型使用自身展示规则 |
|
|
428
|
+
| checkout 编辑试图改变 selector 类型或字段 | 保留原类型和绑定;确需改变时创建新资源并由用户明确处理替换关系 |
|
|
429
|
+
| 条件 selector 使用 `IN`、`BT` 或默认显示值 | 改用 8 种文本匹配操作符;默认值仅传字符串 `values` |
|
|
430
|
+
| 树状筛选器调用普通配置 API | 树状筛选器改用 `.setTreeSetting()`;层级树状筛选器改用 `.setLayerTreeSetting()`;组合条件筛选器改用 `.setCombinationSetting()`;自定义筛选器仍只能保留原配置 |
|
|
431
|
+
| selector 没有进入 Page | 在筛选栏、画布或 SelGroup 中引用,并与 Page 同包发布 |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|