weaver-e10-builder 1.5.2 → 1.5.4
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/assets/org-employee-template.xlsx +0 -0
- package/dist/commands/form-add-detail-table.js +3 -3
- package/dist/commands/form-add-detail-table.js.map +1 -1
- package/dist/commands/form-add-physical-field.d.ts.map +1 -1
- package/dist/commands/form-add-physical-field.js +3 -2
- package/dist/commands/form-add-physical-field.js.map +1 -1
- package/dist/commands/form-data.d.ts.map +1 -1
- package/dist/commands/form-data.js +125 -0
- package/dist/commands/form-data.js.map +1 -1
- package/dist/commands/form-ebuilder-columns.d.ts.map +1 -1
- package/dist/commands/form-ebuilder-columns.js +3 -3
- package/dist/commands/form-ebuilder-columns.js.map +1 -1
- package/dist/commands/form-ebuilder-scope.d.ts.map +1 -1
- package/dist/commands/form-ebuilder-scope.js +3 -4
- package/dist/commands/form-ebuilder-scope.js.map +1 -1
- package/dist/commands/form-field-lang.d.ts.map +1 -1
- package/dist/commands/form-field-lang.js +3 -4
- package/dist/commands/form-field-lang.js.map +1 -1
- package/dist/commands/form-field-linkage.d.ts.map +1 -1
- package/dist/commands/form-field-linkage.js +4 -3
- package/dist/commands/form-field-linkage.js.map +1 -1
- package/dist/commands/form-formula-linkage.d.ts.map +1 -1
- package/dist/commands/form-formula-linkage.js +4 -2
- package/dist/commands/form-formula-linkage.js.map +1 -1
- package/dist/commands/form-formula.d.ts.map +1 -1
- package/dist/commands/form-formula.js +5 -5
- package/dist/commands/form-formula.js.map +1 -1
- package/dist/commands/form-layout.d.ts.map +1 -1
- package/dist/commands/form-layout.js +6 -0
- package/dist/commands/form-layout.js.map +1 -1
- package/dist/commands/form-list-click.d.ts.map +1 -1
- package/dist/commands/form-list-click.js +3 -2
- package/dist/commands/form-list-click.js.map +1 -1
- package/dist/commands/form-physical-table.js +3 -3
- package/dist/commands/form-physical-table.js.map +1 -1
- package/dist/commands/form-relate.d.ts.map +1 -1
- package/dist/commands/form-relate.js +3 -2
- package/dist/commands/form-relate.js.map +1 -1
- package/dist/commands/form-validate.d.ts.map +1 -1
- package/dist/commands/form-validate.js +3 -3
- package/dist/commands/form-validate.js.map +1 -1
- package/dist/commands/form-view.d.ts.map +1 -1
- package/dist/commands/form-view.js +2 -0
- package/dist/commands/form-view.js.map +1 -1
- package/dist/commands/form.d.ts +9 -3
- package/dist/commands/form.d.ts.map +1 -1
- package/dist/commands/form.js +116 -160
- package/dist/commands/form.js.map +1 -1
- package/dist/commands/menu-permission.d.ts.map +1 -1
- package/dist/commands/menu-permission.js +5 -2
- package/dist/commands/menu-permission.js.map +1 -1
- package/dist/commands/report.d.ts +9 -0
- package/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +18 -2
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/special.d.ts +24 -0
- package/dist/commands/special.d.ts.map +1 -0
- package/dist/commands/special.js +487 -0
- package/dist/commands/special.js.map +1 -0
- package/dist/commands/wf-form.d.ts.map +1 -1
- package/dist/commands/wf-form.js +4 -4
- package/dist/commands/wf-form.js.map +1 -1
- package/dist/commands/workflow-message.d.ts.map +1 -1
- package/dist/commands/workflow-message.js +1 -2
- package/dist/commands/workflow-message.js.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.js +54 -12
- package/dist/services/actionflow/components/action_eb_update_compiler.js.map +1 -1
- package/dist/services/actionflow/components/index.d.ts.map +1 -1
- package/dist/services/actionflow/components/index.js +6 -0
- package/dist/services/actionflow/components/index.js.map +1 -1
- package/dist/services/actionflow/components/multiple_execution.d.ts.map +1 -1
- package/dist/services/actionflow/components/multiple_execution.js +73 -13
- package/dist/services/actionflow/components/multiple_execution.js.map +1 -1
- package/dist/services/actionflow/components/output.d.ts.map +1 -1
- package/dist/services/actionflow/components/output.js +144 -5
- package/dist/services/actionflow/components/output.js.map +1 -1
- package/dist/services/actionflow/components/send_message.d.ts.map +1 -1
- package/dist/services/actionflow/components/send_message.js +60 -32
- package/dist/services/actionflow/components/send_message.js.map +1 -1
- package/dist/services/actionflow/components/serverless_action.d.ts +5 -0
- package/dist/services/actionflow/components/serverless_action.d.ts.map +1 -0
- package/dist/services/actionflow/components/serverless_action.js +134 -0
- package/dist/services/actionflow/components/serverless_action.js.map +1 -0
- package/dist/services/actionflow/components/webhook_trigger.d.ts +5 -0
- package/dist/services/actionflow/components/webhook_trigger.d.ts.map +1 -0
- package/dist/services/actionflow/components/webhook_trigger.js +85 -0
- package/dist/services/actionflow/components/webhook_trigger.js.map +1 -0
- package/dist/services/actionflow/context_preflight.d.ts +6 -0
- package/dist/services/actionflow/context_preflight.d.ts.map +1 -1
- package/dist/services/actionflow/context_preflight.js +247 -7
- package/dist/services/actionflow/context_preflight.js.map +1 -1
- package/dist/services/actionflow/context_provider.d.ts.map +1 -1
- package/dist/services/actionflow/context_provider.js +67 -3
- package/dist/services/actionflow/context_provider.js.map +1 -1
- package/dist/services/actionflow/custom_trigger_context.d.ts.map +1 -1
- package/dist/services/actionflow/custom_trigger_context.js +9 -2
- package/dist/services/actionflow/custom_trigger_context.js.map +1 -1
- package/dist/services/actionflow/formula_service.d.ts +2 -0
- package/dist/services/actionflow/formula_service.d.ts.map +1 -1
- package/dist/services/actionflow/formula_service.js +381 -63
- package/dist/services/actionflow/formula_service.js.map +1 -1
- package/dist/services/actionflow/generation_service.d.ts.map +1 -1
- package/dist/services/actionflow/generation_service.js +9 -0
- package/dist/services/actionflow/generation_service.js.map +1 -1
- package/dist/services/actionflow/param_group_dto.d.ts +5 -0
- package/dist/services/actionflow/param_group_dto.d.ts.map +1 -0
- package/dist/services/actionflow/param_group_dto.js +181 -0
- package/dist/services/actionflow/param_group_dto.js.map +1 -0
- package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
- package/dist/services/actionflow/preflight_service.js +53 -11
- package/dist/services/actionflow/preflight_service.js.map +1 -1
- package/dist/services/actionflow/readback_verifier.d.ts.map +1 -1
- package/dist/services/actionflow/readback_verifier.js +14 -1
- package/dist/services/actionflow/readback_verifier.js.map +1 -1
- package/dist/services/actionflow/update_service.d.ts.map +1 -1
- package/dist/services/actionflow/update_service.js +14 -8
- package/dist/services/actionflow/update_service.js.map +1 -1
- package/dist/services/actionflow/webhook_source.d.ts +4 -0
- package/dist/services/actionflow/webhook_source.d.ts.map +1 -0
- package/dist/services/actionflow/webhook_source.js +99 -0
- package/dist/services/actionflow/webhook_source.js.map +1 -0
- package/dist/services/actionflow/workflow_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/workflow_compiler.js +1 -0
- package/dist/services/actionflow/workflow_compiler.js.map +1 -1
- package/dist/services/form-create.d.ts +45 -2
- package/dist/services/form-create.d.ts.map +1 -1
- package/dist/services/form-create.js +78 -8
- package/dist/services/form-create.js.map +1 -1
- package/dist/services/form-data-openapi.d.ts +142 -0
- package/dist/services/form-data-openapi.d.ts.map +1 -0
- package/dist/services/form-data-openapi.js +363 -0
- package/dist/services/form-data-openapi.js.map +1 -0
- package/dist/services/form-field-build.d.ts.map +1 -1
- package/dist/services/form-field-build.js +4 -4
- package/dist/services/form-field-build.js.map +1 -1
- package/dist/services/form-field-template.d.ts +71 -0
- package/dist/services/form-field-template.d.ts.map +1 -0
- package/dist/services/form-field-template.js +103 -0
- package/dist/services/form-field-template.js.map +1 -0
- package/dist/services/form-field-validate.d.ts +26 -0
- package/dist/services/form-field-validate.d.ts.map +1 -0
- package/dist/services/form-field-validate.js +121 -0
- package/dist/services/form-field-validate.js.map +1 -0
- package/dist/services/form-id.d.ts +50 -0
- package/dist/services/form-id.d.ts.map +1 -0
- package/dist/services/form-id.js +110 -0
- package/dist/services/form-id.js.map +1 -0
- package/dist/services/form-layout-grid.d.ts +123 -0
- package/dist/services/form-layout-grid.d.ts.map +1 -0
- package/dist/services/form-layout-grid.js +177 -0
- package/dist/services/form-layout-grid.js.map +1 -0
- package/dist/services/form-layout-insert.d.ts +24 -1
- package/dist/services/form-layout-insert.d.ts.map +1 -1
- package/dist/services/form-layout-insert.js +192 -27
- package/dist/services/form-layout-insert.js.map +1 -1
- package/dist/services/form-physical-table.d.ts +1 -1
- package/dist/services/form-physical-table.js +1 -1
- package/dist/services/form-table-view.d.ts.map +1 -1
- package/dist/services/form-table-view.js +2 -11
- package/dist/services/form-table-view.js.map +1 -1
- package/dist/services/form-view.d.ts +2 -0
- package/dist/services/form-view.d.ts.map +1 -1
- package/dist/services/form-view.js +57 -7
- package/dist/services/form-view.js.map +1 -1
- package/dist/services/form-virtual.d.ts.map +1 -1
- package/dist/services/form-virtual.js +6 -1
- package/dist/services/form-virtual.js.map +1 -1
- package/dist/services/special-page.d.ts +85 -0
- package/dist/services/special-page.d.ts.map +1 -0
- package/dist/services/special-page.js +129 -0
- package/dist/services/special-page.js.map +1 -0
- package/dist/services/special-route.d.ts +92 -0
- package/dist/services/special-route.d.ts.map +1 -0
- package/dist/services/special-route.js +93 -0
- package/dist/services/special-route.js.map +1 -0
- package/dist/services/workflow-node-layout.d.ts +13 -1
- package/dist/services/workflow-node-layout.d.ts.map +1 -1
- package/dist/services/workflow-node-layout.js +11 -3
- package/dist/services/workflow-node-layout.js.map +1 -1
- package/package.json +1 -1
- package/skill-docs/SKILL.md +5 -5
- package/skill-docs/actionflows/SKILL.md +5 -4
- package/skill-docs/actionflows/references/components/logic/MultipleExecution.md +38 -38
- package/skill-docs/actionflows/references/components/logic/Output.md +9 -2
- package/skill-docs/actionflows/references/components/message/SendMessage.md +3 -3
- package/skill-docs/actionflows/references/components/serverless/ServerlessAction.md +42 -0
- package/skill-docs/actionflows/references/components/trigger/WebHookTrigger.md +89 -0
- package/skill-docs/actionflows/references/dynamic_capability_matrix.md +2 -2
- package/skill-docs/references/common/ref-cli-commands.md +3 -1
- package/skill-docs/references/form/guide-form-data.md +30 -0
- package/skill-docs/references/form/guide-form-layout-incremental.md +18 -3
- package/skill-docs/references/form/guide-form-physical-table.md +1 -1
- package/skill-docs/references/form/ref-form-fields.md +1 -1
- package/skill-docs/references/hrm/guide-org-employee.md +32 -1
package/dist/commands/form.js
CHANGED
|
@@ -2,95 +2,34 @@ import { writeFileSync, existsSync, readFileSync } from 'fs';
|
|
|
2
2
|
import { AuthSession } from '../core/auth.js';
|
|
3
3
|
import { ApiClient } from '../core/client.js';
|
|
4
4
|
import { toColumnName, toTableName, resolveFieldKeys } from '../utils/column-name.js';
|
|
5
|
-
import { createCustomPhysicalForm,
|
|
6
|
-
import {
|
|
7
|
-
import { RICH_TYPE_MAP, getRichType, richIdUnits, BROWSER_KINDS } from '../services/rich-types.js';
|
|
5
|
+
import { createCustomPhysicalForm, applyInitialFieldsToNewForm, placeholderFromFormat, reapplyGroupLayout, queryFormStorageSetting } from '../services/form-create.js';
|
|
6
|
+
import { getRichType, richIdUnits, BROWSER_KINDS } from '../services/rich-types.js';
|
|
8
7
|
import { dropFieldComponents, prepareLayoutForSave } from '../services/form-field-drop.js';
|
|
9
8
|
import { describeEditBaseFailure, resolveEditBase as resolveEditBasePure } from '../services/form-edit-base.js';
|
|
10
9
|
import { applyFieldPatches, platformFieldShape } from '../services/form-field-patch.js';
|
|
11
10
|
import { ensureDisplayColumns } from '../services/form-ebuilder-columns.js';
|
|
12
|
-
import { insertFieldIntoLayout, patchFieldLayout } from '../services/form-layout-insert.js';
|
|
11
|
+
import { insertFieldIntoLayout, patchFieldLayout, NO_FIELD_TYPE_TEMPLATE } from '../services/form-layout-insert.js';
|
|
12
|
+
import { fetchFieldTypeTemplates, findTemplateByType } from '../services/form-field-template.js';
|
|
13
13
|
import { buildLinkageAddPayload, addLinkage, resolveEffect, readLinkageConfig } from '../services/form-linkage-condition.js';
|
|
14
14
|
// 字段 jsonObj 的构造器(含 SYSTEM_FIELD_IDS / defaultEBuilderDataTitle)——
|
|
15
15
|
// 原先内联在下面 add-field 的 action 里,为了给「按物理表加字段」第二个入口复用而抽出去。
|
|
16
16
|
// 本文件仍有别处用这两个符号,所以在这里回导。
|
|
17
17
|
import { SYSTEM_FIELD_IDS, defaultEBuilderDataTitle, buildFieldJsonObject } from '../services/form-field-build.js';
|
|
18
|
+
// objId → 表单记录/formId。obj/getList 不含三方表单(专项应用),所以内部带了 getInfoById 兜底。
|
|
19
|
+
import { resolveFormRecord, resolveFormId, appendThirdPartyForms, resolveObjIdByFormId } from '../services/form-id.js';
|
|
20
|
+
// 字段类型归一 / 校验:与「专项建表」共用同一份(原为本文件内联)。
|
|
21
|
+
import { FIELD_TYPE_CHOICES, canonComponentKey, assertFieldType, normalizeFieldDef } from '../services/form-field-validate.js';
|
|
18
22
|
import { listFormTables, readFieldRecords, mapFieldsToTables } from '../services/form-physical-table.js';
|
|
19
23
|
import { buildFormulaParameters, defaultReturnType } from '../services/formula-detail.js';
|
|
20
24
|
import { registerOptionTemplateCommand } from './form-option-template.js';
|
|
21
25
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
const CK_CANON = {
|
|
28
|
-
textarea: 'TextArea', ebuilder: 'EBuilder', datetime: 'DateTime',
|
|
29
|
-
idcard: 'IDCard', mobile: 'Mobile', email: 'Email', phone: 'Phone',
|
|
30
|
-
employee: 'Employee', department: 'Department', subcompany: 'SubCompany', location: 'Location',
|
|
31
|
-
switch: 'Switch', select: 'Select', checkbox: 'CheckBox', radiobox: 'RadioBox',
|
|
32
|
-
money: 'Money', number: 'Number', date: 'Date', text: 'Text',
|
|
33
|
-
daterange: 'DateRange', detailtable: 'DetailTable', city: 'City',
|
|
34
|
-
};
|
|
35
|
-
function canonComponentKey(ck) {
|
|
36
|
-
return CK_CANON[String(ck).toLowerCase()] || ck;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* 代码里另有分支/别名、不在 CK_CANON 与 RICH_TYPE_MAP 两处的字段类型。
|
|
40
|
-
* **宁宽勿窄**:多列一个只是照旧送服务器,漏一个会把合法类型误杀,所以这里尽量收全。
|
|
41
|
-
* 新增字段类型时记得同步。
|
|
42
|
-
*/
|
|
43
|
-
const EXTRA_FIELD_TYPES = [
|
|
44
|
-
'Flow', 'SelectMultiple', 'DateInterval', 'ColorPicker', 'DataTable',
|
|
45
|
-
'DocFolder', 'DocFloder', 'Fold', 'Placeholder', 'Sharer', 'FileComponent',
|
|
46
|
-
'EbuilderAppTag', 'Attachment', 'Image', 'Signature', 'RichText', 'RelateBrowser',
|
|
47
|
-
// EInvoice 电子发票:下方 add-field 有专属构建分支(isSingle/invoiceType),此前漏登记 →
|
|
48
|
-
// 被 assertFieldType 挡成死代码。AudioRecord/VideoRecord 语音视频:极简 jsonObj,平台原样透传
|
|
49
|
-
// (见 rich-types.ts 的说明),无需富组件模板。
|
|
50
|
-
'EInvoice', 'AudioRecord', 'VideoRecord',
|
|
51
|
-
];
|
|
52
|
-
/** 可用的字段类型 = 基础组件(CK_CANON 的值)∪ 富组件(RICH_TYPE_MAP 的键)∪ 上述补充。
|
|
53
|
-
* 导出仅为让测试能盯住"平台支持的合法类型不许漏登记"(漏了会被 assertFieldType 误杀)。 */
|
|
54
|
-
export const FIELD_TYPE_CHOICES = [...new Set([
|
|
55
|
-
...Object.values(CK_CANON),
|
|
56
|
-
...Object.keys(RICH_TYPE_MAP),
|
|
57
|
-
...EXTRA_FIELD_TYPES,
|
|
58
|
-
])].sort();
|
|
59
|
-
/**
|
|
60
|
-
* 校验字段类型名。不校验的话错类型会**直送服务器**,换回一段
|
|
61
|
-
* `Cannot invoke "ComponentType.name()" because ... getComponentKey() is null`——
|
|
62
|
-
* 既看不出哪错了,也看不出该填什么。这里先拦下来并列出可选值。
|
|
63
|
-
*/
|
|
64
|
-
function assertFieldType(fieldType, where = '') {
|
|
65
|
-
if (FIELD_TYPE_CHOICES.includes(fieldType))
|
|
66
|
-
return;
|
|
67
|
-
console.error(`${where}不支持的字段类型: ${fieldType}`);
|
|
68
|
-
console.error(` 可选: ${FIELD_TYPE_CHOICES.join(' / ')}`);
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* 校验选项定义。**键名必须是 `name` / `valueKey`**——写成 `{value,label}` 这类
|
|
73
|
-
* 不会被拦下,而是静默存成「没有名字的选项」(平台侧 fieldOptionName 为空),
|
|
74
|
-
* 之后 `form data add` 按选项名写数据会直接失效,且读回也看不出哪里错了。
|
|
26
|
+
* 字段类型归一 / 校验 / 校验清单已抽到 `services/form-field-validate.ts` ——
|
|
27
|
+
* 「标准建表」与「专项建表」两个入口共用同一份,避免两处真相。
|
|
28
|
+
*
|
|
29
|
+
* `FIELD_TYPE_CHOICES` 在这里**原样 re-export**:
|
|
30
|
+
* `form-add-physical-field.ts` 与 `test/form-field-types.test.ts` 仍从本模块取它。
|
|
75
31
|
*/
|
|
76
|
-
|
|
77
|
-
options.forEach((o, i) => {
|
|
78
|
-
if (typeof o === 'string')
|
|
79
|
-
return; // 字符串简写,归一化时会补成 {name}
|
|
80
|
-
const where = `字段「${fieldName}」第 ${i + 1} 个选项`;
|
|
81
|
-
if (typeof o?.name !== 'string' || !o.name.trim()) {
|
|
82
|
-
const got = o && typeof o === 'object' ? Object.keys(o).join(' / ') : String(o);
|
|
83
|
-
console.error(`${where}缺少 name(收到键:${got || '(无)'})`);
|
|
84
|
-
console.error(' 正确写法: {"name":"待入职","valueKey":"1"}(valueKey 省略则由平台生成)');
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
const vk = o.valueKey;
|
|
88
|
-
if (vk !== undefined && vk !== null && String(vk) !== '' && !/^\d+$/.test(String(vk))) {
|
|
89
|
-
console.error(`${where}的 valueKey「${vk}」必须是数字(平台规范,下游按数字引用)`);
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
32
|
+
export { FIELD_TYPE_CHOICES };
|
|
94
33
|
/** 系统字段的中文名 → 物理字段 id(form read 实测的平台自带字段)。建表时字段与此完全重名 → 跳过新建、直接复用系统字段。 */
|
|
95
34
|
const SYSTEM_FIELD_NAME_TO_ID = {
|
|
96
35
|
'标题': 'name',
|
|
@@ -139,11 +78,21 @@ async function peekViaGetFields(client, baseUrl, objId, fieldId, auth) {
|
|
|
139
78
|
* 单独抽出来是为了让「读不到 → 中止」这条路清晰:**失败要能被调用方看见**,
|
|
140
79
|
* 不能吞掉之后改走别的接口重建一个定义。
|
|
141
80
|
*/
|
|
142
|
-
|
|
81
|
+
/**
|
|
82
|
+
* 读表单的字段记录。
|
|
83
|
+
*
|
|
84
|
+
* ⚠ **主表与明细表是两套结果,不带 `subFormId` 时只返主表字段。**
|
|
85
|
+
* 明细字段必须显式带 `subFormId` 才查得到 —— 少了这个参数,刚建好的明细字段会「查不到」,
|
|
86
|
+
* 表现为「字段已建立,但读回字段定义失败」。
|
|
87
|
+
*/
|
|
88
|
+
async function fetchFieldPageRecords(client, baseUrl, appId, formId, subFormId) {
|
|
143
89
|
const r = await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/getFormFieldPage?apid=${appId}`, {
|
|
144
90
|
pageNo: 1, pageSize: 500, module: 'ebuilderform',
|
|
145
91
|
customParam: { appId },
|
|
146
|
-
formFieldSearchEntity: {
|
|
92
|
+
formFieldSearchEntity: {
|
|
93
|
+
isDelete: 0, status: 'enable', formId,
|
|
94
|
+
...(subFormId ? { subFormId: String(subFormId) } : {}),
|
|
95
|
+
},
|
|
147
96
|
}, { ebbusinessid: formId });
|
|
148
97
|
return r?.data?.pageDatas?.result || r?.data?.data?.records || r?.data?.data || [];
|
|
149
98
|
}
|
|
@@ -194,8 +143,7 @@ export function registerFormCommands(program) {
|
|
|
194
143
|
if (cmdOpts?.appId) {
|
|
195
144
|
try {
|
|
196
145
|
// Get formId from appId
|
|
197
|
-
const
|
|
198
|
-
const formInfo = (listData?.data || []).find((f) => f.id === objId);
|
|
146
|
+
const formInfo = await resolveFormRecord(client, baseUrl, cmdOpts.appId, objId);
|
|
199
147
|
formId = formInfo?.formId || '';
|
|
200
148
|
if (formId) {
|
|
201
149
|
// Fetch options for Select/RadioBox/CheckBox fields (skip system fields with string IDs)
|
|
@@ -342,6 +290,8 @@ export function registerFormCommands(program) {
|
|
|
342
290
|
process.exit(1);
|
|
343
291
|
}
|
|
344
292
|
const forms = data.data || [];
|
|
293
|
+
// obj/getList 不含三方表单(专项应用)—— 补上。标准应用没有三方表单,等于空转。
|
|
294
|
+
await appendThirdPartyForms(client, baseUrl, appId, forms);
|
|
345
295
|
if (cmdOpts?.out) {
|
|
346
296
|
writeFileSync(cmdOpts.out, JSON.stringify(forms, null, 2), 'utf-8');
|
|
347
297
|
console.error(`已写入: ${cmdOpts.out}`);
|
|
@@ -405,22 +355,8 @@ export function registerFormCommands(program) {
|
|
|
405
355
|
// componentKey 大小写归一(canonComponentKey):用户/示例常写 "Textarea"/"Ebuilder" 等,
|
|
406
356
|
// 但 storageFieldType 与各 `=== 'TextArea'` 分支按 canonical 大小写匹配,不归一会导致 type 存成
|
|
407
357
|
// 小写 "Textarea"(FLOW 渲染异常)、TextArea 分支(content/maxLen)漏跑。
|
|
408
|
-
// 归一化 +
|
|
409
|
-
|
|
410
|
-
const out = { ...raw };
|
|
411
|
-
if (!out.componentKey && out.fieldType)
|
|
412
|
-
out.componentKey = out.fieldType;
|
|
413
|
-
if (out.componentKey)
|
|
414
|
-
out.componentKey = canonComponentKey(out.componentKey);
|
|
415
|
-
const label = out.fieldName || out.title || '(未命名)';
|
|
416
|
-
assertFieldType(out.componentKey || '', `字段「${label}」`);
|
|
417
|
-
if (Array.isArray(out.options) && !out.fieldOptions) {
|
|
418
|
-
out.fieldOptions = out.options.map((o) => typeof o === 'string' ? { name: o } : o);
|
|
419
|
-
}
|
|
420
|
-
if (Array.isArray(out.fieldOptions))
|
|
421
|
-
assertFieldOptions(label, out.fieldOptions);
|
|
422
|
-
return out;
|
|
423
|
-
};
|
|
358
|
+
// 归一化 + 就地校验(类型名/选项键名)见 services/form-field-validate.ts 的 normalizeFieldDef ——
|
|
359
|
+
// 顶层与明细子字段共用它,且与「专项建表」共用同一份实现。
|
|
424
360
|
fieldDefs = fieldDefs.map((f) => {
|
|
425
361
|
const out = normalizeFieldDef(f);
|
|
426
362
|
// DetailTable 子字段同样归一化:之前只转顶层,子表 Select 用 options 简写时
|
|
@@ -638,42 +574,10 @@ export function registerFormCommands(program) {
|
|
|
638
574
|
else {
|
|
639
575
|
console.error(` 数据库表名: ${result.tableName}`);
|
|
640
576
|
}
|
|
641
|
-
// Create fields and layout
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
hidden: f.hidden, formFields: f.formFields,
|
|
646
|
-
enableSubDetail: f.enableSubDetail, defaultExpandRow: f.defaultExpandRow,
|
|
647
|
-
subDetailConfig: f.subDetailConfig,
|
|
648
|
-
precision: f.precision, pointSize: f.pointSize,
|
|
649
|
-
percent: f.percent, defaultValue: f.defaultValue,
|
|
650
|
-
group: f.group, multiple: f.multiple,
|
|
651
|
-
singleRow: f.singleRow,
|
|
652
|
-
// 文本最大长度(Text 缺省 100、TextArea 缺省 4000)+ 日期精度 format(Date/DateTime)需透传,
|
|
653
|
-
// 否则 fields.json 标注的 maxLen/format 被丢(bug:长度默认 100 不生效、日期精度丢失)。
|
|
654
|
-
maxLen: f.maxLen, format: f.format,
|
|
655
|
-
// 字段编码 dataKey / 数据库列名 columnName —— 两者是两个东西,可分别指定。
|
|
656
|
-
// 这里是**白名单透传**,漏一项就会静默丢(maxLen/format 历史上就漏过)。
|
|
657
|
-
dataKey: f.dataKey, columnName: f.columnName,
|
|
658
|
-
}));
|
|
659
|
-
const fieldResult = await addInitialFieldsToCustomPhysicalForm(client, baseUrl, appId, objId, formId, fieldDefsForStandard, auth.tenantKey, layoutType, systemOverrides);
|
|
660
|
-
fieldGroups = fieldResult.fieldGroups || [];
|
|
661
|
-
console.error(` 字段+布局已写入: ${fieldDefsForStandard.length} 个字段`);
|
|
662
|
-
const detailTables = fieldResult.detailTables || [];
|
|
663
|
-
for (const dt of detailTables) {
|
|
664
|
-
console.error(` 明细表: ${dt.definition.fieldName} subFormId: ${dt.subFormId}`);
|
|
665
|
-
}
|
|
666
|
-
const subDetailService = new FormSubDetailService(client, baseUrl, appId, objId, formId);
|
|
667
|
-
for (const dt of detailTables) {
|
|
668
|
-
const def = dt.definition;
|
|
669
|
-
if (def.enableSubDetail && Array.isArray(def.subDetailConfig) && def.subDetailConfig.length > 0) {
|
|
670
|
-
await subDetailService.set(def.fieldName, def.subDetailConfig, Boolean(def.defaultExpandRow));
|
|
671
|
-
console.error(` 二级明细已配置: ${def.fieldName} → ${def.subDetailConfig.map((x) => x.subForm).join(', ')}`);
|
|
672
|
-
}
|
|
673
|
-
else if (def.enableSubDetail) {
|
|
674
|
-
throw new Error(`明细表 ${def.fieldName} 已声明 enableSubDetail,但 subDetailConfig 为空`);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
577
|
+
// Create fields and layout —— 白名单映射 + 明细/二级明细那一整步已抽到
|
|
578
|
+
// services/form-create.ts 的 applyInitialFieldsToNewForm,「专项建表」共用同一条链。
|
|
579
|
+
const fieldResult = await applyInitialFieldsToNewForm(client, baseUrl, appId, objId, formId, fieldDefs, { tenantKey: auth.tenantKey, layoutType, systemOverrides });
|
|
580
|
+
fieldGroups = fieldResult.fieldGroups;
|
|
677
581
|
}
|
|
678
582
|
catch (e) {
|
|
679
583
|
console.error(`创建失败: ${e.message}`);
|
|
@@ -717,8 +621,7 @@ export function registerFormCommands(program) {
|
|
|
717
621
|
let resolvedFormId = formId || '';
|
|
718
622
|
const resolveFormId = async () => {
|
|
719
623
|
if (!resolvedFormId) {
|
|
720
|
-
const
|
|
721
|
-
const formInfo = (formList?.data || []).find((f) => f.id === objId);
|
|
624
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
722
625
|
resolvedFormId = formInfo?.formId || '';
|
|
723
626
|
}
|
|
724
627
|
return resolvedFormId;
|
|
@@ -738,6 +641,8 @@ export function registerFormCommands(program) {
|
|
|
738
641
|
// Resolve target form names and field IDs from sformId
|
|
739
642
|
const formList = await client.get(`${baseUrl}/api/bs/ebuilder/form/obj/getList/${appId}?apid=${appId}`, { ebbusinessid: appId });
|
|
740
643
|
const allForms = formList?.data || [];
|
|
644
|
+
// 目标表可能是三方表单(专项应用),它不在 getList 里 —— 补上
|
|
645
|
+
await appendThirdPartyForms(client, baseUrl, appId, allForms);
|
|
741
646
|
const formNameById = new Map();
|
|
742
647
|
for (const fm of allForms) {
|
|
743
648
|
formNameById.set(fm.id, fm.formName || fm.name || fm.id);
|
|
@@ -772,8 +677,7 @@ export function registerFormCommands(program) {
|
|
|
772
677
|
};
|
|
773
678
|
await resolveFormId();
|
|
774
679
|
if (!resolvedFormId) {
|
|
775
|
-
const
|
|
776
|
-
const formInfo = (formList?.data || []).find((f) => f.id === objId);
|
|
680
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
777
681
|
resolvedFormId = formInfo?.formId || '';
|
|
778
682
|
}
|
|
779
683
|
// Use getFormFieldPage to get full field info including columnName
|
|
@@ -988,6 +892,8 @@ export function registerFormCommands(program) {
|
|
|
988
892
|
try {
|
|
989
893
|
const formList = await client.get(`${baseUrl}/api/bs/ebuilder/form/obj/getList/${appId}?apid=${appId}`, { ebbusinessid: appId });
|
|
990
894
|
allForms = formList?.data || [];
|
|
895
|
+
// 目标可能是三方表单(专项应用),它不在 getList 里 —— 补上
|
|
896
|
+
await appendThirdPartyForms(client, baseUrl, appId, allForms);
|
|
991
897
|
}
|
|
992
898
|
catch { /* 查不到则 formName 用 sformId */ }
|
|
993
899
|
// 读已建字段(拿 fieldId)
|
|
@@ -1879,8 +1785,7 @@ export function registerFormCommands(program) {
|
|
|
1879
1785
|
process.exit(1);
|
|
1880
1786
|
}
|
|
1881
1787
|
// Get formId from appId
|
|
1882
|
-
const
|
|
1883
|
-
const formInfo = (listData?.data || []).find((f) => f.id === objId);
|
|
1788
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
1884
1789
|
const formId = formInfo?.formId || '';
|
|
1885
1790
|
if (!formId) {
|
|
1886
1791
|
console.error('无法获取 formId,请确认 appId 和 objId 正确');
|
|
@@ -1925,8 +1830,7 @@ export function registerFormCommands(program) {
|
|
|
1925
1830
|
const client = new ApiClient(auth);
|
|
1926
1831
|
const baseUrl = auth.getBaseUrl();
|
|
1927
1832
|
// objId → formId
|
|
1928
|
-
const
|
|
1929
|
-
const formInfo = (listData?.data || []).find((f) => String(f.id) === String(objId));
|
|
1833
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
1930
1834
|
const formId = formInfo?.formId || '';
|
|
1931
1835
|
if (!formId) {
|
|
1932
1836
|
console.error('无法获取 formId,请确认 objId 正确');
|
|
@@ -1973,8 +1877,7 @@ export function registerFormCommands(program) {
|
|
|
1973
1877
|
const client = new ApiClient(auth);
|
|
1974
1878
|
const baseUrl = auth.getBaseUrl();
|
|
1975
1879
|
// Get formId
|
|
1976
|
-
const
|
|
1977
|
-
const formInfo = (formList?.data || []).find((f) => f.id === objId);
|
|
1880
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
1978
1881
|
const formId = formInfo?.formId || '';
|
|
1979
1882
|
const formTableId = formInfo?.formTableId || '';
|
|
1980
1883
|
if (!formId) {
|
|
@@ -2003,13 +1906,33 @@ export function registerFormCommands(program) {
|
|
|
2003
1906
|
console.error('--options 必须是非空数组');
|
|
2004
1907
|
process.exit(1);
|
|
2005
1908
|
}
|
|
2006
|
-
//
|
|
2007
|
-
|
|
1909
|
+
// 读**现状**(title / dataKey / type / labelObj …)—— 这是「读现状 → 改 → 写回」的底。
|
|
1910
|
+
//
|
|
1911
|
+
// ⚠ 这里**不许降级成 `{}`**。以前读失败只在 catch 里吞掉、`currentField` 变成空对象,
|
|
1912
|
+
// 于是 title 写成空串,平台回「字段标题不能为空」—— 报的是标题,真因是**读没成功**,
|
|
1913
|
+
// 用户怎么去补 title 都没用。宁可中止:拿不到现状就写,等于拿一份空对象覆盖整个字段。
|
|
1914
|
+
let currentField = null;
|
|
1915
|
+
let readErr = '';
|
|
2008
1916
|
try {
|
|
2009
1917
|
const fData = await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/getFormField`, { module: 'ebuilderform', formTableField: { formField: { id: fieldId, form: { id: formId } } } }, { ebbusinessid: formId });
|
|
2010
|
-
|
|
1918
|
+
if (fData?.code === 200 && fData?.status !== false && fData?.data)
|
|
1919
|
+
currentField = fData.data;
|
|
1920
|
+
else
|
|
1921
|
+
readErr = fData?.msg || `code=${fData?.code}`;
|
|
1922
|
+
}
|
|
1923
|
+
catch (e) {
|
|
1924
|
+
readErr = e.message;
|
|
1925
|
+
}
|
|
1926
|
+
if (!currentField || !Object.keys(currentField).length) {
|
|
1927
|
+
console.error(`读取字段现状失败(${readErr || '接口未返回字段'}),已中止、未改动任何东西。`);
|
|
1928
|
+
console.error(' 本命令是「读现状 → 改 → 写回」,读不到现状就写会把字段的其余属性清空。');
|
|
1929
|
+
process.exit(1);
|
|
1930
|
+
}
|
|
1931
|
+
if (!String(currentField.title ?? '').trim()) {
|
|
1932
|
+
console.error(`读回的字段没有 title(fieldId=${fieldId}),已中止、未改动任何东西。`);
|
|
1933
|
+
console.error(' 标题在平台里存的是多语言标签 id(labelObj.title);请先用 `form read` 确认这个字段的状态。');
|
|
1934
|
+
process.exit(1);
|
|
2011
1935
|
}
|
|
2012
|
-
catch { /* best effort */ }
|
|
2013
1936
|
// Build options with defOption
|
|
2014
1937
|
const { randomUUID } = await import('crypto');
|
|
2015
1938
|
// valueKey=用户自定义选项值,必须是纯数字(平台规范+下游引用按数字处理),非数字直接报错;
|
|
@@ -2061,7 +1984,7 @@ export function registerFormCommands(program) {
|
|
|
2061
1984
|
hideScore: true,
|
|
2062
1985
|
groupId: currentField.groupId || '-1',
|
|
2063
1986
|
hasDisplayFormat: currentField.hasDisplayFormat ?? false,
|
|
2064
|
-
title: currentField.title
|
|
1987
|
+
title: currentField.title,
|
|
2065
1988
|
dataCount: currentField.dataCount || 1,
|
|
2066
1989
|
dataKey: currentField.dataKey || '',
|
|
2067
1990
|
systemField: currentField.systemField ?? true,
|
|
@@ -2139,8 +2062,7 @@ export function registerFormCommands(program) {
|
|
|
2139
2062
|
const client = new ApiClient(auth);
|
|
2140
2063
|
const baseUrl = auth.getBaseUrl();
|
|
2141
2064
|
// Get formId from objId
|
|
2142
|
-
const
|
|
2143
|
-
const formInfo = (formList?.data || []).find((f) => f.id === objId);
|
|
2065
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
2144
2066
|
const formId = formInfo?.formId || '';
|
|
2145
2067
|
const formTableId = formInfo?.formTableId || '';
|
|
2146
2068
|
if (!formId) {
|
|
@@ -2208,11 +2130,13 @@ export function registerFormCommands(program) {
|
|
|
2208
2130
|
// 把错误讲清楚,让用户自己决定要不要 --reinit。
|
|
2209
2131
|
if (!cmdOpts.reinit) {
|
|
2210
2132
|
try {
|
|
2211
|
-
|
|
2133
|
+
// ⚠ 明细字段**必须带 subFormId** 才查得到(不带只返主表字段)——
|
|
2134
|
+
// 少了它,刚建好的明细字段会「查不到」,报成「读回字段定义失败」。
|
|
2135
|
+
const fieldDef = (await fetchFieldPageRecords(client, baseUrl, appId, formId, cmdOpts.subFormId))
|
|
2212
2136
|
.find((f) => String(f.fieldId) === String(fieldId));
|
|
2213
2137
|
if (!fieldDef)
|
|
2214
2138
|
throw new Error('字段已建立,但读回字段定义失败');
|
|
2215
|
-
const
|
|
2139
|
+
const insertArgs = {
|
|
2216
2140
|
fieldId, labelFieldId, title: title || fieldName, fieldDef,
|
|
2217
2141
|
subFormId: cmdOpts.subFormId,
|
|
2218
2142
|
// 对齐 initLayout 那条路对新字段的默认:可编辑、显示。
|
|
@@ -2222,12 +2146,38 @@ export function registerFormCommands(program) {
|
|
|
2222
2146
|
required: cmdOpts.required === true,
|
|
2223
2147
|
...(cmdOpts.singleRow === true ? { singleRow: true } : {}),
|
|
2224
2148
|
},
|
|
2225
|
-
}
|
|
2149
|
+
};
|
|
2150
|
+
let placed;
|
|
2151
|
+
try {
|
|
2152
|
+
placed = await insertFieldIntoLayout(client, baseUrl, formId, insertArgs);
|
|
2153
|
+
}
|
|
2154
|
+
catch (e) {
|
|
2155
|
+
// 本表还没有这个类型 → 去要一份**平台按该字段生成的模板**再试一次。
|
|
2156
|
+
// 只在真缺模板时才多打这一次接口,正常路径零开销。
|
|
2157
|
+
if (e?.code !== NO_FIELD_TYPE_TEMPLATE)
|
|
2158
|
+
throw e;
|
|
2159
|
+
const templates = await fetchFieldTypeTemplates(client, baseUrl, appId, formId);
|
|
2160
|
+
// 主表字段按 fieldId 命中;明细表字段拿不到(接口不返回明细),
|
|
2161
|
+
// 退而借**主表同类型**的那一份 —— 模板是按类型而不是按作用域的
|
|
2162
|
+
// (`config.flow` 是空对象、没有 `excel`),作用域由插入方自己写。
|
|
2163
|
+
const tpl = templates.get(String(fieldId))?.comp
|
|
2164
|
+
?? findTemplateByType(templates, String(fieldDef.componentKey ?? fieldType))?.comp;
|
|
2165
|
+
if (!tpl)
|
|
2166
|
+
throw e;
|
|
2167
|
+
console.error(' 本表还没有这个类型,改用平台给的字段模板合成组件...');
|
|
2168
|
+
placed = await insertFieldIntoLayout(client, baseUrl, formId, { ...insertArgs, fieldTypeTemplate: tpl });
|
|
2169
|
+
}
|
|
2226
2170
|
console.error(` 布局已更新: excel[${placed.row},${placed.col}](增量插入,未重建)`);
|
|
2171
|
+
// 网格补格这类「改成功了但不干净」的情况要让人看见,不能闷掉。
|
|
2172
|
+
for (const w of placed.warnings)
|
|
2173
|
+
console.error(` ⚠ ${w}`);
|
|
2227
2174
|
}
|
|
2228
2175
|
catch (e) {
|
|
2229
2176
|
console.error(` 布局更新失败: ${e.message}`);
|
|
2230
|
-
|
|
2177
|
+
// ⚠ 别写「重跑不会重复建字段」——字段已经建出来了,重跑这条命令会再次去建同一个
|
|
2178
|
+
// 字段,撞库列重名而失败。要说清是「先删掉再重跑」。
|
|
2179
|
+
console.error(' 字段本身已建立,但没进布局。要重试请先 `form delete-field` 删掉这个字段再跑,');
|
|
2180
|
+
console.error(' 或直接按上面那条修好布局(字段不用重建)。');
|
|
2231
2181
|
}
|
|
2232
2182
|
}
|
|
2233
2183
|
else {
|
|
@@ -2352,8 +2302,11 @@ export function registerFormCommands(program) {
|
|
|
2352
2302
|
// Get formId — try getList first, fall back to searching by fieldId
|
|
2353
2303
|
let formId = '';
|
|
2354
2304
|
let resolvedObjId = objId;
|
|
2305
|
+
// 这份列表下面还要再用一次(formId → objId 的反查),所以保留不动;
|
|
2306
|
+
// formInfo 走共用解析 —— obj/getList 命不中时按 id 直取,覆盖三方表单。
|
|
2355
2307
|
const formList = await client.get(`${baseUrl}/api/bs/ebuilder/form/obj/getList/${appId}?apid=${appId}`, { ebbusinessid: appId });
|
|
2356
|
-
const formInfo = (formList?.data || []).find((f) => String(f.id) === String(objId))
|
|
2308
|
+
const formInfo = (formList?.data || []).find((f) => String(f.id) === String(objId))
|
|
2309
|
+
|| await resolveFormRecord(client, baseUrl, appId, objId);
|
|
2357
2310
|
formId = formInfo?.formId || '';
|
|
2358
2311
|
// If not found in getList (e.g. workflow sub-table objId), search by fieldId
|
|
2359
2312
|
if (!formId) {
|
|
@@ -2370,6 +2323,12 @@ export function registerFormCommands(program) {
|
|
|
2370
2323
|
const matchForm = (formList?.data || []).find((f) => f.formId === formId);
|
|
2371
2324
|
if (matchForm)
|
|
2372
2325
|
resolvedObjId = matchForm.id;
|
|
2326
|
+
else {
|
|
2327
|
+
// 三方表单不在 getList 里 —— 按 formId 反查补一次
|
|
2328
|
+
const byFormId = await resolveObjIdByFormId(client, baseUrl, appId, formId);
|
|
2329
|
+
if (byFormId)
|
|
2330
|
+
resolvedObjId = byFormId;
|
|
2331
|
+
}
|
|
2373
2332
|
}
|
|
2374
2333
|
}
|
|
2375
2334
|
if (!formId) {
|
|
@@ -2586,8 +2545,7 @@ export function registerFormCommands(program) {
|
|
|
2586
2545
|
let formName = editOpts.formName || fallbackFormName || '';
|
|
2587
2546
|
if (!formName) {
|
|
2588
2547
|
try {
|
|
2589
|
-
const
|
|
2590
|
-
const tf = (tlist?.data || []).find((f) => String(f.id) === String(sformId));
|
|
2548
|
+
const tf = await resolveFormRecord(client, baseUrl, appId, sformId);
|
|
2591
2549
|
formName = tf?.formName || tf?.name || sformId;
|
|
2592
2550
|
}
|
|
2593
2551
|
catch {
|
|
@@ -2783,8 +2741,7 @@ export function registerFormCommands(program) {
|
|
|
2783
2741
|
process.exit(1);
|
|
2784
2742
|
const client = new ApiClient(auth);
|
|
2785
2743
|
const baseUrl = auth.getBaseUrl();
|
|
2786
|
-
const
|
|
2787
|
-
const formInfo = (formList?.data || []).find((f) => String(f.id) === String(objId));
|
|
2744
|
+
const formInfo = await resolveFormRecord(client, baseUrl, appId, objId);
|
|
2788
2745
|
const formId = formInfo?.formId || '';
|
|
2789
2746
|
if (!formId) {
|
|
2790
2747
|
console.error('无法获取 formId,请确认 objId 和 appId 正确');
|
|
@@ -2892,9 +2849,8 @@ export function registerFormCommands(program) {
|
|
|
2892
2849
|
// eb 表 layout/field-manage 接口认 formId(≠objId):从应用表单列表按 objId 解析 formId
|
|
2893
2850
|
let formId = '';
|
|
2894
2851
|
try {
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
formId = hit?.formId || '';
|
|
2852
|
+
// 原实现这条请求没带 ebbusinessid 头;走共用解析后会带上(与其余 12 处一致)。
|
|
2853
|
+
formId = await resolveFormId(client, baseUrl, appId, objId);
|
|
2898
2854
|
}
|
|
2899
2855
|
catch { /* 忽略,下面报错 */ }
|
|
2900
2856
|
if (!formId)
|