worsoft-frontend-codegen-local-mcp 0.1.89 → 0.1.91
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/templates/master_child_jump/form.tpl +2 -1
- package/mcp_server.js +226 -94
- package/package.json +1 -1
|
@@ -24,8 +24,9 @@
|
|
|
24
24
|
<!-- 主子表表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
25
25
|
<el-form ref="dataFormRef" :model="form" :rules="dataRules" :disabled="detail" v-loading="loading" label-width="120px">
|
|
26
26
|
<el-collapse v-model="activeCollapseNames">
|
|
27
|
-
{{
|
|
27
|
+
{{FORM_COLLAPSE_SECTIONS_BEFORE_CHILDREN}}
|
|
28
28
|
{{CHILD_SECTIONS}}
|
|
29
|
+
{{FORM_COLLAPSE_SECTIONS_AFTER_CHILDREN}}
|
|
29
30
|
</el-collapse>
|
|
30
31
|
</el-form>
|
|
31
32
|
</el-card>
|
package/mcp_server.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
7
|
const SERVER_NAME = 'worsoft-codegen-local';
|
|
8
|
-
const SERVER_VERSION = '0.1.
|
|
8
|
+
const SERVER_VERSION = '0.1.91';
|
|
9
9
|
const PROTOCOL_VERSION = '2024-11-05';
|
|
10
10
|
const TOOL_NAME = 'worsoft_codegen_local_generate_frontend';
|
|
11
11
|
const STYLE_CATALOG_PATH = path.join(__dirname, 'assets', 'style-catalog.json');
|
|
@@ -2208,13 +2208,35 @@ function buildModel(safeArgs) {
|
|
|
2208
2208
|
};
|
|
2209
2209
|
}
|
|
2210
2210
|
|
|
2211
|
-
function renderTemplate(templateText, replacements) {
|
|
2212
|
-
let output = templateText;
|
|
2213
|
-
for (const [key, value] of Object.entries(replacements)) {
|
|
2214
|
-
output = output.split('{{' + key + '}}').join(String(value));
|
|
2215
|
-
}
|
|
2216
|
-
return output;
|
|
2217
|
-
}
|
|
2211
|
+
function renderTemplate(templateText, replacements) {
|
|
2212
|
+
let output = templateText;
|
|
2213
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
2214
|
+
output = output.split('{{' + key + '}}').join(String(value));
|
|
2215
|
+
}
|
|
2216
|
+
return output;
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
function findUnresolvedTemplatePlaceholders(content) {
|
|
2220
|
+
const matches = String(content || '').match(/\{\{[A-Z][A-Z0-9_]*\}\}/g) || [];
|
|
2221
|
+
return [...new Set(matches)];
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
function assertNoUnresolvedTemplatePlaceholders(files) {
|
|
2225
|
+
const issues = files
|
|
2226
|
+
.map((file) => ({
|
|
2227
|
+
type: file.type,
|
|
2228
|
+
path: file.path,
|
|
2229
|
+
placeholders: findUnresolvedTemplatePlaceholders(file.content),
|
|
2230
|
+
}))
|
|
2231
|
+
.filter((item) => item.placeholders.length);
|
|
2232
|
+
|
|
2233
|
+
if (issues.length) {
|
|
2234
|
+
const detail = issues
|
|
2235
|
+
.map((item) => `${item.type}:${path.basename(item.path)} -> ${item.placeholders.join(', ')}`)
|
|
2236
|
+
.join('; ');
|
|
2237
|
+
throw new Error(`MCP template rendering left unresolved placeholders: ${detail}`);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2218
2240
|
|
|
2219
2241
|
function renderFormField(field) {
|
|
2220
2242
|
const label = stripDictAnnotation(field.comment).replace(/'/g, "\\'");
|
|
@@ -2545,19 +2567,68 @@ function renderDisabledBoolV2(field) {
|
|
|
2545
2567
|
return field.readonly ? 'true' : 'false';
|
|
2546
2568
|
}
|
|
2547
2569
|
|
|
2548
|
-
function renderMicromeFormatAttr(field) {
|
|
2549
|
-
const length = Number.parseInt(String(field.length || ''), 10);
|
|
2550
|
-
const scale = Number.parseInt(String(field.scale || ''), 10);
|
|
2551
|
-
if (!length || Number.isNaN(length) || Number.isNaN(scale) || scale < 0) return '';
|
|
2552
|
-
const integerLength = Math.max(length - scale, 1);
|
|
2553
|
-
return ` format="${integerLength}-${scale}"`;
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
}
|
|
2570
|
+
function renderMicromeFormatAttr(field) {
|
|
2571
|
+
const length = Number.parseInt(String(field.length || ''), 10);
|
|
2572
|
+
const scale = Number.parseInt(String(field.scale || ''), 10);
|
|
2573
|
+
if (!length || Number.isNaN(length) || Number.isNaN(scale) || scale < 0) return '';
|
|
2574
|
+
const integerLength = Math.max(length - scale, 1);
|
|
2575
|
+
return ` format="${integerLength}-${scale}"`;
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
const FORM_LAYOUT_DOMAIN_GROUPS = [
|
|
2579
|
+
{ key: 'contract', title: '合同信息', words: ['contract', 'sign', 'supplier', 'owner', 'customer', 'tax', 'term'] },
|
|
2580
|
+
{ key: 'pay', title: '支付信息', words: ['pay', 'payable', 'paid', 'payment', 'advance', 'offset'] },
|
|
2581
|
+
{ key: 'receive', title: '收款信息', words: ['receivable', 'receive', 'income', 'collect'] },
|
|
2582
|
+
{ key: 'settle', title: '结算信息', words: ['settle', 'finsettle', 'accountingperiod'] },
|
|
2583
|
+
{ key: 'warranty', title: '保证金/质保金信息', words: ['deposit', 'warranty', 'guarantee', 'return'] },
|
|
2584
|
+
{ key: 'clause', title: '条款信息', words: ['breach', 'argue', 'clause', 'substance', 'content'] },
|
|
2585
|
+
{ key: 'change', title: '变更信息', words: ['change', 'adjust', 'before', 'after'] },
|
|
2586
|
+
{ key: 'claim', title: '索赔/扣款/折扣信息', words: ['claim', 'reply', 'deduct', 'discount'] },
|
|
2587
|
+
{ key: 'work', title: '人员工作信息', words: ['pos', 'dept', 'ogn', 'induction', 'job', 'labor', 'retired', 'restart'] },
|
|
2588
|
+
{ key: 'borrow', title: '借用/领用/使用信息', words: ['borrow', 'lend', 'use', 'requisition', 'admin'] },
|
|
2589
|
+
{ key: 'document', title: '公文信息', words: ['document', 'reference', 'urgency', 'level', 'drafter', 'tomain', 'tocopy', 'tosubmit', 'year', 'no', 'proofread'] },
|
|
2590
|
+
];
|
|
2591
|
+
|
|
2592
|
+
function getFormLayoutFieldText(field) {
|
|
2593
|
+
return [
|
|
2594
|
+
field?.attrName,
|
|
2595
|
+
field?.fieldName,
|
|
2596
|
+
field?.comment,
|
|
2597
|
+
field?.label,
|
|
2598
|
+
field?.description,
|
|
2599
|
+
field?.formType,
|
|
2600
|
+
field?.sqlType,
|
|
2601
|
+
].filter(Boolean).join(' ').toLowerCase();
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
function includesAnyLayoutWord(text, words) {
|
|
2605
|
+
const normalized = String(text || '').toLowerCase();
|
|
2606
|
+
return words.some((word) => normalized.includes(String(word).toLowerCase()));
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
function isAttachmentLikeField(field) {
|
|
2610
|
+
const text = getFormLayoutFieldText(field);
|
|
2611
|
+
return field?.formType === 'upload'
|
|
2612
|
+
|| includesAnyLayoutWord(text, ['attachment', 'file', 'upload', 'photo', 'sign'])
|
|
2613
|
+
|| /附件|上传|图片|签名/.test(text);
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
function computeFormFieldSpan(field) {
|
|
2617
|
+
const prop = String(field?.attrName || field?.fieldName || '');
|
|
2618
|
+
const propLower = prop.toLowerCase();
|
|
2619
|
+
const text = getFormLayoutFieldText(field);
|
|
2620
|
+
|
|
2621
|
+
if (['upload', 'textarea', 'richtext'].includes(field?.formType)) return 24;
|
|
2622
|
+
if (isAttachmentLikeField(field)) return 24;
|
|
2623
|
+
if (includesAnyLayoutWord(text, ['remark', 'remarks', 'reason', 'opinion', 'content', 'address', 'explain', 'description', 'substance', 'clause', 'breach', 'argue'])) return 24;
|
|
2624
|
+
if (/备注|原因|意见|内容|地址|说明|条款|违约|争议/.test(text)) return 24;
|
|
2625
|
+
if (propLower.includes('keywords')) return 18;
|
|
2626
|
+
if (prop === 'projectName') return 12;
|
|
2627
|
+
if (includesAnyLayoutWord(propLower, ['fullname', 'orgname', 'deptname', 'ognname', 'companyname', 'suppliername', 'customername', 'unitname'])) return 12;
|
|
2628
|
+
if (/项目名称|完整名称|组织名称|部门名称|单位名称|供应商名称|客户名称/.test(text)) return 12;
|
|
2629
|
+
|
|
2630
|
+
return 6;
|
|
2631
|
+
}
|
|
2561
2632
|
|
|
2562
2633
|
function renderFieldCommentV2(field, indent = ' ') {
|
|
2563
2634
|
const label = stripDictAnnotation(field.comment || field.attrName).replace(/-->/g, '').trim() || field.attrName;
|
|
@@ -2565,27 +2636,28 @@ function renderFieldCommentV2(field, indent = ' ') {
|
|
|
2565
2636
|
}
|
|
2566
2637
|
|
|
2567
2638
|
function renderFormFieldV2(field) {
|
|
2568
|
-
const prop = field.attrName;
|
|
2569
|
-
const labelExpr = `getMasterFieldLabel('${prop}')`;
|
|
2570
|
-
const dictExpr = `getMasterFieldMeta('${prop}')?.dictType`;
|
|
2571
|
-
const disabledAttr = renderDisabledAttrV2(field);
|
|
2572
|
-
const disabledBool = renderDisabledBoolV2(field);
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
`
|
|
2579
|
-
`
|
|
2639
|
+
const prop = field.attrName;
|
|
2640
|
+
const labelExpr = `getMasterFieldLabel('${prop}')`;
|
|
2641
|
+
const dictExpr = `getMasterFieldMeta('${prop}')?.dictType`;
|
|
2642
|
+
const disabledAttr = renderDisabledAttrV2(field);
|
|
2643
|
+
const disabledBool = renderDisabledBoolV2(field);
|
|
2644
|
+
const span = computeFormFieldSpan(field);
|
|
2645
|
+
|
|
2646
|
+
if (field.formType === 'upload') {
|
|
2647
|
+
return [
|
|
2648
|
+
renderFieldCommentV2(field),
|
|
2649
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2650
|
+
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2651
|
+
` <UploadFile v-model="form.${prop}"${disabledAttr} />`,
|
|
2580
2652
|
' </el-form-item>',
|
|
2581
2653
|
' </el-col>',
|
|
2582
2654
|
].join('\n');
|
|
2583
2655
|
}
|
|
2584
2656
|
|
|
2585
|
-
if (field.formType === 'select') {
|
|
2586
|
-
return [
|
|
2587
|
-
renderFieldCommentV2(field),
|
|
2588
|
-
` <el-col :span="
|
|
2657
|
+
if (field.formType === 'select') {
|
|
2658
|
+
return [
|
|
2659
|
+
renderFieldCommentV2(field),
|
|
2660
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2589
2661
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2590
2662
|
` <el-select v-model="form.${prop}" :placeholder="formSelectPlaceholder(${labelExpr}, ${disabledBool})" style="width: 100%"${disabledAttr}>`,
|
|
2591
2663
|
` <el-option v-for="item in getDictOptions(${dictExpr})" :key="item.value" :label="item.label" :value="item.value" />`,
|
|
@@ -2595,12 +2667,12 @@ function renderFormFieldV2(field) {
|
|
|
2595
2667
|
].join('\n');
|
|
2596
2668
|
}
|
|
2597
2669
|
|
|
2598
|
-
if (field.formType === 'number') {
|
|
2670
|
+
if (field.formType === 'number') {
|
|
2599
2671
|
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
2600
2672
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
2601
|
-
return [
|
|
2602
|
-
renderFieldCommentV2(field),
|
|
2603
|
-
` <el-col :span="
|
|
2673
|
+
return [
|
|
2674
|
+
renderFieldCommentV2(field),
|
|
2675
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2604
2676
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2605
2677
|
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})" style="width: 100%"${disabledAttr} />`,
|
|
2606
2678
|
' </el-form-item>',
|
|
@@ -2608,10 +2680,10 @@ function renderFormFieldV2(field) {
|
|
|
2608
2680
|
].join('\n');
|
|
2609
2681
|
}
|
|
2610
2682
|
|
|
2611
|
-
if (field.formType === 'microme-operator') {
|
|
2612
|
-
return [
|
|
2613
|
-
renderFieldCommentV2(field),
|
|
2614
|
-
` <el-col :span="
|
|
2683
|
+
if (field.formType === 'microme-operator') {
|
|
2684
|
+
return [
|
|
2685
|
+
renderFieldCommentV2(field),
|
|
2686
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2615
2687
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2616
2688
|
` <MicromeOperator v-model="form.${prop}"${renderMicromeFormatAttr(field)} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${disabledAttr} />`,
|
|
2617
2689
|
' </el-form-item>',
|
|
@@ -2619,23 +2691,12 @@ function renderFormFieldV2(field) {
|
|
|
2619
2691
|
].join('\n');
|
|
2620
2692
|
}
|
|
2621
2693
|
|
|
2622
|
-
if (field.formType === '
|
|
2623
|
-
return [
|
|
2624
|
-
renderFieldCommentV2(field),
|
|
2625
|
-
' <el-col :span="12" class="mb20">',
|
|
2626
|
-
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2627
|
-
` <MicromeOperator v-model="form.${prop}"${renderMicromeFormatAttr(field)} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${disabledAttr} />`,
|
|
2628
|
-
' </el-form-item>',
|
|
2629
|
-
' </el-col>',
|
|
2630
|
-
].join('\n');
|
|
2631
|
-
}
|
|
2632
|
-
|
|
2633
|
-
if (field.formType === 'datetime' || field.formType === 'date') {
|
|
2694
|
+
if (field.formType === 'datetime' || field.formType === 'date') {
|
|
2634
2695
|
const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
|
|
2635
2696
|
const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
|
|
2636
|
-
return [
|
|
2637
|
-
renderFieldCommentV2(field),
|
|
2638
|
-
` <el-col :span="
|
|
2697
|
+
return [
|
|
2698
|
+
renderFieldCommentV2(field),
|
|
2699
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2639
2700
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2640
2701
|
` <el-date-picker type="${pickerType}" :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})" v-model="form.${prop}" :value-format="${formatName}" style="width: 100%"${disabledAttr}></el-date-picker>`,
|
|
2641
2702
|
' </el-form-item>',
|
|
@@ -2643,11 +2704,11 @@ function renderFormFieldV2(field) {
|
|
|
2643
2704
|
].join('\n');
|
|
2644
2705
|
}
|
|
2645
2706
|
|
|
2646
|
-
if (field.formType === 'textarea') {
|
|
2707
|
+
if (field.formType === 'textarea') {
|
|
2647
2708
|
const textareaAttrs = renderTextareaMaxlengthAttrsV2(field);
|
|
2648
|
-
return [
|
|
2649
|
-
renderFieldCommentV2(field),
|
|
2650
|
-
` <el-col :span="
|
|
2709
|
+
return [
|
|
2710
|
+
renderFieldCommentV2(field),
|
|
2711
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2651
2712
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2652
2713
|
` <el-input type="textarea" v-model="form.${prop}" :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${textareaAttrs}${disabledAttr} />`,
|
|
2653
2714
|
' </el-form-item>',
|
|
@@ -2656,9 +2717,9 @@ function renderFormFieldV2(field) {
|
|
|
2656
2717
|
}
|
|
2657
2718
|
|
|
2658
2719
|
const maxlengthAttr = renderInputMaxlengthAttr(field);
|
|
2659
|
-
return [
|
|
2660
|
-
renderFieldCommentV2(field),
|
|
2661
|
-
` <el-col :span="
|
|
2720
|
+
return [
|
|
2721
|
+
renderFieldCommentV2(field),
|
|
2722
|
+
` <el-col :span="${span}" class="mb20">`,
|
|
2662
2723
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2663
2724
|
` <el-input v-model="form.${prop}" :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${maxlengthAttr}${disabledAttr} />`,
|
|
2664
2725
|
' </el-form-item>',
|
|
@@ -2666,8 +2727,8 @@ function renderFormFieldV2(field) {
|
|
|
2666
2727
|
].join('\n');
|
|
2667
2728
|
}
|
|
2668
2729
|
|
|
2669
|
-
const FILL_REPORT_FIELD_NAMES = new Set(['createBy', 'createTime', 'finishedTime']);
|
|
2670
|
-
const FILL_REPORT_FIELD_ORDER = ['createBy', 'createTime', 'finishedTime'];
|
|
2730
|
+
const FILL_REPORT_FIELD_NAMES = new Set(['createBy', 'createUser', 'createTime', 'finishedTime']);
|
|
2731
|
+
const FILL_REPORT_FIELD_ORDER = ['createBy', 'createUser', 'createTime', 'finishedTime'];
|
|
2671
2732
|
|
|
2672
2733
|
function isFillReportField(field) {
|
|
2673
2734
|
return FILL_REPORT_FIELD_NAMES.has(String(field?.attrName || field?.fieldName || ''));
|
|
@@ -2683,34 +2744,102 @@ function renderBusinessFormCollapseItem(title, name, fields) {
|
|
|
2683
2744
|
].join('\n');
|
|
2684
2745
|
}
|
|
2685
2746
|
|
|
2686
|
-
function
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
return
|
|
2694
|
-
basicFields: fields.filter((field) => !isFillReportField(field)),
|
|
2695
|
-
fillReportFields,
|
|
2696
|
-
};
|
|
2747
|
+
function getFormFieldOriginalIndex(fields, field) {
|
|
2748
|
+
return fields.indexOf(field);
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
function classifyBusinessFormDomain(field) {
|
|
2752
|
+
const text = getFormLayoutFieldText(field).replace(/[_\-\s]/g, '');
|
|
2753
|
+
const group = FORM_LAYOUT_DOMAIN_GROUPS.find((item) => item.words.some((word) => text.includes(String(word).toLowerCase())));
|
|
2754
|
+
return group?.key || 'basic';
|
|
2697
2755
|
}
|
|
2698
2756
|
|
|
2699
|
-
function
|
|
2757
|
+
function createBusinessFormLayoutSections(model) {
|
|
2700
2758
|
const fields = model.pageType === 'ledger' ? model.visibleFields.map(asReadonlyField) : model.visibleFields;
|
|
2701
|
-
const
|
|
2702
|
-
const
|
|
2759
|
+
const basicFields = [];
|
|
2760
|
+
const attachmentFields = [];
|
|
2761
|
+
const fillReportFields = [];
|
|
2762
|
+
const domainBuckets = new Map();
|
|
2763
|
+
|
|
2764
|
+
fields.forEach((field) => {
|
|
2765
|
+
if (isFillReportField(field)) {
|
|
2766
|
+
fillReportFields.push(field);
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
if (isAttachmentLikeField(field)) {
|
|
2770
|
+
attachmentFields.push(field);
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
const domain = classifyBusinessFormDomain(field);
|
|
2774
|
+
if (domain === 'basic') {
|
|
2775
|
+
basicFields.push(field);
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
if (!domainBuckets.has(domain)) domainBuckets.set(domain, []);
|
|
2779
|
+
domainBuckets.get(domain).push(field);
|
|
2780
|
+
});
|
|
2781
|
+
|
|
2782
|
+
const beforeChildren = [{ title: '基本信息', fields: basicFields }];
|
|
2783
|
+
|
|
2784
|
+
FORM_LAYOUT_DOMAIN_GROUPS.forEach((group) => {
|
|
2785
|
+
const bucket = domainBuckets.get(group.key) || [];
|
|
2786
|
+
if (bucket.length >= 3) {
|
|
2787
|
+
beforeChildren.push({ title: group.title, fields: bucket });
|
|
2788
|
+
} else {
|
|
2789
|
+
beforeChildren[0].fields.push(...bucket);
|
|
2790
|
+
}
|
|
2791
|
+
});
|
|
2792
|
+
|
|
2793
|
+
const afterChildren = [];
|
|
2794
|
+
if (attachmentFields.length >= 2) {
|
|
2795
|
+
afterChildren.push({ title: '附件信息', fields: attachmentFields });
|
|
2796
|
+
} else {
|
|
2797
|
+
beforeChildren[0].fields.push(...attachmentFields);
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
beforeChildren.concat(afterChildren).forEach((section) => {
|
|
2801
|
+
section.fields.sort((left, right) => getFormFieldOriginalIndex(fields, left) - getFormFieldOriginalIndex(fields, right));
|
|
2802
|
+
});
|
|
2803
|
+
|
|
2703
2804
|
if (fillReportFields.length) {
|
|
2704
|
-
|
|
2805
|
+
afterChildren.push({
|
|
2806
|
+
title: '填报信息',
|
|
2807
|
+
fields: fillReportFields.sort((left, right) => FILL_REPORT_FIELD_ORDER.indexOf(left.attrName) - FILL_REPORT_FIELD_ORDER.indexOf(right.attrName)),
|
|
2808
|
+
});
|
|
2705
2809
|
}
|
|
2706
|
-
|
|
2810
|
+
|
|
2811
|
+
let nameIndex = 0;
|
|
2812
|
+
beforeChildren.filter((section) => section.fields.length).forEach((section) => {
|
|
2813
|
+
section.name = String(nameIndex++);
|
|
2814
|
+
});
|
|
2815
|
+
afterChildren.filter((section) => section.fields.length).forEach((section) => {
|
|
2816
|
+
section.name = String(nameIndex++);
|
|
2817
|
+
});
|
|
2818
|
+
|
|
2819
|
+
return {
|
|
2820
|
+
beforeChildren: beforeChildren.filter((section) => section.fields.length),
|
|
2821
|
+
afterChildren: afterChildren.filter((section) => section.fields.length),
|
|
2822
|
+
};
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
function renderBusinessFormCollapseSections(model, placement = 'all') {
|
|
2826
|
+
const layout = createBusinessFormLayoutSections(model);
|
|
2827
|
+
const sections =
|
|
2828
|
+
placement === 'beforeChildren'
|
|
2829
|
+
? layout.beforeChildren
|
|
2830
|
+
: placement === 'afterChildren'
|
|
2831
|
+
? layout.afterChildren
|
|
2832
|
+
: [...layout.beforeChildren, ...layout.afterChildren];
|
|
2833
|
+
return sections.map((section) => renderBusinessFormCollapseItem(section.title, section.name, section.fields)).join('\n');
|
|
2707
2834
|
}
|
|
2708
2835
|
|
|
2709
2836
|
function renderActiveCollapseNames(model) {
|
|
2710
|
-
const
|
|
2711
|
-
const names = [
|
|
2712
|
-
|
|
2713
|
-
|
|
2837
|
+
const layout = createBusinessFormLayoutSections(model);
|
|
2838
|
+
const names = [
|
|
2839
|
+
...layout.beforeChildren.map((section) => section.name),
|
|
2840
|
+
...model.children.map((childModel) => `child-${childModel.listName}`),
|
|
2841
|
+
...layout.afterChildren.map((section) => section.name),
|
|
2842
|
+
];
|
|
2714
2843
|
return `[${names.map((name) => `'${name}'`).join(', ')}]`;
|
|
2715
2844
|
}
|
|
2716
2845
|
|
|
@@ -4380,6 +4509,8 @@ function buildReplacements(model, sharedSupport) {
|
|
|
4380
4509
|
GENERATED_AT: new Date().toISOString(),
|
|
4381
4510
|
FORM_FIELDS: (model.pageType === 'ledger' ? model.visibleFields.map(asReadonlyField) : model.visibleFields).map(renderFormFieldV2).join('\n'),
|
|
4382
4511
|
FORM_COLLAPSE_SECTIONS: renderBusinessFormCollapseSections(model),
|
|
4512
|
+
FORM_COLLAPSE_SECTIONS_BEFORE_CHILDREN: renderBusinessFormCollapseSections(model, 'beforeChildren'),
|
|
4513
|
+
FORM_COLLAPSE_SECTIONS_AFTER_CHILDREN: renderBusinessFormCollapseSections(model, 'afterChildren'),
|
|
4383
4514
|
ACTIVE_COLLAPSE_NAMES: renderActiveCollapseNames(model),
|
|
4384
4515
|
TABLE_COLUMNS: model.gridFields.map((field) => renderTableColumn(field, dictRegistryRefs)).join('\n'),
|
|
4385
4516
|
FORM_DEFAULTS: renderFormDefaults(model),
|
|
@@ -4434,11 +4565,12 @@ function renderFiles(model, stylePreset, sharedSupport, localeZhSupport) {
|
|
|
4434
4565
|
},
|
|
4435
4566
|
];
|
|
4436
4567
|
|
|
4437
|
-
if (menuSqlTemplate) {
|
|
4438
|
-
files.push({ type: 'menuSql', path: path.join(menuRoot, `${model.functionName}_menu.sql`), content: renderTemplate(menuSqlTemplate, replacements) });
|
|
4439
|
-
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4568
|
+
if (menuSqlTemplate) {
|
|
4569
|
+
files.push({ type: 'menuSql', path: path.join(menuRoot, `${model.functionName}_menu.sql`), content: renderTemplate(menuSqlTemplate, replacements) });
|
|
4570
|
+
}
|
|
4571
|
+
assertNoUnresolvedTemplatePlaceholders(files);
|
|
4572
|
+
return files;
|
|
4573
|
+
}
|
|
4442
4574
|
|
|
4443
4575
|
function ensureArguments(input) {
|
|
4444
4576
|
if (!input || typeof input !== 'object') throw new Error('Arguments must be an object');
|
package/package.json
CHANGED