weaver-e10-builder 1.0.2-beta
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/README.md +200 -0
- package/dist/commands/app.d.ts +3 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +305 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +386 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +106 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/compile.d.ts +3 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +134 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/docx.d.ts +3 -0
- package/dist/commands/docx.d.ts.map +1 -0
- package/dist/commands/docx.js +54 -0
- package/dist/commands/docx.js.map +1 -0
- package/dist/commands/form-button.d.ts +3 -0
- package/dist/commands/form-button.d.ts.map +1 -0
- package/dist/commands/form-button.js +441 -0
- package/dist/commands/form-button.js.map +1 -0
- package/dist/commands/form-data.d.ts +3 -0
- package/dist/commands/form-data.d.ts.map +1 -0
- package/dist/commands/form-data.js +197 -0
- package/dist/commands/form-data.js.map +1 -0
- package/dist/commands/form-ebuilder-columns.d.ts +3 -0
- package/dist/commands/form-ebuilder-columns.d.ts.map +1 -0
- package/dist/commands/form-ebuilder-columns.js +118 -0
- package/dist/commands/form-ebuilder-columns.js.map +1 -0
- package/dist/commands/form-ebuilder-filter.d.ts +3 -0
- package/dist/commands/form-ebuilder-filter.d.ts.map +1 -0
- package/dist/commands/form-ebuilder-filter.js +135 -0
- package/dist/commands/form-ebuilder-filter.js.map +1 -0
- package/dist/commands/form-ebuilder-scope.d.ts +3 -0
- package/dist/commands/form-ebuilder-scope.d.ts.map +1 -0
- package/dist/commands/form-ebuilder-scope.js +321 -0
- package/dist/commands/form-ebuilder-scope.js.map +1 -0
- package/dist/commands/form-ebuilder-search.d.ts +3 -0
- package/dist/commands/form-ebuilder-search.d.ts.map +1 -0
- package/dist/commands/form-ebuilder-search.js +252 -0
- package/dist/commands/form-ebuilder-search.js.map +1 -0
- package/dist/commands/form-formula.d.ts +12 -0
- package/dist/commands/form-formula.d.ts.map +1 -0
- package/dist/commands/form-formula.js +252 -0
- package/dist/commands/form-formula.js.map +1 -0
- package/dist/commands/form-layout-init.d.ts +15 -0
- package/dist/commands/form-layout-init.d.ts.map +1 -0
- package/dist/commands/form-layout-init.js +162 -0
- package/dist/commands/form-layout-init.js.map +1 -0
- package/dist/commands/form-layout.d.ts +3 -0
- package/dist/commands/form-layout.d.ts.map +1 -0
- package/dist/commands/form-layout.js +236 -0
- package/dist/commands/form-layout.js.map +1 -0
- package/dist/commands/form-list-click.d.ts +3 -0
- package/dist/commands/form-list-click.d.ts.map +1 -0
- package/dist/commands/form-list-click.js +154 -0
- package/dist/commands/form-list-click.js.map +1 -0
- package/dist/commands/form-list-event.d.ts +3 -0
- package/dist/commands/form-list-event.d.ts.map +1 -0
- package/dist/commands/form-list-event.js +203 -0
- package/dist/commands/form-list-event.js.map +1 -0
- package/dist/commands/form-list-filter.d.ts +9 -0
- package/dist/commands/form-list-filter.d.ts.map +1 -0
- package/dist/commands/form-list-filter.js +107 -0
- package/dist/commands/form-list-filter.js.map +1 -0
- package/dist/commands/form-list-group.d.ts +11 -0
- package/dist/commands/form-list-group.d.ts.map +1 -0
- package/dist/commands/form-list-group.js +100 -0
- package/dist/commands/form-list-group.js.map +1 -0
- package/dist/commands/form-list-permission.d.ts +3 -0
- package/dist/commands/form-list-permission.d.ts.map +1 -0
- package/dist/commands/form-list-permission.js +127 -0
- package/dist/commands/form-list-permission.js.map +1 -0
- package/dist/commands/form-list-search-group.d.ts +3 -0
- package/dist/commands/form-list-search-group.d.ts.map +1 -0
- package/dist/commands/form-list-search-group.js +132 -0
- package/dist/commands/form-list-search-group.js.map +1 -0
- package/dist/commands/form-list-stats.d.ts +11 -0
- package/dist/commands/form-list-stats.d.ts.map +1 -0
- package/dist/commands/form-list-stats.js +139 -0
- package/dist/commands/form-list-stats.js.map +1 -0
- package/dist/commands/form-list-unit.d.ts +3 -0
- package/dist/commands/form-list-unit.d.ts.map +1 -0
- package/dist/commands/form-list-unit.js +95 -0
- package/dist/commands/form-list-unit.js.map +1 -0
- package/dist/commands/form-list-utils.d.ts +32 -0
- package/dist/commands/form-list-utils.d.ts.map +1 -0
- package/dist/commands/form-list-utils.js +76 -0
- package/dist/commands/form-list-utils.js.map +1 -0
- package/dist/commands/form-list.d.ts +3 -0
- package/dist/commands/form-list.d.ts.map +1 -0
- package/dist/commands/form-list.js +624 -0
- package/dist/commands/form-list.js.map +1 -0
- package/dist/commands/form-permission.d.ts +3 -0
- package/dist/commands/form-permission.d.ts.map +1 -0
- package/dist/commands/form-permission.js +193 -0
- package/dist/commands/form-permission.js.map +1 -0
- package/dist/commands/form-relate.d.ts +14 -0
- package/dist/commands/form-relate.d.ts.map +1 -0
- package/dist/commands/form-relate.js +140 -0
- package/dist/commands/form-relate.js.map +1 -0
- package/dist/commands/form-serial-mark.d.ts +18 -0
- package/dist/commands/form-serial-mark.d.ts.map +1 -0
- package/dist/commands/form-serial-mark.js +167 -0
- package/dist/commands/form-serial-mark.js.map +1 -0
- package/dist/commands/form-table-view.d.ts +3 -0
- package/dist/commands/form-table-view.d.ts.map +1 -0
- package/dist/commands/form-table-view.js +217 -0
- package/dist/commands/form-table-view.js.map +1 -0
- package/dist/commands/form-validate.d.ts +3 -0
- package/dist/commands/form-validate.d.ts.map +1 -0
- package/dist/commands/form-validate.js +122 -0
- package/dist/commands/form-validate.js.map +1 -0
- package/dist/commands/form-view-permission.d.ts +3 -0
- package/dist/commands/form-view-permission.d.ts.map +1 -0
- package/dist/commands/form-view-permission.js +86 -0
- package/dist/commands/form-view-permission.js.map +1 -0
- package/dist/commands/form-view.d.ts +3 -0
- package/dist/commands/form-view.d.ts.map +1 -0
- package/dist/commands/form-view.js +145 -0
- package/dist/commands/form-view.js.map +1 -0
- package/dist/commands/form.d.ts +3 -0
- package/dist/commands/form.d.ts.map +1 -0
- package/dist/commands/form.js +2467 -0
- package/dist/commands/form.js.map +1 -0
- package/dist/commands/icon.d.ts +3 -0
- package/dist/commands/icon.d.ts.map +1 -0
- package/dist/commands/icon.js +82 -0
- package/dist/commands/icon.js.map +1 -0
- package/dist/commands/matrix.d.ts +3 -0
- package/dist/commands/matrix.d.ts.map +1 -0
- package/dist/commands/matrix.js +587 -0
- package/dist/commands/matrix.js.map +1 -0
- package/dist/commands/menu-permission.d.ts +3 -0
- package/dist/commands/menu-permission.d.ts.map +1 -0
- package/dist/commands/menu-permission.js +188 -0
- package/dist/commands/menu-permission.js.map +1 -0
- package/dist/commands/menu.d.ts +16 -0
- package/dist/commands/menu.d.ts.map +1 -0
- package/dist/commands/menu.js +269 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +345 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/role.d.ts +3 -0
- package/dist/commands/role.d.ts.map +1 -0
- package/dist/commands/role.js +224 -0
- package/dist/commands/role.js.map +1 -0
- package/dist/commands/user.d.ts +3 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +49 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/commands/workflow-action.d.ts +3 -0
- package/dist/commands/workflow-action.d.ts.map +1 -0
- package/dist/commands/workflow-action.js +1821 -0
- package/dist/commands/workflow-action.js.map +1 -0
- package/dist/commands/workflow-advanced.d.ts +3 -0
- package/dist/commands/workflow-advanced.d.ts.map +1 -0
- package/dist/commands/workflow-advanced.js +290 -0
- package/dist/commands/workflow-advanced.js.map +1 -0
- package/dist/commands/workflow-condition.d.ts +7 -0
- package/dist/commands/workflow-condition.d.ts.map +1 -0
- package/dist/commands/workflow-condition.js +562 -0
- package/dist/commands/workflow-condition.js.map +1 -0
- package/dist/commands/workflow-message.d.ts +3 -0
- package/dist/commands/workflow-message.d.ts.map +1 -0
- package/dist/commands/workflow-message.js +399 -0
- package/dist/commands/workflow-message.js.map +1 -0
- package/dist/commands/workflow-node-overtime.d.ts +3 -0
- package/dist/commands/workflow-node-overtime.d.ts.map +1 -0
- package/dist/commands/workflow-node-overtime.js +150 -0
- package/dist/commands/workflow-node-overtime.js.map +1 -0
- package/dist/commands/workflow-node-reject.d.ts +3 -0
- package/dist/commands/workflow-node-reject.d.ts.map +1 -0
- package/dist/commands/workflow-node-reject.js +115 -0
- package/dist/commands/workflow-node-reject.js.map +1 -0
- package/dist/commands/workflow-node-sign.d.ts +15 -0
- package/dist/commands/workflow-node-sign.d.ts.map +1 -0
- package/dist/commands/workflow-node-sign.js +100 -0
- package/dist/commands/workflow-node-sign.js.map +1 -0
- package/dist/commands/workflow-node-validate.d.ts +16 -0
- package/dist/commands/workflow-node-validate.d.ts.map +1 -0
- package/dist/commands/workflow-node-validate.js +169 -0
- package/dist/commands/workflow-node-validate.js.map +1 -0
- package/dist/commands/workflow-node.d.ts +3 -0
- package/dist/commands/workflow-node.d.ts.map +1 -0
- package/dist/commands/workflow-node.js +347 -0
- package/dist/commands/workflow-node.js.map +1 -0
- package/dist/commands/workflow-numbering.d.ts +17 -0
- package/dist/commands/workflow-numbering.d.ts.map +1 -0
- package/dist/commands/workflow-numbering.js +191 -0
- package/dist/commands/workflow-numbering.js.map +1 -0
- package/dist/commands/workflow-plan-range.d.ts +3 -0
- package/dist/commands/workflow-plan-range.d.ts.map +1 -0
- package/dist/commands/workflow-plan-range.js +116 -0
- package/dist/commands/workflow-plan-range.js.map +1 -0
- package/dist/commands/workflow-setting.d.ts +3 -0
- package/dist/commands/workflow-setting.d.ts.map +1 -0
- package/dist/commands/workflow-setting.js +440 -0
- package/dist/commands/workflow-setting.js.map +1 -0
- package/dist/commands/workflow-title.d.ts +14 -0
- package/dist/commands/workflow-title.d.ts.map +1 -0
- package/dist/commands/workflow-title.js +106 -0
- package/dist/commands/workflow-title.js.map +1 -0
- package/dist/commands/workflow.d.ts +26 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +2359 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/core/auth.d.ts +36 -0
- package/dist/core/auth.d.ts.map +1 -0
- package/dist/core/auth.js +351 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/client.d.ts +27 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +100 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/crypto.d.ts +11 -0
- package/dist/core/crypto.d.ts.map +1 -0
- package/dist/core/crypto.js +102 -0
- package/dist/core/crypto.js.map +1 -0
- package/dist/core/edition.d.ts +4 -0
- package/dist/core/edition.d.ts.map +1 -0
- package/dist/core/edition.js +19 -0
- package/dist/core/edition.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/services/action-detail.d.ts +112 -0
- package/dist/services/action-detail.d.ts.map +1 -0
- package/dist/services/action-detail.js +443 -0
- package/dist/services/action-detail.js.map +1 -0
- package/dist/services/condition-rules.d.ts +45 -0
- package/dist/services/condition-rules.d.ts.map +1 -0
- package/dist/services/condition-rules.js +207 -0
- package/dist/services/condition-rules.js.map +1 -0
- package/dist/services/form-create.d.ts +102 -0
- package/dist/services/form-create.d.ts.map +1 -0
- package/dist/services/form-create.js +835 -0
- package/dist/services/form-create.js.map +1 -0
- package/dist/services/form-ebuilder-filter.d.ts +60 -0
- package/dist/services/form-ebuilder-filter.d.ts.map +1 -0
- package/dist/services/form-ebuilder-filter.js +562 -0
- package/dist/services/form-ebuilder-filter.js.map +1 -0
- package/dist/services/form-table-view.d.ts +117 -0
- package/dist/services/form-table-view.d.ts.map +1 -0
- package/dist/services/form-table-view.js +882 -0
- package/dist/services/form-table-view.js.map +1 -0
- package/dist/services/form-view-permission.d.ts +30 -0
- package/dist/services/form-view-permission.d.ts.map +1 -0
- package/dist/services/form-view-permission.js +208 -0
- package/dist/services/form-view-permission.js.map +1 -0
- package/dist/services/form-view.d.ts +41 -0
- package/dist/services/form-view.d.ts.map +1 -0
- package/dist/services/form-view.js +334 -0
- package/dist/services/form-view.js.map +1 -0
- package/dist/services/formula-detail.d.ts +31 -0
- package/dist/services/formula-detail.d.ts.map +1 -0
- package/dist/services/formula-detail.js +66 -0
- package/dist/services/formula-detail.js.map +1 -0
- package/dist/services/rich-types.d.ts +35 -0
- package/dist/services/rich-types.d.ts.map +1 -0
- package/dist/services/rich-types.js +105 -0
- package/dist/services/rich-types.js.map +1 -0
- package/dist/services/workflow-layout.d.ts +118 -0
- package/dist/services/workflow-layout.d.ts.map +1 -0
- package/dist/services/workflow-layout.js +279 -0
- package/dist/services/workflow-layout.js.map +1 -0
- package/dist/services/workflow-operator.d.ts +36 -0
- package/dist/services/workflow-operator.d.ts.map +1 -0
- package/dist/services/workflow-operator.js +65 -0
- package/dist/services/workflow-operator.js.map +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/column-name.d.ts +13 -0
- package/dist/utils/column-name.d.ts.map +1 -0
- package/dist/utils/column-name.js +45 -0
- package/dist/utils/column-name.js.map +1 -0
- package/ecodecmd/package.json +27 -0
- package/ecodecmd/src/build.js +709 -0
- package/ecodecmd/src/compile.js +81 -0
- package/ecodecmd/src/index.js +48 -0
- package/ecodecmd/src/init.js +73 -0
- package/ecodecmd/src/lib/@babel/plugin-proposal-object-rest-spread@7.5.5/index.js +1795 -0
- package/ecodecmd/src/lib/@babel/plugin-proposal-optional-chaining@7.6.0/index.js +135 -0
- package/ecodecmd/src/lib/@babel/preset-env-standalone@7.5.5/babel-preset-env.js +76043 -0
- package/ecodecmd/src/lib/@babel/standalone@7.5.5/babel.js +90802 -0
- package/ecodecmd/src/lib/exec.js +77 -0
- package/ecodecmd/src/loaddep.js +154 -0
- package/ecodecmd/src/util/compress.js +58 -0
- package/ecodecmd/src/util/crypto-util.js +19 -0
- package/ecodecmd/src/util/index.js +153 -0
- package/ecodecmd/src/util/snowflake.js +144 -0
- package/package.json +43 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
import { toColumnName, pinyinInitials, toSubTableName } from '../utils/column-name.js';
|
|
2
|
+
import { getRichType, richIdUnits } from './rich-types.js';
|
|
3
|
+
export const PHYSICAL_TABLE_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
4
|
+
/** 日期格式 → 占位中文(yyyy-MM-dd HH:mm → 年-月-日 时:分) */
|
|
5
|
+
export function placeholderFromFormat(format) {
|
|
6
|
+
if (!format)
|
|
7
|
+
return '';
|
|
8
|
+
return format
|
|
9
|
+
.replace(/yyyy/g, '年')
|
|
10
|
+
.replace(/MM/g, '月')
|
|
11
|
+
.replace(/dd/g, '日')
|
|
12
|
+
.replace(/HH/g, '时')
|
|
13
|
+
.replace(/mm/g, '分')
|
|
14
|
+
.replace(/ss/g, '秒');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 修复 initLayout 的 DetailTable children(明细表"没字段"的根因)。
|
|
18
|
+
*
|
|
19
|
+
* getConfig 对**未铺列**的明细表子字段返回 display:false / show:false / readOnly:true,
|
|
20
|
+
* 直接发给 initLayout 会被当作"隐藏且只读"而不生成列 → 明细表空。
|
|
21
|
+
* 对齐浏览器 payload:子字段强制 可见 + 可编辑(保留 getConfig 原始 showOrder)。
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeDetailTableChildren(configs) {
|
|
24
|
+
for (const c of configs) {
|
|
25
|
+
if (String(c.type) === 'DetailTable' && Array.isArray(c.children)) {
|
|
26
|
+
c.children = c.children.map((ch) => ({
|
|
27
|
+
...ch,
|
|
28
|
+
display: true, show: true, readOnly: false, required: false,
|
|
29
|
+
disableEdit: false, singleRow: false, isDelete: false,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return configs;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 构建 DateRange 日期区间字段对象(对齐浏览器实测 payload)。
|
|
37
|
+
* 需要 3 个字段 ID:主字段 + 开始时间 + 结束时间(各是一个独立 DateComponent)。
|
|
38
|
+
*/
|
|
39
|
+
function buildDateRangeField(def, ctx) {
|
|
40
|
+
const format = def.format || 'yyyy-MM-dd';
|
|
41
|
+
const title = def.fieldName;
|
|
42
|
+
const defaultPh = placeholderFromFormat(format);
|
|
43
|
+
const start = {
|
|
44
|
+
componentKey: 'DateComponent', content: '', describe: '', earlyDate: 'false',
|
|
45
|
+
format, isDefault: 'false', lateDate: 'false',
|
|
46
|
+
placeholder: def.startPlaceholder || defaultPh,
|
|
47
|
+
position: '', relateMultiple: 'false', required: 'false', size: 'medium',
|
|
48
|
+
title: `${title}(开始时间)`, fieldId: ctx.startId,
|
|
49
|
+
min: { type: 'currentHour' }, max: { type: 'currentHour' },
|
|
50
|
+
};
|
|
51
|
+
const end = {
|
|
52
|
+
...start,
|
|
53
|
+
placeholder: def.endPlaceholder || defaultPh,
|
|
54
|
+
title: `${title}(结束时间)`,
|
|
55
|
+
fieldId: ctx.endId,
|
|
56
|
+
};
|
|
57
|
+
const obj = {
|
|
58
|
+
type: 'DateRange', componentKey: 'DateRange', title,
|
|
59
|
+
isDefault: false,
|
|
60
|
+
start, end,
|
|
61
|
+
dataKey: ctx.dataKey, columnName: ctx.columnName,
|
|
62
|
+
fieldId: ctx.mainId, formId: ctx.formId,
|
|
63
|
+
showOrder: ctx.showOrder, groupId: '-1',
|
|
64
|
+
labelObj: {}, status: true, sysField: false,
|
|
65
|
+
required: Boolean(ctx.required), readOnly: Boolean(ctx.readOnly), unique: Boolean(ctx.unique),
|
|
66
|
+
hasDisplayFormat: true,
|
|
67
|
+
rangeInterval: { limitType: 'max', timeUnit: 'day' },
|
|
68
|
+
};
|
|
69
|
+
if (ctx.subFormId)
|
|
70
|
+
obj.subFormId = ctx.subFormId;
|
|
71
|
+
if (ctx.formTableId)
|
|
72
|
+
obj.formTableId = ctx.formTableId;
|
|
73
|
+
return obj;
|
|
74
|
+
}
|
|
75
|
+
function requireSuccess(response, operation) {
|
|
76
|
+
if (response?.code !== 200 || response?.status === false || response?.fail === true) {
|
|
77
|
+
throw new Error(response?.msg || `${operation} 未确认成功`);
|
|
78
|
+
}
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
export async function queryFormStorageSetting(client, baseUrl, appId) {
|
|
82
|
+
const response = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/comp/queryFormStorageSetting`, { module: 'ebuilderform' }, { ebbusinessid: appId }), 'queryFormStorageSetting');
|
|
83
|
+
const data = response.data ?? response;
|
|
84
|
+
const storageSettings = Array.isArray(data.storageSettings) ? data.storageSettings : [];
|
|
85
|
+
// 物理表环境校验表名长度;共享表(share)环境无物理表名,跳过该校验
|
|
86
|
+
const mainTablePrefix = String(data.mainTablePrefix ?? '');
|
|
87
|
+
const physicalTableNameLength = Number(data.physicalTableNameLength || 30);
|
|
88
|
+
if (storageSettings.includes('physical')) {
|
|
89
|
+
if (!Number.isInteger(physicalTableNameLength) || physicalTableNameLength <= mainTablePrefix.length) {
|
|
90
|
+
throw new Error('平台返回的物理表名长度配置无效');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { mainTablePrefix, physicalTableNameLength, storageSettings };
|
|
94
|
+
}
|
|
95
|
+
export function resolveCustomPhysicalTableName(requested, setting) {
|
|
96
|
+
const suffix = requested.startsWith(setting.mainTablePrefix)
|
|
97
|
+
? requested.slice(setting.mainTablePrefix.length)
|
|
98
|
+
: requested;
|
|
99
|
+
const maxSuffixLength = setting.physicalTableNameLength - setting.mainTablePrefix.length;
|
|
100
|
+
if (!PHYSICAL_TABLE_NAME_PATTERN.test(suffix)) {
|
|
101
|
+
throw new Error('--table-name 必须以英文字母开头,且只能包含英文字母、数字和下划线');
|
|
102
|
+
}
|
|
103
|
+
if (suffix.length > maxSuffixLength) {
|
|
104
|
+
throw new Error(`--table-name 自定义部分最多 ${maxSuffixLength} 位(平台前缀 ${setting.mainTablePrefix},总长度上限 ${setting.physicalTableNameLength})`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
suffix,
|
|
108
|
+
expectedTableName: `${setting.mainTablePrefix}${suffix}`,
|
|
109
|
+
maxSuffixLength,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export async function verifyCreatedFormTableName(client, baseUrl, appId, objId, expectedTableName) {
|
|
113
|
+
const encodedAppId = encodeURIComponent(appId);
|
|
114
|
+
const response = requireSuccess(await client.get(`${baseUrl}/api/bs/ebuilder/form/obj/getList/${encodedAppId}?apid=${encodedAppId}`, { ebbusinessid: appId }), '创建后回读表单列表');
|
|
115
|
+
if (!Array.isArray(response.data))
|
|
116
|
+
throw new Error('创建后表单列表数据结构异常');
|
|
117
|
+
const created = response.data.find((form) => String(form.id) === objId);
|
|
118
|
+
if (!created)
|
|
119
|
+
throw new Error(`创建后回读未找到表单 objId=${objId}`);
|
|
120
|
+
const actualTableName = String(created.tableName ?? '');
|
|
121
|
+
if (actualTableName !== expectedTableName) {
|
|
122
|
+
throw new Error(`数据库表名回读不一致:期望 ${expectedTableName},实际 ${actualTableName || '(空)'}`);
|
|
123
|
+
}
|
|
124
|
+
return { objId, tableName: actualTableName };
|
|
125
|
+
}
|
|
126
|
+
export async function createCustomPhysicalForm(client, baseUrl, appId, name, requestedTableName, multiView = false, layoutType) {
|
|
127
|
+
const setting = await queryFormStorageSetting(client, baseUrl, appId);
|
|
128
|
+
const isPhysical = setting.storageSettings.includes('physical');
|
|
129
|
+
const encodedAppId = encodeURIComponent(appId);
|
|
130
|
+
const basePayload = {
|
|
131
|
+
id: '',
|
|
132
|
+
status: 0,
|
|
133
|
+
appId,
|
|
134
|
+
name,
|
|
135
|
+
showName: name,
|
|
136
|
+
description: '',
|
|
137
|
+
groupId: isPhysical ? '-1' : '-2',
|
|
138
|
+
dnEnable: '0',
|
|
139
|
+
openMatter: 0,
|
|
140
|
+
matterSingle: '0',
|
|
141
|
+
matterRightPass: 0,
|
|
142
|
+
matterName: '',
|
|
143
|
+
matterIcon: 'Icon-e-builder-o',
|
|
144
|
+
autoSave: 0,
|
|
145
|
+
quickEdit: 0,
|
|
146
|
+
enableLog: 0,
|
|
147
|
+
enableComment: 0,
|
|
148
|
+
enableFileDelete: 0,
|
|
149
|
+
// isAdvance:true 会锁死为表格(EXCEL)布局(实测 isAdvance:false 才能建流式),FLOW 时必须 false
|
|
150
|
+
isAdvance: layoutType === 'FLOW' ? false : true,
|
|
151
|
+
associatedAuthorization: 0,
|
|
152
|
+
authorizationFields: '',
|
|
153
|
+
logTypes: '["1","2","3","4"]',
|
|
154
|
+
formLogShowType: 'tile',
|
|
155
|
+
dataLogShowType: 'single',
|
|
156
|
+
multiView,
|
|
157
|
+
// 布局类型在 saveOrUpdate 里定(浏览器建表对话框的 checkbox):FLOW(流式)/EXCEL(表格)。
|
|
158
|
+
// 实测加 layoutType:'FLOW' 后 getFormLayout 返回 FLOW;不传缺省 EXCEL。建表后不可切换。
|
|
159
|
+
...(layoutType ? { layoutType } : {}),
|
|
160
|
+
};
|
|
161
|
+
let payload;
|
|
162
|
+
let resolved = null;
|
|
163
|
+
if (isPhysical) {
|
|
164
|
+
resolved = resolveCustomPhysicalTableName(requestedTableName, setting);
|
|
165
|
+
payload = {
|
|
166
|
+
...basePayload,
|
|
167
|
+
tableName: resolved.suffix,
|
|
168
|
+
tableType: 'physical',
|
|
169
|
+
allowAddShare: 0,
|
|
170
|
+
allowEditShare: 0,
|
|
171
|
+
readonlyAllowAddShare: 0,
|
|
172
|
+
enableShare: 0,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// 共享表(虚拟表):tableType 空、无 tableName、groupId=-2、开启 share 相关字段
|
|
177
|
+
payload = {
|
|
178
|
+
...basePayload,
|
|
179
|
+
tableType: '',
|
|
180
|
+
allowAddShare: 1,
|
|
181
|
+
allowEditShare: 0,
|
|
182
|
+
readonlyAllowAddShare: 1,
|
|
183
|
+
enableShare: 0,
|
|
184
|
+
shareApplyForRemindTarget: { shareType: '0', shareContent: [] },
|
|
185
|
+
recordOperateLog: '0',
|
|
186
|
+
matterScope: '{"scopeType":"0","scope":[]}',
|
|
187
|
+
formDataCreate: false,
|
|
188
|
+
enableFullSearch: false,
|
|
189
|
+
autoSaveNewLayout: 0,
|
|
190
|
+
autoSaveEditLayout: 1,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const response = requireSuccess(await client.post(`${baseUrl}/api/bs/ebuilder/form/obj/saveOrUpdate?apid=${encodedAppId}`, payload, { ebbusinessid: appId }), isPhysical ? '创建物理表单' : '创建共享表单');
|
|
194
|
+
const objId = String(response.data?.id ?? response.data?.objId ?? '');
|
|
195
|
+
const formId = String(response.data?.formId ?? '');
|
|
196
|
+
if (!objId || !formId)
|
|
197
|
+
throw new Error(isPhysical ? '创建物理表单未返回 objId/formId' : '创建共享表单未返回 objId/formId');
|
|
198
|
+
if (isPhysical && resolved) {
|
|
199
|
+
const verified = await verifyCreatedFormTableName(client, baseUrl, appId, objId, resolved.expectedTableName);
|
|
200
|
+
return { objId, formId, tableName: verified.tableName, suffix: resolved.suffix, storageType: 'physical' };
|
|
201
|
+
}
|
|
202
|
+
return { objId, formId, tableName: '', suffix: '', storageType: 'share' };
|
|
203
|
+
}
|
|
204
|
+
function storageFieldType(componentKey) {
|
|
205
|
+
const mapping = {
|
|
206
|
+
FileComponent: 'File',
|
|
207
|
+
// DateTime 日期-时间:平台 Date 字段(DateComponent),靠 format 带时间,时间默认时:分(HH:mm 不含秒)
|
|
208
|
+
DateTime: 'Date',
|
|
209
|
+
};
|
|
210
|
+
// TextArea 的平台字段 type 就是 "TextArea"(与 componentKey 同形,对齐浏览器抓包)。
|
|
211
|
+
// 历史上误映射成小写 "Textarea",FLOW 渲染器按 type 查组件查不到 → 多行文本在流式布局下渲染异常。
|
|
212
|
+
return mapping[componentKey] ?? componentKey;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 字段分组分配(updateFormFieldGroup)之后重新 initLayout。
|
|
216
|
+
* 平台新版 initLayout 据 saveFieldGroup 的分组记录 + configs 顺序自动生成 Collapse 容器,
|
|
217
|
+
* 但前提是字段已分配到分组(groupId 已设)。create 流程里 initLayout 发生在分配之前,
|
|
218
|
+
* 所以分配后需再跑一次。对齐浏览器 payload:configs 平铺、分组字段前置(分组→系统→未分组)、
|
|
219
|
+
* 无 groupFieldIds、styleTemplateId=700000000000000008(EXCEL 表格版)。
|
|
220
|
+
*/
|
|
221
|
+
export async function reapplyGroupLayout(client, baseUrl, appId, formId, objId, groupFieldIdSet, layoutTypeOverride) {
|
|
222
|
+
const preLayout = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/builder/getFormLayout`, { formId, module: 'ebuilderform', customParam: {}, formTableIdList: [],
|
|
223
|
+
designerParam: { onlyLayout: false, convert: false }, form: { id: formId } }, { ebbusinessid: formId }), '读取布局ID');
|
|
224
|
+
const layoutMultiId = preLayout.data?.formLayout?.multipleLayoutId || '';
|
|
225
|
+
const layoutId = preLayout.data?.formLayout?.id || '';
|
|
226
|
+
const layoutName = preLayout.data?.formLayoutMultiple?.name || preLayout.data?.formLayout?.name || '';
|
|
227
|
+
const layoutType = layoutTypeOverride || preLayout.data?.formLayoutMultiple?.layoutType || 'EXCEL';
|
|
228
|
+
// FLOW:分组容器由 initLayout 手动 Collapse config 建好(分配前已建),分配后无需重排;
|
|
229
|
+
// 重排会平铺 configs,而 FLOW 的 generateCollapse 不生效,分组会丢。
|
|
230
|
+
if (layoutType === 'FLOW')
|
|
231
|
+
return false;
|
|
232
|
+
const configRes = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/view/relate/getConfig`, { formId, module: 'ebuilderform', apiModule: 'ebuilder/form', layoutId,
|
|
233
|
+
customParam: { terminal: '', objId: formId }, initMode: 5, groupFieldIds: [],
|
|
234
|
+
designerParam: { sourceModule: 'ebuilderform' } }, { ebbusinessid: formId }), '获取字段布局配置');
|
|
235
|
+
let configs = normalizeDetailTableChildren((configRes?.data?.configs || []));
|
|
236
|
+
// 明细表统一放数组末尾
|
|
237
|
+
if (configs.some((c) => c.type === 'DetailTable')) {
|
|
238
|
+
configs = [...configs.filter((c) => c.type !== 'DetailTable'), ...configs.filter((c) => c.type === 'DetailTable')];
|
|
239
|
+
}
|
|
240
|
+
// 分组字段前置:分组字段 → 系统字段 → 未分组字段(对齐浏览器 initLayout payload)
|
|
241
|
+
configs = [
|
|
242
|
+
...configs.filter((c) => groupFieldIdSet.has(String(c.id))),
|
|
243
|
+
...configs.filter((c) => c.system),
|
|
244
|
+
...configs.filter((c) => !groupFieldIdSet.has(String(c.id)) && !c.system),
|
|
245
|
+
];
|
|
246
|
+
requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/view/relate/initLayout?apid=${encodeURIComponent(appId)}`, {
|
|
247
|
+
formId,
|
|
248
|
+
module: 'ebuilderform',
|
|
249
|
+
apiModule: 'ebuilder/form',
|
|
250
|
+
layoutId,
|
|
251
|
+
generateCollapse: true,
|
|
252
|
+
styleTemplateId: layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008',
|
|
253
|
+
styleTemplateType: 1,
|
|
254
|
+
configs,
|
|
255
|
+
addLayout: false,
|
|
256
|
+
ecodeType: ['js', 'css'],
|
|
257
|
+
initMode: layoutTypeOverride ? '5' : '1',
|
|
258
|
+
customParam: { terminal: '', objId: formId },
|
|
259
|
+
formLayoutMultiple: {
|
|
260
|
+
isSys: true,
|
|
261
|
+
id: layoutMultiId,
|
|
262
|
+
name: layoutName,
|
|
263
|
+
terminalType: 'PC',
|
|
264
|
+
layoutType,
|
|
265
|
+
},
|
|
266
|
+
designerParam: { onlyLayout: false },
|
|
267
|
+
}, { ebbusinessid: formId }), '分组后重新布局');
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
export async function addInitialFieldsToCustomPhysicalForm(client, baseUrl, appId, objId, formId, definitions, tenantKey = '', layoutTypeOverride) {
|
|
271
|
+
const mainDefs = definitions.filter(d => d.componentKey !== 'DetailTable');
|
|
272
|
+
const detailDefs = definitions.filter(d => d.componentKey === 'DetailTable');
|
|
273
|
+
// Generate IDs for main fields. DateRange 需要 3 个 ID(主 + 开始 + 结束),普通字段 1 个,
|
|
274
|
+
// 富组件按 richIdUnits(Matrix 需要主+列+选项)。
|
|
275
|
+
const idUnits = mainDefs.map(d => (d.componentKey === 'DateRange' ? 3 : richIdUnits(d.componentKey, d)));
|
|
276
|
+
const totalIdUnits = idUnits.reduce((a, b) => a + b, 0);
|
|
277
|
+
const idResponse = await client.post(`${baseUrl}/api/ebuilder/form/form/freeform/generatorIds?size=${totalIdUnits || 1}`, {}, { ebbusinessid: formId });
|
|
278
|
+
const allGeneratedIds = (idResponse?.generatorIds ?? idResponse?.data?.generatorIds ?? []).map(String);
|
|
279
|
+
if (allGeneratedIds.length < totalIdUnits)
|
|
280
|
+
throw new Error('字段 ID 生成数量不一致');
|
|
281
|
+
let idCursor = 0;
|
|
282
|
+
const seenCols = new Map();
|
|
283
|
+
const mainFieldObjects = [];
|
|
284
|
+
// fieldId → 分组名(fields.json 里 def.group)。建表后按分组名 saveFieldGroup +
|
|
285
|
+
// updateFormFieldGroup,initLayout 时把同组字段包进 Collapse config。
|
|
286
|
+
const groupOfFieldId = new Map();
|
|
287
|
+
// fieldId → 独占一行(fields.json 里 def.singleRow)。initLayout 时该字段 singleRow:true。
|
|
288
|
+
const singleRowOfFieldId = new Map();
|
|
289
|
+
for (let i = 0; i < mainDefs.length; i++) {
|
|
290
|
+
const def = mainDefs[i];
|
|
291
|
+
const base = pinyinInitials(def.fieldName);
|
|
292
|
+
const dup = seenCols.get(base) ?? 0;
|
|
293
|
+
seenCols.set(base, dup + 1);
|
|
294
|
+
const dataKey = toColumnName(def.fieldName, dup);
|
|
295
|
+
const showOrder = `${i}.00`;
|
|
296
|
+
// DateRange:主 ID + start ID + end ID 共 3 个
|
|
297
|
+
if (def.componentKey === 'DateRange') {
|
|
298
|
+
const mainId = allGeneratedIds[idCursor];
|
|
299
|
+
if (def.group)
|
|
300
|
+
groupOfFieldId.set(mainId, def.group);
|
|
301
|
+
mainFieldObjects.push(buildDateRangeField(def, {
|
|
302
|
+
mainId,
|
|
303
|
+
startId: allGeneratedIds[idCursor++],
|
|
304
|
+
endId: allGeneratedIds[idCursor++],
|
|
305
|
+
formId,
|
|
306
|
+
dataKey,
|
|
307
|
+
columnName: dataKey,
|
|
308
|
+
showOrder,
|
|
309
|
+
required: def.required,
|
|
310
|
+
readOnly: def.readOnly,
|
|
311
|
+
unique: def.unique,
|
|
312
|
+
}));
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const fieldId = allGeneratedIds[idCursor++];
|
|
316
|
+
if (def.group)
|
|
317
|
+
groupOfFieldId.set(fieldId, def.group);
|
|
318
|
+
if (def.singleRow)
|
|
319
|
+
singleRowOfFieldId.set(fieldId, true);
|
|
320
|
+
const baseField = {
|
|
321
|
+
type: storageFieldType(def.componentKey),
|
|
322
|
+
componentKey: def.componentKey,
|
|
323
|
+
title: def.fieldName,
|
|
324
|
+
fieldId,
|
|
325
|
+
formId,
|
|
326
|
+
dataKey,
|
|
327
|
+
showOrder,
|
|
328
|
+
groupId: '-1',
|
|
329
|
+
labelObj: {},
|
|
330
|
+
status: true,
|
|
331
|
+
sysField: false,
|
|
332
|
+
required: Boolean(def.required),
|
|
333
|
+
readOnly: Boolean(def.readOnly),
|
|
334
|
+
unique: Boolean(def.unique),
|
|
335
|
+
hidden: def.hidden,
|
|
336
|
+
};
|
|
337
|
+
// DateTime 日期-时间:平台 Date 字段(componentKey Date),format 带时间,默认时:分(HH:mm 不含秒);
|
|
338
|
+
// fields.json 写 format 可覆盖精度
|
|
339
|
+
if (def.componentKey === 'DateTime') {
|
|
340
|
+
baseField.componentKey = 'Date';
|
|
341
|
+
baseField.format = def.format || 'yyyy-MM-dd HH:mm';
|
|
342
|
+
}
|
|
343
|
+
// Date(年月日):format 缺省 yyyy-MM-dd,fields.json format 覆盖(之前主表 plain Date 没设 format)
|
|
344
|
+
if (def.componentKey === 'Date') {
|
|
345
|
+
baseField.format = def.format || 'yyyy-MM-dd';
|
|
346
|
+
}
|
|
347
|
+
// 富组件:映射到平台真实 type/componentKey + 附加配置(对齐 batch/save/formField 抓包)
|
|
348
|
+
const rich = getRichType(def.componentKey);
|
|
349
|
+
if (rich) {
|
|
350
|
+
baseField.type = rich.platformType;
|
|
351
|
+
baseField.componentKey = rich.platformComponentKey;
|
|
352
|
+
if (rich.build) {
|
|
353
|
+
const extra = richIdUnits(def.componentKey, def) - 1;
|
|
354
|
+
const extraIds = allGeneratedIds.slice(idCursor, idCursor + extra);
|
|
355
|
+
idCursor += extra;
|
|
356
|
+
const extraCfg = await rich.build({
|
|
357
|
+
def, fieldId, formId, formTableId: '', dataKey, columnName: dataKey, showOrder, extraIds,
|
|
358
|
+
});
|
|
359
|
+
Object.assign(baseField, extraCfg);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Number/Money 精度:fields.json 可写 precision/pointSize(缺省 Number=0 整数、Money=2)。
|
|
363
|
+
// 不设置会导致平台存 pointSize=sel(无效精度)。
|
|
364
|
+
// 百分比:percent:true → numberType=percentage(缺省 pointSize=1,对齐浏览器 payload)。
|
|
365
|
+
// 默认值:defaultValue → content + isDefault:true;实测设默认必须连 isDelimiter/stepMode/step/isCapital,
|
|
366
|
+
// 否则平台丢默认(只发 content+isDefault 不落库)。
|
|
367
|
+
// 千分位:delimiter:true → isDelimiter(Money 默认开、Number 默认关);大写:capital:true → isCapital + capitalFormat。
|
|
368
|
+
if (def.componentKey === 'Number') {
|
|
369
|
+
const hasDefault = def.defaultValue !== undefined && def.defaultValue !== null && def.defaultValue !== '';
|
|
370
|
+
const isDelim = def.delimiter === true;
|
|
371
|
+
const isCap = def.capital === true;
|
|
372
|
+
Object.assign(baseField, {
|
|
373
|
+
numberType: def.percent ? 'percentage' : 'number',
|
|
374
|
+
pointSize: String(def.precision ?? def.pointSize ?? (def.percent ? '1' : '0')),
|
|
375
|
+
isDefault: hasDefault,
|
|
376
|
+
// content 始终带(无默认值时空串)——浏览器抓包 Number 字段 getFormField 恒有 content:"",
|
|
377
|
+
// 缺 content 在 FLOW 渲染下异常(与多行文本同因)。
|
|
378
|
+
content: hasDefault ? String(def.defaultValue) : '',
|
|
379
|
+
...(hasDefault ? { stepMode: false, step: 1 } : {}),
|
|
380
|
+
isDelimiter: isDelim,
|
|
381
|
+
isCapital: isCap,
|
|
382
|
+
capitalFormat: 'onlyUpperCase',
|
|
383
|
+
capitalPosition: 'outside',
|
|
384
|
+
capitalSetting: 'system',
|
|
385
|
+
capitalPrecision: 'yuan',
|
|
386
|
+
isExchangeRates: false,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
if (def.componentKey === 'Money') {
|
|
390
|
+
const isDelim = def.delimiter !== false; // Money 默认千分位;delimiter:false 关闭
|
|
391
|
+
const isCap = def.capital === true;
|
|
392
|
+
Object.assign(baseField, {
|
|
393
|
+
pointSize: String(def.precision ?? def.pointSize ?? '2'),
|
|
394
|
+
submitSel: false,
|
|
395
|
+
isDefault: false,
|
|
396
|
+
capitalFormat: 'onlyUpperCase',
|
|
397
|
+
capitalPosition: 'outside',
|
|
398
|
+
isDelimiter: isDelim,
|
|
399
|
+
capitalSetting: 'system',
|
|
400
|
+
capitalPrecision: 'yuan',
|
|
401
|
+
isCapital: isCap,
|
|
402
|
+
isExchangeRates: false,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (def.componentKey === 'TextArea') {
|
|
406
|
+
// 多行文本:对齐浏览器抓包——content 恒为 ""(无默认值时空串)、maxLen 缺省 4000(fields.json maxLen 覆盖)。
|
|
407
|
+
// 缺 content 在 FLOW 渲染异常;maxLen 不发则前端最大长度回显异常。
|
|
408
|
+
Object.assign(baseField, { content: '', maxLen: def.maxLen || 4000 });
|
|
409
|
+
}
|
|
410
|
+
if (def.componentKey === 'Text') {
|
|
411
|
+
// 单行文本最大长度:fields.json maxLen 覆盖,缺省 100(之前主表 Text 没设 maxLen → 标注长度不生效)
|
|
412
|
+
baseField.maxLen = def.maxLen || 100;
|
|
413
|
+
}
|
|
414
|
+
if (def.componentKey === 'City') {
|
|
415
|
+
// 城市/地区选择(对齐浏览器 payload:region 模式 + 系统级联层级 + 字母索引)
|
|
416
|
+
Object.assign(baseField, {
|
|
417
|
+
isSingle: false,
|
|
418
|
+
levelSetting: 'system',
|
|
419
|
+
isDefault: false,
|
|
420
|
+
useLetterIndex: true,
|
|
421
|
+
mode: 'region',
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
mainFieldObjects.push(baseField);
|
|
425
|
+
}
|
|
426
|
+
// Date/DateTime 日期限制:minField 最早不得早于 / maxField 最晚不得晚于另一字段。
|
|
427
|
+
// 对齐抓包 min:{type:'dateField', checkValue:<目标字段fieldId>}(本字段最早不得早于目标字段)。
|
|
428
|
+
// 所有字段 ID 已生成(mainFieldObjects 完整),按字段名解析目标 fieldId。
|
|
429
|
+
for (const f of mainFieldObjects) {
|
|
430
|
+
if (f.type !== 'Date')
|
|
431
|
+
continue;
|
|
432
|
+
const def = mainDefs.find((d) => d.fieldName === f.title);
|
|
433
|
+
if (!def)
|
|
434
|
+
continue;
|
|
435
|
+
if (def.minField) {
|
|
436
|
+
const target = mainFieldObjects.find((x) => x.title === def.minField);
|
|
437
|
+
if (target) {
|
|
438
|
+
f.min = { type: 'dateField', checkValue: String(target.fieldId) };
|
|
439
|
+
f.earlyDate = true; // 启用最早日期限制(对齐抓包 earlyDate:true + min.dateField,否则 min 不生效)
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (def.maxField) {
|
|
443
|
+
const target = mainFieldObjects.find((x) => x.title === def.maxField);
|
|
444
|
+
if (target) {
|
|
445
|
+
f.max = { type: 'dateField', checkValue: String(target.fieldId) };
|
|
446
|
+
f.lateDate = true; // 启用最晚日期限制
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// Detail tables: built via `forms` param in the SAME batch/save/formField call
|
|
451
|
+
const detailFieldMetas = [];
|
|
452
|
+
const formsParam = [];
|
|
453
|
+
const subFieldObjectsForBatch = [];
|
|
454
|
+
let detailShowOrder = mainDefs.length;
|
|
455
|
+
for (const dtDef of detailDefs) {
|
|
456
|
+
// Generate 2 IDs: sub-form formId + physical table formTableId
|
|
457
|
+
const subIdsRes = await client.post(`${baseUrl}/api/ebuilder/form/form/freeform/generatorIds?size=2`, {}, { ebbusinessid: formId });
|
|
458
|
+
const subGenIds = (subIdsRes?.generatorIds ?? subIdsRes?.data?.generatorIds ?? []).map(String);
|
|
459
|
+
const subFormId = subGenIds[0] || '';
|
|
460
|
+
const subTableId = subGenIds[1] || '';
|
|
461
|
+
if (!subFormId || !subTableId)
|
|
462
|
+
throw new Error('子表 ID 生成失败');
|
|
463
|
+
const subDataKey = toColumnName(dtDef.fieldName, detailShowOrder);
|
|
464
|
+
const subTableName = toSubTableName(dtDef.fieldName, detailShowOrder);
|
|
465
|
+
formsParam.push({
|
|
466
|
+
id: subFormId,
|
|
467
|
+
tableName: subTableName,
|
|
468
|
+
name: dtDef.fieldName,
|
|
469
|
+
describe: dtDef.fieldName,
|
|
470
|
+
dataKey: subDataKey,
|
|
471
|
+
dataCount: 0,
|
|
472
|
+
tableType: 'MAIN',
|
|
473
|
+
formTableId: subTableId,
|
|
474
|
+
systemTable: false,
|
|
475
|
+
orderConfig: [],
|
|
476
|
+
deleteState: 0,
|
|
477
|
+
editTable: true,
|
|
478
|
+
delete: false,
|
|
479
|
+
isSubForm: true,
|
|
480
|
+
order: detailShowOrder - mainDefs.length,
|
|
481
|
+
});
|
|
482
|
+
// Sub-fields(DateRange 子字段同样需要 3 个 ID)
|
|
483
|
+
const subFieldCount = (dtDef.formFields || []).length;
|
|
484
|
+
const seenSub = new Map();
|
|
485
|
+
if (subFieldCount > 0) {
|
|
486
|
+
const subIdUnits = (dtDef.formFields || []).map(sf => (sf.componentKey === 'DateRange' ? 3 : 1));
|
|
487
|
+
const subTotalUnits = subIdUnits.reduce((a, b) => a + b, 0);
|
|
488
|
+
const sfIdsRes = await client.post(`${baseUrl}/api/ebuilder/form/form/freeform/generatorIds?size=${subTotalUnits}`, {}, { ebbusinessid: formId });
|
|
489
|
+
const sfIds = (sfIdsRes?.generatorIds ?? sfIdsRes?.data?.generatorIds ?? []).map(String);
|
|
490
|
+
let sfCursor = 0;
|
|
491
|
+
for (let si = 0; si < subFieldCount; si++) {
|
|
492
|
+
const sf = (dtDef.formFields || [])[si];
|
|
493
|
+
const sfBase = pinyinInitials(sf.fieldName);
|
|
494
|
+
const sfDup = seenSub.get(sfBase) ?? 0;
|
|
495
|
+
seenSub.set(sfBase, sfDup + 1);
|
|
496
|
+
const sfColName = toColumnName(sf.fieldName, sfDup);
|
|
497
|
+
if (sf.componentKey === 'DateRange') {
|
|
498
|
+
subFieldObjectsForBatch.push(buildDateRangeField(sf, {
|
|
499
|
+
mainId: sfIds[sfCursor++],
|
|
500
|
+
startId: sfIds[sfCursor++],
|
|
501
|
+
endId: sfIds[sfCursor++],
|
|
502
|
+
formId,
|
|
503
|
+
subFormId,
|
|
504
|
+
formTableId: subTableId,
|
|
505
|
+
dataKey: sfColName,
|
|
506
|
+
columnName: sfColName,
|
|
507
|
+
showOrder: '99999',
|
|
508
|
+
}));
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
const sfObj = {
|
|
512
|
+
type: storageFieldType(sf.componentKey),
|
|
513
|
+
// Date/DateTime 子字段平台组件是 DateComponent(与主表一致),TextArea 子字段 type 存小写 Textarea
|
|
514
|
+
componentKey: sf.componentKey === 'TextArea' ? 'Textarea'
|
|
515
|
+
: (sf.componentKey === 'Date' || sf.componentKey === 'DateTime' ? 'DateComponent' : sf.componentKey),
|
|
516
|
+
title: sf.fieldName,
|
|
517
|
+
fieldId: sfIds[sfCursor++],
|
|
518
|
+
formId,
|
|
519
|
+
subFormId,
|
|
520
|
+
formTableId: subTableId,
|
|
521
|
+
groupId: '-1',
|
|
522
|
+
showOrder: 99999,
|
|
523
|
+
dataKey: sfColName,
|
|
524
|
+
columnName: sfColName,
|
|
525
|
+
};
|
|
526
|
+
// Field-type-specific attributes (matching browser-observed payload)
|
|
527
|
+
if (sf.componentKey === 'Number') {
|
|
528
|
+
const sfDef = sf;
|
|
529
|
+
const sfHasDefault = sfDef.defaultValue !== undefined && sfDef.defaultValue !== null && sfDef.defaultValue !== '';
|
|
530
|
+
sfObj.numberType = sfDef.percent ? 'percentage' : 'number';
|
|
531
|
+
sfObj.pointSize = String(sfDef.precision ?? sfDef.pointSize ?? (sfDef.percent ? '1' : '0'));
|
|
532
|
+
sfObj.isDefault = sfHasDefault;
|
|
533
|
+
if (sfHasDefault) {
|
|
534
|
+
sfObj.content = String(sfDef.defaultValue);
|
|
535
|
+
sfObj.isDelimiter = false;
|
|
536
|
+
sfObj.stepMode = false;
|
|
537
|
+
sfObj.step = 1;
|
|
538
|
+
sfObj.isCapital = false;
|
|
539
|
+
}
|
|
540
|
+
sfObj.capitalPosition = 'outside';
|
|
541
|
+
sfObj.capitalSetting = 'system';
|
|
542
|
+
sfObj.capitalPrecision = 'yuan';
|
|
543
|
+
}
|
|
544
|
+
else if (sf.componentKey === 'Money') {
|
|
545
|
+
sfObj.pointSize = String(sf.precision ?? sf.pointSize ?? '2');
|
|
546
|
+
sfObj.submitSel = false;
|
|
547
|
+
sfObj.isDefault = false;
|
|
548
|
+
sfObj.capitalPosition = 'outside';
|
|
549
|
+
sfObj.isDelimiter = true;
|
|
550
|
+
sfObj.capitalSetting = 'system';
|
|
551
|
+
sfObj.capitalPrecision = 'yuan';
|
|
552
|
+
}
|
|
553
|
+
else if (sf.componentKey === 'Date' || sf.componentKey === 'DateTime') {
|
|
554
|
+
// 明细日期精度:之前误用 dateFormat(错 key,平台不认)→ 精度丢失。浏览器抓包用 format。
|
|
555
|
+
// Date 默认 yyyy-MM-dd(年月日)、DateTime 默认 yyyy-MM-dd HH:mm(时:分);fields.json format 覆盖。
|
|
556
|
+
const isDt = sf.componentKey === 'DateTime';
|
|
557
|
+
const sfFmt = sf.format || (isDt ? 'yyyy-MM-dd HH:mm' : 'yyyy-MM-dd');
|
|
558
|
+
Object.assign(sfObj, {
|
|
559
|
+
format: sfFmt,
|
|
560
|
+
placeholder: placeholderFromFormat(sfFmt),
|
|
561
|
+
timePanelStyle: { type: 'system' },
|
|
562
|
+
earlyDate: false,
|
|
563
|
+
lateDate: false,
|
|
564
|
+
defaultExtend: { date: { type: 'custom' } },
|
|
565
|
+
minuteStep: 1,
|
|
566
|
+
hasDisplayFormat: false,
|
|
567
|
+
columnType: 'VARCHAR',
|
|
568
|
+
typeLen: 25,
|
|
569
|
+
columnTypeSwitch: false,
|
|
570
|
+
isDefault: false,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
else if (sf.componentKey === 'IDCard') {
|
|
574
|
+
// 身份证号:浏览器抓包 payload 极简,无文本长度/唯一/扫码等配置
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
// Text/TextArea/others
|
|
578
|
+
sfObj.maxLen = sf.componentKey === 'TextArea' ? 1000 : 100;
|
|
579
|
+
sfObj.unique = false;
|
|
580
|
+
sfObj.scan = false;
|
|
581
|
+
sfObj.readonlyTransLink = false;
|
|
582
|
+
}
|
|
583
|
+
subFieldObjectsForBatch.push(sfObj);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
detailFieldMetas.push({ fieldId: subFormId, subFormId, definition: dtDef, showOrder: detailShowOrder });
|
|
587
|
+
detailShowOrder++;
|
|
588
|
+
}
|
|
589
|
+
// 子表字段日期校验:minField/maxField 可指向主表字段(mainFieldObjects)或子表字段(subFieldObjectsForBatch)。
|
|
590
|
+
// 先全部生成再统一补(保证同子表后出现的字段也能解析)。对齐抓包 min:{type:'dateField', checkValue} + earlyDate 开关。
|
|
591
|
+
for (const f of subFieldObjectsForBatch) {
|
|
592
|
+
if (f.type !== 'Date')
|
|
593
|
+
continue;
|
|
594
|
+
const sfDef = detailDefs.flatMap((d) => (d.formFields || [])).find((s) => s.fieldName === f.title);
|
|
595
|
+
if (!sfDef)
|
|
596
|
+
continue;
|
|
597
|
+
if (sfDef.minField) {
|
|
598
|
+
const target = [...mainFieldObjects, ...subFieldObjectsForBatch].find((x) => x.title === sfDef.minField);
|
|
599
|
+
if (target) {
|
|
600
|
+
f.min = { type: 'dateField', checkValue: String(target.fieldId) };
|
|
601
|
+
f.earlyDate = true;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (sfDef.maxField) {
|
|
605
|
+
const target = [...mainFieldObjects, ...subFieldObjectsForBatch].find((x) => x.title === sfDef.maxField);
|
|
606
|
+
if (target) {
|
|
607
|
+
f.max = { type: 'dateField', checkValue: String(target.fieldId) };
|
|
608
|
+
f.lateDate = true;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// One call: main fields + sub-form + sub-fields (matching browser-observed payload)
|
|
613
|
+
const allFieldObjects = [...mainFieldObjects, ...subFieldObjectsForBatch];
|
|
614
|
+
if (allFieldObjects.length > 0 || formsParam.length > 0) {
|
|
615
|
+
requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/batch/save/formField?apid=${encodeURIComponent(appId)}`, {
|
|
616
|
+
module: 'ebuilderform',
|
|
617
|
+
formId,
|
|
618
|
+
customParam: { appId, objId },
|
|
619
|
+
forms: formsParam,
|
|
620
|
+
ids: [],
|
|
621
|
+
delSubFormIds: [],
|
|
622
|
+
delFormTableIdList: [],
|
|
623
|
+
jsonObjList: allFieldObjects.map(f => JSON.stringify(f)),
|
|
624
|
+
replaceFieldIdMap: {},
|
|
625
|
+
}, { ebbusinessid: formId }), '批量创建表单字段及明细表');
|
|
626
|
+
}
|
|
627
|
+
// Read back fields
|
|
628
|
+
const fieldResponse = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/getFormFieldPage?apid=${encodeURIComponent(appId)}`, {
|
|
629
|
+
pageNo: 1,
|
|
630
|
+
pageSize: 200,
|
|
631
|
+
module: 'ebuilderform',
|
|
632
|
+
customParam: { appId, objId },
|
|
633
|
+
formFieldSearchEntity: { isDelete: 0, status: 'enable', formId },
|
|
634
|
+
}, { ebbusinessid: formId }), '字段创建后回读');
|
|
635
|
+
const fields = fieldResponse.data?.pageDatas?.result;
|
|
636
|
+
if (!Array.isArray(fields))
|
|
637
|
+
throw new Error('字段创建后回读结构异常');
|
|
638
|
+
const savedIds = new Set(fields.map((field) => String(field.fieldId ?? field.id)));
|
|
639
|
+
const mainOnlyIds = mainFieldObjects.map(f => f.fieldId);
|
|
640
|
+
const missing = mainOnlyIds.filter((id) => !savedIds.has(id));
|
|
641
|
+
if (missing.length)
|
|
642
|
+
throw new Error(`主表字段创建后回读缺少 ${missing.length} 个字段`);
|
|
643
|
+
// 字段分组:fields.json 里 def.group 同名字段归一组。
|
|
644
|
+
// 这里只建分组记录(saveFieldGroup,返回 group.id + group.refFieldId),initLayout 时用
|
|
645
|
+
// refFieldId 包 Collapse config。字段→分组的分配(updateFormFieldGroup)放到 form create
|
|
646
|
+
// 最末做——选项(Step7)/公式(Step8)等 saveFormFieldNew 会重置 field.groupId,先分配会被冲掉。
|
|
647
|
+
// refFieldId 是 layout Collapse config id(= group.id - 1,平台先分 layout config 再分 formFieldGroup)。
|
|
648
|
+
const groupFields = new Map();
|
|
649
|
+
for (const f of mainFieldObjects) {
|
|
650
|
+
const g = groupOfFieldId.get(String(f.fieldId));
|
|
651
|
+
if (!g)
|
|
652
|
+
continue;
|
|
653
|
+
if (!groupFields.has(g))
|
|
654
|
+
groupFields.set(g, []);
|
|
655
|
+
groupFields.get(g).push(String(f.fieldId));
|
|
656
|
+
}
|
|
657
|
+
const groupMeta = new Map();
|
|
658
|
+
for (const [groupName, fieldIds] of groupFields) {
|
|
659
|
+
const sg = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/saveFieldGroup?apid=${encodeURIComponent(appId)}`, { module: 'ebuilderform', formFieldGroup: { groupName, formId }, customParam: { appId, objId } }, { ebbusinessid: formId }), `建字段分组 ${groupName}`);
|
|
660
|
+
const groupId = sg.data?.group?.id;
|
|
661
|
+
const refFieldId = sg.data?.group?.refFieldId;
|
|
662
|
+
if (!groupId || !refFieldId)
|
|
663
|
+
throw new Error(`建分组 ${groupName} 未返回 id/refFieldId`);
|
|
664
|
+
groupMeta.set(groupName, { groupId, refFieldId });
|
|
665
|
+
}
|
|
666
|
+
// 供 form create 末尾统一分配字段到分组(所有 saveFormFieldNew 之后)。
|
|
667
|
+
const fieldGroups = [...groupFields.entries()].map(([name, fieldIds]) => ({
|
|
668
|
+
name, fieldIds, groupId: groupMeta.get(name).groupId, refFieldId: groupMeta.get(name).refFieldId,
|
|
669
|
+
}));
|
|
670
|
+
// Use system auto-layout (initLayout) — handles EXCEL + DetailTable automatically
|
|
671
|
+
// Get layout IDs from getFormLayout (more reliable than layout/list)
|
|
672
|
+
const preLayout = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/builder/getFormLayout`, { formId, module: 'ebuilderform', customParam: {}, formTableIdList: [],
|
|
673
|
+
designerParam: { onlyLayout: false, convert: false }, form: { id: formId } }, { ebbusinessid: formId }), '读取布局ID');
|
|
674
|
+
const layoutMultiId = preLayout.data?.formLayout?.multipleLayoutId || '';
|
|
675
|
+
const layoutId = preLayout.data?.formLayout?.id || '';
|
|
676
|
+
const layoutName = preLayout.data?.formLayoutMultiple?.name || preLayout.data?.formLayout?.name || '';
|
|
677
|
+
// 表单可能是流式布局(FLOW)或表格布局(EXCEL),用实际类型,不能用硬编码 EXCEL。
|
|
678
|
+
// layoutTypeOverride(form create --layout)在建表时显式指定布局类型——布局类型建表后不可切换,
|
|
679
|
+
// 事后改不了,只能在创建时定(浏览器实测:FLOW 用特殊模板 820000000000000001,跨环境一致)。
|
|
680
|
+
const layoutType = layoutTypeOverride || preLayout.data?.formLayoutMultiple?.layoutType || 'EXCEL';
|
|
681
|
+
// Get field configs for initLayout (includes system fields + DetailTable children)
|
|
682
|
+
const configRes = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/view/relate/getConfig`, {
|
|
683
|
+
formId,
|
|
684
|
+
module: 'ebuilderform',
|
|
685
|
+
apiModule: 'ebuilder/form',
|
|
686
|
+
layoutId,
|
|
687
|
+
customParam: { terminal: '', objId: formId },
|
|
688
|
+
initMode: 5,
|
|
689
|
+
groupFieldIds: [],
|
|
690
|
+
designerParam: { sourceModule: 'ebuilderform' },
|
|
691
|
+
}, { ebbusinessid: formId }), '获取字段布局配置');
|
|
692
|
+
// Map field defs by fieldId so fields.json required/readOnly override getConfig defaults.
|
|
693
|
+
// Business fields default to editable (readOnly=false) — getConfig/008 template otherwise
|
|
694
|
+
// emit read-only comps.
|
|
695
|
+
const defByFieldId = new Map(mainFieldObjects.map((f) => [String(f.fieldId), f]));
|
|
696
|
+
// 布局控制(对齐浏览器 initLayout payload):
|
|
697
|
+
// 1. 重排业务字段 showOrder —— getConfig 会把明细表夹在中间(其 subFormId 生成的 ID 早于
|
|
698
|
+
// 部分普通字段),导致"明细表跳到上面"。普通字段按建表顺序在前、明细表统一在最后。
|
|
699
|
+
// 2. 落单字段(普通字段奇数个的最后一个)与明细表设 singleRow:true 独占一行 ——
|
|
700
|
+
// 否则落单字段仍是两列占左列、右列留白("编号单独一行但没独占")。
|
|
701
|
+
const businessOrder = new Map();
|
|
702
|
+
const mainFieldIdOrder = mainFieldObjects.map((f) => String(f.fieldId));
|
|
703
|
+
let layoutIdx = 0;
|
|
704
|
+
for (const id of mainFieldIdOrder)
|
|
705
|
+
businessOrder.set(id, layoutIdx++);
|
|
706
|
+
for (const dt of detailFieldMetas)
|
|
707
|
+
businessOrder.set(String(dt.fieldId), layoutIdx++);
|
|
708
|
+
// 落单字段(奇数个的最后一个)独占一行,避免右列留白。
|
|
709
|
+
// 有分组时:分组内字段由 Collapse 容器自行排布,落单只对**未分组字段**(按未分组字段数奇偶)判断;
|
|
710
|
+
// 否则全局最后一个字段(如未分组字段)被误设 singleRow,把本应两列拼行的未分组字段拆开
|
|
711
|
+
// ("签订日期下面字段独立成行 → 签订日期没占满一行")。
|
|
712
|
+
const hasGroup = groupMeta.size > 0;
|
|
713
|
+
const ungroupedMainIds = mainFieldObjects
|
|
714
|
+
.filter((f) => !groupOfFieldId.get(String(f.fieldId)))
|
|
715
|
+
.map((f) => String(f.fieldId));
|
|
716
|
+
const loneRowId = hasGroup
|
|
717
|
+
? (ungroupedMainIds.length % 2 === 1 ? ungroupedMainIds[ungroupedMainIds.length - 1] : null)
|
|
718
|
+
: (mainFieldIdOrder.length % 2 === 1 ? mainFieldIdOrder[mainFieldIdOrder.length - 1] : null);
|
|
719
|
+
let configs = normalizeDetailTableChildren((configRes?.data?.configs || []).map((c) => {
|
|
720
|
+
const def = defByFieldId.get(String(c.id));
|
|
721
|
+
const isBusiness = !c.system;
|
|
722
|
+
const order = businessOrder.get(String(c.id));
|
|
723
|
+
const isDetail = c.type === 'DetailTable';
|
|
724
|
+
return {
|
|
725
|
+
...c,
|
|
726
|
+
display: c.system ? c.display : true,
|
|
727
|
+
// hidden:true → 布局属性"显示"取消(show:false),字段不展示但保留参与计算
|
|
728
|
+
show: c.system ? c.show : !(def?.hidden),
|
|
729
|
+
...(order !== undefined ? { showOrder: order } : {}),
|
|
730
|
+
...(isBusiness ? {
|
|
731
|
+
readOnly: def ? Boolean(def.readOnly) : false,
|
|
732
|
+
required: def ? Boolean(def.required) : (c.required ?? false),
|
|
733
|
+
// 独占一行:明细表 + 落单字段 + 字段显式写 singleRow:true(其余普通字段保持两列)
|
|
734
|
+
singleRow: isDetail || String(c.id) === loneRowId || singleRowOfFieldId.get(String(c.id)) === true,
|
|
735
|
+
} : {}),
|
|
736
|
+
};
|
|
737
|
+
}));
|
|
738
|
+
// 明细表统一放数组末尾(initLayout 按 configs 数组顺序布局,不看 showOrder;
|
|
739
|
+
// getConfig 会把明细表夹在中间导致"明细表跳到上面")
|
|
740
|
+
if (configs.some((c) => c.type === 'DetailTable')) {
|
|
741
|
+
configs = [...configs.filter((c) => c.type !== 'DetailTable'), ...configs.filter((c) => c.type === 'DetailTable')];
|
|
742
|
+
}
|
|
743
|
+
// 注:FLOW comp 里的 EXCEL 残留属性(componentLevel/index/isReadOnly/isSingle/order/tempId/templateId/
|
|
744
|
+
// unique/labelObj/layout.canDel)来自平台 initLayout 按**字段定义 + 模板**重建 comp,与 CLI 发的
|
|
745
|
+
// configs 内容无关——实测剥残留 + 补 associatedId 后读回仍带残留、associatedId 仍缺,initLayout 忽略
|
|
746
|
+
// 这些 comp 层字段。故真正生效的修都在字段定义层(storageFieldType 的 TextArea 大小写、componentKey
|
|
747
|
+
// 归一、Number/TextArea 的 content/maxLen),comp 层由平台据字段定义生成,字段定义对了 comp 即对。
|
|
748
|
+
// 分组渲染按布局类型分叉:
|
|
749
|
+
// EXCEL:平铺 + 分组字段前置,平台 generateCollapse 据 saveFieldGroup 分组记录自动生成 Collapse 容器
|
|
750
|
+
// (对齐浏览器 007 payload:configs 全平铺、无 Collapse 组件、无 groupFieldIds)。
|
|
751
|
+
// FLOW:平台 generateCollapse 对流式布局**不生效**(实测不生成 Collapse),改用手动 Collapse config +
|
|
752
|
+
// groupFieldIds(旧逻辑,FLOW 分组曾验证 OK)。
|
|
753
|
+
const groupFieldIds = [];
|
|
754
|
+
if (groupMeta.size > 0) {
|
|
755
|
+
if (layoutType === 'FLOW') {
|
|
756
|
+
const childrenByGroup = new Map();
|
|
757
|
+
for (const gname of groupFields.keys())
|
|
758
|
+
childrenByGroup.set(gname, []);
|
|
759
|
+
const ungrouped = [];
|
|
760
|
+
for (const c of configs) {
|
|
761
|
+
const gname = groupOfFieldId.get(String(c.id));
|
|
762
|
+
if (gname && groupMeta.has(gname) && !c.system) {
|
|
763
|
+
childrenByGroup.get(gname).push(c);
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
ungrouped.push(c);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
const collapses = [];
|
|
770
|
+
for (const gname of groupFields.keys()) {
|
|
771
|
+
const meta = groupMeta.get(gname);
|
|
772
|
+
const children = childrenByGroup.get(gname) || [];
|
|
773
|
+
groupFieldIds.push(meta.refFieldId);
|
|
774
|
+
collapses.push({
|
|
775
|
+
id: meta.refFieldId, name: gname, componentKey: 'Fold', display: true, show: true,
|
|
776
|
+
readOnly: true, required: false, disableEdit: false, singleRow: false, isDelete: false,
|
|
777
|
+
type: 'Collapse', typeDescribe: '分组', dataKey: `f_${meta.refFieldId}`,
|
|
778
|
+
children,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
configs = [...collapses, ...ungrouped];
|
|
782
|
+
let so = 0;
|
|
783
|
+
for (const c of configs) {
|
|
784
|
+
c.showOrder = so++;
|
|
785
|
+
for (const ch of (c.children || []))
|
|
786
|
+
ch.showOrder = so++;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
// EXCEL:平铺 + 分组字段前置(分组字段 → 系统字段 → 未分组字段)
|
|
791
|
+
const groupFieldIdSet = new Set();
|
|
792
|
+
for (const [, fieldIds] of groupFields)
|
|
793
|
+
for (const id of fieldIds)
|
|
794
|
+
groupFieldIdSet.add(String(id));
|
|
795
|
+
configs = [
|
|
796
|
+
...configs.filter((c) => groupFieldIdSet.has(String(c.id))),
|
|
797
|
+
...configs.filter((c) => c.system),
|
|
798
|
+
...configs.filter((c) => !groupFieldIdSet.has(String(c.id)) && !c.system),
|
|
799
|
+
];
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
const initResult = requireSuccess(await client.post(`${baseUrl}/api/ebuilder/form/form/view/relate/initLayout?apid=${encodeURIComponent(appId)}`, {
|
|
803
|
+
formId,
|
|
804
|
+
module: 'ebuilderform',
|
|
805
|
+
apiModule: 'ebuilder/form',
|
|
806
|
+
layoutId,
|
|
807
|
+
generateCollapse: true,
|
|
808
|
+
styleTemplateId: layoutType === 'FLOW' ? '820000000000000001' : '700000000000000008',
|
|
809
|
+
styleTemplateType: 1,
|
|
810
|
+
configs,
|
|
811
|
+
addLayout: false,
|
|
812
|
+
ecodeType: ['js', 'css'],
|
|
813
|
+
// 显式指定布局时 initMode 用浏览器新建的 '5'(对齐抓包);缺省路径保持 '1' 防回归
|
|
814
|
+
initMode: layoutTypeOverride ? '5' : '1',
|
|
815
|
+
// FLOW 分组用手动 Collapse config,传各分组 refFieldId(layout Collapse config id);
|
|
816
|
+
// EXCEL 分组由平台 generateCollapse 自动生成,此数组为空。
|
|
817
|
+
groupFieldIds,
|
|
818
|
+
customParam: { terminal: '', objId: formId },
|
|
819
|
+
formLayoutMultiple: {
|
|
820
|
+
isSys: true,
|
|
821
|
+
id: layoutMultiId,
|
|
822
|
+
name: layoutName,
|
|
823
|
+
terminalType: 'PC',
|
|
824
|
+
layoutType,
|
|
825
|
+
},
|
|
826
|
+
designerParam: { onlyLayout: false },
|
|
827
|
+
}, { ebbusinessid: formId }), '系统自动布局');
|
|
828
|
+
// Use initLayout response's pageLayouts directly (more reliable than separate getFormLayout)
|
|
829
|
+
const pageLayouts = initResult.data?.pageLayouts || initResult.data?.formLayout?.pageLayouts || [];
|
|
830
|
+
const comps = pageLayouts.flatMap((p) => Array.isArray(p.comps) ? p.comps : []);
|
|
831
|
+
if (comps.length === 0)
|
|
832
|
+
throw new Error('initLayout 返回的布局无组件');
|
|
833
|
+
return { fieldIds: mainFieldObjects.map(f => f.fieldId), layoutComponentCount: comps.length, detailTables: detailFieldMetas, fieldGroups };
|
|
834
|
+
}
|
|
835
|
+
//# sourceMappingURL=form-create.js.map
|