weaver-e10-builder 1.6.7 → 1.6.9
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/commands/form-attachment-setting.d.ts.map +1 -1
- package/dist/commands/form-attachment-setting.js +147 -50
- package/dist/commands/form-attachment-setting.js.map +1 -1
- package/dist/commands/form-code.d.ts.map +1 -1
- package/dist/commands/form-code.js +4 -1
- package/dist/commands/form-code.js.map +1 -1
- package/dist/commands/form-field-linkage.d.ts +2 -0
- package/dist/commands/form-field-linkage.d.ts.map +1 -1
- package/dist/commands/form-field-linkage.js +97 -41
- package/dist/commands/form-field-linkage.js.map +1 -1
- package/dist/commands/form-layout-code-reviewed.d.ts.map +1 -1
- package/dist/commands/form-layout-code-reviewed.js +5 -2
- package/dist/commands/form-layout-code-reviewed.js.map +1 -1
- package/dist/commands/form-layout.js +1 -1
- package/dist/commands/form-layout.js.map +1 -1
- package/dist/commands/menu.d.ts.map +1 -1
- package/dist/commands/menu.js +90 -1
- package/dist/commands/menu.js.map +1 -1
- package/dist/commands/wf-form.d.ts.map +1 -1
- package/dist/commands/wf-form.js +111 -39
- package/dist/commands/wf-form.js.map +1 -1
- package/dist/services/actionflow/form_source.d.ts.map +1 -1
- package/dist/services/actionflow/form_source.js +7 -6
- package/dist/services/actionflow/form_source.js.map +1 -1
- package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
- package/dist/services/actionflow/preflight_service.js +10 -1
- package/dist/services/actionflow/preflight_service.js.map +1 -1
- package/dist/services/form-attachment-settings.d.ts +47 -20
- package/dist/services/form-attachment-settings.d.ts.map +1 -1
- package/dist/services/form-attachment-settings.js +148 -68
- package/dist/services/form-attachment-settings.js.map +1 -1
- package/dist/services/form-code.d.ts +1 -1
- package/dist/services/form-code.d.ts.map +1 -1
- package/dist/services/form-code.js +2 -2
- package/dist/services/form-code.js.map +1 -1
- package/dist/services/form-layout-code-reviewed.d.ts +2 -0
- package/dist/services/form-layout-code-reviewed.d.ts.map +1 -1
- package/dist/services/form-layout-code-reviewed.js +4 -3
- package/dist/services/form-layout-code-reviewed.js.map +1 -1
- package/dist/services/menu-catalog.d.ts +45 -0
- package/dist/services/menu-catalog.d.ts.map +1 -1
- package/dist/services/menu-catalog.js +76 -0
- package/dist/services/menu-catalog.js.map +1 -1
- package/dist/services/workflow-layout-init-reviewed.d.ts +2 -0
- package/dist/services/workflow-layout-init-reviewed.d.ts.map +1 -1
- package/dist/services/workflow-layout-init-reviewed.js +30 -2
- package/dist/services/workflow-layout-init-reviewed.js.map +1 -1
- package/dist/services/workflow-layout-structure.d.ts +3 -0
- package/dist/services/workflow-layout-structure.d.ts.map +1 -0
- package/dist/services/workflow-layout-structure.js +44 -0
- package/dist/services/workflow-layout-structure.js.map +1 -0
- package/package.json +1 -1
- package/skill-docs/SKILL.md +4 -4
- package/skill-docs/_catalog.md +1 -1
- package/skill-docs/references/common/capability-boundaries.md +6 -4
- package/skill-docs/references/common/ref-cli-commands.md +4 -3
- package/skill-docs/references/form/guide-field-linkage.md +9 -1
- package/skill-docs/references/form/guide-form-attachment-setting.md +31 -12
- package/skill-docs/references/form/guide-form-layout-planning.md +1 -1
- package/skill-docs/references/form/layout/code-block/code-block-guide.md +5 -5
- package/skill-docs/references/form/layout/code-block/layout-css.md +95 -15
- package/skill-docs/references/form/layout/template/advanced.md +2 -0
- package/skill-docs/references/form/layout/workflow-layout.md +10 -0
- package/skill-docs/references/menu/system-menus.md +21 -0
- package/skill-docs/references/code-block/guide-code-block.md +0 -141
- package/skill-docs/references/code-block/guide-layout-css.md +0 -107
- package/skill-docs/references/code-block/ref-controls.md +0 -60
- package/skill-docs/references/code-block/ref-coverage.md +0 -32
- package/skill-docs/references/code-block/ref-details.md +0 -57
- package/skill-docs/references/code-block/ref-events-validation.md +0 -42
- package/skill-docs/references/code-block/ref-foundations-fields.md +0 -56
- package/skill-docs/references/code-block/ref-recipes.md +0 -164
- package/skill-docs/references/code-block/ref-troubleshooting.md +0 -49
- package/skill-docs/references/code-block/ref-ui-global.md +0 -47
- package/skill-docs/references/form/form-template/style-templates-advanced-css-guide.md +0 -167
- package/skill-docs/references/form/form-template/style-templates-advanced.md +0 -315
- package/skill-docs/references/form/form-template/style-templates-easy.md +0 -55
- package/skill-docs/references/form/form-template/style-templates-flow.md +0 -27
- package/skill-docs/references/form/form-template/style-templates.md +0 -29
package/dist/commands/wf-form.js
CHANGED
|
@@ -8,6 +8,9 @@ import { getRichType, resolveBrowserConfig, richIdUnits, BROWSER_TYPE_CATALOG }
|
|
|
8
8
|
import { dropFieldComponents, prepareLayoutForSave } from '../services/form-field-drop.js';
|
|
9
9
|
import { resolveBrowserByName } from '../services/browser.js';
|
|
10
10
|
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import { resolveStyleTemplateId } from '../services/form-style-template.js';
|
|
12
|
+
import { readTemplateEvidence, verifyAppliedTemplate } from '../services/form-layout-template-verification.js';
|
|
13
|
+
import { workflowExcelStructureIssues } from '../services/workflow-layout-structure.js';
|
|
11
14
|
import { readFileSync } from 'node:fs';
|
|
12
15
|
import { buildConditionDetail, resolveWorkflowEffect, readLinkageConfig } from '../services/form-linkage-condition.js';
|
|
13
16
|
import { resolveSourceForm } from '../services/action-detail.js';
|
|
@@ -72,8 +75,34 @@ async function getLayoutMeta(client, baseUrl, formId, layoutMultiId) {
|
|
|
72
75
|
return {
|
|
73
76
|
layoutId: fl.id || '', layoutMultiId: flm.id || '', layoutName: flm.name || '',
|
|
74
77
|
layoutType: flm.layoutType || 'FLOW', terminalType: flm.terminalType || 'PC',
|
|
78
|
+
formLayout: fl,
|
|
75
79
|
};
|
|
76
80
|
}
|
|
81
|
+
/** A rebuilding command must never silently replace a non-default template. */
|
|
82
|
+
async function templateForWorkflowRebuild(client, baseUrl, formId, meta, requested) {
|
|
83
|
+
if (requested)
|
|
84
|
+
return (await resolveStyleTemplateId(client, baseUrl, formId, meta.layoutType, requested)).id;
|
|
85
|
+
const defaultId = meta.layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008';
|
|
86
|
+
if (!(meta.formLayout.pageLayouts || []).some((page) => page.comps?.length) || !meta.formLayout.formStyle?.styleConfig)
|
|
87
|
+
return defaultId;
|
|
88
|
+
const defaultStyle = await readTemplateEvidence(client, baseUrl, meta.layoutType, defaultId);
|
|
89
|
+
if (verifyAppliedTemplate(defaultStyle, meta.formLayout).length) {
|
|
90
|
+
throw new Error('当前布局不是系统默认模板效果;重建会覆盖现有样式。请显式传 --style-template <当前模板ID>,或使用布局局部编辑能力');
|
|
91
|
+
}
|
|
92
|
+
return defaultId;
|
|
93
|
+
}
|
|
94
|
+
async function verifyWorkflowRebuild(client, baseUrl, formId, templateId) {
|
|
95
|
+
const after = await getLayoutMeta(client, baseUrl, formId);
|
|
96
|
+
const issues = workflowExcelStructureIssues(after.formLayout);
|
|
97
|
+
const compCount = after.formLayout.pageLayouts?.[0]?.comps?.length || 0;
|
|
98
|
+
if (!compCount)
|
|
99
|
+
issues.push('回读布局没有组件');
|
|
100
|
+
const evidence = await readTemplateEvidence(client, baseUrl, after.layoutType, templateId);
|
|
101
|
+
issues.push(...verifyAppliedTemplate(evidence, after.formLayout));
|
|
102
|
+
if (issues.length)
|
|
103
|
+
throw new Error(`平台已接受布局,但独立回读校验失败:${issues.join(';')}`);
|
|
104
|
+
return compCount;
|
|
105
|
+
}
|
|
77
106
|
async function readConfigs(client, baseUrl, formId) {
|
|
78
107
|
const meta = await getLayoutMeta(client, baseUrl, formId);
|
|
79
108
|
const cfg = await client.post(`${baseUrl}${ROUTE}/view/relate/getConfig`, {
|
|
@@ -188,6 +217,11 @@ function applyLoneSingleRows(configs) {
|
|
|
188
217
|
const det = details.map((d) => ({ ...d, singleRow: true }));
|
|
189
218
|
return [...others, ...biz, ...det];
|
|
190
219
|
}
|
|
220
|
+
/** initLayout generates group containers from groupFieldIds; never submit existing Fold containers as input. */
|
|
221
|
+
function withoutCollapseContainers(configs) {
|
|
222
|
+
return configs.flatMap((c) => c.type === 'Collapse' || c.componentKey === 'Fold'
|
|
223
|
+
? withoutCollapseContainers(c.children || []) : [c]);
|
|
224
|
+
}
|
|
191
225
|
// 读表单现有字段分组 → refFieldIds(initLayout/getConfig 的 groupFieldIds)。
|
|
192
226
|
// getFieldGroupPage 返回全部主表字段,字段 formField.group 带 groupId+groupName;
|
|
193
227
|
// refFieldId = groupId - 1(平台先分配 layout config 再分配 formFieldGroup,顺序相连)。
|
|
@@ -205,7 +239,7 @@ async function fetchFormGroupEntries(client, baseUrl, formId) {
|
|
|
205
239
|
for (const f of list) {
|
|
206
240
|
const g = f?.formField?.group;
|
|
207
241
|
if (g?.id)
|
|
208
|
-
out.push(g);
|
|
242
|
+
out.push({ ...g, __fieldId: f?.formField?.id || f?.formField?.fieldId || f?.fieldId });
|
|
209
243
|
}
|
|
210
244
|
if (list.length < PAGE)
|
|
211
245
|
break;
|
|
@@ -230,6 +264,9 @@ export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, ho
|
|
|
230
264
|
throw new Error('无法获取 layoutId');
|
|
231
265
|
// 保留字段分组:getConfig/initLayout 带 groupFieldIds,否则 Collapse 折叠被冲掉
|
|
232
266
|
const groupIds = await fetchFormGroups(client, baseUrl, formId);
|
|
267
|
+
if (meta.layoutType === 'EXCEL' && o.generateCollapse === false && groupIds.length) {
|
|
268
|
+
throw new Error('表单已有字段分组;关闭 generateCollapse 会丢失分组子网格,已中止');
|
|
269
|
+
}
|
|
233
270
|
// ⚠️ configs **一律从默认布局取**,哪怕这次要写的是另一套布局。
|
|
234
271
|
// 实测:拿目标布局自己的 runtime id 去 getConfig 也能回一份 configs(字段数看着一样),
|
|
235
272
|
// 但拿它 initLayout **写不进目标布局** —— 接口回 200、回读 `comps: 0`,静默失败。
|
|
@@ -271,7 +308,7 @@ export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, ho
|
|
|
271
308
|
if (hooks.preLayout)
|
|
272
309
|
hooks.preLayout(configs);
|
|
273
310
|
// 落单/孤字段占满行(对齐 eb 表):奇数个最后一个 + 被 singleRow 挤落单的前一字段自动 singleRow
|
|
274
|
-
const finalConfigs = applyLoneSingleRows(configs);
|
|
311
|
+
const finalConfigs = applyLoneSingleRows(meta.layoutType === 'EXCEL' ? withoutCollapseContainers(configs) : configs);
|
|
275
312
|
const styleTemplateId = o.styleTemplate
|
|
276
313
|
|| (meta.layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008');
|
|
277
314
|
const initRes = await client.post(`${baseUrl}${ROUTE}/view/relate/initLayout`, {
|
|
@@ -287,6 +324,10 @@ export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, ho
|
|
|
287
324
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
288
325
|
throw new Error(`initLayout 失败: ${initRes?.msg}`);
|
|
289
326
|
const comps = initRes?.data?.pageLayouts?.[0]?.comps || initRes?.data?.formLayout?.pageLayouts?.[0]?.comps || [];
|
|
327
|
+
const returnedLayout = initRes?.data?.formLayout || { pageLayouts: initRes?.data?.pageLayouts };
|
|
328
|
+
const structureIssues = workflowExcelStructureIssues(returnedLayout);
|
|
329
|
+
if (structureIssues.length)
|
|
330
|
+
throw new Error(`平台已接受布局,但返回结构不完整:${structureIssues.join(';')}`);
|
|
290
331
|
return { layoutType: meta.layoutType, styleTemplateId, comps: comps.length };
|
|
291
332
|
}
|
|
292
333
|
async function genIds(client, baseUrl, n) {
|
|
@@ -510,6 +551,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
510
551
|
.option('--browser-form-source <src>', '--browser-type form 时的来源:business(默认) / ebuilder')
|
|
511
552
|
.option('--browser-name <name>', '按名字指定浏览数据源(含自定义浏览框,如 "CLM-合同类型");优先于 --browser-type')
|
|
512
553
|
.option('--no-init', '跳过末尾自动 layout init(默认加完自动重排布局,对齐 add-fields 批量)')
|
|
554
|
+
.option('--style-template <name|id>', '自动重排时应用的当前样式模板;已有自定义样式需指定')
|
|
513
555
|
.action(async (formId, fieldName, fieldType, title, o) => {
|
|
514
556
|
try {
|
|
515
557
|
const opts = program.opts();
|
|
@@ -519,6 +561,9 @@ export function registerWorkflowFormCommands(program) {
|
|
|
519
561
|
const client = new ApiClient(auth);
|
|
520
562
|
const baseUrl = auth.getBaseUrl();
|
|
521
563
|
const ebb = { ebbusinessid: formId };
|
|
564
|
+
const autoTemplate = o.init !== false
|
|
565
|
+
? await templateForWorkflowRebuild(client, baseUrl, formId, await getLayoutMeta(client, baseUrl, formId), o.styleTemplate)
|
|
566
|
+
: undefined;
|
|
522
567
|
const ck = canon(fieldType);
|
|
523
568
|
const colName = toColumnName(fieldName);
|
|
524
569
|
const [fieldId] = await genIds(client, baseUrl, 1);
|
|
@@ -634,7 +679,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
634
679
|
// 走 initWorkflowFormLayout:强制业务字段可编辑(防 FLOW 锁死)+ 合并运行时 singleRow + applyLoneSingleRows(落单独占整行)。
|
|
635
680
|
if (o.init !== false) {
|
|
636
681
|
try {
|
|
637
|
-
await initWorkflowFormLayout(client, baseUrl, formId, {}, o.singleRow ? {
|
|
682
|
+
await initWorkflowFormLayout(client, baseUrl, formId, { styleTemplate: autoTemplate }, o.singleRow ? {
|
|
638
683
|
preLayout: (cfgs) => {
|
|
639
684
|
// --single-row:field jsonObj 的 singleRow 平台不落到 layout comp(getConfig 不带),
|
|
640
685
|
// 显式给新加字段 config.singleRow=true(递归找 fieldId,含明细 children)。
|
|
@@ -651,10 +696,12 @@ export function registerWorkflowFormCommands(program) {
|
|
|
651
696
|
walkSet(cfgs);
|
|
652
697
|
},
|
|
653
698
|
} : undefined);
|
|
699
|
+
await verifyWorkflowRebuild(client, baseUrl, formId, autoTemplate);
|
|
654
700
|
console.error(` 布局已 init`);
|
|
655
701
|
}
|
|
656
702
|
catch (e) {
|
|
657
|
-
console.error(` 布局 init
|
|
703
|
+
console.error(` 布局 init 或回读失败: ${e?.message || e}(字段已加,布局未确认;请先检查当前布局)`);
|
|
704
|
+
process.exitCode = 1;
|
|
658
705
|
}
|
|
659
706
|
}
|
|
660
707
|
// 开关:布局 init 可能把字段 options 冲回空,布局之后再补一次 开启=1 / 关闭=0。
|
|
@@ -1385,6 +1432,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1385
1432
|
.argument('<formId>', '流程表单 formId')
|
|
1386
1433
|
.argument('<fieldsJson>', '字段定义 JSON / @文件路径')
|
|
1387
1434
|
.option('--no-init', '跳过末尾自动 layout init(默认加完自动重排布局)')
|
|
1435
|
+
.option('--style-template <name|id>', '自动重排时应用的当前样式模板;已有自定义样式需指定')
|
|
1388
1436
|
.action(async (formId, fieldsJson, cmdOpts) => {
|
|
1389
1437
|
try {
|
|
1390
1438
|
const opts = program.opts();
|
|
@@ -1410,6 +1458,9 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1410
1458
|
}
|
|
1411
1459
|
if (!Array.isArray(defs) || !defs.length)
|
|
1412
1460
|
throw new Error('fieldsJson 需为非空数组');
|
|
1461
|
+
const autoTemplate = cmdOpts.init !== false
|
|
1462
|
+
? await templateForWorkflowRebuild(client, baseUrl, formId, await getLayoutMeta(client, baseUrl, formId), cmdOpts.styleTemplate)
|
|
1463
|
+
: undefined;
|
|
1413
1464
|
const ids = await genIds(client, baseUrl, defs.length);
|
|
1414
1465
|
let added = 0;
|
|
1415
1466
|
for (let i = 0; i < defs.length; i++) {
|
|
@@ -1434,12 +1485,13 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1434
1485
|
let compCount = 0;
|
|
1435
1486
|
if (cmdOpts.init !== false && added > 0) {
|
|
1436
1487
|
try {
|
|
1437
|
-
const r = await initWorkflowFormLayout(client, baseUrl, formId);
|
|
1438
|
-
compCount =
|
|
1488
|
+
const r = await initWorkflowFormLayout(client, baseUrl, formId, { styleTemplate: autoTemplate });
|
|
1489
|
+
compCount = await verifyWorkflowRebuild(client, baseUrl, formId, autoTemplate);
|
|
1439
1490
|
console.error(` 布局已 init: 组件 ${compCount} 个`);
|
|
1440
1491
|
}
|
|
1441
1492
|
catch (e) {
|
|
1442
|
-
console.error(` 布局 init
|
|
1493
|
+
console.error(` 布局 init 或回读失败: ${e?.message || e}(字段已加,布局未确认;请先检查当前布局)`);
|
|
1494
|
+
process.exitCode = 1;
|
|
1443
1495
|
}
|
|
1444
1496
|
}
|
|
1445
1497
|
console.log(opts.json
|
|
@@ -1539,8 +1591,14 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1539
1591
|
// 读全字段
|
|
1540
1592
|
const fData = await client.post(`${baseUrl}${ROUTE}/field/manage/getFormField`, { module: MODULE, formTableField: { formField: { id: fieldId, form: { id: formId } } } }, ebb);
|
|
1541
1593
|
const jsonObj = fData?.data || {};
|
|
1542
|
-
if (!jsonObj.fieldId)
|
|
1543
|
-
|
|
1594
|
+
if (!jsonObj.fieldId) {
|
|
1595
|
+
const { configs } = await readConfigs(client, baseUrl, formId);
|
|
1596
|
+
const detail = configs.find((c) => String(c.id) === fieldId &&
|
|
1597
|
+
(c.componentKey === 'DataTable' || c.type === 'DetailTable'));
|
|
1598
|
+
throw new Error(detail
|
|
1599
|
+
? `ID ${fieldId} 是明细表容器,不是普通字段;edit-field 不能修改其标题,当前 CLI 尚无已验证的明细表标题修改命令`
|
|
1600
|
+
: `getFormField 未读到普通字段 fieldId=${fieldId}`);
|
|
1601
|
+
}
|
|
1544
1602
|
const changes = [];
|
|
1545
1603
|
if (o.title !== undefined) {
|
|
1546
1604
|
jsonObj.title = o.title;
|
|
@@ -1827,6 +1885,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1827
1885
|
.argument('[firstFieldName]', '首字段名(强烈建议传;空子表 getConfig 读不到)')
|
|
1828
1886
|
.option('--data-key <k>', '子表物理表名/dataKey(默认 uf_拼音_随机)')
|
|
1829
1887
|
.option('--init', '创建后跑 layout init 放入 DetailTable 组件')
|
|
1888
|
+
.option('--style-template <name|id>', '配合 --init 时应用的当前样式模板;已有自定义样式需指定')
|
|
1830
1889
|
.option('--first-field-type <t>', '首字段类型(默认 Text)')
|
|
1831
1890
|
.option('--first-field-data-key <k>', '首字段编码 dataKey(缺省取首字段名拼音首字母,与 add-field 一致)')
|
|
1832
1891
|
.action(async (formId, name, firstFieldName, o) => {
|
|
@@ -1838,6 +1897,9 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1838
1897
|
const client = new ApiClient(auth);
|
|
1839
1898
|
const baseUrl = auth.getBaseUrl();
|
|
1840
1899
|
const ebb = { ebbusinessid: formId };
|
|
1900
|
+
const autoTemplate = o.init
|
|
1901
|
+
? await templateForWorkflowRebuild(client, baseUrl, formId, await getLayoutMeta(client, baseUrl, formId), o.styleTemplate)
|
|
1902
|
+
: undefined;
|
|
1841
1903
|
const [subFormId] = await genIds(client, baseUrl, 1);
|
|
1842
1904
|
if (!subFormId)
|
|
1843
1905
|
throw new Error('生成 subFormId 失败');
|
|
@@ -1874,7 +1936,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1874
1936
|
// 走 initWorkflowFormLayout:强制业务字段可编辑 + applyLoneSingleRows(落单独占整行)+ 保留分组;
|
|
1875
1937
|
// DetailTable 由 normalizeDetailTableChildren 保留在 configs,applyLoneSingleRows 对明细恒 singleRow。
|
|
1876
1938
|
try {
|
|
1877
|
-
const r = await initWorkflowFormLayout(client, baseUrl, formId);
|
|
1939
|
+
const r = await initWorkflowFormLayout(client, baseUrl, formId, { styleTemplate: autoTemplate });
|
|
1878
1940
|
compCount = r.comps;
|
|
1879
1941
|
console.error(` 布局已 init: 组件 ${compCount} 个(含 DetailTable)`);
|
|
1880
1942
|
}
|
|
@@ -1901,13 +1963,12 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1901
1963
|
// 流程表单字段分组(基本信息/系统设置等折叠容器)。三步接口(module=workflow,实测可用):
|
|
1902
1964
|
// ① saveFieldGroup 建分组 → data.group.id(formFieldGroup记录id) + refFieldId(layout Collapse id)
|
|
1903
1965
|
// ② updateFormFieldGroup 分配字段(fieldList)
|
|
1904
|
-
// ③ initLayout
|
|
1905
|
-
// dataKey:"f_"+refFieldId, children:[分组字段]} + 顶层 groupFieldIds:[refFieldId]
|
|
1906
|
-
// (对齐 eb 表 form-create.ts FLOW 分组结构 / 记忆 field-group-saveFieldGroup-api)
|
|
1966
|
+
// ③ initLayout 平铺 configs + groupFieldIds,平台生成 Collapse 与子网格
|
|
1907
1967
|
wfForm.command('group')
|
|
1908
1968
|
.description('创建字段分组、分配字段并设置布局折叠')
|
|
1909
1969
|
.argument('<formId>', '流程表单 formId')
|
|
1910
1970
|
.requiredOption('--groups <json>', '分组定义 JSON:{"分组名":["字段名或ID",...]},可 @文件路径')
|
|
1971
|
+
.option('--style-template <name|id>', '重建时明确应用的当前样式模板;已有自定义样式必须指定')
|
|
1911
1972
|
.action(async (formId, o) => {
|
|
1912
1973
|
try {
|
|
1913
1974
|
const opts = program.opts();
|
|
@@ -1935,6 +1996,8 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1935
1996
|
const entries = Object.entries(groups || {});
|
|
1936
1997
|
if (entries.length === 0)
|
|
1937
1998
|
throw new Error('--groups 为空');
|
|
1999
|
+
const initialMeta = await getLayoutMeta(client, baseUrl, formId);
|
|
2000
|
+
const styleTemplateId = await templateForWorkflowRebuild(client, baseUrl, formId, initialMeta, o.styleTemplate);
|
|
1938
2001
|
// 名字 → 字段列表,无字段的分组也允许(空分组占位,后续 assign)
|
|
1939
2002
|
// 解析字段(主表字段名→fieldId;含明细字段名但分组只建议主表)
|
|
1940
2003
|
const { configs } = await readConfigs(client, baseUrl, formId);
|
|
@@ -2009,29 +2072,37 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2009
2072
|
}, ebb);
|
|
2010
2073
|
if (cfgRes?.code !== 200 || !cfgRes?.status)
|
|
2011
2074
|
throw new Error(`getConfig 失败: ${cfgRes?.msg}`);
|
|
2012
|
-
const
|
|
2075
|
+
const rawConfigs = JSON.parse(JSON.stringify(cfgRes?.data?.configs || []));
|
|
2076
|
+
const allConfigs = meta.layoutType === 'EXCEL' ? withoutCollapseContainers(rawConfigs) : rawConfigs;
|
|
2013
2077
|
// 合并运行时已保存的 singleRow(getConfig 不带,防 initLayout 冲掉独占一行)
|
|
2014
2078
|
const allSrSet = await fetchRuntimeSingleRows(client, baseUrl, formId);
|
|
2015
2079
|
mergeRuntimeSingleRow(allConfigs, allSrSet);
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
const
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
id
|
|
2080
|
+
const groupFieldIds = await fetchFormGroups(client, baseUrl, formId);
|
|
2081
|
+
// EXCEL 由平台生成容器与子网格;FLOW 需要显式 Fold 输入。
|
|
2082
|
+
let finalConfigs;
|
|
2083
|
+
if (meta.layoutType === 'EXCEL') {
|
|
2084
|
+
finalConfigs = applyLoneSingleRows(allConfigs);
|
|
2085
|
+
}
|
|
2086
|
+
else {
|
|
2087
|
+
const assigned = await fetchFormGroupEntries(client, baseUrl, formId);
|
|
2088
|
+
const byGroup = new Map();
|
|
2089
|
+
for (const row of assigned) {
|
|
2090
|
+
const id = String(row.id);
|
|
2091
|
+
const group = byGroup.get(id) || { name: String(row.groupName || ''), fieldIds: new Set() };
|
|
2092
|
+
if (row.__fieldId)
|
|
2093
|
+
group.fieldIds.add(String(row.__fieldId));
|
|
2094
|
+
byGroup.set(id, group);
|
|
2095
|
+
}
|
|
2096
|
+
const groupedIds = new Set([...byGroup.values()].flatMap(g => [...g.fieldIds]));
|
|
2097
|
+
const rest = allConfigs.filter((c) => !groupedIds.has(String(c.id)));
|
|
2098
|
+
const folds = [...byGroup].map(([groupId, grp]) => ({
|
|
2099
|
+
id: String(BigInt(groupId) - 1n), name: grp.name, componentKey: 'Fold', display: true, show: true,
|
|
2027
2100
|
readOnly: true, required: false, disableEdit: false, singleRow: false, isDelete: false,
|
|
2028
|
-
type: 'Collapse', typeDescribe: '分组', dataKey: `f_${
|
|
2029
|
-
children,
|
|
2030
|
-
});
|
|
2101
|
+
type: 'Collapse', typeDescribe: '分组', dataKey: `f_${String(BigInt(groupId) - 1n)}`,
|
|
2102
|
+
children: allConfigs.filter((c) => grp.fieldIds.has(String(c.id))),
|
|
2103
|
+
}));
|
|
2104
|
+
finalConfigs = applyLoneSingleRows([...folds, ...rest]);
|
|
2031
2105
|
}
|
|
2032
|
-
// 落单/孤字段占满行(含分组内字段 singleRow 由平台 Collapse 自行排布,只对未分组字段算)
|
|
2033
|
-
const finalConfigs = applyLoneSingleRows([...collapses, ...rest]);
|
|
2034
|
-
const styleTemplateId = meta.layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008';
|
|
2035
2106
|
const initRes = await client.post(`${baseUrl}${ROUTE}/view/relate/initLayout`, {
|
|
2036
2107
|
formId, module: MODULE, apiModule: 'workflow/form', layoutId: meta.layoutId,
|
|
2037
2108
|
generateCollapse: true, styleTemplateId, styleTemplateType: 1,
|
|
@@ -2043,10 +2114,10 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2043
2114
|
}, ebb);
|
|
2044
2115
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
2045
2116
|
throw new Error(`initLayout 失败: ${initRes?.msg}`);
|
|
2046
|
-
const
|
|
2117
|
+
const compCount = await verifyWorkflowRebuild(client, baseUrl, formId, styleTemplateId);
|
|
2047
2118
|
console.log(opts.json
|
|
2048
|
-
? JSON.stringify({ success: true, formId, groups: created.map((g) => ({ name: g.name, groupId: g.groupId, refFieldId: g.refFieldId, fieldCount: g.fieldIds.length })), comps:
|
|
2049
|
-
: `字段分组完成: ${created.length} 个分组,布局 ${
|
|
2119
|
+
? JSON.stringify({ success: true, formId, groups: created.map((g) => ({ name: g.name, groupId: g.groupId, refFieldId: g.refFieldId, fieldCount: g.fieldIds.length })), comps: compCount }, null, 2)
|
|
2120
|
+
: `字段分组完成: ${created.length} 个分组,布局 ${compCount} 组件`);
|
|
2050
2121
|
}
|
|
2051
2122
|
catch (e) {
|
|
2052
2123
|
console.error(`字段分组失败: ${e.message}`);
|
|
@@ -2288,6 +2359,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2288
2359
|
.option('--readonly <fields...>', '设为只读(readOnly=true, disableEdit=true)')
|
|
2289
2360
|
.option('--editable <fields...>', '设为可编辑(readOnly=false, disableEdit=false)')
|
|
2290
2361
|
.option('--single-row <fields...>', '独占一行(singleRow=true)')
|
|
2362
|
+
.option('--style-template <name|id>', '重建时明确应用的当前样式模板;已有自定义样式必须指定')
|
|
2291
2363
|
.action(async (formId, o) => {
|
|
2292
2364
|
try {
|
|
2293
2365
|
const opts = program.opts();
|
|
@@ -2300,6 +2372,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2300
2372
|
const meta = await getLayoutMeta(client, baseUrl, formId);
|
|
2301
2373
|
if (!meta.layoutId)
|
|
2302
2374
|
throw new Error('无法获取 layoutId');
|
|
2375
|
+
const styleTemplateId = await templateForWorkflowRebuild(client, baseUrl, formId, meta, o.styleTemplate);
|
|
2303
2376
|
// 保留字段分组:getConfig/initLayout 带 groupFieldIds,否则 Collapse 折叠被冲掉
|
|
2304
2377
|
const groupIds = await fetchFormGroups(client, baseUrl, formId);
|
|
2305
2378
|
// 读当前布局 configs(含明细 children + Collapse 分组)
|
|
@@ -2349,8 +2422,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2349
2422
|
apply(o.editable, (c) => { c.readOnly = false; c.disableEdit = false; }, '可编辑');
|
|
2350
2423
|
apply(o.singleRow, (c) => { c.singleRow = true; }, '独占一行');
|
|
2351
2424
|
// 落单/孤字段占满行(对齐 eb 表):奇数个最后一个 + 被 singleRow 挤落单的前一字段自动 singleRow
|
|
2352
|
-
const finalConfigs = applyLoneSingleRows(configs);
|
|
2353
|
-
const styleTemplateId = meta.layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008';
|
|
2425
|
+
const finalConfigs = applyLoneSingleRows(meta.layoutType === 'EXCEL' ? withoutCollapseContainers(configs) : configs);
|
|
2354
2426
|
const initRes = await client.post(`${baseUrl}${ROUTE}/view/relate/initLayout`, {
|
|
2355
2427
|
formId, module: MODULE, apiModule: 'workflow/form', layoutId: meta.layoutId,
|
|
2356
2428
|
generateCollapse: true, styleTemplateId, styleTemplateType: 1,
|
|
@@ -2362,10 +2434,10 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2362
2434
|
}, ebb);
|
|
2363
2435
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
2364
2436
|
throw new Error(`initLayout 失败: ${initRes?.msg}`);
|
|
2365
|
-
const
|
|
2437
|
+
const compCount = await verifyWorkflowRebuild(client, baseUrl, formId, styleTemplateId);
|
|
2366
2438
|
console.log(opts.json
|
|
2367
|
-
? JSON.stringify({ success: true, formId, layoutType: meta.layoutType, comps:
|
|
2368
|
-
: `字段属性已保存: 布局 ${
|
|
2439
|
+
? JSON.stringify({ success: true, formId, layoutType: meta.layoutType, comps: compCount }, null, 2)
|
|
2440
|
+
: `字段属性已保存: 布局 ${compCount} 组件`);
|
|
2369
2441
|
}
|
|
2370
2442
|
catch (e) {
|
|
2371
2443
|
console.error(`设置字段属性失败: ${e.message}`);
|