@qingflow-tech/qingflow-cli 1.1.61-beta.4 → 1.1.61-beta.6

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.
Files changed (61) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/pyproject.toml +2 -1
  4. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md +1 -1
  5. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_PORTAL_WORKFLOW.md +6 -258
  6. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +13 -0
  7. package/skills/qingflow-cli/reference/builder/70-portal.md +38 -17
  8. package/skills/qingflow-cli/reference/examples/portal/portal_apply_v1alpha1.example.json +100 -0
  9. package/skills/qingflow-cli/reference/examples/portal/portal_sections_all_types.example.json +6 -7
  10. package/src/qingflow_mcp/app_form_validator.py +20 -3
  11. package/src/qingflow_mcp/builder_facade/app_form.py +137 -17
  12. package/src/qingflow_mcp/builder_facade/models.py +177 -15
  13. package/src/qingflow_mcp/builder_facade/portals_schema.py +397 -0
  14. package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +14 -1
  15. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +49 -9
  16. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +27 -0
  17. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_content_classification.json +146 -0
  18. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_content_extraction.json +146 -0
  19. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_content_generation.json +146 -0
  20. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_document_parsing.json +146 -0
  21. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_image_generation.json +146 -0
  22. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_image_recognition.json +146 -0
  23. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_machine_translation.json +146 -0
  24. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ai_text_summary.json +146 -0
  25. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +2 -2
  26. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +27 -0
  27. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date_duration.json +146 -0
  28. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/embed_field.json +146 -0
  29. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/image_select.json +146 -0
  30. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/location.json +146 -0
  31. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +2 -2
  32. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/ocr.json +146 -0
  33. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +2 -2
  34. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +27 -0
  35. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +29 -2
  36. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +20 -7
  37. package/src/qingflow_mcp/builder_facade/schemas/portals/manifest.json +59 -0
  38. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/complete.json +1397 -0
  39. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/carousel.json +193 -0
  40. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/chart.json +643 -0
  41. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/favourite.json +203 -0
  42. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/filter.json +268 -0
  43. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/grid.json +265 -0
  44. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/link.json +131 -0
  45. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/task.json +199 -0
  46. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/text.json +123 -0
  47. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/components/view.json +196 -0
  48. package/src/qingflow_mcp/builder_facade/schemas/portals/v1alpha1/summary.json +800 -0
  49. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/complete.json +1 -1
  50. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/display.json +1 -1
  51. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/summary.json +1 -1
  52. package/src/qingflow_mcp/builder_facade/service.py +1251 -88
  53. package/src/qingflow_mcp/cli/commands/builder.py +132 -5
  54. package/src/qingflow_mcp/public_surface.py +2 -0
  55. package/src/qingflow_mcp/server_app_builder.py +34 -3
  56. package/src/qingflow_mcp/solution/compiler/icon_utils.py +73 -0
  57. package/src/qingflow_mcp/solution/executor.py +5 -2
  58. package/src/qingflow_mcp/tools/ai_builder_tools.py +118 -12
  59. package/src/qingflow_mcp/tools/portal_tools.py +4 -54
  60. package/src/qingflow_mcp/tools/portal_writer.py +59 -0
  61. package/src/qingflow_mcp/tools/solution_tools.py +2 -0
package/README.md CHANGED
@@ -7,7 +7,7 @@ Qingflow CLI 是轻流面向开发者和 AI Agent 的命令行工具。它把轻
7
7
  ## 安装
8
8
 
9
9
  ```bash
10
- npm install @qingflow-tech/qingflow-cli@1.1.61-beta.4
10
+ npm install @qingflow-tech/qingflow-cli@1.1.61-beta.6
11
11
  ```
12
12
 
13
13
  推荐从官网复制这一条一键安装 Qingflow CLI:
@@ -21,7 +21,7 @@ npx qingflow-cli@latest install
21
21
  ## 运行
22
22
 
23
23
  ```bash
24
- npx -y -p @qingflow-tech/qingflow-cli@1.1.61-beta.4 qingflow
24
+ npx -y -p @qingflow-tech/qingflow-cli@1.1.61-beta.6 qingflow
25
25
  ```
26
26
 
27
27
  全局安装后可以直接运行:
@@ -62,7 +62,7 @@ qingflow-skills install --agent codex --scope user
62
62
  如果你通过一次性 `npx -p` 执行 skills 安装,建议加 `--copy`,避免 symlink 指向 npm 临时执行缓存:
63
63
 
64
64
  ```bash
65
- npx -y -p @qingflow-tech/qingflow-cli@1.1.61-beta.4 qingflow-skills install --agent codex --scope user --copy
65
+ npx -y -p @qingflow-tech/qingflow-cli@1.1.61-beta.6 qingflow-skills install --agent codex --scope user --copy
66
66
  ```
67
67
 
68
68
  `qingflow-skills install` 默认使用 symlink,且遇到同名 skill 不会覆盖;只有显式传入 `--force` 才会替换。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qingflow-tech/qingflow-cli",
3
- "version": "1.1.61-beta.4",
3
+ "version": "1.1.61-beta.6",
4
4
  "description": "Human-friendly Qingflow command line interface for auth, record operations, import, tasks, and stable builder flows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qingflow-mcp"
7
- version = "1.1.61b4"
7
+ version = "1.1.61b6"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -70,6 +70,7 @@ qingflow_mcp = [
70
70
  "py.typed",
71
71
  "builder_facade/schemas/app_form/**/*.json",
72
72
  "builder_facade/schemas/views/**/*.json",
73
+ "builder_facade/schemas/portals/**/*.json",
73
74
  ]
74
75
 
75
76
  [tool.pytest.ini_options]
@@ -233,5 +233,5 @@ CLI 对外推荐使用 **`group_by` + `metric(s)`**;旧的 **`dimension_field_
233
233
 
234
234
  - [SKILL.md](../SKILL.md)
235
235
  - [QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md)
236
- - [QINGFLOW_CLI_BUILDER_PORTAL_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_PORTAL_WORKFLOW.md)(**`chart_ref`**)
236
+ - [builder/70-portal.md](./builder/70-portal.md)(门户声明式主链与 **`chart` / `chart_ref`** 用法)
237
237
  - [QINGFLOW_CLI_FIELD_DATA_TYPES.md](./QINGFLOW_CLI_FIELD_DATA_TYPES.md)(成员侧 **`kind`** 与搭建 **`type`** 对照理解业务)
@@ -1,263 +1,11 @@
1
- # Builder 门户创建与变更 SOP:`qingflow builder portal`
1
+ # Builder Portal Workflow
2
2
 
3
- 搭建侧稳定入口:**`qingflow builder portal`**:`list` / `get` / **`apply`** / **`delete`**(与根命令 **`qingflow portal`** 的「成员可读列表/详情」不同,见 **[QINGFLOW_CLI_EXPLORATION_REPORT.md](./QINGFLOW_CLI_EXPLORATION_REPORT.md) §4.6**)。
4
-
5
- 实现要点来自 CLI 打包内的 `builder_facade/models.py`(`PortalApplyRequest`、`PortalSectionPatch`)、`builder_facade/service.py`(`portal_apply` / `portal_delete`)、`cli/commands/builder.py`。已对 **`package_id=2030703`**、应用 **`ead8ims5i401`** **实跑**:**新建**(`--no-publish`)、**`--publish` 更新**(网关 **503** 恢复后已重试成功)、**五类区块可稳定落库**;**`filter`(`type:6`)经 CLI 直传未落库** 见 **§3.4 / §8**。另已对测试包 **`1414907`** 实跑 **`portal delete`**:临时门户 **`etcivtmv5402`** 删除后回读 **`readback_status=deleted`**。
6
-
7
- > **权限**:**更新**需 **`edit_portal`**;**新建**按后端 `DashCtrl.createDash` 链路只预检目标包 **`add_app`**,不额外要求包 **`edit_app`**。失败时参见主技能与 **ADMIN** 速查。
8
-
9
- > **契约**:`qingflow --json builder contract --tool-name portal_apply`;删除契约:`qingflow --json builder contract --tool-name portal_delete`
10
-
11
- ---
12
-
13
- ## 1. 读:`list` → `get`
3
+ 旧文已并入 [builder/70-portal.md](./builder/70-portal.md)。门户创建/更新走声明式主链(版本化 `--file` 声明 + 离线 validate + 唯一 apply 入口):
14
4
 
15
5
  ```bash
16
- qingflow --json builder portal list > tmp/builder_portal_list.json
17
-
18
- qingflow --json builder portal get --dash-key "<DASH_KEY>" > tmp/builder_portal_get.json
19
- qingflow --json builder portal get --dash-key "<DASH_KEY>" --no-being-draft
20
- ```
21
-
22
- - **`list`** 可能带 **`PORTAL_PERMISSION_READ_UNAVAILABLE`**,**`verified: false`** 仍可能有可用 **`items[]`**。
23
- - **`get`**:**`--dash-key`** 必填;默认 **`--being-draft`** 为草稿。
24
-
25
- ---
26
-
27
- ## 2. 写:`apply` 两种模式(互斥)
28
-
29
- **不可同时**出现 **`--dash-key`** 与 **`--package-id`**。
30
-
31
- | 模式 | 必备参数 | 含义 |
32
- |------|----------|------|
33
- | **新建** | **`--package-id`** + **`--dash-name`** | **`--sections-file` 须非空**。 |
34
- | **更新** | **`--dash-key`** | 不要带 **`package_id`**。 |
35
-
36
- | 参数 | 说明 |
37
- |------|------|
38
- | **`--publish` / `--no-publish`** | 默认 **`--publish`**。仅 **`--no-publish`** 时不会调用发布接口;契约说明 **`publish=false` 不宣称线上已变**。 |
39
- | **`--payload-file`** | 完整门户 JSON 对象;**标准字段写 `dash_name`**。新版 CLI 兼容 **`name -> dash_name`**、单页 **`pages[0].components -> sections`**,但 agent 默认不要依赖兼容别名。 |
40
- | **`--sections-file`** | JSON **数组**;**全量替换**。省略时仅改基础信息,且 **`hide_copyright` / `dash_global_config` / `config`** 不能单独提交(**`PORTAL_SECTIONS_REQUIRED`**)。 |
41
- | **`--layout-preset`** | 可选:**`auto` / `dashboard_2col` / `dashboard_3col`**。当区块未显式写 **`position`** 时由工具生成大屏布局。 |
42
- | **`--visibility-file`** | 与 **`--auth-file`** 不能同时用。 |
43
- | **`--icon`** / **`--color`** | 新建门户必须显式传合法的非 `template` 图标和颜色;候选用 `qingflow --json builder icon catalog`。编辑已有门户时省略则保留现状。 |
44
- | **`--hide-copyright`** / **`--dash-global-config-file`** / **`--config-file`** | 见契约;部分键 **依赖与 `sections` 同批提交**。 |
45
-
46
- **图标规则**:CLI 不按门户名自动猜图标;智能体需要自行选择业务贴合的 `icon + color`。读回结果里的 `icon_config` 可直接用于前端资源卡片展示。
47
-
48
- ---
49
-
50
- ## 3. `sections[]`:六类组件与回读 `type`
51
-
52
- ### 3.1 公共键
53
-
54
- - **`title`**(必填)、**`source_type`**(必填,小写)、可选 **`position`**(**`pc`/`mobile`** 各 **`x,y,cols,rows`**;省略则由**实现自动排布**)。
55
- - **`config`**、**`dash_style_config`**:按类型 Optional。默认只写 snake_case 规范键。
56
-
57
- ### 3.1.0 Payload 字段口径
58
-
59
- 推荐完整 payload 直接使用 CLI 标准键:
60
-
61
- ```json
62
- {
63
- "dash_name": "产品研发数据大屏",
64
- "package_id": 1414909,
65
- "layout_preset": "dashboard_2col",
66
- "pages": [
67
- {
68
- "title": "研发总览",
69
- "components": [
70
- {
71
- "title": "部门分布",
72
- "source_type": "chart",
73
- "chart_ref": {"app_key": "APP_KEY", "chart_id": "CHART_ID"}
74
- }
75
- ]
76
- }
77
- ]
78
- }
6
+ qingflow --json builder portal get --dash-key DASH_KEY --schema-kind complete > portal.json # 更新前先读
7
+ qingflow --json builder portal validate --file portal.json # 零后端离线校验
8
+ qingflow builder portal apply --file portal.json --schema-version v1alpha1 [--dash-key DASH_KEY] [--no-publish]
79
9
  ```
80
10
 
81
- `name` 只是兼容别名;如果遇到旧版 CLI 报 **`name Extra inputs are not permitted`**,不要反复重试,改成 **`dash_name`** 或升级 CLI。
82
-
83
- ### 3.1.1 布局硬规则:PC 24 栅格,mobile 6 栅格
84
-
85
- **门户 PC 端不是 12 栅格,而是 24 栅格。**如果把两列写成 **`x=0/6, cols=6`**,所有组件只会占左半屏,工具会返回 **`PORTAL_LAYOUT_HALF_WIDTH`**。
86
-
87
- 推荐:
88
-
89
- | 场景 | PC 写法 |
90
- |------|---------|
91
- | 不确定布局 | **省略 `position`**,或传 **`--layout-preset auto`** |
92
- | 两列可视化图表 | **`x=0/12, cols=12`**,图表 **`rows >= 7`** |
93
- | 三列可视化图表 | **`x=0/8/16, cols=8`**,图表 **`rows >= 7`** |
94
- | 四个指标卡 | **`x=0/6/12/18, cols=6, rows=5`** |
95
- | 具体数据视图 / 明细表 | 优先 **`cols=12`** 或 **`cols=24`**,视图 **`rows >= 11`** |
96
-
97
- mobile 写法固定按 **6 栅格**:通常 **`x=0, cols=6`**。如果只写了 PC position,CLI 会自动补 mobile position,并返回 **`PORTAL_MOBILE_POSITION_MISSING`** 提醒。
98
-
99
- 图表卡片过小时会返回 **`PORTAL_CHART_CARD_TOO_SMALL`**;指标卡按 **`pc.cols >= 6, pc.rows >= 5`** 校验,普通可视化图表按 **`pc.cols >= 8, pc.rows >= 7`** 校验。指标区图表建议写 `role: "metric"`;此时必须引用 `target` / `indicator` 图表,否则返回 **`PORTAL_METRIC_SECTION_CHART_TYPE_MISMATCH`**,应先用 `app_charts_apply` 创建缺失指标卡再组门户。标准工作台数量也会进入 `layout_diagnostics.standard_template_counts`:指标卡推荐 4-6 个、BI 图表 2-3 个、业务视图 1-2 个,超出或不足会返回 `PORTAL_STANDARD_*_COUNT_OUT_OF_RANGE`。
100
-
101
- ### 3.1.2 推荐门户模板:业务工作台
102
-
103
- 默认按 **业务入口 → 核心指标 → BI 可视化 → 业务视图** 搭建。门户首屏应直接呈现可用工作台,不要做营销页、说明页或大面积装饰区。
104
-
105
- | 区域 | 推荐组件 | PC 布局 | 要点 |
106
- |------|----------|---------|------|
107
- | 顶部业务入口 | **`grid`** + 可选 **待办 `task`** | `grid x=0,y=0,cols=12,rows=4`;待办 `x=12,y=0,cols=12,rows=4` | `grid` 放 2-6 个核心业务入口;待办用于当前用户任务概览。当前公开 `portal apply --sections-file` 暂未支持 `source_type=task`,不要伪造;见下方边界说明。 |
108
- | 核心指标 | **`chart`** 指标卡 + `role: "metric"` | 4 张:`x=0/6/12/18,y=4,cols=6,rows=5` | 指标卡推荐高度 **5**。24 栅格下单卡最小 `cols=6`,所以一行 4 张最稳;如果要 5 个指标,拆成两行。 |
109
- | BI 可视化 | **`chart`** 图表 | 3 张:`x=0/8/16,y=9,cols=8,rows=7`;或 2 张:`x=0/12,cols=12,rows=7` | 可视化图表推荐高度 **7**,一行 2-3 个,1-2 行。 |
110
- | 业务数据视图 | **`view`** | `x=0/12,y=16,cols=12,rows=11`;或单表 `cols=24,rows=11` | 数据视图推荐高度 **11**,一行 1-2 个,1-2 行。只挂业务视图,不要创建或引用默认的 **全部数据 / 我的数据** 当主门户视图。 |
111
-
112
- mobile 固定按 **6 栅格** 从上到下堆叠:通常所有组件 `x=0, cols=6`,`y` 按 PC 顺序递增。若顶部同时有 `grid + task`,mobile 建议先业务入口 `y=0,rows=4`,再待办 `y=4,rows=4`,核心指标从 `y=8` 开始;若当前公开 CLI 只能写 `grid`,核心指标可从 `y=4` 开始。
113
-
114
- **当前工具边界**:
115
-
116
- - 公开 `sections-file` 稳定支持:**`grid` / `chart` / `view` / `text` / `link`**;`filter` 仍按 **§3.4** 的 raw `filterConfig` 边界处理,不作为主路径。
117
- - **待办 `task` / 常用 `favorite`** 是前端/后端 raw 组件形状,不在当前公开 `source_type` 合约里。智能体不要在 `sections-file` 中写 `source_type: "task"`;只有工具后续显式支持 `task`,或维护者走 raw 门户写入链路时,才使用待办槽位。
118
- - 推荐门户的可直接 apply 示例见 **[portal_sections_standard_workbench.example.json](./portal_sections_standard_workbench.example.json)**。该示例使用当前公开 CLI 可稳定写入的组件,顶部先用一个业务入口 `grid` 占满 24 栅格;如果工具已支持待办组件,再把顶部拆成 `grid cols=12 + task cols=12`。
119
- - `grid` 必须写 **`config.items[]`**;只写 `gridTitle` / `beingShowTitle` 会生成空入口容器,工具会返回 **`PORTAL_GRID_ITEMS_EMPTY`**。
120
-
121
- **待办组件 raw 形状参考**(仅用于工具实现对齐,当前不要作为 `--sections-file` 输入):
122
-
123
- ```json
124
- {
125
- "type": 8,
126
- "position": {
127
- "pc": {"x": 12, "y": 0, "cols": 12, "rows": 4},
128
- "mobile": {"x": 0, "y": 4, "cols": 6, "rows": 4}
129
- },
130
- "taskConfig": {
131
- "beingShowTitle": true,
132
- "componentTaskTitle": "待办",
133
- "beingShowHint": true,
134
- "componentTaskHint": "及时处理待办,可以有效提升流程效率",
135
- "dashTaskConfigList": [
136
- {"type": 1, "title": "all.taskTodo", "beingCheck": true, "ordinal": 0},
137
- {"type": 2, "title": "all.taskTimeout", "beingCheck": true, "ordinal": 1},
138
- {"type": 3, "title": "all.taskUpcomingTimeout", "beingCheck": true, "ordinal": 2},
139
- {"type": 4, "title": "all.taskRemind", "beingCheck": true, "ordinal": 3}
140
- ]
141
- }
142
- }
143
- ```
144
-
145
- ### 3.2 `source_type` ↔ 回读 `components[].type`(搭建侧)
146
-
147
- | `source_type` | 回读 `type`(数字) | 搭建侧含义 |
148
- |---------------|---------------------|------------|
149
- | **`chart`** | **9** | QingBI 图表块 |
150
- | **`view`** | **10** | 应用视图块 |
151
- | **`grid`** | **2** | 九宫格 |
152
- | **`filter`** | **6** | 筛选条 |
153
- | **`text`** | **5** | 富文本说明 |
154
- | **`link`** | **4** | 外链 |
155
-
156
- CLI 校验(`PortalSectionPatch`):**chart** 须 **`chart_ref`**;**view** 须 **`view_ref`**;**text** 须 **`text`**;**link** 须 **`url`**。**grid** / **filter** 无额外 ref,**`config` 形状由后端接受为准**。
157
-
158
- ### 3.3 **`chart`**:几乎总须 **`builder charts apply` 先建报表**
159
-
160
- - `portal` 只做 **`chart_ref` 解析**(`app_key` + **`chart_id`** 优先,否则 **唯一 `chart_name`**)。
161
- - 若 **`builder app get charts`** 为空,先 **`builder charts apply --app-key … --upsert-file`** 创建(契约 **minimal_example** 如 **`target` + `indicator_field_ids: []`**),从响应 **`chart_results[].chart_id`** 取 id 再写 **`chart_ref`**.
162
-
163
- ### 3.4 **`filter`**:`config` **整包**即接口里的 **`filterConfig`**
164
-
165
- 实现:组件为 **`{"type": 6, "filterConfig": deepcopy(section.config)}`**。
166
-
167
- - **理论上**与 solution 编译器一致:外层 **`{"filterConfig": [ … ], "graphList": [ … ]}`**;**`graphList`** 常含 **`graphType`**(如 **`CHART`**)、**`graphKey`** 或 **`graphRef`(`entity_id` / `chart_id`)** 等。
168
- - **本环境 CLI 直写实测(多次 `--publish`)**:在已验证 **chart / view / grid / text / link** 均可落库的前提下,**`source_type: filter` 始终未出现在 `draft_result.components` 中**;尝试过:**空数组**、**仅 `graphList` + QingBI `chart_id`**、**`graphKey` 为门户 `dashChartId`**、**`chart` 排在 **`filter` 前**、**仅 2 块(chart+filter)** 等,回读仍 **只有 chart(`count: 1`)** 或 **五类缺 `type: 6`**。
169
- **结论**:当前宜 **在搭建界面创建筛选条**,再 **`builder portal get` 反抓** 原始 `filterConfig` 形状;或向后端确认 **POST `/dash/{dashKey}`** 对 **`type: 6`** 的必填字段。**自动化不要默认认为 `filter` 已写入。**
170
- - portal `filter` 组件仍按 raw `filterConfig` 处理,不纳入视图 / 报表 / 关联资源的统一筛选 DSL 主链路。
171
-
172
- ### 3.5 **`grid` / `text` / `link` / `view`**
173
-
174
- - **grid**:**`config`** 并入 **`gridConfig`**;业务入口必须写 **`config.items[]`**。应用入口项推荐 `{ "type": 1, "jumpMode": 1, "linkAppKey": "APP_KEY", "linkFormType": 1, "title": "入口名" }`。空 `config` 或空 `items` 只会生成空入口容器,并触发 **`PORTAL_GRID_ITEMS_EMPTY`**。
175
- - **text** / **link**:**`text`** / **`url`** 必填。
176
- - **view**:**`view_ref`**;**`view_key`** 来自 **`builder app get views`**。
177
-
178
- ---
179
-
180
- ## 4. 前置数据
181
-
182
- | 目的 | 命令 |
183
- |------|------|
184
- | **`package_id`** | **`builder app resolve --app-key …`** → **`package_ids`** |
185
- | **`view_key`** | **`builder app get --app-key … views`** |
186
- | **`chart_id`** | **`builder app get charts`** 或 **`charts apply` 创建** |
187
-
188
- ---
189
-
190
- ## 5. 新建最小例(`--no-publish`)
191
-
192
- 见上文 **§2** 与 **`visibility`** 最小对象;**`sections`** 可先用 **单块 `view`**。成功后拿 **`dash_key`** 再 **更新 / 发布**。
193
-
194
- ---
195
-
196
- ## 6. 更新与替换语义
197
-
198
- - **`--dash-key`** + **`--sections-file`**:**列表即全量**;没写进去的区块会被拿掉。
199
- - 仅改 **可见性 / 图标 / 分组**:**不传 `--sections-file`**,且不要单独带 **§2** 所列「仅在有 sections 时允许」的键。
200
-
201
- ---
202
-
203
- ## 7. 删除:`delete`
204
-
205
- ```bash
206
- qingflow --json builder portal delete --dash-key "<DASH_KEY>" > tmp/builder_portal_delete.json
207
- ```
208
-
209
- - **只按 `dash_key` 删除一个门户**;先用 `builder portal list/get` 确认目标,不要按名称猜。
210
- - 返回成功时重点看:**`delete_executed`**、**`readback_status`**、**`safe_to_retry_delete`**、`summary.removed`。
211
- - **`delete_executed=true` + `readback_status=deleted`**:删除已执行且回读确认不存在。
212
- - **`delete_executed=true` + `readback_status=unavailable|still_exists`**:DELETE 已发出,但回读不可确认或短时间仍存在;**不要盲目重复删除**,稍后用 `builder portal get/list` 确认。
213
- - DELETE 本身失败时才按 `status=failed` / `error_code` 处理。
214
-
215
- ---
216
-
217
- ## 8. **发布**(`--publish`)
218
-
219
- - **默认会发布**:未显式 **`--no-publish`** 即 **`publish: true`**;公开入口仍是 **`portal_apply`**,发布动作由工具内部执行并回读 **`being_draft=false`**。
220
- - **已发布线索**:成功路径上 **`published: true`**;**`live_result.publishStatus`** 常见 **`2`** 表示已发布(以你环境枚举为准)。
221
- - **`partial_success` + `PORTAL_READBACK_PENDING`**:草稿/线上 **组件数量或元数据** 与「本次期望」不一致时会出现;**`PORTAL_*_VERIFICATION_INCOMPLETE`** 警告。应 **`builder portal get --dash-key …`**(草稿与 **`--no-being-draft` 线上**)**肉眼核对**区块是否齐全,而不是仅信 **`verified: true`**。
222
- - **网关 503**:**与 CLI 无关**;环境恢复后重试 **`portal get` / `portal apply`**。(本轮在网关恢复后 **`portal apply` 已成功**。)
223
-
224
- ---
225
-
226
- ## 9. 本环境实测摘要
227
-
228
- | 步骤 | 命令要点 | 结果 |
229
- |------|-----------|------|
230
- | 新建门户 | `--package-id 2030703`、`--dash-name "CLI门户探针_可删"`、`--no-publish`、单 **view** | **`dash_key`: `ecdcell64s02`** |
231
- | 补报表 | **`builder charts apply`**,`name: 门户探针_目标图`,**`target`** | **`chart_id`: `mcp_fb104267c5c249ca`** |
232
- | 503 后重试 | **`--dash-key ecdcell64s02`、`--publish`** + 含 **filter** 的六类 **`sections-file`** | **`published: true`**;**`filter` 仍不落库** → **`partial_success`**,**`components expected 6, got 5`**(与 **§3.4** 一致) |
233
- | **filter 专项** | 仅 **chart + filter** 两块的多种 **`graphList`/`graphRef`/`dashChartId`/`filterGroupConfig`** 组合 | **回读恒为 1 块(仅 `type: 9`)** |
234
- | **稳定可复现** | **`--publish`** + **[portal_sections_five_types.example.json](./portal_sections_five_types.example.json)**(**grid / text / link / view / chart**) | **`status: success`**,**`types: [2,4,5,9,10]`**,**`published: true`** |
235
- | 删除门户 | `builder portal delete --dash-key etcivtmv5402` | **`status: success`**,**`delete_executed: true`**,**`readback_status: deleted`**,**`summary.removed: 1`** |
236
-
237
- **推荐工作台模板示例**:[portal_sections_standard_workbench.example.json](./portal_sections_standard_workbench.example.json)
238
-
239
- **含 `filter` 的六类示例(`filter` 是否落库视环境/后端而定)**:[portal_sections_all_types.example.json](./portal_sections_all_types.example.json)
240
-
241
- ---
242
-
243
- ## 10. 排障
244
-
245
- | 现象 | 处理 |
246
- |------|------|
247
- | `portal apply accepts exactly one selector mode` | **`dash-key`** vs **`package-id`** 二选一。 |
248
- | `PORTAL_READBACK_PENDING` / **`components expected N, got M`** | **`portal get`** 数组件;若多写了 **`filter`** 而回读少一块,见 **§3.4**(**CLI 写 filter 可能整体不生效**);也可能是 **异步回读**,可再 **`get`** 一次。 |
249
- | **`published: true` 但 `verified: false`** | 读 **§7**;用 **`get` 草稿+线上**对照。 |
250
- | **503** | 网关/运维;稍后重试。 |
251
- | 缺 **chart** | **[QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md)**:`builder charts apply`;或换有报表的应用。 |
252
- | **VISIBILITY_CONFLICT** | 只用 **`--visibility-file`**。 |
253
- | `delete_executed=true` 但 `readback_status=unavailable|still_exists` | DELETE 已发出,回读未确认;不要重复删除,稍后 `builder portal get/list` 复核。 |
254
-
255
- ---
256
-
257
- ## 11. 交叉引用
258
-
259
- - [SKILL.md](../SKILL.md)
260
- - [QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md)
261
- - [QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md)
262
- - [QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md](./QINGFLOW_CLI_BUILDER_CHARTS_WORKFLOW.md)
263
- - [QINGFLOW_CLI_EXPLORATION_REPORT.md](./QINGFLOW_CLI_EXPLORATION_REPORT.md)
11
+ 契约与九类组件专项 Schema:`qingflow --json builder portal schema --schema-kind complete|<类型>`。
@@ -218,6 +218,19 @@ current CLI payload.
218
218
  | `relation` | 关联记录(**`config.relationMode`**:`single` \| `multiple`) |
219
219
  | `data_relation` | 数据关联/引用填充 |
220
220
  | `subtable` | 子表(**`subfields[]`**) |
221
+ | `date_duration` | 日期区间(透传型,无特殊配置) |
222
+ | `image_select` | 图片单选(透传型,选项经模板保真) |
223
+ | `location` | 地理位置(透传型) |
224
+ | `ocr` | OCR 识别(透传型) |
225
+ | `embed_field` | 内嵌字段(透传型) |
226
+ | `ai_content_generation` | AI 内容生成(透传型) |
227
+ | `ai_content_extraction` | AI 内容提取(透传型) |
228
+ | `ai_content_classification` | AI 内容分类(透传型) |
229
+ | `ai_machine_translation` | AI 机器翻译(透传型) |
230
+ | `ai_image_recognition` | AI 图像识别(透传型) |
231
+ | `ai_image_generation` | AI 图像生成(透传型) |
232
+ | `ai_document_parsing` | AI 文档解析(透传型) |
233
+ | `ai_text_summary` | AI 文本摘要(透传型) |
221
234
 
222
235
  历史表单中的后端 `queType=1` 是“描述文字”布局控件,不属于上述新建字段类型。`app-form get` 为了保持完整声明可校验,会将它兼容输出为 `long_text`;`app-form apply` 会根据已有字段模板恢复原始 `queType=1` 和 `queDefaultValue`,所以修改其他字段时不会丢失描述文字。新建可填写多行文本仍使用 `long_text`,不要用它创建描述文字控件。
223
236
 
@@ -11,13 +11,26 @@ Not responsible for: creating apps or views referenced by the portal. Create or
11
11
  ## Main chain
12
12
 
13
13
  ```text
14
- portal list/get if updating -> verify apps/views and read chart lists only when reusing existing charts -> portal apply with sections[].chart -> portal get readback -> publish state
14
+ portal list/get if updating -> verify apps/views and read chart lists only when reusing existing charts
15
+ -> (offline) builder portal validate --file decl.json
16
+ -> builder portal apply --file decl.json [--schema-version v1alpha1]
17
+ -> builder portal get --dash-key K --schema-kind summary|complete (readback) -> publish state
15
18
  ```
16
19
 
20
+ ## Versioned schema and declaration files
21
+
22
+ - Declarations are versioned: `schema_version` (default `v1alpha1`), `apiVersion: builder.qingflow.com/v1alpha1`. The envelope echoes `schemaVersion` when you pass `--schema-version`.
23
+ - Two document kinds: **summary** = name + layout + component list (five stable component types: `chart/view/grid/text/link`); **complete** = summary superset with global config (`icon/color/hide_copyright/global_config/style_template_id/overall_style`), nine component types (adds `filter/carousel/task/favourite`), component `style_config`, and `visibility` authorization.
24
+ - Read the contract itself: `qingflow --json builder portal schema --schema-kind summary|complete|<component>`; every component type (`chart|view|grid|filter|text|link|carousel|task|favourite`) has a self-contained schema — fetch it before guessing config keys.
25
+ - `builder portal get` defaults to `--schema-kind summary` and returns a canonical `declaration` (the round-trip anchor for replay tooling). Use `--schema-kind raw` for the legacy normalized response and `--schema-kind complete` for the full declaration.
26
+ - Offline validation: `qingflow --json builder portal validate --file decl.json` (accepts `-` for stdin; zero backend calls). Fix issues before applying.
27
+ - Apply main form: `qingflow builder portal apply --file decl.json --schema-version v1alpha1 [--no-publish]`. Legacy patch parameters (`--sections-file`, `--visibility-file`, ...) still work in a compatibility window but emit a deprecation notice; do not use them in new automations. `--payload-file` (raw DTO passthrough) is legacy-only.
28
+
17
29
  ## Demo files
18
30
 
19
31
  | Scenario | Example |
20
32
  |----------|---------|
33
+ | Recommended v1alpha1 declaration (`--file`) | [portal_apply_v1alpha1.example.json](../examples/portal/portal_apply_v1alpha1.example.json) |
21
34
  | Recommended business workbench | [portal_sections_standard_workbench.example.json](../examples/portal/portal_sections_standard_workbench.example.json) |
22
35
  | Stable component capability probe | [portal_sections_five_types.example.json](../examples/portal/portal_sections_five_types.example.json) |
23
36
  | Raw/experimental all-types probe | [portal_sections_all_types.example.json](../examples/portal/portal_sections_all_types.example.json) |
@@ -66,8 +79,9 @@ Recommended standard workbench skeleton:
66
79
 
67
80
  ## Update existing portal
68
81
 
69
- - Use `--dash-key` for updates and do not send `package_id`.
70
- - Use `patch_sections[]` for targeted section changes when possible.
82
+ - Prefer the declaration-file form: `builder portal apply --file decl.json --schema-version v1alpha1 --dash-key K --no-publish` (the file may omit `dash_key` and pass it via `--dash-key`; do not send `package_id` for updates).
83
+ - Read the current declaration first with `builder portal get --dash-key K --schema-kind complete`, edit it, `builder portal validate --file`, then apply. `sections` is full-replace semantics.
84
+ - `patch_sections[]` (via `--patch-sections-file`, compatibility window) remains for targeted section changes when a full declaration round-trip is not practical.
71
85
  - `patch_sections[]` selectors may use `order`, `chart_ref.chart_id`, `chart_ref.chart_key`, or `view_ref.view_key`; chart sections read back from portal often only include `chart_id`, so patching by `chart_id` is valid and does not require `app_key`.
72
86
  - If using a business-entry grid, include real `items`; do not submit an empty entry container.
73
87
  - Validate referenced `chart_key`, `chart_id`, `view_key`, or `app_key` before claiming the portal is complete.
@@ -110,7 +124,9 @@ qingflow --json builder portal get --dash-key "<DASH_KEY>" --no-being-draft
110
124
  | 参数 | 说明 |
111
125
  |------|------|
112
126
  | **`--publish` / `--no-publish`** | 默认 **`--publish`**。仅 **`--no-publish`** 时不会调用发布接口;契约说明 **`publish=false` 不宣称线上已变**。 |
113
- | **`--payload-file`** | 完整门户 JSON 对象;**标准字段写 `dash_name`**。新版 CLI 兼容 **`name -> dash_name`**、单页 **`pages[0].components -> sections`**,但 agent 默认不要依赖兼容别名。 |
127
+ | **`--file`**(主形态) | 完整门户声明 JSON 对象(支持 **`-`** stdin);与 patch 参数互斥;声明内可带 **`schema_version`**。 |
128
+ | **`--schema-version`** | 固定声明契约版本(缺省读文件内 `schema_version`,再缺省 latest)。传入时声明先过 complete schema 离线校验,**`INVALID_SPEC` 不写**。 |
129
+ | **`--payload-file`**(旧) | 完整门户 JSON 对象透传(兼容窗口);新代码改用 **`--file`**。标准字段写 `dash_name`。 |
114
130
  | **`--sections-file`** | JSON **数组**;**全量替换**。省略时仅改基础信息,且 **`hide_copyright` / `dash_global_config` / `config`** 不能单独提交(**`PORTAL_SECTIONS_REQUIRED`**)。 |
115
131
  | **`--layout-preset`** | 可选:**`auto` / `dashboard_2col` / `dashboard_3col`**。当区块未显式写 **`position`** 时由工具生成大屏布局。 |
116
132
  | **`--visibility-file`** | 与 **`--auth-file`** 不能同时用。 |
@@ -125,7 +141,7 @@ qingflow --json builder portal get --dash-key "<DASH_KEY>" --no-being-draft
125
141
 
126
142
  ### 3.1 公共键
127
143
 
128
- - **`title`**(必填)、**`source_type`**(必填,小写)、可选 **`position`**(**`pc`/`mobile`** 各 **`x,y,cols,rows`**;省略则由**实现自动排布**)。
144
+ - **`source_type`**(必填,小写)、**`title`**(可选——schema 仅强制 `source_type`;新建组件建议提供标题,存量 filter 组件合法无标题,round-trip 透传不要合成)、可选 **`position`**(嵌套 **`pc`/`mobile`** 各 **`x,y,cols,rows`**;平铺别名 **`pc_x/pc_y/pc_w/pc_h`、`mobile_*`** 也接受,`x/y` 与 `w/h/cols/rows` 混写均认;省略则由**实现自动排布**)。
129
145
  - **`config`**、**`dash_style_config`**:按类型 Optional。默认只写 snake_case 规范键。
130
146
 
131
147
  ### 3.1.0 Payload 字段口径
@@ -198,8 +214,8 @@ mobile 固定按 **6 栅格** 从上到下堆叠:通常所有组件 `x=0, cols
198
214
 
199
215
  **当前工具边界**:
200
216
 
201
- - 公开 `sections-file` 稳定支持:**`grid` / `chart` / `view` / `text` / `link`**;`filter` 仍按 **§3.4** 的 raw `filterConfig` 边界处理,不作为主路径。
202
- - **待办 `task` / 常用 `favorite`** 是前端/后端 raw 组件形状,不在当前公开 `source_type` 合约里。智能体不要在 `sections-file` 中写 `source_type: "task"`;只有工具后续显式支持 `task`,或维护者走 raw 门户写入链路时,才使用待办槽位。
217
+ - 声明式(`--file` / complete 档)支持**九类组件**:**`grid` / `chart` / `view` / `text` / `link`**(summary 档稳定面)+ **`carousel` / `task` / `favourite`**(complete 档,配置键见专项 Schema)+ **`filter`**(complete 档受控承载,仍按 **§3.4** raw 边界处理,不作为主路径)。
218
+ - **`task`(一个门户最多 1 个)与 `favourite`(一个门户最多 1 个)** 已进入 v1alpha1 complete 声明面(`task`/`favourite` 类型化 config 键),不要再按后端 raw 形状(`taskConfig`/`favouriteConfig`)手拼;声明形态见 `qingflow --json builder portal schema --schema-kind task|favourite`。旧文档中的「task/favorite 不在公开合约里」已过时。
203
219
  - 推荐门户的可直接 apply 示例见 **[portal_sections_standard_workbench.example.json](../examples/portal/portal_sections_standard_workbench.example.json)**。这是唯一推荐复制的业务工作台布局模板:每一行 `cols_sum=24`,同行 `rows` 一致,下一行 `y` 连续。顶部先用一个业务入口 `grid` 占满 24 栅格;如果工具已支持待办组件,再把顶部拆成 `grid cols=12 + task cols=12`。
204
220
  - **[portal_sections_five_types.example.json](../examples/portal/portal_sections_five_types.example.json)** 和 **[portal_sections_all_types.example.json](../examples/portal/portal_sections_all_types.example.json)** 仅用于组件能力探针,不作为业务门户布局模板;搭建正式门户时不要从这些探针推导布局。
205
221
  - `grid` 必须写 **`config.items[]`**;只写 `gridTitle` / `beingShowTitle` 会生成空入口容器,工具会返回 **`PORTAL_GRID_ITEMS_EMPTY`**。
@@ -230,16 +246,21 @@ mobile 固定按 **6 栅格** 从上到下堆叠:通常所有组件 `x=0, cols
230
246
 
231
247
  ### 3.2 `source_type` ↔ 回读 `components[].type`(搭建侧)
232
248
 
233
- | `source_type` | 回读 `type`(数字) | 搭建侧含义 |
234
- |---------------|---------------------|------------|
235
- | **`chart`** | **9** | QingBI 图表块 |
236
- | **`view`** | **10** | 应用视图块 |
237
- | **`grid`** | **2** | 九宫格 |
238
- | **`filter`** | **6** | 筛选条 |
239
- | **`text`** | **5** | 富文本说明 |
240
- | **`link`** | **4** | 外链 |
249
+ | `source_type` | 回读 `type`(数字) | 搭建侧含义 | 声明档 |
250
+ |---------------|---------------------|------------|----------|
251
+ | **`chart`** | **9** | QingBI 图表块 | summary |
252
+ | **`view`** | **10** | 应用视图块 | summary |
253
+ | **`grid`** | **2** | 九宫格 | summary |
254
+ | **`text`** | **5** | 富文本说明 | summary |
255
+ | **`link`** | **4** | 外链 | summary |
256
+ | **`filter`** | **6** | 筛选条 | complete(raw/unstable) |
257
+ | **`carousel`** | **3** | 轮播(数据源应用 + 标题/图片/链接字段) | complete |
258
+ | **`task`** | **8** | 待办(一个门户最多 1 个) | complete |
259
+ | **`favourite`** | **7** | 收藏(一个门户最多 1 个) | complete |
260
+
261
+ 每类组件的详细配置键经专项 Schema 获取:`qingflow --json builder portal schema --schema-kind <类型>`(如 `--schema-kind carousel`、`--schema-kind task`)。`carousel` 的 `title_field/image_field/link_field` 填字段显示名(CLI 编译为 queId);`task.tasks[].task_type` 取值 1=我的待办 2=已超时 3=即将超时 4=催办 5=我发起的 6=抄送我的 7=草稿箱 8=我的已办 9=待完善;`favourite.items[]` 用 `item_type`(1=应用 2=门户)+`link_key` 锚定目标。
241
262
 
242
- CLI 校验(`PortalSectionPatch`):**chart** 须 **`chart`** 或兼容旧字段 **`chart_ref`**;**view** 须 **`view_ref`**;**text** 须 **`text`**;**link** 须 **`url`**。**grid** / **filter** 无额外 ref,**`config` 形状由后端接受为准**。
263
+ CLI 校验(`PortalSectionPatch`):**chart** 须 **`chart`** 或 **`chart_ref`**;**view** 须 **`view_ref`**;**text** 须 **`text`**;**link** 须 **`url`**;**carousel/task/favourite** 须各自类型化 config 键。**grid** / **filter** 无额外 ref,**`config` 形状由专项 Schema 与后端接受为准**。
243
264
 
244
265
  ### 3.3 **`chart`**:一个字段同时支持引用已有图表和内联创建图表
245
266
 
@@ -327,7 +348,7 @@ qingflow --json builder portal delete --dash-key "<DASH_KEY>" > tmp/builder_port
327
348
 
328
349
  ## 8. **发布**(`--publish`)
329
350
 
330
- - **默认会发布**:未显式 **`--no-publish`** 即 **`publish: true`**;公开入口仍是 **`portal_apply`**,发布动作由工具内部执行并回读 **`being_draft=false`**。
351
+ - **默认会发布**:未显式 **`--no-publish`** 即 **`publish: true`**;公开入口仍是 **`portal_apply`**,发布动作由工具内部执行并回读 **`being_draft=false`**。**注意**:对**已发布门户**用 **`--no-publish`** 更新会把发布状态**降回草稿**(草稿写了、线上态被覆盖标记)——需要保留线上态的试写/迭代不要带 **`--no-publish`** 对已发布门户提交,或写完后显式补发布。
331
352
  - **已发布线索**:成功路径上 **`published: true`**;**`live_result.publishStatus`** 常见 **`2`** 表示已发布(以你环境枚举为准)。
332
353
  - **`partial_success` + `PORTAL_READBACK_PENDING`**:草稿/线上 **组件数量或元数据** 与「本次期望」不一致时会出现;**`PORTAL_*_VERIFICATION_INCOMPLETE`** 警告。应 **`builder portal get --dash-key …`**(草稿与 **`--no-being-draft` 线上**)**肉眼核对**区块是否齐全,而不是仅信 **`verified: true`**。
333
354
  - **网关 503**:**与 CLI 无关**;环境恢复后重试 **`portal get` / `portal apply`**。(本轮在网关恢复后 **`portal apply` 已成功**。)
@@ -0,0 +1,100 @@
1
+ {
2
+ "schema_version": "v1alpha1",
3
+ "name": "业务工作台",
4
+ "package_tag_id": 2030703,
5
+ "icon": "view-grid",
6
+ "color": "#2468F2",
7
+ "hide_copyright": false,
8
+ "global_config": {
9
+ "auto_refresh": false,
10
+ "interval": 60,
11
+ "export": true
12
+ },
13
+ "visibility": {
14
+ "mode": "workspace",
15
+ "external_mode": "not"
16
+ },
17
+ "layout_preset": "auto",
18
+ "sections": [
19
+ {
20
+ "title": "业务入口",
21
+ "source_type": "grid",
22
+ "position": {
23
+ "pc": { "x": 0, "y": 0, "cols": 24, "rows": 4 }
24
+ },
25
+ "config": {
26
+ "gridTitle": "业务入口",
27
+ "beingShowTitle": true,
28
+ "items": [
29
+ { "type": 1, "jumpMode": 1, "linkAppKey": "APP_KEY_DEVICE", "linkFormType": 1, "title": "设备台账" },
30
+ { "type": 1, "jumpMode": 1, "linkAppKey": "APP_KEY_WORKORDER", "linkFormType": 1, "title": "工单管理" }
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "title": "设备总数",
36
+ "source_type": "chart",
37
+ "role": "metric",
38
+ "position": {
39
+ "pc": { "x": 0, "y": 4, "cols": 6, "rows": 5 }
40
+ },
41
+ "chart": {
42
+ "app_key": "APP_KEY_DEVICE",
43
+ "name": "设备总数",
44
+ "chart_type": "target",
45
+ "metric": "count(*)"
46
+ }
47
+ },
48
+ {
49
+ "title": "异常设备数",
50
+ "source_type": "chart",
51
+ "role": "metric",
52
+ "position": {
53
+ "pc": { "x": 6, "y": 4, "cols": 6, "rows": 5 }
54
+ },
55
+ "chart": {
56
+ "app_key": "APP_KEY_DEVICE",
57
+ "name": "异常设备数",
58
+ "chart_type": "target",
59
+ "metric": "count(*)",
60
+ "filters": [
61
+ { "field_name": "状态", "operator": "eq", "values": ["异常"] }
62
+ ]
63
+ }
64
+ },
65
+ {
66
+ "title": "工单趋势",
67
+ "source_type": "chart",
68
+ "position": {
69
+ "pc": { "x": 0, "y": 9, "cols": 12, "rows": 7 }
70
+ },
71
+ "chart": {
72
+ "app_key": "APP_KEY_WORKORDER",
73
+ "name": "工单趋势",
74
+ "chart_type": "line",
75
+ "metric": "count(*)",
76
+ "group_by": ["创建日期"]
77
+ }
78
+ },
79
+ {
80
+ "title": "工单类型分布",
81
+ "source_type": "chart",
82
+ "position": {
83
+ "pc": { "x": 12, "y": 9, "cols": 12, "rows": 7 }
84
+ },
85
+ "chart_ref": { "app_key": "APP_KEY_WORKORDER", "chart_name": "工单类型分布" }
86
+ },
87
+ {
88
+ "title": "异常设备明细",
89
+ "source_type": "view",
90
+ "position": {
91
+ "pc": { "x": 0, "y": 16, "cols": 24, "rows": 11 }
92
+ },
93
+ "view_ref": {
94
+ "app_key": "APP_KEY_DEVICE",
95
+ "view_key": "VIEW_KEY_ABNORMAL_DEVICES"
96
+ },
97
+ "view_display": { "show_title": true }
98
+ }
99
+ ]
100
+ }
@@ -17,14 +17,13 @@
17
17
  }
18
18
  },
19
19
  "config": {
20
- "filterConfig": [],
21
- "graphList": [
20
+ "graphs": [
22
21
  {
23
- "graphType": "CHART",
24
- "graphKey": "REPLACE_WITH_QINGBI_CHART_ID",
25
- "graphName": "可选_图表显示名"
22
+ "chart_key": "REPLACE_WITH_QINGBI_CHART_ID",
23
+ "chart_name": "可选_图表显示名"
26
24
  }
27
- ]
25
+ ],
26
+ "rules": []
28
27
  }
29
28
  },
30
29
  {
@@ -142,4 +141,4 @@
142
141
  "chart_id": "YOUR_CHART_ID"
143
142
  }
144
143
  }
145
- ]
144
+ ]