flycode-mcp 1.14.7 → 1.14.8
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.
|
@@ -72,9 +72,9 @@ Python / Node(或 curl / psql / 其他语言)直接打 APaaS 平台 HTTP 接
|
|
|
72
72
|
| **form** | `page_form_directories` | 只读 | 查**表单所属目录**:返回 `directorytypecode`(即表单 `pageinfo.directorytypecode` 的取值)。接口无分页、全量数百条,故**必须带 `keys` 检索**(目录名模糊,也命中 `centername`),或用 `parentdirectorytypecode` 下钻(`root`=只看顶级);默认回 30 条、硬上限 200,回 `truncated`/`hint` |
|
|
73
73
|
| **form** | `page_form_list` | 只读 | 分页搜表单/页面(按 `code`/`title`/`keywords`/`type`/`status`) |
|
|
74
74
|
| **form** | `get_form` | 只读 | 查表单完整详情(88KB 级,含 `view` 控件树 / `presenter` 事件 / `businessmodel`) |
|
|
75
|
-
| **form** | `get_form_outline` | 只读 |
|
|
75
|
+
| **form** | `get_form_outline` | 只读 | 表单轻量骨架(数 KB):节点树 + **弹窗骨架 `subviews`** + handlers/interfaces 清单 + 逻辑名 |
|
|
76
76
|
| **form** | `get_form_fragment` | 只读 | 表单局部内容(按 `nodeCode`/`handlerCode`/`section` 取几 KB) |
|
|
77
|
-
| **form** | `patch_form` | 写 | 局部改表单(
|
|
77
|
+
| **form** | `patch_form` | 写 | 局部改表单(15 类 ops:控件属性/数组项增删/**弹窗增删改**/action 增删改/action 内数组绑定/插删移节点/改脚本/增删 businessmodel) |
|
|
78
78
|
| **form** | `save_form` | 写 | 整页重构时才用:回传完整 `FormResult` 全量保存 |
|
|
79
79
|
| **h5** | `page_h5_form` | 只读 | 分页搜 H5 表单(智慧100 引擎) |
|
|
80
80
|
| **h5** | `get_h5_form` | 只读 | 查 H5 表单详情(核心 `confjson` 含 Vue 代码) |
|
|
@@ -149,8 +149,8 @@ flycode-mcp 默认开启 `PROGRESSIVE_DISCLOSURE=on`:连接后客户端只看
|
|
|
149
149
|
| 搜名字/代码关键字带「价格同步」的逻辑 | `logic` | `page_model_logic_list`(`keys`/`keywords`) |
|
|
150
150
|
| 查业务逻辑(modelLogic/模型逻辑/领域)所属目录 / 找某逻辑(modelLogic/模型逻辑/领域)挂在哪个目录 | `logic` | `page_model_logic_directories`(`modelname` 模糊搜 / `directorytypecode` 下钻子目录,默认 `rootNode` 查一级;返回 `modelcode` 即查该目录逻辑要用的编码) |
|
|
151
151
|
| 看某条业务逻辑(modelLogic/模型逻辑/领域)完整内容(含 flycode) | `logic` | `get_model_logic`(`modellogiccode`) |
|
|
152
|
-
| 先看表单长啥样(骨架) | `form` | `get_form_outline`(`code`)→
|
|
153
|
-
| 看表单里某段脚本 / 某节点 | `form` | `get_form_fragment`(`code`+`nodeCode`/`handlerCode`/`section
|
|
152
|
+
| 先看表单长啥样(骨架) | `form` | `get_form_outline`(`code`)→ 数 KB;**弹窗 code 在返回的 `subviews` 里**(`viewTree` 不含弹窗) |
|
|
153
|
+
| 看表单里某段脚本 / 某节点 | `form` | `get_form_fragment`(`code`+`nodeCode`/`handlerCode`/`section`;`nodeCode` 可命中弹窗及其内部控件,`section:"subviews"` 取全部弹窗) |
|
|
154
154
|
| 看表单完整结构(含控件树/事件) | `form` | `get_form`(`code`,88KB 级,非必要不用) |
|
|
155
155
|
| 搜表单/页面 | `form` | `page_form_list`(`keys`/`type`/`status`) |
|
|
156
156
|
| 查表单挂在哪个目录 / 取目录编码 directorytypecode | `form` | `page_form_directories`(**先 `keys` 模糊搜目录名**;无筛选时只回顶级目录。切勿裸调拉全量——接口无分页、实测 352 条/74KB) |
|
|
@@ -169,7 +169,7 @@ flycode-mcp 默认开启 `PROGRESSIVE_DISCLOSURE=on`:连接后客户端只看
|
|
|
169
169
|
| 加/删 input 或 output 参数、加/改字段属性 | `patch_model_logic` |
|
|
170
170
|
| 改逻辑标题/描述/`actiontype` 等顶层元数据 | `patch_model_logic`(`set_meta`) |
|
|
171
171
|
| 改导出类(`actioncategory=5`)的导出列 | `patch_model_logic`(5 类导出 op,**勿用 `set_meta` 碰 `bindjson`**) |
|
|
172
|
-
| 给表单加/删/移控件、改控件属性、改 UI 脚本、增删改 action、改 action
|
|
172
|
+
| 给表单加/删/移控件、改控件属性、改 UI 脚本、增删改 action、改 action 内数组绑定、**改/加/删弹窗(popview)** | `patch_form`(15 类 ops) |
|
|
173
173
|
| 整页重构表单布局 | `save_form`(回传完整 `FormResult`) |
|
|
174
174
|
| **新建**一条业务逻辑(首次创建) | `save_model_logic`(配 `generate_unique_code` 生成 `modellogiccode`) |
|
|
175
175
|
| 已有逻辑全量 JSON 很小(如微服务) | `save_model_logic` 全量保存 |
|
|
@@ -203,10 +203,12 @@ flycode-mcp 默认开启 `PROGRESSIVE_DISCLOSURE=on`:连接后客户端只看
|
|
|
203
203
|
|
|
204
204
|
| 改的内容 | 选 |
|
|
205
205
|
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
206
|
-
| 局部:改控件属性、数组内单元素(列 `options`/样式)、插/删/移节点、改某 action 脚本、**增删改 action 本身**、增删 businessmodel、**把界面输出绑定到控件(改 `datarequest.setter
|
|
206
|
+
| 局部:改控件属性、数组内单元素(列 `options`/样式)、插/删/移节点、改某 action 脚本、**增删改 action 本身**、增删 businessmodel、**把界面输出绑定到控件(改 `datarequest.setter`)**、**弹窗(`view.subviews`)及其内部控件的增删改** | **`patch_form`**(15 类 ops;view 树数组用 `patch_node_array_item`,handler action 内数组用 `patch_action_array_item`,**弹窗根节点用 `patch_view_array_item`(`arrayProp:"subviews"`)**,action 本身增删改用 `add_action`/`patch_action`/`remove_action`,避免 `set_attrs` 整段覆盖大数组) |
|
|
207
207
|
| 整页重构(重排布局、模板迁移) | **`save_form`**(回传完整 `FormResult`) |
|
|
208
208
|
|
|
209
|
-
> 数组元素级改动一律用 `patch_node_array_item`(view 树节点数组,如单列 `options`/`cols`,支持 merge/append/insert/remove
|
|
209
|
+
> 数组元素级改动一律用 `patch_node_array_item`(view 树节点数组,如单列 `options`/`cols`,支持 merge/append/insert/remove)、`patch_view_array_item`(**view 级数组,弹窗 `subviews`**)或 `patch_action_array_item`(presenter.handlers/initial 的 action 内数组,如 `datarequest.setter` 绑定输出到控件、`param.properties`,支持四种模式)。**`set_attrs` 默认禁止整段覆盖数组**(`patch` 含数组属性会直接阻断并要求显式 `overwriteArray:true`),因其大 payload 曾触发调用方 stringify bug 致 36 列丢失;且 `set_attrs` 只覆盖 `view.body` 树、`view.subviews` 弹窗及内部控件、`controls`,够不到 action 结构。
|
|
210
|
+
|
|
211
|
+
> **弹窗(popview)**:平台把弹窗放在 `view.subviews`(与 `view.body` **平级**的数组,元素 `type=popview`),弹窗内控件在弹窗节点的 `content` 下。**弹窗 code 不在 `viewTree` 里,只能从 `get_form_outline` 的 `subviews` 拿**。弹窗内加/删/移控件用 `insert_node`/`remove_node`/`move_node`,改属性用 `set_attrs`;弹窗**根节点**自身(没有父节点)的增/改/删用 `patch_view_array_item`(`arrayProp:"subviews"`,新建首次须 `createIfMissing:true`)。**删弹窗两条等价路径**(`remove_node{code}` / `patch_view_array_item{mode:"remove"}`)都默认校验 `popsubview` 的 `viewcode` 引用,报 `REF_VIOLATION` 时先 `remove_action` 解引用,确需强删传 `checkRefs:false`。红线:弹窗内控件 `code` 常被 `datarequest.setter` 引用,**勿改 code、勿删仍被引用的节点**。详见 `tools/form.md`「弹窗专章」。
|
|
210
212
|
|
|
211
213
|
> **action 本身的增删改**不走上面两个数组 op(`patch_action_array_item` 只管 action **内部**的数组):新增用 `add_action`(按 `type` 自动补平台空骨架,`initial` 仅允许 `flycode`/`receivelink`),改字段用 `patch_action`(浅合并任意字段,但**不能改 `type`/`code`**),删除用 `remove_action`(删空保留 `actions: []`)。定位一律用 `actionCode`,`actionIndex` 会随同批次增删漂移。详见 `tools/form.md`。
|
|
212
214
|
|
|
@@ -247,12 +249,13 @@ flycode-mcp 默认开启 `PROGRESSIVE_DISCLOSURE=on`:连接后客户端只看
|
|
|
247
249
|
## 六、关键避坑(高频雷区)
|
|
248
250
|
|
|
249
251
|
- **🚫 禁止自写脚本调用平台(最高优先级)**:见「零、红线」。旧版用户记忆里可能残留「Python/Node 直连接口」「手写脚本模拟工具」的做法,**一律禁止**;所有读写只走官方 MCP 工具,找不到能力就如实告知用户,不绕过。
|
|
250
|
-
- **不回传整份大 JSON**:已有普通逻辑/表单只用局部工具(`str_replace_flycode`/`patch_model_logic`/`patch_form`),`save_model_logic`/`save_form` 全量仅用于新建或极小 JSON;**当且仅当** JSON 过大无法内联且局部工具无法满足时,才可用「八、超大 JSON 全量保存的官方脚本」(真正的 MCP 客户端,非直接打 REST
|
|
252
|
+
- **不回传整份大 JSON**:已有普通逻辑/表单只用局部工具(`str_replace_flycode`/`patch_model_logic`/`patch_form`),`save_model_logic`/`save_form` 全量仅用于新建或极小 JSON;**当且仅当** JSON 过大无法内联且局部工具无法满足时,才可用「八、超大 JSON 全量保存的官方脚本」(真正的 MCP 客户端,非直接打 REST)。⚠️ **含弹窗的表单尤其不能用 `save_form` 兜底**:它按提交内容整份覆盖,旧快照会把 `view.subviews`(弹窗及其 `eventlist`)一起抹掉(线上已发生过);弹窗现已能用 `patch_form` 直接改。
|
|
251
253
|
- **校验口径(2026-09-22 修正)**:`verify:false` / `VERIFY_FAILED` **视为真实未生效信号**(旧版「换行假阴性」已由 MCP 修复)。`applied:true`+`verified:false` 且报「新内容未出现」时,用 `get_form_fragment`/`get_model_logic` 实际回读确认,不要凭错误码重复提交;确需字节严格校验给 op 设 `matchMode:'exact'`。
|
|
252
254
|
- **导出列专用 ops**:`patch_model_logic` 改导出列(`actioncategory=5`)用 5 类导出 op;**切勿用 `set_meta` 碰 `bindjson`**(会整体覆盖顶层字段、丢失导出列定义),改用 `set_bind_meta`。
|
|
253
255
|
- **空串不是定位键**:自定义字段 `propertycode`/`objectcode` 恒为 `""`,传 `""` 安全且推荐(不会误判重复);但 `remove_property`/`replace_property` 只传空串 `propertyCode` 而无 `propertyName` 会报 `INVALID_PARAMS`。
|
|
254
256
|
- **表单 `initial` vs `handlers`**:页面初始类事件(如「页面初始-参数接收」)在 `presenter.initial[]`,**不在 `handlers[]`**;`patch_form` 的 `replace_script` / `add_action` / `patch_action` / `remove_action` / `patch_action_array_item` 都会在两块容器检索,`handlerCode` 同名跨容器须消歧 —— 参数名是 **`scope`**(`handlers`/`initial`),**也接受等价别名 `handlerScope`**(与 `get_form_fragment` 同名,任传其一;都传且取值不同报 `INVALID_PARAMS`);`get_form_outline` 会一并列出并标 `scope='initial'`。
|
|
255
257
|
- **动作(action)增删改的三条硬约束**:① **类型按容器分域**——`initial`(页面初始化)只允许 `flycode`/`receivelink`,其余 24 种只能加到 `handlers`,越界报 `TYPE_NOT_ALLOWED`;② **定位一律用 `actionCode`**,不用 `actionIndex`(同批次前序 op 增删会让下标漂移,回读校验会打到邻居身上);③ `patch_action` 的 `patch` **不能含 `type`/`code`**(`type` 是字段骨架锚点、`code` 是定位键),换类型或改名一律 `remove_action` + `add_action`。另:数据提交是 `datasubmit`(不是 `datacommit`);「数据字典绑定」不是独立 type,是 `datarequest` 的 `_type_spe:"dictbind"` 变体。
|
|
258
|
+
- **弹窗(popview)三条硬约束**:① **code 只从 `get_form_outline().subviews` 拿**——弹窗不在 `viewTree` 里,用 `get_form` 全量翻找是浪费上下文;② 弹窗根节点(挂在 `view.subviews`、没有父节点)的增/改/删用 `patch_view_array_item`(`arrayProp:"subviews"`,首次新建须 `createIfMissing:true`),弹窗**内部**控件才用 `insert_node`/`remove_node`/`set_attrs`;③ **删弹窗前先解引用**——`popsubview`/`closesubview` 的 `viewcode` 仍指向它时报 `REF_VIOLATION`(先 `remove_action`,或 `checkRefs:false` 强删);弹窗内控件 `code` 常被 `datarequest.setter` 引用,勿改 code、勿删被引用节点。
|
|
256
259
|
- **新建逻辑用官方 ID(且勿带 prefix)**:`modellogiccode`/`modellogicstepcode` 必须调 `generate_unique_code` 获取,**调用时不要传 `prefix`**(返回纯 18 位纯数字 ID),不要自写脚本按 epoch 算(官方现 18 位、旧「19 位」约定已过期,硬编码会落到平台雪花方案外)。带字母前缀的 `code` 会被后端 `saveModelLogic` 判 `modellogiccode不能为空` 拒绝。新建逻辑顶层对象**不要带** `metamodelcode`/`confsource`。
|
|
257
260
|
- **`run_sql` 只读**:仅 SELECT、一次一条;不支持 INSERT/UPDATE/DELETE。
|
|
258
261
|
- **数据字典文本**:实体字典字段存 `dickey`(bigint,全局唯一),翻译一律 `LEFT JOIN pl_dictionary d ON d.dickey=k.<col>`,不必拼 `dictionarycode`;字典编码 >2^53 用字符串常量。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 属 **form** 域:使用前需 `mcp_activate('form')` 激活(连接后默认隐藏)。
|
|
4
4
|
> 读写分工:前 5 个只读,`patch_form` 局部改、`save_form` 整页才用。
|
|
5
|
-
> 推荐流程:`page_form_list` 拿 code → `get_form_outline`
|
|
5
|
+
> 推荐流程:`page_form_list` 拿 code → `get_form_outline` 看骨架(**弹窗 code 在 `subviews` 里**)→ `get_form_fragment` 看局部 → `patch_form` 改。**避免一上来 `get_form` 拉全量**(88KB 级)。
|
|
6
6
|
|
|
7
7
|
## 枚举速查
|
|
8
8
|
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
|
|
112
112
|
## `get_form_outline` — 查询表单骨架(只读,首选入口)
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
获取表单轻量骨架(**数 KB,随控件数量增长**:小页面 2–4KB,大页面实测 18.6KB / body 127 节点):pageinfo 关键字段、view 树骨架(body)、**弹窗视图骨架(`subviews`)**、presenter 处理器清单、businessmodel 逻辑名。用于拿全貌与所有可改对象 code,避免盲改。
|
|
115
115
|
|
|
116
116
|
### 输入
|
|
117
117
|
|
|
@@ -124,7 +124,8 @@
|
|
|
124
124
|
| 字段 | 类型 | 说明 |
|
|
125
125
|
| --- | --- | --- |
|
|
126
126
|
| `code` / `title` / `type` / `status` / `clientcategorycode` / `marktype` / `versionnum` | string \| null | 页面基本信息(type 同 page_form_list) |
|
|
127
|
-
| `viewTree` | array | view 树骨架(递归),每项 `{ code, type, title, children[] }` |
|
|
127
|
+
| `viewTree` | array | view 树骨架(递归),每项 `{ code, type, title, children[] }`。⚠️ **只含 `view.body`,不含弹窗** |
|
|
128
|
+
| `subviews` | array | **弹窗视图骨架**,与 `viewTree` 同构,每项一棵弹窗树(元素 `type=popview`)。⚠️ **弹窗及其内部控件的 code 只能从这里拿**——它们不在 `viewTree` 里;无弹窗时恒为 `[]` |
|
|
128
129
|
| `handlers` | array | presenter 处理器清单,每项 `{ code, name, desc, key, condition, actionCount, actionTypes[], scope }`。⚠️ **`scope='handlers'` 为事件处理器 / `'initial'` 为页面初始化**(`replace_script` 寻址依据) |
|
|
129
130
|
| `interfaces` | array | presenter 对外接口清单,每项 `{ code, key, desc, actionCount }` |
|
|
130
131
|
| `businessModels` | array | businessmodel 引用的业务逻辑名清单,每项 `{ modelcode, modellogiccode, modellogicname, actiontype }`(仅名字不回内容) |
|
|
@@ -141,11 +142,11 @@
|
|
|
141
142
|
| 参数 | 类型 | 必填 | 说明 |
|
|
142
143
|
| --- | --- | --- | --- |
|
|
143
144
|
| `code` | string | 是 | 表单/页面唯一编码 |
|
|
144
|
-
| `nodeCode` | string | 否 |
|
|
145
|
+
| `nodeCode` | string | 否 | 目标控件/节点编码,返回其完整子树。**支持 `view.subviews` 里的弹窗节点及其内部控件**;未命中时不会静默返回空壳,`message` 会写明已检索范围 |
|
|
145
146
|
| `itemCode` | string | 否 | 在 nodeCode 命中节点内部,按 code 深度优先钻取某个**数组元素**(如表格的某一列)并返回该元素;未找到时在 message 提示 |
|
|
146
147
|
| `handlerCode` | string | 否 | 目标 presenter 处理器编码(**handlers 与 initial 均检索**),返回完整定义与 actionIndex 清单 |
|
|
147
148
|
| `handlerScope` | string | 否 | `handlers` / `initial`——限定容器;默认两者都检索,同名跨容器时须指定以消歧 |
|
|
148
|
-
| `section` | string | 否 | 返回整段:`pageinfo` / `view` / `presenter` / `controls` / `pageswitch` / `businessmodel` |
|
|
149
|
+
| `section` | string | 否 | 返回整段:`pageinfo` / `view` / `presenter` / `controls` / `pageswitch` / `businessmodel` / `subviews`(只取弹窗数组) |
|
|
149
150
|
|
|
150
151
|
### 输出
|
|
151
152
|
|
|
@@ -157,44 +158,49 @@
|
|
|
157
158
|
| `handler` | any | handlerCode 命中的处理器完整定义 |
|
|
158
159
|
| `section` | any | section 命中的整段内容 |
|
|
159
160
|
| `actionIndex` | array | handler 的 action 清单,每项 `{ index, code, type, scriptLen, conditionLen, expressionLen }`,便于精确构造 `replace_script` |
|
|
160
|
-
| `message` | string \| null |
|
|
161
|
+
| `message` | string \| null | 提示信息。⚠️ **`node`/`handler` 为空且有 message = 未命中**(会写明已检索 view.body 树、view.subviews 弹窗 N 个、controls),不要当成「这表单是空的」 |
|
|
161
162
|
|
|
162
163
|
---
|
|
163
164
|
|
|
164
165
|
## `patch_form` — 局部补丁修改表单(写)
|
|
165
166
|
|
|
166
|
-
以 delta ops 局部修改表单,无需回传完整 JSON。**
|
|
167
|
+
以 delta ops 局部修改表单,无需回传完整 JSON。**15 类 ops**,事务性预演,失败整批回滚。改初始化脚本(presenter.initial)与改按钮事件用法一致。
|
|
168
|
+
|
|
169
|
+
> **弹窗(popview)也在管辖内**:平台把弹窗挂在 `view.subviews`(与 `view.body` 平级的数组)。弹窗内控件用 `set_attrs`/`insert_node`/`remove_node`/`move_node`/`patch_node_array_item` 直接改;弹窗**根节点**(没有父节点)的增/改/删用 `patch_view_array_item`。详见「弹窗(popview)专章」。
|
|
167
170
|
|
|
168
171
|
### 输入
|
|
169
172
|
|
|
170
173
|
| 参数 | 类型 | 必填 | 说明 |
|
|
171
174
|
| --- | --- | --- | --- |
|
|
172
175
|
| `code` | string | 是 | 目标表单/页面唯一编码 |
|
|
173
|
-
| `ops` | array | 是 | 补丁操作数组,至少 1 个;按顺序依次作用于上一步结果。
|
|
176
|
+
| `ops` | array | 是 | 补丁操作数组,至少 1 个;按顺序依次作用于上一步结果。15 类 op 见下 |
|
|
174
177
|
| `commitMessage` | object | 是 | 提交信息,整批 ops 共用一个 |
|
|
175
178
|
| `dryRun` | boolean | 否 | 只预演并输出 diff、不落库,**默认 false** |
|
|
176
179
|
| `verify` | boolean | 否 | 保存后回读校验,**默认 true** |
|
|
177
180
|
|
|
178
|
-
###
|
|
181
|
+
### 15 类 op 一览
|
|
179
182
|
|
|
180
183
|
| op | 定位 | 关键字段 | 说明 |
|
|
181
184
|
| --- | --- | --- | --- |
|
|
182
185
|
| `set_pageinfo` | — | `patch` | 浅合并 pageinfo(如 `{ "title": "新标题", "status": "1" }`) |
|
|
183
|
-
| `set_attrs` | view
|
|
184
|
-
| `patch_node_array_item` | 节点内数组 | `nodeCode`、`arrayProp`(如 `cols`/`options`/`content`)、`mode`、其余见下 |
|
|
186
|
+
| `set_attrs` | view 树节点(body + subviews 弹窗)、controls | `code`、`patch`、`overwriteArray?` | 按 code 定位节点**浅合并属性**。⚠️ 范围是 `view.body` 树、**`view.subviews` 里的弹窗及其内部控件**、`controls` 数组(action 结构改用 patch_action_array_item)。⚠️ **patch 含数组属性默认阻断**(ARRAY_OVERWRITE_BLOCKED,防误改丢列——曾致 36 列丢失);确要整段覆盖须显式 `overwriteArray:true`,否则改用 patch_node_array_item / patch_action_array_item / patch_view_array_item 做元素级增改删 |
|
|
187
|
+
| `patch_node_array_item` | 节点内数组 | `nodeCode`、`arrayProp`(如 `cols`/`options`/`content`/`eventlist`)、`mode`、其余见下 | 节点内**数组元素级**操作,四种模式 + 两级嵌套,详见下节。`nodeCode` 可为**弹窗节点或弹窗内控件**(弹窗 `eventlist` 与其内部节点的事件都用它追加) |
|
|
188
|
+
| `patch_view_array_item` | **view 级数组**(`subviews`) | `arrayProp`(弹窗用 `"subviews"`)、`mode`、`itemKeyValue`、`item`/`patch`、`createIfMissing?`、`checkRefs?`、其余见下 | **弹窗根节点**的增/改/删:base 是整份 `view` 而非某个节点。append 新建弹窗(首次须 `createIfMissing:true`)、merge 改 title/needconfirm 等、remove 删弹窗(默认校验 `popsubview` 引用)。四模式 + 两级嵌套同下节 |
|
|
185
189
|
| `patch_action_array_item` | handler action 内数组 | `handlerCode`、`arrayProp`(如 `setter`)、`mode`、其余见下 | presenter.handlers/initial 中某 **action 内部数组**(如 `datarequest.setter` 界面输出绑定到控件、`param.properties`),四种模式 + 两级嵌套 |
|
|
186
190
|
| `add_action` | handler 的 `actions[]` | `handlerCode`、`scope?`、`type?`(默认 `flycode`)、`code?`、`desc?`、`condition?`、`position?`、`script?`、`fields?` | **追加一条动作**,按 type 自动补平台空骨架;`initial` 仅允许 `flycode`/`receivelink`;`code` 默认 `action_<handlerCode 末8位>`(同 handler 内重复自动加 `_2`/`_3`)。详见「动作的增/改/删」 |
|
|
187
191
|
| `patch_action` | handler 的单条 action | `handlerCode`、`scope?`、`actionCode?`/`actionIndex?`、`patch` | **浅合并任意字段**(`desc`/`condition`/`message`/`url`/`logiccode`/`queue`…,`script` 仅 flycode 可写)。⚠️ 不能含 `type`/`code`(换类型或改名走 `remove_action` + `add_action`) |
|
|
188
192
|
| `remove_action` | 同上 | 同上(无 `patch`) | **删除一条动作**;删空后保留 `actions: []`(不删属性,与平台形态一致) |
|
|
189
|
-
| `insert_node` | view
|
|
190
|
-
| `remove_node` | view
|
|
191
|
-
| `move_node` | view
|
|
193
|
+
| `insert_node` | view 树(body + subviews) | `parentCode`、`node`(新节点对象)、`position?`(默认末尾) | 插入新节点。`parentCode` 可为**弹窗 code**(往弹窗 `content` 加控件) |
|
|
194
|
+
| `remove_node` | view 树(body + subviews) | `code`、`checkRefs?`(默认 true:存在事件/handler 引用时拒绝删除) | 删除节点。`code` 可为**弹窗根节点**;`checkRefs` 也会拦「仍有 `popsubview`/`closesubview` 的 `viewcode` 指向该弹窗」。删掉最后一个弹窗后 `subviews` 属性被清掉(不留 `[]`) |
|
|
195
|
+
| `move_node` | view 树(body + subviews) | `code`、`newParentCode`、`position?` | 移动节点到新父节点;body 与弹窗之间可互移 |
|
|
192
196
|
| `set_section` | 整段 | `section`(`view`/`presenter`/`controls`/`pageswitch`)、`value` | 整段替换(大 payload,慎用) |
|
|
193
197
|
| `replace_script` | handler 的脚本字段 | `handlerCode`、`actionIndex?`/`actionCode?`、`field?`(`script`(默认)/`condition`/`expression`)、`scope?`(`handlers`/`initial`)、`replacement?` 或 `ops[]` | 改 UI 脚本。`replacement` 整段替换优先于 `ops`;`ops[]` 每项 `{ oldString(唯一命中), newString(空串=删除), replaceAll?, occurrence?, matchMode?, label? }`。⚠️ handlerCode 同名跨容器须加 `scope`(或等价别名 `handlerScope`)消歧 |
|
|
194
198
|
| `add_businessmodel` | — | `modellogiccode`、`overwrite?` | **MCP 自动拉取该逻辑完整 JSON** 追加到 businessmodel(无需传大段逻辑 JSON);已存在时默认跳过,`overwrite:true` 覆盖 |
|
|
195
199
|
| `remove_businessmodel` | — | `modellogiccode`、`checkRefs?`(默认 true) | 移除引用 |
|
|
196
200
|
|
|
197
|
-
### 数组元素级操作详解(patch_node_array_item / patch_action_array_item 共用语义)
|
|
201
|
+
### 数组元素级操作详解(patch_node_array_item / patch_view_array_item / patch_action_array_item 共用语义)
|
|
202
|
+
|
|
203
|
+
> 三者字段语义一致,差别只在 **base(基准容器)**:`patch_node_array_item` 的 base 是 `view` 树里的某个节点(`nodeCode` 定位);`patch_view_array_item` 的 base 是**整份 `view`**(没有 `nodeCode`,弹窗用 `arrayProp:"subviews"`);`patch_action_array_item` 的 base 是某 handler 的某 action(`handlerCode` → `actionCode` → `parentProp`)。
|
|
198
204
|
|
|
199
205
|
| 字段 | 必填 | 说明 |
|
|
200
206
|
| --- | --- | --- |
|
|
@@ -204,14 +210,15 @@
|
|
|
204
210
|
| `item` / `position` / `patch` | 条件 | append/insert 的新元素 / 插入下标 / merge 的浅合并属性 |
|
|
205
211
|
| `elementArrayProp` | 否 | **【两级嵌套】**目标在「数组内某元素的嵌套数组」时填子数组名(如 `setter[0].properties` 的 `properties`);必须配合 itemKey/itemKeyValue 先定位外层元素 |
|
|
206
212
|
| `elementItemKey` / `elementItemKeyValue` | 否 | 两级模式下定位嵌套数组内子元素的键/键值(merge/remove 用) |
|
|
207
|
-
| `createIfMissing` | 否 | append/insert 时目标数组(含两级嵌套目标)不存在是否自动新建,**默认 false——fail-closed 报 ARRAY_NOT_FOUND**(防误造平行 orphan 结构,如错层 `datarequest.setter`);确需新建才显式置 true |
|
|
213
|
+
| `createIfMissing` | 否 | append/insert 时目标数组(含两级嵌套目标)不存在是否自动新建,**默认 false——fail-closed 报 ARRAY_NOT_FOUND**(防误造平行 orphan 结构,如错层 `datarequest.setter`);确需新建才显式置 true。⚠️ 表单**首次加弹窗**时 `view.subviews` 通常不存在,必须置 true |
|
|
214
|
+
| `checkRefs` | 否 | **仅 `patch_view_array_item`**:`mode:"remove"` 删**顶层弹窗**时是否校验引用(`popsubview`/`closesubview` 的 `viewcode`),默认 true → 仍被打开动作指向时报 `REF_VIOLATION`;确需强删置 false。删弹窗内嵌套元素时不生效 |
|
|
208
215
|
|
|
209
216
|
### 输出
|
|
210
217
|
|
|
211
218
|
| 字段 | 类型 | 说明 |
|
|
212
219
|
| --- | --- | --- |
|
|
213
220
|
| `ok` / `applied` / `verified` / `message` | — | 同 patch_model_logic 口径 |
|
|
214
|
-
| `errorCode` | string | `OK` / `DRY_RUN` / `EMPTY_OPS` / `FETCH_FAILED` / `NODE_NOT_FOUND` / `DUP_CODE` / `REF_VIOLATION` / `OPS_FAILED` / `SAVE_FAILED` / `VERIFY_FAILED` / `ARRAY_OVERWRITE_BLOCKED` / `ARRAY_NOT_FOUND` / `TYPE_NOT_ALLOWED` / `NO_TARGET` / `INVALID_PARAMS` |
|
|
221
|
+
| `errorCode` | string | `OK` / `DRY_RUN` / `EMPTY_OPS` / `FETCH_FAILED` / `NODE_NOT_FOUND` / `DUP_CODE` / `REF_VIOLATION` / `OPS_FAILED` / `SAVE_FAILED` / `VERIFY_FAILED` / `ARRAY_OVERWRITE_BLOCKED` / `ARRAY_NOT_FOUND` / `TYPE_NOT_ALLOWED` / `NO_TARGET` / `INVALID_PARAMS`。⚠️ `REF_VIOLATION` 也覆盖「弹窗仍被 `popsubview`/`closesubview` 的 `viewcode` 指向」——先 `remove_action` 解引用或传 `checkRefs:false` |
|
|
215
222
|
| `diff` | string | 全部 op 的 diff 片段(超长截断;只回改动摘要不回整份表单) |
|
|
216
223
|
| `ops` | array | 每个 op 的结果:`{ index, op, status, errorCode, message, hunk?(replace_script 才有), suggestions?(NOT_FOUND 时的相似候选 [{startLine, score, preview}]) }` |
|
|
217
224
|
|
|
@@ -271,6 +278,56 @@
|
|
|
271
278
|
|
|
272
279
|
误把嵌套数组当顶层 append 会被 `ARRAY_NOT_FOUND` 阻断(默认 fail-closed,不会污染表单);remove 删后数组变空会自动删除该数组属性,不留 `{"properties":[]}` 空壳。
|
|
273
280
|
|
|
281
|
+
### 弹窗(popview)专章:读、改、加、删
|
|
282
|
+
|
|
283
|
+
**结构**:弹窗挂在 `view.subviews`——一个与 `view.body` **平级的数组**(不是某个节点的 `content`);每项是弹窗根节点,`type: "popview"`,弹窗内控件挂在它的 `content` 下。实测(采购订单-V6.0-详情,4 个弹窗)弹窗根节点**恰好 9 个字段**:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
{ "type":"popview", "code":"…", "title":"货补", "flexdirection":"vertical",
|
|
287
|
+
"needconfirm":"1", "confirmtitle":"确定", "resetwhenopen":"1",
|
|
288
|
+
"content":[...], "eventlist":[{ "trigger":"onopen", "handler":"…" }] }
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
⚠️ **没有 `showclosebutton`**(设计器里那条是可选字段,别硬编进模板);弹窗事件 `trigger` 只有 **`onopen` / `onconfirm`**(不是 `onclicked`)。
|
|
292
|
+
|
|
293
|
+
**先拿到弹窗 code**:`get_form_outline` 的 `subviews`(`viewTree` 里没有弹窗);要看整段弹窗源码用 `get_form_fragment({ section:"subviews" })`,要看单个弹窗用 `get_form_fragment({ nodeCode: 弹窗code })`。
|
|
294
|
+
|
|
295
|
+
| 想做的事 | 用哪个 op |
|
|
296
|
+
| --- | --- |
|
|
297
|
+
| 改弹窗属性(`title` / `needconfirm` / `confirmtitle` / `resetwhenopen` / `flexdirection`) | `set_attrs{code:弹窗code, patch:{…}}`,或 `patch_view_array_item{mode:"merge", itemKeyValue:弹窗code, patch:{…}}` |
|
|
298
|
+
| 弹窗**内**加控件 | `insert_node{parentCode: 弹窗code, node:{…}}` |
|
|
299
|
+
| 弹窗**内**删控件 / 移动控件 | `remove_node{code}` / `move_node{code, newParentCode}` |
|
|
300
|
+
| 给弹窗自身或弹窗内控件加事件 | `patch_node_array_item{nodeCode:弹窗code或控件code, arrayProp:"eventlist", mode:"append", item:{trigger:"onopen", handler:"…"}}` |
|
|
301
|
+
| 弹窗内表格的列 / 下拉选项 | `patch_node_array_item{nodeCode:弹窗内节点code, arrayProp:"cols"/"options", …}` |
|
|
302
|
+
| **新建弹窗** | `patch_view_array_item{arrayProp:"subviews", mode:"append", createIfMissing:true, item:{…完整 popview 节点…}}` |
|
|
303
|
+
| **删除弹窗** | 见下(两条等价路径) |
|
|
304
|
+
| 打开弹窗(按钮事件) | `add_action{handlerCode, type:"popsubview", fields:{"viewcode":弹窗code, "viewwidth":"1020", "viewheight":"580", "viewtitle":"", "popupmode":"center"}}`——模板已内置,无需手写骨架 |
|
|
305
|
+
|
|
306
|
+
**新建弹窗示例**(首次加弹窗时 `view.subviews` 不存在,必须 `createIfMissing:true`,否则报 `ARRAY_NOT_FOUND`):
|
|
307
|
+
|
|
308
|
+
```jsonc
|
|
309
|
+
{ "op": "patch_view_array_item", "arrayProp": "subviews", "mode": "append", "createIfMissing": true,
|
|
310
|
+
"item": { "type": "popview", "code": "生成的新code", "title": "货补", "flexdirection": "vertical",
|
|
311
|
+
"needconfirm": "1", "confirmtitle": "确定", "resetwhenopen": "1",
|
|
312
|
+
"content": [], "eventlist": [] } }
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**删除弹窗(两条等价路径,都默认校验引用)**:
|
|
316
|
+
|
|
317
|
+
```jsonc
|
|
318
|
+
// A. 通用节点删除(弹窗根也支持)
|
|
319
|
+
{ "op": "remove_node", "code": "1501119668772016226" }
|
|
320
|
+
// B. view 数组级删除
|
|
321
|
+
{ "op": "patch_view_array_item", "arrayProp": "subviews", "mode": "remove", "itemKeyValue": "1501119668772016226" }
|
|
322
|
+
// 强删(跳过引用校验)
|
|
323
|
+
{ "op": "remove_node", "code": "…", "checkRefs": false }
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
- 弹窗常被 `popsubview` / `closesubview` 动作的 `viewcode` 指向 → 直接删会报 **`REF_VIOLATION`**。正确顺序:先 `remove_action` 掉指向它的打开动作,再删;确需保留动作悬空才用 `checkRefs:false`。
|
|
327
|
+
- 删掉**最后一个**弹窗后 `subviews` 属性会被清掉(回读为 `undefined`,不留 `[]` 空壳)。
|
|
328
|
+
|
|
329
|
+
**红线**:弹窗内控件的 `code` 常被 `datarequest.setter` 等绑定引用(线上单表单实测 48 处)——**不要改弹窗内控件的 code、不要删仍被引用的节点**;patch 前先 `get_form_fragment({nodeCode})` 核对真实属性名与引用关系。
|
|
330
|
+
|
|
274
331
|
---
|
|
275
332
|
|
|
276
333
|
## `save_form` — 全量保存表单(写,整页重构才用)
|
|
@@ -296,3 +353,4 @@
|
|
|
296
353
|
|
|
297
354
|
- **禁止对已有大表单整份回传**:极易超长截断、误改不相关字段;当且仅当 JSON 过大无法内联且局部工具无法满足时,才可用 SKILL.md「八、超大 JSON 全量保存的官方脚本」(真·MCP 客户端,非直连 REST)。
|
|
298
355
|
- 全量保存会覆盖整个表单:回传前确认来源是最新的 `get_form` 结果,且改动点都已应用。
|
|
356
|
+
- **含弹窗的表单不要用 `save_form` 兜底**:它按提交内容整份覆盖,用改动前的旧快照保存会把 `view.subviews`(弹窗及其 `eventlist`)一起抹掉——线上「布局测试」就因此丢过弹窗。弹窗现已能用 `patch_form` 直接改(见上节),没有理由再走全量。
|