@qingflow-tech/qingflow-cli 1.1.2 → 1.1.34
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/README.md +2 -2
- package/docs/local-agent-install.md +10 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/skills/qingflow-cli/SKILL.md +61 -47
- package/skills/qingflow-cli/manifest.yaml +1 -1
- package/skills/qingflow-cli/reference/00-INDEX.md +35 -0
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md +21 -477
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +44 -290
- package/skills/qingflow-cli/reference/QINGFLOW_CLI_SCHEMA_APPLY_FIELD_TYPES_AND_SCENARIOS.md +11 -102
- package/skills/qingflow-cli/reference/builder/10-build-single-app.md +57 -0
- package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +84 -0
- package/skills/qingflow-cli/reference/builder/30-schema-fields.md +317 -0
- package/skills/qingflow-cli/reference/builder/40-layout.md +70 -0
- package/skills/qingflow-cli/reference/builder/50-views.md +540 -0
- package/skills/qingflow-cli/reference/builder/60-charts.md +328 -0
- package/skills/qingflow-cli/reference/builder/70-portal.md +372 -0
- package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +148 -0
- package/skills/qingflow-cli/reference/builder/90-workflow.md +35 -0
- package/skills/qingflow-cli/reference/builder/99-publish-verify.md +64 -0
- package/skills/qingflow-cli/reference/builder/README.md +62 -0
- package/skills/qingflow-cli/reference/builder/code-integrations/README.md +130 -0
- package/skills/qingflow-cli/reference/builder/code-integrations/code-block.md +66 -0
- package/skills/qingflow-cli/reference/builder/code-integrations/q-linker.md +77 -0
- package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +508 -0
- package/skills/qingflow-cli/reference/builder/reference/match-rules.md +229 -0
- package/skills/qingflow-cli/reference/builder/reference/workspace-icons.md +89 -0
- package/skills/qingflow-cli/reference/builder/workflow/01-overview.md +48 -0
- package/skills/qingflow-cli/reference/builder/workflow/02-update-mode.md +63 -0
- package/skills/qingflow-cli/reference/builder/workflow/03-flow-patterns.md +59 -0
- package/skills/qingflow-cli/reference/builder/workflow/04-stage1-business-modeling.md +131 -0
- package/skills/qingflow-cli/reference/builder/workflow/05-stage2-members-roles.md +29 -0
- package/skills/qingflow-cli/reference/builder/workflow/06-stage3-build-spec.md +211 -0
- package/skills/qingflow-cli/reference/builder/workflow/07-stage4-validate-spec.md +36 -0
- package/skills/qingflow-cli/reference/builder/workflow/08-stage5-apply-verify.md +66 -0
- package/skills/qingflow-cli/reference/builder/workflow/09-stage6-summary.md +88 -0
- package/skills/qingflow-cli/reference/builder/workflow/10-node-config-reference.md +93 -0
- package/skills/qingflow-cli/reference/builder/workflow/11-troubleshooting.md +18 -0
- package/skills/qingflow-cli/reference/builder/workflow/README.md +88 -0
- package/skills/qingflow-cli/reference/builder/workflow/workflow-schema.json +1754 -0
- package/skills/qingflow-cli/reference/charts_upsert_dashboard_starter.example.json +81 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +94 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +139 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +84 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +129 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +195 -0
- package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +159 -0
- package/skills/qingflow-cli/reference/examples/README.md +17 -0
- package/skills/qingflow-cli/reference/examples/associated/associated_resources_semantic_full.example.json +50 -0
- package/skills/qingflow-cli/reference/examples/buttons/custom_buttons_advanced.example.json +56 -0
- package/skills/qingflow-cli/reference/examples/charts/charts_remove.example.json +1 -0
- package/skills/qingflow-cli/reference/examples/charts/charts_reorder.example.json +1 -0
- package/skills/qingflow-cli/reference/examples/charts/charts_upsert_bar.example.json +8 -0
- package/skills/qingflow-cli/reference/examples/charts/charts_upsert_dashboard_starter.example.json +118 -0
- package/skills/qingflow-cli/reference/examples/charts/charts_upsert_minimal.example.json +13 -0
- package/skills/qingflow-cli/reference/examples/layout/layout_sections_full.example.json +22 -0
- package/skills/qingflow-cli/reference/examples/portal/portal_sections_all_types.example.json +145 -0
- package/skills/qingflow-cli/reference/examples/portal/portal_sections_five_types.example.json +126 -0
- package/skills/qingflow-cli/reference/examples/portal/portal_sections_standard_workbench.example.json +178 -0
- package/skills/qingflow-cli/reference/examples/record/record_insert_all_field_types.example.json +35 -0
- package/skills/qingflow-cli/reference/examples/schema/_batch_schema_complex.json +18 -0
- package/skills/qingflow-cli/reference/examples/schema/_batch_schema_scalar.json +17 -0
- package/skills/qingflow-cli/reference/examples/schema/schema_add_fields_minimal.example.json +7 -0
- package/skills/qingflow-cli/reference/examples/schema/schema_apply_add_fields_all_types.json +78 -0
- package/skills/qingflow-cli/reference/examples/schema/schema_multi_app_form_relation_layout.example.json +166 -0
- package/skills/qingflow-cli/reference/examples/schema/schema_single_app_form_standard.example.json +95 -0
- package/skills/qingflow-cli/reference/examples/views/views_batch_full.example.json +159 -0
- package/skills/qingflow-cli/reference/examples/views/views_upsert_table_minimal.example.json +42 -0
- package/skills/qingflow-cli/reference/portal_sections_all_types.example.json +18 -4
- package/skills/qingflow-cli/reference/portal_sections_five_types.example.json +3 -3
- package/skills/qingflow-cli/reference/portal_sections_standard_workbench.example.json +57 -7
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +22 -0
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_DELETE_WORKFLOW.md +31 -0
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_IMPORT_WORKFLOW.md +176 -0
- package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +167 -0
- package/skills/qingflow-cli/reference/record/analysis/README.md +130 -0
- package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +91 -0
- package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +112 -0
- package/skills/qingflow-cli/reference/record/analysis/business-context.md +74 -0
- package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +69 -0
- package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +106 -0
- package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +172 -0
- package/skills/qingflow-cli/reference/record/analysis/report-format.md +76 -0
- package/skills/qingflow-cli/reference/record/insert/README.md +125 -0
- package/skills/qingflow-cli/reference/schema_apply_add_fields_all_types.json +1 -1
- package/skills/qingflow-cli/reference/task/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +153 -0
- package/skills/qingflow-cli/reference/task/ops/README.md +134 -0
- package/skills/qingflow-cli/reference/task/ops/environments.md +43 -0
- package/skills/qingflow-cli/reference/task/ops/workflow-usage.md +29 -0
- package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +42 -7
- package/skills/qingflow-cli/scripts/validate_system_build_summary.py +124 -0
- package/skills/qingflow-cli/scripts/workflow/diff_flow_spec.py +275 -0
- package/skills/qingflow-cli/scripts/workflow/validate_flow_spec.py +627 -0
- package/src/qingflow_mcp/builder_facade/models.py +413 -119
- package/src/qingflow_mcp/builder_facade/service.py +4238 -666
- package/src/qingflow_mcp/cli/commands/builder.py +232 -75
- package/src/qingflow_mcp/cli/main.py +34 -0
- package/src/qingflow_mcp/public_surface.py +10 -0
- package/src/qingflow_mcp/server_app_builder.py +62 -34
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/executor.py +2 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +2649 -457
- package/src/qingflow_mcp/tools/record_tools.py +23 -11
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# Builder Portal
|
|
2
|
+
|
|
3
|
+
Read this when the task is about creating, updating, deleting, publishing, or validating a portal/workbench/dashboard page.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
Responsible for: `builder portal list/get/apply/delete`, portal sections, standard workbench layout, business entry grid items, existing chart references, inline chart creation through section `chart`, view references, publish, and portal readback.
|
|
8
|
+
|
|
9
|
+
Not responsible for: creating apps or views referenced by the portal. Create or verify apps/views first through [20-build-complete-system.md](./20-build-complete-system.md) and [50-views.md](./50-views.md). For reports used only by the portal, declare `chart` inside the portal section when no existing chart matches.
|
|
10
|
+
|
|
11
|
+
## Main chain
|
|
12
|
+
|
|
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
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Demo files
|
|
18
|
+
|
|
19
|
+
| Scenario | Example |
|
|
20
|
+
|----------|---------|
|
|
21
|
+
| Recommended business workbench | [portal_sections_standard_workbench.example.json](../examples/portal/portal_sections_standard_workbench.example.json) |
|
|
22
|
+
| Stable component capability probe | [portal_sections_five_types.example.json](../examples/portal/portal_sections_five_types.example.json) |
|
|
23
|
+
| Raw/experimental all-types probe | [portal_sections_all_types.example.json](../examples/portal/portal_sections_all_types.example.json) |
|
|
24
|
+
|
|
25
|
+
## One-eye portal decision table
|
|
26
|
+
|
|
27
|
+
Start from the portal job, then choose the section strategy. A portal is an assembly surface; it should reference already verified apps, views, and charts.
|
|
28
|
+
|
|
29
|
+
| Portal job | Main action | Required rule |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| Create a standard business workbench | Use business entry -> metric cards -> BI charts -> data views | Verify `app_key` and raw `view_key`; for chart sections use `chart` to reference an existing chart or create the needed QingBI chart inline |
|
|
32
|
+
| Add business entry shortcuts | Use `source_type: "grid"` | `config.items[]` must contain real entries; never submit empty `config` or `items: []` |
|
|
33
|
+
| Show KPI cards | Use chart sections with `role: "metric"` | Referenced charts must be `target` / `indicator`; `rows=5` |
|
|
34
|
+
| Show BI visualizations | Use chart sections | `rows=7`; same-row components share the same `rows` |
|
|
35
|
+
| Show concrete data views | Use view sections | Use business views, not `全部数据` / `我的数据`; `rows=11` |
|
|
36
|
+
| Update one existing portal block | Prefer `patch_sections[]` | Do not replace the whole `sections` list unless intentional |
|
|
37
|
+
| Need a filter bar | Avoid automation by default | `source_type: "filter"` is raw/unstable and not part of the unified filter DSL |
|
|
38
|
+
|
|
39
|
+
Short rule: **portal rows are 24-grid layout rows, not form-field rows. Same `y` = same row, same `rows`, `cols` sum 24.**
|
|
40
|
+
|
|
41
|
+
## Write checklist
|
|
42
|
+
|
|
43
|
+
Before `portal apply`, verify this short list:
|
|
44
|
+
|
|
45
|
+
| Check | Required rule |
|
|
46
|
+
|-------|---------------|
|
|
47
|
+
| Referenced apps/views/charts exist | Read `app_key` and raw `view_key` first. If no existing chart matches, use section `chart` with `app_key + name + chart_type` instead of inventing a chart id/name. |
|
|
48
|
+
| Business entry grid | `grid.config.items[]` must contain real app/portal entries. Empty `config` or `items: []` is invalid. |
|
|
49
|
+
| PC row math | Same `y` means same row. All components in that row must share the same `rows`, and `cols` should sum to 24 unless the user explicitly wants blank space. |
|
|
50
|
+
| Standard heights | Metric cards `rows=5`; BI charts `rows=7`; data views `rows=11`. Do not mix different heights in one row. |
|
|
51
|
+
| Standard order | Business entry -> metrics -> BI charts -> data views. Do not put data views before metrics/charts in a dashboard-style portal. |
|
|
52
|
+
| Default/system views | Do not use `全部数据` / `我的数据` as the main business portal views. Use concrete business views. |
|
|
53
|
+
| Filter component | Do not use `source_type: "filter"` as the main automation path; it is raw/unstable and not part of the unified filter DSL. |
|
|
54
|
+
| Readback | After apply, run `portal get` and compare section count, refs, and positions before claiming frontend visibility. |
|
|
55
|
+
|
|
56
|
+
Inline QingBI chart creation uses one chart job per section and runs with an internal concurrency limit of 10. If two sections declare the same `app_key + name + chart_type` with identical config, CLI creates/updates once and reuses the chart id. If their config differs, CLI rejects the portal write as a duplicate inline chart conflict.
|
|
57
|
+
|
|
58
|
+
Recommended standard workbench skeleton:
|
|
59
|
+
|
|
60
|
+
| Row | Components | PC position |
|
|
61
|
+
|-----|------------|-------------|
|
|
62
|
+
| 1 | Business entry `grid`; optional todo only when the tool supports it | `grid x=0,y=0,cols=24,rows=4` or `grid cols=12 + task cols=12` |
|
|
63
|
+
| 2 | 4 core metric cards | `x=0/6/12/18,y=4,cols=6,rows=5` |
|
|
64
|
+
| 3 | 2-3 BI charts | 2 charts: `x=0/12,cols=12,rows=7`; 3 charts: `x=0/8/16,cols=8,rows=7` |
|
|
65
|
+
| 4 | 1-2 concrete data views | 1 view: `x=0,cols=24,rows=11`; 2 views: `x=0/12,cols=12,rows=11` |
|
|
66
|
+
|
|
67
|
+
## Update existing portal
|
|
68
|
+
|
|
69
|
+
- Use `--dash-key` for updates and do not send `package_id`.
|
|
70
|
+
- Use `patch_sections[]` for targeted section changes when possible.
|
|
71
|
+
- `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
|
+
- If using a business-entry grid, include real `items`; do not submit an empty entry container.
|
|
73
|
+
- Validate referenced `chart_key`, `chart_id`, `view_key`, or `app_key` before claiming the portal is complete.
|
|
74
|
+
|
|
75
|
+
## Detailed contract notes
|
|
76
|
+
|
|
77
|
+
搭建侧稳定入口:**`qingflow builder portal`**:`list` / `get` / **`apply`** / **`delete`**(与根命令 **`qingflow portal`** 的「成员可读列表/详情」不同,见 **[QINGFLOW_CLI_EXPLORATION_REPORT.md](../core/QINGFLOW_CLI_EXPLORATION_REPORT.md) §4.6**)。
|
|
78
|
+
|
|
79
|
+
实现要点来自 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`**。
|
|
80
|
+
|
|
81
|
+
> **权限**:**更新**需 **`edit_portal`**;**新建**按后端 `DashCtrl.createDash` 链路只预检目标包 **`add_app`**,不额外要求包 **`edit_app`**。失败时参见主技能与 **ADMIN** 速查。
|
|
82
|
+
|
|
83
|
+
> **契约**:`qingflow --json builder contract --tool-name portal_apply`;删除契约:`qingflow --json builder contract --tool-name portal_delete`
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 1. 读:`list` → `get`
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
qingflow --json builder portal list > tmp/builder_portal_list.json
|
|
91
|
+
|
|
92
|
+
qingflow --json builder portal get --dash-key "<DASH_KEY>" > tmp/builder_portal_get.json
|
|
93
|
+
qingflow --json builder portal get --dash-key "<DASH_KEY>" --no-being-draft
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- **`list`** 可能带 **`PORTAL_PERMISSION_READ_UNAVAILABLE`**,**`verified: false`** 仍可能有可用 **`items[]`**。
|
|
97
|
+
- **`get`**:**`--dash-key`** 必填;默认 **`--being-draft`** 为草稿。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 2. 写:`apply` 两种模式(互斥)
|
|
102
|
+
|
|
103
|
+
**不可同时**出现 **`--dash-key`** 与 **`--package-id`**。
|
|
104
|
+
|
|
105
|
+
| 模式 | 必备参数 | 含义 |
|
|
106
|
+
|------|----------|------|
|
|
107
|
+
| **新建** | **`--package-id`** + **`--dash-name`** | **`--sections-file` 须非空**。 |
|
|
108
|
+
| **更新** | **`--dash-key`** | 不要带 **`package_id`**。 |
|
|
109
|
+
|
|
110
|
+
| 参数 | 说明 |
|
|
111
|
+
|------|------|
|
|
112
|
+
| **`--publish` / `--no-publish`** | 默认 **`--publish`**。仅 **`--no-publish`** 时不会调用发布接口;契约说明 **`publish=false` 不宣称线上已变**。 |
|
|
113
|
+
| **`--payload-file`** | 完整门户 JSON 对象;**标准字段写 `dash_name`**。新版 CLI 兼容 **`name -> dash_name`**、单页 **`pages[0].components -> sections`**,但 agent 默认不要依赖兼容别名。 |
|
|
114
|
+
| **`--sections-file`** | JSON **数组**;**全量替换**。省略时仅改基础信息,且 **`hide_copyright` / `dash_global_config` / `config`** 不能单独提交(**`PORTAL_SECTIONS_REQUIRED`**)。 |
|
|
115
|
+
| **`--layout-preset`** | 可选:**`auto` / `dashboard_2col` / `dashboard_3col`**。当区块未显式写 **`position`** 时由工具生成大屏布局。 |
|
|
116
|
+
| **`--visibility-file`** | 与 **`--auth-file`** 不能同时用。 |
|
|
117
|
+
| **`--icon`** / **`--color`** | 新建门户必须显式传合法的非 `template` 图标和颜色;候选用 `qingflow --json builder icon catalog`。编辑已有门户时省略则保留现状。 |
|
|
118
|
+
| **`--hide-copyright`** / **`--dash-global-config-file`** / **`--config-file`** | 见契约;部分键 **依赖与 `sections` 同批提交**。 |
|
|
119
|
+
|
|
120
|
+
**图标规则**:CLI 不按门户名自动猜图标;智能体需要自行选择业务贴合的 `icon + color`。读回结果里的 `icon_config` 可直接用于前端资源卡片展示。
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 3. `sections[]`:六类组件与回读 `type`
|
|
125
|
+
|
|
126
|
+
### 3.1 公共键
|
|
127
|
+
|
|
128
|
+
- **`title`**(必填)、**`source_type`**(必填,小写)、可选 **`position`**(**`pc`/`mobile`** 各 **`x,y,cols,rows`**;省略则由**实现自动排布**)。
|
|
129
|
+
- **`config`**、**`dash_style_config`**:按类型 Optional。默认只写 snake_case 规范键。
|
|
130
|
+
|
|
131
|
+
### 3.1.0 Payload 字段口径
|
|
132
|
+
|
|
133
|
+
推荐完整 payload 直接使用 CLI 标准键:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"dash_name": "产品研发数据大屏",
|
|
138
|
+
"package_id": 1414909,
|
|
139
|
+
"layout_preset": "dashboard_2col",
|
|
140
|
+
"pages": [
|
|
141
|
+
{
|
|
142
|
+
"title": "研发总览",
|
|
143
|
+
"components": [
|
|
144
|
+
{
|
|
145
|
+
"title": "部门分布",
|
|
146
|
+
"source_type": "chart",
|
|
147
|
+
"chart": {"chart_id": "CHART_ID"}
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`name` 只是兼容别名;如果遇到旧版 CLI 报 **`name Extra inputs are not permitted`**,不要反复重试,改成 **`dash_name`** 或升级 CLI。
|
|
156
|
+
|
|
157
|
+
### 3.1.1 布局硬规则:PC 24 栅格,mobile 6 栅格
|
|
158
|
+
|
|
159
|
+
**门户 PC 端不是 12 栅格,而是 24 栅格。**如果把两列写成 **`x=0/6, cols=6`**,所有组件只会占左半屏,工具会返回 **`PORTAL_LAYOUT_HALF_WIDTH`**。
|
|
160
|
+
|
|
161
|
+
推荐:
|
|
162
|
+
|
|
163
|
+
| 场景 | PC 写法 |
|
|
164
|
+
|------|---------|
|
|
165
|
+
| 不确定布局 | **省略 `position`**,或传 **`--layout-preset auto`** |
|
|
166
|
+
| 两列可视化图表 | **`x=0/12, cols=12`**,图表 **`rows >= 7`** |
|
|
167
|
+
| 三列可视化图表 | **`x=0/8/16, cols=8`**,图表 **`rows >= 7`** |
|
|
168
|
+
| 四个指标卡 | **`x=0/6/12/18, cols=6, rows=5`** |
|
|
169
|
+
| 具体数据视图 / 明细表 | 优先 **`cols=12`** 或 **`cols=24`**,视图 **`rows >= 11`** |
|
|
170
|
+
|
|
171
|
+
mobile 写法固定按 **6 栅格**:通常 **`x=0, cols=6`**。如果只写了 PC position,CLI 会自动补 mobile position,并返回 **`PORTAL_MOBILE_POSITION_MISSING`** 提醒。
|
|
172
|
+
|
|
173
|
+
图表卡片过小时会返回 **`PORTAL_CHART_CARD_TOO_SMALL`**;指标卡按 **`pc.cols >= 6, pc.rows >= 5`** 校验,普通可视化图表按 **`pc.cols >= 8, pc.rows >= 7`** 校验。指标区图表建议写 `role: "metric"`;此时必须使用 `target` / `indicator` 图表。若已有报表不匹配,用 `chart` 在门户 section 中声明缺失指标卡,不要把报表创建拆成独立主步骤。标准工作台数量也会进入 `layout_diagnostics.standard_template_counts`:指标卡推荐 4-6 个、BI 图表 2-3 个、业务视图 1-2 个,超出或不足会返回 `PORTAL_STANDARD_*_COUNT_OUT_OF_RANGE`。
|
|
174
|
+
|
|
175
|
+
#### 行布局数学规则(必须自检)
|
|
176
|
+
|
|
177
|
+
显式写 `position.pc` 时,先按相同 `y` 把组件分成行,再逐行校验:
|
|
178
|
+
|
|
179
|
+
- 同一行内所有组件 **`rows` 必须一致**;不要让 `rows=5` 的指标卡和 `rows=7` 的图表同处一个 `y`。
|
|
180
|
+
- 同一行内组件按 `x` 从小到大排列,**`cols` 总和默认必须等于 24**;除非用户明确要求留白,否则不要出现 `cols_sum=6/8/12` 的短行。
|
|
181
|
+
- 同一行内不要横向重叠:前一块的 `x + cols` 应等于后一块的 `x`。
|
|
182
|
+
- 下一行 `y` 必须等于上一行 `y + max(rows)`;不要产生竖向重叠或无意义空洞。
|
|
183
|
+
- 不允许孤立短行,例如单独一个 `x=0,y=9,cols=6,rows=5` 的指标卡。若只有一个组件占一行,应写 `cols=24`,或重排到完整行中。
|
|
184
|
+
- 在提交 `portal apply` 前,按 `y -> cols_sum/rows/titles` 自检一次;`portal apply` 当前可能不会阻断所有视觉错位,智能体不能仅依赖 `safe_for_display=true`。
|
|
185
|
+
|
|
186
|
+
### 3.1.2 推荐门户模板:业务工作台
|
|
187
|
+
|
|
188
|
+
默认按 **业务入口 → 核心指标 → BI 可视化 → 业务视图** 搭建。门户首屏应直接呈现可用工作台,不要做营销页、说明页或大面积装饰区。
|
|
189
|
+
|
|
190
|
+
| 区域 | 推荐组件 | PC 布局 | 要点 |
|
|
191
|
+
|------|----------|---------|------|
|
|
192
|
+
| 顶部业务入口 | **`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`,不要伪造;见下方边界说明。 |
|
|
193
|
+
| 核心指标 | **`chart`** 指标卡 + `role: "metric"` | 4 张:`x=0/6/12/18,y=4,cols=6,rows=5` | 指标卡推荐高度 **5**。24 栅格下单卡最小 `cols=6`,所以一行 4 张最稳。若业务给出 5 个指标,默认精选 4 个核心指标;确需展示 5 个时,补齐成平衡行(如扩展到 6 个,2 行 x 3 张,`cols=8,rows=5`),不要写 4+1 的孤立短行。 |
|
|
194
|
+
| 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 行。 |
|
|
195
|
+
| 业务数据视图 | **`view`** | `x=0/12,y=16,cols=12,rows=11`;或单表 `cols=24,rows=11` | 数据视图推荐高度 **11**,一行 1-2 个,1-2 行。只挂业务视图,不要创建或引用默认的 **全部数据 / 我的数据** 当主门户视图。 |
|
|
196
|
+
|
|
197
|
+
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` 开始。
|
|
198
|
+
|
|
199
|
+
**当前工具边界**:
|
|
200
|
+
|
|
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 门户写入链路时,才使用待办槽位。
|
|
203
|
+
- 推荐门户的可直接 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
|
+
- **[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
|
+
- `grid` 必须写 **`config.items[]`**;只写 `gridTitle` / `beingShowTitle` 会生成空入口容器,工具会返回 **`PORTAL_GRID_ITEMS_EMPTY`**。
|
|
206
|
+
|
|
207
|
+
**待办组件 raw 形状参考**(仅用于工具实现对齐,当前不要作为 `--sections-file` 输入):
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"type": 8,
|
|
212
|
+
"position": {
|
|
213
|
+
"pc": {"x": 12, "y": 0, "cols": 12, "rows": 4},
|
|
214
|
+
"mobile": {"x": 0, "y": 4, "cols": 6, "rows": 4}
|
|
215
|
+
},
|
|
216
|
+
"taskConfig": {
|
|
217
|
+
"beingShowTitle": true,
|
|
218
|
+
"componentTaskTitle": "待办",
|
|
219
|
+
"beingShowHint": true,
|
|
220
|
+
"componentTaskHint": "及时处理待办,可以有效提升流程效率",
|
|
221
|
+
"dashTaskConfigList": [
|
|
222
|
+
{"type": 1, "title": "all.taskTodo", "beingCheck": true, "ordinal": 0},
|
|
223
|
+
{"type": 2, "title": "all.taskTimeout", "beingCheck": true, "ordinal": 1},
|
|
224
|
+
{"type": 3, "title": "all.taskUpcomingTimeout", "beingCheck": true, "ordinal": 2},
|
|
225
|
+
{"type": 4, "title": "all.taskRemind", "beingCheck": true, "ordinal": 3}
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 3.2 `source_type` ↔ 回读 `components[].type`(搭建侧)
|
|
232
|
+
|
|
233
|
+
| `source_type` | 回读 `type`(数字) | 搭建侧含义 |
|
|
234
|
+
|---------------|---------------------|------------|
|
|
235
|
+
| **`chart`** | **9** | QingBI 图表块 |
|
|
236
|
+
| **`view`** | **10** | 应用视图块 |
|
|
237
|
+
| **`grid`** | **2** | 九宫格 |
|
|
238
|
+
| **`filter`** | **6** | 筛选条 |
|
|
239
|
+
| **`text`** | **5** | 富文本说明 |
|
|
240
|
+
| **`link`** | **4** | 外链 |
|
|
241
|
+
|
|
242
|
+
CLI 校验(`PortalSectionPatch`):**chart** 须 **`chart`** 或兼容旧字段 **`chart_ref`**;**view** 须 **`view_ref`**;**text** 须 **`text`**;**link** 须 **`url`**。**grid** / **filter** 无额外 ref,**`config` 形状由后端接受为准**。
|
|
243
|
+
|
|
244
|
+
### 3.3 **`chart`**:一个字段同时支持引用已有图表和内联创建图表
|
|
245
|
+
|
|
246
|
+
- 已有图表满足门户需求时,写 **`chart: {"chart_id": "..."}`**;兼容旧 **`chart_ref`**,但主示例不再使用。
|
|
247
|
+
- 没有合适图表时,写 **`chart: {"app_key", "name", "chart_type", ...}`**。CLI 会内部调用 QingBI 图表 apply,拿到 `chart_id` 后再写门户组件。
|
|
248
|
+
- 门户内联创建 QingBI 图表时,固定筛选写在 **`chart.filters`**,格式与 [60-charts.md](./60-charts.md) 一致。不要把图表固定筛选写成门户 `filter` 组件,也不要写成视图 `query_conditions`。
|
|
249
|
+
- `chart.filters` 支持 `eq`、`neq`、`in`、`contains`、`gte`、`lte`、`is_empty`、`not_empty`;示例见 [portal_sections_standard_workbench.example.json](../examples/portal/portal_sections_standard_workbench.example.json) 和 [match-rules.md](./reference/match-rules.md)。
|
|
250
|
+
|
|
251
|
+
`chart` 内联创建示例:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"title": "在制工单数",
|
|
256
|
+
"source_type": "chart",
|
|
257
|
+
"role": "metric",
|
|
258
|
+
"chart": {
|
|
259
|
+
"app_key": "PRODUCTION_ORDER_APP",
|
|
260
|
+
"name": "在制工单数",
|
|
261
|
+
"chart_type": "target",
|
|
262
|
+
"metric": "count(*)",
|
|
263
|
+
"filters": [
|
|
264
|
+
{"field_name": "状态", "operator": "eq", "value": "生产中"}
|
|
265
|
+
]
|
|
266
|
+
},
|
|
267
|
+
"position": {
|
|
268
|
+
"pc": {"x": 0, "y": 4, "cols": 6, "rows": 5},
|
|
269
|
+
"mobile": {"x": 0, "y": 4, "cols": 6, "rows": 5}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 3.4 **`filter`**:`config` **整包**即接口里的 **`filterConfig`**
|
|
275
|
+
|
|
276
|
+
实现:组件为 **`{"type": 6, "filterConfig": deepcopy(section.config)}`**。
|
|
277
|
+
|
|
278
|
+
- **理论上**与 solution 编译器一致:外层 **`{"filterConfig": [ … ], "graphList": [ … ]}`**;**`graphList`** 常含 **`graphType`**(如 **`CHART`**)、**`graphKey`** 或 **`graphRef`(`entity_id` / `chart_id`)** 等。
|
|
279
|
+
- **本环境 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`**。
|
|
280
|
+
**结论**:当前宜 **在搭建界面创建筛选条**,再 **`builder portal get` 反抓** 原始 `filterConfig` 形状;或向后端确认 **POST `/dash/{dashKey}`** 对 **`type: 6`** 的必填字段。**自动化不要默认认为 `filter` 已写入。**
|
|
281
|
+
- portal `filter` 组件仍按 raw `filterConfig` 处理,不纳入视图 / 报表 / 关联资源的统一筛选 DSL 主链路。
|
|
282
|
+
|
|
283
|
+
### 3.5 **`grid` / `text` / `link` / `view`**
|
|
284
|
+
|
|
285
|
+
- **grid**:**`config`** 并入 **`gridConfig`**;业务入口必须写 **`config.items[]`**。应用入口项推荐 `{ "type": 1, "jumpMode": 1, "linkAppKey": "APP_KEY", "linkFormType": 1, "title": "入口名" }`。空 `config` 或空 `items` 只会生成空入口容器,并触发 **`PORTAL_GRID_ITEMS_EMPTY`**。
|
|
286
|
+
- **text** / **link**:**`text`** / **`url`** 必填。
|
|
287
|
+
- **view**:**`view_ref`**;**`view_key`** 来自 **`builder app get views`**。
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 4. 前置数据
|
|
292
|
+
|
|
293
|
+
| 目的 | 命令 |
|
|
294
|
+
|------|------|
|
|
295
|
+
| **`package_id`** | **`builder app resolve --app-key …`** → **`package_ids`** |
|
|
296
|
+
| **`view_key`** | **`builder app get --app-key … views`** |
|
|
297
|
+
| **`chart_id`** | **`builder app get charts`**;缺失时在 portal section 写 **`chart`** 自动创建 |
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## 5. 新建最小例(`--no-publish`)
|
|
302
|
+
|
|
303
|
+
见上文 **§2** 与 **`visibility`** 最小对象;**`sections`** 可先用 **单块 `view`**。成功后拿 **`dash_key`** 再 **更新 / 发布**。
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 6. 更新与替换语义
|
|
308
|
+
|
|
309
|
+
- **`--dash-key`** + **`--sections-file`**:**列表即全量**;没写进去的区块会被拿掉。
|
|
310
|
+
- 仅改 **可见性 / 图标 / 分组**:**不传 `--sections-file`**,且不要单独带 **§2** 所列「仅在有 sections 时允许」的键。
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 7. 删除:`delete`
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
qingflow --json builder portal delete --dash-key "<DASH_KEY>" > tmp/builder_portal_delete.json
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
- **只按 `dash_key` 删除一个门户**;先用 `builder portal list/get` 确认目标,不要按名称猜。
|
|
321
|
+
- 返回成功时重点看:**`delete_executed`**、**`readback_status`**、**`safe_to_retry_delete`**、`summary.removed`。
|
|
322
|
+
- **`delete_executed=true` + `readback_status=deleted`**:删除已执行且回读确认不存在。
|
|
323
|
+
- **`delete_executed=true` + `readback_status=unavailable|still_exists`**:DELETE 已发出,但回读不可确认或短时间仍存在;**不要盲目重复删除**,稍后用 `builder portal get/list` 确认。
|
|
324
|
+
- DELETE 本身失败时才按 `status=failed` / `error_code` 处理。
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 8. **发布**(`--publish`)
|
|
329
|
+
|
|
330
|
+
- **默认会发布**:未显式 **`--no-publish`** 即 **`publish: true`**;公开入口仍是 **`portal_apply`**,发布动作由工具内部执行并回读 **`being_draft=false`**。
|
|
331
|
+
- **已发布线索**:成功路径上 **`published: true`**;**`live_result.publishStatus`** 常见 **`2`** 表示已发布(以你环境枚举为准)。
|
|
332
|
+
- **`partial_success` + `PORTAL_READBACK_PENDING`**:草稿/线上 **组件数量或元数据** 与「本次期望」不一致时会出现;**`PORTAL_*_VERIFICATION_INCOMPLETE`** 警告。应 **`builder portal get --dash-key …`**(草稿与 **`--no-being-draft` 线上**)**肉眼核对**区块是否齐全,而不是仅信 **`verified: true`**。
|
|
333
|
+
- **网关 503**:**与 CLI 无关**;环境恢复后重试 **`portal get` / `portal apply`**。(本轮在网关恢复后 **`portal apply` 已成功**。)
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 9. 本环境实测摘要
|
|
338
|
+
|
|
339
|
+
| 步骤 | 命令要点 | 结果 |
|
|
340
|
+
|------|-----------|------|
|
|
341
|
+
| 新建门户 | `--package-id 2030703`、`--dash-name "CLI门户探针_可删"`、`--no-publish`、单 **view** | **`dash_key`: `ecdcell64s02`** |
|
|
342
|
+
| 503 后重试 | **`--dash-key ecdcell64s02`、`--publish`** + 含 **filter** 的六类 **`sections-file`** | **`published: true`**;**`filter` 仍不落库** → **`partial_success`**,**`components expected 6, got 5`**(与 **§3.4** 一致) |
|
|
343
|
+
| **filter 专项** | 仅 **chart + filter** 两块的多种 **`graphList`/`graphRef`/`dashChartId`/`filterGroupConfig`** 组合 | **回读恒为 1 块(仅 `type: 9`)** |
|
|
344
|
+
| **稳定可复现** | **`--publish`** + **[portal_sections_five_types.example.json](../examples/portal/portal_sections_five_types.example.json)**(**grid / text / link / view / chart**) | **`status: success`**,**`types: [2,4,5,9,10]`**,**`published: true`** |
|
|
345
|
+
| 删除门户 | `builder portal delete --dash-key etcivtmv5402` | **`status: success`**,**`delete_executed: true`**,**`readback_status: deleted`**,**`summary.removed: 1`** |
|
|
346
|
+
|
|
347
|
+
**推荐工作台模板示例**:[portal_sections_standard_workbench.example.json](../examples/portal/portal_sections_standard_workbench.example.json)。正式业务门户优先复制这个文件的行布局。
|
|
348
|
+
|
|
349
|
+
**组件探针示例**:[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)。它们用于验证组件形状和后端边界,不作为业务门户视觉布局模板;其中 `filter` 是否落库视环境/后端而定。
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 10. 排障
|
|
354
|
+
|
|
355
|
+
| 现象 | 处理 |
|
|
356
|
+
|------|------|
|
|
357
|
+
| `portal apply accepts exactly one selector mode` | **`dash-key`** vs **`package-id`** 二选一。 |
|
|
358
|
+
| `PORTAL_READBACK_PENDING` / **`components expected N, got M`** | **`portal get`** 数组件;若多写了 **`filter`** 而回读少一块,见 **§3.4**(**CLI 写 filter 可能整体不生效**);也可能是 **异步回读**,可再 **`get`** 一次。 |
|
|
359
|
+
| **`published: true` 但 `verified: false`** | 读 **§7**;用 **`get` 草稿+线上**对照。 |
|
|
360
|
+
| **503** | 网关/运维;稍后重试。 |
|
|
361
|
+
| 缺 **chart** | 在对应 portal section 写 **`chart`**;或换用已有报表的 **`chart: {"chart_id": "..."}`** / 兼容旧 **`chart_ref`**。 |
|
|
362
|
+
| **VISIBILITY_CONFLICT** | 只用 **`--visibility-file`**。 |
|
|
363
|
+
| `delete_executed=true` 但 `readback_status=unavailable|still_exists` | DELETE 已发出,回读未确认;不要重复删除,稍后 `builder portal get/list` 复核。 |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## 11. 交叉引用
|
|
368
|
+
|
|
369
|
+
- [SKILL.md](../../SKILL.md)
|
|
370
|
+
- [reference/app-delivery-sop.md](./reference/app-delivery-sop.md)
|
|
371
|
+
- [50-views.md](./50-views.md)
|
|
372
|
+
- [QINGFLOW_CLI_EXPLORATION_REPORT.md](../core/QINGFLOW_CLI_EXPLORATION_REPORT.md)
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Builder Buttons And Associated Resources
|
|
2
|
+
|
|
3
|
+
Read this when the task mentions advanced custom button maintenance, deleting button bodies, cross-view button reuse, complex qRobot/wings buttons, associated views, associated reports, or current-record context matching.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
Responsible for: `builder button apply`, `builder associated-resource apply`, advanced view button placement maintenance, associated view/report display config, `match_mappings`, and button add-data mappings.
|
|
8
|
+
|
|
9
|
+
Not responsible for: ordinary business buttons declared while creating or patching a view. For normal cases, write `action_buttons` inside `builder views apply`; see [50-views.md](./50-views.md).
|
|
10
|
+
|
|
11
|
+
## Main chain
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
app get -> app get views/charts/buttons/associated resources -> apply button or associated-resource -> readback
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Demo files
|
|
18
|
+
|
|
19
|
+
| Scenario | Example |
|
|
20
|
+
|----------|---------|
|
|
21
|
+
| Associated views/reports with current-record matching | [associated_resources_semantic_full.example.json](../examples/associated/associated_resources_semantic_full.example.json) |
|
|
22
|
+
| Advanced standalone button maintenance | [custom_buttons_advanced.example.json](../examples/buttons/custom_buttons_advanced.example.json) |
|
|
23
|
+
|
|
24
|
+
## Custom buttons
|
|
25
|
+
|
|
26
|
+
- For normal view-level business actions, prefer `builder views apply` with `action_buttons`.
|
|
27
|
+
- Use this standalone button tool for advanced cases: deleting button bodies, reusing the same button across many views, bulk reordering bindings, changing style independently, or configuring qRobot/wings when the user provides exact config.
|
|
28
|
+
- Use `upsert_buttons` for create/update and `patch_buttons` for small changes.
|
|
29
|
+
- Use `view_configs` only after reading target raw `view_key`.
|
|
30
|
+
- Use semantic conditions from [reference/match-rules.md](./reference/match-rules.md). Fixed filters use `field_name + operator + value/values`; associated-resource context matching uses `target_field + operator + source_field/value`.
|
|
31
|
+
- For add-data button field mappings, use target/source semantics, not raw backend ids, unless a contract explicitly requires ids.
|
|
32
|
+
- If `button apply` returns `CUSTOM_BUTTON_APPLY_PARTIAL` / `VIEW_CUSTOM_BUTTON_READBACK_PENDING` while `custom_buttons_verified=true`, do not recreate the button. Run `builder app get --app-key APP views` and inspect the target view `buttons[]` for `button_type=CUSTOM` plus the expected `button_text` or `button_id`. Only reapply `view_configs` if the view binding is actually absent.
|
|
33
|
+
|
|
34
|
+
Start from user intent:
|
|
35
|
+
|
|
36
|
+
- Current record creates a downstream/related record -> `addData` / `add_data`, usually `detail` or `list`, with `target_app_key + field_mappings`.
|
|
37
|
+
- Global independent entry -> `addData` / `add_data` on `header`, without current-record `source_field`.
|
|
38
|
+
- Open a URL, SOP, or help page -> `link` with URL.
|
|
39
|
+
- Approve, reject, close, or change status -> do not invent a normal button; model workflow/task action or use exact existing automation config.
|
|
40
|
+
- Existing automation/agent -> `qRobot` / `wings` only when the user provides the exact config.
|
|
41
|
+
|
|
42
|
+
### Choose the button path
|
|
43
|
+
|
|
44
|
+
| Need | Preferred path |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| Create or patch a normal business button on one view | `builder views apply` with `action_buttons` |
|
|
47
|
+
| Set style, icon, cross-view reuse, remove button body, reorder bindings | `builder button apply` |
|
|
48
|
+
| Add qRobot/wings behavior | `builder button apply`, only with user-provided exact config |
|
|
49
|
+
| Clear a view's custom button bindings | `builder button apply` with `view_configs[].mode="replace"` and `buttons: []` |
|
|
50
|
+
|
|
51
|
+
### Choose the action
|
|
52
|
+
|
|
53
|
+
| Standalone `trigger_action` | View `action_buttons.action` | Use for | Required inputs | Avoid |
|
|
54
|
+
| --- | --- | --- | --- | --- |
|
|
55
|
+
| `addData` | `add_data` | Create a related/downstream Qingflow record from the current record: acceptance from order, worklog from work order, payment request from purchase order, follow-up from customer | `trigger_add_data_config.target_app_key`; usually `field_mappings: [{"source_field": "数据ID", "target_field": "关联源记录"}]`; optional `default_values` | Do not use without a real target app and compatible relation/reference field |
|
|
56
|
+
| `link` | `link` | Open an external system, help document, SOP, or fixed URL | `trigger_link_url` in standalone mode; `url` in view `action_buttons` | Do not use as a fake workflow/status/approval action |
|
|
57
|
+
| `qRobot` | `qRobot` | Trigger an existing Qingflow robot/automation | User-provided robot/config payload | Do not invent ids, parameters, or automation behavior |
|
|
58
|
+
| `wings` | `wings` | Trigger an existing Wings/agent/external capability | User-provided Wings/config payload | Do not use as the default button type |
|
|
59
|
+
|
|
60
|
+
Status transition or approval is not a generic custom-button action by itself. Use `addData` only if the action really creates a downstream record. Use `qRobot` / `wings` only when the automation already exists and the user supplies the configuration.
|
|
61
|
+
|
|
62
|
+
### Choose the placement
|
|
63
|
+
|
|
64
|
+
| `placement` | Frontend position | Best use | Avoid |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| `header` | View header | Global actions that do not depend on one current row: open SOP, create an independent record, global entrance | Current-record `field_mappings` |
|
|
67
|
+
| `list` | Row/list button, backend `INSIDE` | Row-level actions that depend on the current record | Actions that need a detail-page review before execution |
|
|
68
|
+
| `detail` | Record detail page | Current-record context actions; safest place for add-data buttons | High-frequency bulk actions |
|
|
69
|
+
|
|
70
|
+
View-type guidance:
|
|
71
|
+
|
|
72
|
+
- `table`: supports `header`, `list`, and `detail`; use it as the default view type for operational buttons.
|
|
73
|
+
- `board`: only add state-specific buttons and always configure `button_limit` / `visible_when`.
|
|
74
|
+
- `card`: prefer `detail`; use `list` only when the card-level action is obvious.
|
|
75
|
+
- `gantt`: prefer `header` or `detail`; avoid row/list buttons unless the user explicitly asks.
|
|
76
|
+
|
|
77
|
+
### Choose the style
|
|
78
|
+
|
|
79
|
+
| `style_preset` | Use for |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `primary_blue` | Main positive action on the view, usually one per view |
|
|
82
|
+
| `text_blue` | Low-weight link or secondary row action |
|
|
83
|
+
| `secondary_gray` | Informational or low-priority action |
|
|
84
|
+
| `neutral_outline` | Related-record creation that should not dominate the page |
|
|
85
|
+
| `warning_orange` | Attention/risk action that is not destructive |
|
|
86
|
+
| `danger_red` | Destructive or high-risk action; avoid unless the user explicitly wants it |
|
|
87
|
+
|
|
88
|
+
Do not make every button primary or danger. If the user did not ask for custom style, prefer view-level `action_buttons` and let the tool choose defaults.
|
|
89
|
+
|
|
90
|
+
Standalone example:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"upsert_buttons": [
|
|
95
|
+
{
|
|
96
|
+
"client_key": "create_acceptance",
|
|
97
|
+
"button_text": "创建验收单",
|
|
98
|
+
"style_preset": "primary_blue",
|
|
99
|
+
"trigger_action": "addData",
|
|
100
|
+
"trigger_add_data_config": {
|
|
101
|
+
"target_app_key": "ARRIVAL_APP",
|
|
102
|
+
"field_mappings": [
|
|
103
|
+
{"source_field": "数据ID", "target_field": "关联工单"}
|
|
104
|
+
],
|
|
105
|
+
"default_values": {"状态": "待验收"}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"view_configs": [
|
|
110
|
+
{
|
|
111
|
+
"view_key": "RAW_VIEW_KEY",
|
|
112
|
+
"mode": "merge",
|
|
113
|
+
"buttons": [
|
|
114
|
+
{
|
|
115
|
+
"button_ref": "create_acceptance",
|
|
116
|
+
"placement": "detail",
|
|
117
|
+
"button_limit": [
|
|
118
|
+
[{"field_name": "状态", "operator": "eq", "value": "已完工"}]
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Associated views and reports
|
|
128
|
+
|
|
129
|
+
- Manage the app-level resource pool and view detail display through `associated-resource apply`.
|
|
130
|
+
- Use associated resources only after the target view/report already exists. This tool attaches and filters existing resources; it does not create view bodies or QingBI report configs.
|
|
131
|
+
- Current-record matching belongs here, not in view `filters` or `query_conditions`.
|
|
132
|
+
- For current-record filtering, use `match_mappings`:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"target_field": "关联客户",
|
|
137
|
+
"operator": "eq",
|
|
138
|
+
"source_field": "数据ID"
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- Static filters can use `target_field + operator + value`.
|
|
143
|
+
- Dynamic current-record filters use `source_field`; static filters use `value`. Do not put both in the same mapping.
|
|
144
|
+
- `operator` / `value` follows the same public semantics as view and QingBI filters. Option fields accept option labels or option ids; member/department/relation static values should be unique, and id or `{id,value}` is safest when names may duplicate.
|
|
145
|
+
- Do not mix semantic `match_mappings` with raw `match_rules` in the same resource.
|
|
146
|
+
- Dataset BI reports can only be associated after they already exist; `charts apply` creates application-source QingBI reports.
|
|
147
|
+
|
|
148
|
+
Detailed compatibility rules are in [reference/match-rules.md](./reference/match-rules.md). The older full delivery notes are in [reference/app-delivery-sop.md](./reference/app-delivery-sop.md).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Builder Workflow
|
|
2
|
+
|
|
3
|
+
Read this when the task is about approval/fill/copy/webhook workflow configuration or workflow repair.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
Responsible for: `builder flow get/schema/apply`, WorkflowSpec, `patch_nodes`, assignees, editable fields, and workflow readback.
|
|
8
|
+
|
|
9
|
+
Not responsible for: guessing raw backend fields without first reading `builder flow schema` / `builder flow get`.
|
|
10
|
+
|
|
11
|
+
## Main chain
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
contract -> app get fields -> builder flow schema -> builder flow get -> member/role lookup -> build WorkflowSpec -> flow apply --spec-file -> builder flow get readback
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Demo/reference files
|
|
18
|
+
|
|
19
|
+
Workflow examples depend on live `builder flow schema`, field ids, role ids, and member ids. Use [workflow/README.md](./workflow/README.md) as the staged guide and [workflow/workflow-schema.json](./workflow/workflow-schema.json) for schema validation; do not copy a static flow spec without replacing live ids from the target app/workspace.
|
|
20
|
+
|
|
21
|
+
## Recommended write path
|
|
22
|
+
|
|
23
|
+
- Before applying a workflow, verify the app has an explicit business status select field such as `状态`, `处理状态`, `审批状态`, `工单状态`, `计划状态`, `报工状态`, or `单据状态`. Domain result fields are not enough by themselves: for example, `检验结论` should be paired with `处理状态`.
|
|
24
|
+
- For workflow creation or replacement, always use `builder flow get` / `builder flow schema`, then submit a complete WorkflowSpec with `--spec-file`.
|
|
25
|
+
- Do not use `--nodes-file` + `--transitions-file` in skill-led workflow builds. Even simple linear workflows should be represented as WorkflowSpec.
|
|
26
|
+
- Use `patch_nodes[]` only for targeted maintenance of existing nodes. Node ids come from `builder flow get` readback.
|
|
27
|
+
- Do not mix `patch_nodes` and full `spec` in the same call.
|
|
28
|
+
|
|
29
|
+
## Input modes
|
|
30
|
+
|
|
31
|
+
All workflow creation and replacement uses WorkflowSpec through `--spec-file`. Existing-node maintenance can use `--patch-nodes-file` after readback. This is the only skill-led workflow write path for linear, branching, Q-Robot, approval, filling, and cc flows.
|
|
32
|
+
|
|
33
|
+
## Detailed workflow docs
|
|
34
|
+
|
|
35
|
+
Use [workflow/README.md](./workflow/README.md) for full staged workflow modeling and [workflow/workflow-schema.json](./workflow/workflow-schema.json) for schema validation.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Builder Publish And Readback Verification
|
|
2
|
+
|
|
3
|
+
Read this before reporting a builder task as finished.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
Responsible for: `builder publish verify`, readback-before-retry, partial success interpretation, and final user-facing completion wording.
|
|
8
|
+
|
|
9
|
+
Not responsible for: replacing resource-specific verification. Views, charts, portal, workflow, buttons, and associated resources still need their own apply/readback checks.
|
|
10
|
+
|
|
11
|
+
## Main chain
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
apply result -> resource readback -> publish verify when app resources changed -> final status
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Readback-before-retry rule
|
|
18
|
+
|
|
19
|
+
If a write returns any of these, do not immediately replay the same write:
|
|
20
|
+
|
|
21
|
+
- timeout
|
|
22
|
+
- `partial_success`
|
|
23
|
+
- `write_executed=true`
|
|
24
|
+
- `safe_to_retry=false`
|
|
25
|
+
- readback unavailable
|
|
26
|
+
- backend readback 40002 after a write
|
|
27
|
+
- `VIEW_CUSTOM_BUTTON_READBACK_PENDING` after `custom_buttons_verified=true`
|
|
28
|
+
|
|
29
|
+
Next action:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
package get / app resolve / app get fields|layout|views|charts / portal get / publish verify
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then patch only the missing or mismatched resources.
|
|
36
|
+
|
|
37
|
+
For custom button view binding, verify through `builder app get ... views` before retrying: if the target view already shows a `CUSTOM` button with the expected text/id, treat the write as successful with delayed readback, not as a failed button creation.
|
|
38
|
+
|
|
39
|
+
## Final status decision table
|
|
40
|
+
|
|
41
|
+
Use this table before retrying or reporting to the user.
|
|
42
|
+
|
|
43
|
+
| Evidence | Meaning | Next action | User-facing wording |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| `status=success` and resource readback matches | Write and verification succeeded | Publish verify if the resource needs publish | "已成功,已回读验证" |
|
|
46
|
+
| `partial_success` plus `write_executed=true`, `safe_to_retry=false`, timeout, or readback unavailable | Write may have landed; verification is incomplete | Read back first, then patch only missing/mismatched parts | "写入已发出,回读未完全确认" |
|
|
47
|
+
| Validation/contract error before write, or `write_executed=false` | Write did not execute | Fix payload and retry the same resource only | "失败,原因是入参/契约错误" |
|
|
48
|
+
| Backend readback returns 40002/404/timeout after a write | Verification is blocked or delayed; not proof of write failure | Read package/app/portal inventory through the normal get path | "写入结果待确认,不能直接判定失败" |
|
|
49
|
+
| A workflow/chart/relation/portal reference required by the user request or by another created resource is missing | Build is incomplete | Create or patch the missing required resource | "部分完成,仍缺少关键资源" |
|
|
50
|
+
| Frontend visibility or publish status was not verified | Backend write may be done, but live visibility is unknown | Run publish verify or portal/app readback | "是否前端可见未确认" |
|
|
51
|
+
|
|
52
|
+
Short rule: **write result answers whether the write was attempted; readback answers what exists; publish/portal verification answers whether the user can see it.**
|
|
53
|
+
|
|
54
|
+
## Final report requirements
|
|
55
|
+
|
|
56
|
+
Always state:
|
|
57
|
+
|
|
58
|
+
- whether the intended write appears successful;
|
|
59
|
+
- which path made it successful;
|
|
60
|
+
- what is verified as front-end visible or published;
|
|
61
|
+
- what remains unverified or incomplete;
|
|
62
|
+
- whether further repair is needed.
|
|
63
|
+
|
|
64
|
+
Do not report "全部完成" when resources required by the user request, dependent charts, relations, portal references, or readback checks are missing. If workflow was not requested and not clearly required, say "workflow not requested/not configured" instead of treating it as a missing resource.
|