worsoft-frontend-codegen-local-mcp 0.1.62 → 0.1.65
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 +8 -0
- package/assets/templates/master_child_jump/index.tpl +10 -0
- package/assets/templates/single_table_dialog/form.tpl +4 -0
- package/assets/templates/single_table_dialog/index.tpl +6 -0
- package/assets/templates/single_table_jump/form.tpl +7 -0
- package/assets/templates/single_table_jump/index.tpl +8 -0
- package/mcp_server.js +139 -53
- package/package.json +1 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}主子表表单页 -->
|
|
2
3
|
<div class="layout-padding-auto layout-padding-view">
|
|
4
|
+
<!-- 表单卡片:承载标题、操作按钮、主表字段和子表明细 -->
|
|
3
5
|
<el-card shadow="never" class="w100">
|
|
4
6
|
<template #header>
|
|
7
|
+
<!-- 表单页头:根据新增、编辑、详情模式展示标题和按钮 -->
|
|
5
8
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
6
9
|
<span style="font-size: 16px; font-weight: bold;">{{ form.{{PK_ATTR}} ? (detail ? t('common.viewBtn') : t('common.editBtn')) : t('common.addBtn') }}</span>
|
|
10
|
+
<!-- 编辑模式操作按钮:保存、流转、提交、取消 -->
|
|
7
11
|
<div v-if="!detail">
|
|
8
12
|
<el-button @click="onSubmit('save')" :disabled="loading" icon="document">{{ commonActionLabel('save') }}</el-button>
|
|
9
13
|
<el-button @click="onSubmit('flow')" :disabled="loading" plain type="success" icon="position">{{ commonActionLabel('flow') }}</el-button>
|
|
@@ -11,15 +15,19 @@
|
|
|
11
15
|
<el-divider direction="vertical" />
|
|
12
16
|
<el-button @click="handleBack" icon="close">{{ t('common.cancelButtonText') }}</el-button>
|
|
13
17
|
</div>
|
|
18
|
+
<!-- 详情模式操作按钮:返回列表页 -->
|
|
14
19
|
<div v-else>
|
|
15
20
|
<el-button @click="handleBack" icon="back">{{ commonActionLabel('back') }}</el-button>
|
|
16
21
|
</div>
|
|
17
22
|
</div>
|
|
18
23
|
</template>
|
|
24
|
+
<!-- 主子表表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
19
25
|
<el-form ref="dataFormRef" :model="form" :rules="dataRules" :disabled="detail" v-loading="loading">
|
|
26
|
+
<!-- 主表字段区:字段级注释由 MCP 根据字段名称生成 -->
|
|
20
27
|
<el-row :gutter="24">
|
|
21
28
|
{{FORM_FIELDS}}
|
|
22
29
|
</el-row>
|
|
30
|
+
<!-- 子表明细区:按 children 配置渲染多个子表 -->
|
|
23
31
|
<el-row :gutter="24">
|
|
24
32
|
{{CHILD_SECTIONS}}
|
|
25
33
|
</el-row>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<!-- 功能名称:{{FEATURE_TITLE}} -->
|
|
2
2
|
<template>
|
|
3
|
+
<!-- 页面布局:{{FEATURE_TITLE}}列表页 -->
|
|
3
4
|
<div class="layout-padding">
|
|
4
5
|
<div class="layout-padding-auto layout-padding-view flex h-full flex-col">
|
|
6
|
+
<!-- 列表工具栏:搜索、新增、导入、批量删除、导出、刷新 -->
|
|
5
7
|
<SchemaListToolbar
|
|
6
8
|
v-bind="toolbarProps"
|
|
7
9
|
@update:keyword="state.queryForm.smartVal = $event"
|
|
@@ -15,6 +17,7 @@
|
|
|
15
17
|
@refresh="handleToolbarRefresh"
|
|
16
18
|
/>
|
|
17
19
|
|
|
20
|
+
<!-- 列表表格:展示{{FEATURE_TITLE}}列表数据、分页、排序和行操作 -->
|
|
18
21
|
<SchemaListTable
|
|
19
22
|
v-bind="tableProps"
|
|
20
23
|
row-id-key="{{PK_ATTR}}"
|
|
@@ -23,16 +26,23 @@
|
|
|
23
26
|
@size-change="handleTableSizeChange"
|
|
24
27
|
@current-change="handleTableCurrentChange"
|
|
25
28
|
>
|
|
29
|
+
<!-- 行操作按钮:查看、编辑、提交、流转、删除 -->
|
|
26
30
|
<template #actions="{ row }">
|
|
31
|
+
<!-- 查看{{FEATURE_TITLE}}详情 -->
|
|
27
32
|
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(row.{{PK_ATTR}})">{{ t('common.viewBtn') }}</el-button>
|
|
33
|
+
<!-- 编辑{{FEATURE_TITLE}}:业务单据编辑态控制按需生效 -->
|
|
28
34
|
<el-button{{BUSINESS_EDIT_IF}} icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="handleEdit(row.{{PK_ATTR}})">{{ t('common.editBtn') }}</el-button>
|
|
35
|
+
<!-- 提交{{FEATURE_TITLE}} -->
|
|
29
36
|
<el-button text type="primary" icon="check" @click="handleQuickAction(row, 'submit')">{{ commonActionLabel('submit') }}</el-button>
|
|
37
|
+
<!-- 流转{{FEATURE_TITLE}} -->
|
|
30
38
|
<el-button text type="success" icon="position" @click="handleQuickAction(row, 'flow')">{{ commonActionLabel('flow') }}</el-button>
|
|
39
|
+
<!-- 删除{{FEATURE_TITLE}} -->
|
|
31
40
|
<el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}])">{{ t('common.delBtn') }}</el-button>
|
|
32
41
|
</template>
|
|
33
42
|
</SchemaListTable>
|
|
34
43
|
</div>
|
|
35
44
|
|
|
45
|
+
<!-- Excel 导入组件:导入{{FEATURE_TITLE}}列表数据 -->
|
|
36
46
|
<upload-excel ref="excelUploadRef" :title="t('common.importBtn')" url="/{{API_PATH}}/import" temp-url="/admin/sys-file/local/file/{{FUNCTION_NAME}}.xlsx" @refreshDataList="getDataList" />
|
|
37
47
|
</div>
|
|
38
48
|
</template>
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<!-- 表单弹窗:新增或编辑{{FEATURE_TITLE}}数据 -->
|
|
2
3
|
<el-dialog v-model="visible" :title="form.{{PK_ATTR}} ? t('common.editBtn') : t('common.addBtn')" :close-on-click-modal="false" draggable>
|
|
4
|
+
<!-- 弹窗表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
3
5
|
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="100px" v-loading="loading">
|
|
6
|
+
<!-- 主表字段区:字段级注释由 MCP 根据字段名称生成 -->
|
|
4
7
|
<el-row :gutter="24">
|
|
5
8
|
{{FORM_FIELDS}}
|
|
6
9
|
</el-row>
|
|
7
10
|
</el-form>
|
|
11
|
+
<!-- 弹窗底部操作按钮:取消和确认提交 -->
|
|
8
12
|
<template #footer>
|
|
9
13
|
<span class="dialog-footer">
|
|
10
14
|
<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<!-- 功能名称:{{FEATURE_TITLE}} -->
|
|
2
2
|
<template>
|
|
3
|
+
<!-- 页面布局:{{FEATURE_TITLE}}列表页 -->
|
|
3
4
|
<div class="layout-padding">
|
|
4
5
|
<div class="layout-padding-auto layout-padding-view flex h-full flex-col">
|
|
6
|
+
<!-- 列表工具栏:搜索、新增、导入、批量删除、导出、刷新 -->
|
|
5
7
|
<SchemaListToolbar
|
|
6
8
|
v-bind="toolbarProps"
|
|
7
9
|
@update:keyword="state.queryForm.smartVal = $event"
|
|
@@ -15,6 +17,7 @@
|
|
|
15
17
|
@refresh="handleToolbarRefresh"
|
|
16
18
|
/>
|
|
17
19
|
|
|
20
|
+
<!-- 列表表格:展示{{FEATURE_TITLE}}列表数据、分页、排序和行操作 -->
|
|
18
21
|
<SchemaListTable
|
|
19
22
|
v-bind="tableProps"
|
|
20
23
|
row-id-key="{{PK_ATTR}}"
|
|
@@ -24,13 +27,16 @@
|
|
|
24
27
|
@size-change="handleTableSizeChange"
|
|
25
28
|
@current-change="handleTableCurrentChange"
|
|
26
29
|
>
|
|
30
|
+
<!-- 行操作按钮:编辑、删除、启用、禁用 -->
|
|
27
31
|
<template #actions="{ row }">
|
|
28
32
|
{{LIST_ACTIONS}}
|
|
29
33
|
</template>
|
|
30
34
|
</SchemaListTable>
|
|
31
35
|
</div>
|
|
32
36
|
|
|
37
|
+
<!-- 表单弹窗组件:新增和编辑{{FEATURE_TITLE}}数据 -->
|
|
33
38
|
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
|
39
|
+
<!-- Excel 导入组件:导入{{FEATURE_TITLE}}列表数据 -->
|
|
34
40
|
<upload-excel ref="excelUploadRef" :title="t('common.importBtn')" url="/{{API_PATH}}/import" temp-url="/admin/sys-file/local/file/{{FUNCTION_NAME}}.xlsx" @refreshDataList="getDataList" />
|
|
35
41
|
</div>
|
|
36
42
|
</template>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<!-- 页面布局:{{FEATURE_TITLE}}表单页 -->
|
|
2
3
|
<div class="layout-padding-auto layout-padding-view">
|
|
4
|
+
<!-- 表单卡片:承载标题、操作按钮和主表字段 -->
|
|
3
5
|
<el-card shadow="never" class="w100">
|
|
4
6
|
<template #header>
|
|
7
|
+
<!-- 表单页头:根据新增、编辑、详情模式展示标题和按钮 -->
|
|
5
8
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
6
9
|
<span style="font-size: 16px; font-weight: bold;">{{ form.{{PK_ATTR}} ? (detail ? t('common.viewBtn') : t('common.editBtn')) : t('common.addBtn') }}</span>
|
|
10
|
+
<!-- 编辑模式操作按钮:保存、流转、提交、取消 -->
|
|
7
11
|
<div v-if="!detail">
|
|
8
12
|
<el-button @click="onSubmit('save')" :disabled="loading" icon="document">{{ commonActionLabel('save') }}</el-button>
|
|
9
13
|
<el-button @click="onSubmit('flow')" :disabled="loading" plain type="success" icon="position">{{ commonActionLabel('flow') }}</el-button>
|
|
@@ -11,12 +15,15 @@
|
|
|
11
15
|
<el-divider direction="vertical" />
|
|
12
16
|
<el-button @click="handleBack" icon="close">{{ t('common.cancelButtonText') }}</el-button>
|
|
13
17
|
</div>
|
|
18
|
+
<!-- 详情模式操作按钮:返回列表页 -->
|
|
14
19
|
<div v-else>
|
|
15
20
|
<el-button @click="handleBack" icon="back">{{ commonActionLabel('back') }}</el-button>
|
|
16
21
|
</div>
|
|
17
22
|
</div>
|
|
18
23
|
</template>
|
|
24
|
+
<!-- 主表表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
19
25
|
<el-form ref="dataFormRef" :model="form" :rules="dataRules" :disabled="detail" v-loading="loading">
|
|
26
|
+
<!-- 主表字段区:字段级注释由 MCP 根据字段名称生成 -->
|
|
20
27
|
<el-row :gutter="24">
|
|
21
28
|
{{FORM_FIELDS}}
|
|
22
29
|
</el-row>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<!-- 功能名称:{{FEATURE_TITLE}} -->
|
|
2
2
|
<template>
|
|
3
|
+
<!-- 页面布局:{{FEATURE_TITLE}}列表页 -->
|
|
3
4
|
<div class="layout-padding">
|
|
4
5
|
<div class="layout-padding-auto layout-padding-view flex h-full flex-col">
|
|
6
|
+
<!-- 列表工具栏:搜索、新增、导入、批量删除、导出、刷新 -->
|
|
5
7
|
<SchemaListToolbar
|
|
6
8
|
v-bind="toolbarProps"
|
|
7
9
|
@update:keyword="state.queryForm.smartVal = $event"
|
|
@@ -15,6 +17,7 @@
|
|
|
15
17
|
@refresh="handleToolbarRefresh"
|
|
16
18
|
/>
|
|
17
19
|
|
|
20
|
+
<!-- 列表表格:展示{{FEATURE_TITLE}}列表数据、分页、排序和行操作 -->
|
|
18
21
|
<SchemaListTable
|
|
19
22
|
v-bind="tableProps"
|
|
20
23
|
row-id-key="{{PK_ATTR}}"
|
|
@@ -24,14 +27,19 @@
|
|
|
24
27
|
@size-change="handleTableSizeChange"
|
|
25
28
|
@current-change="handleTableCurrentChange"
|
|
26
29
|
>
|
|
30
|
+
<!-- 行操作按钮:查看、编辑、删除 -->
|
|
27
31
|
<template #actions="{ row }">
|
|
32
|
+
<!-- 查看{{FEATURE_TITLE}}详情 -->
|
|
28
33
|
<el-button text type="primary" icon="view" v-auth="'{{PERMISSION_PREFIX}}_view'" @click="handleDetail(row.{{PK_ATTR}})">{{ t('common.viewBtn') }}</el-button>
|
|
34
|
+
<!-- 编辑{{FEATURE_TITLE}}:业务单据编辑态控制按需生效 -->
|
|
29
35
|
<el-button{{BUSINESS_EDIT_IF}} icon="edit-pen" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_edit'" @click="handleEdit(row.{{PK_ATTR}})">{{ t('common.editBtn') }}</el-button>
|
|
36
|
+
<!-- 删除{{FEATURE_TITLE}} -->
|
|
30
37
|
<el-button icon="delete" text type="primary" v-auth="'{{PERMISSION_PREFIX}}_del'" @click="handleDelete([row.{{PK_ATTR}}])">{{ t('common.delBtn') }}</el-button>
|
|
31
38
|
</template>
|
|
32
39
|
</SchemaListTable>
|
|
33
40
|
</div>
|
|
34
41
|
|
|
42
|
+
<!-- Excel 导入组件:导入{{FEATURE_TITLE}}列表数据 -->
|
|
35
43
|
<upload-excel ref="excelUploadRef" :title="t('common.importBtn')" url="/{{API_PATH}}/import" temp-url="/admin/sys-file/local/file/{{FUNCTION_NAME}}.xlsx" @refreshDataList="getDataList" />
|
|
36
44
|
</div>
|
|
37
45
|
</template>
|
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.65';
|
|
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');
|
|
@@ -983,7 +983,7 @@ function normalizeStructuredFormType(value) {
|
|
|
983
983
|
if (!normalized) return '';
|
|
984
984
|
if (normalized === 'date') return 'date';
|
|
985
985
|
if (normalized === 'datetime') return 'datetime';
|
|
986
|
-
if (normalized === 'microme-operator') return '
|
|
986
|
+
if (normalized === 'microme-operator') return 'microme-operator';
|
|
987
987
|
if (normalized === 'upload') {
|
|
988
988
|
return 'upload';
|
|
989
989
|
}
|
|
@@ -1441,16 +1441,22 @@ function rejectSemanticStageInputs(input) {
|
|
|
1441
1441
|
}
|
|
1442
1442
|
}
|
|
1443
1443
|
|
|
1444
|
-
function validatePageTypeAndStyle(pageType, style) {
|
|
1445
|
-
if (!pageType) return;
|
|
1446
|
-
if (pageType === 'non_standard') {
|
|
1447
|
-
throw new Error('non_standard pages are not supported by worsoft_codegen_local_generate_frontend');
|
|
1448
|
-
}
|
|
1449
|
-
if (pageType
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1444
|
+
function validatePageTypeAndStyle(pageType, style) {
|
|
1445
|
+
if (!pageType) return;
|
|
1446
|
+
if (pageType === 'non_standard') {
|
|
1447
|
+
throw new Error('non_standard pages are not supported by worsoft_codegen_local_generate_frontend');
|
|
1448
|
+
}
|
|
1449
|
+
if (pageType === 'business') {
|
|
1450
|
+
if (style === 'single_table_dialog') {
|
|
1451
|
+
throw new Error('Business pages must use jump-based styles. pageType=business does not support style=single_table_dialog; use single_table_jump for single-table business pages or master_child_jump for master-child business pages.');
|
|
1452
|
+
}
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
if (pageType !== 'dict') return;
|
|
1456
|
+
if (style === 'single_table_jump' || style === 'master_child_jump') {
|
|
1457
|
+
throw new Error(`Dict pages must use dialog-based styles. pageType=dict does not support style=${style}`);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1454
1460
|
|
|
1455
1461
|
function hasRuntimeSupport(stylePreset) {
|
|
1456
1462
|
return Boolean(stylePreset.runtime && stylePreset.runtime.supported && stylePreset.runtime.templateDir);
|
|
@@ -1786,19 +1792,29 @@ function renderFormField(field) {
|
|
|
1786
1792
|
].join('\n');
|
|
1787
1793
|
}
|
|
1788
1794
|
|
|
1789
|
-
if (field.formType === 'number') {
|
|
1790
|
-
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1791
|
-
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1792
|
-
return [
|
|
1793
|
-
' <el-col :span="12" class="mb20">',
|
|
1795
|
+
if (field.formType === 'number') {
|
|
1796
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1797
|
+
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1798
|
+
return [
|
|
1799
|
+
' <el-col :span="12" class="mb20">',
|
|
1794
1800
|
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1795
1801
|
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="${inputPlaceholderExpr}" style="width: 100%" />`,
|
|
1796
1802
|
' </el-form-item>',
|
|
1797
1803
|
' </el-col>',
|
|
1798
|
-
].join('\n');
|
|
1799
|
-
}
|
|
1800
|
-
|
|
1801
|
-
if (field.formType === '
|
|
1804
|
+
].join('\n');
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
if (field.formType === 'microme-operator') {
|
|
1808
|
+
return [
|
|
1809
|
+
' <el-col :span="12" class="mb20">',
|
|
1810
|
+
` <el-form-item label="${label}" prop="${prop}">`,
|
|
1811
|
+
` <MicromeOperator v-model="form.${prop}"${renderMicromeFormatAttr(field)} :placeholder="${inputPlaceholderExpr}" />`,
|
|
1812
|
+
' </el-form-item>',
|
|
1813
|
+
' </el-col>',
|
|
1814
|
+
].join('\n');
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
if (field.formType === 'datetime' || field.formType === 'date') {
|
|
1802
1818
|
const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
|
|
1803
1819
|
const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
|
|
1804
1820
|
return [
|
|
@@ -1863,6 +1879,8 @@ function renderChildTableColumn(field, childListName) {
|
|
|
1863
1879
|
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
1864
1880
|
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
1865
1881
|
control = ` <el-input-number v-model="row.${field.attrName}" :min="0"${max}${precision} :placeholder="${inputPlaceholderExpr}" style="width: 100%"${disabledAttr} />`;
|
|
1882
|
+
} else if (field.formType === 'microme-operator') {
|
|
1883
|
+
control = ` <MicromeOperator v-model="row.${field.attrName}"${renderMicromeFormatAttr(field)} :placeholder="${inputPlaceholderExpr}"${disabledAttr} />`;
|
|
1866
1884
|
}
|
|
1867
1885
|
|
|
1868
1886
|
return [
|
|
@@ -1892,7 +1910,7 @@ function renderDefaultLine(field) {
|
|
|
1892
1910
|
if (field.attrName === 'billDate') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD'),`;
|
|
1893
1911
|
if (field.attrName === 'billStateId' || field.fieldName === 'bill_state_id') return ` ${field.attrName}: '0',`;
|
|
1894
1912
|
if (field.attrName === 'createTime') return ` ${field.attrName}: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),`;
|
|
1895
|
-
if (field.formType === 'number') return ` ${field.attrName}: 0,`;
|
|
1913
|
+
if (field.formType === 'number' || field.formType === 'microme-operator') return ` ${field.attrName}: 0,`;
|
|
1896
1914
|
return ` ${field.attrName}: '',`;
|
|
1897
1915
|
}
|
|
1898
1916
|
|
|
@@ -1938,10 +1956,12 @@ function renderChildSection(childModel, childCount) {
|
|
|
1938
1956
|
|
|
1939
1957
|
return [
|
|
1940
1958
|
' <el-col :span="24" class="mb20">',
|
|
1959
|
+
` <!-- 子表区域:${sanitizeHtmlComment(childModel.comment || childModel.tableName)} -->`,
|
|
1941
1960
|
` <div class="mb10" style="font-weight: 600;">{{ childSectionTitle('${childModel.listName}') }}</div>`,
|
|
1961
|
+
' <!-- 子表编辑表格:支持新增行、删除行和行内字段编辑 -->',
|
|
1942
1962
|
` <sc-form-table v-model="form.${childModel.listName}" :addTemplate="childTemp${childModel.className}" @delete="(obj) => ${deleteExpression}" :placeholder="t('common.noData')">`,
|
|
1943
1963
|
childModel.visibleFields.map((field) => renderChildTableColumn(field, childModel.listName)).join('\n'),
|
|
1944
|
-
' </sc-form-table>',
|
|
1964
|
+
' </sc-form-table>',
|
|
1945
1965
|
' </el-col>',
|
|
1946
1966
|
].join('\n');
|
|
1947
1967
|
}
|
|
@@ -2088,6 +2108,14 @@ function renderDisabledBoolV2(field) {
|
|
|
2088
2108
|
return field.readonly ? 'true' : 'false';
|
|
2089
2109
|
}
|
|
2090
2110
|
|
|
2111
|
+
function renderMicromeFormatAttr(field) {
|
|
2112
|
+
const length = Number.parseInt(String(field.length || ''), 10);
|
|
2113
|
+
const scale = Number.parseInt(String(field.scale || ''), 10);
|
|
2114
|
+
if (!length || Number.isNaN(length) || Number.isNaN(scale) || scale < 0) return '';
|
|
2115
|
+
const integerLength = Math.max(length - scale, 1);
|
|
2116
|
+
return ` format="${integerLength}-${scale}"`;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2091
2119
|
function isAttachmentLikeField(field) {
|
|
2092
2120
|
const fieldName = String(field?.fieldName || field?.attrName || '').toLowerCase();
|
|
2093
2121
|
const comment = String(field?.comment || field?.description || '').toLowerCase();
|
|
@@ -2130,20 +2158,42 @@ function renderFormFieldV2(field) {
|
|
|
2130
2158
|
].join('\n');
|
|
2131
2159
|
}
|
|
2132
2160
|
|
|
2133
|
-
if (field.formType === 'number') {
|
|
2134
|
-
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
2135
|
-
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
2136
|
-
return [
|
|
2137
|
-
renderFieldCommentV2(field),
|
|
2161
|
+
if (field.formType === 'number') {
|
|
2162
|
+
const max = field.comment.includes('%') || /\u6BD4\u4F8B/.test(field.comment) ? ' :max="100"' : '';
|
|
2163
|
+
const precision = field.sqlType === 'DECIMAL' && field.scale ? ` :precision="${field.scale}" :step="0.01"` : '';
|
|
2164
|
+
return [
|
|
2165
|
+
renderFieldCommentV2(field),
|
|
2138
2166
|
` <el-col :span="12" class="mb20">`,
|
|
2139
2167
|
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2140
2168
|
` <el-input-number v-model="form.${prop}" :min="0"${max}${precision} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})" style="width: 100%"${disabledAttr} />`,
|
|
2141
2169
|
' </el-form-item>',
|
|
2142
2170
|
' </el-col>',
|
|
2143
|
-
].join('\n');
|
|
2144
|
-
}
|
|
2145
|
-
|
|
2146
|
-
if (field.formType === '
|
|
2171
|
+
].join('\n');
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
if (field.formType === 'microme-operator') {
|
|
2175
|
+
return [
|
|
2176
|
+
renderFieldCommentV2(field),
|
|
2177
|
+
` <el-col :span="12" class="mb20">`,
|
|
2178
|
+
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2179
|
+
` <MicromeOperator v-model="form.${prop}"${renderMicromeFormatAttr(field)} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${disabledAttr} />`,
|
|
2180
|
+
' </el-form-item>',
|
|
2181
|
+
' </el-col>',
|
|
2182
|
+
].join('\n');
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
if (field.formType === 'microme-operator') {
|
|
2186
|
+
return [
|
|
2187
|
+
renderFieldCommentV2(field),
|
|
2188
|
+
' <el-col :span="12" class="mb20">',
|
|
2189
|
+
` <el-form-item :label="${labelExpr}" prop="${prop}">`,
|
|
2190
|
+
` <MicromeOperator v-model="form.${prop}"${renderMicromeFormatAttr(field)} :placeholder="formInputPlaceholder(${labelExpr}, ${disabledBool})"${disabledAttr} />`,
|
|
2191
|
+
' </el-form-item>',
|
|
2192
|
+
' </el-col>',
|
|
2193
|
+
].join('\n');
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
if (field.formType === 'datetime' || field.formType === 'date') {
|
|
2147
2197
|
const pickerType = field.formType === 'datetime' ? 'datetime' : 'date';
|
|
2148
2198
|
const formatName = field.formType === 'datetime' ? 'dateTimeStr' : 'dateStr';
|
|
2149
2199
|
return [
|
|
@@ -2456,14 +2506,18 @@ function renderMultiLevelFormVue(model, moduleModel) {
|
|
|
2456
2506
|
].join('\n');
|
|
2457
2507
|
const rules = renderFormRulesV2(moduleModel.visibleFields);
|
|
2458
2508
|
return `<template>
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2509
|
+
<!-- 表单弹窗:新增或编辑${sanitizeHtmlComment(moduleModel.comment || moduleModel.tableName)}数据 -->
|
|
2510
|
+
<el-dialog v-model="visible" :title="form.${moduleModel.pk.attrName} ? t('common.editBtn') : t('common.addBtn')" :close-on-click-modal="false" draggable>
|
|
2511
|
+
<!-- 弹窗表单:按 PRD 表单显隐和顺序渲染字段 -->
|
|
2512
|
+
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="100px" v-loading="loading">
|
|
2513
|
+
<!-- 字典字段区:字段级注释由 MCP 根据字段名称生成 -->
|
|
2514
|
+
<el-row :gutter="24">
|
|
2515
|
+
${moduleModel.visibleFields.map(renderMultiLevelFormField).join('\n')}
|
|
2516
|
+
</el-row>
|
|
2517
|
+
</el-form>
|
|
2518
|
+
<!-- 弹窗底部操作按钮:取消和确认提交 -->
|
|
2519
|
+
<template #footer>
|
|
2520
|
+
<span class="dialog-footer">
|
|
2467
2521
|
<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
|
|
2468
2522
|
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
|
|
2469
2523
|
</span>
|
|
@@ -2594,11 +2648,14 @@ ${moduleModel.visibleFields.map(renderMultiLevelFormField).join('\n')}
|
|
|
2594
2648
|
function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
|
|
2595
2649
|
return [
|
|
2596
2650
|
` <div class="multi-level-slot" v-if="${levelVarName}">`,
|
|
2651
|
+
' <!-- 多层字典页签:切换当前层级下的字典模块 -->',
|
|
2597
2652
|
' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
|
|
2598
2653
|
` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
|
|
2599
2654
|
' </el-tabs>',
|
|
2655
|
+
' <!-- 多层字典列表面板:承载当前层级的工具栏和表格 -->',
|
|
2600
2656
|
' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
|
|
2601
2657
|
' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
|
|
2658
|
+
' <!-- 当前层级工具栏:搜索、新增和重置 -->',
|
|
2602
2659
|
` <SchemaListToolbar`,
|
|
2603
2660
|
` v-bind="getPanelToolbarProps(${activeModuleVarName}.key)"`,
|
|
2604
2661
|
` @update:keyword="handlePanelKeywordChange(${activeModuleVarName}.key, $event)"`,
|
|
@@ -2606,16 +2663,22 @@ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeMo
|
|
|
2606
2663
|
` @query="handlePanelQuery(${activeModuleVarName}.key)"`,
|
|
2607
2664
|
` @reset="handlePanelReset(${activeModuleVarName}.key)"`,
|
|
2608
2665
|
` />`,
|
|
2666
|
+
' <!-- 当前层级表格:展示字典数据、分页和行操作 -->',
|
|
2609
2667
|
` <SchemaListTable`,
|
|
2610
2668
|
` v-bind="getPanelTableProps(${activeModuleVarName}.key)"`,
|
|
2611
2669
|
` @row-current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event.row)"`,
|
|
2612
2670
|
` @current-change="handleCurrentPageChange(${activeModuleVarName}.key, $event.current)"`,
|
|
2613
2671
|
` @size-change="handlePageSizeChange(${activeModuleVarName}.key, $event.size)"`,
|
|
2614
2672
|
` >`,
|
|
2673
|
+
' <!-- 行操作按钮:编辑、删除、启用、禁用 -->',
|
|
2615
2674
|
` <template #actions="{ row }">`,
|
|
2675
|
+
' <!-- 编辑当前字典数据 -->',
|
|
2616
2676
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'edit', row)" icon="edit-pen" text type="primary" @click="openEdit(${activeModuleVarName}.key, row)">{{ t('common.editBtn') }}</el-button>`,
|
|
2677
|
+
' <!-- 删除当前字典数据 -->',
|
|
2617
2678
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
|
|
2679
|
+
' <!-- 启用当前字典数据 -->',
|
|
2618
2680
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">闁告凹鍨抽弫?/el-button>`,
|
|
2681
|
+
' <!-- 禁用当前字典数据 -->',
|
|
2619
2682
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">缂佸倷鑳堕弫?/el-button>`,
|
|
2620
2683
|
` </template>`,
|
|
2621
2684
|
` </SchemaListTable>`,
|
|
@@ -2628,14 +2691,18 @@ function renderMultiLevelSchemaListSlot(levelVarName, activeKeyVarName, activeMo
|
|
|
2628
2691
|
function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleVarName) {
|
|
2629
2692
|
return [
|
|
2630
2693
|
` <div class="multi-level-slot" v-if="${levelVarName}">`,
|
|
2694
|
+
' <!-- 多层字典页签:切换当前层级下的字典模块 -->',
|
|
2631
2695
|
' <el-tabs class="multi-level-tabs" v-if="' + `${levelVarName}.moduleKeys.length > 1` + `" v-model="${activeKeyVarName}">`,
|
|
2632
2696
|
` <el-tab-pane v-for="moduleKey in ${levelVarName}.moduleKeys" :key="moduleKey" :label="resolveModuleTitle(moduleConfigs[moduleKey])" :name="moduleKey" />`,
|
|
2633
2697
|
' </el-tabs>',
|
|
2698
|
+
' <!-- 多层字典列表面板:承载当前层级的新增按钮、表格和分页 -->',
|
|
2634
2699
|
' <div class="multi-level-panel" v-if="' + `${activeModuleVarName}` + `">`,
|
|
2635
2700
|
' <div class="layout-padding-auto layout-padding-view flex h-full flex-col">',
|
|
2701
|
+
' <!-- 当前层级新增按钮:受父级状态约束控制 -->',
|
|
2636
2702
|
' <div class="mb8" style="width: 100%">',
|
|
2637
2703
|
` <el-button icon="folder-add" type="primary" class="ml10" :disabled="isAddDisabled(${activeModuleVarName}.key)" @click="openCreate(${activeModuleVarName}.key)">{{ t('common.addBtn') }}</el-button>`,
|
|
2638
2704
|
' </div>',
|
|
2705
|
+
' <!-- 当前层级表格:展示字典数据并处理行选中联动 -->',
|
|
2639
2706
|
' <el-table',
|
|
2640
2707
|
` :data="moduleStateMap[${activeModuleVarName}.key].dataList"`,
|
|
2641
2708
|
` v-loading="moduleStateMap[${activeModuleVarName}.key].loading"`,
|
|
@@ -2644,7 +2711,9 @@ function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleV
|
|
|
2644
2711
|
' highlight-current-row',
|
|
2645
2712
|
` @current-change="handlePanelCurrentChange(${activeModuleVarName}.key, $event)"`,
|
|
2646
2713
|
' >',
|
|
2714
|
+
' <!-- 序号列 -->',
|
|
2647
2715
|
` <el-table-column type="index" :label="t('common.serial')" width="60" />`,
|
|
2716
|
+
' <!-- 字典业务字段列 -->',
|
|
2648
2717
|
` <el-table-column`,
|
|
2649
2718
|
` v-for="column in getListFields(${activeModuleVarName}.key)"`,
|
|
2650
2719
|
' :key="column.key"',
|
|
@@ -2658,15 +2727,21 @@ function renderMultiLevelLevelSlot(levelVarName, activeKeyVarName, activeModuleV
|
|
|
2658
2727
|
' <span v-else>{{ scope.row[column.key] }}</span>',
|
|
2659
2728
|
' </template>',
|
|
2660
2729
|
' </el-table-column>',
|
|
2730
|
+
' <!-- 行操作按钮:编辑、删除、启用、禁用 -->',
|
|
2661
2731
|
` <el-table-column :label="t('common.action')" width="260">`,
|
|
2662
2732
|
' <template #default="{ row }">',
|
|
2733
|
+
' <!-- 编辑当前字典数据 -->',
|
|
2663
2734
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'edit', row)" icon="edit-pen" text type="primary" @click="openEdit(${activeModuleVarName}.key, row)">{{ t('common.editBtn') }}</el-button>`,
|
|
2735
|
+
' <!-- 删除当前字典数据 -->',
|
|
2664
2736
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'delete', row)" icon="delete" text type="primary" @click="handleDelete(${activeModuleVarName}.key, row)">{{ t('common.delBtn') }}</el-button>`,
|
|
2737
|
+
' <!-- 启用当前字典数据 -->',
|
|
2665
2738
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'enable', row)" icon="circle-check" text type="primary" @click="handleEnable(${activeModuleVarName}.key, row)">{{ t('common.actions.enable') }}</el-button>`,
|
|
2739
|
+
' <!-- 禁用当前字典数据 -->',
|
|
2666
2740
|
` <el-button v-if="showModuleAction(${activeModuleVarName}.key, 'disable', row)" icon="remove" text type="primary" @click="handleDisable(${activeModuleVarName}.key, row)">{{ t('common.actions.disable') }}</el-button>`,
|
|
2667
2741
|
' </template>',
|
|
2668
2742
|
' </el-table-column>',
|
|
2669
2743
|
' </el-table>',
|
|
2744
|
+
' <!-- 当前层级分页组件 -->',
|
|
2670
2745
|
' <div class="mt-2.5 flex shrink-0 justify-end">',
|
|
2671
2746
|
' <pagination',
|
|
2672
2747
|
` :current-page="moduleStateMap[${activeModuleVarName}.key].currentPage"`,
|
|
@@ -2718,24 +2793,31 @@ function renderMultiLevelIndexVue(model) {
|
|
|
2718
2793
|
|
|
2719
2794
|
return `<!-- 功能名称:${sanitizeHtmlComment(model.featureTitle)} -->
|
|
2720
2795
|
<template>
|
|
2796
|
+
<!-- 页面布局:${sanitizeHtmlComment(model.featureTitle)}多层字典列表页 -->
|
|
2721
2797
|
<div class="layout-padding">
|
|
2798
|
+
<!-- 多层字典主布局:左侧一级字典,右侧二级和三级字典联动 -->
|
|
2722
2799
|
<div class="multi-level-dict-layout">
|
|
2723
|
-
|
|
2800
|
+
<!-- 一级字典区域 -->
|
|
2801
|
+
<div class="multi-level-left">
|
|
2724
2802
|
${renderMultiLevelSchemaListSlot('level1Config', 'activeLevel1Key', 'activeLevel1Module')}
|
|
2725
|
-
</div>
|
|
2726
|
-
|
|
2727
|
-
|
|
2803
|
+
</div>
|
|
2804
|
+
<!-- 二级和三级字典区域 -->
|
|
2805
|
+
<div class="multi-level-right">
|
|
2806
|
+
<!-- 二级字典区域 -->
|
|
2807
|
+
<div class="multi-level-right-top">
|
|
2728
2808
|
${level2 ? renderMultiLevelSchemaListSlot('level2Config', 'activeLevel2Key', 'activeLevel2Module') : ''}
|
|
2729
|
-
</div>
|
|
2730
|
-
|
|
2809
|
+
</div>
|
|
2810
|
+
<!-- 三级字典区域 -->
|
|
2811
|
+
<div v-if="level3Config" class="multi-level-right-bottom">
|
|
2731
2812
|
${level3 ? renderMultiLevelSchemaListSlot('level3Config', 'activeLevel3Key', 'activeLevel3Module') : ''}
|
|
2732
|
-
</div>
|
|
2733
|
-
</div>
|
|
2734
|
-
</div>
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
</
|
|
2813
|
+
</div>
|
|
2814
|
+
</div>
|
|
2815
|
+
</div>
|
|
2816
|
+
|
|
2817
|
+
<!-- 多层字典表单弹窗:按模块异步挂载 -->
|
|
2818
|
+
${formComponents}
|
|
2819
|
+
</div>
|
|
2820
|
+
</template>
|
|
2739
2821
|
|
|
2740
2822
|
<script setup lang="ts" name="system${model.className}">
|
|
2741
2823
|
// 通用消息与确认弹窗
|
|
@@ -3007,11 +3089,15 @@ function renderSingleTableDialogActions(model, permissionPrefix) {
|
|
|
3007
3089
|
const pkAttr = model.pk.attrName;
|
|
3008
3090
|
const isDictWithStatus = model.pageType === 'dict' && model.statusField;
|
|
3009
3091
|
const lines = [
|
|
3092
|
+
` <!-- 编辑${sanitizeHtmlComment(model.featureTitle)} -->`,
|
|
3010
3093
|
` <el-button${isDictWithStatus ? ` v-if="showDictAction('edit', row)"` : ''} icon="edit-pen" text type="primary" v-auth="'${permissionPrefix}_edit'" @click="formDialogRef.openDialog(row.${pkAttr})">{{ t('common.editBtn') }}</el-button>`,
|
|
3094
|
+
` <!-- 删除${sanitizeHtmlComment(model.featureTitle)} -->`,
|
|
3011
3095
|
` <el-button${isDictWithStatus ? ` v-if="showDictAction('delete', row)"` : ''} icon="delete" text type="primary" v-auth="'${permissionPrefix}_del'" @click="handleDelete([row.${pkAttr}])">{{ t('common.delBtn') }}</el-button>`,
|
|
3012
3096
|
];
|
|
3013
3097
|
if (isDictWithStatus) {
|
|
3098
|
+
lines.push(` <!-- 启用${sanitizeHtmlComment(model.featureTitle)} -->`);
|
|
3014
3099
|
lines.push(` <el-button v-if="showDictAction('enable', row)" icon="circle-check" text type="primary" @click="handleEnable(row.${pkAttr})">{{ t('common.actions.enable') }}</el-button>`);
|
|
3100
|
+
lines.push(` <!-- 禁用${sanitizeHtmlComment(model.featureTitle)} -->`);
|
|
3015
3101
|
lines.push(` <el-button v-if="showDictAction('disable', row)" icon="remove" text type="primary" @click="handleDisable(row.${pkAttr})">{{ t('common.actions.disable') }}</el-button>`);
|
|
3016
3102
|
}
|
|
3017
3103
|
return lines.join('\n');
|
package/package.json
CHANGED