@qingflow-tech/qingflow-cli 1.1.50-beta.5 → 1.1.51

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 (110) hide show
  1. package/README.md +4 -4
  2. package/npm/lib/runtime.mjs +13 -29
  3. package/package.json +1 -1
  4. package/pyproject.toml +2 -8
  5. package/skills/qingflow-cli/SKILL.md +322 -93
  6. package/skills/qingflow-cli/manifest.yaml +1 -1
  7. package/skills/qingflow-cli/reference/00-INDEX.md +4 -4
  8. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  9. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +9 -3
  10. package/skills/qingflow-cli/reference/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +137 -3
  11. package/skills/qingflow-cli/reference/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
  12. package/skills/qingflow-cli/reference/QINGFLOW_CLI_FIELD_DATA_TYPES.md +14 -14
  13. package/skills/qingflow-cli/reference/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
  14. package/skills/qingflow-cli/reference/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
  15. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +12 -7
  16. package/skills/qingflow-cli/reference/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
  17. package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +2 -3
  18. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +5 -9
  19. package/skills/qingflow-cli/reference/builder/50-views.md +191 -192
  20. package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +0 -2
  21. package/skills/qingflow-cli/reference/builder/README.md +1 -1
  22. package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +6 -6
  23. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +1 -1
  24. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +95 -76
  25. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +4 -6
  26. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +13 -13
  27. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +19 -20
  28. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +14 -18
  29. package/skills/qingflow-cli/reference/examples/README.md +1 -1
  30. package/skills/qingflow-cli/reference/examples/views/views_batch_full.example.json +159 -0
  31. package/skills/qingflow-cli/reference/examples/views/views_upsert_table_minimal.example.json +36 -30
  32. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +1 -2
  33. package/skills/qingflow-cli/reference/record/analysis/README.md +113 -21
  34. package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +10 -10
  35. package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +9 -9
  36. package/skills/qingflow-cli/reference/record/analysis/business-context.md +1 -1
  37. package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +10 -10
  38. package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +80 -52
  39. package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +2 -2
  40. package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +42 -0
  41. package/skills/qingflow-common/SKILL.md +4 -7
  42. package/src/qingflow_mcp/__init__.py +1 -1
  43. package/src/qingflow_mcp/app_form_compat.py +0 -3
  44. package/src/qingflow_mcp/app_form_validator.py +17 -69
  45. package/src/qingflow_mcp/builder_facade/app_form.py +100 -497
  46. package/src/qingflow_mcp/builder_facade/models.py +17 -227
  47. package/src/qingflow_mcp/builder_facade/schemas/app_form/manifest.json +0 -1
  48. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/complete.json +30 -64
  49. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/address.json +8 -4
  50. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/amount.json +8 -4
  51. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/attachment.json +10 -6
  52. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/code_block.json +10 -6
  53. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/data_relation.json +18 -11
  54. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/date.json +8 -4
  55. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/datetime.json +8 -4
  56. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/department.json +10 -6
  57. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/email.json +8 -4
  58. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/link.json +8 -4
  59. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/long_text.json +8 -4
  60. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/member.json +10 -6
  61. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/multi_select.json +8 -4
  62. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/number.json +8 -4
  63. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/phone.json +8 -4
  64. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/q_linker.json +10 -6
  65. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/relation.json +15 -46
  66. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_choice.json +8 -4
  67. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/single_select.json +8 -4
  68. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/subtable.json +27 -61
  69. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/text.json +8 -4
  70. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/formula.json +0 -43
  71. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/summary.json +12 -7
  72. package/src/qingflow_mcp/builder_facade/service.py +539 -1671
  73. package/src/qingflow_mcp/builder_facade/workflow_spec.py +1 -1
  74. package/src/qingflow_mcp/cli/commands/__init__.py +1 -2
  75. package/src/qingflow_mcp/cli/commands/builder.py +55 -76
  76. package/src/qingflow_mcp/cli/commands/record.py +1 -1
  77. package/src/qingflow_mcp/cli/context.py +0 -3
  78. package/src/qingflow_mcp/cli/formatters.py +1 -97
  79. package/src/qingflow_mcp/config.py +1 -0
  80. package/src/qingflow_mcp/public_surface.py +0 -8
  81. package/src/qingflow_mcp/response_trim.py +2 -11
  82. package/src/qingflow_mcp/server.py +0 -2
  83. package/src/qingflow_mcp/server_app_builder.py +10 -34
  84. package/src/qingflow_mcp/server_app_user.py +0 -4
  85. package/src/qingflow_mcp/solution/compiler/view_compiler.py +1 -2
  86. package/src/qingflow_mcp/solution/executor.py +8 -96
  87. package/src/qingflow_mcp/solution/spec_models.py +0 -1
  88. package/src/qingflow_mcp/tools/ai_builder_tools.py +398 -218
  89. package/src/qingflow_mcp/tools/base.py +42 -10
  90. package/src/qingflow_mcp/tools/record_tools.py +46 -11
  91. package/src/qingflow_mcp/tools/solution_tools.py +0 -2
  92. package/src/qingflow_mcp/tools/view_tools.py +6 -0
  93. package/skills/qingflow-cli/reference/data/README.md +0 -32
  94. package/skills/qingflow-cli/reference/examples/views/views_apply_v1alpha1.example.json +0 -14
  95. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_SPECIALIZED_WORKFLOW.md +0 -50
  96. package/src/qingflow_mcp/builder_facade/schemas/app_form/v1alpha1/fields/rich_text.json +0 -146
  97. package/src/qingflow_mcp/builder_facade/schemas/views/manifest.json +0 -42
  98. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/complete.json +0 -1245
  99. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/button-config.json +0 -53
  100. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/data-permission.json +0 -60
  101. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/display.json +0 -73
  102. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/operation-permission.json +0 -48
  103. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/details/query-condition.json +0 -47
  104. package/src/qingflow_mcp/builder_facade/schemas/views/v1alpha1/summary.json +0 -319
  105. package/src/qingflow_mcp/builder_facade/views_extract.py +0 -592
  106. package/src/qingflow_mcp/builder_facade/views_schema.py +0 -400
  107. package/src/qingflow_mcp/cli/commands/data.py +0 -134
  108. package/src/qingflow_mcp/tools/csv_export.py +0 -168
  109. package/src/qingflow_mcp/tools/data_tools.py +0 -284
  110. package/src/qingflow_mcp/tools/view_writer.py +0 -44
@@ -1,53 +1,38 @@
1
1
  # Builder Views
2
2
 
3
- Read this when the task is about table/card/board/gantt/hierarchy/calendar views, fixed filters, query panels, view sorting, view data permissions, associated report/view display on a view, or repairing existing views.
3
+ Read this when the task is about table/card/board/gantt views, fixed filters, query panels, view sorting, associated report/view display on a view, or repairing existing views.
4
4
 
5
5
  ## Scope
6
6
 
7
- Responsible for: `builder views apply --app-key APP_KEY --view-file PATH` (the **only** creation entry), one view declaration, `columns`, `filters`, `query_conditions`, `action_buttons`, and view readback.
7
+ Responsible for: `builder views apply --views-file`, top-level `views[]`, `operation`, `columns`, `filters`, `query_conditions`, `action_buttons`, and view readback.
8
8
 
9
9
  Not responsible for: creating associated report resources or maintaining custom button bodies outside the view design. New business views must include `query_conditions`; ordinary business shortcut buttons are required and are declared only through `action_buttons` on the target view.
10
10
 
11
11
  ## Main chain
12
12
 
13
13
  ```text
14
- app get -> app get fields/views -> views schema -> prepare one view -> views validate -> views apply -> app get/views readback
14
+ app get -> app get fields/views -> views apply with required query_conditions and list/detail action_buttons -> app get/views readback
15
15
  ```
16
16
 
17
- ## 版本与 schema(views v1alpha1)
18
-
19
- 视图声明是**版本化契约**(`apiVersion: builder.qingflow.com/v1alpha1`)。`builder views apply` 是视图创建的**唯一入口**(旧命令式 `view_create` 已删除;不要再寻找或使用任何“直接创建视图”的命令/工具)。
20
-
21
- - **两级 schema**:**summary**(最简版:类型/名称/数据展示内容 + `data_permission` 数据权限形状)与 **complete**(完整版:visibility 可见性授权、`filters`、`sort`、`query_conditions`、`action_buttons`/`buttons`、`associated_resources`、`card`/`gantt`/`hierarchy`/`calendar` 类型专属配置、`display`/`record`/`share`)。字段级定义逐字段带 `x-backend` 后端映射。
22
- - **读 schema**:`qingflow --json builder views schema` 默认返回 `v1alpha1/summary.json`;需要完整可写配置时显式传 `--schema-kind complete`。MCP 对应 `app_views_schema`。
23
- - **Schema-first 写入**:先用 `builder views schema --schema-version VERSION --schema-kind complete` 读取完整 schema;将相同版本显式传给 `validate --schema-version VERSION` 和 `apply --schema-version VERSION`。`validate` 也可从声明信封读取 `schema_version`,但推荐显式传版本;apply 的版本校验必须用 `--schema-version`。`validate` 接受一个直接视图声明对象,不接受 `upsert_view` 包装或批量 envelope。
24
- - **说明字段**:视图 Schema 使用语义化的 `*Description` 自定义 key(如 `dataPermissionDescription`)承载说明,加载和引用展开时原样保留;读取说明的工具应识别这些 key。标准校验器忽略这些自定义字段,仍按 `type`、`enum`、`required` 等关键字校验;`default` 是标准注解,不会自动填值。`*Description` 不是提交视图声明时的业务字段。
25
- - **离线校验**:`qingflow --json builder views validate --file PATH`(`-` 支持 stdin),不访问后端;返回 `ok`/`issues[]`(带 JSON pointer path)。
26
- - **读 canonical 声明**:`qingflow --json builder views get --app-key APP --schema-version VERSION --schema-kind summary`,返回指定版本的 summary 声明数组(字段名反解);完整可写配置用 `--schema-kind complete` 并检查 `config_read_errors[].gaps`。
27
- - **完整声明的提取边界**:`views get --schema-kind complete` 优先读取 `buttonConfigVO` 中的完整按钮绑定。公式过滤、无法解析的过滤规则或按钮 ID 会使该视图返回 `VIEW_NOT_EXTRACTABLE`(见 `details.config_read_errors[].gaps`),不会生成删减后的可写声明。修改这类视图的其他属性应使用局部 patch。更新现有视图时,已配置的系统字段原样保留,不补默认值、不重算序号;读接口生成的未配置占位对象不会写回,不会因此新增系统字段配置。
28
- - **版本协商**:apply 显式传 `--schema-version v1alpha1` 时启用版本化校验:非法声明返回 `INVALID_SPEC` 且**不写**;响应信封回显 `schemaVersion`。apply 不传时行为与旧版一致(别名宽容,零破坏)。
29
- - **公开视图类型**:summary 与 complete 均支持 `table`、`card`、`board`、`gantt`、`hierarchy`、`calendar`。层级视图须提供 `hierarchy: {title_que_id, children_que_id}`;日历视图须提供 `calendar: {title_que_id, date_que_id}`,可选 `color_que_id`。日历 `date_que_id` 可引用表单日期字段,也可用系统字段 `2`(申请时间)或 `3`(更新时间)。
30
- - **complete 档配置速览**:`data_permission`(`{type: config|custom, scope: all|oneself|dept|subordinate|custom}`;`scope=custom` 的规则明细写 `filters`);`sort`(`[{que_id, ascending}]`,空数组=恢复默认排序);`hierarchy`(可选 `root_filter`);`card`/`gantt`/`calendar`/`display`/`record`/`share` 配置组。
31
-
32
17
  ## Update existing views
33
18
 
34
- - Prefer `--patch-views-file` for small changes to an existing view.
19
+ - Prefer `views[].operation="patch"` for small changes to an existing view.
35
20
  - Use raw `view_key` from `app_get.views[].view_key`; do not use record-data `custom:<view_key>` prefixes.
36
- - Do not send a partial `--view-file` object to update a complex existing view; use `--patch-views-file` with `set`.
21
+ - Do not send a partial `upsert` object to update a complex existing view; use `operation="patch"` with `set`.
37
22
  - Verify filters, query conditions, and associated resources separately before reporting success.
38
23
 
39
24
  ## Detailed contract notes
40
25
 
41
- 稳定命令:**`qingflow builder views apply --app-key APP_KEY --view-file PATH`**(别名 **`qingflow build views apply`**)。`--view-file` 是一个直接的 JSON 对象,只声明一个新建或完整更新的视图。
26
+ 稳定命令:**`qingflow builder views apply --views-file`**(别名 **`qingflow build views apply`**)。编写前已结合 **builder 契约**与实现要点整理;**标准 `views[]` 文件**见 **[views_upsert_table_minimal.example.json](../examples/views/views_upsert_table_minimal.example.json)**(与门户/报表 **`.example.json`** 同风格,已包含必需的查询面板、列表快捷按钮和详情快捷按钮)。
42
27
 
43
28
  > **权限**:视图**新建**走后端 `createViewgraphConfig`,需要同时满足 **视图管理 / ViewManagementAuth**(`beingViewManageStatus`)和 **数据管理 / DataManageAuth**;视图**更新/删除**只走 **ViewManagementAuth**。未开启高级应用权限时 `beingViewManageStatus` 等价回落到 **DataManageAuth**。失败时常见 **40002 / 40161 / 编辑锁**,参见主技能与 **ADMIN** 速查。
44
29
 
45
- > **默认系统视图**:`全部数据`、`我的数据`、`我发起的`、`待办`、`已办`、`抄送` 等由轻流自带,**不要新建同名业务视图**。新建视图必须用业务名,例如 `项目台账视图`、`客户跟进视图`、`逾期任务看板`。如果确实要调整默认系统视图,只能从 `app get views` 取已存在的 raw **`view_key`** 后通过 `--patch-views-file` 更新。
30
+ > **默认系统视图**:`全部数据`、`我的数据`、`我发起的`、`待办`、`已办`、`抄送` 等由轻流自带,**不要新建同名业务视图**。新建视图必须用业务名,例如 `项目台账视图`、`客户跟进视图`、`逾期任务看板`。如果确实要调整默认系统视图,只能从 `app get views` 取已存在的 raw **`view_key`** 后用 `views[].operation="patch"` 更新。
46
31
 
47
32
  > **契约**(权威键名、枚举、`execution_notes`、示例):
48
33
  > `qingflow --json builder contract --tool-name app_views_apply`
49
34
  > (`--tool-name` 为契约索引,用于拉取 **`allowed_keys` / 别名 / 示例**。)
50
- > 契约示例若带 `"profile"` 或 `"app_key"`,不要复制到 `--view-file`;CLI 分别用根级 `qingflow --profile …` 和 `--app-key` 指定。
35
+ > 契约示例若带 `"profile"`,不要复制到 `--views-file`;CLI 指定 profile 用根级 `qingflow --profile …`。
51
36
 
52
37
  ---
53
38
 
@@ -57,11 +42,10 @@ app get -> app get fields/views -> views schema -> prepare one view -> views val
57
42
  |------|------|-----|
58
43
  | ① 读应用地图 | 先看 compact views/charts/buttons/associated resources | `qingflow --json builder app get --app-key <APP_KEY>` |
59
44
  | ② 读字段/视图 | 确认 **`columns`** / `query_conditions.rows` 可用字段、核对 **`view_key`** | `qingflow --json builder app get --app-key <APP_KEY> fields` / `qingflow --json builder app get --app-key <APP_KEY> views` |
60
- | ③ 读取 schema | 固定版本;按需求读取 summary 或 complete | `qingflow --json builder views schema --schema-version v1alpha1 --schema-kind complete` |
61
- | ④ 准备并校验声明 | 新建或完整更新写一个视图对象;先离线校验;局部修改写单项 patch | `qingflow --json builder views validate --file PATH --schema-version v1alpha1` |
62
- | ⑤ 应用视图操作 | 将同一版本传给 apply;一次只提交一个视图操作 | `qingflow builder views apply --app-key … --view-file PATH --schema-version v1alpha1` |
63
- | ⑥ 配置查询面板和快捷按钮 | 新建业务视图必须写 `query_conditions` 和 `action_buttons`,按钮同时覆盖 `list` 和 `detail` 位置 | `builder views apply` |
64
- | ⑦ 需要上线时 | 发布侧校验 | `qingflow builder publish verify --app-key …` |
45
+ | ③ 准备补丁 JSON | 写入一个 **`{"views":[...]}`** 文件,每个 view item 自带 `operation` 和 `app_key` | — |
46
+ | ④ 应用视图补丁 | 执行 apply | `qingflow builder views apply …`(写入命令自动 JSON,默认直接 stdout;需要留档时用 `tee`) |
47
+ | ⑤ 配置查询面板和快捷按钮 | 新建业务视图必须写 `query_conditions` 和 `action_buttons`,按钮同时覆盖 `list` 和 `detail` 位置 | `builder views apply` |
48
+ | ⑥ 需要上线时 | 发布侧校验 | `qingflow builder publish verify --app-key …` |
65
49
 
66
50
  **说明**:`views apply` 的 **`--publish`** 对应契约里的 **`publish`**;新建业务视图必须包含 `query_conditions` 和 `action_buttons` 并使用 `publish=true`,因为底层按钮写入会自动发布。只有删除、纯维护补丁、或用户明确要求的只读/归档视图,才允许不带按钮;只读/归档视图仍应配置 `query_conditions`。
67
51
 
@@ -71,17 +55,14 @@ app get -> app get fields/views -> views schema -> prepare one view -> views val
71
55
 
72
56
  ```bash
73
57
  qingflow builder views apply \
74
- --app-key APP_KEY \
75
- --view-file PATH \
58
+ --views-file PATH \
76
59
  [--publish | --no-publish]
77
60
  ```
78
61
 
79
- - **`--view-file`**:单个 JSON 对象,用于新建或完整更新一个视图;命令每次只接受一个。
80
- - **`--patch-views-file`**:JSON 数组,用于已有视图的局部更新;每次最多传一项,包含 `view_key` 或唯一 `name`,以及 `set`/`unset`。
81
- - **`--remove-views-file`**:JSON 数组,用于删除一个视图;每次最多传一个 raw `view_key` 或唯一名称。
82
- - 每次调用只能选择一种写入模式:`--view-file`、`--patch-views-file`、`--remove-views-file` 三者不能混用;每次只处理一个应用中的一个视图操作。
83
- - **不支持批量创建**:不要传 `upsert_views`、`views`、`apps` 等批量声明,也不要在 patch/remove 文件中放多项;多个视图须逐个调用 `builder views apply`,每次单独读回确认。
84
- - **`--app-key`**:每次视图写入必须指定一个应用;CLI 不提供跨应用或同次多视图写入。
62
+ - **`--views-file`**:推荐唯一主入口。文件为 **JSON 对象**,形如 `{"views":[...]}`;同一批可混合创建、局部修改、删除,可混合同 app / 跨 app 视图。
63
+ - 每个 `views[]` 项必须写 **`app_key`**;`operation` 为 **`upsert`** / **`patch`** / **`remove`**。
64
+ - CLI 内部按 view job 并发写入,上限 20,结果按输入顺序返回。
65
+ - 兼容旧入口 **`--app-key + --upsert-views-file / --patch-views-file / --remove-views-file`**,但不作为智能体主写法。
85
66
  - 输出默认直接给 stdout,前端可直接读取;需要留档时用 `qingflow builder views apply … | tee tmp/builder_views_apply.json`。
86
67
 
87
68
  ---
@@ -90,10 +71,10 @@ qingflow builder views apply \
90
71
 
91
72
  | 文件 | 用途 |
92
73
  |------|------|
93
- | [views_upsert_table_minimal.example.json](../examples/views/views_upsert_table_minimal.example.json) | 单视图表格示例,可直接作为 `--view-file` |
94
- | [views_apply_v1alpha1.example.json](../examples/views/views_apply_v1alpha1.example.json) | 版本化单视图字段示例;作为 `--view-file` 使用时加 `--schema-version v1alpha1` |
74
+ | [views_upsert_table_minimal.example.json](../examples/views/views_upsert_table_minimal.example.json) | **新建 table 视图**标准 **`views[]` 文件**:`operation` + `app_key` + `name` + `type` + **`columns`** + 必需的 `query_conditions` + 必需的 `action_buttons`(含 `list` 与 `detail`) |
75
+ | [views_batch_full.example.json](../examples/views/views_batch_full.example.json) | 批量能力示例:同批 `upsert` / `patch` / `remove`,table / board / gantt,固定筛选、查询面板、视图内按钮和可见性 |
95
76
 
96
- 复制到具体应用前替换 **`columns`**;应用由命令的 **`--app-key`** 指定。**`name`** 重名时会更新已有同名视图而非新建(见 **§4**)。
77
+ 复制到具体应用前务必替换文件内 **`app_key`** 和 **`columns`**;**`name`** 重名时会更新已有同名视图而非新建(见 **§4**)。
97
78
 
98
79
  ---
99
80
 
@@ -103,11 +84,12 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
103
84
 
104
85
  | 键 | 说明 |
105
86
  |----|------|
106
- | **`app_key`** | 命令的必填参数,定位单个应用 |
107
- | **`upsert_view`** | 来自 `--view-file` 的一个对象;创建用 `name`,完整更新优先带 raw `view_key` |
108
- | **`upsert_view.query_conditions`** | 新建业务视图必填;配置前端查询面板字段布局 |
109
- | **`patch_views`** | 来自 `--patch-views-file` 的数组;每次最多一项,使用 `view_key`/`name` 和 `set`/`unset` |
110
- | **`remove_views`** | 来自 `--remove-views-file` 的数组;每次最多一项,使用 raw `view_key` 或唯一名称 |
87
+ | **`views`** | 必填数组;每项是一个 view job |
88
+ | **`views[].operation`** | `upsert` / `patch` / `remove`;省略时按字段推断,但推荐显式写 |
89
+ | **`views[].app_key`** | 必填;允许同批混合同 app / 跨 app |
90
+ | **`views[].name` / `view_key`** | 创建用 `name`;更新/删除优先用 raw `view_key` |
91
+ | **`views[].query_conditions`** | 新建业务视图必填;配置前端查询面板字段布局 |
92
+ | **`views[].set` / `unset`** | `operation="patch"` 时使用 |
111
93
 
112
94
  **别名**(契约 `aliases` 节选):**`fields` / `column_names` → `columns`**;**`view_key` / `viewKey`**;**`tableView`→`table`**、**`kanban`→`board`** 等;**`filter_rules`→`filters`**;**`startField`→`start_field`** 等。
113
95
 
@@ -117,15 +99,15 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
117
99
 
118
100
  服务逻辑概要:
119
101
 
120
- - **`remove_views`**:优先传 raw **`view_key`**;也可传唯一视图显示名 `name`,显示名重名则 **`AMBIGUOUS_VIEW`**。
121
- - **`upsert_view`**:
102
+ - **`operation="remove"`**:优先传 raw **`view_key`**;也可传唯一视图显示名 `name`,显示名重名则 **`AMBIGUOUS_VIEW`**。
103
+ - **`operation="upsert"`**:
122
104
  - 若提供 **`view_key`**:对该视图做 **更新**(含类型变更等,仍受后端约束)。
123
105
  - 未提供 **`view_key`**:若 **`name` 唯一** 匹配已有视图 → **更新**;否则 → **创建**。
124
- - **`patch_views`**:对已有视图做局部参数替换;必须有 `view_key` 或唯一 `name`,并写 `set` / `unset`。
106
+ - **`operation="patch"`**:对已有视图做局部参数替换;必须有 `view_key` 或唯一 `name`,并写 `set` / `unset`。
125
107
 
126
- 响应中的 **`verification.view.status`** 会出现 **`created` / `updated`** 等;**`view_result`** 给出本次唯一视图操作结果,**`views_diff`** 仅保留兼容摘要。
108
+ 响应中的 **`verification.by_view[].status`** 会出现 **`created` / `updated`** 等;**`views_diff`** 汇总创建/更新/失败名单。
127
109
 
128
- **`partial_success`**:单个视图写入已执行,但读回或附属配置校验未完全通过;务必读 **`view_result`**、**`warnings`** 与 **`verification`**。
110
+ **`partial_success`**:部分视图成功、部分失败时整体仍可能带成功信封,务必读 **`failed`** 与 **`execution_notes`**。
129
111
 
130
112
  **系统默认名禁止新建**:未提供 `view_key` 的 `upsert` 不要使用 `全部数据`、`我的数据`、`我发起的`、`待办`、`已办`、`抄送` 这类默认系统视图名。它们不是业务视图模板,而是平台默认对象;新业务视图用具体业务名。
131
113
 
@@ -133,18 +115,16 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
133
115
 
134
116
  ## 5. `type` 与各类型必填
135
117
 
136
- 契约 **`view.type`**:**`table`** | **`card`** | **`board`** | **`gantt`** | **`hierarchy`** | **`calendar`**。
118
+ 契约 **`view.type`**:**`table`** | **`card`** | **`board`** | **`gantt`**。
137
119
 
138
120
  | `type` | 列/字段要点 | 类型专属键 |
139
121
  |--------|----------------|------------|
140
- | **`table`** | **`columns`**(业务字段 **queId**,或已有系统字段 **queId**) | — |
122
+ | **`table`** | **`columns`**(业务字段 **显示名**,须能在 **`app get fields`** 里找到) | — |
141
123
  | **`card`** | 同 table | — |
142
124
  | **`board`**(看板) | 列;且须 **`group_by`**(分组字段名) | **`group_by`** |
143
125
  | **`gantt`** | 列;须 **`start_field`**、**`end_field`**(通常为日期类字段名) | 可选 **`title_field`** |
144
- | **`hierarchy`** | 层级标题字段和父子关系字段 | `hierarchy.title_que_id`、`hierarchy.children_que_id`;可选 `hierarchy.root_filter` |
145
- | **`calendar`** | 标题字段和日期字段 | `calendar.title_que_id`、`calendar.date_que_id`;可选 `calendar.color_que_id` |
146
126
 
147
- 实现侧校验:对 **table/card**,`columns` 至少包含一列;已知系统字段在读取已有视图时原样透传,不要求出现在表单业务字段索引中。未知系统字段仍会报告覆盖缺口。
127
+ 实现侧校验:对 **table/card**,若声明了 **`columns`**,在 **过滤系统列**后须 **至少保留一个**真实应用字段,否则报错——**不能**只用系统列名凑一列(系统列集合见 **[reference/app-delivery-sop.md](./reference/app-delivery-sop.md)**)。
148
128
 
149
129
  ---
150
130
 
@@ -156,9 +136,9 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
156
136
 
157
137
  | 目标场景 | 写到哪里 | 推荐写法 | 不要这样做 |
158
138
  | --- | --- | --- | --- |
159
- | 视图打开时固定筛选数据 | `filters` | `{"que_id":101,"operator":"eq","value":"进行中"}` | 不要写 `judgeType` / `judgeValues`;不要把它放进 `query_conditions` |
139
+ | 视图打开时固定筛选数据 | `filters` | `{"field_name":"状态","operator":"eq","value":"进行中"}` | 不要写 `judgeType` / `judgeValues`;不要把它放进 `query_conditions` |
160
140
  | 前端查询面板显示哪些字段 | `query_conditions.rows` | `[["客户名称", "负责人"], ["创建时间"]]` | 不要写筛选值;不要把它当 OR 条件 |
161
- | 按钮显示条件 | `action_buttons[].visible_when` | `{"que_id":101,"operator":"eq","value":"已完工"}` | 不要手写后端判断符 |
141
+ | 按钮显示条件 | `action_buttons[].visible_when` | `{"field_name":"状态","operator":"eq","value":"已完工"}` | 不要手写后端判断符 |
162
142
  | 当前记录创建下游记录时传值 | `field_mappings` | `{"source_field":"数据ID","target_field":"关联工单"}` | 不要放在 `header` 按钮;`header` 没有当前记录上下文 |
163
143
  | 关联视图/关联报表按当前记录过滤 | `associated-resource apply.match_mappings` | `{"target_field":"关联客户","operator":"eq","source_field":"数据ID"}` | 不要用 `filters` 或 `query_conditions` 代替 |
164
144
  | 关联视图/关联报表静态筛选 | `match_mappings` | `{"target_field":"状态","operator":"eq","value":"有效"}` | 不要混用 raw `match_rules` |
@@ -167,17 +147,17 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
167
147
 
168
148
  ### 6.1 `filters`
169
149
 
170
- - 项形状:**`que_id`**、**`operator`**、**`values`**(或契约允许的 **`value`** 别名)。
150
+ - 项形状:**`field_name`**、**`operator`**、**`values`**(或契约允许的 **`value`** 别名)。
171
151
  - **`operator`**:统一公共语义,推荐 `eq` / `neq` / `in` / `contains` / `gte` / `lte` / `is_empty` / `not_empty`;兼容 `equal` / `equals` / `=` / `!=` / `any_of` / `one_of` / `empty` 等别名(以契约为准)。
172
152
  - **`in` 等多值**:传 **列表**;**`value`** 为列表时可作别名。
173
153
  - **`value` 按字段类型写**:文本/数字/日期直接写业务值;单选/多选/是否优先写选项文本,也支持 option id;成员/部门/关联记录固定筛选优先写唯一 id 或 `{id,value}`。完整规则见 **[reference/match-rules.md](./reference/match-rules.md)**。
174
154
  - **语义**:固定筛选条件,打开视图即生效。不要把前端查询栏字段写进 `filters`。
175
- - **写入 / 读回语义**:智能体始终写 `que_id + operator + value/values`;CLI 内部自动转换目标协议,读回也会还原成 `operator/value` 语义。不要手写或解释后端判断符。
155
+ - **写入 / 读回语义**:智能体始终写 `field_name + operator + value/values`;CLI 内部自动转换目标协议,读回也会还原成 `operator/value` 语义。不要手写或解释后端判断符。
176
156
 
177
157
  示例:
178
158
 
179
159
  ```json
180
- {"que_id": 101, "operator": "eq", "value": "进行中"}
160
+ {"field_name": "状态", "operator": "eq", "value": "进行中"}
181
161
  ```
182
162
 
183
163
  ### 6.2 `query_conditions`
@@ -196,38 +176,44 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
196
176
 
197
177
  ```json
198
178
  {
199
- "name": "客户查询视图",
200
- "type": "table",
201
- "columns": [101, 102, 103, 104],
202
- "filters": [
203
- {"que_id": 103, "operator": "eq", "value": "有效"}
204
- ],
205
- "query_conditions": {
206
- "enabled": true,
207
- "exact": false,
208
- "hide_before_query": false,
209
- "rows": [["客户名称", "负责人"], ["创建时间"]]
210
- },
211
- "action_buttons": [
179
+ "views": [
212
180
  {
213
- "text": "行内创建跟进",
214
- "action": "add_data",
215
- "target_app_key": "FOLLOWUP_APP_KEY",
216
- "field_mappings": [
217
- {"source_field": "数据ID", "target_field": "关联客户"}
181
+ "operation": "upsert",
182
+ "app_key": "APP_KEY",
183
+ "name": "客户查询视图",
184
+ "type": "table",
185
+ "columns": ["客户名称", "负责人", "客户状态", "创建时间"],
186
+ "filters": [
187
+ {"field_name": "客户状态", "operator": "eq", "value": "有效"}
218
188
  ],
219
- "default_values": {"跟进状态": "待跟进"},
220
- "placement": "list"
221
- },
222
- {
223
- "text": "详情创建跟进",
224
- "action": "add_data",
225
- "target_app_key": "FOLLOWUP_APP_KEY",
226
- "field_mappings": [
227
- {"source_field": "数据ID", "target_field": "关联客户"}
228
- ],
229
- "default_values": {"跟进状态": "待跟进"},
230
- "placement": "detail"
189
+ "query_conditions": {
190
+ "enabled": true,
191
+ "exact": false,
192
+ "hide_before_query": false,
193
+ "rows": [["客户名称", "负责人"], ["创建时间"]]
194
+ },
195
+ "action_buttons": [
196
+ {
197
+ "text": "行内创建跟进",
198
+ "action": "add_data",
199
+ "target_app_key": "FOLLOWUP_APP_KEY",
200
+ "field_mappings": [
201
+ {"source_field": "数据ID", "target_field": "关联客户"}
202
+ ],
203
+ "default_values": {"跟进状态": "待跟进"},
204
+ "placement": "list"
205
+ },
206
+ {
207
+ "text": "详情创建跟进",
208
+ "action": "add_data",
209
+ "target_app_key": "FOLLOWUP_APP_KEY",
210
+ "field_mappings": [
211
+ {"source_field": "数据ID", "target_field": "关联客户"}
212
+ ],
213
+ "default_values": {"跟进状态": "待跟进"},
214
+ "placement": "detail"
215
+ }
216
+ ]
231
217
  }
232
218
  ]
233
219
  }
@@ -250,41 +236,47 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
250
236
 
251
237
  ```json
252
238
  {
253
- "name": "生产工单执行视图",
254
- "type": "table",
255
- "columns": ["工单编号", "产品", "状态", "负责人"],
256
- "filters": [
257
- {"que_id": 101, "operator": "in", "values": ["生产中", "已完工"]}
258
- ],
259
- "query_conditions": {
260
- "enabled": true,
261
- "exact": false,
262
- "hide_before_query": false,
263
- "rows": [["工单编号", "状态"], ["负责人"]]
264
- },
265
- "action_buttons": [
239
+ "views": [
266
240
  {
267
- "text": "行内创建质检单",
268
- "action": "add_data",
269
- "target_app_key": "QUALITY_APP",
270
- "field_mappings": [
271
- {"source_field": "数据ID", "target_field": "关联工单"}
241
+ "operation": "upsert",
242
+ "app_key": "APP_KEY",
243
+ "name": "生产工单执行视图",
244
+ "type": "table",
245
+ "columns": ["工单编号", "产品", "状态", "负责人"],
246
+ "filters": [
247
+ {"field_name": "状态", "operator": "in", "values": ["生产中", "已完工"]}
272
248
  ],
273
- "default_values": {"处理状态": "待处理"},
274
- "placement": "list",
275
- "visible_when": [
276
- {"que_id": 101, "operator": "eq", "value": "已完工"}
249
+ "query_conditions": {
250
+ "enabled": true,
251
+ "exact": false,
252
+ "hide_before_query": false,
253
+ "rows": [["工单编号", "状态"], ["负责人"]]
254
+ },
255
+ "action_buttons": [
256
+ {
257
+ "text": "行内创建质检单",
258
+ "action": "add_data",
259
+ "target_app_key": "QUALITY_APP",
260
+ "field_mappings": [
261
+ {"source_field": "数据ID", "target_field": "关联工单"}
262
+ ],
263
+ "default_values": {"处理状态": "待处理"},
264
+ "placement": "list",
265
+ "visible_when": [
266
+ {"field_name": "状态", "operator": "eq", "value": "已完工"}
267
+ ]
268
+ },
269
+ {
270
+ "text": "详情创建返工单",
271
+ "action": "add_data",
272
+ "target_app_key": "REWORK_APP",
273
+ "field_mappings": [
274
+ {"source_field": "数据ID", "target_field": "关联工单"}
275
+ ],
276
+ "default_values": {"返工状态": "待处理"},
277
+ "placement": "detail"
278
+ }
277
279
  ]
278
- },
279
- {
280
- "text": "详情创建返工单",
281
- "action": "add_data",
282
- "target_app_key": "REWORK_APP",
283
- "field_mappings": [
284
- {"source_field": "数据ID", "target_field": "关联工单"}
285
- ],
286
- "default_values": {"返工状态": "待处理"},
287
- "placement": "detail"
288
280
  }
289
281
  ]
290
282
  }
@@ -294,6 +286,8 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
294
286
 
295
287
  ```json
296
288
  {
289
+ "operation": "patch",
290
+ "app_key": "APP_KEY",
297
291
  "view_key": "RAW_VIEW_KEY",
298
292
  "set": {
299
293
  "action_buttons": [
@@ -331,7 +325,7 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
331
325
  - `publish=false` + `action_buttons` 会被阻断为 `VIEW_ACTION_BUTTONS_REQUIRE_PUBLISH`。
332
326
  - 视图内按钮写智能体语义:`action: "add_data"` 或 `action: "link"`。不要手写底层触发名。
333
327
  - 响应里同时看 `verification.views_verified`、`verification.action_buttons_verified`、`verification.view_button_bindings_verified`。
334
- - 按钮失败但视图成功时是 `partial_success`;先按 `suggested_next_call` 用 `patch_views` 重试失败视图。 如果回读里目标视图已有 `CUSTOM` 按钮、文本/位置/触发类型正确,不要重建视图或重复创建按钮。
328
+ - 按钮失败但视图成功时是 `partial_success`;先按 `suggested_next_call` 重试失败视图的 `views[]` patch。 如果回读里目标视图已有 `CUSTOM` 按钮、文本/位置/触发类型正确,不要重建视图或重复创建按钮。
335
329
 
336
330
  `default_values` 是写入**目标应用新增表单**的静态默认值,必须按目标应用 schema 写:
337
331
 
@@ -339,7 +333,7 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
339
333
  - 单选/多选字段的默认值必须来自目标字段 `options` 的**原始文本或 option id**;不要用业务近义词。例如 schema 选项是 `每月`、`中`,就不要写 `月检`、`普通`。
340
334
  - 成员/部门/关联字段默认值按 record insert 的写法处理;不确定候选或目标记录时,先只写 `field_mappings`,不要编造 `default_values`。
341
335
  - `field_mappings[].target_field` 和 `default_values` 的 key 都是**目标应用字段名**,不是当前视图字段名。
342
- - CLI 会在按钮写入前校验默认值;非法值会返回 `CUSTOM_BUTTON_DEFAULT_VALUE_UNSUPPORTED`。这时视图可能已经创建成功,只需要用 `patch_views` + raw `view_key` 修正 `action_buttons.default_values`,不要重建视图或应用。
336
+ - CLI 会在按钮写入前校验默认值;非法值会返回 `CUSTOM_BUTTON_DEFAULT_VALUE_UNSUPPORTED`。这时视图可能已经创建成功,只需要用 `views[].operation="patch"` + raw `view_key` 修正 `action_buttons.default_values`,不要重建视图或应用。
343
337
 
344
338
  正确示例:
345
339
 
@@ -377,16 +371,6 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
377
371
  - `card`:必须配置 `detail`,并在卡片行操作明确时配置 `list`;核心操作视图不要只给 `header`。
378
372
  - `gantt`:不适合作为唯一核心操作视图;需要快捷按钮时同时提供配套 table/board 视图,在该操作视图中配置 `list` 和 `detail`。
379
373
 
380
- ### 6.4.1 绑定已有自定义按钮(`buttons`,查重优先)
381
-
382
- 视图声明里的 `buttons[]` 只做绑定(引用应用级自定义按钮的 `button_id`),不会创建按钮本体。绑定前必须查重,不要重复创建同名按钮:
383
-
384
- 1. **查询**:`qingflow --json builder button get --app-key APP --button-text 按钮文案`(MCP `app_get_buttons` 传 `button_text`),按文案精确匹配。
385
- 2. **有则复用**:唯一命中 → 取返回的 `button_id` 直接写进 `buttons[]`;同名多个 → 用 `button_id` 精确指定(避免歧义)。
386
- 3. **没有再创建**:`builder button apply` 创建(其自身也按文案去重),拿到 `button_id` 后回到视图声明绑定。
387
-
388
- 按钮本体维护(样式/跨视图复用/删除本体)见 [80-buttons-associated-resources.md](./80-buttons-associated-resources.md)。
389
-
390
374
  ### 6.5 关联视图/报表
391
375
 
392
376
  新版默认不要通过 `app_views_apply.associated_resources` 配置关联资源。应用级关联资源池和视图展示开关统一走 **`app_associated_resources_apply`** / CLI **`builder associated-resource apply`**。
@@ -402,10 +386,10 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
402
386
 
403
387
  ## 7. 删除视图
404
388
 
405
- - 主路径使用 `--remove-views-file`;元素是 raw **`view_key`** 或唯一视图显示名,应用通过 `--app-key` 指定。
389
+ - 主路径使用 `views[].operation="remove"`;元素必须带 `app_key`,优先带 raw **`view_key`**,也可以带唯一视图显示名。
406
390
  - 优先用 **`view_key`** 删除;显示名重名会导致 **`AMBIGUOUS_VIEW`**,需先在 **`app get views`** 里确认。
407
391
  - DELETE 发出后,工具会用单个 **`view_key`** 回读验证,而不是再读全量视图列表判断删除结果。
408
- - 删除结果看 **`verification.view.delete_executed`**、**`readback_status`**、**`safe_to_retry_delete`**:
392
+ - 删除结果看 **`verification.by_view[].delete_executed`**、**`readback_status`**、**`safe_to_retry_delete`**:
409
393
  - **`readback_status=deleted`**:删除已验证。
410
394
  - **`readback_status=unavailable`** 或 **`still_exists`**:删除请求已发出但回读未完全确认,**不要盲目重复删除**;稍后用 `builder app get views` 或对应视图详情确认。
411
395
 
@@ -417,15 +401,21 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
417
401
 
418
402
  ```json
419
403
  {
420
- "name": "项目台账视图",
421
- "type": "table",
422
- "columns": [101],
423
- "visibility": {
424
- "mode": "workspace",
425
- "selectors": {},
426
- "external_mode": "not",
427
- "external_selectors": {}
428
- }
404
+ "views": [
405
+ {
406
+ "operation": "upsert",
407
+ "app_key": "APP_KEY",
408
+ "name": "项目台账视图",
409
+ "type": "table",
410
+ "columns": ["项目名称"],
411
+ "visibility": {
412
+ "mode": "workspace",
413
+ "selectors": {},
414
+ "external_mode": "not",
415
+ "external_selectors": {}
416
+ }
417
+ }
418
+ ]
429
419
  }
430
420
  ```
431
421
 
@@ -433,58 +423,70 @@ CLI 将参数与文件内容拼装为服务层载荷,**顶层键**如下:
433
423
 
434
424
  ```json
435
425
  {
436
- "name": "项目甘特图",
437
- "type": "gantt",
438
- "columns": [101, 102, 103],
439
- "start_que_id": 102,
440
- "end_que_id": 103,
441
- "title_que_id": 101,
442
- "filters": [
426
+ "views": [
443
427
  {
444
- "que_id": 101,
445
- "operator": "eq",
446
- "value": "进行中"
428
+ "operation": "upsert",
429
+ "app_key": "APP_KEY",
430
+ "name": "项目甘特图",
431
+ "type": "gantt",
432
+ "columns": ["项目名称", "开始日期", "结束日期"],
433
+ "start_field": "开始日期",
434
+ "end_field": "结束日期",
435
+ "title_field": "项目名称",
436
+ "filters": [
437
+ {
438
+ "field_name": "状态",
439
+ "operator": "eq",
440
+ "value": "进行中"
441
+ }
442
+ ]
447
443
  }
448
444
  ]
449
445
  }
450
446
  ```
451
447
 
452
- **Table + 筛选 + 查询条件 + 快捷按钮(单条 `--view-file`)**:
448
+ **Table + 筛选 + 查询条件 + 快捷按钮(完整 views-file)**:
453
449
 
454
450
  ```json
455
451
  {
456
- "name": "客户查询视图",
457
- "type": "table",
458
- "columns": [101, 102, 103, 104],
459
- "filters": [
460
- {"que_id": 103, "operator": "eq", "value": "有效"}
461
- ],
462
- "query_conditions": {
463
- "enabled": true,
464
- "exact": false,
465
- "hide_before_query": false,
466
- "rows": [["客户名称", "负责人"], ["创建时间"]]
467
- },
468
- "action_buttons": [
469
- {
470
- "text": "行内创建跟进",
471
- "action": "add_data",
472
- "target_app_key": "FOLLOWUP_APP_KEY",
473
- "field_mappings": [
474
- {"source_field": "数据ID", "target_field": "关联客户"}
475
- ],
476
- "default_values": {"跟进状态": "待跟进"},
477
- "placement": "list"
478
- },
452
+ "views": [
479
453
  {
480
- "text": "详情创建跟进",
481
- "action": "add_data",
482
- "target_app_key": "FOLLOWUP_APP_KEY",
483
- "field_mappings": [
484
- {"source_field": "数据ID", "target_field": "关联客户"}
454
+ "operation": "upsert",
455
+ "app_key": "APP_KEY",
456
+ "name": "客户查询视图",
457
+ "type": "table",
458
+ "columns": ["客户名称", "负责人", "客户状态", "创建时间"],
459
+ "filters": [
460
+ {"field_name": "客户状态", "operator": "eq", "value": "有效"}
485
461
  ],
486
- "default_values": {"跟进状态": "待跟进"},
487
- "placement": "detail"
462
+ "query_conditions": {
463
+ "enabled": true,
464
+ "exact": false,
465
+ "hide_before_query": false,
466
+ "rows": [["客户名称", "负责人"], ["创建时间"]]
467
+ },
468
+ "action_buttons": [
469
+ {
470
+ "text": "行内创建跟进",
471
+ "action": "add_data",
472
+ "target_app_key": "FOLLOWUP_APP_KEY",
473
+ "field_mappings": [
474
+ {"source_field": "数据ID", "target_field": "关联客户"}
475
+ ],
476
+ "default_values": {"跟进状态": "待跟进"},
477
+ "placement": "list"
478
+ },
479
+ {
480
+ "text": "详情创建跟进",
481
+ "action": "add_data",
482
+ "target_app_key": "FOLLOWUP_APP_KEY",
483
+ "field_mappings": [
484
+ {"source_field": "数据ID", "target_field": "关联客户"}
485
+ ],
486
+ "default_values": {"跟进状态": "待跟进"},
487
+ "placement": "detail"
488
+ }
489
+ ]
488
490
  }
489
491
  ]
490
492
  }
@@ -506,12 +508,11 @@ qingflow --json builder app get --app-key ead8ims5i401 views
506
508
 
507
509
  ```bash
508
510
  qingflow builder views apply \
509
- --app-key ead8ims5i401 \
510
511
  --publish \
511
- --view-file ./view.json
512
+ --views-file ./reference/examples/views/views_upsert_table_minimal.example.json
512
513
  ```
513
514
 
514
- **结果摘要**(示例视图名 **`示例业务操作视图_CLI模板`**):`status: success`,`verification.view.status: created`,返回 **`view_key`**(如 **`ecdk22v65c02`**),并验证 `query_conditions` 与 `action_buttons`。
515
+ **结果摘要**(示例视图名 **`示例业务操作视图_CLI模板`**):`status: success`,`verification.by_view[0].status: created`,返回 **`view_key`**(如 **`ecdk22v65c02`**),并验证 `query_conditions` 与 `action_buttons`。
515
516
 
516
517
  ---
517
518
 
@@ -520,12 +521,10 @@ qingflow builder views apply \
520
521
  | 现象 | 处理 |
521
522
  |------|------|
522
523
  | 列校验失败 / 无有效业务列 | **`app get fields`** 核对 **`name`**;避免 `columns` 仅含 **§7.1 系统列** |
523
- | 响应含 **`STALE_FIELD_REFERENCE`** / **`STALE_OPTION_REFERENCE`** 警告 | 声明引用了表单中已删除的字段/选项(后端保存视图本就原样透传);apply 已照写并在 `warnings` 留痕,重放/迁移场景属预期,人工整理时再清理死引用 |
524
- | 系统字段作标题/时间轴 | `title_que_id`/甘特 `start_que_id` 等可直接用系统字段 id(如 2=提交时间),与 `columns` 系统列同规则 |
525
524
  | 重名视图 / 删错 | **`app get views`**;更新时带 **`view_key`** |
526
525
  | 过滤器未生效疑虑 | 看响应 **`verification.view_filters_verified`**;必要时再 **`app get views`** |
527
526
  | 查询条件未生效疑虑 | 看响应 **`verification.view_query_conditions_verified`**;不要把 `query_conditions` 当 `filters` |
528
- | 后端 **40038 / Object not exist** | 先读失败项 **`details.view_result.details.field_level_diagnostics`** 与 **`recommended_minimal_retry`**。不要删除字段、不要重建应用;先按最小列重试,再逐步加非关键列/筛选。 |
527
+ | 后端 **40038 / Object not exist** | 先读失败项 **`details.per_view_results[].details.field_level_diagnostics`** 与 **`recommended_minimal_retry`**。不要删除字段、不要重建应用;先按最小列重试,再逐步加非关键列/筛选。 |
529
528
  | 按钮/关联资源配置 | 常规业务按钮随视图写 **`action_buttons`**;关联视图/报表走 **`builder associated-resource apply`** |
530
529
  | 部分失败 | 读 **`views_diff.failed`** 与契约 **execution_notes** 中 **partial_success** |
531
530
  | 权限/锁 | 同 [publish verify](./99-publish-verify.md) 与 [app delivery reference](./reference/app-delivery-sop.md) |
@@ -534,7 +533,7 @@ qingflow builder views apply \
534
533
 
535
534
  ## 11. 交叉引用
536
535
 
537
- - [views_upsert_table_minimal.example.json](../examples/views/views_upsert_table_minimal.example.json)(单视图示例,可直接作为 `--view-file` 使用)
536
+ - [views_upsert_table_minimal.example.json](../examples/views/views_upsert_table_minimal.example.json)(**table** 视图最小 **`views[]`**)
538
537
  - [SKILL.md](../../SKILL.md):builder 直接输出、鉴权顺序。
539
538
  - [99-publish-verify.md](./99-publish-verify.md):发布与回读。
540
539
  - [reference/app-delivery-sop.md](./reference/app-delivery-sop.md):系统列与历史交付细节。
@@ -23,7 +23,6 @@ app get -> app get views/charts/buttons/associated resources -> apply button or
23
23
 
24
24
  ## Custom buttons
25
25
 
26
- - **查重优先(硬规则)**:创建任何自定义按钮前,先 `builder button get --app-key APP --button-text 文案`(MCP `app_get_buttons` 传 `button_text`)按文案精确查重。唯一命中 → 直接复用其 `button_id`,不要创建;未命中 → 再走 `builder button apply` 创建(apply 本身也按 `button_text` 去重:无 `button_id` 时唯一同名匹配会转为更新,双保险);同名多个 → 必须传 `button_id` 精确指定。禁止每次都新建同名按钮。
27
26
  - For normal view-level business actions, prefer `builder views apply` with `action_buttons`.
28
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.
29
28
  - Use `upsert_buttons` for create/update and `patch_buttons` for small changes.
@@ -45,7 +44,6 @@ Start from user intent:
45
44
  | Need | Preferred path |
46
45
  | --- | --- |
47
46
  | Create or patch a normal business button on one view | `builder views apply` with `action_buttons` |
48
- | 查询/查重已有自定义按钮 | `builder button get --app-key APP --button-text 文案`(唯一命中复用其 `button_id`) |
49
47
  | Set style, icon, cross-view reuse, remove button body, reorder bindings | `builder button apply` |
50
48
  | Add qRobot/wings behavior | `builder button apply`, only with user-provided exact config |
51
49
  | Clear a view's custom button bindings | `builder button apply` with `view_configs[].mode="replace"` and `buttons: []` |