weaver-e10-builder 1.6.5 → 1.6.7

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 (94) hide show
  1. package/dist/commands/actionflow.d.ts.map +1 -1
  2. package/dist/commands/actionflow.js +16 -1
  3. package/dist/commands/actionflow.js.map +1 -1
  4. package/dist/commands/form-browser-definition.d.ts.map +1 -1
  5. package/dist/commands/form-browser-definition.js +8 -0
  6. package/dist/commands/form-browser-definition.js.map +1 -1
  7. package/dist/commands/form-ebuilder-scope.d.ts.map +1 -1
  8. package/dist/commands/form-ebuilder-scope.js +8 -3
  9. package/dist/commands/form-ebuilder-scope.js.map +1 -1
  10. package/dist/commands/form.d.ts.map +1 -1
  11. package/dist/commands/form.js +20 -0
  12. package/dist/commands/form.js.map +1 -1
  13. package/dist/commands/menu-permission.d.ts +11 -0
  14. package/dist/commands/menu-permission.d.ts.map +1 -1
  15. package/dist/commands/menu-permission.js +113 -26
  16. package/dist/commands/menu-permission.js.map +1 -1
  17. package/dist/commands/menu.d.ts +16 -5
  18. package/dist/commands/menu.d.ts.map +1 -1
  19. package/dist/commands/menu.js +153 -42
  20. package/dist/commands/menu.js.map +1 -1
  21. package/dist/commands/wf-form.d.ts.map +1 -1
  22. package/dist/commands/wf-form.js +134 -2
  23. package/dist/commands/wf-form.js.map +1 -1
  24. package/dist/commands/workflow.d.ts.map +1 -1
  25. package/dist/commands/workflow.js +18 -2
  26. package/dist/commands/workflow.js.map +1 -1
  27. package/dist/services/action-detail.d.ts +4 -0
  28. package/dist/services/action-detail.d.ts.map +1 -1
  29. package/dist/services/action-detail.js +49 -9
  30. package/dist/services/action-detail.js.map +1 -1
  31. package/dist/services/actionflow/components/enquiry_form.d.ts.map +1 -1
  32. package/dist/services/actionflow/components/enquiry_form.js +9 -2
  33. package/dist/services/actionflow/components/enquiry_form.js.map +1 -1
  34. package/dist/services/actionflow/components/send_message.d.ts.map +1 -1
  35. package/dist/services/actionflow/components/send_message.js +5 -2
  36. package/dist/services/actionflow/components/send_message.js.map +1 -1
  37. package/dist/services/actionflow/components/time_batch_trigger.js +3 -3
  38. package/dist/services/actionflow/components/time_batch_trigger.js.map +1 -1
  39. package/dist/services/actionflow/context_discovery.d.ts +16 -0
  40. package/dist/services/actionflow/context_discovery.d.ts.map +1 -0
  41. package/dist/services/actionflow/context_discovery.js +73 -0
  42. package/dist/services/actionflow/context_discovery.js.map +1 -0
  43. package/dist/services/actionflow/context_preflight.d.ts +0 -9
  44. package/dist/services/actionflow/context_preflight.d.ts.map +1 -1
  45. package/dist/services/actionflow/context_preflight.js +0 -59
  46. package/dist/services/actionflow/context_preflight.js.map +1 -1
  47. package/dist/services/actionflow/execution_setting.d.ts +11 -0
  48. package/dist/services/actionflow/execution_setting.d.ts.map +1 -0
  49. package/dist/services/actionflow/execution_setting.js +205 -0
  50. package/dist/services/actionflow/execution_setting.js.map +1 -0
  51. package/dist/services/actionflow/form_source.d.ts.map +1 -1
  52. package/dist/services/actionflow/form_source.js +48 -22
  53. package/dist/services/actionflow/form_source.js.map +1 -1
  54. package/dist/services/actionflow/formula_service.d.ts.map +1 -1
  55. package/dist/services/actionflow/formula_service.js +49 -9
  56. package/dist/services/actionflow/formula_service.js.map +1 -1
  57. package/dist/services/actionflow/generation_service.d.ts.map +1 -1
  58. package/dist/services/actionflow/generation_service.js +32 -0
  59. package/dist/services/actionflow/generation_service.js.map +1 -1
  60. package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
  61. package/dist/services/actionflow/preflight_service.js +148 -7
  62. package/dist/services/actionflow/preflight_service.js.map +1 -1
  63. package/dist/services/actionflow/readback_verifier.d.ts.map +1 -1
  64. package/dist/services/actionflow/readback_verifier.js +6 -2
  65. package/dist/services/actionflow/readback_verifier.js.map +1 -1
  66. package/dist/services/actionflow/trigger_common.d.ts.map +1 -1
  67. package/dist/services/actionflow/trigger_common.js +5 -1
  68. package/dist/services/actionflow/trigger_common.js.map +1 -1
  69. package/dist/services/form-linkage-condition.d.ts +23 -2
  70. package/dist/services/form-linkage-condition.d.ts.map +1 -1
  71. package/dist/services/form-linkage-condition.js +54 -11
  72. package/dist/services/form-linkage-condition.js.map +1 -1
  73. package/dist/services/menu-catalog.d.ts +19 -0
  74. package/dist/services/menu-catalog.d.ts.map +1 -1
  75. package/dist/services/menu-catalog.js +31 -1
  76. package/dist/services/menu-catalog.js.map +1 -1
  77. package/dist/services/workflow-info.d.ts +3 -1
  78. package/dist/services/workflow-info.d.ts.map +1 -1
  79. package/dist/services/workflow-info.js.map +1 -1
  80. package/dist/services/workflow-node-layout.d.ts +133 -15
  81. package/dist/services/workflow-node-layout.d.ts.map +1 -1
  82. package/dist/services/workflow-node-layout.js +394 -0
  83. package/dist/services/workflow-node-layout.js.map +1 -1
  84. package/package.json +1 -1
  85. package/skill-docs/SKILL.md +4 -5
  86. package/skill-docs/_catalog.md +2 -2
  87. package/skill-docs/actionflows/SKILL.md +8 -2
  88. package/skill-docs/actionflows/references/trigger_runtime_notes.md +6 -6
  89. package/skill-docs/references/common/ref-cli-commands.md +20 -16
  90. package/skill-docs/references/form/guide-browser-definition.md +62 -4
  91. package/skill-docs/references/form/guide-form-linkage.md +16 -8
  92. package/skill-docs/references/form/layout/workflow-layout.md +45 -0
  93. package/skill-docs/references/menu/system-menus.md +44 -1
  94. package/skill-docs/references/workflow/guide-workflow-node-layout.md +3 -2
@@ -1,18 +1,3 @@
1
- /**
2
- * 流程节点独立布局 —— 节点上挂一套自己的表单布局,与表单默认布局并存。
3
- *
4
- * 关系是**互斥**的:一个节点同时只属于一套布局。把节点从 A 挪到 B 时,
5
- * 服务端会自动把它从 A 摘掉,摘掉后该节点回落到表单默认布局(`layoutId` 置空)。
6
- * 所以「绑定」这件事在接口层是**整集合覆盖**,不是增量追加:
7
- * 1. 读目标布局当前的引用节点全集;
8
- * 2. 加上/去掉本次要动的节点;
9
- * 3. `updateQuoteNode(nodeIds=新集合, sourceNodeIds=旧集合)` 整包提交。
10
- *
11
- * 端点分工(同一件事的三个视角):
12
- * - 节点视角:`nodeLayout/getDisplayLayoutForm` → 这个节点挂的是哪套;
13
- * - 布局视角:`pathLayoutManage/getLayoutInfoParams` → 每套布局被哪些节点引用;
14
- * - 列表视角:`ebuilder/flow/form/layout/list` → 这个表单有哪些布局。
15
- */
16
1
  import { ApiClient } from '../core/client.js';
17
2
  import { type WorkflowFormKind } from './workflow-context.js';
18
3
  /**
@@ -44,7 +29,13 @@ interface FormRoute {
44
29
  designerSource: string;
45
30
  listLayouts: string;
46
31
  saveLayout: string;
32
+ /** 改布局元信息(名称/描述)。**与 saveLayout 不是同一条** —— 带 id 调 save 会主键冲突。 */
33
+ updateLayout: string;
34
+ /** 把某套布局设为该终端的默认布局。 */
35
+ updateDefault: string;
47
36
  getFormLayout: string;
37
+ /** 整份布局回写(设计器保存)。改组件内容只能走这条。 */
38
+ saveFormAndLayout: string;
48
39
  getConfig: string;
49
40
  initLayout: string;
50
41
  }
@@ -212,6 +203,133 @@ export declare function createFormLayout(client: ApiClient, opts: {
212
203
  */
213
204
  isNodeLayout?: boolean;
214
205
  }): Promise<FormLayoutRow>;
206
+ /**
207
+ * `layout/update` 的 `formLayoutMultiple`:列表行 + 新名称/描述。
208
+ *
209
+ * `includeDescribe=false` 时不下发该键 —— 平台列表行本来就没有 `describe` 的
210
+ * (eb 表关联流程的默认布局就是这样)报文里也不带,按原样对齐,不凭空补空串。
211
+ */
212
+ export declare function buildLayoutUpdateRow(row: FormLayoutRow, name: string, describe: string, includeDescribe?: boolean): Record<string, unknown>;
213
+ export interface UpdateFormLayoutResult {
214
+ changed: boolean;
215
+ layoutId: string;
216
+ oldName: string;
217
+ oldDescribe: string;
218
+ name: string;
219
+ describe: string;
220
+ terminalType: string;
221
+ layoutType: string;
222
+ isDefault: boolean;
223
+ }
224
+ /**
225
+ * 修改布局名称或描述(保留布局内容、引用节点与默认设置)。
226
+ *
227
+ * `layout` 可传布局 ID 或布局名称;同名多套时报歧义并列 ID,不替调用方挑。
228
+ * 改完**回读布局列表**:名称/描述必须落库,且终端、类型、默认标记等元信息不能被顺手改掉。
229
+ */
230
+ export declare function updateFormLayout(client: ApiClient, opts: {
231
+ formId: string;
232
+ /** 布局 ID(formLayoutMultiple.id)或布局名称 */
233
+ layout: string;
234
+ /** 新名称;不传 = 保持原名 */
235
+ name?: string;
236
+ /** 新描述;不传 = 保持原描述 */
237
+ describe?: string;
238
+ workflowId?: string;
239
+ formKind?: WorkflowFormKind;
240
+ }): Promise<UpdateFormLayoutResult>;
241
+ export interface SetDefaultLayoutResult {
242
+ changed: boolean;
243
+ layoutId: string;
244
+ name: string;
245
+ terminalType: string;
246
+ /** 改之前该终端上的默认布局(没有则为空串)。 */
247
+ previousDefaultId: string;
248
+ }
249
+ /**
250
+ * 把某套布局设为**该终端**的默认布局。
251
+ *
252
+ * 真机抓包(mulinquan 2026-10-29):
253
+ * `POST {route}/layout/updateDefault`
254
+ * `{ module, formLayoutMultiple:{ id, form:{id:formId}, default:true, terminalType }, local:true }`
255
+ *
256
+ * 默认布局是**表单维度**、且 PC/移动端各自一套 —— 所以终端取自目标布局自身,
257
+ * 不是让调用方再传一次(传错就会把另一端的默认改掉)。
258
+ * 改完回读:目标必须是默认,**同终端不能还有第二套默认**。
259
+ */
260
+ export declare function setDefaultLayout(client: ApiClient, opts: {
261
+ formId: string;
262
+ /** 布局 ID(formLayoutMultiple.id)或布局名称 */
263
+ layout: string;
264
+ workflowId?: string;
265
+ formKind?: WorkflowFormKind;
266
+ }): Promise<SetDefaultLayoutResult>;
267
+ /**
268
+ * 流程系统字段目录。`key` = `config.fieldId/valueKey`,`type` = 组件类型。
269
+ *
270
+ * 样式三档来自设计器落库的组件(真机抓包 2026-10-29,mulinquan):
271
+ * `FlowPageSysFieldInput`+34 = 可输入;`FlowPageSysFieldReadOnly`+35 = 只读;
272
+ * `FlowPageSysFieldNoContent`+36 = 无内容(流程状态)。
273
+ *
274
+ * 标 `inferred` 的几项没在设计器里摆出来过,样式按平台常量推断 ——
275
+ * 若设计器摆出来的实际样式不同,以导出的组件为准改这里。
276
+ */
277
+ export interface SystemFieldDef {
278
+ key: string;
279
+ type: string;
280
+ label: string;
281
+ compKey: string;
282
+ applyStyle: string;
283
+ inferred?: boolean;
284
+ }
285
+ export declare const SYSTEM_FIELD_CATALOG: SystemFieldDef[];
286
+ /** 按 名称 / key / 组件类型 解析系统字段;认不出就报错并列出可选。 */
287
+ export declare function resolveSystemField(input: string): SystemFieldDef;
288
+ /** 拼一个系统字段组件(形状对齐设计器落库,见 2026-10-29 抓包)。 */
289
+ export declare function buildSystemFieldComp(def: SystemFieldDef, ctx: {
290
+ formId: string;
291
+ tenantKey: string;
292
+ showOrder: number;
293
+ offsetTop: number;
294
+ singleRow?: boolean;
295
+ }): Record<string, any>;
296
+ export interface AddSystemFieldsResult {
297
+ layoutId: string;
298
+ layoutName: string;
299
+ terminalType: string;
300
+ added: Array<{
301
+ key: string;
302
+ title: string;
303
+ }>;
304
+ skipped: Array<{
305
+ key: string;
306
+ title: string;
307
+ }>;
308
+ }
309
+ /**
310
+ * 往某套流程表单布局里摆流程系统字段(提交人/流程编号/流程状态…)。
311
+ *
312
+ * 写的是**整份布局**:读取 `getFormLayout` → 在 `pageLayouts[0].comps` 末尾追加组件 →
313
+ * `builder/saveFormAndLayout` 回写。报文形状是设计器保存时的那套
314
+ * (真机抓包 2026-10-29):`formLayout.pageLayouts` 直接发原始 JSON 就能落库,
315
+ * 不需要 `pageLayoutEncodes`;但 `formLayout.multipleLayoutId` 必带。
316
+ *
317
+ * 已经在布局里的系统字段会跳过(幂等);写完回读核对新增字段,并确认原有组件一个没少。
318
+ */
319
+ export declare function addSystemFieldsToLayout(client: ApiClient, opts: {
320
+ formId: string;
321
+ /** 目标布局 ID;不传 = PC 端默认布局 */
322
+ layoutId?: string;
323
+ /** 字段名/key/组件类型 */
324
+ fields?: string[];
325
+ /** true = 目录里全部字段 */
326
+ all?: boolean;
327
+ singleRow?: boolean;
328
+ workflowId?: string;
329
+ formKind?: WorkflowFormKind;
330
+ /** 认证会话里的租户标识(组件上有该字段) */
331
+ tenantKey: string;
332
+ }): Promise<AddSystemFieldsResult>;
215
333
  /** 读某套布局的内容(不传 layoutId 读默认布局)。 */
216
334
  export declare function getLayoutContent(client: ApiClient, formId: string, layoutId?: string, workflowId?: string, formKind?: WorkflowFormKind): Promise<{
217
335
  layout: any;
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-node-layout.d.ts","sourceRoot":"","sources":["../../src/services/workflow-node-layout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow-node-layout.d.ts","sourceRoot":"","sources":["../../src/services/workflow-node-layout.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,19 @@
1
+ /**
2
+ * 流程节点独立布局 —— 节点上挂一套自己的表单布局,与表单默认布局并存。
3
+ *
4
+ * 关系是**互斥**的:一个节点同时只属于一套布局。把节点从 A 挪到 B 时,
5
+ * 服务端会自动把它从 A 摘掉,摘掉后该节点回落到表单默认布局(`layoutId` 置空)。
6
+ * 所以「绑定」这件事在接口层是**整集合覆盖**,不是增量追加:
7
+ * 1. 读目标布局当前的引用节点全集;
8
+ * 2. 加上/去掉本次要动的节点;
9
+ * 3. `updateQuoteNode(nodeIds=新集合, sourceNodeIds=旧集合)` 整包提交。
10
+ *
11
+ * 端点分工(同一件事的三个视角):
12
+ * - 节点视角:`nodeLayout/getDisplayLayoutForm` → 这个节点挂的是哪套;
13
+ * - 布局视角:`pathLayoutManage/getLayoutInfoParams` → 每套布局被哪些节点引用;
14
+ * - 列表视角:`ebuilder/flow/form/layout/list` → 这个表单有哪些布局。
15
+ */
16
+ import { randomBytes } from 'node:crypto';
1
17
  import { getWorkflowContext } from './workflow-context.js';
2
18
  const PATHDEF = '/api/bs/workflow/pathdef';
3
19
  const FLOW_FORM = '/api/ebuilder/flow/form';
@@ -10,7 +26,11 @@ const ROUTE_EBUILDER = {
10
26
  designerSource: 'ebuilderform',
11
27
  listLayouts: `${FLOW_FORM}/layout/list`,
12
28
  saveLayout: `${FLOW_FORM}/layout/save`,
29
+ updateLayout: `${FLOW_FORM}/layout/update`,
30
+ updateDefault: `${FLOW_FORM}/layout/updateDefault`,
13
31
  getFormLayout: `${FORM_BUILDER}/getFormLayout`,
32
+ // ⚠ 与 getFormLayout 不是同一个前缀:保存是 `/api/ebuilder/form/form/builder/*`
33
+ saveFormAndLayout: '/api/ebuilder/form/form/builder/saveFormAndLayout',
14
34
  getConfig: '/api/ebuilder/form/form/view/relate/getConfig',
15
35
  initLayout: '/api/ebuilder/form/form/view/relate/initLayout',
16
36
  };
@@ -22,7 +42,10 @@ const ROUTE_WORKFLOW = {
22
42
  designerSource: 'workflow',
23
43
  listLayouts: '/api/workflow/core/form/layout/list',
24
44
  saveLayout: '/api/workflow/core/form/layout/save',
45
+ updateLayout: '/api/workflow/core/form/layout/update',
46
+ updateDefault: '/api/workflow/core/form/layout/updateDefault',
25
47
  getFormLayout: '/api/workflow/core/form/builder/getFormLayout',
48
+ saveFormAndLayout: '/api/workflow/core/form/builder/saveFormAndLayout',
26
49
  getConfig: '/api/workflow/core/form/view/relate/getConfig',
27
50
  initLayout: '/api/workflow/core/form/view/relate/initLayout',
28
51
  };
@@ -283,6 +306,377 @@ export async function createFormLayout(client, opts) {
283
306
  isDefault: !!flm.isDefault,
284
307
  };
285
308
  }
309
+ /**
310
+ * 「改布局名称/描述」的报文字段白名单(真机抓包 2026-10-29,mulinquan)。
311
+ *
312
+ * 平台走的是**独立的** `layout/update`,不是 `layout/save`:
313
+ * 带 `formLayoutMultiple.id` 调 `save` 会走插入分支,直接主键冲突 500。
314
+ * 报文就是把 `layout/list` 那一行原样带回来、只换 `name`/`describe`,
315
+ * 所以这里按行取值,不自己造字段。
316
+ */
317
+ const LAYOUT_UPDATE_FIELDS = [
318
+ 'id', 'name', 'describe', 'terminalType', 'operator', 'creator', 'createTime', 'updateTime',
319
+ 'isDefault', 'versionId', 'layoutType', 'isSys', 'parentId', 'readOnly', 'simple', 'labelObj',
320
+ ];
321
+ /**
322
+ * `layout/update` 的 `formLayoutMultiple`:列表行 + 新名称/描述。
323
+ *
324
+ * `includeDescribe=false` 时不下发该键 —— 平台列表行本来就没有 `describe` 的
325
+ * (eb 表关联流程的默认布局就是这样)报文里也不带,按原样对齐,不凭空补空串。
326
+ */
327
+ export function buildLayoutUpdateRow(row, name, describe, includeDescribe = true) {
328
+ const out = {};
329
+ for (const key of LAYOUT_UPDATE_FIELDS) {
330
+ if (row[key] !== undefined)
331
+ out[key] = row[key];
332
+ }
333
+ out.id = row.id;
334
+ out.name = name;
335
+ if (includeDescribe)
336
+ out.describe = describe;
337
+ else
338
+ delete out.describe;
339
+ // 默认布局那一行列表里没有 labelObj,抓包里该键是 "{}" —— 缺了它平台会按空对象存
340
+ if (out.labelObj === undefined)
341
+ out.labelObj = '{}';
342
+ return out;
343
+ }
344
+ /**
345
+ * 修改布局名称或描述(保留布局内容、引用节点与默认设置)。
346
+ *
347
+ * `layout` 可传布局 ID 或布局名称;同名多套时报歧义并列 ID,不替调用方挑。
348
+ * 改完**回读布局列表**:名称/描述必须落库,且终端、类型、默认标记等元信息不能被顺手改掉。
349
+ */
350
+ export async function updateFormLayout(client, opts) {
351
+ const base = client.getBaseUrl();
352
+ const rows = await collectLayoutsBothTerminals(client, opts.formId, opts.workflowId, opts.formKind);
353
+ const key = String(opts.layout).trim();
354
+ if (!key)
355
+ throw new Error('布局 ID 或名称不能为空');
356
+ const byId = rows.filter((r) => r.id === key);
357
+ const matches = byId.length ? byId : rows.filter((r) => r.name === key);
358
+ const listCurrent = () => (rows.map((r) => `${r.name}(${r.id}/${r.terminalType})`).join('、') || '(该表单还没有任何布局)');
359
+ if (!matches.length)
360
+ throw new Error(`未找到布局「${opts.layout}」。现有:${listCurrent()}`);
361
+ if (matches.length > 1) {
362
+ throw new Error(`有 ${matches.length} 套布局都叫「${key}」,无法确定目标。请用布局 ID:`
363
+ + matches.map((r) => `${r.id}(${r.terminalType})`).join('、'));
364
+ }
365
+ const row = matches[0];
366
+ // ⚠ 不要按 isSys / readOnly 拦:**默认布局本来就是 isSys:true + readOnly:true**
367
+ // (eb 表关联流程真机抓包 2026-10-29,布局管理里照样能改名)。拦了就是「能用的命令不让用」。
368
+ // 真的不允许改时由平台拒绝,我们照常报错。
369
+ const name = opts.name === undefined ? row.name : opts.name.trim();
370
+ if (!name)
371
+ throw new Error('布局名称不能为空');
372
+ const describe = opts.describe === undefined ? String(row.describe ?? '') : opts.describe;
373
+ const oldDescribe = String(row.describe ?? '');
374
+ const result = (changed) => ({
375
+ changed,
376
+ layoutId: row.id,
377
+ oldName: row.name,
378
+ oldDescribe,
379
+ name,
380
+ describe,
381
+ terminalType: row.terminalType,
382
+ layoutType: row.layoutType,
383
+ isDefault: row.isDefault,
384
+ });
385
+ if (name === row.name && describe === oldDescribe)
386
+ return result(false);
387
+ const route = await resolveFormRoute(client, opts.formId, opts.workflowId, opts.workflowId ? undefined : 'workflow');
388
+ ok(await client.post(`${base}${route.updateLayout}`, {
389
+ module: route.cardModule,
390
+ customParam: {
391
+ // 与 `layout add` 一致:显式给了就用,没给用 formId 兜底
392
+ workflowId: opts.workflowId || opts.formId,
393
+ isNodeLayout: true,
394
+ },
395
+ formLayoutMultiple: buildLayoutUpdateRow(row, name, describe, row.describe !== undefined || opts.describe !== undefined),
396
+ local: true,
397
+ copyConfig: { formDataLinkage: true, excelLinkage: true },
398
+ }, { ebbusinessid: opts.formId }), '修改布局');
399
+ const after = await collectLayoutsBothTerminals(client, opts.formId, opts.workflowId, opts.formKind);
400
+ const saved = after.find((r) => r.id === row.id);
401
+ if (!saved)
402
+ throw new Error(`修改后回读布局列表里找不到布局 ${row.id}`);
403
+ if (saved.name !== name || String(saved.describe ?? '') !== describe) {
404
+ throw new Error(`修改后回读不一致:期望「${name}」/「${describe}」,实际「${saved.name}」/「${saved.describe ?? ''}」`);
405
+ }
406
+ // 只改名字,别把终端/类型/默认设置一起动了
407
+ const drift = ['terminalType', 'layoutType', 'isDefault', 'isSys', 'readOnly']
408
+ .filter((k) => String(row[k] ?? '') !== String(saved[k] ?? ''));
409
+ if (drift.length) {
410
+ throw new Error(`改名的同时这些布局属性被平台改动:${drift.join('、')} —— 请到布局管理核对`);
411
+ }
412
+ return result(true);
413
+ }
414
+ /**
415
+ * 把某套布局设为**该终端**的默认布局。
416
+ *
417
+ * 真机抓包(mulinquan 2026-10-29):
418
+ * `POST {route}/layout/updateDefault`
419
+ * `{ module, formLayoutMultiple:{ id, form:{id:formId}, default:true, terminalType }, local:true }`
420
+ *
421
+ * 默认布局是**表单维度**、且 PC/移动端各自一套 —— 所以终端取自目标布局自身,
422
+ * 不是让调用方再传一次(传错就会把另一端的默认改掉)。
423
+ * 改完回读:目标必须是默认,**同终端不能还有第二套默认**。
424
+ */
425
+ export async function setDefaultLayout(client, opts) {
426
+ const base = client.getBaseUrl();
427
+ const rows = await collectLayoutsBothTerminals(client, opts.formId, opts.workflowId, opts.formKind);
428
+ const key = String(opts.layout).trim();
429
+ if (!key)
430
+ throw new Error('布局 ID 或名称不能为空');
431
+ const byId = rows.filter((r) => r.id === key);
432
+ const matches = byId.length ? byId : rows.filter((r) => r.name === key);
433
+ if (!matches.length) {
434
+ throw new Error(`未找到布局「${opts.layout}」。现有:`
435
+ + (rows.map((r) => `${r.name}(${r.id}/${r.terminalType})`).join('、') || '(该表单还没有任何布局)'));
436
+ }
437
+ if (matches.length > 1) {
438
+ throw new Error(`有 ${matches.length} 套布局都叫「${key}」,无法确定目标。请用布局 ID:`
439
+ + matches.map((r) => `${r.id}(${r.terminalType})`).join('、'));
440
+ }
441
+ const row = matches[0];
442
+ const terminal = row.terminalType || 'PC';
443
+ const currentDefault = rows.find((r) => r.terminalType === terminal && r.isDefault);
444
+ const previousDefaultId = currentDefault?.id || '';
445
+ if (row.isDefault) {
446
+ return { changed: false, layoutId: row.id, name: row.name, terminalType: terminal, previousDefaultId };
447
+ }
448
+ const route = await resolveFormRoute(client, opts.formId, opts.workflowId, opts.workflowId ? undefined : 'workflow');
449
+ ok(await client.post(`${base}${route.updateDefault}`, {
450
+ module: route.cardModule,
451
+ formLayoutMultiple: {
452
+ id: row.id,
453
+ form: { id: opts.formId },
454
+ default: true,
455
+ terminalType: terminal,
456
+ },
457
+ local: true,
458
+ }, { ebbusinessid: opts.formId }), '设置默认布局');
459
+ const after = await collectLayoutsBothTerminals(client, opts.formId, opts.workflowId, opts.formKind);
460
+ const saved = after.find((r) => r.id === row.id);
461
+ if (!saved)
462
+ throw new Error(`设置后回读布局列表里找不到布局 ${row.id}`);
463
+ if (!saved.isDefault) {
464
+ throw new Error(`设置后回读「${saved.name}」仍不是默认布局 —— 请到布局管理核对`);
465
+ }
466
+ const rivalDefaults = after.filter((r) => r.terminalType === terminal && r.id !== row.id && r.isDefault);
467
+ if (rivalDefaults.length) {
468
+ throw new Error(`${terminal} 端同时存在多个默认布局:${rivalDefaults.map((r) => `${r.name}(${r.id})`).join('、')}`
469
+ + ` —— 请到布局管理核对`);
470
+ }
471
+ return { changed: true, layoutId: row.id, name: row.name, terminalType: terminal, previousDefaultId };
472
+ }
473
+ export const SYSTEM_FIELD_CATALOG = [
474
+ { key: 'REQ_REQUEST_NAME', type: 'FlowPageSysFieldReqName', label: '流程标题', compKey: 'FlowPageSysFieldInput', applyStyle: '34' },
475
+ { key: 'REQUEST_NO', type: 'FlowPageSysFieldMarkReserved', label: '流程编号', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
476
+ { key: 'REQUEST_LEVEL', type: 'FlowPageSysFieldRequestlevel', label: '紧急程度', compKey: 'FlowPageSysFieldInput', applyStyle: '34' },
477
+ { key: 'REQUEST_SECRET_LEVEL', type: 'FlowPageSysFieldSeclevel', label: '密级', compKey: 'FlowPageSysFieldInput', applyStyle: '34', inferred: true },
478
+ { key: 'CREATE_USER', type: 'FlowPageSysFieldCreator', label: '提交人', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
479
+ { key: 'CREATE_DEPT', type: 'FlowPageSysFieldCreatorDept', label: '提交人部门', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
480
+ { key: 'CREATE_SUB', type: 'FlowPageSysFieldCreatorSubCompany', label: '提交人分部', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
481
+ { key: 'CREATE_DATETIME', type: 'FlowPageSysFieldCreateTime', label: '提交时间', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
482
+ { key: 'FINISH_DATETIME', type: 'FlowPageSysFieldFinishTime', label: '结束时间', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
483
+ { key: 'FlowPageSysFieldExpiryTime', type: 'FlowPageSysFieldExpiryTime', label: '到期时间', compKey: 'FlowPageSysFieldInput', applyStyle: '34', inferred: true },
484
+ { key: 'PRINT_COUNT', type: 'FlowPageSysFieldPrintCount', label: '打印次数', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35', inferred: true },
485
+ { key: 'WORKFLOW_NAME', type: 'FlowPageSysFieldWorkflowName', label: '工作流名称', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
486
+ { key: 'WORKFLOW_TYPE', type: 'FlowPageSysFieldWorkflowType', label: '工作流类型', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
487
+ { key: 'WORKFLOW_DESC', type: 'FlowPageSysFieldWorkflowDesc', label: '工作流描述', compKey: 'FlowPageSysFieldReadOnly', applyStyle: '35' },
488
+ { key: 'FLOW_STATUS_COMP', type: 'FlowPageFlowStatus', label: '流程状态', compKey: 'FlowPageSysFieldNoContent', applyStyle: '36' },
489
+ ];
490
+ /** 按 名称 / key / 组件类型 解析系统字段;认不出就报错并列出可选。 */
491
+ export function resolveSystemField(input) {
492
+ const raw = String(input ?? '').trim();
493
+ if (!raw)
494
+ throw new Error('系统字段不能为空');
495
+ const hit = SYSTEM_FIELD_CATALOG.find((d) => d.key === raw)
496
+ || SYSTEM_FIELD_CATALOG.find((d) => d.type === raw)
497
+ || SYSTEM_FIELD_CATALOG.find((d) => d.label === raw);
498
+ if (!hit) {
499
+ throw new Error(`不支持的流程系统字段「${input}」。可选:`
500
+ + SYSTEM_FIELD_CATALOG.map((d) => `${d.label}(${d.key})`).join('、'));
501
+ }
502
+ return hit;
503
+ }
504
+ /** 组件 id:32 位十六进制,**首位取 a-f**(与平台生成的一致)。 */
505
+ function randomCompId() {
506
+ const first = 'abcdef';
507
+ const hex = '0123456789abcdef';
508
+ const b = randomBytes(32);
509
+ let out = first[b[0] % first.length];
510
+ for (let i = 1; i < 32; i++)
511
+ out += hex[b[i] % hex.length];
512
+ return out;
513
+ }
514
+ /** `config.flow.nodeId`:10 位 URL-safe 随机串。 */
515
+ function randomFlowNodeId() {
516
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
517
+ const b = randomBytes(10);
518
+ let out = '';
519
+ for (let i = 0; i < 10; i++)
520
+ out += chars[b[i] % chars.length];
521
+ return out;
522
+ }
523
+ /** 拼一个系统字段组件(形状对齐设计器落库,见 2026-10-29 抓包)。 */
524
+ export function buildSystemFieldComp(def, ctx) {
525
+ const isInput = def.compKey === 'FlowPageSysFieldInput';
526
+ return {
527
+ id: randomCompId(),
528
+ refCompId: '',
529
+ type: def.type,
530
+ category: '111',
531
+ refModule: '',
532
+ tenantKey: ctx.tenantKey,
533
+ styleCategoryCompKey: def.compKey,
534
+ styleCategoryPackage: '@weapp/workflow',
535
+ applyStyle: def.applyStyle,
536
+ isCover: 0,
537
+ // 可输入那两档(流程标题/紧急程度)设计器落库时没有 prop:EB,只读/无内容才有
538
+ ...(isInput ? {} : { prop: 'EB' }),
539
+ config: {
540
+ compPackage: '@weapp/workflow',
541
+ fieldId: def.key,
542
+ fieldKey: def.type,
543
+ flow: { parent: 'ROOT', nodes: [], isCanvas: false, linkedNodes: {}, nodeId: randomFlowNodeId() },
544
+ formId: ctx.formId,
545
+ isFormSyncTitleLayout: true,
546
+ layout: { selected: false, offsetTop: ctx.offsetTop },
547
+ name: def.label,
548
+ permission: {},
549
+ size: 'large',
550
+ switchFormItem: true,
551
+ title: def.label,
552
+ type: def.type,
553
+ valueKey: def.key,
554
+ showOrder: ctx.showOrder,
555
+ disableEdit: false,
556
+ display: true,
557
+ singleRow: ctx.singleRow === true,
558
+ readOnly: false,
559
+ required: false,
560
+ },
561
+ package: '@weapp/workflow',
562
+ };
563
+ }
564
+ /**
565
+ * 往某套流程表单布局里摆流程系统字段(提交人/流程编号/流程状态…)。
566
+ *
567
+ * 写的是**整份布局**:读取 `getFormLayout` → 在 `pageLayouts[0].comps` 末尾追加组件 →
568
+ * `builder/saveFormAndLayout` 回写。报文形状是设计器保存时的那套
569
+ * (真机抓包 2026-10-29):`formLayout.pageLayouts` 直接发原始 JSON 就能落库,
570
+ * 不需要 `pageLayoutEncodes`;但 `formLayout.multipleLayoutId` 必带。
571
+ *
572
+ * 已经在布局里的系统字段会跳过(幂等);写完回读核对新增字段,并确认原有组件一个没少。
573
+ */
574
+ export async function addSystemFieldsToLayout(client, opts) {
575
+ const base = client.getBaseUrl();
576
+ const route = await resolveFormRoute(client, opts.formId, opts.workflowId, opts.workflowId ? undefined : 'workflow');
577
+ // 目标布局:显式给了就按 id/名称找;没给 = PC 默认布局
578
+ const rows = await collectLayoutsBothTerminals(client, opts.formId, opts.workflowId, opts.formKind);
579
+ let target;
580
+ if (opts.layoutId) {
581
+ const key = String(opts.layoutId).trim();
582
+ const byId = rows.filter((r) => r.id === key);
583
+ const matches = byId.length ? byId : rows.filter((r) => r.name === key);
584
+ if (!matches.length) {
585
+ throw new Error(`未找到布局「${opts.layoutId}」。现有:`
586
+ + (rows.map((r) => `${r.name}(${r.id}/${r.terminalType})`).join('、') || '(该表单还没有任何布局)'));
587
+ }
588
+ if (matches.length > 1) {
589
+ throw new Error(`有 ${matches.length} 套布局都叫「${key}」,请用布局 ID:`
590
+ + matches.map((r) => `${r.id}(${r.terminalType})`).join('、'));
591
+ }
592
+ target = matches[0];
593
+ }
594
+ else {
595
+ target = rows.find((r) => r.terminalType === 'PC' && r.isDefault)
596
+ || rows.find((r) => r.isDefault);
597
+ if (!target)
598
+ throw new Error('该表单没有默认布局,请用 --layout-id 指定目标布局');
599
+ }
600
+ const defs = opts.all
601
+ ? [...SYSTEM_FIELD_CATALOG]
602
+ : (opts.fields || []).map(resolveSystemField);
603
+ if (!defs.length)
604
+ throw new Error('请给出要添加的系统字段,或加 --all 添加全部');
605
+ const read = async () => {
606
+ const res = ok(await client.post(`${base}${route.getFormLayout}`, { ...getFormLayoutBody(opts.formId, target.id), module: route.formModule }, { ebbusinessid: opts.formId }), '读取布局内容');
607
+ return res;
608
+ };
609
+ const data = await read();
610
+ const layout = structuredClone(data?.formLayout || {});
611
+ const pages = Array.isArray(layout.pageLayouts) ? layout.pageLayouts : [];
612
+ if (!pages.length)
613
+ throw new Error('该布局没有 pageLayouts,无法添加字段');
614
+ const page = pages[0];
615
+ const comps = Array.isArray(page.comps) ? page.comps : [];
616
+ const existingKeys = new Set(comps.map((c) => String(c?.config?.fieldId ?? c?.config?.valueKey ?? '')).filter(Boolean));
617
+ const beforeIds = new Set(comps.map((c) => String(c?.id ?? '')).filter(Boolean));
618
+ const added = [];
619
+ const skipped = [];
620
+ let maxOrder = comps.reduce((m, c) => Math.max(m, Number(c?.config?.showOrder) || 0), -1);
621
+ let maxTop = comps.reduce((m, c) => Math.max(m, Number(c?.config?.layout?.offsetTop) || 0), -1);
622
+ for (const def of defs) {
623
+ if (existingKeys.has(def.key)) {
624
+ skipped.push({ key: def.key, title: def.label });
625
+ continue;
626
+ }
627
+ maxOrder += 1;
628
+ maxTop += 79;
629
+ comps.push(buildSystemFieldComp(def, {
630
+ formId: opts.formId, tenantKey: opts.tenantKey,
631
+ showOrder: maxOrder, offsetTop: maxTop, singleRow: opts.singleRow,
632
+ }));
633
+ existingKeys.add(def.key);
634
+ added.push({ key: def.key, title: def.label });
635
+ }
636
+ if (!added.length) {
637
+ return { layoutId: target.id, layoutName: target.name, terminalType: target.terminalType, added, skipped };
638
+ }
639
+ page.comps = comps;
640
+ const form = data?.form || {};
641
+ ok(await client.post(`${base}${route.saveFormAndLayout}`, {
642
+ module: route.cardModule,
643
+ // 与设计器保存一致:workflowId 必带;layoutMultiId/nodeId 置空
644
+ customParam: { workflowId: opts.workflowId || opts.formId, layoutMultiId: '', nodeId: '' },
645
+ designerParam: { permissionId: '', changes: {}, onlyLayout: false, convert: false },
646
+ form: {
647
+ module: form.module || route.formModule,
648
+ id: String(form.id || opts.formId),
649
+ name: String(form.name || ''),
650
+ describe: String(form.describe || ''),
651
+ physicalTable: !!form.physicalTable,
652
+ pageNo: 0, current: 0, pageSize: 0,
653
+ isVirtualForm: !!form.isVirtualForm,
654
+ },
655
+ formLayout: {
656
+ updateTimeStamp: layout.updateTimeStamp,
657
+ id: layout.id,
658
+ name: layout.name,
659
+ describe: layout.describe || '',
660
+ multipleLayoutId: target.id,
661
+ formId: opts.formId,
662
+ pageLayouts: layout.pageLayouts,
663
+ formStyle: layout.formStyle,
664
+ },
665
+ }, { ebbusinessid: opts.formId }), '保存布局');
666
+ // 回读:新字段必须在、原有组件一个不能少
667
+ const after = await read();
668
+ const afterComps = (after?.formLayout?.pageLayouts?.[0]?.comps) || [];
669
+ const afterKeys = new Set(afterComps.map((c) => String(c?.config?.fieldId ?? c?.config?.valueKey ?? '')).filter(Boolean));
670
+ const missing = added.filter((x) => !afterKeys.has(x.key)).map((x) => `${x.title}(${x.key})`);
671
+ if (missing.length)
672
+ throw new Error(`保存后回读缺少系统字段:${missing.join('、')}`);
673
+ const afterIds = new Set(afterComps.map((c) => String(c?.id ?? '')).filter(Boolean));
674
+ const lost = [...beforeIds].filter((id) => !afterIds.has(id));
675
+ if (lost.length) {
676
+ throw new Error(`保存后原有组件少了 ${lost.length} 个(${lost.slice(0, 3).join('、')}${lost.length > 3 ? '…' : ''})—— 请到设计器核对`);
677
+ }
678
+ return { layoutId: target.id, layoutName: target.name, terminalType: target.terminalType, added, skipped };
679
+ }
286
680
  /** 读某套布局的内容(不传 layoutId 读默认布局)。 */
287
681
  export async function getLayoutContent(client, formId, layoutId, workflowId, formKind) {
288
682
  const base = client.getBaseUrl();