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.
package/dist/cli.js CHANGED
@@ -3712,6 +3712,51 @@ function findViewNode(root, code) {
3712
3712
  }
3713
3713
  return null;
3714
3714
  }
3715
+ function viewRoots(form) {
3716
+ const roots = [];
3717
+ if (form.view?.body) roots.push(form.view.body);
3718
+ for (const sub of rawSubViews(form) ?? []) {
3719
+ if (sub && typeof sub === "object") roots.push(sub);
3720
+ }
3721
+ return roots;
3722
+ }
3723
+ function rawSubViews(form) {
3724
+ const subs = form.view?.subviews;
3725
+ return Array.isArray(subs) ? subs : null;
3726
+ }
3727
+ function findViewNodeInForm(form, code) {
3728
+ for (const root of viewRoots(form)) {
3729
+ const found = findViewNode(root, code);
3730
+ if (found) return found;
3731
+ }
3732
+ return null;
3733
+ }
3734
+ function viewNodeContainers(form) {
3735
+ const out = [];
3736
+ const walk = (node) => {
3737
+ if (!node) return;
3738
+ if (Array.isArray(node.content)) {
3739
+ out.push(node.content);
3740
+ node.content.forEach(walk);
3741
+ }
3742
+ };
3743
+ for (const root of viewRoots(form)) walk(root);
3744
+ const subs = rawSubViews(form);
3745
+ if (subs) out.push(subs);
3746
+ if (Array.isArray(form.controls)) out.push(form.controls);
3747
+ return out;
3748
+ }
3749
+ function locateViewNode(form, code) {
3750
+ for (const arr of viewNodeContainers(form)) {
3751
+ for (let i = 0; i < arr.length; i++) {
3752
+ const it = arr[i];
3753
+ if (it && typeof it === "object" && it.code === code) {
3754
+ return { node: it, siblings: arr, index: i };
3755
+ }
3756
+ }
3757
+ }
3758
+ return null;
3759
+ }
3715
3760
  function collectAllNodes(form) {
3716
3761
  const out = [];
3717
3762
  const walk = (node) => {
@@ -3719,7 +3764,7 @@ function collectAllNodes(form) {
3719
3764
  out.push(node);
3720
3765
  if (Array.isArray(node.content)) node.content.forEach(walk);
3721
3766
  };
3722
- walk(form.view?.body ?? null);
3767
+ for (const root of viewRoots(form)) walk(root);
3723
3768
  if (Array.isArray(form.controls)) form.controls.forEach((c) => {
3724
3769
  if (c) out.push(c);
3725
3770
  });
@@ -3744,30 +3789,11 @@ function findElementByCodeDeep(node, code) {
3744
3789
  }
3745
3790
  return null;
3746
3791
  }
3747
- function detachViewNode(root, code) {
3748
- if (!root?.content) return null;
3749
- const idx = root.content.findIndex((c) => c?.code === code);
3750
- if (idx >= 0) {
3751
- const [n] = root.content.splice(idx, 1);
3752
- return n ?? null;
3753
- }
3754
- for (const child of root.content) {
3755
- const found = detachViewNode(child, code);
3756
- if (found) return found;
3757
- }
3758
- return null;
3759
- }
3760
3792
  function detachNodeAnywhere(form, code) {
3761
- const fromTree = detachViewNode(form.view?.body ?? null, code);
3762
- if (fromTree) return fromTree;
3763
- if (Array.isArray(form.controls)) {
3764
- const i = form.controls.findIndex((c) => c?.code === code);
3765
- if (i >= 0) {
3766
- const [n] = form.controls.splice(i, 1);
3767
- return n ?? null;
3768
- }
3769
- }
3770
- return null;
3793
+ const loc = locateViewNode(form, code);
3794
+ if (!loc) return null;
3795
+ const [n] = loc.siblings.splice(loc.index, 1);
3796
+ return n ?? null;
3771
3797
  }
3772
3798
  function collectReferencedCodes(form) {
3773
3799
  const set = /* @__PURE__ */ new Set();
@@ -3777,10 +3803,13 @@ function collectReferencedCodes(form) {
3777
3803
  if (Array.isArray(node.content)) node.content.forEach(walk);
3778
3804
  };
3779
3805
  walk(form.view?.body ?? null);
3806
+ for (const root of viewRoots(form)) walk(root);
3780
3807
  for (const h of form.presenter?.handlers ?? []) {
3781
3808
  for (const a of h?.actions ?? []) {
3782
3809
  if (a?.handler) set.add(a.handler);
3783
3810
  if (a?.logiccode) set.add(a.logiccode);
3811
+ const viewcode = a?.viewcode;
3812
+ if (viewcode) set.add(viewcode);
3784
3813
  }
3785
3814
  for (const e of h?.eventlist ?? []) if (e?.handler) set.add(e.handler);
3786
3815
  }
@@ -3788,11 +3817,17 @@ function collectReferencedCodes(form) {
3788
3817
  for (const a of h?.actions ?? []) {
3789
3818
  if (a?.handler) set.add(a.handler);
3790
3819
  if (a?.logiccode) set.add(a.logiccode);
3820
+ const viewcode = a?.viewcode;
3821
+ if (viewcode) set.add(viewcode);
3791
3822
  }
3792
3823
  for (const e of h?.eventlist ?? []) if (e?.handler) set.add(e.handler);
3793
3824
  }
3794
3825
  for (const i of form.presenter?.interface ?? []) {
3795
- for (const a of i?.actions ?? []) if (a?.handler) set.add(a.handler);
3826
+ for (const a of i?.actions ?? []) {
3827
+ if (a?.handler) set.add(a.handler);
3828
+ const viewcode = a?.viewcode;
3829
+ if (viewcode) set.add(viewcode);
3830
+ }
3796
3831
  }
3797
3832
  return set;
3798
3833
  }
@@ -3854,6 +3889,8 @@ async function getFormOutline(code) {
3854
3889
  marktype: form.pageinfo?.marktype ?? null,
3855
3890
  versionnum: form.pageinfo?.versionnum ?? null,
3856
3891
  viewTree: form.view?.body ? [buildViewTree(form.view.body)] : [],
3892
+ // 弹窗单列一段:viewTree 保持「页面主体」的既有语义不变,避免调用方把弹窗当成 body 子节点
3893
+ subviews: (rawSubViews(form) ?? []).filter((s) => Boolean(s) && typeof s === "object").map((s) => buildViewTree(s)),
3857
3894
  handlers,
3858
3895
  interfaces,
3859
3896
  businessModels,
@@ -3869,8 +3906,11 @@ async function getFormFragment(code, opts) {
3869
3906
  let section;
3870
3907
  let fragmentMessage = form.message ?? null;
3871
3908
  if (opts.nodeCode) {
3872
- node = findViewNode(form.view?.body ?? null, opts.nodeCode) ?? form.controls?.find((c) => c?.code === opts.nodeCode) ?? null;
3873
- if (node && opts.itemCode) {
3909
+ node = findViewNodeInForm(form, opts.nodeCode) ?? form.controls?.find((c) => c?.code === opts.nodeCode) ?? null;
3910
+ if (!node) {
3911
+ const subviewCount = rawSubViews(form)?.length ?? 0;
3912
+ fragmentMessage = `\u672A\u627E\u5230 code=${opts.nodeCode} \u7684\u8282\u70B9\uFF08\u5DF2\u68C0\u7D22 view.body \u6811\u3001view.subviews \u5F39\u7A97 ${subviewCount} \u4E2A\u3001controls\uFF09`;
3913
+ } else if (opts.itemCode) {
3874
3914
  const elem = findElementByCodeDeep(node, opts.itemCode);
3875
3915
  if (elem) {
3876
3916
  node = elem;
@@ -3887,10 +3927,13 @@ async function getFormFragment(code, opts) {
3887
3927
  } else if (found.length > 1) {
3888
3928
  handler = null;
3889
3929
  fragmentMessage = `handlerCode=${opts.handlerCode} \u5728 handlers \u4E0E initial \u4E2D\u540C\u65F6\u51FA\u73B0\uFF0C\u8BF7\u7528 handlerScope \u6307\u5B9A\u552F\u4E00\u5BB9\u5668`;
3930
+ } else {
3931
+ handler = null;
3932
+ fragmentMessage = `\u672A\u627E\u5230 handlerCode=${opts.handlerCode} \u7684\u5904\u7406\u5668\uFF08\u5DF2\u68C0\u7D22 handlers \u4E0E initial${opts.handlerScope ? `\uFF0C\u672C\u6B21\u9650\u5B9A ${opts.handlerScope}` : ""}\uFF09`;
3890
3933
  }
3891
3934
  }
3892
3935
  if (opts.section) {
3893
- section = form[opts.section] ?? null;
3936
+ section = opts.section === "subviews" ? rawSubViews(form) ?? null : form[opts.section] ?? null;
3894
3937
  }
3895
3938
  const actionIndex = handler?.actions ? handler.actions.map((a, i) => ({
3896
3939
  index: i,
@@ -4093,6 +4136,32 @@ async function applyFormOp(form, op, index, resolvedActionCodes) {
4093
4136
  label: `\u8282\u70B9 ${op.nodeCode}`
4094
4137
  });
4095
4138
  }
4139
+ case "patch_view_array_item": {
4140
+ const view = form.view;
4141
+ if (!view) return fail("NODE_NOT_FOUND", "\u8868\u5355\u6CA1\u6709 view \u7ED3\u6784\uFF0C\u65E0\u6CD5\u64CD\u4F5C view \u7EA7\u6570\u7EC4");
4142
+ if ((op.mode ?? "merge") === "remove" && op.arrayProp === "subviews" && op.elementArrayProp == null && op.checkRefs !== false) {
4143
+ const target = op.itemKeyValue;
4144
+ if (typeof target === "string" && collectReferencedCodes(form).has(target)) {
4145
+ return fail("REF_VIOLATION", `\u4ECD\u6709\u4E8B\u4EF6/action \u7684 viewcode \u6307\u5411\u5F39\u7A97 ${target}\uFF0C\u79FB\u9664\u524D\u8BF7\u5148\u89E3\u9664\u5F15\u7528\uFF08\u6216 checkRefs=false \u5F3A\u5236\u5220\u9664\uFF09`);
4146
+ }
4147
+ }
4148
+ return applyArrayItem({
4149
+ base: view,
4150
+ arrayProp: op.arrayProp,
4151
+ elementArrayProp: op.elementArrayProp,
4152
+ mode: op.mode ?? "merge",
4153
+ itemKey: op.itemKey,
4154
+ itemKeyValue: op.itemKeyValue,
4155
+ elementItemKey: op.elementItemKey,
4156
+ elementItemKeyValue: op.elementItemKeyValue,
4157
+ item: op.item,
4158
+ position: op.position,
4159
+ patch: op.patch,
4160
+ createIfMissing: op.createIfMissing,
4161
+ // label 只给 "view":applyArrayItem 内部会拼 `label.arrayProp`,给成 view.subviews 会重复
4162
+ label: "view"
4163
+ });
4164
+ }
4096
4165
  case "patch_action_array_item": {
4097
4166
  const found = findPresenterHandlers(form, op.handlerCode, op.scope);
4098
4167
  if (found.length === 0) {
@@ -4256,8 +4325,8 @@ async function applyFormOp(form, op, index, resolvedActionCodes) {
4256
4325
  });
4257
4326
  }
4258
4327
  case "insert_node": {
4259
- const parent = findViewNode(form.view?.body ?? null, op.parentCode);
4260
- if (!parent) return fail("NODE_NOT_FOUND", `\u672A\u5728 view \u6811\u4E2D\u627E\u5230 parentCode=${op.parentCode} \u7684\u7236\u8282\u70B9`);
4328
+ const parent = findViewNodeInForm(form, op.parentCode);
4329
+ if (!parent) return fail("NODE_NOT_FOUND", `\u672A\u5728 view \u6811\uFF08\u542B subviews \u5F39\u7A97\uFF09\u4E2D\u627E\u5230 parentCode=${op.parentCode} \u7684\u7236\u8282\u70B9`);
4261
4330
  if (!parent.content) parent.content = [];
4262
4331
  const pos = op.position ?? parent.content.length;
4263
4332
  parent.content.splice(pos, 0, op.node);
@@ -4275,6 +4344,8 @@ async function applyFormOp(form, op, index, resolvedActionCodes) {
4275
4344
  }
4276
4345
  const detached = detachNodeAnywhere(form, op.code);
4277
4346
  if (!detached) return fail("NODE_NOT_FOUND", `\u8282\u70B9 ${op.code} \u6458\u9664\u5931\u8D25`);
4347
+ const remainSubs = rawSubViews(form);
4348
+ if (remainSubs && remainSubs.length === 0) delete form.view.subviews;
4278
4349
  return ok({ message: `\u5DF2\u79FB\u9664\u8282\u70B9 ${op.code}` });
4279
4350
  }
4280
4351
  case "move_node": {
@@ -4283,8 +4354,8 @@ async function applyFormOp(form, op, index, resolvedActionCodes) {
4283
4354
  if (matches.length > 1) return fail("DUP_CODE", `code=${op.code} \u5728\u8868\u5355\u4E2D\u51FA\u73B0 ${matches.length} \u6B21\uFF0C\u4E0D\u552F\u4E00`);
4284
4355
  const detached = detachNodeAnywhere(form, op.code);
4285
4356
  if (!detached) return fail("NODE_NOT_FOUND", `\u8282\u70B9 ${op.code} \u6458\u9664\u5931\u8D25`);
4286
- const parent = findViewNode(form.view?.body ?? null, op.newParentCode);
4287
- if (!parent) return fail("NODE_NOT_FOUND", `\u672A\u5728 view \u6811\u4E2D\u627E\u5230 newParentCode=${op.newParentCode} \u7684\u7236\u8282\u70B9`);
4357
+ const parent = findViewNodeInForm(form, op.newParentCode);
4358
+ if (!parent) return fail("NODE_NOT_FOUND", `\u672A\u5728 view \u6811\uFF08\u542B subviews \u5F39\u7A97\uFF09\u4E2D\u627E\u5230 newParentCode=${op.newParentCode} \u7684\u7236\u8282\u70B9`);
4288
4359
  if (!parent.content) parent.content = [];
4289
4360
  const pos = op.position ?? parent.content.length;
4290
4361
  parent.content.splice(pos, 0, detached);
@@ -4402,6 +4473,52 @@ function drillToArray(base, arrayProp, elementArrayProp, itemKey, itemKeyValue,
4402
4473
  if (!Array.isArray(nested)) return { error: `${arrayProp}[${itemKey}=${String(itemKeyValue)}].${elementArrayProp} \u975E\u6570\u7EC4` };
4403
4474
  return { finalArr: nested, finalProp: `${arrayProp}[${itemKey}=${String(itemKeyValue)}].${elementArrayProp}` };
4404
4475
  }
4476
+ function verifyArrayItemOnBase(base, op, label, i, problems) {
4477
+ const mode = op.mode ?? "merge";
4478
+ const locKey = op.elementArrayProp != null ? op.elementItemKey ?? "code" : op.itemKey ?? "code";
4479
+ const locValue = op.elementArrayProp != null ? op.elementItemKeyValue : op.itemKeyValue;
4480
+ if (mode === "remove") {
4481
+ const outer = base[op.arrayProp];
4482
+ let target = null;
4483
+ if (op.elementArrayProp != null) {
4484
+ if (Array.isArray(outer)) {
4485
+ const outerElem = outer.find((it) => it && typeof it === "object" && it[op.itemKey ?? "code"] === op.itemKeyValue);
4486
+ target = outerElem ? outerElem[op.elementArrayProp] ?? null : null;
4487
+ }
4488
+ } else {
4489
+ target = Array.isArray(outer) ? outer : null;
4490
+ }
4491
+ if (target == null) return;
4492
+ if (target.some((it) => it && typeof it === "object" && it[locKey] === locValue)) {
4493
+ problems.push(`ops[${i}] ${label} remove \u5143\u7D20 ${locKey}=${String(locValue)} \u4ECD\u5B58\u5728`);
4494
+ }
4495
+ return;
4496
+ }
4497
+ const drilled = drillToArray(base, op.arrayProp, op.elementArrayProp, op.itemKey, op.itemKeyValue, op.elementItemKey, op.elementItemKeyValue);
4498
+ if ("error" in drilled) {
4499
+ problems.push(`ops[${i}] ${label} ${drilled.error}`);
4500
+ return;
4501
+ }
4502
+ const arr = drilled.finalArr;
4503
+ if (mode === "append" || mode === "insert") {
4504
+ if (!op.item) {
4505
+ problems.push(`ops[${i}] ${label} ${mode} \u7F3A item`);
4506
+ return;
4507
+ }
4508
+ if (!arrayContains(arr, op.item)) problems.push(`ops[${i}] ${label} ${mode} \u5143\u7D20\u672A\u51FA\u73B0`);
4509
+ return;
4510
+ }
4511
+ const elem = arr.find((it) => it && typeof it === "object" && it[locKey] === locValue);
4512
+ if (!elem) {
4513
+ problems.push(`ops[${i}] ${label} \u5143\u7D20 ${locKey}=${String(locValue)} \u672A\u627E\u5230`);
4514
+ return;
4515
+ }
4516
+ for (const [k, v] of Object.entries(op.patch ?? {})) {
4517
+ if (JSON.stringify(elem[k]) !== JSON.stringify(v)) {
4518
+ problems.push(`ops[${i}] ${label}.${k} \u672A\u751F\u6548`);
4519
+ }
4520
+ }
4521
+ }
4405
4522
  function verifyPatch(form2, ops, baseline, resolvedActionCodes) {
4406
4523
  const problems = [];
4407
4524
  const nodes = collectAllNodes(form2);
@@ -4435,51 +4552,16 @@ function verifyPatch(form2, ops, baseline, resolvedActionCodes) {
4435
4552
  problems.push(`ops[${i}] patch_node_array_item \u8282\u70B9 ${op.nodeCode} \u6D88\u5931`);
4436
4553
  break;
4437
4554
  }
4438
- const base = n;
4439
- const mode = op.mode ?? "merge";
4440
- const locKey = op.elementArrayProp != null ? op.elementItemKey ?? "code" : op.itemKey ?? "code";
4441
- const locValue = op.elementArrayProp != null ? op.elementItemKeyValue : op.itemKeyValue;
4442
- if (mode === "remove") {
4443
- const outer = base[op.arrayProp];
4444
- let target = null;
4445
- if (op.elementArrayProp != null) {
4446
- if (Array.isArray(outer)) {
4447
- const outerElem = outer.find((it) => it && typeof it === "object" && it[op.itemKey ?? "code"] === op.itemKeyValue);
4448
- target = outerElem ? outerElem[op.elementArrayProp] ?? null : null;
4449
- }
4450
- } else {
4451
- target = Array.isArray(outer) ? outer : null;
4452
- }
4453
- if (target == null) break;
4454
- if (target.some((it) => it && typeof it === "object" && it[locKey] === locValue)) {
4455
- problems.push(`ops[${i}] patch_node_array_item remove \u5143\u7D20 ${locKey}=${String(locValue)} \u4ECD\u5B58\u5728`);
4456
- }
4457
- break;
4458
- }
4459
- const drilled = drillToArray(base, op.arrayProp, op.elementArrayProp, op.itemKey, op.itemKeyValue, op.elementItemKey, op.elementItemKeyValue);
4460
- if ("error" in drilled) {
4461
- problems.push(`ops[${i}] patch_node_array_item ${drilled.error}`);
4462
- break;
4463
- }
4464
- const arr = drilled.finalArr;
4465
- if (mode === "append" || mode === "insert") {
4466
- if (!op.item) {
4467
- problems.push(`ops[${i}] patch_node_array_item ${mode} \u7F3A item`);
4468
- break;
4469
- }
4470
- if (!arrayContains(arr, op.item)) problems.push(`ops[${i}] patch_node_array_item ${mode} \u5143\u7D20\u672A\u51FA\u73B0`);
4471
- break;
4472
- }
4473
- const elem = arr.find((it) => it && typeof it === "object" && it[locKey] === locValue);
4474
- if (!elem) {
4475
- problems.push(`ops[${i}] patch_node_array_item \u5143\u7D20 ${locKey}=${String(locValue)} \u672A\u627E\u5230`);
4555
+ verifyArrayItemOnBase(n, op, "patch_node_array_item", i, problems);
4556
+ break;
4557
+ }
4558
+ case "patch_view_array_item": {
4559
+ const v = form2.view;
4560
+ if (!v) {
4561
+ problems.push(`ops[${i}] patch_view_array_item \u8868\u5355\u6CA1\u6709 view \u7ED3\u6784`);
4476
4562
  break;
4477
4563
  }
4478
- for (const [k, v] of Object.entries(op.patch ?? {})) {
4479
- if (JSON.stringify(elem[k]) !== JSON.stringify(v)) {
4480
- problems.push(`ops[${i}] patch_node_array_item.${k} \u672A\u751F\u6548`);
4481
- }
4482
- }
4564
+ verifyArrayItemOnBase(v, op, "patch_view_array_item", i, problems);
4483
4565
  break;
4484
4566
  }
4485
4567
  case "patch_action_array_item": {
@@ -5081,7 +5163,7 @@ var init_form2 = __esm({
5081
5163
 
5082
5164
  // src/tools/form/read.ts
5083
5165
  import { z as z9 } from "zod";
5084
- var formPageResultShape, formResultShape, readTools3;
5166
+ var outlineViewNodeSchema, formPageResultShape, formResultShape, readTools3;
5085
5167
  var init_read3 = __esm({
5086
5168
  "src/tools/form/read.ts"() {
5087
5169
  "use strict";
@@ -5089,6 +5171,17 @@ var init_read3 = __esm({
5089
5171
  init_form();
5090
5172
  init_form2();
5091
5173
  init_result();
5174
+ outlineViewNodeSchema = z9.object({
5175
+ code: z9.union([z9.string(), z9.null()]).optional(),
5176
+ type: z9.union([z9.string(), z9.null()]).optional(),
5177
+ title: z9.union([z9.string(), z9.null()]).optional(),
5178
+ children: z9.array(z9.object({
5179
+ code: z9.union([z9.string(), z9.null()]).optional(),
5180
+ type: z9.union([z9.string(), z9.null()]).optional(),
5181
+ title: z9.union([z9.string(), z9.null()]).optional(),
5182
+ children: z9.array(z9.unknown()).optional()
5183
+ })).optional()
5184
+ });
5092
5185
  formPageResultShape = z9.object({
5093
5186
  createtime: z9.union([z9.string(), z9.null()]).optional().describe("\u521B\u5EFA\u65F6\u95F4"),
5094
5187
  createaccountcode: z9.union([z9.string(), z9.null()]).optional().describe("\u521B\u5EFA\u4EBA\u7684\u8D26\u53F7\u7F16\u7801"),
@@ -5311,7 +5404,7 @@ ${FORM_ENUM}`,
5311
5404
  name: "get_form_outline",
5312
5405
  config: {
5313
5406
  title: "\u67E5\u8BE2\u8868\u5355/\u9875\u9762\u9AA8\u67B6",
5314
- description: `\u83B7\u53D6\u8868\u5355\u8F7B\u91CF\u9AA8\u67B6\uFF08\u7EA6 2\u20134KB\uFF09\uFF1Apageinfo \u5173\u952E\u5B57\u6BB5\u3001view \u6811\u9AA8\u67B6\u3001presenter \u7684 handlers \u4E0E initial \u5904\u7406\u5668\u6E05\u5355\uFF08\u6BCF\u9879\u5E26 scope \u6807\u6CE8\uFF09\u3001businessmodel \u903B\u8F91\u540D\u3002\u7528\u4E8E\u62FF\u5168\u8C8C\u4E0E\u6240\u6709\u53EF\u6539\u5BF9\u8C61 code\uFF0C\u907F\u514D\u76F2\u6539\u3002\u6CE8\u610F\u9875\u9762\u521D\u59CB\u5316\u811A\u672C\u5728 presenter.initial\uFF08scope='initial'\uFF09\u3002
5407
+ description: `\u83B7\u53D6\u8868\u5355\u8F7B\u91CF\u9AA8\u67B6\uFF08\u6570 KB\uFF0C\u968F\u63A7\u4EF6\u6570\u91CF\u589E\u957F\uFF09\uFF1Apageinfo \u5173\u952E\u5B57\u6BB5\u3001view \u6811\u9AA8\u67B6\uFF08body\uFF09\u3001\u5F39\u7A97\u89C6\u56FE\u9AA8\u67B6\uFF08subviews\uFF0C\u5143\u7D20 type=popview\uFF09\u3001presenter \u7684 handlers \u4E0E initial \u5904\u7406\u5668\u6E05\u5355\uFF08\u6BCF\u9879\u5E26 scope \u6807\u6CE8\uFF09\u3001businessmodel \u903B\u8F91\u540D\u3002\u7528\u4E8E\u62FF\u5168\u8C8C\u4E0E\u6240\u6709\u53EF\u6539\u5BF9\u8C61 code\uFF0C\u907F\u514D\u76F2\u6539\u3002\u6CE8\u610F\u9875\u9762\u521D\u59CB\u5316\u811A\u672C\u5728 presenter.initial\uFF08scope='initial'\uFF09\uFF1B\u5F39\u7A97\u53CA\u5176\u5185\u90E8\u63A7\u4EF6\u7684 code \u53EA\u51FA\u73B0\u5728 subviews \u91CC\uFF0C\u4E0D\u5728 viewTree \u4E2D\u3002
5315
5408
 
5316
5409
  ${FORM_ENUM}`,
5317
5410
  inputSchema: {
@@ -5325,17 +5418,8 @@ ${FORM_ENUM}`,
5325
5418
  clientcategorycode: z9.union([z9.string(), z9.null()]).optional().describe("\u7528\u6237\u7AEF\u5206\u7C7B"),
5326
5419
  marktype: z9.union([z9.string(), z9.null()]).optional().describe("\u521B\u5EFA\u6807\u8BB0"),
5327
5420
  versionnum: z9.union([z9.string(), z9.null()]).optional().describe("\u7248\u672C\u53F7"),
5328
- viewTree: z9.array(z9.lazy(() => z9.object({
5329
- code: z9.union([z9.string(), z9.null()]).optional(),
5330
- type: z9.union([z9.string(), z9.null()]).optional(),
5331
- title: z9.union([z9.string(), z9.null()]).optional(),
5332
- children: z9.array(z9.lazy(() => z9.object({
5333
- code: z9.union([z9.string(), z9.null()]).optional(),
5334
- type: z9.union([z9.string(), z9.null()]).optional(),
5335
- title: z9.union([z9.string(), z9.null()]).optional(),
5336
- children: z9.array(z9.unknown()).optional()
5337
- }))).optional()
5338
- }))).optional().describe("view \u6811\u9AA8\u67B6\uFF08\u9012\u5F52\uFF0C\u4EC5 code/type/title + children\uFF09"),
5421
+ viewTree: z9.array(outlineViewNodeSchema).optional().describe("view \u6811\u9AA8\u67B6\uFF08body \u9875\u9762\u4E3B\u4F53\uFF0C\u9012\u5F52\uFF0C\u4EC5 code/type/title + children\uFF09"),
5422
+ subviews: z9.array(outlineViewNodeSchema).optional().describe("\u5F39\u7A97\u89C6\u56FE\u9AA8\u67B6\uFF08view.subviews\uFF0C\u5143\u7D20 type=popview\uFF09\uFF0C\u6BCF\u9879\u4E00\u68F5\u4E0E viewTree \u540C\u6784\u7684\u6811\uFF1B\u5F39\u7A97\u53CA\u5176\u5185\u90E8\u63A7\u4EF6\u7684 code \u53EA\u80FD\u4ECE\u8FD9\u91CC\u62FF\u5230"),
5339
5423
  handlers: z9.array(z9.object({
5340
5424
  code: z9.union([z9.string(), z9.null()]).optional(),
5341
5425
  name: z9.union([z9.string(), z9.null()]).optional(),
@@ -5383,16 +5467,16 @@ ${FORM_ENUM}`,
5383
5467
  name: "get_form_fragment",
5384
5468
  config: {
5385
5469
  title: "\u67E5\u8BE2\u8868\u5355/\u9875\u9762\u5C40\u90E8\u5185\u5BB9",
5386
- description: `\u6309 code \u53D6\u8868\u5355\u5C40\u90E8\u5185\u5BB9\uFF08\u51E0 KB\uFF09\uFF1AnodeCode \u8282\u70B9\u5B50\u6811\uFF08\u53EF\u914D itemCode \u94BB\u53D6\u67D0\u6570\u7EC4\u5143\u7D20\uFF09\u3001handlerCode \u5904\u7406\u5668\u5B9A\u4E49\u4E0E actionIndex \u6E05\u5355\uFF08handlers \u4E0E initial \u5747\u68C0\u7D22\uFF09\u3001section \u6574\u6BB5\u3002\u914D\u5408 patch_form \u4F7F\u7528\u3002
5470
+ description: `\u6309 code \u53D6\u8868\u5355\u5C40\u90E8\u5185\u5BB9\uFF08\u51E0 KB\uFF09\uFF1AnodeCode \u8282\u70B9\u5B50\u6811\uFF08\u53EF\u914D itemCode \u94BB\u53D6\u67D0\u6570\u7EC4\u5143\u7D20\uFF1BnodeCode \u4E5F\u652F\u6301 view.subviews \u91CC\u7684\u5F39\u7A97\u53CA\u5176\u5185\u90E8\u63A7\u4EF6\uFF0C\u672A\u547D\u4E2D\u4F1A\u5728 message \u660E\u786E\u8BF4\u660E\uFF09\u3001handlerCode \u5904\u7406\u5668\u5B9A\u4E49\u4E0E actionIndex \u6E05\u5355\uFF08handlers \u4E0E initial \u5747\u68C0\u7D22\uFF09\u3001section \u6574\u6BB5\uFF08section='subviews' \u53EA\u53D6\u5F39\u7A97\u6570\u7EC4\uFF09\u3002\u914D\u5408 patch_form \u4F7F\u7528\u3002
5387
5471
 
5388
5472
  ${FORM_ENUM}`,
5389
5473
  inputSchema: {
5390
5474
  code: z9.string().describe("\u8868\u5355/\u9875\u9762\u7684\u552F\u4E00\u7F16\u7801"),
5391
- nodeCode: z9.string().optional().describe("\u76EE\u6807\u63A7\u4EF6/\u8282\u70B9\u7F16\u7801\uFF0C\u8FD4\u56DE\u5176\u5B8C\u6574\u5B50\u6811"),
5475
+ nodeCode: z9.string().optional().describe("\u76EE\u6807\u63A7\u4EF6/\u8282\u70B9\u7F16\u7801\uFF08\u542B view.subviews \u5F39\u7A97\u8282\u70B9\u53CA\u5176\u5185\u90E8\u63A7\u4EF6\uFF09\uFF0C\u8FD4\u56DE\u5176\u5B8C\u6574\u5B50\u6811\uFF1B\u672A\u547D\u4E2D\u65F6 message \u4F1A\u8BF4\u660E\u5DF2\u68C0\u7D22\u7684\u8303\u56F4"),
5392
5476
  itemCode: z9.string().optional().describe("\u5728 nodeCode \u547D\u4E2D\u7684\u8282\u70B9\u5185\u90E8\uFF0C\u6309 code \u6DF1\u5EA6\u4F18\u5148\u94BB\u53D6\u67D0\u4E2A\u6570\u7EC4\u5143\u7D20\uFF08\u5982\u8868\u683C\u7684\u67D0\u4E00\u5217\uFF09\u5E76\u8FD4\u56DE\u8BE5\u5143\u7D20\uFF0C\u800C\u975E\u6574\u68F5\u5B50\u6811\uFF1B\u672A\u627E\u5230\u65F6\u5728 message \u63D0\u793A"),
5393
5477
  handlerCode: z9.string().optional().describe("\u76EE\u6807 presenter \u5904\u7406\u5668\u7F16\u7801\uFF08handlers \u4E0E initial \u5747\u68C0\u7D22\uFF09\uFF0C\u8FD4\u56DE\u5176\u5B8C\u6574\u5B9A\u4E49\u4E0E actionIndex \u6E05\u5355"),
5394
5478
  handlerScope: z9.enum(["handlers", "initial"]).optional().describe("\u9650\u5B9A\u5904\u7406\u5668\u5BB9\u5668\uFF1B\u9ED8\u8BA4\u540C\u65F6\u68C0\u7D22 handlers \u4E0E initial\uFF0C\u540C\u540D\u8DE8\u5BB9\u5668\u65F6\u987B\u6307\u5B9A\u4EE5\u6D88\u6B67"),
5395
- section: z9.enum(["pageinfo", "view", "presenter", "controls", "pageswitch", "businessmodel"]).optional().describe("\u8FD4\u56DE\u6574\u6BB5\u5185\u5BB9\uFF08\u4EC5\u6838\u5BF9\u5F15\u7528\u7528\uFF09")
5479
+ section: z9.enum(["pageinfo", "view", "presenter", "controls", "pageswitch", "businessmodel", "subviews"]).optional().describe("\u8FD4\u56DE\u6574\u6BB5\u5185\u5BB9\uFF08\u4EC5\u6838\u5BF9\u5F15\u7528\u7528\uFF09\uFF1Bsubviews=\u53EA\u53D6\u5F39\u7A97\u6570\u7EC4")
5396
5480
  },
5397
5481
  outputSchema: {
5398
5482
  code: z9.string().describe("\u8868\u5355\u7F16\u7801"),
@@ -5419,9 +5503,9 @@ ${FORM_ENUM}`,
5419
5503
  }
5420
5504
  },
5421
5505
  handler: async (args) => {
5422
- const { code, nodeCode, itemCode, handlerCode, section } = args;
5506
+ const { code, nodeCode, itemCode, handlerCode, handlerScope, section } = args;
5423
5507
  try {
5424
- const fragment = await getFormFragment(code, { nodeCode, itemCode, handlerCode, section });
5508
+ const fragment = await getFormFragment(code, { nodeCode, itemCode, handlerCode, handlerScope, section });
5425
5509
  return okResult(fragment);
5426
5510
  } catch (e) {
5427
5511
  return errResult(e);
@@ -5450,13 +5534,13 @@ var init_write3 = __esm({
5450
5534
  }),
5451
5535
  z10.object({
5452
5536
  op: z10.literal("set_attrs"),
5453
- code: z10.string().describe("\u76EE\u6807\u63A7\u4EF6/\u8282\u70B9\u7F16\u7801\uFF08\u6574\u4E2A\u8868\u5355\u552F\u4E00\uFF0C\u4EC5\u9650 view \u6811\u8282\u70B9\u4E0E controls \u6570\u7EC4\uFF1Bpresenter/interface \u7684 action \u7ED3\u6784\u6539\u8BF7\u7528 patch_action_array_item\uFF09"),
5537
+ code: z10.string().describe("\u76EE\u6807\u63A7\u4EF6/\u8282\u70B9\u7F16\u7801\uFF08\u6574\u4E2A\u8868\u5355\u552F\u4E00\uFF0C\u542B view.subviews \u5F39\u7A97\u53CA\u5176\u5185\u90E8\u63A7\u4EF6\uFF1Bpresenter/interface \u7684 action \u7ED3\u6784\u6539\u8BF7\u7528 patch_action_array_item\uFF09"),
5454
5538
  patch: z10.record(z10.string(), z10.unknown()).describe('\u8981\u6539\u7684\u5C5E\u6027\u952E\u503C\uFF0C\u6309 code \u5B9A\u4F4D\u540E\u6D45\u5408\u5E76\uFF0C\u5982 { "hidden": "1" }\u3002\u6CE8\u610F\uFF1A\u82E5 patch \u542B\u6570\u7EC4\u5C5E\u6027\u4F1A**\u6574\u4F53\u8986\u76D6**\u8BE5\u6570\u7EC4\uFF0C\u4E14 set_attrs \u9ED8\u8BA4\u7981\u6B62\u6574\u6BB5\u8986\u76D6\u6570\u7EC4\uFF08\u907F\u514D\u8BEF\u6539\u4E22\u5217/\u4E22\u7ED1\u5B9A\uFF0C\u66FE\u81F4\u6574\u5217\u4E22\u5931\uFF09\uFF0C\u5982\u9700\u6574\u4F53\u66FF\u6362\u8BF7\u663E\u5F0F\u4F20 overwriteArray:true\uFF0C\u5426\u5219\u8BF7\u6539\u7528 patch_node_array_item / patch_action_array_item \u505A\u5143\u7D20\u7EA7\u589E\u6539\u5220'),
5455
5539
  overwriteArray: z10.boolean().optional().describe("patch \u542B\u6570\u7EC4\u5C5E\u6027\u65F6\u662F\u5426\u5141\u8BB8\u6574\u6BB5\u8986\u76D6\uFF0C\u9ED8\u8BA4 false\uFF08\u8986\u76D6\u5373\u963B\u65AD\u5E76\u63D0\u793A\u6539\u7528\u6570\u7EC4\u5143\u7D20\u7EA7 op\uFF09")
5456
5540
  }),
5457
5541
  z10.object({
5458
5542
  op: z10.literal("patch_node_array_item"),
5459
- nodeCode: z10.string().describe("\u7236\u8282\u70B9 code\uFF08\u5982\u8868\u683C\u8282\u70B9 infotable-table-...\uFF09"),
5543
+ nodeCode: z10.string().describe("\u7236\u8282\u70B9 code\uFF08\u5982\u8868\u683C\u8282\u70B9 infotable-table-...\uFF1B\u4E5F\u53EF\u4EE5\u662F view.subviews \u91CC\u7684\u5F39\u7A97 code\uFF0C\u7528\u4E8E\u6539\u5F39\u7A97\u5185\u90E8\u6570\u7EC4\uFF09"),
5460
5544
  arrayProp: z10.string().describe('\u8981\u6539\u7684\u6570\u7EC4\u5C5E\u6027\u540D\uFF0C\u5982 "cols" / "options" / "content"'),
5461
5545
  itemKey: z10.string().optional().describe('\u6570\u7EC4\u5143\u7D20\u5B9A\u4F4D\u952E\u5B57\u6BB5\u540D\uFF0C\u9ED8\u8BA4 "code"\uFF08merge/remove \u6A21\u5F0F\u3001\u4EE5\u53CA\u4E24\u7EA7\u6A21\u5F0F\u5B9A\u4F4D\u5916\u5C42\u5143\u7D20\u65F6\u7528\uFF09'),
5462
5546
  itemKeyValue: z10.unknown().optional().describe("\u8981\u5B9A\u4F4D / \u5220\u9664\u7684\u5143\u7D20\u952E\u503C\uFF08merge/remove \u6A21\u5F0F\u7528\uFF09\uFF0C\u5982 dms_status \u5217\u7684 code=890419529224687617"),
@@ -5469,6 +5553,21 @@ var init_write3 = __esm({
5469
5553
  elementItemKeyValue: z10.unknown().optional().describe("\u4E24\u7EA7\u6A21\u5F0F\u4E0B\u5B9A\u4F4D\u5D4C\u5957\u6570\u7EC4\u5185\u67D0\u5B50\u5143\u7D20\u7684\u952E\u503C\uFF08merge/remove \u6A21\u5F0F\u7528\uFF09"),
5470
5554
  createIfMissing: z10.boolean().optional().describe("append/insert \u65F6\u82E5\u76EE\u6807\u6570\u7EC4\uFF08\u542B\u4E24\u7EA7\u5D4C\u5957\u76EE\u6807\uFF09\u4E0D\u5B58\u5728\uFF0C\u662F\u5426\u5141\u8BB8\u81EA\u52A8\u65B0\u5EFA\uFF0C\u9ED8\u8BA4 false\u2014\u2014\u9ED8\u8BA4 fail-closed \u62A5 ARRAY_NOT_FOUND \u4EE5\u907F\u514D\u8BEF\u9020\u5E73\u884C orphan \u7ED3\u6784\uFF1B\u786E\u9700\u65B0\u5EFA\u624D\u7F6E true")
5471
5555
  }),
5556
+ z10.object({
5557
+ op: z10.literal("patch_view_array_item"),
5558
+ arrayProp: z10.string().describe('view \u5C42\u7EA7\u7684\u6570\u7EC4\u5C5E\u6027\u540D\uFF0C\u5F39\u7A97\u8BF7\u7528 "subviews"\uFF08\u5143\u7D20 type=popview\uFF09'),
5559
+ itemKey: z10.string().optional().describe('\u6570\u7EC4\u5143\u7D20\u5B9A\u4F4D\u952E\u5B57\u6BB5\u540D\uFF0C\u9ED8\u8BA4 "code"\uFF08merge/remove \u6A21\u5F0F\u3001\u4EE5\u53CA\u4E24\u7EA7\u6A21\u5F0F\u5B9A\u4F4D\u5916\u5C42\u5143\u7D20\u65F6\u7528\uFF09'),
5560
+ itemKeyValue: z10.unknown().optional().describe("\u8981\u5B9A\u4F4D / \u5220\u9664\u7684\u5143\u7D20\u952E\u503C\uFF08merge/remove \u6A21\u5F0F\u7528\uFF09\uFF0C\u5982\u5F39\u7A97 code=1501119668772016226"),
5561
+ mode: z10.enum(["merge", "append", "insert", "remove"]).optional().describe("\u64CD\u4F5C\u6A21\u5F0F\uFF1Amerge=\u6D45\u5408\u5E76\u5230\u5DF2\u5B58\u5728\u5143\u7D20(\u9ED8\u8BA4)\uFF1Bappend=\u5728\u6570\u7EC4\u672B\u5C3E\u8FFD\u52A0 item\uFF08\u65B0\u5EFA\u5F39\u7A97\uFF09\uFF1Binsert=\u6309 position \u63D2\u5165 item\uFF1Bremove=\u6309 itemKey \u5220\u9664\u5143\u7D20\uFF08\u5220\u9664\u5F39\u7A97\uFF09"),
5562
+ item: z10.record(z10.string(), z10.unknown()).optional().describe("append/insert \u6A21\u5F0F\u4E0B\u8981\u52A0\u5165\u7684\u65B0\u5143\u7D20\u5BF9\u8C61\uFF08\u65B0\u5EFA\u5F39\u7A97\u65F6\u4F20\u5B8C\u6574 popview \u8282\u70B9\uFF09"),
5563
+ position: z10.number().int().nonnegative().optional().describe("insert \u6A21\u5F0F\u4E0B\u7684\u63D2\u5165\u4E0B\u6807\uFF0C\u9ED8\u8BA4\u672B\u5C3E"),
5564
+ patch: z10.record(z10.string(), z10.unknown()).optional().describe('merge \u6A21\u5F0F\u4E0B\u6D45\u5408\u5E76\u5230\u8BE5\u5143\u7D20\u7684\u5C5E\u6027\uFF0C\u5982 { "title": "\u8D27\u8865", "needconfirm": "0" }'),
5565
+ elementArrayProp: z10.string().optional().describe("\u3010\u4E24\u7EA7\u5D4C\u5957\u3011\u82E5\u76EE\u6807\u5728\u300C\u6570\u7EC4\u5185\u67D0\u5143\u7D20\u7684\u5D4C\u5957\u6570\u7EC4\u300D\u4E2D\uFF0C\u586B\u6B64\u5904\u5B50\u6570\u7EC4\u540D\uFF1B\u9700\u914D\u5408 itemKey/itemKeyValue \u5148\u5B9A\u4F4D\u5916\u5C42\u5143\u7D20"),
5566
+ elementItemKey: z10.string().optional().describe('\u4E24\u7EA7\u6A21\u5F0F\u4E0B\u5B9A\u4F4D\u5D4C\u5957\u6570\u7EC4\u5185\u67D0\u5B50\u5143\u7D20\u7684\u952E\uFF0C\u9ED8\u8BA4 "code"'),
5567
+ elementItemKeyValue: z10.unknown().optional().describe("\u4E24\u7EA7\u6A21\u5F0F\u4E0B\u5B9A\u4F4D\u5D4C\u5957\u6570\u7EC4\u5185\u67D0\u5B50\u5143\u7D20\u7684\u952E\u503C"),
5568
+ createIfMissing: z10.boolean().optional().describe("append/insert \u65F6\u82E5\u76EE\u6807\u6570\u7EC4\uFF08\u542B\u4E24\u7EA7\u5D4C\u5957\u76EE\u6807\uFF09\u4E0D\u5B58\u5728\uFF0C\u662F\u5426\u5141\u8BB8\u81EA\u52A8\u65B0\u5EFA\uFF0C\u9ED8\u8BA4 false\u3002\u8868\u5355\u9996\u6B21\u52A0\u5F39\u7A97\u65F6 view.subviews \u901A\u5E38\u4E0D\u5B58\u5728\uFF0C\u987B\u663E\u5F0F\u7F6E true"),
5569
+ checkRefs: z10.boolean().optional().describe("remove \u5220\u9664\u9876\u5C42\u5F39\u7A97\u65F6\u662F\u5426\u6821\u9A8C\u5F15\u7528\uFF08popsubview/closesubview \u7684 viewcode\uFF09\uFF0C\u9ED8\u8BA4 true\uFF1B\u4ECD\u88AB\u6253\u5F00\u52A8\u4F5C\u6307\u5411\u7684\u5F39\u7A97\u4F1A\u62A5 REF_VIOLATION\uFF0C\u786E\u9700\u5F3A\u5220\u624D\u7F6E false\u3002\u5220\u5F39\u7A97\u5185\u5D4C\u5957\u5143\u7D20\u65F6\u4E0D\u751F\u6548")
5570
+ }),
5472
5571
  z10.object({
5473
5572
  op: z10.literal("patch_action_array_item"),
5474
5573
  handlerCode: z10.string().describe("presenter \u5904\u7406\u5668 code\uFF08handlers \u4E0E initial \u5747\u68C0\u7D22\uFF0C\u4E0E replace_script \u540C\uFF09"),
@@ -5521,14 +5620,14 @@ var init_write3 = __esm({
5521
5620
  }),
5522
5621
  z10.object({
5523
5622
  op: z10.literal("insert_node"),
5524
- parentCode: z10.string().describe("\u7236\u8282\u70B9 code\uFF08view \u6811\u4E2D\uFF09"),
5623
+ parentCode: z10.string().describe("\u7236\u8282\u70B9 code\uFF08view \u6811\uFF0C\u542B subviews \u5F39\u7A97\u8282\u70B9\uFF1B\u4F20\u5F39\u7A97 code \u5373\u5F80\u5F39\u7A97\u5185\u52A0\u63A7\u4EF6\uFF09"),
5525
5624
  position: z10.number().int().nonnegative().optional().describe("\u63D2\u5165\u4F4D\u7F6E\u4E0B\u6807\uFF0C\u9ED8\u8BA4\u672B\u5C3E"),
5526
5625
  node: z10.record(z10.string(), z10.unknown()).describe("\u65B0\u8282\u70B9\u5BF9\u8C61\uFF08\u542B type/code/title/content \u7B49\uFF09\uFF0C\u540C view \u6811\u8282\u70B9\u7ED3\u6784")
5527
5626
  }),
5528
5627
  z10.object({
5529
5628
  op: z10.literal("remove_node"),
5530
- code: z10.string().describe("\u8981\u5220\u9664\u7684\u8282\u70B9 code"),
5531
- checkRefs: z10.boolean().optional().describe("\u524D\u7F6E\u5F15\u7528\u6821\u9A8C\uFF0C\u9ED8\u8BA4 true\uFF1B\u5B58\u5728\u4E8B\u4EF6/handler \u5F15\u7528\u65F6\u62D2\u7EDD\u5220\u9664\uFF0C\u7F6E false \u8DF3\u8FC7\u6821\u9A8C")
5629
+ code: z10.string().describe("\u8981\u5220\u9664\u7684\u8282\u70B9 code\uFF08\u5F39\u7A97\u6839\u8282\u70B9\u4E5F\u53EF\uFF1A\u5B83\u5728 view.subviews \u91CC\uFF09"),
5630
+ checkRefs: z10.boolean().optional().describe("\u524D\u7F6E\u5F15\u7528\u6821\u9A8C\uFF0C\u9ED8\u8BA4 true\uFF1B\u5B58\u5728\u4E8B\u4EF6/handler \u5F15\u7528\uFF08\u542B popsubview/closesubview \u7684 viewcode \u6307\u5411\u8BE5\u5F39\u7A97\uFF09\u65F6\u62D2\u7EDD\u5220\u9664\uFF0C\u7F6E false \u8DF3\u8FC7\u6821\u9A8C")
5532
5631
  }),
5533
5632
  z10.object({
5534
5633
  op: z10.literal("move_node"),
@@ -5575,7 +5674,9 @@ var init_write3 = __esm({
5575
5674
  name: "patch_form",
5576
5675
  config: {
5577
5676
  title: "\u5C40\u90E8\u8865\u4E01\u4FEE\u6539\u8868\u5355/\u9875\u9762",
5578
- description: `\u4EE5 delta ops \u5C40\u90E8\u4FEE\u6539\u8868\u5355\uFF0C\u65E0\u9700\u56DE\u4F20\u5B8C\u6574 JSON\u300214 \u7C7B ops\uFF1Aset_pageinfo/set_attrs/patch_node_array_item/patch_action_array_item/add_action/patch_action/remove_action/insert_node/remove_node/move_node/set_section/replace_script/add_businessmodel/remove_businessmodel\u3002\u63A8\u8350\u6D41\u7A0B\uFF1Aget_form_outline \u62FF code \u2192 get_form_fragment \u786E\u8BA4\u771F\u5B9E\u5C5E\u6027\u540D/\u811A\u672C \u2192 patch_form\u3002ops \u4E8B\u52A1\u6027\u9884\u6F14\uFF0C\u5931\u8D25\u6574\u6279\u56DE\u6EDA\uFF1B\u6539\u521D\u59CB\u5316\u811A\u672C\uFF08presenter.initial\uFF09\u4E0E\u6539\u6309\u94AE\u4E8B\u4EF6\u7528\u6CD5\u4E00\u81F4\u3002
5677
+ description: `\u4EE5 delta ops \u5C40\u90E8\u4FEE\u6539\u8868\u5355\uFF0C\u65E0\u9700\u56DE\u4F20\u5B8C\u6574 JSON\u300215 \u7C7B ops\uFF1Aset_pageinfo/set_attrs/patch_node_array_item/patch_view_array_item/patch_action_array_item/add_action/patch_action/remove_action/insert_node/remove_node/move_node/set_section/replace_script/add_businessmodel/remove_businessmodel\u3002\u63A8\u8350\u6D41\u7A0B\uFF1Aget_form_outline \u62FF code \u2192 get_form_fragment \u786E\u8BA4\u771F\u5B9E\u5C5E\u6027\u540D/\u811A\u672C \u2192 patch_form\u3002ops \u4E8B\u52A1\u6027\u9884\u6F14\uFF0C\u5931\u8D25\u6574\u6279\u56DE\u6EDA\uFF1B\u6539\u521D\u59CB\u5316\u811A\u672C\uFF08presenter.initial\uFF09\u4E0E\u6539\u6309\u94AE\u4E8B\u4EF6\u7528\u6CD5\u4E00\u81F4\u3002
5678
+
5679
+ **\u5F39\u7A97\uFF08popview\uFF09**\uFF1A\u5E73\u53F0\u7684\u5F39\u7A97\u6302\u5728 view.subviews\uFF08\u4E0E view.body \u5E73\u7EA7\u7684\u6570\u7EC4\uFF0C\u5143\u7D20 type=popview\uFF09\uFF0C\u5F39\u7A97\u5185\u63A7\u4EF6\u5728\u5F39\u7A97\u8282\u70B9\u7684 content \u4E0B\u3002view \u6811\u904D\u5386\u5DF2\u8986\u76D6 subviews\uFF0C\u56E0\u6B64\uFF1A\u6539\u5F39\u7A97\u5C5E\u6027\u6216\u5728\u5F39\u7A97\u5185\u52A0/\u5220\u63A7\u4EF6\uFF0C\u76F4\u63A5\u7528 set_attrs / insert_node\uFF08parentCode=\u5F39\u7A97 code\uFF09/ remove_node / move_node / patch_node_array_item\uFF08\u542B\u5F39\u7A97\u5185\u90E8\u8282\u70B9\u7684 eventlist\uFF09\uFF1B\u800C\u300C\u5F39\u7A97\u6839\u8282\u70B9\u81EA\u8EAB\u5728 subviews \u6570\u7EC4\u91CC\u3001\u6CA1\u6709\u7236\u8282\u70B9\u300D\u7684\u589E\u5220\u6539\uFF0C\u7528 patch_view_array_item\uFF08base=view\uFF09\uFF1Aappend \u65B0\u5EFA\u5F39\u7A97\uFF08\u8868\u5355\u9996\u6B21\u52A0\u5F39\u7A97\u987B createIfMissing:true\uFF09\u3001merge \u6539 title/needconfirm \u7B49\u3001remove \u5220\u9664\u5F39\u7A97\u3002\u5220\u5F39\u7A97\u4E24\u6761\u8DEF\u7B49\u4EF7\uFF1Aremove_node{code=\u5F39\u7A97code} \u6216 patch_view_array_item{arrayProp:"subviews",mode:"remove",itemKeyValue:\u5F39\u7A97code}\uFF0C\u4E24\u8005\u90FD\u9ED8\u8BA4\u6821\u9A8C popsubview/closesubview \u7684 viewcode \u5F15\u7528\uFF08\u62A5 REF_VIOLATION\uFF09\uFF0C\u786E\u9700\u5F3A\u5220\u4F20 checkRefs:false\uFF1B\u5220\u6389\u6700\u540E\u4E00\u4E2A\u5F39\u7A97\u540E subviews \u5C5E\u6027\u4F1A\u88AB\u6E05\u6389\uFF0C\u4E0D\u7559\u7A7A\u6570\u7EC4\u3002\u6253\u5F00\u5F39\u7A97\u4ECD\u7528 add_action type="popsubview"\uFF08fields:{viewcode,viewwidth,viewheight,popupmode}\uFF09\u3002\u7EA2\u7EBF\uFF1A\u5F39\u7A97\u5185\u63A7\u4EF6 code \u5E38\u88AB datarequest.setter \u5F15\u7528\uFF0C\u52FF\u6539 code\u3001\u52FF\u5220\u4ECD\u88AB\u5F15\u7528\u7684\u8282\u70B9\u3002
5579
5680
 
5580
5681
  \u6570\u7EC4\u5143\u7D20\u7EA7\u6539\u52A8\uFF1Apatch_node_array_item \u652F\u6301 merge(\u9ED8\u8BA4)/append/insert/remove \u56DB\u79CD\u6A21\u5F0F\uFF0C\u4F5C\u7528\u4E8E view \u6811\u8282\u70B9\u7684 cols/options/content \u7B49\uFF1Bpatch_action_array_item \u7528\u4E8E presenter.handlers/initial \u4E2D\u67D0 action \u5185\u90E8\u6570\u7EC4\uFF08\u5982 datarequest.setter\u300C\u754C\u9762\u8F93\u51FA\u7ED1\u5B9A\u5230\u63A7\u4EF6\u300D\u3001param.properties\uFF09\uFF0C\u540C\u6837\u652F\u6301\u56DB\u79CD\u6A21\u5F0F\u3002\u4E24\u8005\u90FD\u652F\u6301\u300C\u4E24\u7EA7\u5D4C\u5957\u300D\uFF08elementArrayProp\uFF09\uFF1A\u5F53\u771F\u5B9E\u7ED1\u5B9A\u5728\u300C\u6570\u7EC4\u5185\u67D0\u5143\u7D20\u7684\u5D4C\u5957\u6570\u7EC4\u300D\uFF08\u5982 datarequest.setter[0].properties \u6A21\u578B\u7EA7\u5C5E\u6027\u6620\u5C04\uFF09\u65F6\uFF0C\u7528 itemKey/itemKeyValue \u5148\u5B9A\u4F4D\u5916\u5C42\u5143\u7D20\u3001\u518D\u586B elementArrayProp \u94BB\u5230\u5D4C\u5957\u6570\u7EC4\u64CD\u4F5C\uFF0C\u65E0\u9700\u56DE\u4F20\u6574\u6BB5\u6570\u7EC4\u3002append/insert \u76EE\u6807\u6570\u7EC4\u4E0D\u5B58\u5728\u65F6\u9ED8\u8BA4 fail-closed \u62A5 ARRAY_NOT_FOUND\uFF08\u987B\u663E\u5F0F createIfMissing:true \u624D\u65B0\u5EFA\uFF09\uFF0C\u907F\u514D\u8BEF\u9020\u5E73\u884C orphan \u7ED3\u6784\uFF1Bremove \u6E05\u7A7A\u8C03\u5219\u5220\u9664\u8BE5\u6570\u7EC4\u5C5E\u6027\u907F\u514D\u7A7A\u58F3\u3002set_attrs \u9ED8\u8BA4\u7981\u6B62\u6574\u6BB5\u8986\u76D6\u6570\u7EC4\uFF08\u542B\u6570\u7EC4\u5C5E\u6027\u987B\u663E\u5F0F overwriteArray:true\uFF0C\u5426\u5219\u6539\u7528\u4E0A\u8FF0\u4E24 op\uFF09\u3002
5581
5682